From e601bbdc43bae9a08e2e10c5139a6f76b47860d7 Mon Sep 17 00:00:00 2001 From: Einat Vinouze Date: Tue, 16 Jul 2019 17:17:36 +0300 Subject: [PATCH] Implant vid-app-common org.onap.vid.job (main and test) Issue-ID: VID-378 Change-Id: I41b0bdc2c4e3635f3f3319b1cd63cefc61912dfc Signed-off-by: Einat Vinouze Signed-off-by: Ittay Stern --- .../src/main/webapp/WEB-INF/conf/system.properties | 32 +- .../webapp/WEB-INF/conf/system_template.properties | 8 + vid-app-common/pom.xml | 7 +- .../src/main/java/org/onap/vid/aai/AaiClient.java | 44 +- .../java/org/onap/vid/aai/AaiClientInterface.java | 29 +- .../KeyValueModel.java} | 32 +- .../RelatedToProperty.java | 59 +- .../Relationship.java | 8 +- .../RelationshipData.java | 32 +- .../java/org/onap/vid/aai/model/ModelVersions.kt | 3 + .../org/onap/vid/aai/util/AAITreeConverter.java | 95 +- .../org/onap/vid/aai/util/AAITreeNodeUtils.java | 49 + .../org/onap/vid/asdc/local/LocalAsdcClient.java | 19 +- .../org/onap/vid/asdc/parser/ToscaParserImpl2.java | 101 +- .../onap/vid/asdc/parser/VidNotionsBuilder.java | 142 +- .../vid/changeManagement/CloudConfiguration.java | 20 +- .../org/onap/vid/controller/AaiController.java | 15 +- .../AaiServiceInstanceStandardQueryController.java | 120 +- .../controller/AsyncInstantiationController.java | 69 +- .../java/org/onap/vid/controller/MsoConfig.java | 4 +- .../org/onap/vid/controller/MsoController.java | 35 +- .../java/org/onap/vid/controller/WebConfig.java | 20 +- .../onap/vid/dal/AsyncInstantiationRepository.kt | 147 +++ .../src/main/java/org/onap/vid/dao/JobRequest.java | 111 ++ .../org/onap/vid/exceptions/AbortingException.java | 28 + .../AccessDeniedException.java} | 35 +- .../org/onap/vid/exceptions/TryAgainException.java | 28 + .../src/main/java/org/onap/vid/job/Job.java | 13 +- .../src/main/java/org/onap/vid/job/JobAdapter.java | 8 +- .../src/main/java/org/onap/vid/job/JobCommand.java | 4 +- .../main/java/org/onap/vid/job/JobException.java | 4 +- .../src/main/java/org/onap/vid/job/JobType.java | 28 +- .../java/org/onap/vid/job/JobsBrokerService.java | 5 +- .../main/java/org/onap/vid/job/NextCommand.java | 4 +- .../onap/vid/job/command/ALaCarteServiceCommand.kt | 96 +- .../vid/job/command/AggregateStateCommand.java | 4 +- .../job/command/BaseInProgressStatusCommand.java | 115 -- .../org/onap/vid/job/command/BaseRootCommand.java | 61 - .../onap/vid/job/command/BaseWatchingCommand.java | 90 -- .../java/org/onap/vid/job/command/CommandBase.java | 4 +- .../onap/vid/job/command/CommandParentData.java | 37 +- .../org/onap/vid/job/command/CommandUtils.java | 4 +- .../org/onap/vid/job/command/ExpiryChecker.java | 4 +- .../org/onap/vid/job/command/HttpCallCommand.java | 4 +- .../vid/job/command/InProgressStatusService.java | 21 +- .../onap/vid/job/command/InstanceGroupCommand.kt | 34 +- .../command/InstanceGroupInstantiationCommand.java | 67 - .../vid/job/command/InstanceGroupMemberCommand.kt | 63 + .../onap/vid/job/command/JobCommandFactory.java | 4 +- .../onap/vid/job/command/MacroServiceCommand.kt | 98 ++ .../org/onap/vid/job/command/MsoRequestBuilder.kt | 411 ++++++ .../vid/job/command/MsoResultHandlerService.kt | 27 +- .../org/onap/vid/job/command/NetworkCommand.kt | 65 + .../job/command/NetworkInstantiationCommand.java | 61 - .../java/org/onap/vid/job/command/NoOpCommand.java | 4 +- .../org/onap/vid/job/command/ResourceCommand.kt | 172 ++- .../job/command/ResourceInstantiationCommand.java | 107 -- .../ResourceWithChildrenInProgressCommand.java | 85 -- .../org/onap/vid/job/command/RootServiceCommand.kt | 98 ++ .../command/ServiceInProgressStatusCommand.java | 120 -- .../job/command/ServiceInstantiationCommand.java | 126 -- .../org/onap/vid/job/command/VfmoduleCommand.kt | 106 ++ .../job/command/VfmoduleInstantiationCommand.java | 64 - .../java/org/onap/vid/job/command/VnfCommand.kt | 140 ++ .../job/command/VnfInProgressStatusCommand.java | 107 -- .../vid/job/command/VnfInstantiationCommand.java | 70 - .../org/onap/vid/job/command/VolumeGroupCommand.kt | 94 ++ .../VolumeGroupInProgressStatusCommand.java | 85 -- .../command/VolumeGroupInstantiationCommand.java | 103 -- .../onap/vid/job/command/WatchChildrenJobsBL.kt | 6 +- .../org/onap/vid/job/command/WatchingCommand.java | 53 - .../vid/job/command/WatchingCommandBaseModule.java | 113 -- .../impl/DeleteOldJobsSchedulerInitializer.java | 96 ++ .../DeleteOldJobsWorker.java} | 41 +- .../java/org/onap/vid/job/impl/JobAdapterImpl.java | 25 +- .../java/org/onap/vid/job/impl/JobDaoImpl.java | 28 +- .../main/java/org/onap/vid/job/impl/JobData.java | 4 +- .../onap/vid/job/impl/JobSchedulerInitializer.java | 27 +- .../java/org/onap/vid/job/impl/JobSharedData.java | 18 +- .../main/java/org/onap/vid/job/impl/JobWorker.java | 31 +- .../job/impl/JobsBrokerServiceInDatabaseImpl.java | 144 ++- .../src/main/java/org/onap/vid/model/Action.java | 8 +- .../java/org/onap/vid/model/JobAuditStatus.java | 100 +- .../main/java/org/onap/vid/model/ModelUtil.java | 7 - .../main/java/org/onap/vid/model/ResourceInfo.java | 144 +++ .../main/java/org/onap/vid/model/ServiceInfo.java | 161 +-- .../main/java/org/onap/vid/model/ServiceModel.java | 75 +- .../java/org/onap/vid/model/VersionAndFeatures.kt | 12 + .../src/main/java/org/onap/vid/model/VidNotions.kt | 25 +- .../org/onap/vid/model/aaiTree/AAITreeNode.java | 50 +- .../org/onap/vid/model/aaiTree/AbstractNode.java | 8 +- .../onap/vid/model/aaiTree/CollectionResource.kt | 15 + .../org/onap/vid/model/aaiTree/InstanceGroup.kt | 23 + .../main/java/org/onap/vid/model/aaiTree/NCF.kt | 12 + .../java/org/onap/vid/model/aaiTree/Network.java | 116 +- .../main/java/org/onap/vid/model/aaiTree/Node.java | 33 +- .../java/org/onap/vid/model/aaiTree/NodeType.java | 82 ++ .../org/onap/vid/model/aaiTree/RelatedVnf.java | 34 +- .../onap/vid/model/aaiTree/ServiceInstance.java | 35 +- .../java/org/onap/vid/model/aaiTree/VfModule.java | 9 +- .../main/java/org/onap/vid/model/aaiTree/Vnf.java | 18 +- .../java/org/onap/vid/model/aaiTree/VnfGroup.java | 72 -- .../java/org/onap/vid/model/aaiTree/VnfGroup.kt | 10 + .../java/org/onap/vid/model/aaiTree/VpnBinding.kt | 50 + .../main/java/org/onap/vid/model/aaiTree/Vrf.java | 65 + .../errorReport/ReportCreationParameters.java | 1 + .../model/serviceInstantiation/BaseResource.java | 86 +- .../model/serviceInstantiation/InstanceGroup.java | 34 +- .../serviceInstantiation/InstanceGroupMember.java | 54 + .../vid/model/serviceInstantiation/Network.java | 42 +- .../serviceInstantiation/ServiceInstantiation.java | 62 +- .../vid/model/serviceInstantiation/VfModule.java | 49 +- .../onap/vid/model/serviceInstantiation/Vnf.java | 52 +- .../vid/model/serviceInstantiation/VrfEntry.kt | 6 + .../java/org/onap/vid/mso/MsoBusinessLogic.java | 11 +- .../org/onap/vid/mso/MsoBusinessLogicImpl.java | 149 +-- .../src/main/java/org/onap/vid/mso/MsoUtil.java | 33 +- ...dOrRemoveInstanceGroupMemberRequestDetails.java | 51 + .../BaseResourceInstantiationRequestDetails.java | 35 +- .../org/onap/vid/mso/model/CloudConfiguration.java | 192 --- .../org/onap/vid/mso/model/CloudConfiguration.kt | 12 + .../ServiceInstantiationPre1806RequestDetails.java | 51 + .../model/ServiceInstantiationRequestDetails.java | 8 +- .../model/VfModuleInstantiationRequestDetails.java | 16 +- .../org/onap/vid/mso/rest/AsyncRequestStatus.java | 5 +- .../java/org/onap/vid/mso/rest/RequestStatus.java | 8 + .../java/org/onap/vid/properties/Features.java | 23 +- .../org/onap/vid/properties/VidProperties.java | 93 +- .../java/org/onap/vid/services/AAIServiceTree.java | 124 +- .../org/onap/vid/services/AAITreeNodeBuilder.java | 341 ++--- .../java/org/onap/vid/services/AaiService.java | 2 +- .../java/org/onap/vid/services/AaiServiceImpl.java | 47 +- .../services/AsyncInstantiationBusinessLogic.java | 66 +- .../AsyncInstantiationBusinessLogicImpl.java | 711 ++++------ .../java/org/onap/vid/services/AuditService.java | 24 +- .../org/onap/vid/services/AuditServiceImpl.java | 189 ++- .../org/onap/vid/services/CloudOwnerService.java | 4 +- .../vid/services/RoleGenaratorServiceImpl.java | 2 +- .../java/org/onap/vid/services/VersionService.kt | 66 + .../main/java/org/onap/vid/utils/KotlinUtils.kt | 2 +- .../src/main/java/org/onap/vid/utils/Tree.kt | 12 +- vid-app-common/src/main/resources/1712_ADIOD.zip | Bin 89573 -> 0 bytes vid-app-common/src/main/resources/2f80c596.zip | Bin 87488 -> 0 bytes vid-app-common/src/main/resources/adiod.zip | Bin 79927 -> 0 bytes .../src/main/resources/csar317927061915233480.zip | Bin 63104 -> 0 bytes .../src/main/resources/csar3933948645405128424.zip | Bin 103891 -> 0 bytes .../mso_get_manual_task_by_request_id.json | 23 - vid-app-common/src/main/resources/pnf.zip | Bin 33397 -> 0 bytes .../src/main/resources/service-David-csar.csar | Bin 29894 -> 0 bytes .../main/resources/service-DemoService1-csar.csar | Bin 37635 -> 0 bytes .../src/main/resources/service-VdbeSrv-csar.zip | Bin 70825 -> 0 bytes .../src/main/resources/service-vf-csar.zip | Bin 58363 -> 0 bytes .../main/resources/service-vf-with-annotations.zip | Bin 118031 -> 0 bytes .../src/main/resources/service-vl-csar.zip | Bin 34965 -> 0 bytes .../new-change-management.controller.js | 4 +- .../org/onap/vid/aai/AAITreeConverterTest.java | 134 +- .../test/java/org/onap/vid/aai/AaiClientTest.java | 184 ++- .../onap/vid/aai/AaiResponseTranslatorTest.java | 6 +- .../onap/vid/asdc/parser/ToscaParserImpl2Test.java | 86 +- .../vid/asdc/parser/ToscaParserInflatorTest.java | 29 +- .../vid/asdc/parser/VidNotionsBuilderTest.java | 340 ++++- .../WorkflowRequestDetailTest.java | 6 +- .../java/org/onap/vid/config/DataSourceConfig.java | 2 +- .../java/org/onap/vid/config/JobAdapterConfig.java | 25 +- .../vid/config/JobCommandsConfigWithMockedMso.java | 175 ++- .../org/onap/vid/controller/AaiControllerTest.java | 56 +- ...ServiceInstanceStandardQueryControllerTest.java | 26 +- .../org/onap/vid/controller/LocalWebConfig.java | 5 +- .../onap/vid/controller/MsoControllerNewTest.java | 12 +- .../org/onap/vid/controller/MsoControllerTest.java | 5 +- .../onap/vid/controller/ToscaParserMockHelper.java | 20 +- .../org/onap/vid/controller/VidControllerTest.java | 2 +- .../vid/dal/AsyncInstantiationRepositoryTest.java | 103 ++ .../org/onap/vid/job/command/CommandUtilsTest.java | 4 +- .../job/command/InProgressStatusServiceTest.java | 83 +- .../vid/job/command/InstanceGroupCommandTest.java | 71 +- .../vid/job/command/JobCommandFactoryTest.java | 8 +- .../vid/job/command/MacroServiceCommandTest.java | 136 ++ .../job/command/MsoResultHandlerServiceTest.java | 95 ++ .../onap/vid/job/command/ResourceCommandTest.java | 258 +++- .../ResourceInProgressStatusCommandTest.java | 60 - .../ServiceInProgressStatusCommandTest.java | 157 +-- .../vid/job/command/WatchChildrenJobsBLTest.java | 6 +- .../onap/vid/job/command/WatchingCommandTest.java | 97 -- .../impl/AsyncInstantiationIntegrationTest.java | 1020 +++++++++------ .../DeleteOldJobsSchedulerInitializerTest.java | 55 + .../vid/job/impl/DeleteOldJobsWorkerTest.java} | 36 +- .../java/org/onap/vid/job/impl/JobAdapterTest.java | 43 +- .../java/org/onap/vid/job/impl/JobWorkerTest.java | 13 +- .../org/onap/vid/model/JobAuditStatusTest.java | 12 +- .../org/onap/vid/model/aaiTree/VpnBindingKtTest.kt | 16 + .../org/onap/vid/mso/MsoBusinessLogicImplTest.java | 181 +-- .../vid/mso/MsoOperationalEnvironmentTest.java | 17 +- .../onap/vid/mso/rest/MsoRestClientNewTest.java | 36 +- .../org/onap/vid/mso/rest/RequestDetailsTest.java | 23 +- .../onap/vid/services/AAITreeNodeBuilderTest.java | 469 ++++++- .../org/onap/vid/services/AaiServiceImplTest.java | 1354 ++++++++++---------- .../vid/services/AsyncInstantiationBaseTest.java | 119 +- .../AsyncInstantiationBusinessLogicTest.java | 1105 +++++++--------- .../onap/vid/services/AuditServiceImplTest.java | 99 +- .../onap/vid/services/JobsBrokerServiceTest.java | 390 ++++-- .../vid/services/PortDetailsTranslatorTest.java | 10 +- .../vid/services/RoleGenaratorServiceImplTest.java | 4 +- .../java/org/onap/vid/testUtils/TestUtils.java | 51 +- .../test/resources/WEB-INF/conf/system.properties | 108 +- vid-app-common/src/test/resources/cr-csar.JSON | 7 +- .../src/test/resources/csars/1712_PASQUALE.zip | Bin 0 -> 87747 bytes .../test/resources/csars/csarTransportWithPnfs.zip | Bin 0 -> 33722 bytes .../resources/csars}/service-AmpPhSvc-csar.zip | Bin 67661 -> 56568 bytes .../test/resources/csars/service-Infravpn-csar.zip | Bin 0 -> 36957 bytes .../csars/service-JennyVtsbcVlanSvc-csar.zip | Bin 0 -> 181221 bytes .../csars}/service-MsoExampleService-csar.zip | Bin .../service-ServicecontainerContainsPprobe.zip | Bin 32759 -> 31473 bytes ...ervice-Servicecontainermultiplepprobes-csar.zip | Bin 32750 -> 31463 bytes .../resources/csars/service-VdorotheaSrv-csar.zip | Bin 0 -> 67068 bytes .../csars/service-fabric-configuration.zip | Bin 0 -> 82131 bytes .../src/test/resources/csars/service-vf-csar.zip | Bin 0 -> 46618 bytes .../csars/service-vf-with-annotations.zip | Bin 0 -> 83322 bytes .../src/test/resources/csars/service-vl-csar.zip | Bin 0 -> 33677 bytes .../resources/csars/service-vnf-grouping-csar.zip | Bin 0 -> 71009 bytes .../csars}/vLoadBalancerMS-with-policy.TOSCA.zip | Bin .../src/test/resources/fabric-configuration.json | 11 +- .../resources/fabric-real-sriov-configuration.json | 2 +- .../src/test/resources/getTopology/network.json | 79 ++ .../resources/getTopology/serviceWithCR/CR.json | 62 + .../serviceWithCR/getTopologyWithCR.json | 95 ++ .../serviceWithCR/instanceGroup-NCF.json | 43 + .../serviceWithCR/service-design-and-creation.json | 1057 +++++++++++++++ .../getTopology/serviceWithCR/serviceWithCR.json | 38 + .../serviceWithCR/serviceWithCRModel.json | 72 ++ .../src/test/resources/getTopology/vfModule.json | 66 + .../src/test/resources/getTopology/vnf.json | 160 +++ .../orchestrationRequestsByServiceInstanceId.json | 4 +- .../VnfGroupCreate1Delete1None1Request.json | 123 ++ .../VnfGroupCreate3Delete1None1Request.json | 171 +++ ...Create3Delete1None1RequestResolvedForRetry.json | 176 +++ .../bulk_alacarte_service_request.json | 2 +- ...bulk_alacarte_service_request_naming_false.json | 2 +- .../payload_jsons/bulk_macro_service_request.json | 4 +- .../bulk_service_request_ecomp_naming.json | 4 +- ...k_service_request_no_vfmodule_ecomp_naming.json | 4 +- .../bulk_service_request_unique_names.json | 4 +- .../resources/payload_jsons/bulk_vnf_request.json | 2 +- .../bulk_vnf_request_without_instance_name.json | 2 +- .../instance_group_instantiation_request.json | 5 +- .../mso_request_create_configuration.json | 2 +- .../payload_jsons/mso_service_instantiation.json | 4 +- .../networkDelete1Create1Request.json | 117 ++ .../network_instantiation_request.json | 7 +- ...nstantiation_request_without_instance_name.json | 5 +- ...e_1806_macro_service_instantiation_request.json | 47 + .../pre_1806_macro_without_cloudConfiguration.json | 42 + .../resume/feRequestResumeMacroService.json | 107 ++ .../msoResponseGetRequestsOfServiceInstance.json | 62 + .../vfModuleDelete1Create1None1Request.json | 139 ++ .../payload_jsons/vfmodule/replace_vfmodule.json | 52 + .../vfmodule/replace_vfmodule_fe_input.json | 92 ++ .../vfmodule_instantiation_request.json | 5 +- ...nstantiation_request_without_instance_name.json | 5 +- ...instantiation_request_without_volume_group.json | 5 +- .../payload_jsons/vnf/bulk_vnf_request.json | 49 + .../vnf/bulk_vnf_request_without_cloud_owner.json | 48 + .../bulk_vnf_request_without_instance_name.json | 48 + .../vnf/vnf_without_lob_expected.json | 46 + .../vnf/vnf_without_lob_user_input.json | 24 + .../payload_jsons/vnfDelete1Create1Request.json | 240 ++++ .../volumegroup_instantiation_request.json | 5 +- .../vrfEntry/service_with_vrf_entry_fe_input.json | 81 ++ .../service_with_vrf_instantiation_request.json | 59 + .../policy-configuration-by-policy-false.JSON | 42 +- .../test/resources/policy-configuration-csar.JSON | 49 +- .../aai/getCloudRegionAndTenantByVnfId.json | 12 +- ...ltipleOrchestrationRequestsServiceInstance.json | 300 +++++ .../responses/mso/orchestrationRequestsVnf.json | 2 +- .../src/{main => test}/resources/sdcservices.json | 118 +- .../vLoadBalancerMS-with-policy.TOSCA.json | 2 +- vid-app-common/src/test/resources/vf-csar.JSON | 11 +- .../test/resources/vf-with-annotation-csar.json | 223 ++-- .../test/resources/vf-with-vfcInstanceGroups.json | 31 +- vid-app-common/src/test/resources/vl-csar.JSON | 7 +- .../src/test/resources/vnf-grouping-csar.json | 24 +- 281 files changed, 13556 insertions(+), 6652 deletions(-) rename vid-app-common/src/main/java/org/onap/vid/{job/command/BaseInstantiationCommand.java => aai/model/AaiGetNetworkCollectionDetails/KeyValueModel.java} (67%) create mode 100644 vid-app-common/src/main/java/org/onap/vid/aai/model/ModelVersions.kt create mode 100644 vid-app-common/src/main/java/org/onap/vid/aai/util/AAITreeNodeUtils.java create mode 100644 vid-app-common/src/main/java/org/onap/vid/dal/AsyncInstantiationRepository.kt create mode 100644 vid-app-common/src/main/java/org/onap/vid/dao/JobRequest.java create mode 100644 vid-app-common/src/main/java/org/onap/vid/exceptions/AbortingException.java rename vid-app-common/src/main/java/org/onap/vid/{job/command/ResourceInProgressStatusCommand.java => exceptions/AccessDeniedException.java} (52%) create mode 100644 vid-app-common/src/main/java/org/onap/vid/exceptions/TryAgainException.java delete mode 100644 vid-app-common/src/main/java/org/onap/vid/job/command/BaseInProgressStatusCommand.java delete mode 100644 vid-app-common/src/main/java/org/onap/vid/job/command/BaseRootCommand.java delete mode 100644 vid-app-common/src/main/java/org/onap/vid/job/command/BaseWatchingCommand.java delete mode 100644 vid-app-common/src/main/java/org/onap/vid/job/command/InstanceGroupInstantiationCommand.java create mode 100644 vid-app-common/src/main/java/org/onap/vid/job/command/InstanceGroupMemberCommand.kt create mode 100644 vid-app-common/src/main/java/org/onap/vid/job/command/MacroServiceCommand.kt create mode 100644 vid-app-common/src/main/java/org/onap/vid/job/command/MsoRequestBuilder.kt create mode 100644 vid-app-common/src/main/java/org/onap/vid/job/command/NetworkCommand.kt delete mode 100644 vid-app-common/src/main/java/org/onap/vid/job/command/NetworkInstantiationCommand.java delete mode 100644 vid-app-common/src/main/java/org/onap/vid/job/command/ResourceInstantiationCommand.java delete mode 100644 vid-app-common/src/main/java/org/onap/vid/job/command/ResourceWithChildrenInProgressCommand.java create mode 100644 vid-app-common/src/main/java/org/onap/vid/job/command/RootServiceCommand.kt delete mode 100644 vid-app-common/src/main/java/org/onap/vid/job/command/ServiceInProgressStatusCommand.java delete mode 100644 vid-app-common/src/main/java/org/onap/vid/job/command/ServiceInstantiationCommand.java create mode 100644 vid-app-common/src/main/java/org/onap/vid/job/command/VfmoduleCommand.kt delete mode 100644 vid-app-common/src/main/java/org/onap/vid/job/command/VfmoduleInstantiationCommand.java create mode 100644 vid-app-common/src/main/java/org/onap/vid/job/command/VnfCommand.kt delete mode 100644 vid-app-common/src/main/java/org/onap/vid/job/command/VnfInProgressStatusCommand.java delete mode 100644 vid-app-common/src/main/java/org/onap/vid/job/command/VnfInstantiationCommand.java create mode 100644 vid-app-common/src/main/java/org/onap/vid/job/command/VolumeGroupCommand.kt delete mode 100644 vid-app-common/src/main/java/org/onap/vid/job/command/VolumeGroupInProgressStatusCommand.java delete mode 100644 vid-app-common/src/main/java/org/onap/vid/job/command/VolumeGroupInstantiationCommand.java delete mode 100644 vid-app-common/src/main/java/org/onap/vid/job/command/WatchingCommand.java delete mode 100644 vid-app-common/src/main/java/org/onap/vid/job/command/WatchingCommandBaseModule.java create mode 100644 vid-app-common/src/main/java/org/onap/vid/job/impl/DeleteOldJobsSchedulerInitializer.java rename vid-app-common/src/main/java/org/onap/vid/job/{command/MacroServiceInstantiationCommand.java => impl/DeleteOldJobsWorker.java} (52%) create mode 100644 vid-app-common/src/main/java/org/onap/vid/model/ResourceInfo.java create mode 100644 vid-app-common/src/main/java/org/onap/vid/model/VersionAndFeatures.kt create mode 100644 vid-app-common/src/main/java/org/onap/vid/model/aaiTree/CollectionResource.kt create mode 100644 vid-app-common/src/main/java/org/onap/vid/model/aaiTree/InstanceGroup.kt create mode 100644 vid-app-common/src/main/java/org/onap/vid/model/aaiTree/NCF.kt create mode 100644 vid-app-common/src/main/java/org/onap/vid/model/aaiTree/NodeType.java delete mode 100644 vid-app-common/src/main/java/org/onap/vid/model/aaiTree/VnfGroup.java create mode 100644 vid-app-common/src/main/java/org/onap/vid/model/aaiTree/VnfGroup.kt create mode 100644 vid-app-common/src/main/java/org/onap/vid/model/aaiTree/VpnBinding.kt create mode 100644 vid-app-common/src/main/java/org/onap/vid/model/aaiTree/Vrf.java create mode 100644 vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/InstanceGroupMember.java create mode 100644 vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/VrfEntry.kt create mode 100644 vid-app-common/src/main/java/org/onap/vid/mso/model/AddOrRemoveInstanceGroupMemberRequestDetails.java delete mode 100644 vid-app-common/src/main/java/org/onap/vid/mso/model/CloudConfiguration.java create mode 100644 vid-app-common/src/main/java/org/onap/vid/mso/model/CloudConfiguration.kt create mode 100644 vid-app-common/src/main/java/org/onap/vid/mso/model/ServiceInstantiationPre1806RequestDetails.java create mode 100644 vid-app-common/src/main/java/org/onap/vid/services/VersionService.kt delete mode 100644 vid-app-common/src/main/resources/1712_ADIOD.zip delete mode 100644 vid-app-common/src/main/resources/2f80c596.zip delete mode 100644 vid-app-common/src/main/resources/adiod.zip delete mode 100644 vid-app-common/src/main/resources/csar317927061915233480.zip delete mode 100644 vid-app-common/src/main/resources/csar3933948645405128424.zip delete mode 100644 vid-app-common/src/main/resources/mso_get_manual_task_by_request_id.json delete mode 100644 vid-app-common/src/main/resources/pnf.zip delete mode 100644 vid-app-common/src/main/resources/service-David-csar.csar delete mode 100644 vid-app-common/src/main/resources/service-DemoService1-csar.csar delete mode 100644 vid-app-common/src/main/resources/service-VdbeSrv-csar.zip delete mode 100644 vid-app-common/src/main/resources/service-vf-csar.zip delete mode 100644 vid-app-common/src/main/resources/service-vf-with-annotations.zip delete mode 100644 vid-app-common/src/main/resources/service-vl-csar.zip create mode 100644 vid-app-common/src/test/java/org/onap/vid/dal/AsyncInstantiationRepositoryTest.java create mode 100644 vid-app-common/src/test/java/org/onap/vid/job/command/MacroServiceCommandTest.java create mode 100644 vid-app-common/src/test/java/org/onap/vid/job/command/MsoResultHandlerServiceTest.java delete mode 100644 vid-app-common/src/test/java/org/onap/vid/job/command/ResourceInProgressStatusCommandTest.java delete mode 100644 vid-app-common/src/test/java/org/onap/vid/job/command/WatchingCommandTest.java create mode 100644 vid-app-common/src/test/java/org/onap/vid/job/impl/DeleteOldJobsSchedulerInitializerTest.java rename vid-app-common/src/{main/java/org/onap/vid/job/command/ALaCarteServiceInstantiationCommand.java => test/java/org/onap/vid/job/impl/DeleteOldJobsWorkerTest.java} (52%) create mode 100644 vid-app-common/src/test/java/org/onap/vid/model/aaiTree/VpnBindingKtTest.kt create mode 100644 vid-app-common/src/test/resources/csars/1712_PASQUALE.zip create mode 100644 vid-app-common/src/test/resources/csars/csarTransportWithPnfs.zip rename vid-app-common/src/{main/resources => test/resources/csars}/service-AmpPhSvc-csar.zip (52%) create mode 100644 vid-app-common/src/test/resources/csars/service-Infravpn-csar.zip create mode 100644 vid-app-common/src/test/resources/csars/service-JennyVtsbcVlanSvc-csar.zip rename vid-app-common/src/{main/resources => test/resources/csars}/service-MsoExampleService-csar.zip (100%) rename vid-app-common/src/{main/resources => test/resources/csars}/service-ServicecontainerContainsPprobe.zip (76%) rename vid-app-common/src/{main/resources => test/resources/csars}/service-Servicecontainermultiplepprobes-csar.zip (76%) create mode 100644 vid-app-common/src/test/resources/csars/service-VdorotheaSrv-csar.zip create mode 100644 vid-app-common/src/test/resources/csars/service-fabric-configuration.zip create mode 100644 vid-app-common/src/test/resources/csars/service-vf-csar.zip create mode 100644 vid-app-common/src/test/resources/csars/service-vf-with-annotations.zip create mode 100644 vid-app-common/src/test/resources/csars/service-vl-csar.zip create mode 100644 vid-app-common/src/test/resources/csars/service-vnf-grouping-csar.zip rename vid-app-common/src/{main/resources => test/resources/csars}/vLoadBalancerMS-with-policy.TOSCA.zip (100%) create mode 100644 vid-app-common/src/test/resources/getTopology/network.json create mode 100644 vid-app-common/src/test/resources/getTopology/serviceWithCR/CR.json create mode 100644 vid-app-common/src/test/resources/getTopology/serviceWithCR/getTopologyWithCR.json create mode 100644 vid-app-common/src/test/resources/getTopology/serviceWithCR/instanceGroup-NCF.json create mode 100644 vid-app-common/src/test/resources/getTopology/serviceWithCR/service-design-and-creation.json create mode 100644 vid-app-common/src/test/resources/getTopology/serviceWithCR/serviceWithCR.json create mode 100644 vid-app-common/src/test/resources/getTopology/serviceWithCR/serviceWithCRModel.json create mode 100644 vid-app-common/src/test/resources/getTopology/vfModule.json create mode 100644 vid-app-common/src/test/resources/getTopology/vnf.json create mode 100644 vid-app-common/src/test/resources/payload_jsons/VnfGroupCreate1Delete1None1Request.json create mode 100644 vid-app-common/src/test/resources/payload_jsons/VnfGroupCreate3Delete1None1Request.json create mode 100644 vid-app-common/src/test/resources/payload_jsons/VnfGroupCreate3Delete1None1RequestResolvedForRetry.json create mode 100644 vid-app-common/src/test/resources/payload_jsons/networkDelete1Create1Request.json create mode 100644 vid-app-common/src/test/resources/payload_jsons/pre_1806_macro_service_instantiation_request.json create mode 100644 vid-app-common/src/test/resources/payload_jsons/pre_1806_macro_without_cloudConfiguration.json create mode 100644 vid-app-common/src/test/resources/payload_jsons/resume/feRequestResumeMacroService.json create mode 100644 vid-app-common/src/test/resources/payload_jsons/resume/msoResponseGetRequestsOfServiceInstance.json create mode 100644 vid-app-common/src/test/resources/payload_jsons/vfModuleDelete1Create1None1Request.json create mode 100644 vid-app-common/src/test/resources/payload_jsons/vfmodule/replace_vfmodule.json create mode 100644 vid-app-common/src/test/resources/payload_jsons/vfmodule/replace_vfmodule_fe_input.json create mode 100644 vid-app-common/src/test/resources/payload_jsons/vnf/bulk_vnf_request.json create mode 100644 vid-app-common/src/test/resources/payload_jsons/vnf/bulk_vnf_request_without_cloud_owner.json create mode 100644 vid-app-common/src/test/resources/payload_jsons/vnf/bulk_vnf_request_without_instance_name.json create mode 100644 vid-app-common/src/test/resources/payload_jsons/vnf/vnf_without_lob_expected.json create mode 100644 vid-app-common/src/test/resources/payload_jsons/vnf/vnf_without_lob_user_input.json create mode 100644 vid-app-common/src/test/resources/payload_jsons/vnfDelete1Create1Request.json create mode 100644 vid-app-common/src/test/resources/payload_jsons/vrfEntry/service_with_vrf_entry_fe_input.json create mode 100644 vid-app-common/src/test/resources/payload_jsons/vrfEntry/service_with_vrf_instantiation_request.json create mode 100644 vid-app-common/src/test/resources/responses/mso/multipleOrchestrationRequestsServiceInstance.json rename vid-app-common/src/{main => test}/resources/sdcservices.json (67%) diff --git a/epsdk-app-onap/src/main/webapp/WEB-INF/conf/system.properties b/epsdk-app-onap/src/main/webapp/WEB-INF/conf/system.properties index 5c78c253f..976ec7504 100755 --- a/epsdk-app-onap/src/main/webapp/WEB-INF/conf/system.properties +++ b/epsdk-app-onap/src/main/webapp/WEB-INF/conf/system.properties @@ -23,21 +23,6 @@ # The following properties should NOT be changed by partner applications. ########################################################################## -application_user_id = 30000 -post_default_role_id = 16 -clustered = true - -#Enable Fusion Mobile capabilities for the application -mobile_enable = false - -# Cache config file is needed on the classpath -cache_config_file_path = /WEB-INF/classes/cache.ccf -cache_switch = 199 -cache_load_on_startup = false - -user_name = fullName -decryption_key = AGLDdG4D04BKm2IxIWEr8o== - ########################################################################## # The following properties MAY require changes by partner applications. ########################################################################## @@ -122,12 +107,11 @@ aai.truststore.filename=tomcat_keystore aai.truststore.passwd.x=OBF:1ks51l8d1o3i1pcc1r2r1e211r391kls1pyj1z7u1njf1lx51go21hnj1y0k1mli1sop1k8o1j651vu91mxw1vun1mze1vv11j8x1k5i1sp11mjc1y161hlr1gm41m111nkj1z781pw31kku1r4p1e391r571pbm1o741l4x1ksp aai.keystore.filename=tomcat_keystore aai.keystore.passwd.x=OBF:1ks51l8d1o3i1pcc1r2r1e211r391kls1pyj1z7u1njf1lx51go21hnj1y0k1mli1sop1k8o1j651vu91mxw1vun1mze1vv11j8x1k5i1sp11mjc1y161hlr1gm41m111nkj1z781pw31kku1r4p1e391r571pbm1o741l4x1ksp - aai.vid.username=VID aai.vid.passwd.x=OBF:1jm91i0v1jl9 - aai.use.client.cert=false aai.vnf.provstatus=PREPROV,NVTPROV,PROV,CAPPED + #Cron Schedules log_cron = 0 0/1 * * * ?; mylogins_feed_cron = 0 0/60 * * * ?; @@ -169,17 +153,18 @@ mso.restapi.svc.instance.deleteAndUnassign=/serviceInstantiation/v7/serviceInsta mso.restapi.vnf.instance=/serviceInstances/v6//vnfs mso.restapi.vnf.changemanagement.instance=/serviceInstances/v6//vnfs// mso.restapi.network.instance=/serviceInstances/v6//networks -mso.restapi.vf.module.instance=/serviceInstances/v6//vnfs//vfModules mso.restapi.vf.module.scaleout=/serviceInstantiation/v7/serviceInstances//vnfs//vfModules/scaleOut +mso.restapi.vf.module.instance=/serviceInstances/v6//vnfs//vfModules mso.restapi.workflow.invoke=/instanceManagement/v1/serviceInstances//vnfs//workflows/ mso.restapi.volume.group.instance=/serviceInstances/v6//vnfs//volumeGroups mso.restapi.instance.group=/serviceInstantiation/v7/instanceGroups mso.restapi.get.orc.req=/orchestrationRequests/v6 mso.restapi.get.orc.reqs=/orchestrationRequests/v6? +mso.restapi.resume.orc.req=/orchestrationRequests/v7//resume mso.restapi.get.man.tasks=/tasks/v1 mso.restapi.configurations=/serviceInstances/v6//configurations mso.restapi.configuration.instance=${mso.restapi.configurations}/ - +mso.restapi.changeManagement.workflowSpecifications=/workflowSpecifications/v1/workflows?vnfModelVersionId= mso.restapi.serviceInstantiationApiRoot=/serviceInstantiation/v7 mso.restapi.serviceInstanceCreate=${mso.restapi.serviceInstantiationApiRoot}/serviceInstances mso.restapi.serviceInstanceAssign=${mso.restapi.serviceInstantiationApiRoot}/serviceInstances/assign @@ -193,7 +178,7 @@ mso.restapi.operationalEnvironment.create=${mso.restapi.cloudResourcesApiRoot}/o mso.restapi.cloudResourcesRequestsApiRoot=/cloudResourcesRequests/v1 mso.restapi.operationalEnvironment.cloudResourcesRequests.status=${mso.restapi.cloudResourcesRequestsApiRoot}?requestId= -mso.restapi.changeManagement.workflowSpecifications=/workflowSpecifications/v1/workflows?vnfModelVersionId= + mso.displayTestAPIOnScreen=true mso.defaultTestAPI=GR_API mso.maxOpenedInstantiationRequests=20 @@ -204,6 +189,7 @@ vid.truststore.filename=/opt/app/vid/etc/org.onap.vid.trust.jks vid.truststore.passwd.x=OBF:1dx01j0e1hs01t981mis1dws156s1ojc1qjc1zsx1pw31qob1qr71pyj1zst1qhy1ojq156i1dua1mm21tb61hvi1j0g1du2 mso.dme2.client.timeout=30000 mso.dme2.client.read.timeout=120000 + scheduler.create.new.vnf.change.instance=/v1/ChangeManagement/schedules/ scheduler.get.time.slots=/v1/ChangeManagement/schedules/ scheduler.server.url=http://BYO.scheduler:8989/scheduler @@ -211,3 +197,9 @@ scheduler.server.url=http://BYO.scheduler:8989/scheduler scheduler.submit.new.vnf.change=/v1/ChangeManagement/schedules/{scheduleId}/approvals scheduler.get.schedules=/v1/ChangeManagement/schedules/scheduleDetails/ scheduler.basic.auth= + +vid.asyncJob.howLongToKeepOldJobsInDays=7 + +# thread definition - count and timeout (in seconds) +vid.thread.count=50 +vid.thread.timeout=30 \ No newline at end of file diff --git a/epsdk-app-onap/src/main/webapp/WEB-INF/conf/system_template.properties b/epsdk-app-onap/src/main/webapp/WEB-INF/conf/system_template.properties index 2af6798d2..e25b84944 100755 --- a/epsdk-app-onap/src/main/webapp/WEB-INF/conf/system_template.properties +++ b/epsdk-app-onap/src/main/webapp/WEB-INF/conf/system_template.properties @@ -119,10 +119,12 @@ mso.restapi.volume.group.instance=/serviceInstances/v6//vnf mso.restapi.instance.group=/serviceInstantiation/v7/instanceGroups mso.restapi.get.orc.req=/orchestrationRequests/v6 mso.restapi.get.orc.reqs=/orchestrationRequests/v6? +mso.restapi.resume.orc.req=/orchestrationRequests/v7//resume mso.restapi.get.man.tasks=/tasks/v1 mso.restapi.configurations=/serviceInstances/v6//configurations mso.restapi.configuration.instance=${mso.restapi.configurations}/ mso.restapi.changeManagement.workflowSpecifications=/workflowSpecifications/v1/workflows?vnfModelVersionId= + mso.restapi.serviceInstantiationApiRoot=/serviceInstantiation/v7 mso.restapi.serviceInstanceCreate=${mso.restapi.serviceInstantiationApiRoot}/serviceInstances mso.restapi.serviceInstanceAssign=${mso.restapi.serviceInstantiationApiRoot}/serviceInstances/assign @@ -150,3 +152,9 @@ mso.dme2.client.read.timeout=${MSO_DME2_CLIENT_READ_TIMEOUT} mso.dme2.server.url=${MSO_DME2_SERVER_URL} mso.dme2.enabled=${MSO_DME2_ENABLED} scheduler.basic.auth=${SCHEDULER_BASIC_AUTH} + +vid.asyncJob.howLongToKeepOldJobsInDays=7 + +# thread definition - count and timeout (in seconds) +vid.thread.count=50 +vid.thread.timeout=30 \ No newline at end of file diff --git a/vid-app-common/pom.xml b/vid-app-common/pom.xml index b2c5c9dce..28b17a373 100755 --- a/vid-app-common/pom.xml +++ b/vid-app-common/pom.xml @@ -821,7 +821,7 @@ org.apache.commons commons-lang3 - 3.6 + 3.9 org.apache.commons @@ -871,5 +871,10 @@ springfox-swagger2 2.9.2 + + org.apache.maven + maven-artifact + 3.6.1 + diff --git a/vid-app-common/src/main/java/org/onap/vid/aai/AaiClient.java b/vid-app-common/src/main/java/org/onap/vid/aai/AaiClient.java index 4ef6fbd24..015ede893 100644 --- a/vid-app-common/src/main/java/org/onap/vid/aai/AaiClient.java +++ b/vid-app-common/src/main/java/org/onap/vid/aai/AaiClient.java @@ -21,11 +21,13 @@ package org.onap.vid.aai; import static java.util.Collections.emptyList; +import static java.util.Comparator.comparing; import static java.util.stream.Collectors.toMap; import static org.apache.commons.lang3.ObjectUtils.defaultIfNull; import static org.apache.commons.lang3.StringUtils.equalsIgnoreCase; import static org.apache.commons.lang3.StringUtils.isEmpty; +import org.apache.maven.artifact.versioning.DefaultArtifactVersion; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; @@ -37,6 +39,7 @@ import java.util.List; import java.util.Map; import java.util.UUID; import java.util.function.Function; +import java.util.stream.Stream; import javax.inject.Inject; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Response; @@ -49,6 +52,7 @@ import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; import org.onap.vid.aai.exceptions.InvalidAAIResponseException; +import org.onap.vid.aai.model.*; import org.onap.vid.aai.model.AaiGetAicZone.AicZones; import org.onap.vid.aai.model.AaiGetInstanceGroupsByCloudRegion; import org.onap.vid.aai.model.AaiGetNetworkCollectionDetails.AaiGetNetworkCollectionDetails; @@ -117,6 +121,7 @@ public class AaiClient implements AaiClientInterface { private static final String GET_SERVICE_MODELS_RESPONSE_BODY = "{\"start\" : \"service-design-and-creation/models/\", \"query\" : \"query/serviceModels-byDistributionStatus?distributionStatus=DISTRIBUTION_COMPLETE_OK\"}"; + @Inject public AaiClient(AAIRestInterface restController, PortDetailsTranslator portDetailsTranslator, CacheProvider cacheProvider) { this.restController = restController; @@ -425,14 +430,49 @@ public class AaiClient implements AaiClientInterface { } @Override - public AaiResponse getSubscriberData(String subscriberId) { - String depth = "2"; + public AaiResponse getSubscriberData(String subscriberId, boolean omitServiceInstances) { + String depth = omitServiceInstances ? "1" : "2"; AaiResponse subscriberDataResponse; Response resp = doAaiGet(BUSINESS_CUSTOMERS_CUSTOMER + subscriberId + "?depth=" + depth, false); subscriberDataResponse = processAaiResponse(resp, Services.class, null); return subscriberDataResponse; } + @Override + public ModelVer getLatestVersionByInvariantId(String modelInvariantId) { + if (modelInvariantId.isEmpty()) { + throw new GenericUncheckedException("no invariant-id provided to getLatestVersionByInvariantId; request is rejected"); + } + + // add the modelInvariantId to the payload + StringBuilder payload = new StringBuilder(GET_SERVICE_MODELS_RESPONSE_BODY); + payload.insert(50, modelInvariantId); + + Response response = doAaiPut("service-design-and-creation/models/model/", payload.toString(),false); + AaiResponse aaiResponse = processAaiResponse(response, ModelVersions.class, null, VidObjectMapperType.FASTERXML); + Stream modelVerStream = toModelVerStream(aaiResponse.getT()); + return maxModelVer(modelVerStream); + + } + + protected Stream toModelVerStream(ModelVersions modelVersions) { + + return Stream.of(modelVersions) + .map(ModelVersions::getResults) + .flatMap(java.util.Collection::stream) + .flatMap(map -> map.entrySet().stream()) + .filter(kv -> StringUtils.equals(kv.getKey(), "model-ver")) + .map(Map.Entry::getValue); + + } + + protected ModelVer maxModelVer(Stream modelVerStream) { + return modelVerStream + .filter(modelVer -> StringUtils.isNotEmpty(modelVer.getModelVersion())) + .max(comparing(ModelVer::getModelVersion, comparing(DefaultArtifactVersion::new))) + .orElseThrow(() -> new GenericUncheckedException("Could not find any version")); + } + @Override public AaiResponse getServices() { Response resp = doAaiGet("service-design-and-creation/services", false); diff --git a/vid-app-common/src/main/java/org/onap/vid/aai/AaiClientInterface.java b/vid-app-common/src/main/java/org/onap/vid/aai/AaiClientInterface.java index 5f69b8769..1061ae5f5 100644 --- a/vid-app-common/src/main/java/org/onap/vid/aai/AaiClientInterface.java +++ b/vid-app-common/src/main/java/org/onap/vid/aai/AaiClientInterface.java @@ -7,9 +7,9 @@ * 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. @@ -21,30 +21,37 @@ package org.onap.vid.aai; import com.fasterxml.jackson.databind.JsonNode; -import java.net.URI; -import java.util.List; -import java.util.Map; -import javax.ws.rs.core.Response; import org.onap.vid.aai.model.AaiGetOperationalEnvironments.OperationalEnvironmentList; import org.onap.vid.aai.model.AaiGetPnfs.Pnf; import org.onap.vid.aai.model.AaiGetTenatns.GetTenantsResponse; +import org.onap.vid.aai.model.ModelVer; import org.onap.vid.aai.model.PortDetailsTranslator; import org.onap.vid.aai.model.Properties; import org.onap.vid.aai.model.ResourceType; -import org.onap.vid.services.ProbeInterface; import org.onap.vid.model.SubscriberList; +import org.onap.vid.model.probes.ExternalComponentStatus; +import org.onap.vid.services.ProbeInterface; +import org.springframework.http.HttpMethod; + +import javax.ws.rs.core.Response; +import java.net.URI; +import java.util.List; +import java.util.Map; + /** * Created by Oren on 7/4/17. */ -public interface AaiClientInterface extends ProbeInterface { +public interface AaiClientInterface extends ProbeInterface { boolean isNodeTypeExistsByName(String name, ResourceType type); T typedAaiGet(URI path, Class clz); + T typedAaiRest(URI path, Class clz, String payload, HttpMethod method, boolean propagateExceptions); + AaiResponse getAllSubscribers(); - AaiResponse getSubscriberData(String subscriberId); + AaiResponse getSubscriberData(String subscriberId, boolean omitServiceInstances); AaiResponse getServices(); @@ -68,10 +75,12 @@ public interface AaiClientInterface extends ProbeInterface { Response getVersionByInvariantId(List modelInvariantId); + ModelVer getLatestVersionByInvariantId(String modelInvariantId); + AaiResponse getServicesByProjectNames(List projectNames); AaiResponse getServiceModelsByDistributionStatus(); - + AaiResponse getPNFData(String globalCustomerId, String serviceType, String modelVersionId, String modelInvariantId, String cloudRegion, String equipVendor, String equipModel); AaiResponse getSpecificPnf(String pnfId); diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/BaseInstantiationCommand.java b/vid-app-common/src/main/java/org/onap/vid/aai/model/AaiGetNetworkCollectionDetails/KeyValueModel.java similarity index 67% rename from vid-app-common/src/main/java/org/onap/vid/job/command/BaseInstantiationCommand.java rename to vid-app-common/src/main/java/org/onap/vid/aai/model/AaiGetNetworkCollectionDetails/KeyValueModel.java index 20d71ab29..6e0e1c06a 100644 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/BaseInstantiationCommand.java +++ b/vid-app-common/src/main/java/org/onap/vid/aai/model/AaiGetNetworkCollectionDetails/KeyValueModel.java @@ -7,9 +7,9 @@ * 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. @@ -18,21 +18,25 @@ * ============LICENSE_END========================================================= */ -package org.onap.vid.job.command; +package org.onap.vid.aai.model.AaiGetNetworkCollectionDetails; -import org.onap.vid.job.impl.JobSharedData; +public abstract class KeyValueModel { + private String key; + private String value; -import java.util.Map; - - -public abstract class BaseInstantiationCommand extends CommandBase{ + public String getKey() { + return key; + } + public String getValue() { + return value; + } + public void setKey(String key) { + this.key = key; + } + public void setValue(String value) { + this.value = value; + } - protected CommandParentData commandParentData = new CommandParentData(); - protected BaseInstantiationCommand init(JobSharedData sharedData, Map commandData) { - super.init(sharedData); - commandParentData.initParentData(commandData); - return this; - } } diff --git a/vid-app-common/src/main/java/org/onap/vid/aai/model/AaiGetNetworkCollectionDetails/RelatedToProperty.java b/vid-app-common/src/main/java/org/onap/vid/aai/model/AaiGetNetworkCollectionDetails/RelatedToProperty.java index d53d90fd4..7c5287770 100644 --- a/vid-app-common/src/main/java/org/onap/vid/aai/model/AaiGetNetworkCollectionDetails/RelatedToProperty.java +++ b/vid-app-common/src/main/java/org/onap/vid/aai/model/AaiGetNetworkCollectionDetails/RelatedToProperty.java @@ -7,9 +7,9 @@ * 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. @@ -25,33 +25,30 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; @JsonIgnoreProperties(ignoreUnknown = true) -public class RelatedToProperty { - - public String getPropertyKey() { - return propertyKey; - } - - - public void setPropertyKey(String propertyKey) { - this.propertyKey = propertyKey; - } - - - public String getPropertyValue() { - return propertyValue; - } - - - public void setPropertyValue(String propertyValue) { - this.propertyValue = propertyValue; - } - - - @JsonProperty("property-key") - public String propertyKey; - - - @JsonProperty("property-value") - public String propertyValue; - +public class RelatedToProperty extends KeyValueModel { + + @Override + @JsonProperty("property-key") + public String getKey() { + return super.getKey(); + } + + @Override + @JsonProperty("property-key") + public void setKey(String propertyKey) { + super.setKey(propertyKey); + } + + @Override + @JsonProperty("property-value") + public String getValue() { + return super.getValue(); + } + + @Override + @JsonProperty("property-value") + public void setValue(String propertyValue) { + super.setValue(propertyValue); + } } + diff --git a/vid-app-common/src/main/java/org/onap/vid/aai/model/AaiGetNetworkCollectionDetails/Relationship.java b/vid-app-common/src/main/java/org/onap/vid/aai/model/AaiGetNetworkCollectionDetails/Relationship.java index 4de11500e..110e922c1 100644 --- a/vid-app-common/src/main/java/org/onap/vid/aai/model/AaiGetNetworkCollectionDetails/Relationship.java +++ b/vid-app-common/src/main/java/org/onap/vid/aai/model/AaiGetNetworkCollectionDetails/Relationship.java @@ -7,9 +7,9 @@ * 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. @@ -31,13 +31,13 @@ public class Relationship { @JsonProperty("related-to") public String relatedTo; - + @JsonProperty("related-link") public String relatedLink; @JsonProperty("relationship-label") public String relationshipLabel; - + @JsonProperty("relationship-data") public List relationshipData; diff --git a/vid-app-common/src/main/java/org/onap/vid/aai/model/AaiGetNetworkCollectionDetails/RelationshipData.java b/vid-app-common/src/main/java/org/onap/vid/aai/model/AaiGetNetworkCollectionDetails/RelationshipData.java index cba7f43cb..f480ef8d0 100644 --- a/vid-app-common/src/main/java/org/onap/vid/aai/model/AaiGetNetworkCollectionDetails/RelationshipData.java +++ b/vid-app-common/src/main/java/org/onap/vid/aai/model/AaiGetNetworkCollectionDetails/RelationshipData.java @@ -7,9 +7,9 @@ * 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. @@ -24,26 +24,26 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; @JsonIgnoreProperties(ignoreUnknown = true) -public class RelationshipData { +public class RelationshipData extends KeyValueModel { + + @Override @JsonProperty("relationship-key") - public String getRelationshipKey() { - return relationshipKey; + public String getKey() { + return super.getKey(); } + @Override @JsonProperty("relationship-key") - public void setRelationshipKey(String relationshipKey) { - this.relationshipKey = relationshipKey; + public void setKey(String relationshipKey) { + super.setKey(relationshipKey); } + @Override @JsonProperty("relationship-value") - public String getRelationshipValue() { - return relationshipValue; + public String getValue() { + return super.getValue(); } + @Override @JsonProperty("relationship-value") - public void setRelationshipValue(String relationshipValue) { - this.relationshipValue = relationshipValue; + public void setValue(String relationshipValue) { + super.setValue(relationshipValue); } - - public String relationshipKey; - - public String relationshipValue; - } diff --git a/vid-app-common/src/main/java/org/onap/vid/aai/model/ModelVersions.kt b/vid-app-common/src/main/java/org/onap/vid/aai/model/ModelVersions.kt new file mode 100644 index 000000000..c4aa45d55 --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/aai/model/ModelVersions.kt @@ -0,0 +1,3 @@ +package org.onap.vid.aai.model + +data class ModelVersions(val results: List>) diff --git a/vid-app-common/src/main/java/org/onap/vid/aai/util/AAITreeConverter.java b/vid-app-common/src/main/java/org/onap/vid/aai/util/AAITreeConverter.java index 5be26a0ec..48736bc01 100644 --- a/vid-app-common/src/main/java/org/onap/vid/aai/util/AAITreeConverter.java +++ b/vid-app-common/src/main/java/org/onap/vid/aai/util/AAITreeConverter.java @@ -7,9 +7,9 @@ * 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. @@ -20,36 +20,43 @@ package org.onap.vid.aai.util; -import org.apache.commons.lang3.StringUtils; -import org.onap.vid.model.aaiTree.*; -import org.onap.vid.mso.model.ModelInfo; -import org.onap.vid.services.AAITreeNodeBuilder; -import org.springframework.stereotype.Component; - -import java.util.Objects; - import static java.util.function.Function.identity; import static java.util.stream.Collectors.counting; import static java.util.stream.Collectors.groupingBy; import static org.onap.vid.asdc.parser.ToscaParserImpl2.Constants.A_LA_CARTE; +import java.util.Map; +import java.util.Objects; +import org.apache.commons.lang3.StringUtils; +import org.onap.vid.model.aaiTree.AAITreeNode; +import org.onap.vid.model.aaiTree.CollectionResource; +import org.onap.vid.model.aaiTree.Network; +import org.onap.vid.model.aaiTree.Node; +import org.onap.vid.model.aaiTree.NodeType; +import org.onap.vid.model.aaiTree.ServiceInstance; +import org.onap.vid.model.aaiTree.Vnf; +import org.onap.vid.model.aaiTree.VnfGroup; +import org.onap.vid.model.aaiTree.Vrf; +import org.onap.vid.mso.model.ModelInfo; +import org.springframework.stereotype.Component; + @Component public class AAITreeConverter { public static final String VNF_TYPE = "vnf-type"; public static final String NETWORK_TYPE = "network-type"; + public static final String NETWORK_ROLE = "network-role"; + public static final String PHYSICAL_NETWORK_NAME = "physical-network-name"; + public static final String SERVICE_INSTANCE = "service-instance"; + public static final String TENANT = "tenant"; + public static final String VPN_BINDING = "vpn-binding"; public static final String IS_BASE_VF_MODULE = "is-base-vf-module"; + public static final String SERVICE_INSTANCE_SERVICE_INSTANCE_NAME = "service-instance.service-instance-name"; + public static final String SERVICE_INSTANCE_SERVICE_INSTANCE_ID = "service-instance.service-instance-id"; + public static final String TENANT_TENANT_NAME = "tenant.tenant-name"; - public enum ModelType { - service, - vnf, - network, - instanceGroup, - vfModule - } - - public ServiceInstance convertTreeToUIModel(AAITreeNode rootNode, String globalCustomerId, String serviceType, String instantiationType) { + public ServiceInstance convertTreeToUIModel(AAITreeNode rootNode, String globalCustomerId, String serviceType, String instantiationType, String instanceRole, String instanceType) { ServiceInstance serviceInstance = new ServiceInstance(); serviceInstance.setInstanceId(rootNode.getId()); serviceInstance.setInstanceName(rootNode.getName()); @@ -58,46 +65,60 @@ public class AAITreeConverter { serviceInstance.setSubscriptionServiceType(serviceType); serviceInstance.setIsALaCarte(StringUtils.equals(instantiationType, A_LA_CARTE)); - serviceInstance.setModelInfo(createModelInfo(rootNode, ModelType.service)); + serviceInstance.setModelInfo(createModelInfo(rootNode)); //set children: vnf, network,group rootNode.getChildren().forEach(child -> { - if (child.getType().equals(AAITreeNodeBuilder.GENERIC_VNF)) { + if (child.getType() == NodeType.GENERIC_VNF) { serviceInstance.getVnfs().put(child.getUniqueNodeKey(), Vnf.from(child)); - } else if (child.getType().equals(AAITreeNodeBuilder.NETWORK)) { + } else if (child.getType() == NodeType.NETWORK) { serviceInstance.getNetworks().put(child.getUniqueNodeKey(), Network.from(child)); - } else if (child.getType().equals(AAITreeNodeBuilder.INSTANCE_GROUP)) { - serviceInstance.getVnfGroups().put(child.getUniqueNodeKey(), VnfGroup.from(child)); + } else if (child.getType() == NodeType.INSTANCE_GROUP) { + serviceInstance.getVnfGroups().put(child.getUniqueNodeKey(), new VnfGroup(child)); + } else if (child.getType() == NodeType.COLLECTION_RESOURCE) { + serviceInstance.getCollectionResources().put(child.getUniqueNodeKey(), new CollectionResource(child)); + } else if (isChildVrf(instanceType, instanceRole, child)){ + serviceInstance.getVrfs().put(child.getUniqueNodeKey(), Vrf.from(child)); } }); serviceInstance.setExistingVNFCounterMap( - serviceInstance.getVnfs().entrySet().stream() - .map(k -> k.getValue().getModelInfo().getModelVersionId()) - .collect(groupingBy(identity(), counting())) + getExistingCounterMap(serviceInstance.getVnfs()) ); serviceInstance.setExistingNetworksCounterMap( - serviceInstance.getNetworks().entrySet().stream() - .map(k -> k.getValue().getModelInfo().getModelVersionId()) - .filter(Objects::nonNull) - .collect(groupingBy(identity(), counting())) + getExistingCounterMap(serviceInstance.getNetworks()) ); serviceInstance.setExistingVnfGroupCounterMap( - serviceInstance.getVnfGroups().entrySet().stream() - .map(k -> k.getValue().getModelInfo().getModelVersionId()) - .filter(Objects::nonNull) - .collect(groupingBy(identity(), counting())) + getExistingCounterMap(serviceInstance.getVnfGroups()) + ); + + serviceInstance.setExistingVRFCounterMap( + getExistingCounterMap(serviceInstance.getVrfs()) ); return serviceInstance; } - private static ModelInfo createModelInfo(AAITreeNode aaiNode, ModelType modelType) { + protected boolean isChildVrf(String instanceType, String serviceRole, AAITreeNode child) { + return child.getType() == NodeType.CONFIGURATION && StringUtils.equalsIgnoreCase(instanceType, "BONDING") && StringUtils.equalsIgnoreCase(serviceRole, "INFRASTRUCTURE-VPN"); + } + + private Map getExistingCounterMap(Map nodeList) { + return nodeList.entrySet().stream() + .map(k -> { + ModelInfo modelInfo = k.getValue().getModelInfo(); + return StringUtils.defaultIfEmpty(modelInfo.getModelCustomizationId(), modelInfo.getModelVersionId()); + }) + .filter(Objects::nonNull) + .collect(groupingBy(identity(), counting())); + } + + private static ModelInfo createModelInfo(AAITreeNode aaiNode) { ModelInfo modelInfo = new ModelInfo(); - modelInfo.setModelType(modelType.name()); + modelInfo.setModelType(aaiNode.getType().getModelType()); modelInfo.setModelName(aaiNode.getModelName()); modelInfo.setModelVersion(aaiNode.getModelVersion()); modelInfo.setModelVersionId(aaiNode.getModelVersionId()); diff --git a/vid-app-common/src/main/java/org/onap/vid/aai/util/AAITreeNodeUtils.java b/vid-app-common/src/main/java/org/onap/vid/aai/util/AAITreeNodeUtils.java new file mode 100644 index 000000000..7ff6f280f --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/aai/util/AAITreeNodeUtils.java @@ -0,0 +1,49 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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.vid.aai.util; + +import java.util.List; +import java.util.Optional; +import org.onap.vid.aai.model.AaiGetNetworkCollectionDetails.KeyValueModel; +import org.onap.vid.aai.model.AaiGetNetworkCollectionDetails.Relationship; +import org.onap.vid.aai.model.AaiGetNetworkCollectionDetails.RelationshipList; + +public class AAITreeNodeUtils { + + private AAITreeNodeUtils() { + } + + public static Optional findFirstRelationshipByRelatedTo(RelationshipList relationshipList, String relatedTo) { + if (relationshipList==null || relationshipList.getRelationship()==null) { + return Optional.empty(); + } + return relationshipList.getRelationship().stream().filter(x->relatedTo.equals(x.getRelatedTo())).findFirst(); + } + + public static Optional findFirstValue(List data, String key) { + if (data==null || data.isEmpty()) { + return Optional.empty(); + } + Optional optValue = data.stream().filter(x->key.equals(x.getKey())).findFirst(); + return optValue.map(KeyValueModel::getValue); + } + +} diff --git a/vid-app-common/src/main/java/org/onap/vid/asdc/local/LocalAsdcClient.java b/vid-app-common/src/main/java/org/onap/vid/asdc/local/LocalAsdcClient.java index 7cfd094df..ce1bbe930 100644 --- a/vid-app-common/src/main/java/org/onap/vid/asdc/local/LocalAsdcClient.java +++ b/vid-app-common/src/main/java/org/onap/vid/asdc/local/LocalAsdcClient.java @@ -25,13 +25,6 @@ import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.ObjectMapper; import io.joshworks.restclient.http.HttpResponse; -import org.json.JSONArray; -import org.json.JSONObject; -import org.onap.vid.asdc.AsdcCatalogException; -import org.onap.vid.asdc.AsdcClient; -import org.onap.vid.asdc.beans.Service; -import org.onap.vid.exceptions.GenericUncheckedException; - import java.io.File; import java.io.IOException; import java.io.UnsupportedEncodingException; @@ -39,6 +32,12 @@ import java.net.URLDecoder; import java.nio.file.Path; import java.nio.file.Paths; import java.util.UUID; +import org.json.JSONArray; +import org.json.JSONObject; +import org.onap.vid.asdc.AsdcCatalogException; +import org.onap.vid.asdc.AsdcClient; +import org.onap.vid.asdc.beans.Service; +import org.onap.vid.exceptions.GenericUncheckedException; /** * The Class LocalAsdcClient. @@ -147,14 +146,14 @@ public class LocalAsdcClient implements AsdcClient { return null; } ClassLoader classLoader = getClass().getClassLoader(); - File file = new File(classLoader.getResource(toscaModelURL).getFile()); try { + File file = new File(classLoader.getResource(toscaModelURL).getFile()); //using URLDecoder.decode to convert special characters from %XX to real character //see https://stackoverflow.com/questions/32251251/java-classloader-getresource-with-special-characters-in-path return Paths.get(URLDecoder.decode(file.getPath(), "UTF-8")); - } catch (UnsupportedEncodingException e) { - throw new GenericUncheckedException(e); + } catch (RuntimeException | UnsupportedEncodingException e) { + throw new GenericUncheckedException("Can't find " + toscaModelURL, e); } } diff --git a/vid-app-common/src/main/java/org/onap/vid/asdc/parser/ToscaParserImpl2.java b/vid-app-common/src/main/java/org/onap/vid/asdc/parser/ToscaParserImpl2.java index c702cf40a..735ba437c 100644 --- a/vid-app-common/src/main/java/org/onap/vid/asdc/parser/ToscaParserImpl2.java +++ b/vid-app-common/src/main/java/org/onap/vid/asdc/parser/ToscaParserImpl2.java @@ -7,9 +7,9 @@ * 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. @@ -22,6 +22,8 @@ package org.onap.vid.asdc.parser; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.tuple.Pair; +import org.jetbrains.annotations.Nullable; import org.onap.sdc.tosca.parser.api.ISdcCsarHelper; import org.onap.sdc.tosca.parser.enums.FilterType; import org.onap.sdc.tosca.parser.enums.SdcTypes; @@ -29,7 +31,6 @@ import org.onap.sdc.tosca.parser.exceptions.SdcToscaParserException; import org.onap.sdc.tosca.parser.impl.SdcToscaParserFactory; import org.onap.sdc.toscaparser.api.Group; import org.onap.sdc.toscaparser.api.*; -import org.onap.sdc.toscaparser.api.elements.Metadata; import org.onap.sdc.toscaparser.api.parameters.Input; import org.onap.vid.asdc.beans.Service; import org.onap.vid.model.*; @@ -66,6 +67,7 @@ public class ToscaParserImpl2 { public static final String VF_MODULE_MODEL_NAME = "vfModuleModelName"; public static final String GET_INPUT = "get_input"; public static final String TYPE = "type"; + public static final String QUANTITY = "quantity"; public static final String INSTANTIATION_TYPE = "instantiationType"; //instantiation type @@ -106,8 +108,16 @@ public class ToscaParserImpl2 { public static final String VNF_GROUP = "VnfGroup"; + public static final String VRF_NODE_TYPE = "org.openecomp.nodes.VRFEntry"; + + public static final String PORT_MIRRORING_CONFIGURATION_NODE_TYPE = "org.openecomp.nodes.PortMirroringConfiguration"; + + public static final String PORT_MIRRORING_CONFIGURATION_BY_POLICY_NODE_TYPE = "org.openecomp.nodes.PortMirroringConfigurationByPolicy"; + public static final String NAMING_POLICY_TYPE = "org.openecomp.policies.External"; + public static final String SCALING_POLICY_TYPE = "org.openecomp.policies.scaling.Fixed"; + public static final String ECOMP_GENERATED_NAMING_PROPERTY = "ecomp_generated_naming"; } @@ -119,6 +129,7 @@ public class ToscaParserImpl2 { ServiceModel serviceModel = new ServiceModel(); ISdcCsarHelper sdcCsarHelper = getSdcCsarHelper(path); List policiesTargets = extractNamingPoliciesTargets(sdcCsarHelper); + Map scalingPolicies = extractScalingPolicyOfGroup(sdcCsarHelper); serviceModel.setService(extractServiceFromCsar(asdcServiceMetadata, sdcCsarHelper)); serviceModel.setVolumeGroups(extractVolumeGroups(sdcCsarHelper)); @@ -128,9 +139,10 @@ public class ToscaParserImpl2 { serviceModel.setServiceProxies(extractServiceProxyFromCsar(sdcCsarHelper, policiesTargets)); serviceModel.setNetworks(extractNetworksFromCsar(sdcCsarHelper, policiesTargets)); serviceModel.setPnfs(extractPnfsFromCsar(sdcCsarHelper, policiesTargets)); - serviceModel.setCollectionResource(extractCRFromCsar(sdcCsarHelper, policiesTargets)); + serviceModel.setCollectionResources(extractCRFromCsar(sdcCsarHelper, policiesTargets)); serviceModel.setFabricConfigurations(extractFabricConfigFromCsar(sdcCsarHelper, policiesTargets)); - serviceModel.setVnfGroups(extractVnfGroupsFromCsar(sdcCsarHelper, policiesTargets)); + serviceModel.setVnfGroups(extractVnfGroupsFromCsar(sdcCsarHelper, policiesTargets, scalingPolicies)); + serviceModel.setVrfs(extractVrfsFromCsar(sdcCsarHelper, policiesTargets)); serviceModel.getService().setVidNotions(vidNotionsBuilder.buildVidNotions(sdcCsarHelper, serviceModel)); return serviceModel; } @@ -248,7 +260,7 @@ public class ToscaParserImpl2 { vnf.setVfModules(getVfModulesFromVF(csarHelper, vnf.getCustomizationUuid())); vnf.setVolumeGroups(getVolumeGroupsFromVF(csarHelper, vnf.getCustomizationUuid())); vnf.setVfcInstanceGroups(getVfcInstanceGroup(csarHelper, nodeTemplate)); - if (ToscaNamingPolicy.getEcompNamingValueForNode(nodeTemplate, "nf_naming").equals("true")) { + if ("true".equals(ToscaNamingPolicy.getEcompNamingValueForNode(nodeTemplate, "nf_naming"))) { setEcompNamingProperty(vnf.getProperties(), "true"); } vnfsMaps.put(nodeTemplate.getName(), vnf); @@ -291,7 +303,8 @@ public class ToscaParserImpl2 { } private Map extractPortMirroringConfigFromCsar(ISdcCsarHelper csarHelper, List policiesTargets) { - List nodeTemplates = csarHelper.getServiceNodeTemplateBySdcType(SdcTypes.CONFIGURATION);//TODO change to + List nodeTemplates = csarHelper.getServiceNodeTemplatesByType(Constants.PORT_MIRRORING_CONFIGURATION_NODE_TYPE); + nodeTemplates.addAll(csarHelper.getServiceNodeTemplatesByType(Constants.PORT_MIRRORING_CONFIGURATION_BY_POLICY_NODE_TYPE)); Map configMaps = new HashMap<>(); for (NodeTemplate nodeTemplate : nodeTemplates) { @@ -379,7 +392,7 @@ public class ToscaParserImpl2 { Network newNetwork = new Network(); populateNodeFromNodeTemplate(nodeTemplate, csarHelper, newNetwork, policiesTargets); newNetwork.setModelCustomizationName(nodeTemplate.getName()); - if (ToscaNamingPolicy.getEcompNamingValueForNode(nodeTemplate, "exVL_naming").equals("true")) { + if ("true".equals(ToscaNamingPolicy.getEcompNamingValueForNode(nodeTemplate, "exVL_naming"))) { setEcompNamingProperty(newNetwork.getProperties(), "true"); } networksMap.put(nodeTemplate.getName(), newNetwork); @@ -389,14 +402,7 @@ public class ToscaParserImpl2 { private Map extractPnfsFromCsar(ISdcCsarHelper csarHelper, List policiesTargets) { List nodeTemplates = csarHelper.getServiceNodeTemplateBySdcType(SdcTypes.PNF); - HashMap pnfHashMap = new HashMap<>(); - - for (NodeTemplate nodeTemplate : nodeTemplates) { - Node pnf = new Node(); - populateNodeFromNodeTemplate(nodeTemplate, csarHelper, pnf, policiesTargets); - pnfHashMap.put(nodeTemplate.getName(), pnf); - } - return pnfHashMap; + return this.extractNodesFromCsar(csarHelper,policiesTargets,nodeTemplates); } private Map extractVfModuleFromCsar(ISdcCsarHelper csarHelper) { @@ -426,7 +432,7 @@ public class ToscaParserImpl2 { for (org.onap.sdc.toscaparser.api.parameters.Input input : inputList) { //Set only inputs without annotation to the service level if ( input.getAnnotations() == null ) - inputs.put(input.getName(), convertInput(input, new org.onap.vid.asdc.beans.tosca.Input(), null)); + inputs.put(input.getName(), convertInput(input, new org.onap.vid.asdc.beans.tosca.Input())); } return inputs; } @@ -546,7 +552,7 @@ public class ToscaParserImpl2 { } - public static boolean isModuleTypeIsBaseObjectSafe(Object vfModuleTypeValue) { + public static boolean isModuleTypeIsBaseObjectSafe(@Nullable Object vfModuleTypeValue) { return (vfModuleTypeValue instanceof String) && (isModuleTypeIsBase((String) vfModuleTypeValue)); } @@ -567,7 +573,7 @@ public class ToscaParserImpl2 { for (Input input : inputs) { if ( input.getName().equals(key) ) { org.onap.vid.asdc.beans.tosca.Input localInput = new org.onap.vid.asdc.beans.tosca.Input(); - localInput = convertInput(input, localInput, nodeTemplate); + localInput = convertInput(input, localInput); String name = property.getKey(); commandPropertyMap.put(name, extractCommands(name, key)); inputMap.put(name, localInput); @@ -582,23 +588,13 @@ public class ToscaParserImpl2 { return inputKey.substring(inputKey.indexOf(':') + 1); } - private org.onap.vid.asdc.beans.tosca.Input convertInput(Input parserInput, org.onap.vid.asdc.beans.tosca.Input localInput, NodeTemplate nodeTemplate){ + private org.onap.vid.asdc.beans.tosca.Input convertInput(Input parserInput, org.onap.vid.asdc.beans.tosca.Input localInput) { localInput.setDefault(parserInput.getDefault()); localInput.setDescription(parserInput.getDescription()); localInput.setRequired(parserInput.isRequired()); localInput.setType(parserInput.getType()); localInput.setConstraints(parserInput.getConstraints()); // localInput.setentry_schema() - - //if inputs of inner nodeTemplate - tell its details - if(nodeTemplate != null) { - Metadata metadata = nodeTemplate.getMetaData(); - localInput.setTemplateName(metadata.getValue("name")); - localInput.setTemplateUUID(metadata.getValue("UUID")); - localInput.setTemplateInvariantUUID(metadata.getValue("invariantUUID")); - localInput.setTemplateCustomizationUUID(metadata.getValue("customizationUUID")); - } - return localInput; } @@ -626,15 +622,30 @@ public class ToscaParserImpl2 { return validatedInstantiationType; } - private Map extractVnfGroupsFromCsar(ISdcCsarHelper csarHelper, List policiesTargets) { + private Map extractVrfsFromCsar(ISdcCsarHelper csarHelper, List policiesTargets) { + List nodeTemplates = csarHelper.getServiceNodeTemplatesByType(Constants.VRF_NODE_TYPE); + return this.extractNodesFromCsar(csarHelper,policiesTargets,nodeTemplates); + } + + private Map extractNodesFromCsar(ISdcCsarHelper csarHelper, List policiesTargets, List nodeTemplates){ + HashMap nodeHashMap = new HashMap<>(); + for (NodeTemplate nodeTemplate : nodeTemplates) { + Node node = new Node(); + populateNodeFromNodeTemplate(nodeTemplate, csarHelper, node, policiesTargets); + nodeHashMap.put(nodeTemplate.getName(), node); + } + return nodeHashMap; + } + + private Map extractVnfGroupsFromCsar(ISdcCsarHelper csarHelper, List policiesTargets, Map scalingPolicies) { List resourceGroups = csarHelper.getGroupsOfTopologyTemplateByToscaGroupType(Constants.RESOURCE_GROUP_TYPE); return resourceGroups.stream() .filter(group -> group.getProperties().get(Constants.RESOURCE_GROUP_CONTAINED_TYPE).getValue().equals("VF")) - .collect(toMap(Group::getName, group -> parseResourceGroup(group, csarHelper, policiesTargets))); + .collect(toMap(Group::getName, group -> parseResourceGroup(group, csarHelper, policiesTargets, scalingPolicies))); } - private ResourceGroup parseResourceGroup(Group group, ISdcCsarHelper csarHelper, List policiesTargets) { + private ResourceGroup parseResourceGroup(Group group, ISdcCsarHelper csarHelper, List policiesTargets, Map scalingPolicies) { return new ResourceGroup( Constants.VNF_GROUP, group.getMetadata().getValue(Constants.INVARIANT_UUID), @@ -642,16 +653,19 @@ public class ToscaParserImpl2 { group.getMetadata().getValue(Constants.VERSION), group.getMetadata().getValue(Constants.NAME), group.getMetadata().getValue(Constants.NAME), - getPropertiesOfResourceGroup(group.getProperties(), policiesTargets.contains(group.getName())), + getPropertiesOfResourceGroup(group.getProperties(), policiesTargets.contains(group.getName()), scalingPolicies.get(group.getName())), csarHelper.getGroupMembersFromTopologyTemplate(group.getName()).stream() .collect(toMap(NodeTemplate::getName, node -> getServiceProxyFromNodeTemplate(node, csarHelper, policiesTargets))) ); } - private Map getPropertiesOfResourceGroup(Map properties, boolean hasPolicyTarget) { + private Map getPropertiesOfResourceGroup(Map properties, boolean hasPolicyTarget, Integer qty) { Map propertiesMap = properties.entrySet().stream() .collect(toMap(Map.Entry::getKey, e -> e.getValue().getValue())); propertiesMap.put(Constants.ECOMP_GENERATED_NAMING_PROPERTY, String.valueOf(hasPolicyTarget)); + if (qty != null) { + propertiesMap.put(Constants.QUANTITY, qty); + } return propertiesMap; } @@ -660,9 +674,22 @@ public class ToscaParserImpl2 { List policies = csarHelper.getPoliciesOfTopologyTemplateByToscaPolicyType(Constants.NAMING_POLICY_TYPE); return policies.stream() .filter(policy -> policy.getProperties().get(Constants.TYPE) != null && - policy.getProperties().get(Constants.TYPE).getValue() != null && + policy.getProperties().get(Constants.TYPE).getValue() != null && StringUtils.equalsIgnoreCase(policy.getProperties().get(Constants.TYPE).getValue().toString(), "naming")) .flatMap(policy -> policy.getTargets().stream()) .collect(toList()); } -} + + public Map extractScalingPolicyOfGroup(ISdcCsarHelper csarHelper) { + return csarHelper.getPoliciesOfTopologyTemplateByToscaPolicyType(Constants.SCALING_POLICY_TYPE) + .stream() + .filter(policy -> policy.getProperties().containsKey(Constants.QUANTITY)) + .flatMap(policy -> { + Integer qty = Integer.parseInt(policy.getProperties().get(Constants.QUANTITY).getValue().toString()); + return policy + .getTargets().stream() + .map(target -> Pair.of(target, qty)); + }) + .collect(toMap(Pair::getKey, Pair::getValue)); + } +} \ No newline at end of file diff --git a/vid-app-common/src/main/java/org/onap/vid/asdc/parser/VidNotionsBuilder.java b/vid-app-common/src/main/java/org/onap/vid/asdc/parser/VidNotionsBuilder.java index a28695211..c9c2649ae 100644 --- a/vid-app-common/src/main/java/org/onap/vid/asdc/parser/VidNotionsBuilder.java +++ b/vid-app-common/src/main/java/org/onap/vid/asdc/parser/VidNotionsBuilder.java @@ -7,9 +7,9 @@ * 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. @@ -20,36 +20,75 @@ package org.onap.vid.asdc.parser; +import static org.apache.commons.lang3.StringUtils.equalsAnyIgnoreCase; +import static org.apache.commons.lang3.StringUtils.equalsIgnoreCase; +import static org.apache.commons.lang3.StringUtils.isEmpty; + +import com.google.common.collect.ImmutableMap; +import java.util.Map; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang3.StringUtils; +import org.jetbrains.annotations.Nullable; import org.onap.sdc.tosca.parser.api.ISdcCsarHelper; import org.onap.sdc.toscaparser.api.NodeTemplate; +import org.onap.sdc.toscaparser.api.elements.Metadata; import org.onap.vid.model.ServiceModel; import org.onap.vid.model.VidNotions; import org.onap.vid.properties.Features; import org.togglz.core.manager.FeatureManager; -import static org.apache.commons.lang3.StringUtils.equalsAnyIgnoreCase; -import static org.apache.commons.lang3.StringUtils.equalsIgnoreCase; - public class VidNotionsBuilder { private final FeatureManager featureManager; + //map of service type that are always macro services, and their relevant featureFlag + private static final Map macroServicesByModelCategory = ImmutableMap.of( + VidNotions.ModelCategory.INFRASTRUCTURE_VPN, Features.FLAG_1908_INFRASTRUCTURE_VPN, + VidNotions.ModelCategory.Transport, Features.FLAG_1908_TRANSPORT_SERVICE_NEW_INSTANTIATION_UI, + VidNotions.ModelCategory.SERVICE_WITH_COLLECTION_RESOURCE, Features.FLAG_1908_COLLECTION_RESOURCE_NEW_INSTANTIATION_UI + ); + public VidNotionsBuilder(FeatureManager featureManager) { this.featureManager = featureManager; } - public VidNotions buildVidNotions(ISdcCsarHelper csarHelper, ServiceModel serviceModel) { - final VidNotions.InstantiationUI instantiationUI = suggestInstantiationUI(csarHelper); + VidNotions buildVidNotions(ISdcCsarHelper csarHelper, ServiceModel serviceModel) { + VidNotions.ModelCategory modelCategory = suggestModelCategory(csarHelper, serviceModel); + return new VidNotions( + suggestInstantiationUI(csarHelper, serviceModel), + modelCategory, + suggestViewEditUI(csarHelper, serviceModel), + suggestInstantiationType(serviceModel, modelCategory)); + } - return new VidNotions(instantiationUI, suggestModelCategory(csarHelper), suggestViewEditUI(csarHelper, serviceModel)); + private boolean isMacroTypeByModelCategory(VidNotions.ModelCategory modelCategory) { + Features featureOfMacroType = macroServicesByModelCategory.get(modelCategory); + //if featureOfMacroType is null this service is not a macro by its type + return (featureOfMacroType!=null && featureManager.isActive(featureOfMacroType)); + } + + VidNotions.InstantiationType suggestInstantiationType(ServiceModel serviceModel, VidNotions.ModelCategory modelCategory) { + if (isMacroTypeByModelCategory(modelCategory)) { + return VidNotions.InstantiationType.Macro; + } + if (serviceModel==null || serviceModel.getService()==null || isEmpty(serviceModel.getService().getInstantiationType())) { + return VidNotions.InstantiationType.ClientConfig; + } + String instantiationType = serviceModel.getService().getInstantiationType(); + if (instantiationType.equals(ToscaParserImpl2.Constants.MACRO)) { + return VidNotions.InstantiationType.Macro; + } + if (instantiationType.equals(ToscaParserImpl2.Constants.A_LA_CARTE)) { + return VidNotions.InstantiationType.ALaCarte; + } + + return VidNotions.InstantiationType.ClientConfig; } //UI route a-la-carte services to old UI only if InstantiationUI is LEGACY //So any other value for InstantiationUI other than LEGACY make UI to route //a-la-carte services to new UI - VidNotions.InstantiationUI suggestInstantiationUI(ISdcCsarHelper csarHelper) { + VidNotions.InstantiationUI suggestInstantiationUI(ISdcCsarHelper csarHelper, ServiceModel serviceModel) { if(featureManager.isActive(Features.FLAG_EXP_ANY_ALACARTE_NEW_INSTANTIATION_UI) && isALaCarte(csarHelper)) { return VidNotions.InstantiationUI.ANY_ALACARTE_NEW_UI; } @@ -57,42 +96,91 @@ public class VidNotionsBuilder { return VidNotions.InstantiationUI.SERVICE_WITH_VNF_GROUPING; } if (featureManager.isActive(Features.FLAG_5G_IN_NEW_INSTANTIATION_UI)) { - if (isUuidExactlyHardCoded1ffce89fef3f(csarHelper)) { - return VidNotions.InstantiationUI.SERVICE_UUID_IS_1ffce89f_ef3f_4cbb_8b37_82134590c5de; - } else if (isALaCarte(csarHelper) && hasAnyNetworkWithPropertyNetworkTechnologyEqualsStandardSriovOrOvs(csarHelper)) { - return VidNotions.InstantiationUI.NETWORK_WITH_PROPERTY_NETWORK_TECHNOLOGY_EQUALS_STANDARD_SRIOV_OR_OVS; - } else if (isALaCarte(csarHelper) && hasFabricConfiguration(csarHelper)) { - return VidNotions.InstantiationUI.SERVICE_WITH_FABRIC_CONFIGURATION; - } + VidNotions.InstantiationUI instantiationUI = determine5GInstantiationUI(csarHelper); + if ( instantiationUI != null ) return instantiationUI; + } + if (featureManager.isActive(Features.FLAG_1908_TRANSPORT_SERVICE_NEW_INSTANTIATION_UI) && isTransportService(csarHelper)){ + return VidNotions.InstantiationUI.TRANSPORT_SERVICE; + } + if (featureManager.isActive(Features.FLAG_1908_COLLECTION_RESOURCE_NEW_INSTANTIATION_UI) && isServiceWithCollectionResource(serviceModel)){ + return VidNotions.InstantiationUI.SERVICE_WITH_COLLECTION_RESOURCE; + } + if (featureManager.isActive(Features.FLAG_1908_INFRASTRUCTURE_VPN) && isInfraStructureVpn(csarHelper)){ + return VidNotions.InstantiationUI.INFRASTRUCTURE_VPN; + } + if (featureManager.isActive(Features.FLAG_1908_A_LA_CARTE_VNF_NEW_INSTANTIATION_UI) && isVnfServiceRole(csarHelper)){ + return VidNotions.InstantiationUI.A_LA_CARTE_VNF_SERVICE_ROLE; } - return VidNotions.InstantiationUI.LEGACY; } - VidNotions.ModelCategory suggestModelCategory(ISdcCsarHelper csarHelper) { + private boolean isVnfServiceRole(ISdcCsarHelper csarHelper) { + final String serviceRole = csarHelper.getServiceMetadata().getValue(ToscaParserImpl2.Constants.SERVICE_ROLE ); + return StringUtils.equalsIgnoreCase("VNF" , serviceRole); + } + + @Nullable + private VidNotions.InstantiationUI determine5GInstantiationUI(ISdcCsarHelper csarHelper) { + if (isUuidExactlyHardCoded1ffce89fef3f(csarHelper)) { + return VidNotions.InstantiationUI.SERVICE_UUID_IS_1ffce89f_ef3f_4cbb_8b37_82134590c5de; + } else if (isALaCarte(csarHelper) && hasAnyNetworkWithPropertyNetworkTechnologyEqualsStandardSriovOrOvs(csarHelper)) { + return VidNotions.InstantiationUI.NETWORK_WITH_PROPERTY_NETWORK_TECHNOLOGY_EQUALS_STANDARD_SRIOV_OR_OVS; + } else if (isALaCarte(csarHelper) && hasFabricConfiguration(csarHelper)) { + return VidNotions.InstantiationUI.SERVICE_WITH_FABRIC_CONFIGURATION; + } + return null; + } + + private boolean isTransportService(ISdcCsarHelper csarHelper) { + return ("TRANSPORT".equalsIgnoreCase(csarHelper.getServiceMetadata().getValue(ToscaParserImpl2.Constants.SERVICE_TYPE))); + } + + private boolean isServiceWithCollectionResource(ServiceModel serviceModel){ + return MapUtils.isNotEmpty(serviceModel.getCollectionResources()); + } + + private boolean isInfraStructureVpn(ISdcCsarHelper csarHelper) { + Metadata serviceMetadata = csarHelper.getServiceMetadata(); + return ("BONDING".equalsIgnoreCase(serviceMetadata.getValue(ToscaParserImpl2.Constants.SERVICE_TYPE)) && + "INFRASTRUCTURE-VPN".equalsIgnoreCase(serviceMetadata.getValue(ToscaParserImpl2.Constants.SERVICE_ROLE))); + } + + VidNotions.ModelCategory suggestModelCategory(ISdcCsarHelper csarHelper, ServiceModel serviceModel) { if (isALaCarte(csarHelper) && hasAnyNetworkWithPropertyNetworkTechnologyEqualsStandardSriovOrOvs(csarHelper)){ return VidNotions.ModelCategory.IS_5G_PROVIDER_NETWORK_MODEL; - } else if(isALaCarte(csarHelper) && hasFabricConfiguration(csarHelper)) { + } + if(isALaCarte(csarHelper) && hasFabricConfiguration(csarHelper)) { return VidNotions.ModelCategory.IS_5G_FABRIC_CONFIGURATION_MODEL; - } else { - return VidNotions.ModelCategory.OTHER; } + if (isInfraStructureVpn(csarHelper)) { + return VidNotions.ModelCategory.INFRASTRUCTURE_VPN; + } + if (isTransportService(csarHelper)) { + return VidNotions.ModelCategory.Transport; + } + if (isServiceWithCollectionResource(serviceModel)) { + return VidNotions.ModelCategory.SERVICE_WITH_COLLECTION_RESOURCE; + } + return VidNotions.ModelCategory.OTHER; } VidNotions.InstantiationUI suggestViewEditUI(ISdcCsarHelper csarHelper, ServiceModel serviceModel) { - if (!featureManager.isActive(Features.FLAG_ASYNC_INSTANTIATION)){ - return VidNotions.InstantiationUI.LEGACY; - } if (featureManager.isActive(Features.FLAG_1902_VNF_GROUPING) && isGrouping(csarHelper)) { return VidNotions.InstantiationUI.SERVICE_WITH_VNF_GROUPING; } + if (featureManager.isActive(Features.FLAG_1908_COLLECTION_RESOURCE_NEW_INSTANTIATION_UI) && + featureManager.isActive(Features.FLAG_1908_RESUME_MACRO_SERVICE) && + isServiceWithCollectionResource(serviceModel)) { + return VidNotions.InstantiationUI.SERVICE_WITH_COLLECTION_RESOURCE; + } + if (featureManager.isActive(Features.FLAG_1902_NEW_VIEW_EDIT)) { if (isMacro(serviceModel) && !isMacroExcludedFromAsyncFlow(serviceModel)) { return VidNotions.InstantiationUI.MACRO_SERVICE; } - VidNotions.InstantiationUI instantiationUISuggestion = suggestInstantiationUI(csarHelper); + VidNotions.InstantiationUI instantiationUISuggestion = suggestInstantiationUI(csarHelper, serviceModel); if (instantiationUISuggestion!=VidNotions.InstantiationUI.LEGACY) { return instantiationUISuggestion; } @@ -137,10 +225,8 @@ public class VidNotionsBuilder { boolean isMacroExcludedFromAsyncFlow(ServiceModel serviceModel) { return (MapUtils.isNotEmpty(serviceModel.getPnfs()) || - MapUtils.isNotEmpty(serviceModel.getCollectionResource()) || + MapUtils.isNotEmpty(serviceModel.getCollectionResources()) || (MapUtils.isNotEmpty(serviceModel.getNetworks()) && !featureManager.isActive(Features.FLAG_NETWORK_TO_ASYNC_INSTANTIATION))); - - } private boolean isGrouping(ISdcCsarHelper csarHelper) { diff --git a/vid-app-common/src/main/java/org/onap/vid/changeManagement/CloudConfiguration.java b/vid-app-common/src/main/java/org/onap/vid/changeManagement/CloudConfiguration.java index da4fd0aa5..f24e2615f 100644 --- a/vid-app-common/src/main/java/org/onap/vid/changeManagement/CloudConfiguration.java +++ b/vid-app-common/src/main/java/org/onap/vid/changeManagement/CloudConfiguration.java @@ -7,9 +7,9 @@ * 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. @@ -27,8 +27,8 @@ import java.util.Map; @JsonInclude(JsonInclude.Include.NON_NULL) @JsonPropertyOrder({ -"lcpCloudRegionId", -"tenantId" + "lcpCloudRegionId", + "tenantId" }) public class CloudConfiguration { @JsonProperty("lcpCloudRegionId") @@ -40,32 +40,32 @@ public class CloudConfiguration { @JsonProperty("lcpCloudRegionId") public String getLcpCloudRegionId() { - return lcpCloudRegionId; + return lcpCloudRegionId; } @JsonProperty("lcpCloudRegionId") public void setLcpCloudRegionId(String lcpCloudRegionId) { - this.lcpCloudRegionId = lcpCloudRegionId; + this.lcpCloudRegionId = lcpCloudRegionId; } @JsonProperty("tenantId") public String getTenantId() { - return tenantId; + return tenantId; } @JsonProperty("tenantId") public void setTenantId(String tenantId) { - this.tenantId = tenantId; + this.tenantId = tenantId; } @JsonAnyGetter public Map getAdditionalProperties() { - return this.additionalProperties; + return this.additionalProperties; } @JsonAnySetter public void setAdditionalProperty(String name, Object value) { - this.additionalProperties.put(name, value); + this.additionalProperties.put(name, value); } } diff --git a/vid-app-common/src/main/java/org/onap/vid/controller/AaiController.java b/vid-app-common/src/main/java/org/onap/vid/controller/AaiController.java index 4a4f3d300..eee2acc51 100644 --- a/vid-app-common/src/main/java/org/onap/vid/controller/AaiController.java +++ b/vid-app-common/src/main/java/org/onap/vid/controller/AaiController.java @@ -50,6 +50,7 @@ import org.onap.vid.aai.model.AaiGetPnfs.Pnf; import org.onap.vid.aai.model.AaiGetTenatns.GetTenantsResponse; import org.onap.vid.aai.util.AAIRestInterface; import org.onap.vid.model.VersionByInvariantIdsRequest; +import org.onap.vid.properties.Features; import org.onap.vid.roles.Role; import org.onap.vid.roles.RoleProvider; import org.onap.vid.roles.RoleValidator; @@ -68,6 +69,7 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.servlet.HandlerMapping; import org.springframework.web.servlet.ModelAndView; +import org.togglz.core.manager.FeatureManager; @RestController @@ -80,17 +82,22 @@ public class AaiController extends RestrictedBaseController { private AAIRestInterface aaiRestInterface; private RoleProvider roleProvider; private SystemPropertiesWrapper systemPropertiesWrapper; + private FeatureManager featureManager; + @Autowired public AaiController(AaiService aaiService, AAIRestInterface aaiRestInterface, RoleProvider roleProvider, - SystemPropertiesWrapper systemPropertiesWrapper) { + SystemPropertiesWrapper systemPropertiesWrapper, + FeatureManager featureManager + ) { this.aaiService = aaiService; this.aaiRestInterface = aaiRestInterface; this.roleProvider = roleProvider; this.systemPropertiesWrapper = systemPropertiesWrapper; + this.featureManager = featureManager; } @RequestMapping(value = {"/subscriberSearch"}, method = RequestMethod.GET) @@ -261,13 +268,13 @@ public class AaiController extends RestrictedBaseController { } @RequestMapping(value = "/aai_sub_details/{subscriberId}", method = RequestMethod.GET) - public ResponseEntity GetSubscriberDetails(HttpServletRequest request, - @PathVariable("subscriberId") String subscriberId) throws IOException { + public ResponseEntity getSubscriberDetails(HttpServletRequest request, @PathVariable("subscriberId") String subscriberId, + @RequestParam(value="omitServiceInstances", required = false, defaultValue = "false") boolean omitServiceInstances) throws IOException { ObjectMapper objectMapper = new ObjectMapper(); ResponseEntity responseEntity; List roles = roleProvider.getUserRoles(request); RoleValidator roleValidator = RoleValidator.by(roles); - AaiResponse subscriberData = aaiService.getSubscriberData(subscriberId, roleValidator); + AaiResponse subscriberData = aaiService.getSubscriberData(subscriberId, roleValidator, featureManager.isActive(Features.FLAG_1906_AAI_SUB_DETAILS_REDUCE_DEPTH) && omitServiceInstances); String httpMessage = subscriberData.getT() != null ? objectMapper.writeValueAsString(subscriberData.getT()) : subscriberData.getErrorMessage(); diff --git a/vid-app-common/src/main/java/org/onap/vid/controller/AaiServiceInstanceStandardQueryController.java b/vid-app-common/src/main/java/org/onap/vid/controller/AaiServiceInstanceStandardQueryController.java index 8f56f7795..015f8dc96 100644 --- a/vid-app-common/src/main/java/org/onap/vid/controller/AaiServiceInstanceStandardQueryController.java +++ b/vid-app-common/src/main/java/org/onap/vid/controller/AaiServiceInstanceStandardQueryController.java @@ -21,48 +21,54 @@ package org.onap.vid.controller; -import org.onap.vid.aai.model.AaiGetNetworkCollectionDetails.Network; -import org.onap.vid.aai.model.AaiGetNetworkCollectionDetails.ServiceInstance; -import org.onap.vid.aai.model.AaiGetNetworkCollectionDetails.Vlan; -import org.onap.vid.aai.model.AaiGetNetworkCollectionDetails.Vnf; -import org.onap.vid.aai.util.ServiceInstanceStandardQuery; +import static java.util.stream.Collectors.toList; + +import com.google.common.collect.ImmutableMap; +import java.util.Collection; +import java.util.Collections; +import java.util.Objects; +import java.util.UUID; +import javax.servlet.http.HttpServletRequest; +import org.apache.commons.text.StrSubstitutor; import org.onap.vid.asdc.AsdcCatalogException; import org.onap.vid.exceptions.GenericUncheckedException; import org.onap.vid.model.ServiceModel; import org.onap.vid.model.VidNotions; +import org.onap.vid.model.aaiTree.AAITreeNode; +import org.onap.vid.model.aaiTree.NodeType; import org.onap.vid.properties.Features; +import org.onap.vid.services.AAIServiceTree; import org.onap.vid.services.VidService; -import org.onap.vid.utils.Multival; +import org.onap.vid.utils.Tree; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpMethod; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.togglz.core.manager.FeatureManager; -import javax.servlet.http.HttpServletRequest; -import java.util.Collection; -import java.util.Collections; -import java.util.UUID; - -import static java.util.stream.Collectors.toList; - @RestController @RequestMapping(AaiServiceInstanceStandardQueryController.AAI_STANDARD_QUERY) public class AaiServiceInstanceStandardQueryController extends VidRestrictedBaseController { - public static final String AAI_STANDARD_QUERY = "aai/standardQuery"; + static final String AAI_STANDARD_QUERY = "aai/standardQuery"; + private static final String SERVICE_INSTANCE_URI_TEMPLATE = "" + + "business/customers/customer/${global-customer-id}" + + "/service-subscriptions/service-subscription/${service-type}" + + "/service-instances/service-instance/${service-instance-id}"; - private final ServiceInstanceStandardQuery serviceInstanceStandardQuery; private final FeatureManager featureManager; private final VidService sdcService; + private final AAIServiceTree aaiServiceTree; @Autowired - public AaiServiceInstanceStandardQueryController(FeatureManager featureManager, ServiceInstanceStandardQuery serviceInstanceStandardQuery, VidService sdcService) { + public AaiServiceInstanceStandardQueryController(FeatureManager featureManager, + VidService sdcService, AAIServiceTree aaiServiceTree) { this.featureManager = featureManager; - this.serviceInstanceStandardQuery = serviceInstanceStandardQuery; this.sdcService = sdcService; + this.aaiServiceTree = aaiServiceTree; } @RequestMapping(value = "vlansByNetworks", method = RequestMethod.GET) @@ -80,54 +86,50 @@ public class AaiServiceInstanceStandardQueryController extends VidRestrictedBase return new VlansByNetworksHierarchy(); } - final ServiceInstance serviceInstance = - serviceInstanceStandardQuery.fetchServiceInstance(globalCustomerId, serviceType, serviceInstanceId); + Tree pathsToSearch = new Tree<>(new AAIServiceTree.AaiRelationship(NodeType.SERVICE_INSTANCE)); + pathsToSearch.addPath(AAIServiceTree.toAaiRelationshipList(NodeType.GENERIC_VNF, NodeType.NETWORK, NodeType.VLAN_TAG)); + pathsToSearch.addPath(AAIServiceTree.toAaiRelationshipList(NodeType.NETWORK, NodeType.VLAN_TAG)); - Multival>> l3NetworksWithVlansForVnfForService = fetchVnfsForService(serviceInstance); - Multival> l3NetworksWithVlansForService = fetchNetworksForService(serviceInstance); + AAITreeNode aaiTree = aaiServiceTree.buildAAITree(getServiceInstanceUri(globalCustomerId, serviceType, serviceInstanceId), + null, HttpMethod.GET, pathsToSearch, false).get(0); // translate to response's format return new VlansByNetworksHierarchy( - l3NetworksWithVlansForService.getValues().stream().map(this::translateNetworksFormat - ).collect(toList()), - - l3NetworksWithVlansForVnfForService.getValues().stream().map(vnfWithNetworks -> - new VnfVlansByNetworks(vnfWithNetworks.getKey().getVnfId(), - vnfWithNetworks.getValues().stream().map(this::translateNetworksFormat - ).collect(toList()) - ) - ).collect(toList()) + aaiTree.getChildren().stream() + .filter(child -> child.getType() == NodeType.NETWORK) + .map(this::translateNetworksFormat) + .collect(toList()), + + aaiTree.getChildren().stream() + .filter(child -> child.getType() == NodeType.GENERIC_VNF) + .map(vnf -> new VnfVlansByNetworks(vnf.getId(), + vnf.getChildren().stream() + .map(this::translateNetworksFormat) + .collect(toList()) + )) + .collect(toList()) ); } - private Multival>> fetchVnfsForService(ServiceInstance serviceInstance) { - final Multival vnfsForService = - serviceInstanceStandardQuery.fetchRelatedVnfs(serviceInstance); - - final Multival> vnfsWithL3NetworksForService = - vnfsForService.mapEachVal(vnf -> serviceInstanceStandardQuery.fetchRelatedL3Networks("vnf", vnf)); - - return vnfsWithL3NetworksForService.mapEachVal(vnfMulti-> - vnfMulti.mapEachVal(serviceInstanceStandardQuery::fetchRelatedVlanTags) - ); + private String getServiceInstanceUri(String globalCustomerId, String serviceType, String serviceInstanceId) { + return new StrSubstitutor(ImmutableMap.of( + "global-customer-id", globalCustomerId, + "service-type", serviceType, + "service-instance-id", serviceInstanceId + )).replace(SERVICE_INSTANCE_URI_TEMPLATE); } - private Multival> fetchNetworksForService(ServiceInstance serviceInstance) { - final Multival l3NetworksForService = - serviceInstanceStandardQuery.fetchRelatedL3Networks("service", serviceInstance); - - return l3NetworksForService.mapEachVal(serviceInstanceStandardQuery::fetchRelatedVlanTags); - } - - private NetworksToVlans translateNetworksFormat(Multival networkWithVlan) { + private NetworksToVlans translateNetworksFormat(AAITreeNode networkWithVlan) { return new NetworksToVlans( - networkWithVlan.getKey().getNetworkId(), - networkWithVlan.getKey().getNetworkName(), - networkWithVlan.getKey().getNetworkType(), - networkWithVlan.getKey().getOrchestrationStatus(), - networkWithVlan.getValues().stream().map( - vlan -> new NetworksToVlans.Vlan(vlan.getVlanIdInner()) + networkWithVlan.getId(), + networkWithVlan.getName(), + Objects.toString(networkWithVlan.getAdditionalProperties().get("network-type"), null), + networkWithVlan.getOrchestrationStatus(), + networkWithVlan.getChildren().stream().map( + vlan -> new NetworksToVlans.Vlan( + Objects.toString(vlan.getAdditionalProperties().get("vlan-id-outer"), null) + ) ).collect(toList()) ); } @@ -138,8 +140,8 @@ public class AaiServiceInstanceStandardQueryController extends VidRestrictedBase throw new GenericUncheckedException("Internal error while fetching Service Model: " + sdcModelUuid); } VidNotions.ModelCategory serviceModelCategory = serviceModel.getService().getVidNotions().getModelCategory(); - return serviceModelCategory.equals(VidNotions.ModelCategory.IS_5G_PROVIDER_NETWORK_MODEL) || - serviceModelCategory.equals(VidNotions.ModelCategory.IS_5G_FABRIC_CONFIGURATION_MODEL); + return (serviceModelCategory == VidNotions.ModelCategory.IS_5G_PROVIDER_NETWORK_MODEL) || + (serviceModelCategory == VidNotions.ModelCategory.IS_5G_FABRIC_CONFIGURATION_MODEL); } protected static class VlansByNetworksHierarchy { @@ -182,10 +184,10 @@ public class AaiServiceInstanceStandardQueryController extends VidRestrictedBase } private static class Vlan { - public final String vlanIdInner; + public final String vlanIdOuter; - private Vlan(String vlanIdInner) { - this.vlanIdInner = vlanIdInner; + private Vlan(String vlanIdOuter) { + this.vlanIdOuter = vlanIdOuter; } } diff --git a/vid-app-common/src/main/java/org/onap/vid/controller/AsyncInstantiationController.java b/vid-app-common/src/main/java/org/onap/vid/controller/AsyncInstantiationController.java index 081e3c640..01b005c4b 100644 --- a/vid-app-common/src/main/java/org/onap/vid/controller/AsyncInstantiationController.java +++ b/vid-app-common/src/main/java/org/onap/vid/controller/AsyncInstantiationController.java @@ -7,9 +7,9 @@ * 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. @@ -20,25 +20,28 @@ package org.onap.vid.controller; - -import com.fasterxml.jackson.databind.ObjectMapper; import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; +import org.onap.vid.exceptions.AccessDeniedException; import org.onap.vid.exceptions.OperationNotAllowedException; import org.onap.vid.model.ExceptionResponse; import org.onap.vid.model.JobAuditStatus; import org.onap.vid.model.ServiceInfo; import org.onap.vid.model.serviceInstantiation.ServiceInstantiation; import org.onap.vid.mso.MsoResponseWrapper2; +import org.onap.vid.properties.Features; +import org.onap.vid.roles.RoleProvider; import org.onap.vid.services.AsyncInstantiationBusinessLogic; import org.onap.vid.services.AuditService; import org.onap.vid.utils.SystemPropertiesWrapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; +import org.togglz.core.manager.FeatureManager; import javax.servlet.http.HttpServletRequest; import java.util.List; import java.util.UUID; +import static org.onap.vid.utils.KotlinUtilsKt.JACKSON_OBJECT_MAPPER; import static org.springframework.http.HttpStatus.METHOD_NOT_ALLOWED; @@ -51,14 +54,18 @@ public class AsyncInstantiationController extends VidRestrictedBaseController { protected final AsyncInstantiationBusinessLogic asyncInstantiationBL; private final SystemPropertiesWrapper systemPropertiesWrapper; - protected ObjectMapper objectMapper = new ObjectMapper(); + private final RoleProvider roleProvider; + + private final FeatureManager featureManager; @Autowired protected AuditService auditService; @Autowired - public AsyncInstantiationController(AsyncInstantiationBusinessLogic asyncInstantiationBL, SystemPropertiesWrapper systemPropertiesWrapper) { + public AsyncInstantiationController(AsyncInstantiationBusinessLogic asyncInstantiationBL, RoleProvider roleProvider, FeatureManager featureManager, SystemPropertiesWrapper systemPropertiesWrapper) { this.asyncInstantiationBL = asyncInstantiationBL; + this.roleProvider = roleProvider; + this.featureManager = featureManager; this.systemPropertiesWrapper = systemPropertiesWrapper; } @@ -82,14 +89,25 @@ public class AsyncInstantiationController extends VidRestrictedBaseController { public MsoResponseWrapper2> createBulkOfServices(@RequestBody ServiceInstantiation request, HttpServletRequest httpServletRequest) { //Push to DB according the model try { - LOGGER.debug(EELFLoggerDelegate.debugLogger, "incoming ServiceInstantiation request: "+ objectMapper.writeValueAsString(request)); + LOGGER.debug(EELFLoggerDelegate.debugLogger, "incoming ServiceInstantiation request: "+ JACKSON_OBJECT_MAPPER.writeValueAsString(request)); } catch (Exception e) { LOGGER.error(EELFLoggerDelegate.errorLogger, "failed to log incoming ServiceInstantiation request ", e); } String userId = new ControllersUtils(systemPropertiesWrapper).extractUserId(httpServletRequest); - List uuids = asyncInstantiationBL.pushBulkJob(request, userId); + throwExceptionIfAccessDenied(request, httpServletRequest, userId); + List uuids = asyncInstantiationBL.pushBulkJob(request, userId); + return new MsoResponseWrapper2(200, uuids); + } + + + + @RequestMapping(value = "retryJobWithChangedData/{jobId}", method = RequestMethod.POST) + public MsoResponseWrapper2> retryJobWithChangedData(@RequestBody ServiceInstantiation request, @PathVariable(value="jobId") UUID jobId, HttpServletRequest httpServletRequest) { + + String userId = new ControllersUtils(systemPropertiesWrapper).extractUserId(httpServletRequest); + List uuids = asyncInstantiationBL.retryJob(request, jobId, userId); return new MsoResponseWrapper2(200, uuids); } @@ -105,7 +123,7 @@ public class AsyncInstantiationController extends VidRestrictedBaseController { @RequestMapping(value = "auditStatus/{jobId}", method = RequestMethod.GET) public List getJobAuditStatus(HttpServletRequest request, @PathVariable(value="jobId") UUID jobId, @RequestParam(value="source") JobAuditStatus.SourceStatus source){ - return asyncInstantiationBL.getAuditStatuses(jobId, source); + return auditService.getAuditStatuses(jobId, source); } @RequestMapping(value = "auditStatus/{jobId}/mso", method = RequestMethod.GET) @@ -114,7 +132,7 @@ public class AsyncInstantiationController extends VidRestrictedBaseController { @RequestParam(value="requestId", required = false) UUID requestId, @RequestParam(value="serviceInstanceId", required = false) UUID serviceInstanceId){ if (serviceInstanceId != null) { - return auditService.getAuditStatusFromMsoByServiceInstanceId(jobId, serviceInstanceId); + return auditService.getAuditStatusFromMsoByInstanceId(JobAuditStatus.ResourceTypeFilter.SERVICE, serviceInstanceId, jobId); } if (requestId != null){ return auditService.getAuditStatusFromMsoByRequestId(jobId, requestId); @@ -123,5 +141,36 @@ public class AsyncInstantiationController extends VidRestrictedBaseController { } + @RequestMapping(value = "auditStatus/{type}/{instanceId}/mso", method = RequestMethod.GET) + public List getAuditStatusFromMsoByInstanceId(HttpServletRequest request, + @PathVariable(value="type") JobAuditStatus.ResourceTypeFilter resourceTypeFilter, + @PathVariable(value="instanceId") UUID instanceId) { + return auditService.getAuditStatusFromMsoByInstanceId(resourceTypeFilter, instanceId, null); + } + + @RequestMapping(value = "/bulkForRetry/{jobId}", method = RequestMethod.GET) + public ServiceInstantiation getBulkForRetry(HttpServletRequest request, @PathVariable(value="jobId") UUID jobId) { + return asyncInstantiationBL.getBulkForRetry(jobId); + } + + @RequestMapping(value = "retry/{jobId}", method = RequestMethod.POST) + public MsoResponseWrapper2> retryJobRequest(HttpServletRequest httpServletRequest, + @PathVariable(value="jobId") UUID jobId) { + + String userId = new ControllersUtils(systemPropertiesWrapper).extractUserId(httpServletRequest); + List uuids = asyncInstantiationBL.retryJob(jobId, userId); + return new MsoResponseWrapper2(200, uuids); + } + + @RequestMapping(value = "/auditStatusForRetry/{trackById}", method = RequestMethod.GET) + public JobAuditStatus getResourceAuditStatus(HttpServletRequest request, @PathVariable(value="trackById") String trackById) { + return auditService.getResourceAuditStatus(trackById); + } + + private void throwExceptionIfAccessDenied(ServiceInstantiation request, HttpServletRequest httpServletRequest, String userId) { + if (featureManager.isActive(Features.FLAG_1906_INSTANTIATION_API_USER_VALIDATION) && !roleProvider.getUserRolesValidator(httpServletRequest).isServicePermitted(request.getGlobalSubscriberId(), request.getSubscriptionServiceType())) { + throw new AccessDeniedException(String.format("User %s is not allowed to make this request", userId)); + } + } } diff --git a/vid-app-common/src/main/java/org/onap/vid/controller/MsoConfig.java b/vid-app-common/src/main/java/org/onap/vid/controller/MsoConfig.java index 8d5fbbdbb..20cf6f038 100644 --- a/vid-app-common/src/main/java/org/onap/vid/controller/MsoConfig.java +++ b/vid-app-common/src/main/java/org/onap/vid/controller/MsoConfig.java @@ -56,8 +56,8 @@ public class MsoConfig { @Bean - public MsoBusinessLogic getMsoBusinessLogic(MsoInterface msoClient, FeatureManager featureManager){ - return new MsoBusinessLogicImpl(msoClient, featureManager); + public MsoBusinessLogic getMsoBusinessLogic(MsoInterface msoClient){ + return new MsoBusinessLogicImpl(msoClient); } @Bean diff --git a/vid-app-common/src/main/java/org/onap/vid/controller/MsoController.java b/vid-app-common/src/main/java/org/onap/vid/controller/MsoController.java index db3a21910..fc718f0d2 100644 --- a/vid-app-common/src/main/java/org/onap/vid/controller/MsoController.java +++ b/vid-app-common/src/main/java/org/onap/vid/controller/MsoController.java @@ -20,9 +20,9 @@ package org.onap.vid.controller; +import static org.onap.vid.utils.KotlinUtilsKt.JACKSON_OBJECT_MAPPER; import static org.onap.vid.utils.Logging.getMethodName; -import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; import java.util.LinkedHashMap; import java.util.List; @@ -31,10 +31,14 @@ import javax.servlet.http.HttpServletResponse; import org.onap.portalsdk.core.controller.RestrictedBaseController; import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; import org.onap.vid.model.ExceptionResponse; +import org.onap.vid.model.RequestReferencesContainer; import org.onap.vid.model.SoftDeleteRequest; import org.onap.vid.mso.MsoBusinessLogic; import org.onap.vid.mso.MsoResponseWrapper; import org.onap.vid.mso.MsoResponseWrapper2; +import org.onap.vid.mso.RestMsoImplementation; +import org.onap.vid.mso.RestObject; +import org.onap.vid.mso.rest.MsoRestClientNew; import org.onap.vid.mso.rest.Request; import org.onap.vid.mso.rest.RequestDetails; import org.onap.vid.mso.rest.RequestDetailsWrapper; @@ -82,11 +86,13 @@ public class MsoController extends RestrictedBaseController { public static final String START_LOG = " start"; private final MsoBusinessLogic msoBusinessLogic; + private final RestMsoImplementation restMso; private final CloudOwnerService cloudOwnerService; @Autowired - public MsoController(MsoBusinessLogic msoBusinessLogic, CloudOwnerService cloudOwnerService) { + public MsoController(MsoBusinessLogic msoBusinessLogic, MsoRestClientNew msoClientInterface, CloudOwnerService cloudOwnerService) { this.msoBusinessLogic = msoBusinessLogic; + this.restMso = msoClientInterface; this.cloudOwnerService = cloudOwnerService; } @@ -678,30 +684,35 @@ public class MsoController extends RestrictedBaseController { @RequestMapping(value = "/mso_activate_fabric_configuration/{serviceInstanceId}", method = RequestMethod.POST) public MsoResponseWrapper2 activateFabricConfiguration( - @PathVariable("serviceInstanceId") String serviceInstanceId, - @RequestBody RequestDetails requestDetails) { + @PathVariable("serviceInstanceId") String serviceInstanceId , + @RequestBody RequestDetails requestDetails) { String methodName = "activateFabricConfiguration"; LOGGER.debug(EELFLoggerDelegate.debugLogger, "<== " + methodName + START_LOG); - return msoBusinessLogic.activateFabricConfiguration(serviceInstanceId, requestDetails); + String path = msoBusinessLogic.getActivateFabricConfigurationPath(serviceInstanceId); + RestObject msoResponse = restMso.PostForObject(requestDetails, path, RequestReferencesContainer.class); + + return new MsoResponseWrapper2<>(msoResponse); } @RequestMapping(value = "/mso_vfmodule_soft_delete/{serviceInstanceId}/{vnfInstanceId}/{vfModuleInstanceId}", method = RequestMethod.POST) public MsoResponseWrapper2 deactivateAndCloudDelete( - @PathVariable("serviceInstanceId") String serviceInstanceId, - @PathVariable("vnfInstanceId") String vnfInstanceId, - @PathVariable("vfModuleInstanceId") String vfModuleInstanceId, - @RequestBody SoftDeleteRequest softDeleteRequest) { + @PathVariable("serviceInstanceId") String serviceInstanceId, + @PathVariable("vnfInstanceId") String vnfInstanceId, + @PathVariable("vfModuleInstanceId") String vfModuleInstanceId, + @RequestBody SoftDeleteRequest softDeleteRequest) { String methodName = "deactivateAndCloudDelete"; LOGGER.debug(EELFLoggerDelegate.debugLogger, "<== " + methodName + START_LOG); + String path = msoBusinessLogic.getDeactivateAndCloudDeletePath(serviceInstanceId, vnfInstanceId, vfModuleInstanceId); RequestDetails requestDetails = msoBusinessLogic.buildRequestDetailsForSoftDelete(softDeleteRequest); cloudOwnerService.enrichRequestWithCloudOwner(requestDetails); - return msoBusinessLogic - .deactivateAndCloudDelete(serviceInstanceId, vnfInstanceId, vfModuleInstanceId, requestDetails); + RestObject msoResponse = restMso.PostForObject(new org.onap.vid.changeManagement.RequestDetailsWrapper<>(requestDetails), path, RequestReferencesContainer.class); + + return new MsoResponseWrapper2<>(msoResponse); } /** @@ -723,7 +734,7 @@ public class MsoController extends RestrictedBaseController { exceptionResponse.setException(e.getClass().toString().replaceFirst("^.*\\.", "")); exceptionResponse.setMessage(e.getMessage()); - response.getWriter().write(new ObjectMapper().writeValueAsString(exceptionResponse)); + response.getWriter().write(JACKSON_OBJECT_MAPPER.writeValueAsString(exceptionResponse)); response.flushBuffer(); } diff --git a/vid-app-common/src/main/java/org/onap/vid/controller/WebConfig.java b/vid-app-common/src/main/java/org/onap/vid/controller/WebConfig.java index 8d55c62c6..6f4ce4ddb 100644 --- a/vid-app-common/src/main/java/org/onap/vid/controller/WebConfig.java +++ b/vid-app-common/src/main/java/org/onap/vid/controller/WebConfig.java @@ -21,6 +21,8 @@ package org.onap.vid.controller; +import static org.apache.commons.lang3.ObjectUtils.defaultIfNull; + import static org.apache.commons.lang3.StringUtils.isEmpty; import com.fasterxml.jackson.core.JsonProcessingException; @@ -29,6 +31,7 @@ import io.joshworks.restclient.http.mapper.ObjectMapper; import java.io.File; import java.io.IOException; import javax.servlet.ServletContext; +import java.util.concurrent.Executors; import org.onap.portalsdk.core.util.SystemProperties; import org.onap.vid.aai.AaiClient; import org.onap.vid.aai.AaiClientInterface; @@ -54,6 +57,7 @@ import org.onap.vid.asdc.rest.SdcRestClient; import org.onap.vid.client.SyncRestClient; import org.onap.vid.client.SyncRestClientInterface; import org.onap.vid.properties.AsdcClientConfiguration; +import org.onap.vid.properties.VidProperties; import org.onap.vid.scheduler.SchedulerService; import org.onap.vid.scheduler.SchedulerServiceImpl; import org.onap.vid.services.AAIServiceTree; @@ -73,6 +77,12 @@ import springfox.documentation.spi.DocumentationType; import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger2.annotations.EnableSwagger2; + +import javax.servlet.ServletContext; +import java.io.File; +import java.io.IOException; +import java.util.concurrent.ExecutorService; + @EnableSwagger2 @Configuration public class WebConfig { @@ -95,8 +105,8 @@ public class WebConfig { @Bean public AaiService getAaiService(AaiClientInterface aaiClient, AaiOverTLSClientInterface aaiOverTLSClient, - AaiResponseTranslator aaiResponseTranslator, AAITreeNodeBuilder aaiTreeNode, AAIServiceTree aaiServiceTree) { - return new AaiServiceImpl(aaiClient, aaiOverTLSClient, aaiResponseTranslator, aaiTreeNode, aaiServiceTree); + AaiResponseTranslator aaiResponseTranslator, AAITreeNodeBuilder aaiTreeNode, AAIServiceTree aaiServiceTree, ExecutorService executorService) { + return new AaiServiceImpl(aaiClient, aaiOverTLSClient, aaiResponseTranslator, aaiTreeNode, aaiServiceTree, executorService); } @Bean @@ -223,4 +233,10 @@ public class WebConfig { .paths(PathSelectors.any()) .build(); } + + @Bean + public ExecutorService executorService() { + int threadsCount = defaultIfNull(Integer.parseInt(SystemProperties.getProperty(VidProperties.VID_THREAD_COUNT)), 1); + return Executors.newFixedThreadPool(threadsCount); + } } diff --git a/vid-app-common/src/main/java/org/onap/vid/dal/AsyncInstantiationRepository.kt b/vid-app-common/src/main/java/org/onap/vid/dal/AsyncInstantiationRepository.kt new file mode 100644 index 000000000..79c7297a3 --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/dal/AsyncInstantiationRepository.kt @@ -0,0 +1,147 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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.vid.dal + +import org.onap.portalsdk.core.domain.support.DomainVo +import org.onap.portalsdk.core.service.DataAccessService +import org.onap.vid.dao.JobRequest +import org.onap.vid.exceptions.GenericUncheckedException +import org.onap.vid.exceptions.NotFoundException +import org.onap.vid.job.Job +import org.onap.vid.model.JobAuditStatus +import org.onap.vid.model.ResourceInfo +import org.onap.vid.model.ServiceInfo +import org.onap.vid.model.serviceInstantiation.ServiceInstantiation +import org.onap.vid.utils.DaoUtils +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.stereotype.Repository +import java.sql.Timestamp +import java.time.LocalDateTime +import java.util.* +import kotlin.collections.HashMap + +@Repository +class AsyncInstantiationRepository @Autowired constructor(val dataAccessService:DataAccessService) { + + fun addJobRequest(jobUuid: UUID, request:ServiceInstantiation) { + save(JobRequest(jobUuid, request)) + } + + fun getJobRequest(jobUuid: UUID):ServiceInstantiation? { + return getSingleItem(JobRequest::class.java, "JOB_ID", jobUuid).request + } + + fun saveResourceInfo(resource:ResourceInfo) { + save(resource) + } + + fun getResourceInfoByRootJobId(rootJobId: UUID): Map { + val resourceInfoList:List = getResultList(ResourceInfo::class.java, "ROOT_JOB_ID", rootJobId) + + if (resourceInfoList.isEmpty()) { + throw GenericUncheckedException("Failed to retrieve resource info with rootJobId " + rootJobId + " from ResourceInfo table. no resource found") + } + return resourceInfoList.fold(HashMap(), { accumulator, item -> + accumulator.put(item.trackById, item); accumulator}) + } + + fun getResourceInfoByTrackId(trackById: String):ResourceInfo { + return getSingleItem(ResourceInfo::class.java, "TRACK_BY_ID", trackById) + } + + fun saveServiceInfo(serviceInfo: ServiceInfo) { + save(serviceInfo) + } + + fun getServiceInfoByJobId(jobUuid: UUID): ServiceInfo { + return getSingleItem(ServiceInfo::class.java, "jobId", jobUuid) + } + + fun getServiceInfoByTemplateIdAndJobStatus(templateId: UUID, jobStatus: Job.JobStatus): List { + return getResultList(ServiceInfo::class.java, mapOf("templateId" to templateId, "jobStatus" to jobStatus), "AND") + } + + fun getAllServicesInfo(): List { + return dataAccessService.getList(ServiceInfo::class.java, filterByCreationDateAndNotDeleted(), orderByCreatedDateAndStatus(), null) as List + } + + private fun filterByCreationDateAndNotDeleted(): String { + val minus3Months = LocalDateTime.now().minusMonths(3) + val filterDate = Timestamp.valueOf(minus3Months) + return " WHERE" + + " hidden = false" + + " and deleted_at is null" + // don't fetch deleted + + " and created >= '" + filterDate + "' " + } + + private fun orderByCreatedDateAndStatus(): String { + return " createdBulkDate DESC ,\n" + + " (CASE jobStatus\n" + + " WHEN 'COMPLETED' THEN 0\n" + + " WHEN 'FAILED' THEN 0\n" + + " WHEN 'COMPLETED_WITH_ERRORS' THEN 0\n" + + " WHEN 'IN_PROGRESS' THEN 1\n" + + " WHEN 'PAUSE' THEN 2\n" + + " WHEN 'PENDING' THEN 3\n" + + " WHEN 'STOPPED' THEN 3 END),\n" + + " statusModifiedDate " + } + + fun getAuditStatuses(jobUUID: UUID, source: JobAuditStatus.SourceStatus): List { + // order by ORDINAL. + // CREATED_DATE is kept for backward compatibility: when all Ordinals are zero + return getResultList(JobAuditStatus::class.java, mapOf("SOURCE" to source, "JOB_ID" to jobUUID), "AND", " ORDINAL, CREATED_DATE ") + } + + fun addJobAudiStatus(jobAuditStatus:JobAuditStatus) { + save(jobAuditStatus) + } + + private fun save(item:T) { + dataAccessService.saveDomainObject(item, DaoUtils.getPropsMap()) + } + + private fun getSingleItem(className:Class, filterKey:String, filterValue:Any): T { + val resultList:List = getResultList(className, filterKey, filterValue) + if (resultList.size < 1) { + throw NotFoundException("Failed to retrieve $className with $filterKey $filterValue from table. no resource found") + }else if (resultList.size > 1) { + throw GenericUncheckedException("Failed to retrieve $className with $filterKey $filterValue from table. found more than 1 resources") + } + return resultList[0] + } + + private fun getResultList(className:Class, filterKey:String, filterValue:Any): List { + return getResultList(className, mapOf(filterKey to filterValue), "AND", null) + } + + private fun getResultList(className:Class, filters: Map, conditionType: String): List { + return getResultList(className, filters, conditionType, null) + } + + private fun getResultList(className:Class, filters: Map, conditionType: String, orderBy: String?): List { + var condition:String = filters + .map{f -> f.key + " = '" + f.value + "'"} + .joinToString(" $conditionType ") + return dataAccessService.getList(className, " WHERE $condition", orderBy, null) as List + } +} diff --git a/vid-app-common/src/main/java/org/onap/vid/dao/JobRequest.java b/vid-app-common/src/main/java/org/onap/vid/dao/JobRequest.java new file mode 100644 index 000000000..eb4035836 --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/dao/JobRequest.java @@ -0,0 +1,111 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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.vid.dao; + +import static org.onap.vid.utils.KotlinUtilsKt.JACKSON_OBJECT_MAPPER; + +import com.fasterxml.jackson.core.JsonProcessingException; +import java.io.IOException; +import java.util.Objects; +import java.util.UUID; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; +import javax.persistence.Transient; +import org.hibernate.annotations.DynamicUpdate; +import org.hibernate.annotations.SelectBeforeUpdate; +import org.hibernate.annotations.Type; +import org.onap.vid.model.VidBaseEntity; +import org.onap.vid.model.serviceInstantiation.ServiceInstantiation; + + +@DynamicUpdate +@SelectBeforeUpdate +@Entity +@Table(name = "vid_job_request") +public class JobRequest extends VidBaseEntity { + + private UUID jobId; + private ServiceInstantiation request; + + + public JobRequest(UUID jobId, ServiceInstantiation request) { + this.jobId = jobId; + this.request = request; + } + + public JobRequest() { + } + + @Id + @Column(name = "JOB_ID", columnDefinition = "CHAR(36)") + @Type(type = "org.hibernate.type.UUIDCharType") + public UUID getJobId() { + return jobId; + } + + public void setJobId(UUID jobId) { + this.jobId = jobId; + } + + @Transient + public ServiceInstantiation getRequest() { + return request; + } + + public void setRequest(ServiceInstantiation request) { + this.request = request; + } + + //the columnDefinition is used only in UT + @Column(name = "REQUEST", columnDefinition = "VARCHAR(30000)") + public String getRequestRaw() { + try { + return JACKSON_OBJECT_MAPPER.writeValueAsString(request); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } + + public void setRequestRaw(String raw) { + try { + this.request = JACKSON_OBJECT_MAPPER.readValue(raw, ServiceInstantiation.class); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof JobRequest)) return false; + JobRequest that = (JobRequest) o; + return Objects.equals(getJobId(), that.getJobId()) && + Objects.equals(getRequest(), that.getRequest()); + } + + @Override + public int hashCode() { + return Objects.hash(getJobId(), getRequest()); + } +} + diff --git a/vid-app-common/src/main/java/org/onap/vid/exceptions/AbortingException.java b/vid-app-common/src/main/java/org/onap/vid/exceptions/AbortingException.java new file mode 100644 index 000000000..22c312513 --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/exceptions/AbortingException.java @@ -0,0 +1,28 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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.vid.exceptions; + +public class AbortingException extends RuntimeException { + + public AbortingException(Throwable cause) { + super(cause); + } +} diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/ResourceInProgressStatusCommand.java b/vid-app-common/src/main/java/org/onap/vid/exceptions/AccessDeniedException.java similarity index 52% rename from vid-app-common/src/main/java/org/onap/vid/job/command/ResourceInProgressStatusCommand.java rename to vid-app-common/src/main/java/org/onap/vid/exceptions/AccessDeniedException.java index 123d38bd0..e82bfbc9d 100644 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/ResourceInProgressStatusCommand.java +++ b/vid-app-common/src/main/java/org/onap/vid/exceptions/AccessDeniedException.java @@ -7,9 +7,9 @@ * 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. @@ -18,34 +18,11 @@ * ============LICENSE_END========================================================= */ -package org.onap.vid.job.command; +package org.onap.vid.exceptions; -import org.onap.vid.job.Job; -import org.onap.vid.job.NextCommand; -import org.onap.vid.job.impl.JobSharedData; -import org.springframework.beans.factory.config.ConfigurableBeanFactory; -import org.springframework.context.annotation.Scope; -import org.springframework.stereotype.Component; - -@Component -@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) -public class ResourceInProgressStatusCommand extends BaseInProgressStatusCommand { - - public ResourceInProgressStatusCommand() { - } - - ResourceInProgressStatusCommand(JobSharedData sharedData, String requestId, String instanceId) { - init(sharedData, requestId, instanceId); - } - - @Override - protected ExpiryChecker getExpiryChecker() { - return x->false; - } - - @Override - protected NextCommand processJobStatus(Job.JobStatus jobStatus) { - return new NextCommand(jobStatus, this); +public class AccessDeniedException extends GenericUncheckedException { + public AccessDeniedException(String message) { + super(message); } diff --git a/vid-app-common/src/main/java/org/onap/vid/exceptions/TryAgainException.java b/vid-app-common/src/main/java/org/onap/vid/exceptions/TryAgainException.java new file mode 100644 index 000000000..f46e7e3b5 --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/exceptions/TryAgainException.java @@ -0,0 +1,28 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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.vid.exceptions; + +public class TryAgainException extends RuntimeException { + + public TryAgainException(Throwable cause) { + super(cause); + } +} diff --git a/vid-app-common/src/main/java/org/onap/vid/job/Job.java b/vid-app-common/src/main/java/org/onap/vid/job/Job.java index 3825c2cde..197e03b7b 100644 --- a/vid-app-common/src/main/java/org/onap/vid/job/Job.java +++ b/vid-app-common/src/main/java/org/onap/vid/job/Job.java @@ -7,9 +7,9 @@ * 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. @@ -23,8 +23,11 @@ package org.onap.vid.job; import com.fasterxml.jackson.annotation.JsonIgnore; import org.onap.vid.job.impl.JobSharedData; +import java.util.List; import java.util.Map; import java.util.UUID; +import java.util.stream.Collectors; +import java.util.stream.Stream; public interface Job { @@ -63,7 +66,9 @@ public interface Job { STOPPED(true, true), COMPLETED_WITH_ERRORS(true, true), COMPLETED_WITH_NO_ACTION(true, false), - CREATING(false); + CREATING(false), + PENDING_RESOURCE(false), + ; private final Boolean finalStatus; public Boolean isFinal(){return finalStatus;} @@ -83,5 +88,7 @@ public interface Job { this.failure = failure; } + public static final List FINAL_STATUS = Stream.of(JobStatus.values()).filter(JobStatus::isFinal).collect(Collectors.toList()); + } } diff --git a/vid-app-common/src/main/java/org/onap/vid/job/JobAdapter.java b/vid-app-common/src/main/java/org/onap/vid/job/JobAdapter.java index cd2ab8e4b..53b8a3028 100644 --- a/vid-app-common/src/main/java/org/onap/vid/job/JobAdapter.java +++ b/vid-app-common/src/main/java/org/onap/vid/job/JobAdapter.java @@ -7,9 +7,9 @@ * 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. @@ -32,9 +32,9 @@ import java.util.UUID; public interface JobAdapter { JobModel toModel(Job job); - Job createServiceInstantiationJob(JobType jobType, AsyncJobRequest request, UUID templateId, String userId, String optimisticUniqueServiceInstanceName, Integer indexInBulk); + Job createServiceInstantiationJob(JobType jobType, AsyncJobRequest request, UUID templateId, String userId, String testApi, String optimisticUniqueServiceInstanceName, Integer indexInBulk); - Job createChildJob(JobType jobType, Job.JobStatus jobStatus, AsyncJobRequest request, JobSharedData parentSharedData, Map jobData); + Job createChildJob(JobType jobType, AsyncJobRequest request, JobSharedData parentSharedData, Map jobData, int indexInBulk); // Marks types that are an AsyncJob payload interface AsyncJobRequest { diff --git a/vid-app-common/src/main/java/org/onap/vid/job/JobCommand.java b/vid-app-common/src/main/java/org/onap/vid/job/JobCommand.java index 9d49df003..dfeacae66 100644 --- a/vid-app-common/src/main/java/org/onap/vid/job/JobCommand.java +++ b/vid-app-common/src/main/java/org/onap/vid/job/JobCommand.java @@ -7,9 +7,9 @@ * 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. diff --git a/vid-app-common/src/main/java/org/onap/vid/job/JobException.java b/vid-app-common/src/main/java/org/onap/vid/job/JobException.java index 0ae0b1b98..eb2fecc8e 100644 --- a/vid-app-common/src/main/java/org/onap/vid/job/JobException.java +++ b/vid-app-common/src/main/java/org/onap/vid/job/JobException.java @@ -7,9 +7,9 @@ * 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. diff --git a/vid-app-common/src/main/java/org/onap/vid/job/JobType.java b/vid-app-common/src/main/java/org/onap/vid/job/JobType.java index 7576c430f..b0cfa7a58 100644 --- a/vid-app-common/src/main/java/org/onap/vid/job/JobType.java +++ b/vid-app-common/src/main/java/org/onap/vid/job/JobType.java @@ -7,9 +7,9 @@ * 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. @@ -32,26 +32,20 @@ public enum JobType { HttpCall(HttpCallCommand.class), AggregateState(AggregateStateCommand.class), - ServiceInstantiation(MacroServiceInstantiationCommand.class), - MacroServiceInstantiation(MacroServiceInstantiationCommand.class), - ALaCarteServiceInstantiation(ALaCarteServiceInstantiationCommand.class), + ServiceInstantiation(MacroServiceCommand.class), + MacroServiceInstantiation(MacroServiceCommand.class), + ALaCarteServiceInstantiation(ALaCarteServiceCommand.class), ALaCarteService(ALaCarteServiceCommand.class), - VnfInstantiation(VnfInstantiationCommand.class), - VfmoduleInstantiation(VfmoduleInstantiationCommand.class), - VolumeGroupInstantiation(VolumeGroupInstantiationCommand.class), - VolumeGroupInProgressStatus(VolumeGroupInProgressStatusCommand.class), - NetworkInstantiation(NetworkInstantiationCommand.class), - InstanceGroupInstantiation(InstanceGroupInstantiationCommand.class), + VnfInstantiation(VnfCommand.class), + VfmoduleInstantiation(VfmoduleCommand.class), + VolumeGroupInstantiation(VolumeGroupCommand.class), + NetworkInstantiation(NetworkCommand.class), InstanceGroup(InstanceGroupCommand.class), - InProgressStatus(ServiceInProgressStatusCommand.class), - ResourceInProgressStatus(ResourceInProgressStatusCommand.class), - VnfInProgressStatus(VnfInProgressStatusCommand.class), - Watching(WatchingCommand.class), - WatchingBaseModule(WatchingCommandBaseModule.class), + InstanceGroupMember(InstanceGroupMemberCommand.class), NoOp(NoOpCommand.class); private static final Map REVERSE_MAP = Stream.of(values()) - .filter(not(jobType -> jobType.equals(ServiceInstantiation))) + .filter(not(jobType -> (jobType == ServiceInstantiation) || (jobType == ALaCarteServiceInstantiation))) .collect(Collectors.toMap(t -> t.getCommandClass(), t -> t)); private final Class commandClass; diff --git a/vid-app-common/src/main/java/org/onap/vid/job/JobsBrokerService.java b/vid-app-common/src/main/java/org/onap/vid/job/JobsBrokerService.java index 5da3b309a..6c3eeb9a4 100644 --- a/vid-app-common/src/main/java/org/onap/vid/job/JobsBrokerService.java +++ b/vid-app-common/src/main/java/org/onap/vid/job/JobsBrokerService.java @@ -7,9 +7,9 @@ * 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. @@ -40,4 +40,5 @@ public interface JobsBrokerService { boolean mute(UUID jobId); + void deleteOldFinalJobs(long secondsAgo); } diff --git a/vid-app-common/src/main/java/org/onap/vid/job/NextCommand.java b/vid-app-common/src/main/java/org/onap/vid/job/NextCommand.java index 966158fb9..298a3f439 100644 --- a/vid-app-common/src/main/java/org/onap/vid/job/NextCommand.java +++ b/vid-app-common/src/main/java/org/onap/vid/job/NextCommand.java @@ -7,9 +7,9 @@ * 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. diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/ALaCarteServiceCommand.kt b/vid-app-common/src/main/java/org/onap/vid/job/command/ALaCarteServiceCommand.kt index 29897aceb..9bef3c11b 100644 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/ALaCarteServiceCommand.kt +++ b/vid-app-common/src/main/java/org/onap/vid/job/command/ALaCarteServiceCommand.kt @@ -7,9 +7,9 @@ * 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. @@ -21,14 +21,16 @@ package org.onap.vid.job.command import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate -import org.onap.vid.changeManagement.RequestDetailsWrapper -import org.onap.vid.job.* -import org.onap.vid.model.Action +import org.onap.vid.job.Job +import org.onap.vid.job.JobAdapter +import org.onap.vid.job.JobCommand +import org.onap.vid.job.JobsBrokerService +import org.onap.vid.model.serviceInstantiation.BaseResource import org.onap.vid.model.serviceInstantiation.ServiceInstantiation import org.onap.vid.mso.RestMsoImplementation -import org.onap.vid.mso.model.ServiceDeletionRequestDetails import org.onap.vid.properties.VidProperties import org.onap.vid.services.AsyncInstantiationBusinessLogic +import org.onap.vid.services.AuditService import org.springframework.beans.factory.annotation.Autowired import org.springframework.beans.factory.config.ConfigurableBeanFactory import org.springframework.context.annotation.Scope @@ -38,6 +40,8 @@ import java.time.ZonedDateTime import java.time.temporal.ChronoUnit import java.util.* +const val UNIQUE_INSTANCE_NAME = "optimisticUniqueServiceInstanceName" + class ServiceExpiryChecker : ExpiryChecker { override fun isExpired(jobStartTime: ZonedDateTime?): Boolean { @@ -48,22 +52,20 @@ class ServiceExpiryChecker : ExpiryChecker { } } - @Component @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) class ALaCarteServiceCommand @Autowired constructor( inProgressStatusService: InProgressStatusService, watchChildrenJobsBL: WatchChildrenJobsBL, private val asyncInstantiationBL: AsyncInstantiationBusinessLogic, - private val jobsBrokerService: JobsBrokerService, + jobsBrokerService: JobsBrokerService, + private val msoRequestBuilder: MsoRequestBuilder, msoResultHandlerService: MsoResultHandlerService, - private val jobAdapter: JobAdapter, - restMso: RestMsoImplementation -) : ResourceCommand(restMso, inProgressStatusService, msoResultHandlerService, watchChildrenJobsBL), JobCommand { - - override fun getExpiryChecker(): ExpiryChecker { - return ServiceExpiryChecker(); - } + jobAdapter: JobAdapter, + restMso: RestMsoImplementation, + auditService: AuditService +) : RootServiceCommand(restMso, inProgressStatusService, msoResultHandlerService, + watchChildrenJobsBL, jobsBrokerService, jobAdapter, asyncInstantiationBL, auditService, msoRequestBuilder), JobCommand { companion object { private val LOGGER = EELFLoggerDelegate.getLogger(ALaCarteServiceCommand::class.java) @@ -74,69 +76,27 @@ class ALaCarteServiceCommand @Autowired constructor( } override fun createChildren(): Job.JobStatus { - val dataForChild = buildDataForChild(getRequest())//.plus(ACTION_PHASE to actionPhase) - - val childJobType = when (actionPhase) { - Action.Create -> JobType.InstanceGroupInstantiation - Action.Delete -> JobType.InstanceGroup - else -> return Job.JobStatus.COMPLETED - } + val dataForChild = buildDataForChild(getRequest(), actionPhase) - childJobs = getRequest().vnfGroups - .map { jobAdapter.createChildJob(childJobType, Job.JobStatus.CREATING, it.value, sharedData, dataForChild) } - .map { jobsBrokerService.add(it) } - .map { it.toString() } + childJobs = pushChildrenJobsToBroker(getRequest().children, dataForChild) return Job.JobStatus.COMPLETED_WITH_NO_ACTION } - private fun buildDataForChild(request: ServiceInstantiation): Map { - val commandParentData = CommandParentData() - commandParentData.addInstanceId(CommandParentData.CommandDataKey.SERVICE_INSTANCE_ID, request.instanceId) + override fun addMyselfToChildrenData(commandParentData: CommandParentData, request: BaseResource) { + val instanceId = getActualInstanceId(request) + commandParentData.addInstanceId(CommandParentData.CommandDataKey.SERVICE_INSTANCE_ID, instanceId) commandParentData.addModelInfo(CommandParentData.CommandDataKey.SERVICE_MODEL_INFO, request.modelInfo) - return commandParentData.parentData } - override fun planCreateMyselfRestCall(commandParentData: CommandParentData, request: JobAdapter.AsyncJobRequest, userId: String): MsoRestCallPlan { - TODO("not implemented") - } - - override fun planDeleteMyselfRestCall(commandParentData: CommandParentData, request: JobAdapter.AsyncJobRequest, userId: String): MsoRestCallPlan { - val requestDetailsWrapper = generateServiceDeletionRequest() - val path = asyncInstantiationBL.getServiceDeletionPath(getRequest().instanceId) - return MsoRestCallPlan(HttpMethod.DELETE, path, Optional.of(requestDetailsWrapper), Optional.empty(), - "delete instance with id ${getRequest().instanceId}") - - } + override fun planCreateMyselfRestCall(commandParentData: CommandParentData, request: JobAdapter.AsyncJobRequest, userId: String, testApi: String?): MsoRestCallPlan { + val instantiatePath = asyncInstantiationBL.getServiceInstantiationPath(request as ServiceInstantiation) - override fun handleInProgressStatus(jobStatus: Job.JobStatus): Job.JobStatus { - if (jobStatus==Job.JobStatus.FAILED) { - asyncInstantiationBL.handleFailedInstantiation(sharedData.jobUuid) - return jobStatus - } + val requestDetailsWrapper = msoRequestBuilder.generateALaCarteServiceInstantiationRequest( + request, optimisticUniqueServiceInstanceName, userId) - asyncInstantiationBL.updateServiceInfoAndAuditStatus(sharedData.jobUuid, jobStatus) - return if (jobStatus == Job.JobStatus.PAUSE) Job.JobStatus.IN_PROGRESS else jobStatus - } - - - private fun generateServiceDeletionRequest(): RequestDetailsWrapper { - return asyncInstantiationBL.generateALaCarteServiceDeletionRequest( - sharedData.jobUuid, getRequest(), sharedData.userId - ) - } - - override fun getExternalInProgressStatus() = Job.JobStatus.IN_PROGRESS - - override fun isServiceCommand(): Boolean = true - - override fun onFinal(jobStatus: Job.JobStatus) { - asyncInstantiationBL.updateServiceInfoAndAuditStatus(sharedData.jobUuid, jobStatus) - } + val actionDescription = "create service instance" - override fun onInitial(phase: Action) { - if (phase== Action.Delete) { - asyncInstantiationBL.updateServiceInfoAndAuditStatus(sharedData.jobUuid, Job.JobStatus.IN_PROGRESS) - } + return MsoRestCallPlan(HttpMethod.POST, instantiatePath, Optional.of(requestDetailsWrapper), Optional.empty(), actionDescription) } } diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/AggregateStateCommand.java b/vid-app-common/src/main/java/org/onap/vid/job/command/AggregateStateCommand.java index e64c304cb..34861d0ef 100644 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/AggregateStateCommand.java +++ b/vid-app-common/src/main/java/org/onap/vid/job/command/AggregateStateCommand.java @@ -7,9 +7,9 @@ * 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. diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/BaseInProgressStatusCommand.java b/vid-app-common/src/main/java/org/onap/vid/job/command/BaseInProgressStatusCommand.java deleted file mode 100644 index d21973dc2..000000000 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/BaseInProgressStatusCommand.java +++ /dev/null @@ -1,115 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * VID - * ================================================================================ - * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * 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.vid.job.command; - -import com.google.common.collect.ImmutableMap; -import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; -import org.onap.vid.job.*; -import org.onap.vid.job.impl.JobSharedData; -import org.onap.vid.mso.RestMsoImplementation; -import org.onap.vid.mso.RestObject; -import org.onap.vid.mso.rest.AsyncRequestStatus; -import org.onap.vid.services.AsyncInstantiationBusinessLogic; -import org.togglz.core.manager.FeatureManager; - -import javax.inject.Inject; -import java.util.Map; - -public abstract class BaseInProgressStatusCommand extends BaseInstantiationCommand implements JobCommand { - private static final EELFLoggerDelegate LOGGER = EELFLoggerDelegate.getLogger(BaseInProgressStatusCommand.class); - - @Inject - protected AsyncInstantiationBusinessLogic asyncInstantiationBL; - - @Inject - protected JobsBrokerService jobsBrokerService; - - @Inject - protected JobAdapter jobAdapter; - - @Inject - protected RestMsoImplementation restMso; - - @Inject - protected FeatureManager featureManager; - - @Inject - protected InProgressStatusService inProgressStatusService; - - - protected String requestId; - - protected String instanceId; - - - @Override - public NextCommand call() { - - try { - Job.JobStatus jobStatus = inProgressStatusService.call(getExpiryChecker(), getSharedData(), requestId); - return processJobStatus(jobStatus); - } catch (javax.ws.rs.ProcessingException e) { - // Retry when we can't connect MSO during getStatus - LOGGER.error(EELFLoggerDelegate.errorLogger, "Cannot get orchestration status for {}, will retry: {}", requestId, e, e); - return new NextCommand(Job.JobStatus.IN_PROGRESS, this); - } catch (InProgressStatusService.BadResponseFromMso e) { - return handleFailedMsoResponse(e.getMsoResponse()); - } - catch (RuntimeException e) { - LOGGER.error(EELFLoggerDelegate.errorLogger, "Cannot get orchestration status for {}, stopping: {}", requestId, e, e); - return new NextCommand(Job.JobStatus.STOPPED, this); - } - } - - protected abstract ExpiryChecker getExpiryChecker(); - - abstract NextCommand processJobStatus(Job.JobStatus jobStatus); - - private NextCommand handleFailedMsoResponse(RestObject msoResponse) { - inProgressStatusService.handleFailedMsoResponse(getSharedData().getJobUuid(), requestId, msoResponse); - return new NextCommand(Job.JobStatus.IN_PROGRESS, this); - } - - @Override - public BaseInProgressStatusCommand init(JobSharedData sharedData, Map commandData) { - return init(sharedData, (String) commandData.get("requestId"), (String) commandData.get("instanceId")); - } - - - protected BaseInProgressStatusCommand init(JobSharedData sharedData, - String requestId, - String instanceId) { - init(sharedData); - this.requestId = requestId; - this.instanceId = instanceId; - return this; - } - - @Override - public Map getData() { - return ImmutableMap.of( - "requestId", requestId, - "instanceId", instanceId - ); - } - - -} diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/BaseRootCommand.java b/vid-app-common/src/main/java/org/onap/vid/job/command/BaseRootCommand.java deleted file mode 100644 index 4b81a9412..000000000 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/BaseRootCommand.java +++ /dev/null @@ -1,61 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * VID - * ================================================================================ - * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * 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.vid.job.command; - -import org.onap.vid.job.NextCommand; -import org.onap.vid.job.impl.JobSharedData; -import org.onap.vid.model.RequestReferencesContainer; -import org.onap.vid.model.serviceInstantiation.ServiceInstantiation; -import org.onap.vid.mso.RestObject; - -import javax.inject.Inject; - - -public abstract class BaseRootCommand extends CommandBase{ - - @Inject - private MsoResultHandlerService msoResultHandlerService; - - @Override - protected CommandBase init(JobSharedData sharedData) { - super.init(sharedData); - return this; - } - - protected ServiceInstantiation getRequest() { - return msoResultHandlerService.getRequest(getSharedData()); - } - - protected NextCommand handleRootResponse(RestObject msoResponse){ - MsoResult msoResult = msoResultHandlerService.handleRootResponse(getSharedData().getJobUuid(), msoResponse); - return new NextCommand(msoResult.getJobStatus(), - (msoResult.getMsoResourceIds()!=null) ? - new ServiceInProgressStatusCommand(getSharedData(), msoResult.getMsoResourceIds()) : - null - ); - - } - - protected NextCommand handleCommandFailed() { - return new NextCommand(msoResultHandlerService.handleRootCommandFailed(getSharedData().getJobUuid()).getJobStatus()); - } - -} diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/BaseWatchingCommand.java b/vid-app-common/src/main/java/org/onap/vid/job/command/BaseWatchingCommand.java deleted file mode 100644 index a0b7cd784..000000000 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/BaseWatchingCommand.java +++ /dev/null @@ -1,90 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * VID - * ================================================================================ - * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * 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.vid.job.command; - -import org.apache.commons.lang3.ObjectUtils; -import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; -import org.onap.vid.job.Job; -import org.onap.vid.job.JobCommand; -import org.onap.vid.job.NextCommand; -import org.onap.vid.job.impl.JobSharedData; -import org.onap.vid.services.AsyncInstantiationBusinessLogic; - -import javax.inject.Inject; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public abstract class BaseWatchingCommand extends BaseInstantiationCommand implements JobCommand { - - private static final EELFLoggerDelegate LOGGER = EELFLoggerDelegate.getLogger(BaseWatchingCommand.class); - - @Inject - protected AsyncInstantiationBusinessLogic asyncInstantiationBL; - - @Inject - private WatchChildrenJobsBL watchChildrenJobsBL; - - private List childrenJobsIds; - - protected boolean isService; - - public BaseWatchingCommand() {} - - public BaseWatchingCommand(JobSharedData sharedData, List childrenJobsIds, boolean isService) { - init(sharedData, childrenJobsIds, isService); - } - - @Override - public NextCommand call() { - Job.JobStatus cumulativeJobsStatus = watchChildrenJobsBL.cumulateJobStatus( - watchChildrenJobsBL.retrieveChildrenJobsStatus(childrenJobsIds), - Job.JobStatus.COMPLETED); - return getNextCommand(cumulativeJobsStatus); - } - - protected abstract NextCommand getNextCommand(Job.JobStatus cumulativeJobsStatus); - - @Override - public BaseWatchingCommand init(JobSharedData sharedData, Map commandData) { - return init( - sharedData, - (List) commandData.get("childrenJobs"), - (boolean) commandData.get("isService") - ); - } - - protected BaseWatchingCommand init(JobSharedData sharedData, List childrenJobsIds, boolean isService) { - super.init(sharedData); - this.childrenJobsIds = ObjectUtils.defaultIfNull(childrenJobsIds, new ArrayList<>()); - this.isService = isService; - return this; - } - - @Override - public Map getData() { - Map data = new HashMap<>(); - data.put("childrenJobs", childrenJobsIds); - data.put("isService", isService); - return data; - } -} diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/CommandBase.java b/vid-app-common/src/main/java/org/onap/vid/job/command/CommandBase.java index a13e4dc38..a9b524e01 100644 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/CommandBase.java +++ b/vid-app-common/src/main/java/org/onap/vid/job/command/CommandBase.java @@ -7,9 +7,9 @@ * 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. diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/CommandParentData.java b/vid-app-common/src/main/java/org/onap/vid/job/command/CommandParentData.java index 35f631183..744b2fe39 100644 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/CommandParentData.java +++ b/vid-app-common/src/main/java/org/onap/vid/job/command/CommandParentData.java @@ -7,9 +7,9 @@ * 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. @@ -21,12 +21,15 @@ package org.onap.vid.job.command; import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.ObjectMapper; +import org.onap.vid.model.Action; import org.onap.vid.mso.model.ModelInfo; import java.util.HashMap; import java.util.Map; +import static java.util.Collections.emptyMap; +import static org.onap.vid.utils.KotlinUtilsKt.JACKSON_OBJECT_MAPPER; + public class CommandParentData { @@ -36,6 +39,7 @@ public class CommandParentData { VNF_INSTANCE_ID, VNF_MODEL_INFO, VG_INSTANCE_ID, + VNF_GROUP_INSTANCE_ID, ; } @@ -49,32 +53,30 @@ public class CommandParentData { new TypeReference> () {}; - private ObjectMapper objectMapper = new ObjectMapper(); - private Map getModelInfosByCommandData(Map commandData) { - Object object = commandData.get(RESOURCE_MODEL_INFOS); - if (object != null) { - return objectMapper.convertValue(object, mapCommandKeyToModelInfo); - } - return null; + Object object = commandData.getOrDefault(RESOURCE_MODEL_INFOS, emptyMap()); + return JACKSON_OBJECT_MAPPER.convertValue(object, mapCommandKeyToModelInfo); } private Map getInstanceIdsByCommandData(Map commandData) { - Object object = commandData.get(RESOURCE_INSTANCE_IDS); - if (object != null) { - return objectMapper.convertValue(object, mapCommandKeyToString); - } - return null; + Object object = commandData.getOrDefault(RESOURCE_INSTANCE_IDS, emptyMap()); + return JACKSON_OBJECT_MAPPER.convertValue(object, mapCommandKeyToString); } public Map getParentData() { Map data = new HashMap<>(); data.put(RESOURCE_INSTANCE_IDS, resourceInstancesIds); data.put(RESOURCE_MODEL_INFOS, resourceModelInfos); + + if (actionPhase != null) { + data.put(ResourceCommandKt.ACTION_PHASE, actionPhase); + } + return data; } private Map resourceInstancesIds = new HashMap<>(); private Map resourceModelInfos = new HashMap<>(); + private Action actionPhase = null; public void addModelInfo(CommandDataKey modelInfoKey, ModelInfo modelInfo) { resourceModelInfos.put(modelInfoKey, modelInfo); @@ -83,6 +85,11 @@ public class CommandParentData { public void addInstanceId(CommandDataKey instanceIdKey, String instanceId) { resourceInstancesIds.put(instanceIdKey, instanceId); } + + public void setActionPhase(Action actionPhase) { + this.actionPhase = actionPhase; + } + public ModelInfo getModelInfo(CommandDataKey modelInfoKey) { return resourceModelInfos.get(modelInfoKey); } diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/CommandUtils.java b/vid-app-common/src/main/java/org/onap/vid/job/command/CommandUtils.java index e9936ed4c..0fe7255c4 100644 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/CommandUtils.java +++ b/vid-app-common/src/main/java/org/onap/vid/job/command/CommandUtils.java @@ -7,9 +7,9 @@ * 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. diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/ExpiryChecker.java b/vid-app-common/src/main/java/org/onap/vid/job/command/ExpiryChecker.java index c41963d14..5d608255a 100644 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/ExpiryChecker.java +++ b/vid-app-common/src/main/java/org/onap/vid/job/command/ExpiryChecker.java @@ -7,9 +7,9 @@ * 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. diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/HttpCallCommand.java b/vid-app-common/src/main/java/org/onap/vid/job/command/HttpCallCommand.java index 21c10ffac..9dc88dfea 100644 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/HttpCallCommand.java +++ b/vid-app-common/src/main/java/org/onap/vid/job/command/HttpCallCommand.java @@ -7,9 +7,9 @@ * 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. diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/InProgressStatusService.java b/vid-app-common/src/main/java/org/onap/vid/job/command/InProgressStatusService.java index 842a1bd17..3d1d78f8b 100644 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/InProgressStatusService.java +++ b/vid-app-common/src/main/java/org/onap/vid/job/command/InProgressStatusService.java @@ -7,9 +7,9 @@ * 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. @@ -26,10 +26,12 @@ import org.onap.vid.job.impl.JobSharedData; import org.onap.vid.mso.RestMsoImplementation; import org.onap.vid.mso.RestObject; import org.onap.vid.mso.rest.AsyncRequestStatus; +import org.onap.vid.properties.Features; import org.onap.vid.services.AsyncInstantiationBusinessLogic; import org.onap.vid.services.AuditService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import org.togglz.core.manager.FeatureManager; import java.time.ZonedDateTime; import java.time.format.DateTimeParseException; @@ -48,30 +50,37 @@ public class InProgressStatusService { private final AuditService auditService; + private final FeatureManager featureManager; + @Autowired - public InProgressStatusService(AsyncInstantiationBusinessLogic asyncInstantiationBL, RestMsoImplementation restMso, AuditService auditService) { + public InProgressStatusService(AsyncInstantiationBusinessLogic asyncInstantiationBL, RestMsoImplementation restMso, AuditService auditService, FeatureManager featureManager) { this.asyncInstantiationBL = asyncInstantiationBL; this.restMso = restMso; this.auditService = auditService; + this.featureManager = featureManager; } public Job.JobStatus call(ExpiryChecker expiryChecker, JobSharedData sharedData, String requestId) { RestObject asyncRequestStatus = getAsyncRequestStatus(requestId); - asyncInstantiationBL.auditMsoStatus(sharedData.getRootJobId(), asyncRequestStatus.get().request); + auditService.auditMsoStatus(sharedData.getRootJobId(), asyncRequestStatus.get().request); Job.JobStatus jobStatus = asyncInstantiationBL.calcStatus(asyncRequestStatus.get()); ZonedDateTime jobStartTime = getZonedDateTime(asyncRequestStatus, requestId); jobStatus = expiryChecker.isExpired(jobStartTime) ? Job.JobStatus.FAILED : jobStatus; + asyncInstantiationBL.updateResourceInfo(sharedData, jobStatus, asyncRequestStatus.get()); return jobStatus; } - private RestObject getAsyncRequestStatus(String requestId) { - String path = asyncInstantiationBL.getOrchestrationRequestsPath()+"/"+requestId; + RestObject getAsyncRequestStatus(String requestId) { + String path = asyncInstantiationBL.getOrchestrationRequestsPath() + "/" + requestId + + (featureManager.isActive(Features.FLAG_1908_RESUME_MACRO_SERVICE) ? "?format=detail" : ""); RestObject msoResponse = restMso.GetForObject(path, AsyncRequestStatus.class); + if (msoResponse.getStatusCode() >= 400 || msoResponse.get() == null) { throw new BadResponseFromMso(msoResponse); } + return msoResponse; } diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/InstanceGroupCommand.kt b/vid-app-common/src/main/java/org/onap/vid/job/command/InstanceGroupCommand.kt index e81fcd34e..26fb9aa09 100644 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/InstanceGroupCommand.kt +++ b/vid-app-common/src/main/java/org/onap/vid/job/command/InstanceGroupCommand.kt @@ -7,9 +7,9 @@ * 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. @@ -24,6 +24,8 @@ import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate import org.onap.vid.job.Job import org.onap.vid.job.JobAdapter import org.onap.vid.job.JobCommand +import org.onap.vid.job.JobsBrokerService +import org.onap.vid.model.serviceInstantiation.BaseResource import org.onap.vid.model.serviceInstantiation.InstanceGroup import org.onap.vid.mso.RestMsoImplementation import org.onap.vid.services.AsyncInstantiationBusinessLogic @@ -39,29 +41,42 @@ import java.util.* class InstanceGroupCommand @Autowired constructor( private val asyncInstantiationBL: AsyncInstantiationBusinessLogic, restMso: RestMsoImplementation, + private val msoRequestBuilder: MsoRequestBuilder, msoResultHandlerService: MsoResultHandlerService, inProgressStatusService:InProgressStatusService, - watchChildrenJobsBL: WatchChildrenJobsBL -) : ResourceCommand(restMso, inProgressStatusService, msoResultHandlerService, watchChildrenJobsBL), JobCommand { + watchChildrenJobsBL: WatchChildrenJobsBL, + jobsBrokerService: JobsBrokerService, + jobAdapter: JobAdapter + ) : ResourceCommand(restMso, inProgressStatusService, msoResultHandlerService, + watchChildrenJobsBL, jobsBrokerService, jobAdapter), JobCommand { companion object { private val LOGGER = EELFLoggerDelegate.getLogger(InstanceGroupCommand::class.java) } override fun createChildren(): Job.JobStatus { + val dataForChild = buildDataForChild(getRequest(), actionPhase) + + childJobs = pushChildrenJobsToBroker(getRequest().vnfGroupMembers.values, dataForChild); + return Job.JobStatus.COMPLETED_WITH_NO_ACTION } - override fun planCreateMyselfRestCall(commandParentData: CommandParentData, request: JobAdapter.AsyncJobRequest, userId: String): MsoRestCallPlan { + override fun addMyselfToChildrenData(commandParentData: CommandParentData, request: BaseResource) { + commandParentData.addInstanceId(CommandParentData.CommandDataKey.VNF_GROUP_INSTANCE_ID, request.instanceId) + } + + override fun planCreateMyselfRestCall(commandParentData: CommandParentData, request: JobAdapter.AsyncJobRequest, userId: String, testApi: String?): MsoRestCallPlan { val serviceInstanceId = commandParentData.getInstanceId(CommandParentData.CommandDataKey.SERVICE_INSTANCE_ID) val serviceModelInfo = commandParentData.getModelInfo(CommandParentData.CommandDataKey.SERVICE_MODEL_INFO) val instantiatePath = asyncInstantiationBL.getInstanceGroupInstantiationPath() - val requestDetailsWrapper = asyncInstantiationBL.generateInstanceGroupInstantiationRequest( + val requestDetailsWrapper = msoRequestBuilder.generateInstanceGroupInstantiationRequest( request as InstanceGroup, serviceModelInfo, serviceInstanceId, - userId + userId, + testApi ) val actionDescription = "create instance group in $serviceInstanceId" @@ -76,4 +91,7 @@ class InstanceGroupCommand @Autowired constructor( } -} + override fun getRequest(): InstanceGroup { + return sharedData.request as InstanceGroup + } +} \ No newline at end of file diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/InstanceGroupInstantiationCommand.java b/vid-app-common/src/main/java/org/onap/vid/job/command/InstanceGroupInstantiationCommand.java deleted file mode 100644 index 6d9ddd499..000000000 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/InstanceGroupInstantiationCommand.java +++ /dev/null @@ -1,67 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * VID - * ================================================================================ - * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * 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.vid.job.command;//package org.onap.vid.job.command; - -import org.onap.vid.changeManagement.RequestDetailsWrapper; -import org.onap.vid.job.JobAdapter; -import org.onap.vid.job.command.CommandParentData.CommandDataKey; -import org.onap.vid.model.Action; -import org.onap.vid.model.serviceInstantiation.InstanceGroup; -import org.onap.vid.mso.model.InstanceGroupInstantiationRequestDetails; -import org.onap.vid.services.AsyncInstantiationBusinessLogic; -import org.springframework.beans.factory.config.ConfigurableBeanFactory; -import org.springframework.context.annotation.Scope; -import org.springframework.stereotype.Component; - -import javax.inject.Inject; - -@Component -@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) -public class InstanceGroupInstantiationCommand extends ResourceInstantiationCommand { - - @Inject - private AsyncInstantiationBusinessLogic asyncInstantiationBL; - - @Override - protected String getRequestPath() { - return asyncInstantiationBL.getInstanceGroupInstantiationPath(); - } - - @Override - protected RequestDetailsWrapper generateMSORequest(JobAdapter.AsyncJobRequest request, String userId) { - return asyncInstantiationBL.generateInstanceGroupInstantiationRequest( - (InstanceGroup) getSharedData().getRequest(), - commandParentData.getModelInfo(CommandDataKey.SERVICE_MODEL_INFO), - commandParentData.getInstanceId(CommandDataKey.SERVICE_INSTANCE_ID), - getSharedData().getUserId() - ); - } - - @Override - protected String getJobAuditMSOStatus() { - return "INSTANCE_GROUP_REQUESTED"; - } - - @Override - protected boolean shouldInstantiateMyself() { - return Action.Create == ((InstanceGroup) getSharedData().getRequest()).getAction(); - } -} diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/InstanceGroupMemberCommand.kt b/vid-app-common/src/main/java/org/onap/vid/job/command/InstanceGroupMemberCommand.kt new file mode 100644 index 000000000..d8e9297a3 --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/job/command/InstanceGroupMemberCommand.kt @@ -0,0 +1,63 @@ +package org.onap.vid.job.command + +import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate +import org.onap.vid.job.Job +import org.onap.vid.job.JobAdapter +import org.onap.vid.job.JobCommand +import org.onap.vid.job.JobsBrokerService +import org.onap.vid.model.serviceInstantiation.InstanceGroupMember +import org.onap.vid.mso.RestMsoImplementation +import org.onap.vid.services.AsyncInstantiationBusinessLogic +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.beans.factory.config.ConfigurableBeanFactory +import org.springframework.context.annotation.Scope +import org.springframework.http.HttpMethod +import org.springframework.stereotype.Component +import java.util.* + +@Component +@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) +class InstanceGroupMemberCommand @Autowired constructor( + private val asyncInstantiationBL: AsyncInstantiationBusinessLogic, + restMso: RestMsoImplementation, + private val msoRequestBuilder: MsoRequestBuilder, + msoResultHandlerService: MsoResultHandlerService, + inProgressStatusService:InProgressStatusService, + watchChildrenJobsBL: WatchChildrenJobsBL, + jobsBrokerService: JobsBrokerService, + jobAdapter: JobAdapter +) : ResourceCommand(restMso, inProgressStatusService, msoResultHandlerService, + watchChildrenJobsBL, jobsBrokerService, jobAdapter), JobCommand { + + companion object { + private val LOGGER = EELFLoggerDelegate.getLogger(InstanceGroupMemberCommand::class.java) + } + + override fun createChildren(): Job.JobStatus { + return Job.JobStatus.COMPLETED_WITH_NO_ACTION + } + + override fun planCreateMyselfRestCall(commandParentData: CommandParentData, request: JobAdapter.AsyncJobRequest, userId: String, testApi: String?): MsoRestCallPlan { + val instanceGroupId = commandParentData.getInstanceId(CommandParentData.CommandDataKey.VNF_GROUP_INSTANCE_ID) + + val instantiatePath = asyncInstantiationBL.getInstanceGroupMemberInstantiationPath(instanceGroupId) + + val requestDetailsWrapper = msoRequestBuilder.generateInstanceGroupMemberRequest(getRequest().instanceId, userId) + + val actionDescription = "add instance group member ${getRequest().instanceId} to instance group $instanceGroupId" + + return MsoRestCallPlan(HttpMethod.POST, instantiatePath, Optional.of(requestDetailsWrapper), Optional.empty(), actionDescription) + } + + override fun planDeleteMyselfRestCall(commandParentData: CommandParentData, request: JobAdapter.AsyncJobRequest, userId: String): MsoRestCallPlan { + val instanceGroupId = commandParentData.getInstanceId(CommandParentData.CommandDataKey.VNF_GROUP_INSTANCE_ID) + val path = asyncInstantiationBL.getInstanceGroupMemberDeletePath(instanceGroupId) + val requestDetailsWrapper = msoRequestBuilder.generateInstanceGroupMemberRequest(getRequest().instanceId, userId) + return MsoRestCallPlan(HttpMethod.POST, path, Optional.of(requestDetailsWrapper), Optional.of(userId), + "delete instance group member ${getRequest().instanceId} from instance group $instanceGroupId") + } + + override fun getRequest(): InstanceGroupMember { + return sharedData.request as InstanceGroupMember + } +} \ No newline at end of file diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/JobCommandFactory.java b/vid-app-common/src/main/java/org/onap/vid/job/command/JobCommandFactory.java index 9f9a62201..32828ad5c 100644 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/JobCommandFactory.java +++ b/vid-app-common/src/main/java/org/onap/vid/job/command/JobCommandFactory.java @@ -7,9 +7,9 @@ * 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. diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/MacroServiceCommand.kt b/vid-app-common/src/main/java/org/onap/vid/job/command/MacroServiceCommand.kt new file mode 100644 index 000000000..8ce73d713 --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/job/command/MacroServiceCommand.kt @@ -0,0 +1,98 @@ +package org.onap.vid.job.command + +import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate +import org.onap.vid.aai.ExceptionWithRequestInfo +import org.onap.vid.changeManagement.RequestDetailsWrapper +import org.onap.vid.exceptions.AbortingException +import org.onap.vid.exceptions.MaxRetriesException +import org.onap.vid.exceptions.TryAgainException +import org.onap.vid.job.Job +import org.onap.vid.job.JobAdapter +import org.onap.vid.job.JobCommand +import org.onap.vid.job.JobsBrokerService +import org.onap.vid.model.Action +import org.onap.vid.model.VidNotions.ModelCategory.* +import org.onap.vid.model.serviceInstantiation.ServiceInstantiation +import org.onap.vid.mso.RestMsoImplementation +import org.onap.vid.services.AsyncInstantiationBusinessLogic +import org.onap.vid.services.AuditService +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.beans.factory.config.ConfigurableBeanFactory +import org.springframework.context.annotation.Scope +import org.springframework.http.HttpMethod +import org.springframework.stereotype.Component +import java.util.* + +@Component +@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) +class MacroServiceCommand @Autowired constructor( + inProgressStatusService: InProgressStatusService, + watchChildrenJobsBL: WatchChildrenJobsBL, + private val asyncInstantiationBL: AsyncInstantiationBusinessLogic, + jobsBrokerService: JobsBrokerService, + private val msoRequestBuilder: MsoRequestBuilder, + msoResultHandlerService: MsoResultHandlerService, + jobAdapter: JobAdapter, + restMso: RestMsoImplementation, + auditService: AuditService +) : RootServiceCommand(restMso, inProgressStatusService, msoResultHandlerService, + watchChildrenJobsBL, jobsBrokerService, jobAdapter, asyncInstantiationBL, auditService, msoRequestBuilder), JobCommand { + + + companion object { + private val Logger = EELFLoggerDelegate.getLogger(MacroServiceCommand::class.java) + } + + override fun createChildren(): Job.JobStatus { + return Job.JobStatus.COMPLETED_WITH_NO_ACTION + } + + private val pre1806Models = setOf(Transport, INFRASTRUCTURE_VPN, SERVICE_WITH_COLLECTION_RESOURCE); + + override fun planCreateMyselfRestCall(commandParentData: CommandParentData, request: JobAdapter.AsyncJobRequest, userId: String, testApi: String?): MsoRestCallPlan { + try { + val instantiatePath = asyncInstantiationBL.getServiceInstantiationPath(request as ServiceInstantiation) + + val requestDetailsWrapper = generateRequest(sharedData.jobUuid, request, optimisticUniqueServiceInstanceName, userId) + + val actionDescription = "create macro service instance" + + return MsoRestCallPlan(HttpMethod.POST, instantiatePath, Optional.of(requestDetailsWrapper), Optional.empty(), actionDescription) + } + + //Aai return bad response while checking names uniqueness + catch (exception : ExceptionWithRequestInfo) { + Logger.error("Failed to check name uniqueness in AAI. VID will try again later", exception) + throw TryAgainException(exception); + } + + //Vid reached to max retries while trying to find unique name in AAI + catch (exception : MaxRetriesException) { + Logger.error("Failed to find unused name in AAI", exception) + throw AbortingException(exception); + } + } + + private fun generateRequest(jobUuid: UUID?, request: ServiceInstantiation, optimisticUniqueServiceInstanceName: String, userId: String): RequestDetailsWrapper { + // for transport or for infrastructure VPN - send the pre 1806 request + if (shouldUsePre1806Request(request)){ + return msoRequestBuilder.generateMacroServicePre1806InstantiationRequest(request, userId) + } + return msoRequestBuilder.generateMacroServiceInstantiationRequest(jobUuid, request, optimisticUniqueServiceInstanceName, userId) + } + + protected fun shouldUsePre1806Request(request: ServiceInstantiation): Boolean { + return (request.vidNotions != null && pre1806Models.contains(request.vidNotions.modelCategory)) + } + + + override fun handleInProgressStatus(jobStatus: Job.JobStatus): Job.JobStatus { + asyncInstantiationBL.updateServiceInfoAndAuditStatus(sharedData.jobUuid, jobStatus) + return if (jobStatus==Job.JobStatus.PAUSE) Job.JobStatus.IN_PROGRESS else jobStatus + } + + override fun isDescendantHasAction(phase: Action): Boolean { + return false + } + +} \ No newline at end of file diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/MsoRequestBuilder.kt b/vid-app-common/src/main/java/org/onap/vid/job/command/MsoRequestBuilder.kt new file mode 100644 index 000000000..c8502b1e5 --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/job/command/MsoRequestBuilder.kt @@ -0,0 +1,411 @@ +package org.onap.vid.job.command + +import com.google.common.collect.ImmutableList +import org.apache.commons.lang3.ObjectUtils.defaultIfNull +import org.apache.commons.lang3.StringUtils +import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate +import org.onap.vid.aai.AaiClientInterface +import org.onap.vid.aai.ExceptionWithRequestInfo +import org.onap.vid.aai.model.ResourceType +import org.onap.vid.changeManagement.RequestDetailsWrapper +import org.onap.vid.model.serviceInstantiation.* +import org.onap.vid.mso.model.* +import org.onap.vid.mso.model.BaseResourceInstantiationRequestDetails.* +import org.onap.vid.mso.model.VfModuleInstantiationRequestDetails.UserParamMap +import org.onap.vid.mso.rest.SubscriberInfo +import org.onap.vid.services.AsyncInstantiationBusinessLogic +import org.onap.vid.services.CloudOwnerService +import org.onap.vid.utils.JACKSON_OBJECT_MAPPER +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.stereotype.Service +import org.togglz.core.manager.FeatureManager +import java.util.* +import java.util.Collections.emptyList +import java.util.stream.Collectors + +@Service +class MsoRequestBuilder +@Autowired constructor(private val asyncInstantiationBL: AsyncInstantiationBusinessLogic, + private val cloudOwnerService: CloudOwnerService, + private val aaiClient: AaiClientInterface, + private val featureManager: FeatureManager) { + + companion object { + private val LOGGER = EELFLoggerDelegate.getLogger(MsoRequestBuilder::class.java) + private const val VID_SOURCE = "VID" + } + + fun generateALaCarteServiceInstantiationRequest(payload: ServiceInstantiation, optimisticUniqueServiceInstanceName: String, userId: String): RequestDetailsWrapper { + val userParams = generateUserParamList() + + val requestParameters = ServiceInstantiationRequestDetails.RequestParameters(payload.subscriptionServiceType, true, userParams, payload.testApi) + + val requestDetails = generateServiceInstantiationRequestDetails(payload, requestParameters, optimisticUniqueServiceInstanceName, userId) + + return RequestDetailsWrapper(requestDetails) + } + + fun generateServiceDeletionRequest(payload: ServiceInstantiation, userId: String): RequestDetailsWrapper { + + val requestParameters = ServiceDeletionRequestDetails.RequestParameters(payload.isALaCarte, payload.testApi) + + val requestInfo = ServiceDeletionRequestDetails.RequestInfo( + VID_SOURCE, + userId) + + val requestDetails = ServiceDeletionRequestDetails(payload.modelInfo, requestInfo, requestParameters) + + return RequestDetailsWrapper(requestDetails) + } + + fun generateMacroServiceInstantiationRequest(jobId: UUID?, payload: ServiceInstantiation, optimisticUniqueServiceInstanceName: String, userId: String): RequestDetailsWrapper { + val serviceInstanceName = generateServiceName(jobId, payload, optimisticUniqueServiceInstanceName) + + val serviceInstantiationServiceList = generateServiceInstantiationServicesList(payload, serviceInstanceName, createServiceInstantiationVnfList(jobId, payload)) + + val requestParameters = ServiceInstantiationRequestDetails.RequestParameters(payload.subscriptionServiceType, false, serviceInstantiationServiceList) + + val requestDetails = generateServiceInstantiationRequestDetails(payload, requestParameters, serviceInstanceName, userId) + + return RequestDetailsWrapper(requestDetails) + } + + fun generateNetworkInstantiationRequest(networkDetails: Network, serviceModelInfo: ModelInfo, serviceInstanceId: String, userId: String, testApi: String?): RequestDetailsWrapper { + val requestInfo = generateRequestInfo(networkDetails.instanceName, ResourceType.L3_NETWORK, networkDetails.isRollbackOnFailure, networkDetails.productFamilyId, userId) + val cloudConfiguration = generateCloudConfiguration(networkDetails.lcpCloudRegionId, networkDetails.tenantId) + val platform = Platform(networkDetails.platformName) + val lineOfBusiness = LineOfBusiness.of(networkDetails.lineOfBusiness) + val requestParameters = BaseResourceInstantiationRequestDetails.RequestParameters(generateUserParamList(), testApi) + val relatedInstanceList = generateRelatedInstances(mapOf(serviceInstanceId to serviceModelInfo)) + return RequestDetailsWrapper(NetworkInstantiationRequestDetails(networkDetails.modelInfo, cloudConfiguration, requestInfo, platform, lineOfBusiness, relatedInstanceList, requestParameters)) + } + + fun generateVnfInstantiationRequest(vnfDetails: Vnf, serviceModelInfo: ModelInfo, serviceInstanceId: String, userId: String, testApi: String?): RequestDetailsWrapper { + val requestInfo = generateRequestInfo(vnfDetails.instanceName, ResourceType.GENERIC_VNF, vnfDetails.isRollbackOnFailure, vnfDetails.productFamilyId, userId) + val cloudConfiguration = generateCloudConfiguration(vnfDetails.lcpCloudRegionId, vnfDetails.tenantId) + val platform = Platform(vnfDetails.platformName) + val lineOfBusiness = LineOfBusiness.of(vnfDetails.lineOfBusiness) + val requestParameters = BaseResourceInstantiationRequestDetails.RequestParameters(generateUserParamList(), testApi) + val relatedInstanceList = generateRelatedInstances(mapOf(serviceInstanceId to serviceModelInfo)) + return RequestDetailsWrapper(VnfInstantiationRequestDetails(vnfDetails.modelInfo, cloudConfiguration, requestInfo, platform, lineOfBusiness, relatedInstanceList, requestParameters)) + } + + fun generateDeleteVnfRequest(vnfDetails: Vnf, userId: String): RequestDetailsWrapper { + val requestInfo = generateRequestInfo(null, null, null, null, userId) + val cloudConfiguration = generateCloudConfiguration(vnfDetails.lcpCloudRegionId, vnfDetails.tenantId) + return RequestDetailsWrapper(VnfInstantiationRequestDetails(vnfDetails.modelInfo, cloudConfiguration, requestInfo, null, null, null, null)) + } + + fun generateVfModuleInstantiationRequest(vfModuleDetails: VfModule, serviceModelInfo: ModelInfo, serviceInstanceId: String, vnfModelInfo: ModelInfo, vnfInstanceId: String, vgInstanceId: String?, userId: String, testApi: String?): RequestDetailsWrapper { + val requestInfo = generateRequestInfo(vfModuleDetails.instanceName, ResourceType.VF_MODULE, vfModuleDetails.isRollbackOnFailure, null, userId) + + //cloud configuration + val cloudConfiguration = generateCloudConfiguration(vfModuleDetails.lcpCloudRegionId, vfModuleDetails.tenantId) + + //request parameters + val userParams = aggregateAllInstanceParams(extractActualInstanceParams(vfModuleDetails.instanceParams), vfModuleDetails.supplementaryParams) + val requestParameters = VfModuleInstantiationRequestDetails.RequestParametersVfModule(userParams, vfModuleDetails.isUsePreload, testApi) + + //related instance list + val relatedInstanceList = generateRelatedInstances(mapOf(serviceInstanceId to serviceModelInfo, vnfInstanceId to vnfModelInfo)) + if (StringUtils.isNotEmpty(vgInstanceId)) { + val volumeGroupModel = ModelInfo() + volumeGroupModel.modelType = "volumeGroup" + relatedInstanceList.add(RelatedInstance(volumeGroupModel, vgInstanceId, vfModuleDetails.volumeGroupInstanceName)) + } + return RequestDetailsWrapper(VfModuleInstantiationRequestDetails(vfModuleDetails.modelInfo, cloudConfiguration, requestInfo, relatedInstanceList, requestParameters)) + } + + fun generateVolumeGroupInstantiationRequest(vfModuleDetails: VfModule, serviceModelInfo: ModelInfo, serviceInstanceId: String, vnfModelInfo: ModelInfo, vnfInstanceId: String, userId: String, testApi: String?): RequestDetailsWrapper { + val requestInfo = generateRequestInfo(vfModuleDetails.volumeGroupInstanceName, ResourceType.VOLUME_GROUP, vfModuleDetails.isRollbackOnFailure, null, userId) + val cloudConfiguration = generateCloudConfiguration(vfModuleDetails.lcpCloudRegionId, vfModuleDetails.tenantId) + val userParams = aggregateAllInstanceParams(extractActualInstanceParams(vfModuleDetails.instanceParams), vfModuleDetails.supplementaryParams) + val requestParameters = VfModuleInstantiationRequestDetails.RequestParametersVfModule(userParams, vfModuleDetails.isUsePreload, testApi) + val relatedInstances = generateRelatedInstances(mapOf(serviceInstanceId to serviceModelInfo, vnfInstanceId to vnfModelInfo)) + + vfModuleDetails.modelInfo.modelType = "volumeGroup" + return RequestDetailsWrapper(VolumeGroupRequestDetails(vfModuleDetails.modelInfo, cloudConfiguration, requestInfo, relatedInstances, requestParameters)) + } + + fun generateInstanceGroupInstantiationRequest(instanceGroupDetails: InstanceGroup, serviceModelInfo: ModelInfo, serviceInstanceId: String, userId: String, testApi: String?): RequestDetailsWrapper { + val requestInfo = generateRequestInfo(instanceGroupDetails.instanceName, ResourceType.INSTANCE_GROUP, instanceGroupDetails.isRollbackOnFailure, null, userId) + val requestParameters = BaseResourceInstantiationRequestDetails.RequestParameters(generateUserParamList(), testApi) + val relatedInstanceList = generateRelatedInstances(mapOf(serviceInstanceId to serviceModelInfo)) + return RequestDetailsWrapper(InstanceGroupInstantiationRequestDetails(instanceGroupDetails.modelInfo, requestInfo, relatedInstanceList, requestParameters)) + } + + fun generateInstanceGroupMemberRequest(instanceGroupMemberId: String, userId: String): RequestDetailsWrapper { + val requestInfo = generateRequestInfo(null, null, null, null, userId) + val modelInfo = ModelInfo() + modelInfo.modelType = "vnf" + val relatedInstanceList = generateRelatedInstances(mapOf(instanceGroupMemberId to modelInfo)) + return RequestDetailsWrapper(AddOrRemoveInstanceGroupMemberRequestDetails(requestInfo, relatedInstanceList)) + } + + fun generateDeleteNetworkRequest(networkDetails: Network, userId: String): RequestDetailsWrapper { + val requestInfo = generateRequestInfo(null, null, null, null, userId) + val cloudConfiguration = generateCloudConfiguration(networkDetails.lcpCloudRegionId, networkDetails.tenantId) + return RequestDetailsWrapper(NetworkInstantiationRequestDetails(networkDetails.modelInfo, cloudConfiguration, requestInfo, null, null, null, null)) + } + + fun generateDeleteVfModuleRequest(vfModuleDetails: VfModule, userId: String): RequestDetailsWrapper { + val requestInfo = generateRequestInfo(null, null, null, null, userId) + val cloudConfiguration = generateCloudConfiguration(vfModuleDetails.lcpCloudRegionId, vfModuleDetails.tenantId) + return RequestDetailsWrapper(VfModuleInstantiationRequestDetails(vfModuleDetails.modelInfo, cloudConfiguration, requestInfo, null, null)) + } + + private fun generateServiceName(jobId: UUID?, payload: ServiceInstantiation, optimisticUniqueServiceInstanceName: String): String? { + var serviceInstanceName: String? = null + if (StringUtils.isNotEmpty(optimisticUniqueServiceInstanceName)) { + serviceInstanceName = peekServiceName(jobId, payload, optimisticUniqueServiceInstanceName) + } + return serviceInstanceName + } + + private fun peekServiceName(jobId: UUID?, payload: ServiceInstantiation, optimisticUniqueServiceInstanceName: String): String { + val serviceInstanceName: String + // unique name already exist in service info. If it's free in AAI we use it + if (isNameFreeInAai(optimisticUniqueServiceInstanceName, ResourceType.SERVICE_INSTANCE)) { + serviceInstanceName = optimisticUniqueServiceInstanceName + } else { + serviceInstanceName = asyncInstantiationBL.getUniqueName(payload.instanceName, ResourceType.SERVICE_INSTANCE) + }//otherwise we used the original service instance name (from payload) to get a new unique name from DB and AAI + + //update serviceInfo with new name if needed + try { + asyncInstantiationBL.updateServiceInfo(jobId) { x -> x.serviceInstanceName = serviceInstanceName } + } catch (e: Exception) { + LOGGER.error("Failed updating service name {} in serviceInfo", serviceInstanceName, e) + } + + return serviceInstanceName + } + + @Throws(ExceptionWithRequestInfo::class) + private fun isNameFreeInAai(name: String, resourceType: ResourceType): Boolean { + return !aaiClient.isNodeTypeExistsByName(name, resourceType) + } + + private fun generateServiceInstantiationServicesList(payload: ServiceInstantiation, serviceInstanceName: String?, vnfList: ServiceInstantiationRequestDetails.ServiceInstantiationVnfList): List { + val serviceInstantiationServiceList = LinkedList() + val unFilteredInstanceParams = defaultIfNull>>(payload.instanceParams, emptyList()) + val filteredInstanceParams = removeUnNeededParams(unFilteredInstanceParams) + val serviceInstantiationService = ServiceInstantiationRequestDetails.ServiceInstantiationService( + payload.modelInfo, + serviceInstanceName, + filteredInstanceParams, + vnfList + ) + serviceInstantiationServiceList.add(serviceInstantiationService) + return serviceInstantiationServiceList + } + + private fun removeUnNeededParams(instanceParams: List>?): List> { + val keysToRemove = mutableListOf() + if (instanceParams.isNullOrEmpty()) { + return emptyList() + } + + for (key in instanceParams[0].keys) { + for (paramToIgnore in AsyncInstantiationBusinessLogic.PARAMS_TO_IGNORE) + if (key.equals(paramToIgnore, ignoreCase = true)) { + keysToRemove.add(key) + } + } + + val result : MutableMap = instanceParams[0].entries.stream() + .filter { entry -> !keysToRemove.contains(entry.key) } + .collect(Collectors.toMap({it.key}, {it.value})) + + return if (result.isEmpty()) emptyList() else listOf(result) + } + + private fun createServiceInstantiationVnfList(jobId: UUID?, payload: ServiceInstantiation): ServiceInstantiationRequestDetails.ServiceInstantiationVnfList { + val cloudConfiguration = generateCloudConfiguration(payload.lcpCloudRegionId, payload.tenantId) + val isBulk = asyncInstantiationBL.isPartOfBulk(jobId) + + val vnfs = payload.vnfs + val vnfList = mutableListOf() + for (vnf in vnfs.values) { + val vfModules = vnf.vfModules + val convertedUnFilteredVfModules = convertVfModuleMapToList(vfModules) + val filteredVfModules = filterInstanceParamsFromVfModuleAndUniqueNames(convertedUnFilteredVfModules, isBulk) + val serviceInstantiationVnf = ServiceInstantiationRequestDetails.ServiceInstantiationVnf( + vnf.modelInfo, + cloudConfiguration, + vnf.platformName, + vnf.lineOfBusiness, + payload.productFamilyId, + buildVnfInstanceParams(vnf.instanceParams, filteredVfModules), + filteredVfModules, + getUniqueNameIfNeeded(vnf.instanceName, ResourceType.GENERIC_VNF, isBulk) + ) + vnfList.add(serviceInstantiationVnf) + } + + return ServiceInstantiationRequestDetails.ServiceInstantiationVnfList(vnfList) + } + + private fun convertVfModuleMapToList(vfModules: Map>): List { + return vfModules.values.stream().flatMap { vfModule -> + vfModule.values.stream().map { item -> + val aggregatedParams = aggregateAllInstanceParams(extractActualInstanceParams(item.instanceParams), item.supplementaryParams) + val aggregatedParamsConverted = JACKSON_OBJECT_MAPPER.convertValue(aggregatedParams, List::class.java) + + VfModuleMacro( + item.modelInfo, + item.instanceName, + item.volumeGroupInstanceName, + aggregatedParamsConverted as List>) + } + }.collect(Collectors.toList()) + } + + fun aggregateAllInstanceParams(instanceParams: Map?, supplementaryParams: Map?): List> { + var instanceParamsFinal: Map = instanceParams ?: emptyMap() + val supplementaryParamsFinal: Map = supplementaryParams ?: emptyMap() + + if (!(instanceParamsFinal.isEmpty() && supplementaryParamsFinal.isEmpty())) { + //remove duplicate keys from instanceParams if exist in supplementaryParams + instanceParamsFinal = instanceParamsFinal.entries.stream() + .filter { m -> !supplementaryParamsFinal.containsKey(m.key) } + .collect(Collectors.toMap({ it.key }, { it.value })) + + //aggregate the 2 collections and format them as UserParamMap + val aggregatedParams = UserParamMap() + aggregatedParams.putAll(instanceParamsFinal) + aggregatedParams.putAll(supplementaryParamsFinal) + + return mutableListOf(aggregatedParams) + } + + return emptyList() + } + + //Make sure we always get a one Map from InstanceParams + private fun extractActualInstanceParams(originalInstanceParams: List>?): MutableMap { + return if (originalInstanceParams.isNullOrEmpty() || originalInstanceParams[0].isNullOrEmpty()) { + mutableMapOf() + } else originalInstanceParams[0] + } + + private fun filterInstanceParamsFromVfModuleAndUniqueNames(unFilteredVfModules: List, isBulk: Boolean): List { + return unFilteredVfModules.stream().map { vfModule -> + VfModuleMacro( + vfModule.modelInfo, + getUniqueNameIfNeeded(vfModule.instanceName, ResourceType.VF_MODULE, isBulk), + getUniqueNameIfNeeded(vfModule.volumeGroupInstanceName, ResourceType.VOLUME_GROUP, isBulk), + removeUnNeededParams(vfModule.instanceParams)) + } + .collect(Collectors.toList()) + } + + fun buildVnfInstanceParams(currentVnfInstanceParams: List>, vfModules: List): List> { + val filteredVnfInstanceParams = removeUnNeededParams(currentVnfInstanceParams) + + val vnfInstanceParams = extractActualInstanceParams(filteredVnfInstanceParams) + vfModules.stream() + .map { x -> extractActualInstanceParams(x.instanceParams) } + .forEach { vnfInstanceParams.putAll(it) } + return if (vnfInstanceParams.isEmpty()) emptyList() else ImmutableList.of(vnfInstanceParams) + } + + private fun generateServiceInstantiationRequestDetails(payload: ServiceInstantiation, requestParameters: ServiceInstantiationRequestDetails.RequestParameters, serviceInstanceName: String?, userId: String): ServiceInstantiationRequestDetails { + val requestInfo = ServiceInstantiationRequestDetails.RequestInfo(serviceInstanceName, + payload.productFamilyId, + VID_SOURCE, + payload.isRollbackOnFailure, + userId) + val owningEntity = ServiceInstantiationRequestDetails.ServiceInstantiationOwningEntity(payload.owningEntityId, payload.owningEntityName) + val subscriberInfo = generateSubscriberInfo(payload) + val project = if (payload.projectName != null) ServiceInstantiationRequestDetails.Project(payload.projectName) else null + return ServiceInstantiationRequestDetails(payload.modelInfo, owningEntity, subscriberInfo, project, requestInfo, requestParameters) + } + + private fun generateSubscriberInfo(payload: ServiceInstantiation): SubscriberInfo { + val subscriberInfo = SubscriberInfo() + subscriberInfo.globalSubscriberId = payload.globalSubscriberId + return subscriberInfo + } + + private fun generateCloudConfiguration(lcpCloudRegionId: String?, tenantId: String?): CloudConfiguration { + val cloudConfiguration = CloudConfiguration(lcpCloudRegionId, tenantId) + if(lcpCloudRegionId != null){ + cloudOwnerService.enrichCloudConfigurationWithCloudOwner(cloudConfiguration, lcpCloudRegionId) + } + return cloudConfiguration + } + + private fun generateRelatedInstances(relatedInstances: Map): MutableList { + return relatedInstances.entries.stream() + .map { RelatedInstance(it.value, it.key) } + .collect(Collectors.toList()) + } + + private fun generateRequestInfo(instanceName: String?, resourceType: ResourceType?, rollbackOnFailure: Boolean?, productFamilyId: String?, userId: String) : BaseResourceInstantiationRequestDetails.RequestInfo { + return BaseResourceInstantiationRequestDetails.RequestInfo( + if (resourceType == null) null else getUniqueNameIfNeeded(instanceName, resourceType, false), + productFamilyId, + VID_SOURCE, + rollbackOnFailure, + userId) + + } + + private fun getUniqueNameIfNeeded(name: String?, resourceType: ResourceType, isBulk: Boolean): String? { + return if (StringUtils.isNotEmpty(name)) { + if (isBulk) asyncInstantiationBL.getUniqueName(name, resourceType) else name + } else { + null + } + } + + private fun generateUserParamList(): List { + return emptyList() + } + + fun generateMacroServicePre1806InstantiationRequest(payload: ServiceInstantiation, userId: String): RequestDetailsWrapper { + val requestInfo = ServiceInstantiationRequestDetails.RequestInfo(payload.instanceName, payload.productFamilyId, VID_SOURCE, payload.isRollbackOnFailure, userId) + val userParams = generateUserParamsNameAndValue(payload.instanceParams) + val requestParameters = ServiceInstantiationRequestDetails.RequestParameters(payload.subscriptionServiceType, false, userParams) + val subscriberInfo = generateSubscriberInfoPre1806(payload) + val project = if (payload.projectName != null) ServiceInstantiationRequestDetails.Project(payload.projectName) else null + val owningEntity = ServiceInstantiationRequestDetails.ServiceInstantiationOwningEntity(payload.owningEntityId, payload.owningEntityName) + val cloudConfiguration = generateCloudConfiguration(payload.lcpCloudRegionId, payload.tenantId) + val relatedInstanceList = generateRelatedInstanceListForVrfEntry(payload.vrfs) + + return RequestDetailsWrapper(ServiceInstantiationPre1806RequestDetails( + payload.modelInfo, + owningEntity, + subscriberInfo, + project, + requestInfo, + requestParameters, + cloudConfiguration, + relatedInstanceList)) + } + + private fun generateUserParamsNameAndValue(instanceParams: List>): List { + if (instanceParams == null){ + return emptyList() + } + return instanceParams.getOrElse(0, {emptyMap()}).map{x-> ServiceInstantiationRequestDetails.UserParamNameAndValue(x.key, x.value)} + } + + private fun generateSubscriberInfoPre1806(payload: ServiceInstantiation): SubscriberInfo { + val subscriberInfo = SubscriberInfo() + subscriberInfo.globalSubscriberId = payload.globalSubscriberId + subscriberInfo.subscriberName = payload.subscriberName + return subscriberInfo + } + + private fun generateRelatedInstanceListForVrfEntry(vrfEntries: MutableMap): List { + //fe send map of vrfs, with maps of networks and vpns, but actually we expect to only one vpn and one network + return if (vrfEntries.isEmpty() || vrfEntries.values.first().vpns.isEmpty() || vrfEntries.values.first().networks.isEmpty()) emptyList() + else { + val vpn = vrfEntries.values.first().vpns.values.first() + val network = vrfEntries.values.first().networks.values.first() + listOf(vpn, network).map { RelatedInstance(it.modelInfo, it.instanceId, it.instanceName) } + } + } +} diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/MsoResultHandlerService.kt b/vid-app-common/src/main/java/org/onap/vid/job/command/MsoResultHandlerService.kt index e1e9b1397..50eada64f 100644 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/MsoResultHandlerService.kt +++ b/vid-app-common/src/main/java/org/onap/vid/job/command/MsoResultHandlerService.kt @@ -7,9 +7,9 @@ * 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. @@ -44,43 +44,42 @@ class MsoResultHandlerService return jobSharedData.request as ServiceInstantiation } - fun handleRootResponse(jobUUID: UUID, msoResponse: RestObject): MsoResult { + fun handleRootResponse(sharedData: JobSharedData, msoResponse: RestObject): MsoResult { + val jobUUID:UUID = sharedData.jobUuid return if (msoResponse.statusCode in 200..399) { val jobStatus = Job.JobStatus.IN_PROGRESS val msoResourceIds = MsoResourceIds(msoResponse.get().requestReferences.requestId, msoResponse.get().requestReferences.instanceId) - asyncInstantiationBL.auditVidStatus(jobUUID, jobStatus) + auditService.auditVidStatus(jobUUID, jobStatus) setInitialRequestAuditStatusFromMso(jobUUID, msoResourceIds.requestId) asyncInstantiationBL.updateServiceInfo(jobUUID) { x -> x.jobStatus = jobStatus x.serviceInstanceId = msoResourceIds.instanceId x.msoRequestId = UUID.fromString(msoResourceIds.requestId) } - MsoResult(jobStatus, msoResourceIds) + asyncInstantiationBL.addResourceInfo(sharedData, jobStatus, msoResourceIds.instanceId) + MsoResult(Job.JobStatus.COMPLETED_WITH_NO_ACTION, msoResourceIds) } else { auditService.setFailedAuditStatusFromMso(jobUUID, null, msoResponse.statusCode, msoResponse.raw) - handleRootCommandFailed(jobUUID) + asyncInstantiationBL.addFailedResourceInfo(sharedData, msoResponse) + return MsoResult(Job.JobStatus.FAILED) } } - fun handleResponse(msoResponse: RestObject, actionDescription: String): MsoResult { + fun handleResponse(sharedData: JobSharedData, msoResponse: RestObject, actionDescription: String): MsoResult { return if (msoResponse.statusCode in 200..399) { val msoResourceIds = MsoResourceIds(msoResponse.get().requestReferences.requestId, msoResponse.get().requestReferences.instanceId) LOGGER.debug("Successfully sent $actionDescription. Request id: ${msoResourceIds.requestId}") + asyncInstantiationBL.addResourceInfo(sharedData, Job.JobStatus.IN_PROGRESS, msoResourceIds.instanceId) MsoResult(Job.JobStatus.COMPLETED_WITH_NO_ACTION, msoResourceIds) } else { LOGGER.debug("Failed to $actionDescription. Details: ${msoResponse.raw}") + asyncInstantiationBL.addFailedResourceInfo(sharedData, msoResponse) MsoResult(Job.JobStatus.FAILED) } } - - fun handleRootCommandFailed(jobUUID: UUID): MsoResult { - asyncInstantiationBL.handleFailedInstantiation(jobUUID) - return MsoResult(Job.JobStatus.FAILED) - } - private fun setInitialRequestAuditStatusFromMso(jobUUID: UUID, requestId: String) { val initialMsoRequestStatus = "REQUESTED" - asyncInstantiationBL.auditMsoStatus(jobUUID, initialMsoRequestStatus, requestId, null) + auditService.auditMsoStatus(jobUUID, initialMsoRequestStatus, requestId, null) } } diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/NetworkCommand.kt b/vid-app-common/src/main/java/org/onap/vid/job/command/NetworkCommand.kt new file mode 100644 index 000000000..bc4de7ccd --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/job/command/NetworkCommand.kt @@ -0,0 +1,65 @@ +package org.onap.vid.job.command + +import org.onap.vid.job.Job +import org.onap.vid.job.JobAdapter +import org.onap.vid.job.JobCommand +import org.onap.vid.job.JobsBrokerService +import org.onap.vid.model.Action +import org.onap.vid.model.serviceInstantiation.Network +import org.onap.vid.mso.RestMsoImplementation +import org.onap.vid.services.AsyncInstantiationBusinessLogic +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.beans.factory.config.ConfigurableBeanFactory +import org.springframework.context.annotation.Scope +import org.springframework.http.HttpMethod +import org.springframework.stereotype.Component +import java.util.* + + +@Component +@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) +class NetworkCommand @Autowired constructor( + private val asyncInstantiationBL: AsyncInstantiationBusinessLogic, + restMso: RestMsoImplementation, + private val msoRequestBuilder: MsoRequestBuilder, + msoResultHandlerService: MsoResultHandlerService, + inProgressStatusService:InProgressStatusService, + watchChildrenJobsBL: WatchChildrenJobsBL, + jobsBrokerService: JobsBrokerService, + jobAdapter: JobAdapter + ) : ResourceCommand(restMso, inProgressStatusService, msoResultHandlerService, + watchChildrenJobsBL, jobsBrokerService, jobAdapter), JobCommand { + override fun createChildren(): Job.JobStatus { + return Job.JobStatus.COMPLETED_WITH_NO_ACTION + } + + override fun planCreateMyselfRestCall(commandParentData: CommandParentData, request: JobAdapter.AsyncJobRequest, userId: String, testApi: String?): MsoRestCallPlan { + val serviceInstanceId = commandParentData.getInstanceId(CommandParentData.CommandDataKey.SERVICE_INSTANCE_ID) + val serviceModelInfo = commandParentData.getModelInfo(CommandParentData.CommandDataKey.SERVICE_MODEL_INFO) + + val instantiatePath = asyncInstantiationBL.getNetworkInstantiationPath(serviceInstanceId) + val requestDetailsWrapper = msoRequestBuilder.generateNetworkInstantiationRequest( + request as Network, + serviceModelInfo, + serviceInstanceId, + userId, + testApi + ) + + val actionDescription = "create network in $serviceInstanceId" + + return MsoRestCallPlan(HttpMethod.POST, instantiatePath, Optional.of(requestDetailsWrapper), Optional.empty(), actionDescription) + } + + override fun planDeleteMyselfRestCall(commandParentData: CommandParentData, request: JobAdapter.AsyncJobRequest, userId: String): MsoRestCallPlan { + val serviceInstanceId = commandParentData.getInstanceId(CommandParentData.CommandDataKey.SERVICE_INSTANCE_ID) + val path = asyncInstantiationBL.getNetworkDeletePath(serviceInstanceId, getRequest().instanceId) + val requestDetailsWrapper = msoRequestBuilder.generateDeleteNetworkRequest(getRequest() as Network, userId) + return MsoRestCallPlan(HttpMethod.DELETE, path, Optional.of(requestDetailsWrapper), Optional.of(userId), + "delete network ${getRequest().instanceId} from service instance $serviceInstanceId") + } + + override fun isDescendantHasAction(phase: Action): Boolean { + return false + } +} \ No newline at end of file diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/NetworkInstantiationCommand.java b/vid-app-common/src/main/java/org/onap/vid/job/command/NetworkInstantiationCommand.java deleted file mode 100644 index 2b7f79c15..000000000 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/NetworkInstantiationCommand.java +++ /dev/null @@ -1,61 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * VID - * ================================================================================ - * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * 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.vid.job.command; - -import org.onap.vid.changeManagement.RequestDetailsWrapper; -import org.onap.vid.job.JobAdapter; -import org.onap.vid.job.command.CommandParentData.CommandDataKey; -import org.onap.vid.model.serviceInstantiation.Network; -import org.onap.vid.mso.model.NetworkInstantiationRequestDetails; -import org.onap.vid.services.AsyncInstantiationBusinessLogic; -import org.springframework.beans.factory.config.ConfigurableBeanFactory; -import org.springframework.context.annotation.Scope; -import org.springframework.stereotype.Component; - -import javax.inject.Inject; - -@Component -@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) -public class NetworkInstantiationCommand extends ResourceInstantiationCommand { - - @Inject - private AsyncInstantiationBusinessLogic asyncInstantiationBL; - - @Override - protected String getRequestPath() { - return asyncInstantiationBL.getNetworkInstantiationPath(commandParentData.getInstanceId(CommandDataKey.SERVICE_INSTANCE_ID)); - } - - @Override - protected RequestDetailsWrapper generateMSORequest(JobAdapter.AsyncJobRequest request, String userId) { - return asyncInstantiationBL.generateNetworkInstantiationRequest( - (Network) getSharedData().getRequest(), - commandParentData.getModelInfo(CommandDataKey.SERVICE_MODEL_INFO), - commandParentData.getInstanceId(CommandDataKey.SERVICE_INSTANCE_ID), - getSharedData().getUserId() - ); - } - - @Override - protected String getJobAuditMSOStatus() { - return "NETWORK_REQUESTED"; - } -} diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/NoOpCommand.java b/vid-app-common/src/main/java/org/onap/vid/job/command/NoOpCommand.java index 9be37bbf2..4cc54e5d7 100644 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/NoOpCommand.java +++ b/vid-app-common/src/main/java/org/onap/vid/job/command/NoOpCommand.java @@ -7,9 +7,9 @@ * 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. diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/ResourceCommand.kt b/vid-app-common/src/main/java/org/onap/vid/job/command/ResourceCommand.kt index 7f3a05be8..0e9ab7b7a 100644 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/ResourceCommand.kt +++ b/vid-app-common/src/main/java/org/onap/vid/job/command/ResourceCommand.kt @@ -7,9 +7,9 @@ * 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. @@ -20,14 +20,14 @@ package org.onap.vid.job.command + import com.fasterxml.jackson.module.kotlin.convertValue import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate import org.onap.vid.changeManagement.RequestDetailsWrapper -import org.onap.vid.job.Job +import org.onap.vid.exceptions.AbortingException +import org.onap.vid.exceptions.TryAgainException +import org.onap.vid.job.* import org.onap.vid.job.Job.JobStatus -import org.onap.vid.job.JobAdapter -import org.onap.vid.job.JobCommand -import org.onap.vid.job.NextCommand import org.onap.vid.job.impl.JobSharedData import org.onap.vid.model.Action import org.onap.vid.model.RequestReferencesContainer @@ -38,6 +38,7 @@ import org.onap.vid.utils.getEnumFromMapOfStrings import org.springframework.http.HttpMethod import java.util.* + const val INTERNAL_STATE = "internalState" const val ACTION_PHASE = "actionPhase" const val CHILD_JOBS = "childJobs" @@ -51,7 +52,9 @@ enum class InternalState constructor(val immediate:Boolean=false) { DELETE_MYSELF, CREATE_MYSELF, IN_PROGRESS, - TERMINAL + TERMINAL, + RESUME_MYSELF, + REPLACE_MYSELF, } data class NextInternalState(val nextActionPhase: Action, val nextInternalState: InternalState) @@ -69,8 +72,10 @@ abstract class ResourceCommand( protected val restMso: RestMsoImplementation, protected val inProgressStatusService: InProgressStatusService, protected val msoResultHandlerService: MsoResultHandlerService, - protected val watchChildrenJobsBL: WatchChildrenJobsBL -) : CommandBase(), JobCommand { + protected val watchChildrenJobsBL: WatchChildrenJobsBL, + private val jobsBrokerService: JobsBrokerService, + private val jobAdapter: JobAdapter + ) : CommandBase(), JobCommand { companion object { private val Logger = EELFLoggerDelegate.getLogger(ResourceCommand::class.java) @@ -78,7 +83,7 @@ abstract class ResourceCommand( abstract fun createChildren():JobStatus - abstract fun planCreateMyselfRestCall(commandParentData: CommandParentData, request: JobAdapter.AsyncJobRequest, userId: String): MsoRestCallPlan + abstract fun planCreateMyselfRestCall(commandParentData: CommandParentData, request: JobAdapter.AsyncJobRequest, userId: String, testApi: String?): MsoRestCallPlan abstract fun planDeleteMyselfRestCall(commandParentData: CommandParentData, request: JobAdapter.AsyncJobRequest, userId: String): MsoRestCallPlan @@ -86,23 +91,28 @@ abstract class ResourceCommand( Pair(InternalState.CREATING_CHILDREN, ::createChildren), Pair(InternalState.WATCHING, ::watchChildren), Pair(InternalState.CREATE_MYSELF, ::createMyself), + Pair(InternalState.RESUME_MYSELF, ::resumeMyself), Pair(InternalState.DELETE_MYSELF, ::deleteMyself), - Pair(InternalState.IN_PROGRESS, ::inProgress) + Pair(InternalState.IN_PROGRESS, ::inProgress), + Pair(InternalState.REPLACE_MYSELF, ::replaceMyself) ) private lateinit var internalState:InternalState protected lateinit var actionPhase: Action - private var commandParentData: CommandParentData = CommandParentData() - private var msoResourceIds: MsoResourceIds = EMPTY_MSO_RESOURCE_ID + protected var commandParentData: CommandParentData = CommandParentData() + protected var msoResourceIds: MsoResourceIds = EMPTY_MSO_RESOURCE_ID protected var childJobs:List = emptyList() private lateinit var cumulativeStatus:JobStatus override fun call(): NextCommand { - var jobStatus:JobStatus = invokeCommand() + var jobStatus:JobStatus = if (internalState!=InternalState.TERMINAL) invokeCommand() else cumulativeStatus jobStatus = comulateStatusAndUpdatePropertyIfFinal(jobStatus) - Logger.debug("command for job ${sharedData.jobUuid} invoked and finished with jobStatus $jobStatus") + try { + Logger.debug("job: ${this.javaClass.simpleName} ${sharedData.jobUuid} $actionPhase ${getActionType()} $internalState $jobStatus $childJobs") + } catch (e:Exception) { /* do nothing. Just failed to log...*/} + if (shallStopJob(jobStatus)) { onFinal(jobStatus) return NextCommand(jobStatus) @@ -133,7 +143,17 @@ abstract class ResourceCommand( protected open fun getExternalInProgressStatus() = JobStatus.RESOURCE_IN_PROGRESS private fun invokeCommand(): JobStatus { - return commandByInternalState.getOrDefault (internalState, ::throwIllegalState).invoke() + return try { + commandByInternalState.getOrDefault(internalState, ::throwIllegalState).invoke() + } + catch (exception: TryAgainException) { + Logger.warn("caught TryAgainException. Set job status to IN_PROGRESS") + JobStatus.IN_PROGRESS + } + catch (exception: AbortingException) { + Logger.error("caught AbortingException. Set job status to FAILED") + JobStatus.FAILED; + } } private fun throwIllegalState():JobStatus { @@ -177,7 +197,7 @@ abstract class ResourceCommand( InternalState.DELETE_MYSELF -> InternalState.IN_PROGRESS InternalState.IN_PROGRESS -> { - if (jobStatus == Job.JobStatus.COMPLETED) InternalState.TERMINAL else InternalState.IN_PROGRESS + if (jobStatus == JobStatus.COMPLETED) InternalState.TERMINAL else InternalState.IN_PROGRESS } else -> InternalState.TERMINAL @@ -187,10 +207,28 @@ abstract class ResourceCommand( protected fun calcNextStateCreatePhase(jobStatus: JobStatus, internalState: InternalState): InternalState { return when (internalState) { - InternalState.CREATE_MYSELF -> InternalState.IN_PROGRESS + InternalState.CREATE_MYSELF -> when (jobStatus) { + JobStatus.IN_PROGRESS -> InternalState.CREATE_MYSELF + else -> InternalState.IN_PROGRESS + } + + InternalState.RESUME_MYSELF -> when (jobStatus) { + JobStatus.IN_PROGRESS -> InternalState.RESUME_MYSELF + else -> InternalState.IN_PROGRESS + } + + InternalState.REPLACE_MYSELF -> when (jobStatus) { + JobStatus.IN_PROGRESS -> InternalState.REPLACE_MYSELF + else -> InternalState.IN_PROGRESS + } InternalState.IN_PROGRESS -> { - if (jobStatus == Job.JobStatus.COMPLETED) InternalState.CREATING_CHILDREN else InternalState.IN_PROGRESS + when { + jobStatus != JobStatus.COMPLETED -> InternalState.IN_PROGRESS + isDescendantHasAction(Action.Create) -> InternalState.CREATING_CHILDREN + isDescendantHasAction(Action.Replace) -> InternalState.CREATING_CHILDREN + else -> InternalState.TERMINAL + } } InternalState.CREATING_CHILDREN -> InternalState.WATCHING @@ -202,7 +240,6 @@ abstract class ResourceCommand( } } - else -> InternalState.TERMINAL } } @@ -214,7 +251,7 @@ abstract class ResourceCommand( MSO_RESOURCE_ID to msoResourceIds, CHILD_JOBS to childJobs, CUMULATIVE_STATUS to cumulativeStatus - ) + ) + commandParentData.parentData } override fun init(sharedData: JobSharedData, commandData: Map): ResourceCommand { @@ -232,13 +269,24 @@ abstract class ResourceCommand( return this } - private fun calcInitialState(commandData: Map, phase: Action):InternalState { + fun calcInitialState(commandData: Map, phase: Action):InternalState { val status:InternalState = getEnumFromMapOfStrings(commandData, INTERNAL_STATE, InternalState.INITIAL) if (status == InternalState.INITIAL) { onInitial(phase) return when (phase) { - Action.Delete -> InternalState.CREATING_CHILDREN - Action.Create -> if (isNeedToCreateMyself()) InternalState.CREATE_MYSELF else InternalState.CREATING_CHILDREN + Action.Delete -> when { + isDescendantHasAction(phase) -> InternalState.CREATING_CHILDREN + isNeedToDeleteMyself() -> InternalState.DELETE_MYSELF + else -> InternalState.TERMINAL + } + Action.Create -> when { + isNeedToCreateMyself() -> InternalState.CREATE_MYSELF + isNeedToResumeMySelf() -> InternalState.RESUME_MYSELF + isNeedToReplaceMySelf() -> InternalState.REPLACE_MYSELF + isDescendantHasAction(phase) -> InternalState.CREATING_CHILDREN + isDescendantHasAction(Action.Replace) -> InternalState.CREATING_CHILDREN + else -> InternalState.TERMINAL + } else -> throw IllegalStateException("state $internalState is not supported yet") } } @@ -269,7 +317,11 @@ abstract class ResourceCommand( protected open fun isNeedToCreateMyself(): Boolean = getActionType() == Action.Create - protected open fun inProgress(): Job.JobStatus { + protected open fun isNeedToResumeMySelf(): Boolean = getActionType() == Action.Resume + + protected open fun isNeedToReplaceMySelf(): Boolean = false + + protected open fun inProgress(): JobStatus { val requestId:String = msoResourceIds.requestId; return try { val jobStatus = inProgressStatusService.call(getExpiryChecker(), sharedData, requestId) @@ -277,29 +329,35 @@ abstract class ResourceCommand( } catch (e: javax.ws.rs.ProcessingException) { // Retry when we can't connect MSO during getStatus Logger.error(EELFLoggerDelegate.errorLogger, "Cannot get orchestration status for {}, will retry: {}", requestId, e, e) - Job.JobStatus.IN_PROGRESS; + JobStatus.IN_PROGRESS; } catch (e: InProgressStatusService.BadResponseFromMso) { inProgressStatusService.handleFailedMsoResponse(sharedData.jobUuid, requestId, e.msoResponse) - Job.JobStatus.IN_PROGRESS + JobStatus.IN_PROGRESS } catch (e: RuntimeException) { Logger.error(EELFLoggerDelegate.errorLogger, "Cannot get orchestration status for {}, stopping: {}", requestId, e, e) - Job.JobStatus.STOPPED + JobStatus.STOPPED } } - fun createMyself(): Job.JobStatus { - val createMyselfCommand = planCreateMyselfRestCall(commandParentData, sharedData.request, sharedData.userId) - + fun createMyself(): JobStatus { + val createMyselfCommand = planCreateMyselfRestCall(commandParentData, sharedData.request, sharedData.userId, sharedData.testApi) return executeAndHandleMsoInstanceRequest(createMyselfCommand) } - fun deleteMyself(): Job.JobStatus { - val deleteMyselfCommand = planDeleteMyselfRestCall(commandParentData, sharedData.request, sharedData.userId) + protected open fun resumeMyself(): JobStatus { + throw NotImplementedError("Resume is not implemented for this command " + this.javaClass) + } + + protected open fun replaceMyself(): JobStatus { + throw NotImplementedError("Replace is not implemented for this command " + this.javaClass) + } + fun deleteMyself(): JobStatus { + val deleteMyselfCommand = planDeleteMyselfRestCall(commandParentData, sharedData.request, sharedData.userId) return executeAndHandleMsoInstanceRequest(deleteMyselfCommand) } - private fun executeAndHandleMsoInstanceRequest(restCallPlan: MsoRestCallPlan): JobStatus { + protected fun executeAndHandleMsoInstanceRequest(restCallPlan: MsoRestCallPlan): JobStatus { val msoResponse = restMso.restCall( restCallPlan.httpMethod, RequestReferencesContainer::class.java, @@ -309,9 +367,9 @@ abstract class ResourceCommand( ) val msoResult = if (isServiceCommand()) { - msoResultHandlerService.handleRootResponse(sharedData.jobUuid, msoResponse) + msoResultHandlerService.handleRootResponse(sharedData, msoResponse) } else { - msoResultHandlerService.handleResponse(msoResponse, restCallPlan.actionDescription) + msoResultHandlerService.handleResponse(sharedData, msoResponse, restCallPlan.actionDescription) } this.msoResourceIds = msoResult.msoResourceIds @@ -321,14 +379,14 @@ abstract class ResourceCommand( protected open fun getExpiryChecker(): ExpiryChecker = ExpiryChecker {false} protected open fun handleInProgressStatus(jobStatus: JobStatus): JobStatus { - return if (jobStatus == Job.JobStatus.PAUSE) Job.JobStatus.IN_PROGRESS else jobStatus + return if (jobStatus == JobStatus.PAUSE) JobStatus.IN_PROGRESS else jobStatus } protected open fun watchChildren():JobStatus { return watchChildrenJobsBL.retrieveChildrenJobsStatus(childJobs) } - private fun comulateStatusAndUpdatePropertyIfFinal(internalStateStatus: JobStatus): JobStatus { + protected fun comulateStatusAndUpdatePropertyIfFinal(internalStateStatus: JobStatus): JobStatus { val status = watchChildrenJobsBL.cumulateJobStatus(internalStateStatus, cumulativeStatus) //we want to update cumulativeStatus only for final status @@ -338,6 +396,44 @@ abstract class ResourceCommand( return status } + + protected fun buildDataForChild(request: BaseResource, actionPhase: Action): Map { + addMyselfToChildrenData(commandParentData, request) + commandParentData.setActionPhase(actionPhase) + return commandParentData.parentData + } + + protected open fun addMyselfToChildrenData(commandParentData: CommandParentData, request: BaseResource) { + // Nothing by default + } + + protected open fun isDescendantHasAction(phase:Action):Boolean = isDescendantHasAction(getRequest(), phase, true ) + + + @JvmOverloads + fun isDescendantHasAction(request: BaseResource, phase: Action, isFirstLevel:Boolean=true): Boolean { + if (!isFirstLevel && request.action == phase) { + return true; + } + + return request.children.map {this.isDescendantHasAction(it, phase, false)}.any {it} + } + + protected fun getActualInstanceId(request: BaseResource):String = + if (getActionType() == Action.Create) msoResourceIds.instanceId else request.instanceId + + + protected fun pushChildrenJobsToBroker(children:Collection, + dataForChild: Map, + jobType: JobType?=null): List { + var counter = 0; + return children + .map {Pair(it, counter++)} + .map { jobAdapter.createChildJob(jobType ?: it.first.jobType, it.first, sharedData, dataForChild, it.second) } + .map { jobsBrokerService.add(it) } + .map { it.toString() } + } + } diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/ResourceInstantiationCommand.java b/vid-app-common/src/main/java/org/onap/vid/job/command/ResourceInstantiationCommand.java deleted file mode 100644 index 98980a35d..000000000 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/ResourceInstantiationCommand.java +++ /dev/null @@ -1,107 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * VID - * ================================================================================ - * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * 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.vid.job.command; - -import org.onap.vid.changeManagement.RequestDetailsWrapper; -import org.onap.vid.job.Job; -import org.onap.vid.job.JobAdapter; -import org.onap.vid.job.JobCommand; -import org.onap.vid.job.NextCommand; -import org.onap.vid.job.impl.JobSharedData; -import org.onap.vid.model.RequestReferencesContainer; -import org.onap.vid.mso.RestMsoImplementation; -import org.onap.vid.mso.RestObject; -import org.onap.vid.mso.model.BaseResourceInstantiationRequestDetails; -import org.onap.vid.services.AsyncInstantiationBusinessLogic; -import org.onap.vid.services.AuditService; -import org.springframework.beans.factory.config.ConfigurableBeanFactory; -import org.springframework.context.annotation.Scope; -import org.springframework.stereotype.Component; - -import javax.inject.Inject; -import java.util.Map; - - -@Component -@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) -public abstract class ResourceInstantiationCommand extends BaseInstantiationCommand implements JobCommand { - - - @Inject - protected RestMsoImplementation restMso; - - @Inject - private AsyncInstantiationBusinessLogic asyncInstantiationBL; - - @Inject - private AuditService auditService; - - @Override - public ResourceInstantiationCommand init(JobSharedData sharedData, Map commandData) { - super.init(sharedData, commandData); - return this; - } - - @Override - public Map getData() { - return commandParentData.getParentData(); - } - - @Override - public NextCommand call() { - if (!shouldInstantiateMyself()) { - return new NextCommand(Job.JobStatus.COMPLETED_WITH_NO_ACTION); - } - - RequestDetailsWrapper requestDetailsWrapper = generateMSORequest( - getSharedData().getRequest(), - getSharedData().getUserId() - ); - String instantiatePath = getRequestPath(); - - RestObject msoResponse = restMso.PostForObject(requestDetailsWrapper, - instantiatePath, RequestReferencesContainer.class); - - if (msoResponse.getStatusCode() >= 200 && msoResponse.getStatusCode() < 400) { - String requestId = msoResponse.get().getRequestReferences().getRequestId(); - String instanceId = msoResponse.get().getRequestReferences().getInstanceId(); - asyncInstantiationBL.auditMsoStatus(getSharedData().getRootJobId(), getJobAuditMSOStatus(), requestId, null); - return getNextCommand(requestId, instanceId); - } - else { - auditService.setFailedAuditStatusFromMso(getSharedData().getRootJobId(), null, msoResponse.getStatusCode(), msoResponse.getRaw()); - return new NextCommand(Job.JobStatus.FAILED); - } - } - protected NextCommand getNextCommand(String requestId, String instanceId){ - return new NextCommand(Job.JobStatus.RESOURCE_IN_PROGRESS, new ResourceInProgressStatusCommand(getSharedData(), requestId, instanceId)); - } - - protected boolean shouldInstantiateMyself() { - return true; - } - - protected abstract String getRequestPath(); - protected abstract RequestDetailsWrapper generateMSORequest(JobAdapter.AsyncJobRequest request, String userId); - protected abstract String getJobAuditMSOStatus(); -} - - diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/ResourceWithChildrenInProgressCommand.java b/vid-app-common/src/main/java/org/onap/vid/job/command/ResourceWithChildrenInProgressCommand.java deleted file mode 100644 index 0a345c52c..000000000 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/ResourceWithChildrenInProgressCommand.java +++ /dev/null @@ -1,85 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * VID - * ================================================================================ - * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * 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.vid.job.command; - -import org.onap.vid.job.Job; -import org.onap.vid.job.NextCommand; -import org.onap.vid.job.impl.JobSharedData; - -import java.util.HashMap; -import java.util.Map; - - -public class ResourceWithChildrenInProgressCommand extends BaseInProgressStatusCommand { - - public ResourceWithChildrenInProgressCommand() { - } - - public ResourceWithChildrenInProgressCommand(JobSharedData sharedData, - String requestId, - String instanceId, - CommandParentData commandParentData) { - init(sharedData, requestId, instanceId, commandParentData); - } - - protected BaseInProgressStatusCommand init(JobSharedData sharedData, - String requestId, - String instanceId, - CommandParentData commandParentData) { - init(sharedData, requestId, instanceId); - this.commandParentData= commandParentData; - return this; - } - - - @Override - public Map getData() { - Map data = new HashMap<>(super.getData()); - data.putAll(buildDataForChild()); - return data; - } - - @Override - public BaseInProgressStatusCommand init(JobSharedData sharedData, Map commandData) { - return init( - sharedData, - (String) commandData.get("requestId"), - (String) commandData.get("instanceId"), - commandParentData.initParentData(commandData)); - } - - protected Map buildDataForChild() { - return commandParentData.getParentData(); - } - - - - @Override - protected NextCommand processJobStatus(Job.JobStatus jobStatus) { - return new NextCommand(jobStatus, this); - } - - @Override - protected ExpiryChecker getExpiryChecker() { - return x->false; - } - -} diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/RootServiceCommand.kt b/vid-app-common/src/main/java/org/onap/vid/job/command/RootServiceCommand.kt new file mode 100644 index 000000000..c4680b2bd --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/job/command/RootServiceCommand.kt @@ -0,0 +1,98 @@ +package org.onap.vid.job.command + +import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate +import org.onap.vid.job.Job +import org.onap.vid.job.JobAdapter +import org.onap.vid.job.JobCommand +import org.onap.vid.job.JobsBrokerService +import org.onap.vid.job.impl.JobSharedData +import org.onap.vid.model.Action +import org.onap.vid.model.serviceInstantiation.ServiceInstantiation +import org.onap.vid.mso.RestMsoImplementation +import org.onap.vid.services.AsyncInstantiationBusinessLogic +import org.onap.vid.services.AuditService +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.http.HttpMethod +import java.util.* + +abstract class RootServiceCommand @Autowired constructor( + restMso: RestMsoImplementation, + inProgressStatusService: InProgressStatusService, + msoResultHandlerService: MsoResultHandlerService, + watchChildrenJobsBL: WatchChildrenJobsBL, + jobsBrokerService: JobsBrokerService, + jobAdapter: JobAdapter, + private val asyncInstantiationBL: AsyncInstantiationBusinessLogic, + private val auditService: AuditService, + private val msoRequestBuilder: MsoRequestBuilder +) : ResourceCommand(restMso, inProgressStatusService, msoResultHandlerService, + watchChildrenJobsBL, jobsBrokerService, jobAdapter), JobCommand { + + lateinit var optimisticUniqueServiceInstanceName: String + + companion object { + private val LOGGER = EELFLoggerDelegate.getLogger(RootServiceCommand::class.java) + } + + final override fun onInitial(phase: Action) { + if (phase== Action.Delete) { + asyncInstantiationBL.updateServiceInfoAndAuditStatus(sharedData.jobUuid, Job.JobStatus.IN_PROGRESS) + } + } + + final override fun getExternalInProgressStatus() = Job.JobStatus.IN_PROGRESS + + final override fun getData(): Map { + return super.getData() + mapOf(UNIQUE_INSTANCE_NAME to optimisticUniqueServiceInstanceName) + } + + final override fun onFinal(jobStatus: Job.JobStatus) { + asyncInstantiationBL.updateServiceInfoAndAuditStatus(sharedData.jobUuid, jobStatus) + if (jobStatus.isFailure) { + asyncInstantiationBL.handleFailedInstantiation(sharedData.jobUuid) + } + } + + final override fun init(sharedData: JobSharedData, commandData: Map): ResourceCommand { + optimisticUniqueServiceInstanceName = commandData.getOrDefault(UNIQUE_INSTANCE_NAME, "") as String + return super.init(sharedData, commandData) + } + + final override fun isServiceCommand(): Boolean = true + + final override fun getExpiryChecker(): ExpiryChecker { + return ServiceExpiryChecker() + } + + override fun resumeMyself(): Job.JobStatus { + val requestType = "createInstance" + val scope = "service" + val serviceInstanceId = getActualInstanceId(getRequest()) + try { + val requests = auditService.retrieveRequestsFromMsoByServiceIdAndRequestTypeAndScope(serviceInstanceId, requestType, scope) + if (requests.isEmpty() || requests[0].requestId == null) { + LOGGER.error("Failed to retrieve requestId with type: $type, scope: $scope for service instanceId $serviceInstanceId ") + return Job.JobStatus.FAILED + } + val createMyselfCommand = planResumeMyselfRestCall(requests[0].requestId, sharedData.userId) + return executeAndHandleMsoInstanceRequest(createMyselfCommand) + } catch (exception: Exception) { + LOGGER.error("Failed to resume instanceId $serviceInstanceId ", exception) + return Job.JobStatus.FAILED + } + } + + private fun planResumeMyselfRestCall(requestId: String, userId: String): MsoRestCallPlan { + val path = asyncInstantiationBL.getResumeRequestPath(requestId) + return MsoRestCallPlan(HttpMethod.POST, path, Optional.empty(), Optional.of(userId), "resume request $requestId") + } + + override fun planDeleteMyselfRestCall(commandParentData: CommandParentData, request: JobAdapter.AsyncJobRequest, userId: String): MsoRestCallPlan { + val requestDetailsWrapper = msoRequestBuilder.generateServiceDeletionRequest( + request as ServiceInstantiation, userId + ) + val path = asyncInstantiationBL.getServiceDeletionPath(request.instanceId) + return MsoRestCallPlan(HttpMethod.DELETE, path, Optional.of(requestDetailsWrapper), Optional.empty(), + "delete instance with id ${request.instanceId}") + } +} \ No newline at end of file diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/ServiceInProgressStatusCommand.java b/vid-app-common/src/main/java/org/onap/vid/job/command/ServiceInProgressStatusCommand.java deleted file mode 100644 index 6fd22132f..000000000 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/ServiceInProgressStatusCommand.java +++ /dev/null @@ -1,120 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * VID - * ================================================================================ - * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * 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.vid.job.command; - -import org.apache.commons.collections.MapUtils; -import org.onap.vid.job.Job; -import org.onap.vid.job.Job.JobStatus; -import org.onap.vid.job.JobCommand; -import org.onap.vid.job.JobType; -import org.onap.vid.job.NextCommand; -import org.onap.vid.job.command.CommandParentData.CommandDataKey; -import org.onap.vid.job.impl.JobSharedData; -import org.onap.vid.model.serviceInstantiation.ServiceInstantiation; -import org.onap.vid.properties.Features; -import org.springframework.beans.factory.config.ConfigurableBeanFactory; -import org.springframework.context.annotation.Scope; -import org.springframework.stereotype.Component; - -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -@Component -@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) -public class ServiceInProgressStatusCommand extends BaseInProgressStatusCommand { - - public ServiceInProgressStatusCommand() { - } - - ServiceInProgressStatusCommand(JobSharedData sharedData, MsoResourceIds msoResourceIds) { - init(sharedData, msoResourceIds.getRequestId(), msoResourceIds.getInstanceId()); - } - - @Override - protected ExpiryChecker getExpiryChecker() { - return new ServiceExpiryChecker(); - } - - protected NextCommand processJobStatus(Job.JobStatus jobStatus) { - JobCommand jobCommand = this; - Job.JobStatus nextJobStatus = jobStatus; - switch (jobStatus) { - case FAILED: - asyncInstantiationBL.handleFailedInstantiation(getSharedData().getJobUuid()); - return new NextCommand(nextJobStatus, jobCommand); - case PAUSE: - nextJobStatus = Job.JobStatus.IN_PROGRESS; - break; - case COMPLETED: - ServiceInstantiation request = (ServiceInstantiation) getSharedData().getRequest(); - if (isNeedToCreateChildJobs(request)) { - List childrenJobs = getChildJobs(request); - nextJobStatus = Job.JobStatus.IN_PROGRESS; - jobCommand = new WatchingCommand(getSharedData(), childrenJobs, true); - return new NextCommand(nextJobStatus, jobCommand); - } - break; - default: // for sonar - } - asyncInstantiationBL.updateServiceInfoAndAuditStatus(getSharedData().getJobUuid(), jobStatus); - return new NextCommand(nextJobStatus, jobCommand); - } - - private List getChildJobs(ServiceInstantiation request) { - Map dataForChild = buildDataForChild(request); - - Stream vnfJobs = request.getVnfs().values().stream().map( - vnf -> jobsBrokerService.add( - jobAdapter.createChildJob(JobType.VnfInstantiation, JobStatus.CREATING , vnf, getSharedData(), dataForChild)).toString() - ); - - Stream networkJobs = request.getNetworks().values().stream().map( - network -> jobsBrokerService.add( - jobAdapter.createChildJob(JobType.NetworkInstantiation, JobStatus.CREATING , network, getSharedData(), dataForChild)).toString() - ); - - Stream instanceGroupJobs = request.getVnfGroups().values().stream().map( - instanceGroup -> jobsBrokerService.add( - jobAdapter.createChildJob(JobType.InstanceGroupInstantiation, JobStatus.CREATING , instanceGroup, getSharedData(), dataForChild)).toString() - ); - - return Stream.of(vnfJobs, networkJobs, instanceGroupJobs) - .reduce(Stream::concat) - .orElseGet(Stream::empty) - .collect(Collectors.toList()); - } - - public boolean isNeedToCreateChildJobs(ServiceInstantiation request) { - return featureManager.isActive(Features.FLAG_ASYNC_ALACARTE_VNF) && request.isALaCarte() && - ( - MapUtils.isNotEmpty(request.getVnfs()) || MapUtils.isNotEmpty(request.getNetworks()) || - (featureManager.isActive(Features.FLAG_1902_VNF_GROUPING) && MapUtils.isNotEmpty(request.getVnfGroups())) - ); - } - - protected Map buildDataForChild(ServiceInstantiation request) { - commandParentData.addInstanceId(CommandDataKey.SERVICE_INSTANCE_ID, this.instanceId); - commandParentData.addModelInfo(CommandDataKey.SERVICE_MODEL_INFO, request.getModelInfo()); - return commandParentData.getParentData(); - } -} diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/ServiceInstantiationCommand.java b/vid-app-common/src/main/java/org/onap/vid/job/command/ServiceInstantiationCommand.java deleted file mode 100644 index 414379b0d..000000000 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/ServiceInstantiationCommand.java +++ /dev/null @@ -1,126 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * VID - * ================================================================================ - * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * 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.vid.job.command; - -import com.google.common.collect.ImmutableMap; -import org.apache.commons.lang3.ObjectUtils; -import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; -import org.onap.vid.aai.ExceptionWithRequestInfo; -import org.onap.vid.changeManagement.RequestDetailsWrapper; -import org.onap.vid.exceptions.MaxRetriesException; -import org.onap.vid.job.Job; -import org.onap.vid.job.JobCommand; -import org.onap.vid.job.NextCommand; -import org.onap.vid.job.impl.JobSharedData; -import org.onap.vid.model.RequestReferencesContainer; -import org.onap.vid.model.serviceInstantiation.ServiceInstantiation; -import org.onap.vid.mso.RestMsoImplementation; -import org.onap.vid.mso.RestObject; -import org.onap.vid.mso.model.ServiceInstantiationRequestDetails; -import org.onap.vid.services.AsyncInstantiationBusinessLogic; - -import javax.inject.Inject; -import java.util.Map; - - -public abstract class ServiceInstantiationCommand extends BaseRootCommand implements JobCommand { - - private static final EELFLoggerDelegate LOGGER = EELFLoggerDelegate.getLogger(ServiceInstantiationCommand.class); - - @Inject - protected AsyncInstantiationBusinessLogic asyncInstantiationBL; - - @Inject - private RestMsoImplementation restMso; - - protected String optimisticUniqueServiceInstanceName; - - public ServiceInstantiationCommand() { - } - - @Override - public NextCommand call() { - RequestDetailsWrapper requestDetailsWrapper ; - try { - requestDetailsWrapper = generateServiceInstantiationRequest(); - } - - //Aai return bad response while checking names uniqueness - catch (ExceptionWithRequestInfo exception) { - return handleAaiNameUniquenessBadResponse(exception); - } - - //Vid reached to max retries while trying to find unique name in AAI - catch (MaxRetriesException exception) { - return handleMaxRetryInNameUniqueness(exception); - } - - String path = asyncInstantiationBL.getServiceInstantiationPath(getRequest()); - - RestObject msoResponse = restMso.PostForObject(requestDetailsWrapper, - path, RequestReferencesContainer.class); - - return handleRootResponse(msoResponse); - - } - - @Override - protected ServiceInstantiation getRequest() { - return (ServiceInstantiation) getSharedData().getRequest(); - } - - protected abstract RequestDetailsWrapper generateServiceInstantiationRequest(); - - private NextCommand handleMaxRetryInNameUniqueness(MaxRetriesException exception) { - LOGGER.error("Failed to find unused name in AAI. Set the job to FAILED ", exception); - return handleCommandFailed(); - } - - private NextCommand handleAaiNameUniquenessBadResponse(ExceptionWithRequestInfo exception) { - LOGGER.error("Failed to check name uniqueness in AAI. VID will try again later", exception); - //put the job in_progress so we will keep trying to check name uniqueness in AAI - //And then send the request to MSO - return new NextCommand(Job.JobStatus.IN_PROGRESS, this); - } - - @Override - public ServiceInstantiationCommand init(JobSharedData sharedData, Map commandData) { - - return init( - sharedData, - (String) commandData.get("optimisticUniqueServiceInstanceName") - ); - } - - protected ServiceInstantiationCommand init(JobSharedData sharedData, String optimisticUniqueServiceInstanceName) { - init(sharedData); - this.optimisticUniqueServiceInstanceName = ObjectUtils.defaultIfNull(optimisticUniqueServiceInstanceName, - (getRequest()).getInstanceName()); - return this; - } - - @Override - public Map getData() { - return ImmutableMap.of( - "optimisticUniqueServiceInstanceName", optimisticUniqueServiceInstanceName - ); - } -} diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/VfmoduleCommand.kt b/vid-app-common/src/main/java/org/onap/vid/job/command/VfmoduleCommand.kt new file mode 100644 index 000000000..af52fa049 --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/job/command/VfmoduleCommand.kt @@ -0,0 +1,106 @@ +package org.onap.vid.job.command + +import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate +import org.onap.vid.job.Job +import org.onap.vid.job.JobAdapter +import org.onap.vid.job.JobCommand +import org.onap.vid.job.JobsBrokerService +import org.onap.vid.model.Action +import org.onap.vid.model.serviceInstantiation.VfModule +import org.onap.vid.mso.RestMsoImplementation +import org.onap.vid.services.AsyncInstantiationBusinessLogic +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.beans.factory.config.ConfigurableBeanFactory +import org.springframework.context.annotation.Scope +import org.springframework.http.HttpMethod +import org.springframework.stereotype.Component +import java.util.* + +@Component +@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) +class VfmoduleCommand @Autowired constructor( + private val asyncInstantiationBL: AsyncInstantiationBusinessLogic, + restMso: RestMsoImplementation, + private val msoRequestBuilder: MsoRequestBuilder, + msoResultHandlerService: MsoResultHandlerService, + inProgressStatusService:InProgressStatusService, + watchChildrenJobsBL: WatchChildrenJobsBL, + jobsBrokerService: JobsBrokerService, + jobAdapter: JobAdapter +) : ResourceCommand(restMso, inProgressStatusService, msoResultHandlerService, + watchChildrenJobsBL, jobsBrokerService, jobAdapter), JobCommand { + + companion object { + private val LOGGER = EELFLoggerDelegate.getLogger(VfmoduleCommand::class.java) + } + + override fun createChildren(): Job.JobStatus { + return Job.JobStatus.COMPLETED_WITH_NO_ACTION + } + + override fun planCreateMyselfRestCall(commandParentData: CommandParentData, request: JobAdapter.AsyncJobRequest, userId: String, testApi: String?): MsoRestCallPlan { + val serviceInstanceId = commandParentData.getInstanceId(CommandParentData.CommandDataKey.SERVICE_INSTANCE_ID) + val serviceModelInfo = commandParentData.getModelInfo(CommandParentData.CommandDataKey.SERVICE_MODEL_INFO) + val vnfModelInfo = commandParentData.getModelInfo(CommandParentData.CommandDataKey.VNF_MODEL_INFO) + val vnfInstanceId = commandParentData.getInstanceId(CommandParentData.CommandDataKey.VNF_INSTANCE_ID) + val vgInstaceId = commandParentData.getInstanceId(CommandParentData.CommandDataKey.VG_INSTANCE_ID) + + val instantiatePath = asyncInstantiationBL.getVfmoduleInstantiationPath(serviceInstanceId, vnfInstanceId) + + val requestDetailsWrapper = msoRequestBuilder.generateVfModuleInstantiationRequest( + request as VfModule, + serviceModelInfo, serviceInstanceId, vnfModelInfo, vnfInstanceId, vgInstaceId, userId, testApi) + + val actionDescription = "create vfmodule in $vnfInstanceId" + + return MsoRestCallPlan(HttpMethod.POST, instantiatePath, Optional.of(requestDetailsWrapper), Optional.empty(), actionDescription) + + } + + override fun planDeleteMyselfRestCall(commandParentData: CommandParentData, request: JobAdapter.AsyncJobRequest, userId: String): MsoRestCallPlan { + val serviceInstanceId = commandParentData.getInstanceId(CommandParentData.CommandDataKey.SERVICE_INSTANCE_ID) + val vnfInstanceId = commandParentData.getInstanceId(CommandParentData.CommandDataKey.VNF_INSTANCE_ID) + + val path = asyncInstantiationBL.getVfModuleDeletePath(serviceInstanceId, vnfInstanceId, getRequest().instanceId) + val requestDetailsWrapper = msoRequestBuilder.generateDeleteVfModuleRequest(getRequest(), userId) + return MsoRestCallPlan(HttpMethod.DELETE, path, Optional.of(requestDetailsWrapper), Optional.of(userId), + "delete vfmodule ${getRequest().instanceId} from service instance $serviceInstanceId and vnf $vnfInstanceId") + } + + override fun getRequest(): VfModule { + return sharedData.request as VfModule + } + + override fun isDescendantHasAction(phase: Action): Boolean { + return false + } + + private fun planReplaceMyselfRestCall(commandParentData: CommandParentData, request: JobAdapter.AsyncJobRequest, userId: String, testApi: String?): MsoRestCallPlan { + val serviceInstanceId = commandParentData.getInstanceId(CommandParentData.CommandDataKey.SERVICE_INSTANCE_ID) + val serviceModelInfo = commandParentData.getModelInfo(CommandParentData.CommandDataKey.SERVICE_MODEL_INFO) + val vnfModelInfo = commandParentData.getModelInfo(CommandParentData.CommandDataKey.VNF_MODEL_INFO) + val vnfInstanceId = commandParentData.getInstanceId(CommandParentData.CommandDataKey.VNF_INSTANCE_ID) + val replacePath = asyncInstantiationBL.getVfModuleReplacePath(serviceInstanceId, vnfInstanceId, getRequest().instanceId) + + val requestDetailsWrapper = msoRequestBuilder.generateVfModuleInstantiationRequest( + request as VfModule, serviceModelInfo, serviceInstanceId,vnfModelInfo, vnfInstanceId,null,userId, testApi) + + val actionDescription = "replace vfmodule ${request.instanceId}" + + return MsoRestCallPlan(HttpMethod.POST, replacePath, Optional.of(requestDetailsWrapper), Optional.of(userId), actionDescription) + } + + override fun replaceMyself(): Job.JobStatus { + try { + val replaceMyselfCommand = planReplaceMyselfRestCall(commandParentData, sharedData.request, sharedData.userId, sharedData.testApi ) + return executeAndHandleMsoInstanceRequest(replaceMyselfCommand) + } catch (exception: Exception) { + LOGGER.error("Failed to replace instanceId ${getRequest().instanceId} ", exception) + return Job.JobStatus.FAILED + } + } + + override fun isNeedToReplaceMySelf(): Boolean { + return getActionType() == Action.Replace + } +} diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/VfmoduleInstantiationCommand.java b/vid-app-common/src/main/java/org/onap/vid/job/command/VfmoduleInstantiationCommand.java deleted file mode 100644 index 75bf97f8d..000000000 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/VfmoduleInstantiationCommand.java +++ /dev/null @@ -1,64 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * VID - * ================================================================================ - * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * 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.vid.job.command; - -import org.onap.vid.changeManagement.RequestDetailsWrapper; -import org.onap.vid.job.JobAdapter; -import org.onap.vid.job.command.CommandParentData.CommandDataKey; -import org.onap.vid.model.serviceInstantiation.VfModule; -import org.onap.vid.mso.model.VfModuleInstantiationRequestDetails; -import org.onap.vid.services.AsyncInstantiationBusinessLogic; -import org.springframework.beans.factory.config.ConfigurableBeanFactory; -import org.springframework.context.annotation.Scope; -import org.springframework.stereotype.Component; - -import javax.inject.Inject; - -@Component -@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) -public class VfmoduleInstantiationCommand extends ResourceInstantiationCommand { - @Inject - private AsyncInstantiationBusinessLogic asyncInstantiationBL; - - @Override - protected String getRequestPath() { - return asyncInstantiationBL.getVfmoduleInstantiationPath(commandParentData.getInstanceId(CommandDataKey.SERVICE_INSTANCE_ID),commandParentData.getInstanceId(CommandDataKey.VNF_INSTANCE_ID)); - } - - @Override - protected RequestDetailsWrapper generateMSORequest(JobAdapter.AsyncJobRequest request, String userId) { - return asyncInstantiationBL.generateVfModuleInstantiationRequest( - (VfModule) getSharedData().getRequest(), - commandParentData.getModelInfo(CommandDataKey.SERVICE_MODEL_INFO), - commandParentData.getInstanceId(CommandDataKey.SERVICE_INSTANCE_ID), - commandParentData.getModelInfo(CommandDataKey.VNF_MODEL_INFO), - commandParentData.getInstanceId(CommandDataKey.VNF_INSTANCE_ID), - commandParentData.getInstanceId(CommandDataKey.VG_INSTANCE_ID), - getSharedData().getUserId() - ); - } - - @Override - protected String getJobAuditMSOStatus() { - return "VF_MODULE_REQUESTED"; - } - -} diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/VnfCommand.kt b/vid-app-common/src/main/java/org/onap/vid/job/command/VnfCommand.kt new file mode 100644 index 000000000..a89e196de --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/job/command/VnfCommand.kt @@ -0,0 +1,140 @@ +package org.onap.vid.job.command + +import org.apache.commons.collections.MapUtils +import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate +import org.onap.vid.asdc.AsdcCatalogException +import org.onap.vid.job.* +import org.onap.vid.job.impl.JobSharedData +import org.onap.vid.model.Action +import org.onap.vid.model.serviceInstantiation.BaseResource +import org.onap.vid.model.serviceInstantiation.VfModule +import org.onap.vid.model.serviceInstantiation.Vnf +import org.onap.vid.mso.RestMsoImplementation +import org.onap.vid.properties.Features +import org.onap.vid.services.AsyncInstantiationBusinessLogic +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.beans.factory.config.ConfigurableBeanFactory +import org.springframework.context.annotation.Scope +import org.springframework.http.HttpMethod +import org.springframework.stereotype.Component +import org.togglz.core.manager.FeatureManager +import java.util.* +import java.util.stream.Collectors +import kotlin.properties.Delegates + +const val NEED_TO_CREATE_BASE_MODULE = "needToCreateBaseModule" + +@Component +@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) +class VnfCommand @Autowired constructor( + private val asyncInstantiationBL: AsyncInstantiationBusinessLogic, + restMso: RestMsoImplementation, + private val msoRequestBuilder: MsoRequestBuilder, + msoResultHandlerService: MsoResultHandlerService, + inProgressStatusService:InProgressStatusService, + watchChildrenJobsBL: WatchChildrenJobsBL, + jobsBrokerService: JobsBrokerService, + jobAdapter: JobAdapter, + private val featureManager: FeatureManager +) : ResourceCommand(restMso, inProgressStatusService, msoResultHandlerService, + watchChildrenJobsBL, jobsBrokerService, jobAdapter), JobCommand { + + private var needToCreateBaseModule:Boolean by Delegates.notNull() + + override fun getData(): Map { + return super.getData() + mapOf(NEED_TO_CREATE_BASE_MODULE to needToCreateBaseModule) + } + + override fun init(sharedData: JobSharedData, commandData: Map): ResourceCommand { + super.init(sharedData, commandData) + needToCreateBaseModule = commandData.getOrDefault(NEED_TO_CREATE_BASE_MODULE, actionPhase != Action.Delete) as Boolean + return this + } + + + override fun createChildren(): Job.JobStatus { + val request:Vnf = getRequest() + if(isNeedToCreateChildJobs()){ + val dataForChild = buildDataForChild(request, actionPhase) + val vfModules:List = request.vfModules.values.stream().flatMap { vfKey -> vfKey.values.stream() }.collect(Collectors.toList()) + + try { + childJobs = pushChildrenJobsToBroker(vfModules.filter { filterModuleByNeedToCreateBase(it) }, dataForChild, JobType.VolumeGroupInstantiation) + } catch (e: AsdcCatalogException) { + LOGGER.error("Failed to retrieve service definitions from SDC, for VfModule is BaseModule.. Error: " + e.message , e) + return Job.JobStatus.FAILED + } + } + + return Job.JobStatus.COMPLETED_WITH_NO_ACTION + } + + private fun filterModuleByNeedToCreateBase(it: VfModule):Boolean { + return needToCreateBaseModule == + commandUtils.isVfModuleBaseModule( + commandParentData.getModelInfo(CommandParentData.CommandDataKey.SERVICE_MODEL_INFO).getModelVersionId(), + it.modelInfo.modelVersionId) + } + + override fun planCreateMyselfRestCall(commandParentData: CommandParentData, request: JobAdapter.AsyncJobRequest, userId: String, testApi: String?): MsoRestCallPlan { + val serviceInstanceId = commandParentData.getInstanceId(CommandParentData.CommandDataKey.SERVICE_INSTANCE_ID) + val serviceModelInfo = commandParentData.getModelInfo(CommandParentData.CommandDataKey.SERVICE_MODEL_INFO) + + val instantiatePath = asyncInstantiationBL.getVnfInstantiationPath(serviceInstanceId) + + val requestDetailsWrapper = msoRequestBuilder.generateVnfInstantiationRequest( + request as Vnf, + serviceModelInfo, serviceInstanceId, + userId, + testApi + ) + + val actionDescription = "create vnf in $serviceInstanceId" + + return MsoRestCallPlan(HttpMethod.POST, instantiatePath, Optional.of(requestDetailsWrapper), Optional.empty(), actionDescription) + + } + + override fun addMyselfToChildrenData(commandParentData: CommandParentData, request: BaseResource) { + commandParentData.addModelInfo(CommandParentData.CommandDataKey.VNF_MODEL_INFO, request.modelInfo); + commandParentData.addInstanceId(CommandParentData.CommandDataKey.VNF_INSTANCE_ID, getActualInstanceId(request)) + } + + override fun getRequest(): Vnf { + return sharedData.request as Vnf + } + + private fun isNeedToCreateChildJobs(): Boolean { + return featureManager.isActive(Features.FLAG_ASYNC_ALACARTE_VFMODULE) && + MapUtils.isNotEmpty(getRequest().vfModules) + } + + override fun planDeleteMyselfRestCall(commandParentData: CommandParentData, request: JobAdapter.AsyncJobRequest, userId: String): MsoRestCallPlan { + val serviceInstanceId = commandParentData.getInstanceId(CommandParentData.CommandDataKey.SERVICE_INSTANCE_ID) + val path = asyncInstantiationBL.getVnfDeletionPath(serviceInstanceId, getRequest().instanceId) + val requestDetailsWrapper = msoRequestBuilder.generateDeleteVnfRequest(getRequest(), userId) + return MsoRestCallPlan(HttpMethod.DELETE, path, Optional.of(requestDetailsWrapper), Optional.of(userId), + "delete vnf ${getRequest().instanceId} from service $serviceInstanceId") + + } + + companion object { + private val LOGGER = EELFLoggerDelegate.getLogger(VnfCommand::class.java) + } + + //in Delete phase - we delete all non-base vf-modules first, before base vf-module + //in Create phase - we create base vf-module first, and then all the others + override fun watchChildren(): Job.JobStatus { + val childrenStatus:Job.JobStatus = comulateStatusAndUpdatePropertyIfFinal(watchChildrenJobsBL.retrieveChildrenJobsStatus(childJobs)) + if (!childrenStatus.isFinal || + childrenStatus.isFailure || + (actionPhase == Action.Create && !needToCreateBaseModule) || + (actionPhase == Action.Delete && needToCreateBaseModule)) { + return childrenStatus + } + + needToCreateBaseModule = !needToCreateBaseModule; + createChildren() + return Job.JobStatus.IN_PROGRESS + } +} diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/VnfInProgressStatusCommand.java b/vid-app-common/src/main/java/org/onap/vid/job/command/VnfInProgressStatusCommand.java deleted file mode 100644 index 832c575db..000000000 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/VnfInProgressStatusCommand.java +++ /dev/null @@ -1,107 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * VID - * ================================================================================ - * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * 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.vid.job.command; - -import org.apache.commons.collections.MapUtils; -import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; -import org.onap.vid.asdc.AsdcCatalogException; -import org.onap.vid.job.Job; -import org.onap.vid.job.JobType; -import org.onap.vid.job.NextCommand; -import org.onap.vid.job.command.CommandParentData.CommandDataKey; -import org.onap.vid.job.impl.JobSharedData; -import org.onap.vid.model.serviceInstantiation.BaseResource; -import org.onap.vid.model.serviceInstantiation.VfModule; -import org.onap.vid.model.serviceInstantiation.Vnf; -import org.onap.vid.properties.Features; -import org.springframework.beans.factory.config.ConfigurableBeanFactory; -import org.springframework.context.annotation.Scope; -import org.springframework.stereotype.Component; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -@Component -@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) -public class VnfInProgressStatusCommand extends ResourceWithChildrenInProgressCommand { - private static final EELFLoggerDelegate LOG = EELFLoggerDelegate.getLogger(VnfInProgressStatusCommand.class); - - public VnfInProgressStatusCommand(JobSharedData sharedData, - String requestId, - String instanceId, - CommandParentData commandParentData) { - super(sharedData, requestId, instanceId, commandParentData); - } - - public VnfInProgressStatusCommand() { - } - - @Override - protected NextCommand processJobStatus(Job.JobStatus jobStatus) { - if (jobStatus == Job.JobStatus.FAILED) { - return new NextCommand(jobStatus); - } - - Vnf request = (Vnf) getSharedData().getRequest(); - - if (isNeedToCreateChildJobs(jobStatus, request)) { - commandParentData.addInstanceId(CommandDataKey.VNF_INSTANCE_ID, instanceId); - commandParentData.addModelInfo(CommandDataKey.VNF_MODEL_INFO, request.getModelInfo()); - //create volume group of base module job - Map dataForChild = buildDataForChild(); - List vfModules = request.getVfModules().values().stream().flatMap(vfKey -> vfKey.values().stream()).collect(Collectors.toList()); - List vgBaseJobs = new ArrayList<>(); - for( VfModule vfModule : vfModules){ - try { - if(commandUtils.isVfModuleBaseModule(commandParentData.getModelInfo(CommandDataKey.SERVICE_MODEL_INFO).getModelVersionId(), vfModule.getModelInfo().getModelVersionId())) { - vgBaseJobs.add(jobsBrokerService.add( - jobAdapter.createChildJob(JobType.VolumeGroupInstantiation, Job.JobStatus.CREATING, vfModule, getSharedData(), dataForChild)).toString()); - } - } catch (AsdcCatalogException e) { - LOG.error("Failed to retrieve service definitions from SDC, for VfModule is BaseModule. Error: "+e.getMessage() , e); - return new NextCommand(Job.JobStatus.COMPLETED_WITH_ERRORS); - } - } - return new NextCommand(Job.JobStatus.RESOURCE_IN_PROGRESS, new WatchingCommandBaseModule(getSharedData(), vgBaseJobs, false, commandParentData)); - } - - //in case of JobStatus.PAUSE we leave the job itself as IN_PROGRESS, for keep tracking job progress - if (jobStatus == Job.JobStatus.PAUSE) { - return new NextCommand(Job.JobStatus.RESOURCE_IN_PROGRESS, this); - } - return new NextCommand(jobStatus, this); - } - - - protected boolean isNeedToCreateChildJobs(Job.JobStatus jobStatus, BaseResource request) { - return featureManager.isActive(Features.FLAG_ASYNC_ALACARTE_VFMODULE) && - jobStatus == Job.JobStatus.COMPLETED && - MapUtils.isNotEmpty(((Vnf)request).getVfModules()); - } - - - @Override - protected ExpiryChecker getExpiryChecker() { - return x->false; - } -} diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/VnfInstantiationCommand.java b/vid-app-common/src/main/java/org/onap/vid/job/command/VnfInstantiationCommand.java deleted file mode 100644 index d3bfde3b6..000000000 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/VnfInstantiationCommand.java +++ /dev/null @@ -1,70 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * VID - * ================================================================================ - * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * 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.vid.job.command; - -import org.onap.vid.changeManagement.RequestDetailsWrapper; -import org.onap.vid.job.Job; -import org.onap.vid.job.JobAdapter; -import org.onap.vid.job.NextCommand; -import org.onap.vid.job.command.CommandParentData.CommandDataKey; -import org.onap.vid.model.serviceInstantiation.Vnf; -import org.onap.vid.mso.model.VnfInstantiationRequestDetails; -import org.onap.vid.services.AsyncInstantiationBusinessLogic; -import org.springframework.beans.factory.config.ConfigurableBeanFactory; -import org.springframework.context.annotation.Scope; -import org.springframework.stereotype.Component; - -import javax.inject.Inject; - -@Component -@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) -public class VnfInstantiationCommand extends ResourceInstantiationCommand { - - @Inject - private AsyncInstantiationBusinessLogic asyncInstantiationBL; - - @Override - protected String getRequestPath() { - return asyncInstantiationBL.getVnfInstantiationPath( commandParentData.getInstanceId(CommandDataKey.SERVICE_INSTANCE_ID)); - } - - @Override - protected RequestDetailsWrapper generateMSORequest(JobAdapter.AsyncJobRequest request, String userId) { - return asyncInstantiationBL.generateVnfInstantiationRequest( - (Vnf) getSharedData().getRequest(), - commandParentData.getModelInfo(CommandDataKey.SERVICE_MODEL_INFO), - commandParentData.getInstanceId(CommandDataKey.SERVICE_INSTANCE_ID), - getSharedData().getUserId() - ); - } - - @Override - protected String getJobAuditMSOStatus() { - return "VNF_REQUESTED"; - } - - @Override - protected NextCommand getNextCommand(String requestId, String instanceId) { - return new NextCommand(Job.JobStatus.RESOURCE_IN_PROGRESS, - new VnfInProgressStatusCommand(getSharedData(), requestId, instanceId, commandParentData)); - } - -} diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/VolumeGroupCommand.kt b/vid-app-common/src/main/java/org/onap/vid/job/command/VolumeGroupCommand.kt new file mode 100644 index 000000000..4da1dad15 --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/job/command/VolumeGroupCommand.kt @@ -0,0 +1,94 @@ +package org.onap.vid.job.command + +import org.apache.commons.lang3.StringUtils.isNotEmpty +import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate +import org.onap.vid.job.* +import org.onap.vid.model.Action +import org.onap.vid.model.serviceInstantiation.BaseResource +import org.onap.vid.model.serviceInstantiation.VfModule +import org.onap.vid.mso.RestMsoImplementation +import org.onap.vid.services.AsyncInstantiationBusinessLogic +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.beans.factory.config.ConfigurableBeanFactory +import org.springframework.context.annotation.Scope +import org.springframework.http.HttpMethod +import org.springframework.stereotype.Component +import java.util.* + +@Component +@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) +class VolumeGroupCommand @Autowired constructor( + private val asyncInstantiationBL: AsyncInstantiationBusinessLogic, + restMso: RestMsoImplementation, + private val msoRequestBuilder: MsoRequestBuilder, + msoResultHandlerService: MsoResultHandlerService, + inProgressStatusService:InProgressStatusService, + watchChildrenJobsBL: WatchChildrenJobsBL, + jobsBrokerService: JobsBrokerService, + jobAdapter: JobAdapter +) : ResourceCommand(restMso, inProgressStatusService, msoResultHandlerService, + watchChildrenJobsBL, jobsBrokerService, jobAdapter), JobCommand { + + companion object { + private val LOGGER = EELFLoggerDelegate.getLogger(VolumeGroupCommand::class.java) + } + + override fun createChildren(): Job.JobStatus { + val request: VfModule = getRequest() + val dataForChild = buildDataForChild(request, actionPhase) + + childJobs = pushChildrenJobsToBroker(listOf(request), dataForChild, JobType.VfmoduleInstantiation) + + return Job.JobStatus.COMPLETED_WITH_NO_ACTION + } + + override fun planCreateMyselfRestCall(commandParentData: CommandParentData, request: JobAdapter.AsyncJobRequest, userId: String, testApi: String?): MsoRestCallPlan { + + val serviceInstanceId = commandParentData.getInstanceId(CommandParentData.CommandDataKey.SERVICE_INSTANCE_ID) + val serviceModelInfo = commandParentData.getModelInfo(CommandParentData.CommandDataKey.SERVICE_MODEL_INFO) + val vnfInstanceId = commandParentData.getInstanceId(CommandParentData.CommandDataKey.VNF_INSTANCE_ID) + val vnfModelInfo = commandParentData.getModelInfo(CommandParentData.CommandDataKey.VNF_MODEL_INFO) + + val instantiatePath = asyncInstantiationBL.getVolumeGroupInstantiationPath(serviceInstanceId,vnfInstanceId) + + val requestDetailsWrapper = msoRequestBuilder.generateVolumeGroupInstantiationRequest( + request as VfModule, + serviceModelInfo, serviceInstanceId, + vnfModelInfo,vnfInstanceId, + userId, + testApi + ) + + val actionDescription = "create volumeGroup in $vnfInstanceId" + + return MsoRestCallPlan(HttpMethod.POST, instantiatePath, Optional.of(requestDetailsWrapper), Optional.empty(), actionDescription) + } + + override fun planDeleteMyselfRestCall(commandParentData: CommandParentData, request: JobAdapter.AsyncJobRequest, userId: String): MsoRestCallPlan { + TODO("not implemented") + } + + override fun isNeedToCreateMyself(): Boolean { + return super.isNeedToCreateMyself() && isNotEmpty(getRequest().volumeGroupInstanceName) + } + + override fun isNeedToDeleteMyself(): Boolean { + return false + } + + override fun getRequest(): VfModule { + return sharedData.request as VfModule + } + + override fun isDescendantHasAction(phase: Action): Boolean { + return phase == getRequest().action + } + + override fun addMyselfToChildrenData(commandParentData: CommandParentData, request: BaseResource) { + commandParentData.addInstanceId(CommandParentData.CommandDataKey.VG_INSTANCE_ID, getActualInstanceId(request)); + } + + override fun replaceMyself(): Job.JobStatus { + return Job.JobStatus.COMPLETED + } +} diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/VolumeGroupInProgressStatusCommand.java b/vid-app-common/src/main/java/org/onap/vid/job/command/VolumeGroupInProgressStatusCommand.java deleted file mode 100644 index 9c4d7b825..000000000 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/VolumeGroupInProgressStatusCommand.java +++ /dev/null @@ -1,85 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * VID - * ================================================================================ - * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * 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.vid.job.command; - -import org.onap.vid.job.Job; -import org.onap.vid.job.JobType; -import org.onap.vid.job.NextCommand; -import org.onap.vid.job.command.CommandParentData.CommandDataKey; -import org.onap.vid.job.impl.JobSharedData; -import org.onap.vid.model.serviceInstantiation.VfModule; -import org.springframework.beans.factory.config.ConfigurableBeanFactory; -import org.springframework.context.annotation.Scope; -import org.springframework.stereotype.Component; - -import java.util.Arrays; -import java.util.List; -import java.util.Map; - -@Component -@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) -public class VolumeGroupInProgressStatusCommand extends ResourceWithChildrenInProgressCommand { - - public VolumeGroupInProgressStatusCommand( - JobSharedData sharedData, - String requestId, - String instanceId, - CommandParentData parentData) { - super(sharedData, requestId, instanceId, parentData); - } - - public VolumeGroupInProgressStatusCommand() { - } - - @Override - protected NextCommand processJobStatus(Job.JobStatus jobStatus) { - if (jobStatus == Job.JobStatus.FAILED) { - return new NextCommand(Job.JobStatus.FAILED); - } - VfModule request = (VfModule) getSharedData().getRequest(); - - if (jobStatus == Job.JobStatus.COMPLETED) { - //vf module creation - Map dataForChild = buildDataForChild(); - List vfModuleJob = Arrays.asList(jobsBrokerService.add( - jobAdapter.createChildJob(JobType.VfmoduleInstantiation, Job.JobStatus.CREATING , request, getSharedData(), dataForChild)).toString()); - - return new NextCommand(Job.JobStatus.RESOURCE_IN_PROGRESS, new WatchingCommand(getSharedData(), vfModuleJob, false)); - } - - //in case of JobStatus.PAUSE we leave the job itself as IN_PROGRESS, for keep tracking job progress - if (jobStatus == Job.JobStatus.PAUSE) { - return new NextCommand(Job.JobStatus.RESOURCE_IN_PROGRESS, this); - } - return new NextCommand(jobStatus, this); - } - - @Override - protected Map buildDataForChild() { - commandParentData.addInstanceId(CommandDataKey.VG_INSTANCE_ID, this.instanceId); - return super.buildDataForChild(); - } - - @Override - protected ExpiryChecker getExpiryChecker() { - return x->false; - } -} diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/VolumeGroupInstantiationCommand.java b/vid-app-common/src/main/java/org/onap/vid/job/command/VolumeGroupInstantiationCommand.java deleted file mode 100644 index eff12ec73..000000000 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/VolumeGroupInstantiationCommand.java +++ /dev/null @@ -1,103 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * VID - * ================================================================================ - * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * 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.vid.job.command; - - -import org.apache.commons.lang3.StringUtils; -import org.onap.vid.changeManagement.RequestDetailsWrapper; -import org.onap.vid.job.*; -import org.onap.vid.job.command.CommandParentData.CommandDataKey; -import org.onap.vid.model.serviceInstantiation.VfModule; -import org.onap.vid.mso.model.VolumeGroupRequestDetails; -import org.onap.vid.services.AsyncInstantiationBusinessLogic; -import org.springframework.beans.factory.config.ConfigurableBeanFactory; -import org.springframework.context.annotation.Scope; -import org.springframework.stereotype.Component; - -import javax.inject.Inject; -import java.util.Collections; -import java.util.List; -import java.util.Map; - -@Component -@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) -public class VolumeGroupInstantiationCommand extends ResourceInstantiationCommand { - @Inject - private AsyncInstantiationBusinessLogic asyncInstantiationBL; - - @Inject - protected JobsBrokerService jobsBrokerService; - - @Inject - protected JobAdapter jobAdapter; - - @Override - protected String getRequestPath() { - return asyncInstantiationBL.getVolumeGroupInstantiationPath(commandParentData.getInstanceId(CommandDataKey.SERVICE_INSTANCE_ID),commandParentData.getInstanceId(CommandDataKey.VNF_INSTANCE_ID)); - } - - @Override - protected RequestDetailsWrapper generateMSORequest(JobAdapter.AsyncJobRequest request, String userId) { - return asyncInstantiationBL.generateVolumeGroupInstantiationRequest( - (VfModule) getSharedData().getRequest(), - commandParentData.getModelInfo(CommandDataKey.SERVICE_MODEL_INFO), - commandParentData.getInstanceId(CommandDataKey.SERVICE_INSTANCE_ID), - commandParentData.getModelInfo(CommandDataKey.VNF_MODEL_INFO), - commandParentData.getInstanceId(CommandDataKey.VNF_INSTANCE_ID), - getSharedData().getUserId() - ); - } - - @Override - protected NextCommand getNextCommand(String requestId, String instanceId){ - return new NextCommand( - Job.JobStatus.RESOURCE_IN_PROGRESS, - new VolumeGroupInProgressStatusCommand(getSharedData(), requestId, instanceId, commandParentData) - ); - } - - @Override - protected String getJobAuditMSOStatus() { - return "VOLUME_GROUP_REQUESTED"; - } - - @Override - public NextCommand call() { - String vgName = ((VfModule)getSharedData().getRequest()).getVolumeGroupInstanceName(); - if(StringUtils.isNotEmpty(vgName)){ - return super.call();//create volume group - }else { - //go to vf module creation - VfModule request = (VfModule) getSharedData().getRequest(); - Map dataForChild = buildDataForChild(); - List vfModuleJob = Collections.singletonList(jobsBrokerService.add( - jobAdapter.createChildJob(JobType.VfmoduleInstantiation, Job.JobStatus.CREATING, request, getSharedData(), dataForChild)).toString()); - - return new NextCommand(Job.JobStatus.RESOURCE_IN_PROGRESS, new WatchingCommand(getSharedData(), vfModuleJob, false)); - } - - } - - private Map buildDataForChild() { - return commandParentData.getParentData(); - } - -} diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/WatchChildrenJobsBL.kt b/vid-app-common/src/main/java/org/onap/vid/job/command/WatchChildrenJobsBL.kt index 7cebe2188..194fe4ba2 100644 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/WatchChildrenJobsBL.kt +++ b/vid-app-common/src/main/java/org/onap/vid/job/command/WatchChildrenJobsBL.kt @@ -7,9 +7,9 @@ * 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. @@ -21,11 +21,11 @@ package org.onap.vid.job.command import org.apache.commons.lang3.StringUtils -import org.onap.portalsdk.core.service.DataAccessService import org.onap.vid.job.Job import org.onap.vid.job.Job.JobStatus.* import org.onap.vid.job.impl.JobDaoImpl import org.onap.vid.utils.DaoUtils +import org.onap.portalsdk.core.service.DataAccessService import org.springframework.beans.factory.annotation.Autowired import org.springframework.stereotype.Service import java.util.* diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/WatchingCommand.java b/vid-app-common/src/main/java/org/onap/vid/job/command/WatchingCommand.java deleted file mode 100644 index 758cb56d7..000000000 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/WatchingCommand.java +++ /dev/null @@ -1,53 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * VID - * ================================================================================ - * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * 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.vid.job.command; - -import org.onap.vid.job.Job; -import org.onap.vid.job.NextCommand; -import org.onap.vid.job.impl.JobSharedData; -import org.springframework.beans.factory.config.ConfigurableBeanFactory; -import org.springframework.context.annotation.Scope; -import org.springframework.stereotype.Component; - -import java.util.List; - -@Component -@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) -public class WatchingCommand extends BaseWatchingCommand { - - public WatchingCommand() {} - - public WatchingCommand(JobSharedData sharedData, List childrenJobsIds, boolean isService) { - super(sharedData, childrenJobsIds, isService); - } - - protected NextCommand getNextCommand(Job.JobStatus cumulativeJobsStatus) { - if (cumulativeJobsStatus==Job.JobStatus.IN_PROGRESS) { - return (isService) ? new NextCommand(Job.JobStatus.IN_PROGRESS, this) - : new NextCommand(Job.JobStatus.RESOURCE_IN_PROGRESS, this); - } - if (isService) { - asyncInstantiationBL.updateServiceInfoAndAuditStatus(getSharedData().getJobUuid(), cumulativeJobsStatus); - } - return new NextCommand(cumulativeJobsStatus); - } - -} diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/WatchingCommandBaseModule.java b/vid-app-common/src/main/java/org/onap/vid/job/command/WatchingCommandBaseModule.java deleted file mode 100644 index 258811a01..000000000 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/WatchingCommandBaseModule.java +++ /dev/null @@ -1,113 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * VID - * ================================================================================ - * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * 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.vid.job.command; - -import com.google.common.collect.ImmutableMap; -import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; -import org.onap.vid.asdc.AsdcCatalogException; -import org.onap.vid.job.*; -import org.onap.vid.job.command.CommandParentData.CommandDataKey; -import org.onap.vid.job.impl.JobSharedData; -import org.onap.vid.model.serviceInstantiation.VfModule; -import org.onap.vid.model.serviceInstantiation.Vnf; -import org.springframework.beans.factory.config.ConfigurableBeanFactory; -import org.springframework.context.annotation.Scope; -import org.springframework.stereotype.Component; - -import javax.inject.Inject; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -@Component -@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) -public class WatchingCommandBaseModule extends BaseWatchingCommand { - @Inject - protected JobsBrokerService jobsBrokerService; - - @Inject - protected JobAdapter jobAdapter; - private static final EELFLoggerDelegate LOG = EELFLoggerDelegate.getLogger(WatchingCommandBaseModule.class); - - public WatchingCommandBaseModule( - JobSharedData sharedData, - List childrenJobsIds, - boolean isService, - CommandParentData commandParentData) { - super(sharedData, childrenJobsIds, isService); - this.commandParentData = commandParentData; - } - - public WatchingCommandBaseModule() { - - } - - @Override - protected NextCommand getNextCommand(Job.JobStatus cumulativeJobsStatus) { - - if (cumulativeJobsStatus== Job.JobStatus.IN_PROGRESS) { - return new NextCommand(Job.JobStatus.RESOURCE_IN_PROGRESS, this); - } - - if(cumulativeJobsStatus==Job.JobStatus.FAILED || cumulativeJobsStatus==Job.JobStatus.COMPLETED_WITH_ERRORS){ - return new NextCommand(Job.JobStatus.COMPLETED_WITH_ERRORS); - } - Vnf request = (Vnf) getSharedData().getRequest(); - Map dataForChild = buildDataForChild(); - //Create non-base Volume groups job - List vfModules = request.getVfModules().values().stream().flatMap(vfKey -> vfKey.values().stream()).collect(Collectors.toList()); - List vgNonBaseJobs = new ArrayList<>(); - for( VfModule vfModule : vfModules){ - try { - if(!commandUtils.isVfModuleBaseModule(commandParentData.getModelInfo(CommandDataKey.SERVICE_MODEL_INFO).getModelVersionId(), vfModule.getModelInfo().getModelVersionId())) { - vgNonBaseJobs.add(jobsBrokerService.add( - jobAdapter.createChildJob(JobType.VolumeGroupInstantiation, Job.JobStatus.CREATING, vfModule, getSharedData(), dataForChild)).toString()); - } - } catch (AsdcCatalogException e) { - LOG.error("Failed to retrieve service definitions from SDC, for VfModule is BaseModule. Error: "+e.getMessage() , e); - return new NextCommand(Job.JobStatus.COMPLETED_WITH_ERRORS); - } - } - return new NextCommand(Job.JobStatus.RESOURCE_IN_PROGRESS, new WatchingCommand(getSharedData(), vgNonBaseJobs, false)); - } - - @Override - public WatchingCommandBaseModule init(JobSharedData sharedData, Map commandData) { - super.init(sharedData, commandData); - commandParentData.initParentData(commandData); - return this; - } - - protected Map buildDataForChild() { - return commandParentData.getParentData(); - } - - @Override - public Map getData() { - return ImmutableMap.builder() - .putAll(super.getData()) - .putAll(commandParentData.getParentData()) - .build(); - } - - -} diff --git a/vid-app-common/src/main/java/org/onap/vid/job/impl/DeleteOldJobsSchedulerInitializer.java b/vid-app-common/src/main/java/org/onap/vid/job/impl/DeleteOldJobsSchedulerInitializer.java new file mode 100644 index 000000000..ad4b8c95a --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/job/impl/DeleteOldJobsSchedulerInitializer.java @@ -0,0 +1,96 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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.vid.job.impl; + + +import static org.quartz.CronScheduleBuilder.dailyAtHourAndMinute; + +import com.google.common.collect.ImmutableMap; +import java.util.Random; +import java.util.concurrent.TimeUnit; +import javax.annotation.PostConstruct; +import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; +import org.onap.portalsdk.core.util.SystemProperties; +import org.onap.vid.exceptions.GenericUncheckedException; +import org.onap.vid.job.JobsBrokerService; +import org.quartz.JobBuilder; +import org.quartz.JobDataMap; +import org.quartz.JobDetail; +import org.quartz.SchedulerException; +import org.quartz.Trigger; +import org.quartz.TriggerBuilder; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.quartz.SchedulerFactoryBean; +import org.springframework.stereotype.Component; + +@Component +public class DeleteOldJobsSchedulerInitializer { + + private JobsBrokerService jobsBrokerService; + private SchedulerFactoryBean schedulerFactoryBean; + private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(DeleteOldJobsSchedulerInitializer.class); + + @Autowired + public DeleteOldJobsSchedulerInitializer( + JobsBrokerService jobsBrokerService, + SchedulerFactoryBean schedulerFactoryBean + ) { + this.jobsBrokerService = jobsBrokerService; + this.schedulerFactoryBean = schedulerFactoryBean; + } + + @PostConstruct + public void init() { + try { + JobDetail jobDetail = createJobDetail(); + Trigger deleteOldJobsTrigger = createTrigger(); + schedulerFactoryBean.getScheduler().scheduleJob(jobDetail, deleteOldJobsTrigger); + } catch (SchedulerException e) { + logger.error(EELFLoggerDelegate.errorLogger, "Failed to schedule trigger for delete old jobs: {}", e.getMessage()); + throw new GenericUncheckedException(e); + } + } + + JobDetail createJobDetail() { + int days = Integer.parseInt(SystemProperties.getProperty("vid.asyncJob.howLongToKeepOldJobsInDays")); + long secondsAgo = TimeUnit.DAYS.toSeconds(days); + return JobBuilder.newJob().ofType(DeleteOldJobsWorker.class) + .withIdentity("DeleteOldJobsWorker") + .withDescription("worker that delete old vid jobs from DB") + .setJobData(new JobDataMap(ImmutableMap.of( + "jobsBrokerService", jobsBrokerService, + "secondsAgo", secondsAgo + ))) + .build(); + } + + Trigger createTrigger() { + int minutes = new Random(System.nanoTime()).nextInt(59); + int hours = 6; + logger.info("trigger for DeleteOldJobs is {}:{} ", hours, minutes); + + return TriggerBuilder.newTrigger() + .withIdentity("DeleteOldJobsTrigger") + .withDescription("Trigger to run delete old vid jobs worker") + .withSchedule(dailyAtHourAndMinute(hours, minutes)) + .build(); + } +} diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/MacroServiceInstantiationCommand.java b/vid-app-common/src/main/java/org/onap/vid/job/impl/DeleteOldJobsWorker.java similarity index 52% rename from vid-app-common/src/main/java/org/onap/vid/job/command/MacroServiceInstantiationCommand.java rename to vid-app-common/src/main/java/org/onap/vid/job/impl/DeleteOldJobsWorker.java index 6687a2c2e..d60ddab8d 100644 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/MacroServiceInstantiationCommand.java +++ b/vid-app-common/src/main/java/org/onap/vid/job/impl/DeleteOldJobsWorker.java @@ -7,9 +7,9 @@ * 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. @@ -18,29 +18,32 @@ * ============LICENSE_END========================================================= */ -package org.onap.vid.job.command; +package org.onap.vid.job.impl; -import org.onap.vid.changeManagement.RequestDetailsWrapper; -import org.onap.vid.job.JobCommand; -import org.onap.vid.mso.model.ServiceInstantiationRequestDetails; -import org.springframework.beans.factory.config.ConfigurableBeanFactory; -import org.springframework.context.annotation.Scope; -import org.springframework.stereotype.Component; +import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; +import org.onap.vid.job.JobsBrokerService; +import org.quartz.JobExecutionContext; +import org.springframework.scheduling.quartz.QuartzJobBean; +public class DeleteOldJobsWorker extends QuartzJobBean { -@Component -@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) -public class MacroServiceInstantiationCommand extends ServiceInstantiationCommand implements JobCommand { + private static final EELFLoggerDelegate LOGGER = EELFLoggerDelegate.getLogger(DeleteOldJobsWorker.class); - public MacroServiceInstantiationCommand() { - // empty constructor - } + private JobsBrokerService jobsBrokerService; + private long secondsAgo; @Override - protected RequestDetailsWrapper generateServiceInstantiationRequest() { - return asyncInstantiationBL.generateMacroServiceInstantiationRequest( - getSharedData().getJobUuid(), getRequest(), optimisticUniqueServiceInstanceName, getSharedData().getUserId() - ); + protected void executeInternal(JobExecutionContext context) { + LOGGER.info("delete old final jobs that has finished before {} seconds", secondsAgo); + jobsBrokerService.deleteOldFinalJobs(secondsAgo); + } + + //the following methods are used by quartz to inject members + public void setJobsBrokerService(JobsBrokerService jobsBrokerService) { + this.jobsBrokerService = jobsBrokerService; } + public void setSecondsAgo(long secondsAgo) { + this.secondsAgo = secondsAgo; + } } diff --git a/vid-app-common/src/main/java/org/onap/vid/job/impl/JobAdapterImpl.java b/vid-app-common/src/main/java/org/onap/vid/job/impl/JobAdapterImpl.java index 9ea1f1326..1bf0f43ee 100644 --- a/vid-app-common/src/main/java/org/onap/vid/job/impl/JobAdapterImpl.java +++ b/vid-app-common/src/main/java/org/onap/vid/job/impl/JobAdapterImpl.java @@ -7,9 +7,9 @@ * 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. @@ -25,7 +25,10 @@ import org.onap.vid.job.Job; import org.onap.vid.job.JobAdapter; import org.onap.vid.job.JobType; import org.onap.vid.model.JobModel; +import org.onap.vid.properties.Features; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import org.togglz.core.manager.FeatureManager; import java.util.Map; import java.util.UUID; @@ -33,6 +36,14 @@ import java.util.UUID; @Component public class JobAdapterImpl implements JobAdapter { + private final FeatureManager featureManager; + + @Autowired + public JobAdapterImpl(FeatureManager featureManager) { + this.featureManager = featureManager; + } + + @Override public JobModel toModel(Job job) { JobModel jobModel = new JobModel(); @@ -43,9 +54,9 @@ public class JobAdapterImpl implements JobAdapter { } @Override - public Job createServiceInstantiationJob(JobType jobType, AsyncJobRequest request, UUID templateId, String userId, String optimisticUniqueServiceInstanceName, Integer indexInBulk){ + public Job createServiceInstantiationJob(JobType jobType, AsyncJobRequest request, UUID templateId, String userId, String testApi, String optimisticUniqueServiceInstanceName, Integer indexInBulk){ JobDaoImpl job = createJob(jobType, Job.JobStatus.PENDING , userId); - job.setSharedData(new JobSharedData(job.getUuid(), userId, request)); + job.setSharedData(new JobSharedData(job.getUuid(), userId, request, testApi)); job.setTypeAndData(jobType, ImmutableMap.of( "optimisticUniqueServiceInstanceName", optimisticUniqueServiceInstanceName )); @@ -55,10 +66,14 @@ public class JobAdapterImpl implements JobAdapter { } @Override - public Job createChildJob(JobType jobType, Job.JobStatus jobStatus, AsyncJobRequest request, JobSharedData parentSharedData, Map jobData) { + public Job createChildJob(JobType jobType, AsyncJobRequest request, JobSharedData parentSharedData, Map jobData, int indexInBulk) { + Job.JobStatus jobStatus = featureManager.isActive(Features.FLAG_EXP_CREATE_RESOURCES_IN_PARALLEL) ? + Job.JobStatus.CREATING : Job.JobStatus.PENDING_RESOURCE; JobDaoImpl job = createJob(jobType, jobStatus , parentSharedData.getUserId()); job.setSharedData(new JobSharedData(job.getUuid(), request, parentSharedData)); job.setTypeAndData(jobType, jobData); + job.setTemplateId(parentSharedData.jobUuid); + job.setIndexInBulk(indexInBulk); return job; } diff --git a/vid-app-common/src/main/java/org/onap/vid/job/impl/JobDaoImpl.java b/vid-app-common/src/main/java/org/onap/vid/job/impl/JobDaoImpl.java index 5cddd4d0f..7d78d4580 100644 --- a/vid-app-common/src/main/java/org/onap/vid/job/impl/JobDaoImpl.java +++ b/vid-app-common/src/main/java/org/onap/vid/job/impl/JobDaoImpl.java @@ -7,9 +7,9 @@ * 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. @@ -23,7 +23,6 @@ package org.onap.vid.job.impl; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.base.MoreObjects; import org.hibernate.annotations.DynamicUpdate; import org.hibernate.annotations.SelectBeforeUpdate; @@ -41,6 +40,8 @@ import java.util.Map; import java.util.Objects; import java.util.UUID; +import static org.onap.vid.utils.KotlinUtilsKt.JACKSON_OBJECT_MAPPER; + /* The following 2 annotations let hibernate to update only fields that actually have been changed. DynamicUpdate tell hibernate to update only dirty fields. @@ -52,7 +53,6 @@ import java.util.UUID; @Table(name = "vid_job") public class JobDaoImpl extends VidBaseEntity implements Job { - private static ObjectMapper objectMapper = new ObjectMapper(); private Job.JobStatus status; private JobType type; private JobData data = new JobData(); @@ -63,6 +63,7 @@ public class JobDaoImpl extends VidBaseEntity implements Job { private Integer age = 0; private Integer indexInBulk = 0; private Date deletedAt; + private String build; @Id @Column(name = "JOB_ID", columnDefinition = "CHAR(36)") @@ -107,7 +108,7 @@ public class JobDaoImpl extends VidBaseEntity implements Job { @Column(name = "JOB_DATA", columnDefinition = "VARCHAR(30000)") public String getDataRaw() { try { - return objectMapper.writeValueAsString(data); + return JACKSON_OBJECT_MAPPER.writeValueAsString(data); } catch (JsonProcessingException e) { throw new GenericUncheckedException(e); } @@ -115,7 +116,7 @@ public class JobDaoImpl extends VidBaseEntity implements Job { public void setDataRaw(String data) { try { - this.data = objectMapper.readValue(data, JobData.class); + this.data = JACKSON_OBJECT_MAPPER.readValue(data, JobData.class); } catch (IOException e) { throw new JobException("Error parsing job's data", uuid, e); } @@ -202,6 +203,15 @@ public class JobDaoImpl extends VidBaseEntity implements Job { this.deletedAt = deletedAt; } + @Column(name = "BUILD", columnDefinition = "VARCHAR(100)") + public String getBuild() { + return build; + } + + public void setBuild(String build) { + this.build = build; + } + @Override public boolean equals(Object o) { if (this == o) return true; @@ -220,15 +230,15 @@ public class JobDaoImpl extends VidBaseEntity implements Job { return MoreObjects.toStringHelper(this) .add("status", status) .add("type", type) + .add("data", data) .add("templateId", templateId) .add("uuid", uuid) .add("takenBy", takenBy) .add("userId", userId) .add("age", age) - .add("created", created) - .add("modified", modified) + .add("indexInBulk", indexInBulk) .add("deletedAt", deletedAt) - .add("data", data) + .add("build", build) .toString(); } } diff --git a/vid-app-common/src/main/java/org/onap/vid/job/impl/JobData.java b/vid-app-common/src/main/java/org/onap/vid/job/impl/JobData.java index c8e128e60..113fde38c 100644 --- a/vid-app-common/src/main/java/org/onap/vid/job/impl/JobData.java +++ b/vid-app-common/src/main/java/org/onap/vid/job/impl/JobData.java @@ -7,9 +7,9 @@ * 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. diff --git a/vid-app-common/src/main/java/org/onap/vid/job/impl/JobSchedulerInitializer.java b/vid-app-common/src/main/java/org/onap/vid/job/impl/JobSchedulerInitializer.java index 234c10614..b3ab75b23 100644 --- a/vid-app-common/src/main/java/org/onap/vid/job/impl/JobSchedulerInitializer.java +++ b/vid-app-common/src/main/java/org/onap/vid/job/impl/JobSchedulerInitializer.java @@ -7,9 +7,9 @@ * 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. @@ -20,13 +20,13 @@ package org.onap.vid.job.impl; +import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; import org.onap.vid.exceptions.GenericUncheckedException; import org.onap.vid.job.Job; import org.onap.vid.job.JobsBrokerService; import org.onap.vid.job.command.JobCommandFactory; -import org.onap.vid.properties.Features; import org.quartz.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.quartz.SchedulerFactoryBean; @@ -34,6 +34,7 @@ import org.springframework.stereotype.Component; import org.togglz.core.manager.FeatureManager; import javax.annotation.PostConstruct; +import java.util.List; import static org.quartz.SimpleScheduleBuilder.simpleSchedule; @@ -51,24 +52,26 @@ public class JobSchedulerInitializer { JobsBrokerService jobsBrokerService, SchedulerFactoryBean schedulerFactoryBean, FeatureManager featureManager, - JobCommandFactory JobCommandFactory + JobCommandFactory jobCommandFactory ) { this.jobsBrokerService = jobsBrokerService; this.schedulerFactoryBean = schedulerFactoryBean; this.featureManager = featureManager; - this.jobCommandFactory = JobCommandFactory; + this.jobCommandFactory = jobCommandFactory; } + public static final List WORKERS_TOPICS = ImmutableList.of( + Job.JobStatus.PENDING, + Job.JobStatus.CREATING, + Job.JobStatus.IN_PROGRESS, + Job.JobStatus.RESOURCE_IN_PROGRESS, + Job.JobStatus.PENDING_RESOURCE + ); + @PostConstruct public void init() { - if (!featureManager.isActive(Features.FLAG_ASYNC_JOBS)) { - return; - } - scheduleJobWorker(Job.JobStatus.PENDING, 1); - scheduleJobWorker(Job.JobStatus.CREATING, 1); - scheduleJobWorker(Job.JobStatus.IN_PROGRESS, 1); - scheduleJobWorker(Job.JobStatus.RESOURCE_IN_PROGRESS, 1); + WORKERS_TOPICS.forEach(topic->scheduleJobWorker(topic, 1)); } private void scheduleJobWorker(Job.JobStatus topic, int intervalInSeconds) { diff --git a/vid-app-common/src/main/java/org/onap/vid/job/impl/JobSharedData.java b/vid-app-common/src/main/java/org/onap/vid/job/impl/JobSharedData.java index 66a04996e..f420f4f3e 100644 --- a/vid-app-common/src/main/java/org/onap/vid/job/impl/JobSharedData.java +++ b/vid-app-common/src/main/java/org/onap/vid/job/impl/JobSharedData.java @@ -7,9 +7,9 @@ * 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. @@ -32,6 +32,7 @@ public class JobSharedData { protected String userId; protected Class requestType; protected UUID rootJobId; + protected String testApi; @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, property="class") protected JobAdapter.AsyncJobRequest request; @@ -39,16 +40,17 @@ public class JobSharedData { public JobSharedData() { } - public JobSharedData(UUID jobUuid, String userId, JobAdapter.AsyncJobRequest request) { + public JobSharedData(UUID jobUuid, String userId, JobAdapter.AsyncJobRequest request, String testApi) { this.jobUuid = jobUuid; this.userId = userId; this.requestType = request.getClass(); this.request = request; this.rootJobId = jobUuid; + this.testApi = testApi; } public JobSharedData(UUID jobUuid, JobAdapter.AsyncJobRequest request, JobSharedData parentData) { - this(jobUuid, parentData.getUserId(), request); + this(jobUuid, parentData.getUserId(), request, parentData.getTestApi()); rootJobId = parentData.getRootJobId() != null ? parentData.getRootJobId() : parentData.getJobUuid(); } @@ -85,6 +87,14 @@ public class JobSharedData { return rootJobId; } + public String getTestApi() { + return testApi; + } + + public void setTestApi(String testApi) { + this.testApi = testApi; + } + @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/vid-app-common/src/main/java/org/onap/vid/job/impl/JobWorker.java b/vid-app-common/src/main/java/org/onap/vid/job/impl/JobWorker.java index 5b5d1e13d..0b277b4d2 100644 --- a/vid-app-common/src/main/java/org/onap/vid/job/impl/JobWorker.java +++ b/vid-app-common/src/main/java/org/onap/vid/job/impl/JobWorker.java @@ -7,9 +7,9 @@ * 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. @@ -25,17 +25,17 @@ import org.apache.commons.lang3.exception.ExceptionUtils; import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; import org.onap.vid.job.*; import org.onap.vid.job.command.JobCommandFactory; -import org.onap.vid.properties.Features; import org.quartz.JobExecutionContext; import org.springframework.scheduling.quartz.QuartzJobBean; import org.springframework.stereotype.Component; -import org.togglz.core.manager.FeatureManager; import java.util.Optional; import java.util.UUID; import static org.onap.vid.job.Job.JobStatus.FAILED; import static org.onap.vid.job.Job.JobStatus.STOPPED; +import static org.onap.vid.job.command.ResourceCommandKt.ACTION_PHASE; +import static org.onap.vid.job.command.ResourceCommandKt.INTERNAL_STATE; @Component public class JobWorker extends QuartzJobBean { @@ -43,7 +43,6 @@ public class JobWorker extends QuartzJobBean { private static final EELFLoggerDelegate LOGGER = EELFLoggerDelegate.getLogger(JobWorker.class); private JobsBrokerService jobsBrokerService; - private FeatureManager featureManager; private JobCommandFactory jobCommandFactory; private Job.JobStatus topic; @@ -51,10 +50,6 @@ public class JobWorker extends QuartzJobBean { protected void executeInternal(JobExecutionContext context) { Optional job; - if (!isMsoNewApiActive()) { - return; - } - job = pullJob(); while (job.isPresent()) { @@ -85,10 +80,16 @@ public class JobWorker extends QuartzJobBean { } protected Job executeJobAndGetNext(Job job) { - LOGGER.debug(EELFLoggerDelegate.debugLogger, "going to execute job {} of {}: {}/{}", + Object internalState = job.getData().get(INTERNAL_STATE); + Object actionPhase = job.getData().get(ACTION_PHASE); + LOGGER.debug(EELFLoggerDelegate.debugLogger, "going to execute job {} of {}: {}/{} {}/{}", StringUtils.substring(String.valueOf(job.getUuid()), 0, 8), StringUtils.substring(String.valueOf(job.getTemplateId()), 0, 8), - job.getStatus(), job.getType()); + job.getStatus(), + job.getType(), + actionPhase, + internalState + ); NextCommand nextCommand = executeCommandAndGetNext(job); @@ -128,10 +129,6 @@ public class JobWorker extends QuartzJobBean { return job; } - private boolean isMsoNewApiActive() { - return featureManager.isActive(Features.FLAG_ASYNC_INSTANTIATION); - } - private void tryMutingJobFromException(Exception e) { // If there's JobException in the stack, read job uuid from // the exception, and mute it in DB. @@ -158,10 +155,6 @@ public class JobWorker extends QuartzJobBean { this.jobsBrokerService = jobsBrokerService; } - public void setFeatureManager(FeatureManager featureManager) { - this.featureManager = featureManager; - } - public void setJobCommandFactory(JobCommandFactory jobCommandFactory) { this.jobCommandFactory = jobCommandFactory; } diff --git a/vid-app-common/src/main/java/org/onap/vid/job/impl/JobsBrokerServiceInDatabaseImpl.java b/vid-app-common/src/main/java/org/onap/vid/job/impl/JobsBrokerServiceInDatabaseImpl.java index 59ca43743..74a729494 100644 --- a/vid-app-common/src/main/java/org/onap/vid/job/impl/JobsBrokerServiceInDatabaseImpl.java +++ b/vid-app-common/src/main/java/org/onap/vid/job/impl/JobsBrokerServiceInDatabaseImpl.java @@ -7,9 +7,9 @@ * 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. @@ -22,6 +22,7 @@ package org.onap.vid.job.impl; import org.apache.commons.lang3.StringUtils; import org.hibernate.SessionFactory; +import org.jetbrains.annotations.NotNull; import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; import org.onap.portalsdk.core.service.DataAccessService; import org.onap.portalsdk.core.util.SystemProperties; @@ -30,18 +31,19 @@ import org.onap.vid.exceptions.OperationNotAllowedException; import org.onap.vid.job.Job; import org.onap.vid.job.JobsBrokerService; import org.onap.vid.properties.VidProperties; +import org.onap.vid.services.VersionService; import org.onap.vid.utils.DaoUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import javax.annotation.PostConstruct; -import java.nio.ByteBuffer; import java.sql.Timestamp; import java.time.LocalDateTime; import java.util.*; +import java.util.stream.Collectors; -import static org.onap.vid.job.Job.JobStatus.CREATING; +import static org.onap.vid.job.Job.JobStatus.*; @Service public class JobsBrokerServiceInDatabaseImpl implements JobsBrokerService { @@ -54,15 +56,20 @@ public class JobsBrokerServiceInDatabaseImpl implements JobsBrokerService { private int maxOpenedInstantiationRequestsToMso; private int pollingIntervalSeconds; + private final VersionService versionService; + @Autowired - public JobsBrokerServiceInDatabaseImpl(DataAccessService dataAccessService, SessionFactory sessionFactory, + public JobsBrokerServiceInDatabaseImpl(DataAccessService dataAccessService, + SessionFactory sessionFactory, @Value("0") int maxOpenedInstantiationRequestsToMso, - @Value("10") int pollingIntervalSeconds) { + @Value("10") int pollingIntervalSeconds, + VersionService versionService) { // tha @Value will inject conservative defaults; overridden in @PostConstruct from configuration this.dataAccessService = dataAccessService; this.sessionFactory = sessionFactory; this.maxOpenedInstantiationRequestsToMso = maxOpenedInstantiationRequestsToMso; this.pollingIntervalSeconds = pollingIntervalSeconds; + this.versionService = versionService; } @PostConstruct @@ -78,6 +85,7 @@ public class JobsBrokerServiceInDatabaseImpl implements JobsBrokerService { @Override public UUID add(Job job) { final JobDaoImpl jobDao = castToJobDaoImpl(job); + jobDao.setBuild(versionService.retrieveBuildNumber()); dataAccessService.saveDomainObject(jobDao, DaoUtils.getPropsMap()); return job.getUuid(); } @@ -120,7 +128,11 @@ public class JobsBrokerServiceInDatabaseImpl implements JobsBrokerService { } private java.sql.Timestamp nowMinusInterval() { - return Timestamp.valueOf(LocalDateTime.now().minusSeconds(pollingIntervalSeconds)); + return nowMinusInterval(pollingIntervalSeconds); + } + + private java.sql.Timestamp nowMinusInterval(long seconds) { + return Timestamp.valueOf(LocalDateTime.now().minusSeconds(seconds)); } private String selectQueryByJobStatus(Job.JobStatus topic){ @@ -130,17 +142,23 @@ public class JobsBrokerServiceInDatabaseImpl implements JobsBrokerService { "select * from VID_JOB" + " where" + // select only non-deleted in-progress jobs - " JOB_STATUS = '" + topic + "'" + - " and TAKEN_BY is null" + - " and DELETED_AT is null" + + filterByStatusNotTakenNotDeleted(topic) + // give some breath, don't select jos that were recently reached - intervalCondition + + intervalCondition + // take the oldest handled one " order by MODIFIED_DATE ASC" + // select only one result " limit 1"; } + @NotNull + private String filterByStatusNotTakenNotDeleted(Job.JobStatus topic) { + return " JOB_STATUS = '" + topic + "'" + + " and TAKEN_BY is null" + + " and DELETED_AT is null "+ + " and BUILD = '"+ versionService.retrieveBuildNumber() +"'"; + } + private String sqlQueryForTopic(Job.JobStatus topic) { switch (topic) { case IN_PROGRESS: @@ -148,44 +166,73 @@ public class JobsBrokerServiceInDatabaseImpl implements JobsBrokerService { case CREATING: return selectQueryByJobStatus(topic); case PENDING: - return "" + - // select only pending jobs - "select vid_job.* from VID_JOB " + - // select users have in_progress jobs - "left join \n" + - " (select user_Id, 1 as has_any_in_progress_job from VID_JOB where JOB_STATUS = 'IN_PROGRESS' or TAKEN_BY IS NOT NULL \n" + - "group by user_id) users_have_any_in_progress_job_tbl\n" + - "on vid_job.user_id = users_have_any_in_progress_job_tbl.user_id " + - "where JOB_STATUS = 'PENDING' and TAKEN_BY is null" + - // job is not deleted - " AND DELETED_AT is null and (\n" + - // limit in-progress to some amount - "select sum(CASE WHEN JOB_STATUS='IN_PROGRESS' or (JOB_STATUS='PENDING' and TAKEN_BY IS NOT NULL) THEN 1 ELSE 0 END) as in_progress\n" + - "from VID_JOB ) <" + maxOpenedInstantiationRequestsToMso + " \n " + - // don't take jobs from templates that already in-progress/failed - "and TEMPLATE_Id not in \n" + - "(select TEMPLATE_Id from vid_job where" + - " TEMPLATE_Id IS NOT NULL and("+ - " (JOB_STATUS='FAILED' and DELETED_AT is null)" + // failed but not deleted - " or JOB_STATUS='IN_PROGRESS'" + - " or TAKEN_BY IS NOT NULL))" + " \n " + - // prefer older jobs, but the earlier in each bulk - "order by has_any_in_progress_job, CREATED_DATE, INDEX_IN_BULK " + - // select only one result - "limit 1"; + return selectQueryForPendingJob(); + case PENDING_RESOURCE: + return selectQueryForPendingResource(); default: throw new GenericUncheckedException("Unsupported topic to pull from: " + topic); } } + @NotNull + private String selectQueryForPendingJob() { + return "" + + // select only pending jobs + "select vid_job.* from VID_JOB " + + // select users have in_progress jobs + "left join \n" + + " (select user_Id, 1 as has_any_in_progress_job from VID_JOB where JOB_STATUS = 'IN_PROGRESS' or TAKEN_BY IS NOT NULL \n" + + "group by user_id) users_have_any_in_progress_job_tbl\n" + + "on vid_job.user_id = users_have_any_in_progress_job_tbl.user_id " + + "where "+filterByStatusNotTakenNotDeleted(Job.JobStatus.PENDING)+" and (\n" + + // limit in-progress to some amount + "select sum(CASE WHEN JOB_STATUS='IN_PROGRESS' or (JOB_STATUS='PENDING' and TAKEN_BY IS NOT NULL) THEN 1 ELSE 0 END) as in_progress\n" + + "from VID_JOB ) <" + maxOpenedInstantiationRequestsToMso + " \n " + + // don't take jobs from templates that already in-progress/failed + "and TEMPLATE_Id not in \n" + + "(select TEMPLATE_Id from vid_job where" + + " TEMPLATE_Id IS NOT NULL and("+ + " (JOB_STATUS='FAILED' and DELETED_AT is null)" + // failed but not deleted + " or JOB_STATUS='IN_PROGRESS'" + + " or TAKEN_BY IS NOT NULL))" + " \n " + + // prefer older jobs, but the earlier in each bulk + "order by has_any_in_progress_job, CREATED_DATE, INDEX_IN_BULK " + + // select only one result + "limit 1"; + } - private byte[] getUuidAsByteArray(UUID owner) { - ByteBuffer bb = ByteBuffer.wrap(new byte[16]); - bb.putLong(owner.getMostSignificantBits()); - bb.putLong(owner.getLeastSignificantBits()); - return bb.array(); + @NotNull + private String selectQueryForPendingResource() { + return "select * from vid_job as JOB left join \n" + + //count jobs + "(select template_id,count(*) as in_progress_count from vid_job \n" + + String.format("where (\n"+ + " (\n"+ + //with job_status IN_PROGRESS or RESOURCE_IN_PROGRESS + " (job_status in ('%s','%s') and DELETED_AT is NULL) \n",IN_PROGRESS, RESOURCE_IN_PROGRESS)+ + //or that with job_status PENDING_RESOURCE that are taken + String.format(" or (JOB_STATUS='%s' and TAKEN_BY IS NOT NULL)\n )\n", PENDING_RESOURCE) + + //with template ID and are not deleted + " and TEMPLATE_ID IS NOT NULL and DELETED_AT is NULL\n)\n" + + //join them to vid_job by template_id + "group by template_id)\n"+ + "as COUNTER on COUNTER.template_id=JOB.template_id \n" + + + "where (\n"+ + //select jobs with job_status PENDING_RESOURCE that are nit taken and not deleted + filterByStatusNotTakenNotDeleted(PENDING_RESOURCE) + "\n" + + //that have no count in the counter (no other in progress job with same templateId) + " and in_progress_count is NULL \n" + + //and that have valid templateId + " and JOB.template_id is not NULL \n"+ + ")\n" + + //INDEX_IN_BULK is for order them inside same templateId, + //template_id - for order between different templateId (just to be deterministic) + "order by INDEX_IN_BULK,JOB.template_id \n" + + "limit 1;"; } + @Override public void pushBack(Job job) { final JobDaoImpl remoteDaoJob = (JobDaoImpl) dataAccessService.getDomainObject(JobDaoImpl.class, job.getUuid(), null); @@ -253,7 +300,7 @@ public class JobsBrokerServiceInDatabaseImpl implements JobsBrokerService { throw new OperationNotAllowedException("Service does not exist"); } - if (!remoteDaoJob.getStatus().equals(Job.JobStatus.PENDING) && !remoteDaoJob.getStatus().equals(Job.JobStatus.STOPPED) || !StringUtils.isEmpty(remoteDaoJob.getTakenBy()) ) { + if ((remoteDaoJob.getStatus() != Job.JobStatus.PENDING) && (remoteDaoJob.getStatus() != Job.JobStatus.STOPPED) || !StringUtils.isEmpty(remoteDaoJob.getTakenBy()) ) { logger.debug(EELFLoggerDelegate.debugLogger,"jobId {}: Service status does not allow deletion from the queue, status = {}", jobId, remoteDaoJob.getStatus() + ", takenBy " + remoteDaoJob.getTakenBy()); throw new OperationNotAllowedException("Service status does not allow deletion from the queue"); @@ -290,4 +337,17 @@ public class JobsBrokerServiceInDatabaseImpl implements JobsBrokerService { return updatedEntities != 0; } + + private static String sqlListOfFinalStatus = + String.format("(%s)", + FINAL_STATUS.stream(). + map(x->String.format("'%s'",x)). + collect(Collectors.joining(",")) + ); + + @Override + public void deleteOldFinalJobs(long secondsAgo) { + String select = String.format(" MODIFIED_DATE <= '%s' and JOB_STATUS in %s", nowMinusInterval(secondsAgo), sqlListOfFinalStatus); + dataAccessService.deleteDomainObjects(JobDaoImpl.class, select, null); + } } diff --git a/vid-app-common/src/main/java/org/onap/vid/model/Action.java b/vid-app-common/src/main/java/org/onap/vid/model/Action.java index ebaa691af..c0d4fae6a 100644 --- a/vid-app-common/src/main/java/org/onap/vid/model/Action.java +++ b/vid-app-common/src/main/java/org/onap/vid/model/Action.java @@ -7,9 +7,9 @@ * 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. @@ -23,7 +23,9 @@ package org.onap.vid.model; public enum Action { Create(ServiceInfo.ServiceAction.INSTANTIATE), Delete(ServiceInfo.ServiceAction.DELETE), - None(ServiceInfo.ServiceAction.UPDATE); + None(ServiceInfo.ServiceAction.UPDATE), + Resume(ServiceInfo.ServiceAction.RESUME), + Replace(ServiceInfo.ServiceAction.REPLACE); private final ServiceInfo.ServiceAction serviceAction; Action(ServiceInfo.ServiceAction serviceAction){ diff --git a/vid-app-common/src/main/java/org/onap/vid/model/JobAuditStatus.java b/vid-app-common/src/main/java/org/onap/vid/model/JobAuditStatus.java index 49e25ecb0..645934530 100644 --- a/vid-app-common/src/main/java/org/onap/vid/model/JobAuditStatus.java +++ b/vid-app-common/src/main/java/org/onap/vid/model/JobAuditStatus.java @@ -7,9 +7,9 @@ * 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. @@ -20,6 +20,21 @@ package org.onap.vid.model; +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.TimeZone; +import java.util.UUID; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; +import javax.persistence.Transient; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder; @@ -29,14 +44,6 @@ import org.hibernate.annotations.Type; import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; import org.onap.vid.job.Job.JobStatus; -import javax.persistence.*; -import java.text.DateFormat; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.TimeZone; -import java.util.UUID; - /* The following 2 annotations let hibernate to update only fields that actually have been changed. DynamicUpdate tell hibernate to update only dirty fields. @@ -54,43 +61,40 @@ public class JobAuditStatus extends VidBaseEntity { public JobAuditStatus(){} - public JobAuditStatus(UUID jobId, String jobStatus, SourceStatus source){ + private JobAuditStatus(UUID jobId, String instanceName, String instanceType, String jobStatus, + SourceStatus source, UUID requestId, String additionalInfo, Date date, int ordinal) { this.jobId = jobId; + this.instanceName = instanceName; + this.instanceType = instanceType; this.jobStatus = jobStatus; this.source = source; + this.requestId = requestId; + setAdditionalInfo(additionalInfo); + this.ordinal = ordinal; + this.created = date; } - public JobAuditStatus(UUID jobId, String jobStatus, SourceStatus source, Date date){ - this(jobId, jobStatus, source); - this.created = date; + public JobAuditStatus(UUID jobId, String jobStatus, SourceStatus source){ + this(jobId, null, null, jobStatus, source, null, null, null, 0); } public JobAuditStatus(UUID jobId, String jobStatus, SourceStatus source, UUID requestId, String additionalInfo) { - this(jobId, jobStatus, source); - this.requestId = requestId; - setAdditionalInfo(additionalInfo); + this(jobId, null, null, jobStatus, source, requestId, additionalInfo, null, 0); } - public JobAuditStatus(UUID jobId, String jobStatus, SourceStatus source, UUID requestId, String additionalInfo, Date date){ - this(jobId, jobStatus, source, requestId, additionalInfo); - this.created = date; + public JobAuditStatus(String instanceName, String jobStatus, UUID requestId, String additionalInfo, String date, String instanceType) { + this(null, instanceName, instanceType, jobStatus, null, requestId, additionalInfo, null, 0); + this.created = dateStringToDate(date); } - public JobAuditStatus(String instanceName, String jobStatus, UUID requestId, String additionalInfo) { - this.instanceName = instanceName; - this.jobStatus = jobStatus; - this.requestId = requestId; - this.additionalInfo = additionalInfo; - + public static JobAuditStatus createForTest(UUID jobId, String jobStatus, SourceStatus source, Date date, int ordinal) { + return new JobAuditStatus(jobId, null, null, jobStatus, source, null, null, date, ordinal); } - public JobAuditStatus(String instanceName, String jobStatus, UUID requestId, String additionalInfo, String date, String instanceType) { - this(instanceName, jobStatus, requestId, additionalInfo); - this.created = dateStringToDate(date); - this.instanceType = instanceType; + public static JobAuditStatus createForTest(UUID jobId, String jobStatus, SourceStatus source, UUID requestId, String additionalInfo, Date date) { + return new JobAuditStatus(jobId, null, null, jobStatus, source, requestId, additionalInfo, date, 0); } - private Date dateStringToDate(String dateAsString){ if (StringUtils.isEmpty(dateAsString)) { return null; @@ -121,6 +125,7 @@ public class JobAuditStatus extends VidBaseEntity { .append(source, that.source) .append(requestId, that.requestId) .append(additionalInfo, that.additionalInfo) + // ordinal is not part of equality (similarly to "created" field) .isEquals(); } @@ -132,6 +137,7 @@ public class JobAuditStatus extends VidBaseEntity { .append(source) .append(requestId) .append(additionalInfo) + // ordinal is not part of equality (similarly to "created" field) .toHashCode(); } @@ -140,6 +146,25 @@ public class JobAuditStatus extends VidBaseEntity { VID } + public enum ResourceTypeFilter { + SERVICE("serviceInstanceId"), + VNF("vnfInstanceId"), + VFMODULE("vfModuleInstanceId"), + NETWORK("networkInstanceId"), + VNFGROUP("instanceGroupId"); + + private final String filterBy; + + ResourceTypeFilter(String filterBy) { + this.filterBy = filterBy; + } + + public String getFilterBy() { + return filterBy; + } + } + + private UUID jobId; private String instanceName; private String instanceType; @@ -147,6 +172,7 @@ public class JobAuditStatus extends VidBaseEntity { private SourceStatus source; private UUID requestId; private String additionalInfo; + private int ordinal; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @@ -206,6 +232,18 @@ public class JobAuditStatus extends VidBaseEntity { this.additionalInfo = StringUtils.substring(additionalInfo, 0, MAX_ADDITIONAL_INFO_LENGTH); } + @Column(name = "ORDINAL", columnDefinition = "INT") + public int getOrdinal() { + // Ordinal allows sorting audit statuses by + // insertion order, regardless of "created" + // field + return ordinal; + } + + public void setOrdinal(int ordinal) { + this.ordinal = ordinal; + } + @Transient public String getInstanceName() { return instanceName; diff --git a/vid-app-common/src/main/java/org/onap/vid/model/ModelUtil.java b/vid-app-common/src/main/java/org/onap/vid/model/ModelUtil.java index 98514f0c1..45e100fb1 100644 --- a/vid-app-common/src/main/java/org/onap/vid/model/ModelUtil.java +++ b/vid-app-common/src/main/java/org/onap/vid/model/ModelUtil.java @@ -18,15 +18,8 @@ * ============LICENSE_END========================================================= */ -/** - * - */ package org.onap.vid.model; -/** - * The Class ModelUtil. - * - */ public class ModelUtil { /** * Gets the tags for the given element according to the configured namespace diff --git a/vid-app-common/src/main/java/org/onap/vid/model/ResourceInfo.java b/vid-app-common/src/main/java/org/onap/vid/model/ResourceInfo.java new file mode 100644 index 000000000..deda23f37 --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/model/ResourceInfo.java @@ -0,0 +1,144 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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.vid.model; + +import static org.onap.vid.utils.KotlinUtilsKt.JACKSON_OBJECT_MAPPER; + +import com.fasterxml.jackson.core.JsonProcessingException; +import java.io.IOException; +import java.util.Objects; +import java.util.UUID; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.Id; +import javax.persistence.Table; +import javax.persistence.Transient; +import org.hibernate.annotations.DynamicUpdate; +import org.hibernate.annotations.SelectBeforeUpdate; +import org.hibernate.annotations.Type; +import org.onap.vid.exceptions.GenericUncheckedException; +import org.onap.vid.job.Job; +import org.onap.vid.job.JobException; +import org.onap.vid.mso.rest.AsyncRequestStatus; + +@DynamicUpdate +@SelectBeforeUpdate +@Entity +@Table(name = "vid_resource_info") +public class ResourceInfo extends VidBaseEntity { + + private String trackById; + private UUID rootJobId; + private String instanceId; + private Job.JobStatus jobStatus; + private AsyncRequestStatus errorMessage; + + public ResourceInfo(){} + + public ResourceInfo(String trackById, UUID rootJobId, String instanceId, Job.JobStatus jobStatus, AsyncRequestStatus errorMessage) { + this.trackById = trackById; + this.rootJobId = rootJobId; + this.instanceId = instanceId; + this.jobStatus = jobStatus; + this.errorMessage = errorMessage; + } + + @Id + @Column(name = "TRACK_BY_ID", columnDefinition = "CHAR(36)") + public String getTrackById() { + return trackById; + } + + @Column(name = "ROOT_JOB_ID", columnDefinition = "CHAR(36)") + @Type(type="org.hibernate.type.UUIDCharType") + public UUID getRootJobId() { + return rootJobId; + } + + @Column(name="JOB_STATUS") + @Enumerated(EnumType.STRING) + public Job.JobStatus getJobStatus() { + return jobStatus; + } + + @Column(name="INSTANCE_ID") + public String getInstanceId() { + return instanceId; + } + + public void setTrackById(String trackById) { + this.trackById = trackById; + } + + public void setRootJobId(UUID rootJobId) { + this.rootJobId = rootJobId; + } + + public void setInstanceId(String instanceId) { + this.instanceId = instanceId; + } + public void setJobStatus(Job.JobStatus jobStatus) { + this.jobStatus = jobStatus; + } + + @Column(name = "ERROR_MESSAGE", columnDefinition = "VARCHAR(30000)") + public String getErrorMessageRaw() { + try { + return JACKSON_OBJECT_MAPPER.writeValueAsString(errorMessage); + } catch (JsonProcessingException e) { + throw new GenericUncheckedException(e); + } + } + + public void setErrorMessageRaw(String failedMessage) { + try { + this.errorMessage = JACKSON_OBJECT_MAPPER.readValue(failedMessage, AsyncRequestStatus.class); + } catch (IOException e) { + throw new JobException("Error parsing mso failed message", rootJobId, e); + } + } + + @Transient + public AsyncRequestStatus getErrorMessage() { + return this.errorMessage; + } + + public void setErrorMessage(AsyncRequestStatus errorMessage) { + this.errorMessage = errorMessage; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ResourceInfo that = (ResourceInfo) o; + return Objects.equals(trackById, that.trackById) && + Objects.equals(instanceId, that.instanceId) && + jobStatus == that.jobStatus; + } + + @Override + public int hashCode() { + return Objects.hash(trackById, instanceId, jobStatus); + } +} diff --git a/vid-app-common/src/main/java/org/onap/vid/model/ServiceInfo.java b/vid-app-common/src/main/java/org/onap/vid/model/ServiceInfo.java index 3b49eedca..1e1e6c2a7 100644 --- a/vid-app-common/src/main/java/org/onap/vid/model/ServiceInfo.java +++ b/vid-app-common/src/main/java/org/onap/vid/model/ServiceInfo.java @@ -7,9 +7,9 @@ * 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. @@ -18,22 +18,22 @@ * ============LICENSE_END========================================================= */ - package org.onap.vid.model; +package org.onap.vid.model; - import com.fasterxml.jackson.annotation.JsonProperty; - import org.hibernate.annotations.DynamicUpdate; - import org.hibernate.annotations.SelectBeforeUpdate; - import org.hibernate.annotations.Type; - import org.onap.portalsdk.core.domain.support.DomainVo; - import org.onap.vid.job.Job; +import com.fasterxml.jackson.annotation.JsonProperty; +import org.hibernate.annotations.DynamicUpdate; +import org.hibernate.annotations.SelectBeforeUpdate; +import org.hibernate.annotations.Type; +import org.onap.portalsdk.core.domain.support.DomainVo; +import org.onap.vid.job.Job; - import javax.persistence.*; - import java.io.Serializable; - import java.util.Date; - import java.util.Objects; - import java.util.Set; - import java.util.UUID; +import javax.persistence.*; +import java.io.Serializable; +import java.util.Date; +import java.util.Objects; +import java.util.Set; +import java.util.UUID; /* The following 2 annotations let hibernate to update only fields that actually have been changed. @@ -49,11 +49,9 @@ public class ServiceInfo extends DomainVo { public enum ServiceAction { INSTANTIATE, DELETE, - UPDATE - } - - public void setUserId(String userId) { - this.userId = userId; + UPDATE, + RESUME, + REPLACE } private UUID jobId; @@ -65,6 +63,7 @@ public class ServiceInfo extends DomainVo { private Date statusModifiedDate; private boolean hidden; private boolean pause; + private boolean retryEnabled; private Date deletedAt; private String owningEntityId; private String owningEntityName; @@ -90,7 +89,12 @@ public class ServiceInfo extends DomainVo { } - public ServiceInfo(String userId, Boolean aLaCarte, Job.JobStatus jobStatus, boolean pause, UUID jobId, UUID templateId, String owningEntityId, String owningEntityName, String project, String aicZoneId, String aicZoneName, String tenantId, String tenantName, String regionId, String regionName, String serviceType, String subscriberName, String subscriberId, String serviceInstanceId, String serviceInstanceName, String serviceModelId, String serviceModelName, String serviceModelVersion, Date createdBulkDate, ServiceAction action) { + public ServiceInfo(String userId, Boolean aLaCarte, Job.JobStatus jobStatus, boolean pause, UUID jobId, UUID templateId, + String owningEntityId, String owningEntityName, String project, String aicZoneId, String aicZoneName, + String tenantId, String tenantName, String regionId, String regionName, String serviceType, + String subscriberName, String subscriberId, String serviceInstanceId, String serviceInstanceName, + String serviceModelId, String serviceModelName, String serviceModelVersion, Date createdBulkDate, + ServiceAction action, boolean retryEnabled) { this.userId = userId; this.aLaCarte = aLaCarte; this.jobStatus = jobStatus; @@ -116,6 +120,7 @@ public class ServiceInfo extends DomainVo { this.serviceModelVersion = serviceModelVersion; this.createdBulkDate = createdBulkDate; this.action = action; + this.retryEnabled = retryEnabled; } @Column(name = "JOB_ID", columnDefinition = "CHAR(36)") @@ -168,6 +173,12 @@ public class ServiceInfo extends DomainVo { return pause; } + @Column(name="IS_RETRY_ENABLED") + @JsonProperty("isRetryEnabled") + public boolean isRetryEnabled() { + return retryEnabled; + } + @Column(name="OWNING_ENTITY_ID") public String getOwningEntityId() { return owningEntityId; @@ -260,8 +271,8 @@ public class ServiceInfo extends DomainVo { @Column(name="DELETED_AT") public Date getDeletedAt() { - return deletedAt; - } + return deletedAt; + } @Column(name="ACTION") @Enumerated(EnumType.STRING) @@ -319,6 +330,9 @@ public class ServiceInfo extends DomainVo { return super.getAuditTrail(); } + public void setUserId(String userId) { + this.userId = userId; + } public void setJobId(UUID jobId) { this.jobId = jobId; } @@ -351,6 +365,10 @@ public class ServiceInfo extends DomainVo { this.pause = pause; } + public void setRetryEnabled(boolean retryEnabled) { + this.retryEnabled = retryEnabled; + } + public void setOwningEntityId(String owningEntityId) { this.owningEntityId = owningEntityId; } @@ -424,55 +442,54 @@ public class ServiceInfo extends DomainVo { } public void setDeletedAt(Date deletedAt) { - this.deletedAt = deletedAt; - } + this.deletedAt = deletedAt; + } public void setAction(ServiceAction action) { this.action = action; } - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof ServiceInfo)) return false; - ServiceInfo that = (ServiceInfo) o; - return isHidden() == that.isHidden() && - isPause() == that.isPause() && - isALaCarte() == that.isALaCarte() && - Objects.equals(getDeletedAt(), that.getDeletedAt()) && - Objects.equals(getJobId(), that.getJobId()) && - Objects.equals(getTemplateId(), that.getTemplateId()) && - Objects.equals(getUserId(), that.getUserId()) && - Objects.equals(getMsoRequestId(), that.getMsoRequestId()) && - getJobStatus() == that.getJobStatus() && - Objects.equals(getStatusModifiedDate(), that.getStatusModifiedDate()) && - Objects.equals(getOwningEntityId(), that.getOwningEntityId()) && - Objects.equals(getOwningEntityName(), that.getOwningEntityName()) && - Objects.equals(getProject(), that.getProject()) && - Objects.equals(getAicZoneId(), that.getAicZoneId()) && - Objects.equals(getAicZoneName(), that.getAicZoneName()) && - Objects.equals(getTenantId(), that.getTenantId()) && - Objects.equals(getTenantName(), that.getTenantName()) && - Objects.equals(getRegionId(), that.getRegionId()) && - Objects.equals(getRegionName(), that.getRegionName()) && - Objects.equals(getServiceType(), that.getServiceType()) && - Objects.equals(getSubscriberName(), that.getSubscriberName()) && - Objects.equals(getSubscriberId(), that.getSubscriberId()) && - Objects.equals(getServiceInstanceId(), that.getServiceInstanceId()) && - Objects.equals(getServiceInstanceName(), that.getServiceInstanceName()) && - Objects.equals(getServiceModelId(), that.getServiceModelId()) && - Objects.equals(getServiceModelName(), that.getServiceModelName()) && - Objects.equals(getServiceModelVersion(), that.getServiceModelVersion()) && - Objects.equals(getCreatedBulkDate(), that.getCreatedBulkDate()) && - Objects.equals(getAction(), that.getAction()); - } - - @Override - public int hashCode() { - - return Objects.hash(getJobId(), getTemplateId(), getUserId(), getMsoRequestId(), isALaCarte(), getJobStatus(), getStatusModifiedDate(), - isHidden(), isPause(), getDeletedAt(), getOwningEntityId(), getOwningEntityName(), getProject(), - getAicZoneId(), getAicZoneName(), getTenantId(), getTenantName(), getRegionId(), - getRegionName(), getServiceType(), getSubscriberName(), getSubscriberId(), getServiceInstanceId(), - getServiceInstanceName(), getServiceModelId(), getServiceModelName(), - getServiceModelVersion(), getCreatedBulkDate(), getAction()); - } - } + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof ServiceInfo)) return false; + ServiceInfo that = (ServiceInfo) o; + return aLaCarte == that.aLaCarte && + isHidden() == that.isHidden() && + isPause() == that.isPause() && + isRetryEnabled() == that.isRetryEnabled() && + Objects.equals(getJobId(), that.getJobId()) && + Objects.equals(getTemplateId(), that.getTemplateId()) && + Objects.equals(getUserId(), that.getUserId()) && + Objects.equals(getMsoRequestId(), that.getMsoRequestId()) && + getJobStatus() == that.getJobStatus() && + Objects.equals(getStatusModifiedDate(), that.getStatusModifiedDate()) && + Objects.equals(getDeletedAt(), that.getDeletedAt()) && + Objects.equals(getOwningEntityId(), that.getOwningEntityId()) && + Objects.equals(getOwningEntityName(), that.getOwningEntityName()) && + Objects.equals(getProject(), that.getProject()) && + Objects.equals(getAicZoneId(), that.getAicZoneId()) && + Objects.equals(getAicZoneName(), that.getAicZoneName()) && + Objects.equals(getTenantId(), that.getTenantId()) && + Objects.equals(getTenantName(), that.getTenantName()) && + Objects.equals(getRegionId(), that.getRegionId()) && + Objects.equals(getRegionName(), that.getRegionName()) && + Objects.equals(getServiceType(), that.getServiceType()) && + Objects.equals(getSubscriberName(), that.getSubscriberName()) && + Objects.equals(getSubscriberId(), that.getSubscriberId()) && + Objects.equals(getServiceInstanceId(), that.getServiceInstanceId()) && + Objects.equals(getServiceInstanceName(), that.getServiceInstanceName()) && + Objects.equals(getServiceModelId(), that.getServiceModelId()) && + Objects.equals(getServiceModelName(), that.getServiceModelName()) && + Objects.equals(getServiceModelVersion(), that.getServiceModelVersion()) && + Objects.equals(getCreatedBulkDate(), that.getCreatedBulkDate()) && + getAction() == that.getAction(); + } + + @Override + public int hashCode() { + return Objects.hash(getJobId(), getTemplateId(), getUserId(), getMsoRequestId(), aLaCarte, getJobStatus(), + getStatusModifiedDate(), isHidden(), isPause(), isRetryEnabled(), getDeletedAt(), getOwningEntityId(), getOwningEntityName(), + getProject(), getAicZoneId(), getAicZoneName(), getTenantId(), getTenantName(), getRegionId(), getRegionName(), getServiceType(), + getSubscriberName(), getSubscriberId(), getServiceInstanceId(), getServiceInstanceName(), getServiceModelId(), getServiceModelName(), + getServiceModelVersion(), getCreatedBulkDate(), getAction()); + } +} diff --git a/vid-app-common/src/main/java/org/onap/vid/model/ServiceModel.java b/vid-app-common/src/main/java/org/onap/vid/model/ServiceModel.java index c1e403587..121c7e4c1 100644 --- a/vid-app-common/src/main/java/org/onap/vid/model/ServiceModel.java +++ b/vid-app-common/src/main/java/org/onap/vid/model/ServiceModel.java @@ -2,14 +2,14 @@ * ============LICENSE_START======================================================= * VID * ================================================================================ - * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. * ================================================================================ * 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. @@ -40,14 +40,14 @@ public class ServiceModel { /** The service. */ private Service service; - + /** The vnfs. */ private Map vnfs; - + /** The networks. */ private Map networks; - private Map collectionResource; + private Map collectionResources; /** Port Mirroring Configuration node templates */ private Map configurations; @@ -60,12 +60,12 @@ public class ServiceModel { /** * The vf modules. The VNF also has vfmodules but the vfmodules at the service level may have additional info - * that is not present in the VNF, like the vf module customization String + * that is not present in the VNF, like the vf module customization String */ private Map vfModules; - /** - * The volume groups. The VNF also has volume groups but the volume groups will be populated at the service level - * for newer models + /** + * The volume groups. The VNF also has volume groups but the volume groups will be populated at the service level + * for newer models */ private Map volumeGroups; @@ -74,12 +74,15 @@ public class ServiceModel { /** Resource groups of VF (VNF) type. */ private Map vnfGroups; - + + /** The vrfs */ + private Map vrfs; + /** * Instantiates a new service model. */ public ServiceModel() {} - + /** * Gets the service. * @@ -140,6 +143,10 @@ public class ServiceModel { return vnfGroups; } + public Map getVrfs() { + return vrfs; + } + /** * Sets the service. * @@ -230,12 +237,16 @@ public class ServiceModel { this.vnfGroups = vnfGroups; } - public Map getCollectionResource() { - return collectionResource; + public void setVrfs(Map vrfs) { + this.vrfs = vrfs; } - public void setCollectionResource(Map collectionResource) { - this.collectionResource = collectionResource; + public Map getCollectionResources() { + return collectionResources; + } + + public void setCollectionResources(Map collectionResources) { + this.collectionResources = collectionResources; } public Map getFabricConfigurations() { @@ -254,9 +265,9 @@ public class ServiceModel { * @return the service */ public static Service extractService(ToscaModel serviceToscaModel, org.onap.vid.asdc.beans.Service asdcServiceMetadata) { - + final Service service = new Service(); - + service.setCategory(serviceToscaModel.getMetadata().getCategory()); service.setInvariantUuid(serviceToscaModel.getMetadata().getInvariantUUID()); service.setName(serviceToscaModel.getMetadata().getName()); @@ -274,18 +285,18 @@ public class ServiceModel { public static void extractGroups (ToscaModel serviceToscaModel,ServiceModel serviceModel) { // Get the groups. The groups may duplicate the groups that are in the VNF model and have // additional data like the VF module customization String> - + final Map vfModules = new HashMap<> (); final Map volumeGroups = new HashMap<> (); - + String asdcModelNamespace = VidProperties.getAsdcModelNamespace(); - String vfModuleTag = asdcModelNamespace + ModelConstants.VF_MODULE; - + String vfModuleTag = asdcModelNamespace + ModelConstants.VF_MODULE; + for (Entry component : serviceToscaModel.gettopology_template().getGroups().entrySet()) { final Group group = component.getValue(); final String type = group.getType(); final String customizationName = component.getKey(); - + if (type.startsWith(vfModuleTag)) { VfModule vfMod = VfModule.extractVfModule(customizationName, group); vfModules.put(customizationName, vfMod); @@ -298,14 +309,14 @@ public class ServiceModel { // add this point vfModules and volume groups are disconnected from VNF serviceModel.setVfModules (vfModules); serviceModel.setVolumeGroups (volumeGroups); - + } /** * Populate the vf modules and volume groups that we may have under the service level under each VNF. */ public void associateGroups() { String methodName = "associateGroups()"; - LOG.debug(EELFLoggerDelegate.debugLogger, methodName + " start"); + LOG.debug(EELFLoggerDelegate.debugLogger, methodName + " start"); // go through the vnfs, get the vnf normalized name and look for a vf module with a customization name that starts // with vnf + ".." String vnfCustomizationName = null; @@ -319,13 +330,13 @@ public class ServiceModel { LOG.debug(EELFLoggerDelegate.debugLogger, methodName + " VNF customizationName=" + vnfCustomizationName + "normalized customization name=" + normalizedVnfCustomizationName); - + // now check to see if there is a vf module with customization name that starts with normalizedVnfCustomizationName if (!MapUtils.isEmpty(getVolumeGroups())) { for (Entry vfModuleComponent : getVfModules().entrySet()) { vfModuleCustomizationName = vfModuleComponent.getValue().getModelCustomizationName(); - + LOG.debug(EELFLoggerDelegate.debugLogger, methodName + " VF Module customizationName=" + vfModuleCustomizationName ); if ( vfModuleCustomizationName.startsWith(normalizedVnfCustomizationName + ".." )) { @@ -335,7 +346,7 @@ public class ServiceModel { } } } - + } @@ -346,14 +357,14 @@ public class ServiceModel { (tmpVnf.getVfModules()).put(vfModuleComponent.getKey(), vfModuleComponent.getValue()); LOG.debug(EELFLoggerDelegate.debugLogger, methodName + - " Associated VF Module customizationName=" + vfModuleComponent.getKey() + " with VNF customization name=" + vnfCustomizationName); + " Associated VF Module customizationName=" + vfModuleComponent.getKey() + " with VNF customization name=" + vnfCustomizationName); // now find if this vf module has volume groups, if so, find the volume group with the same customization name and put it under the VNF if ( vfModuleComponent.getValue().isVolumeGroupAllowed() ) { if (isVolumeGroupsContainsVfModuleCustomName(vfModuleCustomizationName)) { - (vnfComponent.getValue().getVolumeGroups()).put(vfModuleCustomizationName, (getVolumeGroups()).get(vfModuleCustomizationName)); - } - } + (vnfComponent.getValue().getVolumeGroups()).put(vfModuleCustomizationName, (getVolumeGroups()).get(vfModuleCustomizationName)); + } + } } private boolean isVolumeGroupsContainsVfModuleCustomName(String vfModuleCustomizationName) { diff --git a/vid-app-common/src/main/java/org/onap/vid/model/VersionAndFeatures.kt b/vid-app-common/src/main/java/org/onap/vid/model/VersionAndFeatures.kt new file mode 100644 index 000000000..730e382d3 --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/model/VersionAndFeatures.kt @@ -0,0 +1,12 @@ +package org.onap.vid.model + +data class VersionAndFeatures( + val features:String, + val build:String, + val displayVersion:String +) { + companion object { + val unknown: VersionAndFeatures = VersionAndFeatures("unknown", "unknown", "unknown") + } +} + diff --git a/vid-app-common/src/main/java/org/onap/vid/model/VidNotions.kt b/vid-app-common/src/main/java/org/onap/vid/model/VidNotions.kt index 7f06bfe2f..f67d8fbd9 100644 --- a/vid-app-common/src/main/java/org/onap/vid/model/VidNotions.kt +++ b/vid-app-common/src/main/java/org/onap/vid/model/VidNotions.kt @@ -7,9 +7,9 @@ * 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. @@ -26,7 +26,10 @@ import com.fasterxml.jackson.annotation.JsonValue import com.google.common.base.CaseFormat class VidNotions(@get:JsonInclude(JsonInclude.Include.NON_NULL) - val instantiationUI: InstantiationUI, val modelCategory: ModelCategory, val viewEditUI: InstantiationUI) { + val instantiationUI: InstantiationUI, + val modelCategory: ModelCategory, + val viewEditUI: InstantiationUI, + val instantiationType: InstantiationType) { enum class InstantiationUI { NETWORK_WITH_PROPERTY_NETWORK_TECHNOLOGY_EQUALS_STANDARD_SRIOV_OR_OVS, SERVICE_WITH_FABRIC_CONFIGURATION, @@ -34,7 +37,12 @@ class VidNotions(@get:JsonInclude(JsonInclude.Include.NON_NULL) SERVICE_UUID_IS_1ffce89f_ef3f_4cbb_8b37_82134590c5de, ANY_ALACARTE_NEW_UI, MACRO_SERVICE, - SERVICE_WITH_VNF_GROUPING; + SERVICE_WITH_VNF_GROUPING, + TRANSPORT_SERVICE, + SERVICE_WITH_COLLECTION_RESOURCE, + A_LA_CARTE_VNF_SERVICE_ROLE, + INFRASTRUCTURE_VPN + ; @JsonValue fun toLowerCamel(): String { @@ -48,7 +56,16 @@ class VidNotions(@get:JsonInclude(JsonInclude.Include.NON_NULL) IS_5G_PROVIDER_NETWORK_MODEL, @JsonProperty("5G Fabric Configuration") IS_5G_FABRIC_CONFIGURATION_MODEL, + Transport, + SERVICE_WITH_COLLECTION_RESOURCE, + INFRASTRUCTURE_VPN, @JsonProperty("other") OTHER } + + enum class InstantiationType { + Macro, + ALaCarte, + ClientConfig + } } diff --git a/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/AAITreeNode.java b/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/AAITreeNode.java index 4b16b3122..f092c9ae6 100644 --- a/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/AAITreeNode.java +++ b/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/AAITreeNode.java @@ -7,9 +7,9 @@ * 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. @@ -20,17 +20,19 @@ package org.onap.vid.model.aaiTree; +import com.fasterxml.jackson.annotation.JsonIgnore; import org.apache.commons.lang3.StringUtils; +import org.onap.vid.aai.model.AaiGetNetworkCollectionDetails.RelationshipList; +import org.onap.vid.mso.model.CloudConfiguration; import java.util.*; public class AAITreeNode { - private String type; - private int uniqueNumber; + private NodeType type; private String orchestrationStatus; private String provStatus; - private Boolean inMaint = null; + private boolean inMaint; private String modelVersionId; private String modelCustomizationId; private String modelInvariantId; @@ -41,25 +43,19 @@ public class AAITreeNode { private String modelCustomizationName; private final List children = Collections.synchronizedList(new LinkedList<>()); private Map additionalProperties = new HashMap<>(); + private CloudConfiguration cloudConfiguration; + private RelationshipList relationshipList; private String keyInModel; private AAITreeNode parent; - public String getType() { + public NodeType getType() { return type; } - public void setType(String type) { + public void setType(NodeType type) { this.type = type; } - public int getUniqueNumber() { - return uniqueNumber; - } - - public void setUniqueNumber(int uniqueNumber) { - this.uniqueNumber = uniqueNumber; - } - public String getOrchestrationStatus() { return orchestrationStatus; } @@ -76,11 +72,11 @@ public class AAITreeNode { this.provStatus = provStatus; } - public Boolean getInMaint() { + public boolean getInMaint() { return inMaint; } - public void setInMaint(Boolean inMaint) { + public void setInMaint(boolean inMaint) { this.inMaint = inMaint; } @@ -169,7 +165,7 @@ public class AAITreeNode { } public String getUniqueNodeKey() { - return getNodeKey() + ":" + String.format("%03d", this.uniqueNumber); + return this.id; } public void setKeyInModel(String keyInModel) { @@ -180,6 +176,8 @@ public class AAITreeNode { return keyInModel; } + //prevent cyclic serialization of parent and children + @JsonIgnore public AAITreeNode getParent() { return parent; } @@ -188,6 +186,22 @@ public class AAITreeNode { this.parent = parent; } + public CloudConfiguration getCloudConfiguration() { + return cloudConfiguration; + } + + public void setCloudConfiguration(CloudConfiguration cloudConfiguration) { + this.cloudConfiguration = cloudConfiguration; + } + + public RelationshipList getRelationshipList() { + return relationshipList; + } + + public void setRelationshipList(RelationshipList relationshipList) { + this.relationshipList = relationshipList; + } + public void addChildren(List children) { for (AAITreeNode child : children) { child.setParent(this); diff --git a/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/AbstractNode.java b/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/AbstractNode.java index 64e953e17..a0fa60e97 100644 --- a/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/AbstractNode.java +++ b/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/AbstractNode.java @@ -7,9 +7,9 @@ * 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. @@ -32,6 +32,7 @@ public abstract class AbstractNode { protected String productFamilyId; protected String lcpCloudRegionId; protected String tenantId; + protected String cloudOwner; protected ModelInfo modelInfo; public AbstractNode() { @@ -70,4 +71,7 @@ public abstract class AbstractNode { return modelInfo; } + public String getCloudOwner() { + return cloudOwner; + } } diff --git a/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/CollectionResource.kt b/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/CollectionResource.kt new file mode 100644 index 000000000..054618dd5 --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/CollectionResource.kt @@ -0,0 +1,15 @@ +package org.onap.vid.model.aaiTree + +import org.apache.commons.lang.StringUtils + +fun isNfc(node: AAITreeNode): Boolean { + return node.type == NodeType.INSTANCE_GROUP && + node.additionalProperties["instance-group-type"] != null && + StringUtils.equalsIgnoreCase(node.additionalProperties["instance-group-type"].toString(), "L3-NETWORK") +} + +class CollectionResource(node: AAITreeNode) : Node(node) { + + val ncfs: Map = node.children.filter { isNfc(it) }.map { it.uniqueNodeKey to NCF(it) }.toMap() + +} \ No newline at end of file diff --git a/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/InstanceGroup.kt b/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/InstanceGroup.kt new file mode 100644 index 000000000..490853aa1 --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/InstanceGroup.kt @@ -0,0 +1,23 @@ +package org.onap.vid.model.aaiTree + +open class InstanceGroup(aaiNode: AAITreeNode) : Node(aaiNode) { + var instanceGroupRole: String? = null + var instanceGroupFunction: String? = null + + init { + val INSTANCE_GROUP_TYPE = "instance-group-type" + val INSTANCE_GROUP_ROLE = "instance-group-role" + val INSTANCE_GROUP_FUNCTION = "instance-group-function" + + if (aaiNode.additionalProperties[INSTANCE_GROUP_TYPE] != null) { + instanceType = aaiNode.additionalProperties[INSTANCE_GROUP_TYPE].toString() + } + if (aaiNode.additionalProperties[INSTANCE_GROUP_FUNCTION] != null) { + instanceGroupFunction = aaiNode.additionalProperties[INSTANCE_GROUP_FUNCTION].toString() + } + if (aaiNode.additionalProperties[INSTANCE_GROUP_ROLE] != null) { + instanceGroupRole = aaiNode.additionalProperties[INSTANCE_GROUP_ROLE].toString() + } + } + +} diff --git a/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/NCF.kt b/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/NCF.kt new file mode 100644 index 000000000..6d407da4c --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/NCF.kt @@ -0,0 +1,12 @@ +package org.onap.vid.model.aaiTree + +import org.apache.commons.lang.StringUtils + +class NCF(node: AAITreeNode) : InstanceGroup(node) { + val numberOfNetworks: Int = if (node.relationshipList != null && node.relationshipList.relationship != null) { + node.relationshipList.relationship + .filter { StringUtils.equalsIgnoreCase(it.relatedTo, "L3-NETWORK") } + .count() + } else 0 +} + diff --git a/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/Network.java b/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/Network.java index e80e57520..6b3023332 100644 --- a/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/Network.java +++ b/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/Network.java @@ -7,9 +7,9 @@ * 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. @@ -20,21 +20,121 @@ package org.onap.vid.model.aaiTree; -import org.onap.vid.aai.util.AAITreeConverter; - +import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL; +import static org.onap.vid.aai.util.AAITreeConverter.NETWORK_ROLE; import static org.onap.vid.aai.util.AAITreeConverter.NETWORK_TYPE; +import static org.onap.vid.aai.util.AAITreeConverter.PHYSICAL_NETWORK_NAME; +import static org.onap.vid.aai.util.AAITreeConverter.SERVICE_INSTANCE; +import static org.onap.vid.aai.util.AAITreeConverter.SERVICE_INSTANCE_SERVICE_INSTANCE_ID; +import static org.onap.vid.aai.util.AAITreeConverter.SERVICE_INSTANCE_SERVICE_INSTANCE_NAME; +import static org.onap.vid.aai.util.AAITreeConverter.TENANT; +import static org.onap.vid.aai.util.AAITreeConverter.TENANT_TENANT_NAME; +import static org.onap.vid.aai.util.AAITreeConverter.VPN_BINDING; + +import com.fasterxml.jackson.annotation.JsonInclude; +import org.apache.commons.collections.CollectionUtils; +import org.onap.vid.aai.model.AaiGetNetworkCollectionDetails.Relationship; +import org.onap.vid.aai.model.AaiGetNetworkCollectionDetails.RelationshipList; +import org.onap.vid.aai.util.AAITreeNodeUtils; +@JsonInclude(NON_NULL) public class Network extends Node { - public Network(AAITreeNode node) { - super(node, AAITreeConverter.ModelType.network); + private String role; + private String physicalName; + private String serviceName; + private String serviceUUID; + private String tenantName; + private Boolean isBoundToVpn; + private RouteTarget routeTarget; + + public Network(){} + + private Network(AAITreeNode node) { + super(node); + fillCloudConfigurationProperties(this, node.getCloudConfiguration()); } public static Network from(AAITreeNode node) { Network network = new Network(node); - if (node.getAdditionalProperties().get(NETWORK_TYPE) != null) { - network.setInstanceType(node.getAdditionalProperties().get(NETWORK_TYPE).toString()); + network.setInstanceType(readValueAsStringFromAdditionalProperties(node, NETWORK_TYPE)); + network.setRole(readValueAsStringFromAdditionalProperties(node, NETWORK_ROLE)); + network.setPhysicalName(readValueAsStringFromAdditionalProperties(node, PHYSICAL_NETWORK_NAME)); + RelationshipList relationshipList = node.getRelationshipList(); + Relationship serviceInstanceRelationship = AAITreeNodeUtils.findFirstRelationshipByRelatedTo(relationshipList, SERVICE_INSTANCE).orElse(null); + if (serviceInstanceRelationship != null) { + network.setServiceName(AAITreeNodeUtils.findFirstValue(serviceInstanceRelationship.getRelatedToPropertyList(), SERVICE_INSTANCE_SERVICE_INSTANCE_NAME).orElse(null)); + network.setServiceUUID(AAITreeNodeUtils.findFirstValue(serviceInstanceRelationship.getRelationDataList(), SERVICE_INSTANCE_SERVICE_INSTANCE_ID).orElse(null)); } + AAITreeNodeUtils.findFirstRelationshipByRelatedTo(relationshipList, TENANT).ifPresent( + tenantRelationship -> network.setTenantName(AAITreeNodeUtils.findFirstValue(tenantRelationship.getRelatedToPropertyList(), TENANT_TENANT_NAME).orElse(null)) + ); + // We are ignoring "is-bound-to-vpn" parameter from additionalProperties because there is a requirement to define vpn binding presence from by related-to: vpn-binding + network.setBoundToVpn(AAITreeNodeUtils.findFirstRelationshipByRelatedTo(relationshipList, VPN_BINDING).isPresent()); + + //get the route target + node.getChildren().stream() + .filter(x->x.getType()== NodeType.VPN_BINDING) // get all VPN_BINDING related to the network + .map(x->VpnBindingKt.from(x)) // create VPN_BINDING nodes + .filter(x-> CollectionUtils.isNotEmpty(x.getRouteTargets())) // get the RouteTargets that are not empty + .findFirst() // get the first one + .ifPresent(x->network.setRouteTarget(x.getRouteTargets().get(0))); // If there is a route target - add it to the network return network; } + + public String getRole() { + return role; + } + + public void setRole(String role) { + this.role = role; + } + + public String getPhysicalName() { + return physicalName; + } + + public void setPhysicalName(String physicalName) { + this.physicalName = physicalName; + } + + public String getServiceName() { + return serviceName; + } + + public void setServiceName(String serviceName) { + this.serviceName = serviceName; + } + + public String getServiceUUID() { + return serviceUUID; + } + + public void setServiceUUID(String serviceUUID) { + this.serviceUUID = serviceUUID; + } + + public String getTenantName() { + return tenantName; + } + + public void setTenantName(String tenantName) { + this.tenantName = tenantName; + } + + public Boolean isBoundToVpn() { + return isBoundToVpn; + } + + public void setBoundToVpn(Boolean boundToVpn) { + isBoundToVpn = boundToVpn; + } + + public RouteTarget getRouteTarget() { + return routeTarget; + } + + public void setRouteTarget(RouteTarget routeTarget) { + this.routeTarget = routeTarget; + } } diff --git a/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/Node.java b/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/Node.java index 5ce5eec43..435f70f1a 100644 --- a/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/Node.java +++ b/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/Node.java @@ -7,9 +7,9 @@ * 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. @@ -20,9 +20,12 @@ package org.onap.vid.model.aaiTree; -import org.onap.vid.aai.util.AAITreeConverter; +import org.onap.vid.mso.model.CloudConfiguration; import org.onap.vid.mso.model.ModelInfo; +import java.util.Objects; +import java.util.UUID; + public class Node extends AbstractNode { private String instanceType; @@ -38,7 +41,11 @@ public class Node extends AbstractNode { private final String trackById; - public Node(AAITreeNode aaiNode, AAITreeConverter.ModelType modelType) { + public Node() { + trackById = UUID.randomUUID().toString(); + } + + public Node(AAITreeNode aaiNode) { super(); this.instanceId = aaiNode.getId(); this.instanceName = aaiNode.getName(); @@ -46,11 +53,13 @@ public class Node extends AbstractNode { this.provStatus = aaiNode.getProvStatus(); this.inMaint = aaiNode.getInMaint(); this.uuid = aaiNode.getModelVersionId(); - this.originalName = aaiNode.getModelCustomizationName(); + this.originalName = aaiNode.getKeyInModel(); this.trackById = aaiNode.getUniqueNodeKey(); ModelInfo nodeModelInfo = new ModelInfo(); - nodeModelInfo.setModelType(modelType.name()); + if (aaiNode.getType() != null) { + nodeModelInfo.setModelType(aaiNode.getType().getModelType()); + } nodeModelInfo.setModelName(aaiNode.getModelName()); nodeModelInfo.setModelVersion(aaiNode.getModelVersion()); nodeModelInfo.setModelVersionId(aaiNode.getModelVersionId()); @@ -156,4 +165,16 @@ public class Node extends AbstractNode { public String getTrackById() { return trackById; } + + public static void fillCloudConfigurationProperties(AbstractNode that, CloudConfiguration cloudConfiguration) { + if (cloudConfiguration !=null) { + that.lcpCloudRegionId = cloudConfiguration.getLcpCloudRegionId(); + that.tenantId = cloudConfiguration.getTenantId(); + that.cloudOwner = cloudConfiguration.getCloudOwner(); + } + } + + public static String readValueAsStringFromAdditionalProperties(AAITreeNode node, String key) { + return Objects.toString(node.getAdditionalProperties().get(key), null); + } } diff --git a/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/NodeType.java b/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/NodeType.java new file mode 100644 index 000000000..5e1228f9f --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/NodeType.java @@ -0,0 +1,82 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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.vid.model.aaiTree; + +public enum NodeType { + SERVICE_INSTANCE("service-instance", "service-instance-id", "service-instance-name", "service"), + GENERIC_VNF ("generic-vnf", "vnf-id", "vnf-name", "vnf"), + NETWORK ("l3-network", "network-id", "network-name", "network"), + FAILURE ("failure_node", NodeType.NONE, NodeType.NONE, NodeType.NONE), + COLLECTION_RESOURCE ("collection", "collection-id", "collection-name", "collection"), + CONFIGURATION ("configuration", "configuration-id", "configuration-name", "configuration"), + PNF ("pnf", "pnf-id", "pnf-name", "pnf"), + VF_MODULE ("vf-module", "vf-module-id", "vf-module-name", "vfModule"), + INSTANCE_GROUP ("instance-group", "id", "instance-group-name", "instanceGroup"), + PORT ("l-interface", "interface-id", "interface-name", "connectionPoint"), + VOLUME_GROUP ("volume-group", "volume-group-id", "volume-group-name", "volumeGroup"), + VLAN_TAG("vlan-tag", "vlan-tag-id", NodeType.NONE, NodeType.NONE), + VPN_BINDING("vpn-binding", "vpn-id", "vpn-name", "vpnBinding"), + ; + + private String type; + private String id; + private String name; + private String modelType; + + public static final String NONE = ""; + + NodeType(String type, String id, String name, String modelType) { + this.type = type; + this.id = id; + this.name = name; + this.modelType = modelType; + } + + public String getType() { + return type; + } + + public String getId() { + return id; + } + + public String getName() { + return name; + } + + public String getModelType() { + return modelType; + } + + public static NodeType fromString(String type) { + for (NodeType nodeType : NodeType.values()) { + if (nodeType.type.equalsIgnoreCase(type)) { + return nodeType; + } + } + return null; + } + + @Override + public String toString() { + return this.type; + } +} \ No newline at end of file diff --git a/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/RelatedVnf.java b/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/RelatedVnf.java index 37dc45afd..febd8e0fd 100644 --- a/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/RelatedVnf.java +++ b/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/RelatedVnf.java @@ -7,9 +7,9 @@ * 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. @@ -20,10 +20,10 @@ package org.onap.vid.model.aaiTree; -import org.onap.vid.aai.util.AAITreeConverter; - import static org.onap.vid.aai.util.AAITreeConverter.VNF_TYPE; +import org.apache.commons.lang3.builder.ToStringBuilder; + public class RelatedVnf extends Node { private String serviceInstanceId; @@ -55,13 +55,15 @@ public class RelatedVnf extends Node { } public RelatedVnf(AAITreeNode node) { - super(node, AAITreeConverter.ModelType.vnf); + super(node); } public static RelatedVnf from(AAITreeNode node) { RelatedVnf vnf = new RelatedVnf(node); - vnf.setServiceInstanceId(node.getParent().getId()); - vnf.setServiceInstanceName(node.getParent().getName()); + if (node.getParent() != null && node.getParent().getType() == NodeType.SERVICE_INSTANCE) { + vnf.setServiceInstanceId(node.getParent().getId()); + vnf.setServiceInstanceName(node.getParent().getName()); + } if (node.getAdditionalProperties().get(VNF_TYPE) != null) { vnf.setInstanceType(node.getAdditionalProperties().get(VNF_TYPE).toString()); @@ -69,4 +71,22 @@ public class RelatedVnf extends Node { return vnf; } + + @Override + public String toString() { + return new ToStringBuilder(this) + .append("serviceInstanceId", serviceInstanceId) + .append("serviceInstanceName", serviceInstanceName) + .append("tenantName", tenantName) + .append("action", action) + .append("instanceName", instanceName) + .append("instanceId", instanceId) + .append("orchStatus", orchStatus) + .append("productFamilyId", productFamilyId) + .append("lcpCloudRegionId", lcpCloudRegionId) + .append("tenantId", tenantId) + .append("cloudOwner", cloudOwner) + .append("modelInfo", modelInfo) + .toString(); + } } diff --git a/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/ServiceInstance.java b/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/ServiceInstance.java index 111e98b25..923be132f 100644 --- a/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/ServiceInstance.java +++ b/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/ServiceInstance.java @@ -7,9 +7,9 @@ * 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. @@ -20,10 +20,9 @@ package org.onap.vid.model.aaiTree; -import org.onap.vid.mso.model.ModelInfo; - import java.util.HashMap; import java.util.Map; +import org.onap.vid.mso.model.ModelInfo; public class ServiceInstance extends AbstractNode { @@ -43,13 +42,17 @@ public class ServiceInstance extends AbstractNode { private Map vnfs = new HashMap<>(); private Map networks = new HashMap<>(); + private Map vrfs = new HashMap<>(); + private Map vnfGroups = new HashMap<>(); + private Map collectionResources = new HashMap<>(); private int validationCounter; private Map existingVNFCounterMap; private Map existingNetworksCounterMap; private Map existingVnfGroupCounterMap; + private Map existingVRFCounterMap; public void setInstanceName(String instanceName) { this.instanceName = instanceName; @@ -175,6 +178,14 @@ public class ServiceInstance extends AbstractNode { this.networks = networks; } + public Map getCollectionResources() { + return collectionResources; + } + + public void setCollectionResources(Map collectionResources) { + this.collectionResources = collectionResources; + } + public Map getVnfGroups() { return vnfGroups; } public void setVnfGroups(Map vnfGroups) { this.vnfGroups = vnfGroups; } @@ -210,4 +221,20 @@ public class ServiceInstance extends AbstractNode { public void setExistingVnfGroupCounterMap(Map existingVnfGroupCounterMap) { this.existingVnfGroupCounterMap = existingVnfGroupCounterMap; } + + public Map getVrfs() { + return vrfs; + } + + public void setVrfs(Map vrfs) { + this.vrfs = vrfs; + } + + public Map getExistingVRFCounterMap() { + return existingVRFCounterMap; + } + + public void setExistingVRFCounterMap(Map existingVRFCounterMap) { + this.existingVRFCounterMap = existingVRFCounterMap; + } } diff --git a/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/VfModule.java b/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/VfModule.java index 2a4c83b2a..0db27eaa4 100644 --- a/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/VfModule.java +++ b/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/VfModule.java @@ -7,9 +7,9 @@ * 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. @@ -20,8 +20,6 @@ package org.onap.vid.model.aaiTree; -import org.onap.vid.aai.util.AAITreeConverter; - import static org.onap.vid.aai.util.AAITreeConverter.IS_BASE_VF_MODULE; public class VfModule extends Node { @@ -30,7 +28,8 @@ public class VfModule extends Node { private String volumeGroupName; public VfModule(AAITreeNode node) { - super(node, AAITreeConverter.ModelType.vfModule); + super(node); + fillCloudConfigurationProperties(this, node.getCloudConfiguration()); } public boolean getIsBase() { diff --git a/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/Vnf.java b/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/Vnf.java index 03c1508f9..2df5bdcf6 100644 --- a/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/Vnf.java +++ b/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/Vnf.java @@ -7,9 +7,9 @@ * 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. @@ -20,21 +20,19 @@ package org.onap.vid.model.aaiTree; -import org.onap.vid.aai.util.AAITreeConverter; -import org.onap.vid.services.AAITreeNodeBuilder; +import static org.onap.vid.aai.util.AAITreeConverter.VNF_TYPE; import java.util.HashMap; import java.util.Map; -import static org.onap.vid.aai.util.AAITreeConverter.VNF_TYPE; - public class Vnf extends Node { private Map> vfModules = new HashMap<>(); private Map networks = new HashMap<>(); public Vnf(AAITreeNode node) { - super(node, AAITreeConverter.ModelType.vnf); + super(node); + fillCloudConfigurationProperties(this, node.getCloudConfiguration()); } public Map> getVfModules() { @@ -60,11 +58,11 @@ public class Vnf extends Node { } node.getChildren().forEach(child -> { - if (child.getType().equals(AAITreeNodeBuilder.VF_MODULE)) { + if (child.getType() == NodeType.VF_MODULE) { vnf.getVfModules().putIfAbsent(child.getNodeKey(), new HashMap<>()); vnf.getVfModules().get(child.getNodeKey()) - .put(child.getUniqueNodeKey(), VfModule.from(child)); - } else if (child.getType().equals(AAITreeNodeBuilder.NETWORK)) { + .put(child.getUniqueNodeKey(), VfModule.from(child)); + } else if (child.getType() == NodeType.NETWORK) { vnf.getNetworks().put(child.getUniqueNodeKey(), Network.from(child)); } }); diff --git a/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/VnfGroup.java b/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/VnfGroup.java deleted file mode 100644 index 21e5ca45e..000000000 --- a/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/VnfGroup.java +++ /dev/null @@ -1,72 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * VID - * ================================================================================ - * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * 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.vid.model.aaiTree; - -import org.onap.vid.aai.util.AAITreeConverter; - - -public class VnfGroup extends Node { - - public static final String INSTANCE_GROUP_TYPE = "instance-group-type"; - public static final String INSTANCE_GROUP_ROLE = "instance-group-role"; - public static final String INSTANCE_GROUP_FUNCTION = "instance-group-function"; - - private String instanceGroupRole; - private String instanceGroupFunction; - - - public VnfGroup(AAITreeNode node) { - super(node, AAITreeConverter.ModelType.instanceGroup); - } - - public static VnfGroup from(AAITreeNode node) { - VnfGroup vnfGroup = new VnfGroup(node); - if (node.getAdditionalProperties().get(INSTANCE_GROUP_TYPE) != null) { - vnfGroup.setInstanceType(node.getAdditionalProperties().get(INSTANCE_GROUP_TYPE).toString()); - } - if (node.getAdditionalProperties().get(INSTANCE_GROUP_FUNCTION) != null) { - vnfGroup.setInstanceGroupFunction(node.getAdditionalProperties().get(INSTANCE_GROUP_FUNCTION).toString()); - } - if (node.getAdditionalProperties().get(INSTANCE_GROUP_ROLE) != null) { - vnfGroup.setInstanceGroupRole(node.getAdditionalProperties().get(INSTANCE_GROUP_ROLE).toString()); - } - - return vnfGroup; - } - - public String getInstanceGroupRole() { - return instanceGroupRole; - } - - public void setInstanceGroupRole(String instanceGroupRole) { - this.instanceGroupRole = instanceGroupRole; - } - - public String getInstanceGroupFunction() { - return instanceGroupFunction; - } - - public void setInstanceGroupFunction(String instanceGroupFunction) { - this.instanceGroupFunction = instanceGroupFunction; - } - - -} diff --git a/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/VnfGroup.kt b/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/VnfGroup.kt new file mode 100644 index 000000000..47a6c98be --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/VnfGroup.kt @@ -0,0 +1,10 @@ +package org.onap.vid.model.aaiTree + +class VnfGroup(node: AAITreeNode) : InstanceGroup(node) { + + val vnfs: Map = node.children + .filter { it.type == NodeType.GENERIC_VNF } + .map { it.uniqueNodeKey to RelatedVnf.from(it) } + .toMap() + +} \ No newline at end of file diff --git a/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/VpnBinding.kt b/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/VpnBinding.kt new file mode 100644 index 000000000..d43bf26f0 --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/VpnBinding.kt @@ -0,0 +1,50 @@ +package org.onap.vid.model.aaiTree + +import com.fasterxml.jackson.annotation.JsonAlias +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonIgnoreProperties +import com.fasterxml.jackson.annotation.JsonInclude +import com.fasterxml.jackson.core.type.TypeReference +import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate +import org.onap.vid.utils.JACKSON_OBJECT_MAPPER + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +class VpnBinding(aaiNode: AAITreeNode) : Node(aaiNode) { + @JsonCreator + constructor() : this(AAITreeNode()) + var region: String? = null + var customerId: String? = null + var routeTargets: List? = null +} + +val LOGGER: EELFLoggerDelegate = EELFLoggerDelegate.getLogger(VpnBinding::class.java) + +fun from(node: AAITreeNode): VpnBinding { + val vpnBinding = VpnBinding(node) + vpnBinding.platformName = Node.readValueAsStringFromAdditionalProperties(node, "vpn-platform") + vpnBinding.instanceType = Node.readValueAsStringFromAdditionalProperties(node, "vpn-type") + vpnBinding.region = Node.readValueAsStringFromAdditionalProperties(node, "vpn-region") + vpnBinding.customerId = Node.readValueAsStringFromAdditionalProperties(node, "customer-vpn-id") + + vpnBinding.routeTargets = try { + JACKSON_OBJECT_MAPPER.convertValue( + node.additionalProperties.getOrDefault("route-targets", emptyList()), + object : TypeReference>() {}) + } catch (exception: Exception) { + LOGGER.error("Failed to parse route-targets of vpn with id:${vpnBinding.instanceId}", exception) + listOf(RouteTarget("ParsingFailure", "ParsingFailure")) + } + + return vpnBinding +} + +@JsonIgnoreProperties(ignoreUnknown = true) +data class RouteTarget( + + @JsonAlias("global-route-target") + val globalRouteTarget: String? = null, + + @JsonAlias("route-target-role") + val routeTargetRole: String? = null +) diff --git a/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/Vrf.java b/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/Vrf.java new file mode 100644 index 000000000..d6ef7ab0e --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/Vrf.java @@ -0,0 +1,65 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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.vid.model.aaiTree; + +import java.util.HashMap; +import java.util.Map; + +public class Vrf extends Node { + + private Map networks = new HashMap<>(); + private Map vpns = new HashMap<>(); + + + public Vrf(AAITreeNode node){ + super(node); + } + + public static Vrf from(AAITreeNode node) { + Vrf vrf = new Vrf(node); + + node.getChildren().forEach(child -> { + if (child.getType() == NodeType.NETWORK) { + vrf.getNetworks().put(child.getUniqueNodeKey(), Network.from(child)); + } + if (child.getType() == NodeType.VPN_BINDING) { + vrf.getVpns().put(child.getUniqueNodeKey(), VpnBindingKt.from(child)); + } + }); + return vrf; + } + + public Map getNetworks() { + return networks; + } + + public void setNetworks(Map networks) { + this.networks = networks; + } + + public Map getVpns() { + return vpns; + } + + public void setVpns(Map vpns) { + this.vpns = vpns; + } +} diff --git a/vid-app-common/src/main/java/org/onap/vid/model/errorReport/ReportCreationParameters.java b/vid-app-common/src/main/java/org/onap/vid/model/errorReport/ReportCreationParameters.java index babbf8906..e7b7fa67d 100644 --- a/vid-app-common/src/main/java/org/onap/vid/model/errorReport/ReportCreationParameters.java +++ b/vid-app-common/src/main/java/org/onap/vid/model/errorReport/ReportCreationParameters.java @@ -17,6 +17,7 @@ * limitations under the License. * ============LICENSE_END========================================================= */ + package org.onap.vid.model.errorReport; public class ReportCreationParameters { diff --git a/vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/BaseResource.java b/vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/BaseResource.java index fe9ebc037..926dc3cdc 100644 --- a/vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/BaseResource.java +++ b/vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/BaseResource.java @@ -7,9 +7,9 @@ * 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. @@ -20,25 +20,29 @@ package org.onap.vid.model.serviceInstantiation; +import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.common.collect.ImmutableMap; import org.apache.commons.lang3.StringUtils; import org.onap.vid.job.JobAdapter; +import org.onap.vid.job.JobType; import org.onap.vid.model.Action; import org.onap.vid.mso.model.ModelInfo; +import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; public abstract class BaseResource implements JobAdapter.AsyncJobRequest { - protected final String instanceId; + protected String instanceId; + protected ModelInfo modelInfo; protected String instanceName; - protected final Action action; + protected Action action; protected String lcpCloudRegionId; @@ -48,13 +52,21 @@ public abstract class BaseResource implements JobAdapter.AsyncJobRequest { protected boolean rollbackOnFailure; - private static final Map actionStingToEnumMap = ImmutableMap.of( - "Delete", Action.Delete, - "Create", Action.Create, - "None", Action.None, - "Update_Delete", Action.Delete, - "None_Delete", Action.Delete - ); + protected String trackById; + + protected Boolean isFailed; + + protected String statusMessage; + + private static final Map actionStingToEnumMap = ImmutableMap.builder() + .put("Delete", Action.Delete) + .put("Create", Action.Create) + .put("None", Action.None) + .put("Update_Delete", Action.Delete) + .put("None_Delete", Action.Delete) + .put("Resume", Action.Resume) + .put("Replace", Action.Replace) + .build(); protected BaseResource(@JsonProperty("modelInfo") ModelInfo modelInfo, @@ -65,16 +77,22 @@ public abstract class BaseResource implements JobAdapter.AsyncJobRequest { @JsonProperty("tenantId") String tenantId, @JsonProperty("instanceParams") List> instanceParams, @JsonProperty("rollbackOnFailure") boolean rollbackOnFailure, - @JsonProperty("instanceId") String instanceId) { + @JsonProperty("instanceId") String instanceId, + @JsonProperty("trackById") String trackById, + @JsonProperty("isFailed") Boolean isFailed, + @JsonProperty("statusMessage") String statusMessage) { this.modelInfo = modelInfo; this.modelInfo.setModelType(getModelType()); this.rollbackOnFailure = rollbackOnFailure; - this.instanceName = StringUtils.defaultString(instanceName, "");; + this.instanceName = StringUtils.defaultString(instanceName, ""); this.action = actionStringToEnum(action); this.lcpCloudRegionId = StringUtils.isNotEmpty(legacyRegion) ? legacyRegion : lcpCloudRegionId; this.tenantId = tenantId; this.instanceParams = instanceParams; this.instanceId = instanceId; + this.trackById = trackById; + this.isFailed = isFailed!= null ? isFailed: false; + this.statusMessage = statusMessage; } private Action actionStringToEnum(String actionAsString) { @@ -90,7 +108,7 @@ public abstract class BaseResource implements JobAdapter.AsyncJobRequest { } public Action getAction() { - return action; + return (action == null ? Action.Create : action); } public String getLcpCloudRegionId() { @@ -105,11 +123,49 @@ public abstract class BaseResource implements JobAdapter.AsyncJobRequest { return instanceParams == null ? Collections.emptyList() : instanceParams; } - public boolean isRollbackOnFailure() { return rollbackOnFailure; } + public boolean isRollbackOnFailure() { return rollbackOnFailure; } public String getInstanceId() { return instanceId; } protected abstract String getModelType(); + + public String getTrackById() { + return trackById; + } + + public void setTrackById(String trackById) { + this.trackById = trackById; + } + + public Boolean getIsFailed() { + return isFailed; + } + + public void setIsFailed(Boolean isFailed) { + this.isFailed = isFailed; + } + + public void setInstanceId(String instanceId) { + this.instanceId = instanceId; + } + + public void setAction(Action action) { + this.action = action; + } + + public String getStatusMessage() { + return statusMessage; + } + + public void setStatusMessage(String statusMessage) { + this.statusMessage = statusMessage; + } + + @JsonIgnore + public abstract Collection getChildren(); + + @JsonIgnore + public abstract JobType getJobType(); } diff --git a/vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/InstanceGroup.java b/vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/InstanceGroup.java index 3fda8429b..b945f1327 100644 --- a/vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/InstanceGroup.java +++ b/vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/InstanceGroup.java @@ -7,9 +7,9 @@ * 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. @@ -22,21 +22,47 @@ package org.onap.vid.model.serviceInstantiation; import com.fasterxml.jackson.annotation.JsonProperty; import org.onap.vid.job.JobAdapter; +import org.onap.vid.job.JobType; import org.onap.vid.mso.model.ModelInfo; +import java.util.Collection; +import java.util.Collections; +import java.util.Map; + public class InstanceGroup extends BaseResource implements JobAdapter.AsyncJobRequest { + private final Map vnfGroupMembers; + public InstanceGroup(@JsonProperty("modelInfo") ModelInfo modelInfo, @JsonProperty("instanceName") String instanceName, @JsonProperty("action") String action, @JsonProperty("rollbackOnFailure") boolean rollbackOnFailure, - @JsonProperty("instanceId") String instanceId) { + @JsonProperty("instanceId") String instanceId, + @JsonProperty("vnfs") Map vnfGroupMembers, + @JsonProperty("trackById") String trackById, + @JsonProperty("isFailed") Boolean isFailed, + @JsonProperty("statusMessage") String statusMessage) { - super(modelInfo, instanceName, action, null, null, null, null, rollbackOnFailure, instanceId); + super(modelInfo, instanceName, action, null, null, null, null, rollbackOnFailure, instanceId, trackById, isFailed, statusMessage); + this.vnfGroupMembers = vnfGroupMembers; } @Override protected String getModelType() { return "instanceGroup"; } + + @Override + public Collection getChildren() { + return getVnfGroupMembers().values(); + } + + public Map getVnfGroupMembers() { + return vnfGroupMembers == null ? Collections.emptyMap() : vnfGroupMembers; + } + + @Override + public JobType getJobType() { + return JobType.InstanceGroup; + } } diff --git a/vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/InstanceGroupMember.java b/vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/InstanceGroupMember.java new file mode 100644 index 000000000..7bfaf02b1 --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/InstanceGroupMember.java @@ -0,0 +1,54 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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.vid.model.serviceInstantiation; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.Collection; +import java.util.Collections; +import org.onap.vid.job.JobAdapter; +import org.onap.vid.job.JobType; +import org.onap.vid.mso.model.ModelInfo; + +public class InstanceGroupMember extends BaseResource implements JobAdapter.AsyncJobRequest{ + + public InstanceGroupMember(@JsonProperty("instanceId") String instanceId, + @JsonProperty("action") String action, + @JsonProperty("trackById") String trackById, + @JsonProperty("isFailed") Boolean isFailed, + @JsonProperty("statusMessage") String statusMessage) { + super(new ModelInfo(), null, action, null, null, null, null, false, instanceId, trackById, isFailed, statusMessage); + } + + @Override + protected String getModelType() { + return "vnf"; + } + + @Override + public Collection getChildren() { + return Collections.emptyList(); + } + + @Override + public JobType getJobType() { + return JobType.InstanceGroupMember; + } +} diff --git a/vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/Network.java b/vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/Network.java index addd7e1ee..797e28a02 100644 --- a/vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/Network.java +++ b/vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/Network.java @@ -2,14 +2,14 @@ * ============LICENSE_START======================================================= * VID * ================================================================================ - * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. * ================================================================================ * 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. @@ -22,8 +22,11 @@ package org.onap.vid.model.serviceInstantiation; import com.fasterxml.jackson.annotation.JsonProperty; import org.onap.vid.job.JobAdapter; +import org.onap.vid.job.JobType; import org.onap.vid.mso.model.ModelInfo; +import java.util.Collection; +import java.util.Collections; import java.util.List; import java.util.Map; @@ -36,19 +39,22 @@ public class Network extends BaseResource implements JobAdapter.AsyncJobRequest private final String lineOfBusiness; public Network(@JsonProperty("modelInfo") ModelInfo modelInfo, - @JsonProperty("productFamilyId") String productFamilyId, - @JsonProperty("instanceName") String instanceName, + @JsonProperty("productFamilyId") String productFamilyId, + @JsonProperty("instanceName") String instanceName, @JsonProperty("action") String action, - @JsonProperty("platformName") String platformName, - @JsonProperty("lcpCloudRegionId") String lcpCloudRegionId, + @JsonProperty("platformName") String platformName, + @JsonProperty("lcpCloudRegionId") String lcpCloudRegionId, @JsonProperty("legacyRegion") String legacyRegion, - @JsonProperty("tenantId") String tenantId, - @JsonProperty("instanceParams") List> instanceParams, - @JsonProperty("lineOfBusinessName") String lineOfBusiness, - @JsonProperty("rollbackOnFailure") boolean rollbackOnFailure, - @JsonProperty("instanceId") String instanceId) { + @JsonProperty("tenantId") String tenantId, + @JsonProperty("instanceParams") List> instanceParams, + @JsonProperty("lineOfBusinessName") String lineOfBusiness, + @JsonProperty("rollbackOnFailure") boolean rollbackOnFailure, + @JsonProperty("instanceId") String instanceId, + @JsonProperty("trackById") String trackById, + @JsonProperty("isFailed") Boolean isFailed, + @JsonProperty("statusMessage") String statusMessage) { - super(modelInfo, instanceName, action, lcpCloudRegionId, legacyRegion, tenantId, instanceParams, rollbackOnFailure, instanceId); + super(modelInfo, instanceName, action, lcpCloudRegionId, legacyRegion, tenantId, instanceParams, rollbackOnFailure, instanceId, trackById, isFailed, statusMessage); this.productFamilyId = productFamilyId; this.platformName = platformName; this.lineOfBusiness = lineOfBusiness; @@ -71,4 +77,14 @@ public class Network extends BaseResource implements JobAdapter.AsyncJobRequest return "network"; } + @Override + public Collection getChildren() { + return Collections.emptyList(); + } + + @Override + public JobType getJobType() { + return JobType.NetworkInstantiation; + } + } diff --git a/vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/ServiceInstantiation.java b/vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/ServiceInstantiation.java index 5d963134b..afc8534a1 100644 --- a/vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/ServiceInstantiation.java +++ b/vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/ServiceInstantiation.java @@ -7,9 +7,9 @@ * 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. @@ -21,12 +21,18 @@ package org.onap.vid.model.serviceInstantiation; import com.fasterxml.jackson.annotation.JsonProperty; +import org.apache.commons.lang3.ObjectUtils; import org.onap.vid.job.JobAdapter; +import org.onap.vid.job.JobType; +import org.onap.vid.model.VidNotions; import org.onap.vid.mso.model.ModelInfo; +import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.Stream; public class ServiceInstantiation extends BaseResource implements JobAdapter.AsyncJobRequest { @@ -58,12 +64,15 @@ public class ServiceInstantiation extends BaseResource implements JobAdapter.Asy private final boolean isPause; - private final int bulkSize; + private int bulkSize; private final String testApi; private final boolean isALaCarte; + private final VidNotions vidNotions; + private Map vrfs; + public ServiceInstantiation(@JsonProperty("modelInfo") ModelInfo modelInfo, @JsonProperty("owningEntityId") String owningEntityId, @JsonProperty("owningEntityName") String owningEntityName, @@ -82,6 +91,7 @@ public class ServiceInstantiation extends BaseResource implements JobAdapter.Asy @JsonProperty("vnfs") Map vnfs, @JsonProperty("networks") Map networks, @JsonProperty("vnfGroups") Map vnfGroups, + @JsonProperty("vrfs") Map vrfs, @JsonProperty("instanceParams") List> instanceParams, @JsonProperty("pause") boolean isPause, @JsonProperty("bulkSize") int bulkSize, @@ -89,9 +99,12 @@ public class ServiceInstantiation extends BaseResource implements JobAdapter.Asy @JsonProperty("isALaCarte") boolean isALaCarte, @JsonProperty("testApi") String testApi, @JsonProperty("instanceId") String instanceId, - @JsonProperty("action") String action - ) { - super(modelInfo, instanceName, action, lcpCloudRegionId, legacyRegion, tenantId, instanceParams, rollbackOnFailure, instanceId); + @JsonProperty("action") String action, + @JsonProperty("trackById") String trackById, + @JsonProperty("isFailed") Boolean isFailed, + @JsonProperty("statusMessage") String statusMessage, + @JsonProperty("vidNotions") VidNotions vidNotions) { + super(modelInfo, instanceName, action, lcpCloudRegionId, legacyRegion, tenantId, instanceParams, rollbackOnFailure, instanceId, trackById, isFailed, statusMessage); this.owningEntityId = owningEntityId; this.owningEntityName = owningEntityName; this.projectName = projectName; @@ -105,12 +118,15 @@ public class ServiceInstantiation extends BaseResource implements JobAdapter.Asy this.vnfs = vnfs; this.networks = networks; this.vnfGroups = vnfGroups; + this.vrfs = vrfs; this.isPause = isPause; this.bulkSize = bulkSize; this.isALaCarte = isALaCarte; this.testApi = isALaCarte ? testApi : null; + this.vidNotions = vidNotions; } + public String getOwningEntityId() { return owningEntityId; } @@ -152,15 +168,19 @@ public class ServiceInstantiation extends BaseResource implements JobAdapter.Asy } public Map getVnfs() { - return vnfs == null ? Collections.emptyMap() : vnfs; + return emptyMapIfNull(vnfs); } public Map getNetworks() { - return networks == null ? Collections.emptyMap() : networks; + return emptyMapIfNull(networks); } public Map getVnfGroups() { - return vnfGroups == null ? Collections.emptyMap() : vnfGroups; + return emptyMapIfNull(vnfGroups); + } + + public Map getVrfs() { + return emptyMapIfNull(vrfs); } public boolean isPause() { @@ -169,11 +189,24 @@ public class ServiceInstantiation extends BaseResource implements JobAdapter.Asy public int getBulkSize() { return bulkSize; } + public void setBulkSize(int bulkSize) { + this.bulkSize = bulkSize; + } + + public VidNotions getVidNotions() { + return vidNotions; + } + @Override protected String getModelType() { return "service"; } + @Override + public Collection getChildren() { + return Stream.of(getNetworks().values(), getVnfs().values(), getVnfGroups().values()).flatMap(Collection::stream).collect(Collectors.toList()); + } + @JsonProperty("isALaCarte") public boolean isALaCarte() { return isALaCarte; @@ -183,4 +216,13 @@ public class ServiceInstantiation extends BaseResource implements JobAdapter.Asy return this.testApi; } -} + @Override + public JobType getJobType() { + return JobType.ALaCarteService; + } + + private Map emptyMapIfNull(Map map) { + return ObjectUtils.defaultIfNull(map, Collections.emptyMap()); + } + +} \ No newline at end of file diff --git a/vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/VfModule.java b/vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/VfModule.java index b56f116cd..97b23af20 100644 --- a/vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/VfModule.java +++ b/vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/VfModule.java @@ -2,14 +2,14 @@ * ============LICENSE_START======================================================= * VID * ================================================================================ - * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. * ================================================================================ * 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. @@ -23,8 +23,11 @@ package org.onap.vid.model.serviceInstantiation; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import org.onap.vid.job.JobAdapter; +import org.onap.vid.job.JobType; import org.onap.vid.mso.model.ModelInfo; +import java.util.Collection; +import java.util.Collections; import java.util.List; import java.util.Map; @@ -37,22 +40,25 @@ import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL; public class VfModule extends BaseResource implements JobAdapter.AsyncJobRequest { @JsonInclude(NON_NULL) private final String volumeGroupInstanceName; - private boolean usePreload; + @JsonInclude(NON_NULL) private Boolean usePreload; private Map supplementaryParams; public VfModule( @JsonProperty("modelInfo") ModelInfo modelInfo, - @JsonProperty("instanceName") String instanceName, - @JsonProperty("volumeGroupName") String volumeGroupInstanceName, + @JsonProperty("instanceName") String instanceName, + @JsonProperty("volumeGroupName") String volumeGroupInstanceName, @JsonProperty("action") String action, - @JsonProperty("lcpCloudRegionId") String lcpCloudRegionId, - @JsonProperty("legacyRegion") String legacyRegion, - @JsonProperty("tenantId") String tenantId, - @JsonProperty("instanceParams") List> instanceParams, - @JsonProperty("supplementaryFileContent") Map supplementaryParams, - @JsonProperty("rollbackOnFailure") boolean rollbackOnFailure, - @JsonProperty("sdncPreLoad") boolean usePreload, - @JsonProperty("instanceId") String instanceId) { - super(modelInfo, instanceName, action, lcpCloudRegionId, legacyRegion, tenantId, instanceParams, rollbackOnFailure, instanceId); + @JsonProperty("lcpCloudRegionId") String lcpCloudRegionId, + @JsonProperty("legacyRegion") String legacyRegion, + @JsonProperty("tenantId") String tenantId, + @JsonProperty("instanceParams") List> instanceParams, + @JsonProperty("supplementaryFileContent") Map supplementaryParams, + @JsonProperty("rollbackOnFailure") boolean rollbackOnFailure, + @JsonProperty("sdncPreLoad") Boolean usePreload, + @JsonProperty("instanceId") String instanceId, + @JsonProperty("trackById") String trackById, + @JsonProperty("isFailed") Boolean isFailed, + @JsonProperty("statusMessage") String statusMessage) { + super(modelInfo, instanceName, action, lcpCloudRegionId, legacyRegion, tenantId, instanceParams, rollbackOnFailure, instanceId, trackById, isFailed, statusMessage); this.volumeGroupInstanceName = volumeGroupInstanceName; this.usePreload = usePreload; this.supplementaryParams = supplementaryParams; @@ -62,7 +68,8 @@ public class VfModule extends BaseResource implements JobAdapter.AsyncJobRequest return volumeGroupInstanceName; } - public boolean isUsePreload() { + public Boolean isUsePreload() { + return usePreload; } @@ -75,5 +82,13 @@ public class VfModule extends BaseResource implements JobAdapter.AsyncJobRequest return "vfModule"; } + @Override + public Collection getChildren() { + return Collections.emptyList(); + } -} + @Override + public JobType getJobType() { + return JobType.VfmoduleInstantiation; + } +} \ No newline at end of file diff --git a/vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/Vnf.java b/vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/Vnf.java index 2619533a7..0da3f0695 100644 --- a/vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/Vnf.java +++ b/vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/Vnf.java @@ -2,14 +2,14 @@ * ============LICENSE_START======================================================= * VID * ================================================================================ - * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. * ================================================================================ * 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. @@ -23,10 +23,12 @@ package org.onap.vid.model.serviceInstantiation; import com.fasterxml.jackson.annotation.JsonProperty; import org.onap.vid.job.JobAdapter; +import org.onap.vid.job.JobType; import org.onap.vid.mso.model.ModelInfo; -import java.util.List; -import java.util.Map; +import java.util.*; + +import static java.util.stream.Collectors.toList; /** * The Class VNF. @@ -42,24 +44,27 @@ public class Vnf extends BaseResource implements JobAdapter.AsyncJobRequest { private final Map> vfModules; public Vnf(@JsonProperty("modelInfo") ModelInfo modelInfo, - @JsonProperty("productFamilyId") String productFamilyId, - @JsonProperty("instanceName") String instanceName, + @JsonProperty("productFamilyId") String productFamilyId, + @JsonProperty("instanceName") String instanceName, @JsonProperty("action") String action, - @JsonProperty("platformName") String platformName, - @JsonProperty("lcpCloudRegionId") String lcpCloudRegionId, - @JsonProperty("legacyRegion") String legacyRegion, - @JsonProperty("tenantId") String tenantId, - @JsonProperty("instanceParams") List> instanceParams, - @JsonProperty("lineOfBusinessName") String lineOfBusiness, - @JsonProperty("rollbackOnFailure") boolean rollbackOnFailure, + @JsonProperty("platformName") String platformName, + @JsonProperty("lcpCloudRegionId") String lcpCloudRegionId, + @JsonProperty("legacyRegion") String legacyRegion, + @JsonProperty("tenantId") String tenantId, + @JsonProperty("instanceParams") List> instanceParams, + @JsonProperty("lineOfBusinessName") String lineOfBusiness, + @JsonProperty("rollbackOnFailure") boolean rollbackOnFailure, @JsonProperty("instanceId") String instanceId, - @JsonProperty("vfModules") Map> vfModules) { + @JsonProperty("vfModules") Map> vfModules, + @JsonProperty("trackById") String trackById, + @JsonProperty("isFailed") Boolean isFailed, + @JsonProperty("statusMessage") String statusMessage) { - super(modelInfo, instanceName, action, lcpCloudRegionId, legacyRegion, tenantId, instanceParams, rollbackOnFailure, instanceId); + super(modelInfo, instanceName, action, lcpCloudRegionId, legacyRegion, tenantId, instanceParams, rollbackOnFailure, instanceId, trackById, isFailed, statusMessage); this.productFamilyId = productFamilyId; this.platformName = platformName; this.lineOfBusiness = lineOfBusiness; - this.vfModules = vfModules; + this.vfModules = vfModules==null ? Collections.emptyMap() : vfModules; } public String getProductFamilyId() { @@ -82,4 +87,17 @@ public class Vnf extends BaseResource implements JobAdapter.AsyncJobRequest { protected String getModelType() { return "vnf"; } + + @Override + public Collection getChildren() { + return getVfModules().values().stream() + .filter(Objects::nonNull) + .flatMap(x->x.values().stream()) + .collect(toList()); + } + + @Override + public JobType getJobType() { + return JobType.VnfInstantiation; + } } diff --git a/vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/VrfEntry.kt b/vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/VrfEntry.kt new file mode 100644 index 000000000..5c9ac9095 --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/VrfEntry.kt @@ -0,0 +1,6 @@ +package org.onap.vid.model.serviceInstantiation + +import org.onap.vid.model.aaiTree.Network +import org.onap.vid.model.aaiTree.VpnBinding + +data class VrfEntry(val networks: Map, val vpns: Map) diff --git a/vid-app-common/src/main/java/org/onap/vid/mso/MsoBusinessLogic.java b/vid-app-common/src/main/java/org/onap/vid/mso/MsoBusinessLogic.java index cc3231582..949fdab70 100644 --- a/vid-app-common/src/main/java/org/onap/vid/mso/MsoBusinessLogic.java +++ b/vid-app-common/src/main/java/org/onap/vid/mso/MsoBusinessLogic.java @@ -21,10 +21,11 @@ package org.onap.vid.mso; +import java.util.List; +import java.util.UUID; import org.onap.vid.changeManagement.RequestDetailsWrapper; import org.onap.vid.changeManagement.WorkflowRequestDetail; import org.onap.vid.controller.OperationalEnvironmentController; -import org.onap.vid.services.ProbeInterface; import org.onap.vid.model.SOWorkflowList; import org.onap.vid.model.SoftDeleteRequest; import org.onap.vid.mso.model.OperationalEnvironmentActivateInfo; @@ -33,9 +34,7 @@ import org.onap.vid.mso.rest.OperationalEnvironment.OperationEnvironmentRequestD import org.onap.vid.mso.rest.Request; import org.onap.vid.mso.rest.RequestDetails; import org.onap.vid.mso.rest.Task; - -import java.util.List; -import java.util.UUID; +import org.onap.vid.services.ProbeInterface; public interface MsoBusinessLogic extends ProbeInterface { @@ -137,9 +136,5 @@ public interface MsoBusinessLogic extends ProbeInterface { RequestDetails buildRequestDetailsForSoftDelete(SoftDeleteRequest softDeleteRequest); - MsoResponseWrapper2 deactivateAndCloudDelete(String serviceInstanceId, String vnfInstanceId, String vfModuleInstanceId, RequestDetails requestDetails); - - MsoResponseWrapper2 activateFabricConfiguration(String serviceInstanceId, RequestDetails requestDetails); - SOWorkflowList getWorkflowListByModelId(String modelVersionId); } diff --git a/vid-app-common/src/main/java/org/onap/vid/mso/MsoBusinessLogicImpl.java b/vid-app-common/src/main/java/org/onap/vid/mso/MsoBusinessLogicImpl.java index 4cb495e2f..9146e8f1b 100644 --- a/vid-app-common/src/main/java/org/onap/vid/mso/MsoBusinessLogicImpl.java +++ b/vid-app-common/src/main/java/org/onap/vid/mso/MsoBusinessLogicImpl.java @@ -20,6 +20,24 @@ */ package org.onap.vid.mso; +import static com.fasterxml.jackson.module.kotlin.ExtensionsKt.jacksonObjectMapper; +import static java.util.stream.Collectors.collectingAndThen; +import static java.util.stream.Collectors.toList; +import static org.apache.commons.lang.StringUtils.upperCase; +import static org.onap.vid.changeManagement.ChangeManagementRequest.MsoChangeManagementRequest; +import static org.onap.vid.controller.MsoController.CONFIGURATION_ID; +import static org.onap.vid.controller.MsoController.REQUEST_TYPE; +import static org.onap.vid.controller.MsoController.SVC_INSTANCE_ID; +import static org.onap.vid.controller.MsoController.VNF_INSTANCE_ID; +import static org.onap.vid.controller.MsoController.WORKFLOW_ID; +import static org.onap.vid.mso.MsoProperties.MSO_REST_API_CLOUD_RESOURCES_REQUEST_STATUS; +import static org.onap.vid.mso.MsoProperties.MSO_REST_API_OPERATIONAL_ENVIRONMENT_ACTIVATE; +import static org.onap.vid.mso.MsoProperties.MSO_REST_API_OPERATIONAL_ENVIRONMENT_CREATE; +import static org.onap.vid.mso.MsoProperties.MSO_REST_API_OPERATIONAL_ENVIRONMENT_DEACTIVATE; +import static org.onap.vid.mso.MsoProperties.MSO_REST_API_WORKFLOW_SPECIFICATIONS; +import static org.onap.vid.utils.KotlinUtilsKt.JACKSON_OBJECT_MAPPER; +import static org.onap.vid.utils.Logging.debugRequestDetails; + import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonValue; import com.fasterxml.jackson.databind.DeserializationFeature; @@ -27,6 +45,18 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import io.joshworks.restclient.http.HttpResponse; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.UUID; +import java.util.regex.Pattern; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import javax.ws.rs.BadRequestException; import org.apache.commons.collections4.ListUtils; import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; import org.onap.portalsdk.core.util.SystemProperties; @@ -35,7 +65,6 @@ import org.onap.vid.changeManagement.RequestDetailsWrapper; import org.onap.vid.changeManagement.WorkflowRequestDetail; import org.onap.vid.controller.OperationalEnvironmentController; import org.onap.vid.exceptions.GenericUncheckedException; -import org.onap.vid.model.RequestReferencesContainer; import org.onap.vid.model.SOWorkflowList; import org.onap.vid.model.SoftDeleteRequest; import org.onap.vid.model.probes.ExternalComponentStatus; @@ -58,37 +87,6 @@ import org.onap.vid.mso.rest.TaskList; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; -import org.togglz.core.manager.FeatureManager; - -import javax.ws.rs.BadRequestException; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.UUID; -import java.util.regex.Pattern; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import static java.util.stream.Collectors.collectingAndThen; -import static java.util.stream.Collectors.toList; -import static org.apache.commons.lang.StringUtils.upperCase; -import static org.onap.vid.changeManagement.ChangeManagementRequest.MsoChangeManagementRequest; -import static org.onap.vid.controller.MsoController.CONFIGURATION_ID; -import static org.onap.vid.controller.MsoController.REQUEST_TYPE; -import static org.onap.vid.controller.MsoController.SVC_INSTANCE_ID; -import static org.onap.vid.controller.MsoController.VNF_INSTANCE_ID; -import static org.onap.vid.controller.MsoController.WORKFLOW_ID; -import static org.onap.vid.mso.MsoProperties.MSO_REST_API_CLOUD_RESOURCES_REQUEST_STATUS; -import static org.onap.vid.mso.MsoProperties.MSO_REST_API_OPERATIONAL_ENVIRONMENT_ACTIVATE; -import static org.onap.vid.mso.MsoProperties.MSO_REST_API_OPERATIONAL_ENVIRONMENT_CREATE; -import static org.onap.vid.mso.MsoProperties.MSO_REST_API_OPERATIONAL_ENVIRONMENT_DEACTIVATE; -import static org.onap.vid.mso.MsoProperties.MSO_REST_API_WORKFLOW_SPECIFICATIONS; -import static org.onap.vid.properties.Features.FLAG_UNASSIGN_SERVICE; -import static org.onap.vid.utils.Logging.debugRequestDetails; public class MsoBusinessLogicImpl implements MsoBusinessLogic { @@ -120,12 +118,10 @@ public class MsoBusinessLogicImpl implements MsoBusinessLogic { * This should be replaced with mso client factory. */ private final MsoInterface msoClientInterface; - FeatureManager featureManager; @Autowired - public MsoBusinessLogicImpl(MsoInterface msoClientInterface, FeatureManager featureManager) { + public MsoBusinessLogicImpl(MsoInterface msoClientInterface) { this.msoClientInterface = msoClientInterface; - this.featureManager = featureManager; } public static String validateEndpointPath(String endpointEnvVariable) { @@ -168,17 +164,19 @@ public class MsoBusinessLogicImpl implements MsoBusinessLogic { public MsoResponseWrapper createNwInstance(RequestDetails requestDetails, String serviceInstanceId) { logInvocationInDebug("createNwInstance"); - String endpoint = validateEndpointPath(MsoProperties.MSO_REST_API_NETWORK_INSTANCE); + String endpoint; + endpoint = validateEndpointPath(MsoProperties.MSO_REST_API_NETWORK_INSTANCE); - String nw_endpoint = endpoint.replaceFirst(SVC_INSTANCE_ID, serviceInstanceId); - return msoClientInterface.createNwInstance(requestDetails, nw_endpoint); + String nwEndpoint = endpoint.replaceFirst(SVC_INSTANCE_ID, serviceInstanceId); + return msoClientInterface.createNwInstance(requestDetails, nwEndpoint); } @Override public MsoResponseWrapper createVolumeGroupInstance(RequestDetails requestDetails, String serviceInstanceId, String vnfInstanceId) { logInvocationInDebug("createVolumeGroupInstance"); - String endpoint = validateEndpointPath(MsoProperties.MSO_REST_API_VOLUME_GROUP_INSTANCE); + String endpoint; + endpoint = validateEndpointPath(MsoProperties.MSO_REST_API_VOLUME_GROUP_INSTANCE); String vnfEndpoint = endpoint.replaceFirst(SVC_INSTANCE_ID, serviceInstanceId); vnfEndpoint = vnfEndpoint.replaceFirst(VNF_INSTANCE_ID, vnfInstanceId); @@ -192,10 +190,10 @@ public class MsoBusinessLogicImpl implements MsoBusinessLogic { String endpoint = validateEndpointPath(MsoProperties.MSO_REST_API_VF_MODULE_INSTANCE); - String partial_endpoint = endpoint.replaceFirst(SVC_INSTANCE_ID, serviceInstanceId); - String vf_module_endpoint = partial_endpoint.replaceFirst(VNF_INSTANCE_ID, vnfInstanceId); + String partialEndpoint = endpoint.replaceFirst(SVC_INSTANCE_ID, serviceInstanceId); + String vfModuleEndpoint = partialEndpoint.replaceFirst(VNF_INSTANCE_ID, vnfInstanceId); - return msoClientInterface.createVfModuleInstance(requestDetails, vf_module_endpoint); + return msoClientInterface.createVfModuleInstance(requestDetails, vfModuleEndpoint); } @Override @@ -259,19 +257,15 @@ public class MsoBusinessLogicImpl implements MsoBusinessLogic { logInvocationInDebug("deleteSvcInstance"); String endpoint; - if (featureManager.isActive(FLAG_UNASSIGN_SERVICE)) { - endpoint = validateEndpointPath(MsoProperties.MSO_DELETE_OR_UNASSIGN_REST_API_SVC_INSTANCE); - if (shouldUnassignService(serviceStatus)) { - logger.debug(EELFLoggerDelegate.debugLogger, "unassign service"); - String svc_endpoint = endpoint + "/" + serviceInstanceId + "/unassign"; - return msoClientInterface.unassignSvcInstance(requestDetails, svc_endpoint); - } - } else { - endpoint = validateEndpointPath(MsoProperties.MSO_REST_API_SVC_INSTANCE); + endpoint = validateEndpointPath(MsoProperties.MSO_DELETE_OR_UNASSIGN_REST_API_SVC_INSTANCE); + if (shouldUnassignService(serviceStatus)){ + logger.debug(EELFLoggerDelegate.debugLogger, "unassign service"); + String svcEndpoint = endpoint + "/" + serviceInstanceId + "/unassign"; + return msoClientInterface.unassignSvcInstance(requestDetails, svcEndpoint); } - String svc_endpoint = endpoint + "/" + serviceInstanceId; - return msoClientInterface.deleteSvcInstance(requestDetails, svc_endpoint); + String svcEndpoint = endpoint + "/" + serviceInstanceId; + return msoClientInterface.deleteSvcInstance(requestDetails, svcEndpoint); } private boolean shouldUnassignService(String serviceStatus) { @@ -294,10 +288,10 @@ public class MsoBusinessLogicImpl implements MsoBusinessLogic { logInvocationInDebug("deleteVfModule"); String endpoint = validateEndpointPath(MsoProperties.MSO_REST_API_VF_MODULE_INSTANCE); - String vf__modules_endpoint = endpoint.replaceFirst(SVC_INSTANCE_ID, serviceInstanceId).replaceFirst(VNF_INSTANCE_ID, vnfInstanceId); - String delete_vf_endpoint = vf__modules_endpoint + '/' + vfModuleId; + String vfModulesEndpoint = endpoint.replaceFirst(SVC_INSTANCE_ID, serviceInstanceId).replaceFirst(VNF_INSTANCE_ID, vnfInstanceId); + String deleteVfEndpoint = vfModulesEndpoint + '/' + vfModuleId; - return msoClientInterface.deleteVfModule(requestDetails, delete_vf_endpoint); + return msoClientInterface.deleteVfModule(requestDetails, deleteVfEndpoint); } @Override @@ -305,11 +299,11 @@ public class MsoBusinessLogicImpl implements MsoBusinessLogic { logInvocationInDebug("deleteVolumeGroupInstance"); String endpoint = validateEndpointPath(MsoProperties.MSO_REST_API_VOLUME_GROUP_INSTANCE); - String svc_endpoint = endpoint.replaceFirst(SVC_INSTANCE_ID, serviceInstanceId); - String vnfEndpoint = svc_endpoint.replaceFirst(VNF_INSTANCE_ID, vnfInstanceId); - String delete_volume_group_endpoint = vnfEndpoint + "/" + volumeGroupId; + String svcEndpoint = endpoint.replaceFirst(SVC_INSTANCE_ID, serviceInstanceId); + String vnfEndpoint = svcEndpoint.replaceFirst(VNF_INSTANCE_ID, vnfInstanceId); + String deleteVolumeGroupEndpoint = vnfEndpoint + "/" + volumeGroupId; - return msoClientInterface.deleteVolumeGroupInstance(requestDetails, delete_volume_group_endpoint); + return msoClientInterface.deleteVolumeGroupInstance(requestDetails, deleteVolumeGroupEndpoint); } @Override @@ -317,10 +311,10 @@ public class MsoBusinessLogicImpl implements MsoBusinessLogic { logInvocationInDebug("deleteNwInstance"); String endpoint = validateEndpointPath(MsoProperties.MSO_REST_API_NETWORK_INSTANCE); - String svc_endpoint = endpoint.replaceFirst(SVC_INSTANCE_ID, serviceInstanceId); - String delete_nw_endpoint = svc_endpoint + "/" + networkInstanceId; + String svcEndpoint = endpoint.replaceFirst(SVC_INSTANCE_ID, serviceInstanceId); + String deleteNwEndpoint = svcEndpoint + "/" + networkInstanceId; - return msoClientInterface.deleteNwInstance(requestDetails, delete_nw_endpoint); + return msoClientInterface.deleteNwInstance(requestDetails, deleteNwEndpoint); } @Override @@ -400,7 +394,7 @@ public class MsoBusinessLogicImpl implements MsoBusinessLogic { private List deserializeOrchestrationRequestsJson(String orchestrationRequestsJson) { logInvocationInDebug("deserializeOrchestrationRequestsJson"); - ObjectMapper mapper = new ObjectMapper(); + ObjectMapper mapper = jacksonObjectMapper(); mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); mapper.configure(DeserializationFeature.READ_ENUMS_USING_TO_STRING, true); RequestList requestList; @@ -423,7 +417,7 @@ public class MsoBusinessLogicImpl implements MsoBusinessLogic { String path = p + "?originalRequestId=" + originalRequestId; RestObject restObjStr = new RestObject<>(); - String str = new String(); + String str = ""; restObjStr.set(str); MsoResponseWrapper msoResponseWrapper = msoClientInterface.getManualTasksByRequestId(str, "", path, restObjStr); @@ -438,9 +432,8 @@ public class MsoBusinessLogicImpl implements MsoBusinessLogic { private List deserializeManualTasksJson(String manualTasksJson) { logInvocationInDebug("deserializeManualTasksJson"); - ObjectMapper mapper = new ObjectMapper(); try { - TaskList taskList = mapper.readValue(manualTasksJson, TaskList.class); + TaskList taskList = JACKSON_OBJECT_MAPPER.readValue(manualTasksJson, TaskList.class); return taskList.getTaskList(); } catch (IOException e) { throw new GenericUncheckedException(e); @@ -457,7 +450,7 @@ public class MsoBusinessLogicImpl implements MsoBusinessLogic { String path = p + "/" + taskId + "/complete"; RestObject restObjStr = new RestObject<>(); - String str = new String(); + String str = ""; restObjStr.set(str); return msoClientInterface.completeManualTask(requestDetails, str, "", path, restObjStr); @@ -561,9 +554,7 @@ public class MsoBusinessLogicImpl implements MsoBusinessLogic { requestInfo.setRequestorId(softDeleteRequest.getUserId()); requestDetails.setRequestInfo(requestInfo); - CloudConfiguration cloudConfiguration = new CloudConfiguration(); - cloudConfiguration.setTenantId(softDeleteRequest.getTenantId()); - cloudConfiguration.setLcpCloudRegionId(softDeleteRequest.getLcpCloudRegionId()); + CloudConfiguration cloudConfiguration = new CloudConfiguration(softDeleteRequest.getLcpCloudRegionId(), softDeleteRequest.getTenantId(), null); requestDetails.setCloudConfiguration(cloudConfiguration); ModelInfo modelInfo = new ModelInfo(); @@ -577,18 +568,6 @@ public class MsoBusinessLogicImpl implements MsoBusinessLogic { return requestDetails; } - @Override - public MsoResponseWrapper2 deactivateAndCloudDelete(String serviceInstanceId, String vnfInstanceId, String vfModuleInstanceId, RequestDetails requestDetails) { - String path = getDeactivateAndCloudDeletePath(serviceInstanceId, vnfInstanceId, vfModuleInstanceId); - return new MsoResponseWrapper2<>(msoClientInterface.post(path, requestDetails, RequestReferencesContainer.class)); - } - - @Override - public MsoResponseWrapper2 activateFabricConfiguration(String serviceInstanceId, RequestDetails requestDetails) { - String path = getActivateFabricConfigurationPath(serviceInstanceId); - return new MsoResponseWrapper2<>(msoClientInterface.post(path, requestDetails, RequestReferencesContainer.class)); - } - @Override public SOWorkflowList getWorkflowListByModelId(String modelVersionId) { logInvocationInDebug("getWorkflowListByModelId"); @@ -634,7 +613,7 @@ public class MsoBusinessLogicImpl implements MsoBusinessLogic { } Object payloadRaw = requestDetails.getRequestParameters().getAdditionalProperties().get("payload"); try { - return objectMapper.readValue((String) payloadRaw, Map.class); + return JACKSON_OBJECT_MAPPER.readValue((String) payloadRaw, Map.class); } catch (Exception exception) { throw new BadRequestException(message); } @@ -912,7 +891,7 @@ public class MsoBusinessLogicImpl implements MsoBusinessLogic { } } - enum RequestType { + public enum RequestType { CREATE_INSTANCE("createInstance"), DELETE_INSTANCE("deleteInstance"), diff --git a/vid-app-common/src/main/java/org/onap/vid/mso/MsoUtil.java b/vid-app-common/src/main/java/org/onap/vid/mso/MsoUtil.java index 562182a3c..fcc20fafd 100644 --- a/vid-app-common/src/main/java/org/onap/vid/mso/MsoUtil.java +++ b/vid-app-common/src/main/java/org/onap/vid/mso/MsoUtil.java @@ -21,15 +21,20 @@ package org.onap.vid.mso; +import static org.onap.vid.utils.KotlinUtilsKt.JACKSON_OBJECT_MAPPER; + +import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import io.joshworks.restclient.http.HttpResponse; +import java.io.IOException; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.exception.ExceptionUtils; - +import org.onap.vid.exceptions.GenericUncheckedException; public class MsoUtil { - final static ObjectMapper objectMapper = new ObjectMapper(); + static final ObjectMapper objectMapper = new ObjectMapper(); private MsoUtil() { } @@ -48,12 +53,30 @@ public class MsoUtil { T body = httpResponse.getBody(); String entityStr = body instanceof String ? (String) body : objectMapper.writeValueAsString(httpResponse.getBody()); msoResponseWrapper.setEntity(entityStr); - } - catch(JsonProcessingException e) - { + } catch(JsonProcessingException e) { ExceptionUtils.rethrow(e); } } return msoResponseWrapper; } + + public static String formatExceptionAdditionalInfo(int statusCode, String msoResponse) { + String errorMsg = "Http Code:" + statusCode; + if (!StringUtils.isEmpty(msoResponse)) { + String filteredJson; + try { + filteredJson = StringUtils.defaultIfEmpty( + JACKSON_OBJECT_MAPPER.readTree(msoResponse).path("serviceException").toString().replaceAll("[\\{\\}]","") , + msoResponse + ); + } catch (JsonParseException e) { + filteredJson = msoResponse; + } catch (IOException e) { + throw new GenericUncheckedException(e); + } + + errorMsg = errorMsg + ", " + filteredJson; + } + return errorMsg; + } } diff --git a/vid-app-common/src/main/java/org/onap/vid/mso/model/AddOrRemoveInstanceGroupMemberRequestDetails.java b/vid-app-common/src/main/java/org/onap/vid/mso/model/AddOrRemoveInstanceGroupMemberRequestDetails.java new file mode 100644 index 000000000..f6b8a4241 --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/mso/model/AddOrRemoveInstanceGroupMemberRequestDetails.java @@ -0,0 +1,51 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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.vid.mso.model; + +import java.util.List; + +/* +Based on this model: +{ + "requestDetails": { + "requestInfo": { + "source": "VID", + "requestorId": "az2016" + }, + "relatedInstanceList": [ + { + "relatedInstance": { + "instanceId": "{the to be removed/added as member vnf-id}", + "modelInfo": { + "modelType": "vnf" + } + } + } + ] + } +} +*/ + +public class AddOrRemoveInstanceGroupMemberRequestDetails extends BaseResourceInstantiationRequestDetails { + public AddOrRemoveInstanceGroupMemberRequestDetails(RequestInfo requestInfo, List relatedInstanceList) { + super(null, null, requestInfo, null, null, relatedInstanceList, null); + } +} diff --git a/vid-app-common/src/main/java/org/onap/vid/mso/model/BaseResourceInstantiationRequestDetails.java b/vid-app-common/src/main/java/org/onap/vid/mso/model/BaseResourceInstantiationRequestDetails.java index c6eb53832..43f5b0070 100644 --- a/vid-app-common/src/main/java/org/onap/vid/mso/model/BaseResourceInstantiationRequestDetails.java +++ b/vid-app-common/src/main/java/org/onap/vid/mso/model/BaseResourceInstantiationRequestDetails.java @@ -7,9 +7,9 @@ * 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. @@ -20,15 +20,15 @@ package org.onap.vid.mso.model; +import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_EMPTY; +import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL; + import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.annotation.JsonTypeName; - import java.util.List; -import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL; - @JsonInclude(NON_NULL) public class BaseResourceInstantiationRequestDetails { @@ -83,21 +83,21 @@ public class BaseResourceInstantiationRequestDetails { this.requestParameters = requestParameters; } - public static class RequestInfo { + public static class RequestInfo { - @JsonInclude(NON_NULL) public final String instanceName; - @JsonInclude(NON_NULL) public final String productFamilyId; + @JsonInclude(NON_EMPTY) public final String instanceName; + @JsonInclude(NON_EMPTY) public final String productFamilyId; public final String source; - public final boolean suppressRollback; + @JsonInclude(NON_NULL) public final Boolean suppressRollback; public final String requestorId; - public RequestInfo(String instanceName, String productFamilyId, String source, boolean rollbackOnFailure, String requestorId) { + public RequestInfo(String instanceName, String productFamilyId, String source, Boolean rollbackOnFailure, String requestorId) { this.instanceName = instanceName; this.productFamilyId = productFamilyId; this.source = source; this.requestorId = requestorId; // in the FE we are asking for "RollbackOnFailure" but to MSO we are passing the negative value "suppressRollback" - this.suppressRollback = !rollbackOnFailure; + this.suppressRollback = rollbackOnFailure != null ? (!rollbackOnFailure) : null; } } @@ -120,9 +120,13 @@ public class BaseResourceInstantiationRequestDetails { public static class LineOfBusiness{ public final String lineOfBusinessName; - public LineOfBusiness(String lineOfBusiness) { + private LineOfBusiness(String lineOfBusiness) { this.lineOfBusinessName = lineOfBusiness; } + + public static LineOfBusiness of(String lineOfBusiness) { + return lineOfBusiness==null ? null : new LineOfBusiness(lineOfBusiness); + } } @JsonTypeName("relatedInstance") @@ -150,13 +154,18 @@ public class BaseResourceInstantiationRequestDetails { public static class RequestParameters { public final List userParams; - public RequestParameters(List userParams) { + @JsonInclude(NON_NULL) public final String testApi; + public RequestParameters(List userParams, String testApi) { this.userParams = userParams; + this.testApi = testApi; } public List getUserParams() { return userParams; } + public String getTestApi() { + return testApi; + } } } diff --git a/vid-app-common/src/main/java/org/onap/vid/mso/model/CloudConfiguration.java b/vid-app-common/src/main/java/org/onap/vid/mso/model/CloudConfiguration.java deleted file mode 100644 index 2e0991755..000000000 --- a/vid-app-common/src/main/java/org/onap/vid/mso/model/CloudConfiguration.java +++ /dev/null @@ -1,192 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * VID - * ================================================================================ - * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * 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.vid.mso.model; - -import com.fasterxml.jackson.annotation.*; -import org.apache.commons.lang.builder.EqualsBuilder; -import org.apache.commons.lang.builder.HashCodeBuilder; -import org.apache.commons.lang.builder.ToStringBuilder; - -import java.util.HashMap; -import java.util.Map; - - -/** - * fields communicating the cloud configuration in a standard way - * - */ -@JsonInclude(JsonInclude.Include.NON_NULL) -@JsonPropertyOrder({ - "nodeLocation", - "lcpCloudRegionId", - "tenantId", - "cloudOwner" -}) -public class CloudConfiguration { - - /** - * Location identifier for the node - * - */ - @JsonProperty("nodeLocation") - private String nodeLocation; - /** - * LCP Node Location identifier - * - */ - @JsonProperty("lcpCloudRegionId") - private String lcpCloudRegionId; - /** - * Openstack tenant id - * - */ - @JsonProperty("tenantId") - private String tenantId; - /** - * the cloud owner - * - */ - @JsonProperty("cloudOwner") - private String cloudOwner; - @JsonIgnore - private Map additionalProperties = new HashMap<>(); - - /** - * Location identifier for the node - * - * @return - * The nodeLocation - */ - @JsonProperty("nodeLocation") - public String getNodeLocation() { - return nodeLocation; - } - - /** - * Location identifier for the node - * - * @param nodeLocation - * The nodeLocation - */ - @JsonProperty("nodeLocation") - public void setNodeLocation(String nodeLocation) { - this.nodeLocation = nodeLocation; - } - - /** - * LCP Node Location identifier - * - * @return - * The lcpCloudRegionId - */ - @JsonProperty("lcpCloudRegionId") - public String getLcpCloudRegionId() { - return lcpCloudRegionId; - } - - /** - * LCP Node Location identifier - * - * @param lcpCloudRegionId - * The lcpCloudRegionId - */ - @JsonProperty("lcpCloudRegionId") - public void setLcpCloudRegionId(String lcpCloudRegionId) { - this.lcpCloudRegionId = lcpCloudRegionId; - } - - /** - * Openstack tenant id - * - * @return - * The tenantId - */ - @JsonProperty("tenantId") - public String getTenantId() { - return tenantId; - } - - /** - * Openstack tenant id - * - * @param tenantId - * The tenantId - */ - @JsonProperty("tenantId") - public void setTenantId(String tenantId) { - this.tenantId = tenantId; - } - - /** - * the cloud owner - * - * @return - * The cloudOwner - */ - @JsonProperty("cloudOwner") - public String getCloudOwner() { - return cloudOwner; - } - - /** - * the cloud owner - * - * @param cloudOwner - * The cloudOwner - */ - @JsonProperty("cloudOwner") - public void setCloudOwner(String cloudOwner) { - this.cloudOwner = cloudOwner; - } - - @Override - public String toString() { - return ToStringBuilder.reflectionToString(this); - } - - @JsonAnyGetter - public Map getAdditionalProperties() { - return this.additionalProperties; - } - - @JsonAnySetter - public void setAdditionalProperty(String name, Object value) { - this.additionalProperties.put(name, value); - } - - @Override - public int hashCode() { - return new HashCodeBuilder().append(nodeLocation).append(lcpCloudRegionId).append(tenantId).append(cloudOwner).append(additionalProperties).toHashCode(); - } - - @Override - public boolean equals(Object other) { - if (other == this) { - return true; - } - if (!(other instanceof CloudConfiguration)) { - return false; - } - CloudConfiguration rhs = ((CloudConfiguration) other); - return new EqualsBuilder().append(nodeLocation, rhs.nodeLocation).append(lcpCloudRegionId, rhs.lcpCloudRegionId).append(tenantId, rhs.tenantId).append(cloudOwner, rhs.cloudOwner).append(additionalProperties, rhs.additionalProperties).isEquals(); - } - -} diff --git a/vid-app-common/src/main/java/org/onap/vid/mso/model/CloudConfiguration.kt b/vid-app-common/src/main/java/org/onap/vid/mso/model/CloudConfiguration.kt new file mode 100644 index 000000000..d603e5b87 --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/mso/model/CloudConfiguration.kt @@ -0,0 +1,12 @@ +package org.onap.vid.mso.model + +import com.fasterxml.jackson.annotation.JsonInclude + +@JsonInclude(JsonInclude.Include.NON_EMPTY) +//tenantId and might be null for supporting create configuration API (port mirroring) +//cloudOwner might because MSO enable it and it might be used in some flows (default value in MSO "irma-aic") +data class CloudConfiguration @JvmOverloads constructor( + var lcpCloudRegionId: String? = null, + var tenantId:String? = null, + var cloudOwner: String? = null +) \ No newline at end of file diff --git a/vid-app-common/src/main/java/org/onap/vid/mso/model/ServiceInstantiationPre1806RequestDetails.java b/vid-app-common/src/main/java/org/onap/vid/mso/model/ServiceInstantiationPre1806RequestDetails.java new file mode 100644 index 000000000..effc10a08 --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/mso/model/ServiceInstantiationPre1806RequestDetails.java @@ -0,0 +1,51 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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.vid.mso.model; + +import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_EMPTY; +import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL; +import static org.onap.vid.mso.model.BaseResourceInstantiationRequestDetails.RelatedInstance; + +import com.fasterxml.jackson.annotation.JsonInclude; +import java.util.List; +import org.apache.commons.lang3.StringUtils; +import org.onap.vid.mso.rest.SubscriberInfo; + +public class ServiceInstantiationPre1806RequestDetails extends ServiceInstantiationRequestDetails { + + @JsonInclude(NON_NULL) + public final CloudConfiguration cloudConfiguration; + @JsonInclude(NON_EMPTY) + public final List relatedInstanceList; + + public ServiceInstantiationPre1806RequestDetails(ModelInfo modelInfo, ServiceInstantiationOwningEntity owningEntity, + SubscriberInfo subscriberInfo, Project project, RequestInfo requestInfo, + RequestParameters requestParameters, CloudConfiguration cloudConfiguration, + List relatedInstanceList) { + super(modelInfo, owningEntity, subscriberInfo, project, requestInfo, requestParameters); + if ((cloudConfiguration != null) && (!StringUtils.isEmpty(cloudConfiguration.getLcpCloudRegionId())) && (!StringUtils.isEmpty(cloudConfiguration.getTenantId()))){ + this.cloudConfiguration = cloudConfiguration; + } else { + this.cloudConfiguration = null; + } + this.relatedInstanceList = relatedInstanceList; + } +} diff --git a/vid-app-common/src/main/java/org/onap/vid/mso/model/ServiceInstantiationRequestDetails.java b/vid-app-common/src/main/java/org/onap/vid/mso/model/ServiceInstantiationRequestDetails.java index 700f43857..8f8dd681a 100644 --- a/vid-app-common/src/main/java/org/onap/vid/mso/model/ServiceInstantiationRequestDetails.java +++ b/vid-app-common/src/main/java/org/onap/vid/mso/model/ServiceInstantiationRequestDetails.java @@ -76,8 +76,8 @@ public class ServiceInstantiationRequestDetails { public static class RequestInfo { - @JsonInclude(NON_NULL) public final String instanceName; - @JsonInclude(NON_NULL) public final String productFamilyId; + @JsonInclude(NON_EMPTY) public final String instanceName; + @JsonInclude(NON_EMPTY) public final String productFamilyId; public final String source; public final boolean suppressRollback; public final String requestorId; @@ -150,7 +150,7 @@ public class ServiceInstantiationRequestDetails { private static class ServiceInstantiationServiceInner implements UserParamTypes { public ModelInfo modelInfo = new ModelInfo(); - @JsonInclude(NON_NULL) + @JsonInclude(NON_EMPTY) public String instanceName; public List> instanceParams; public ServiceInstantiationVnfList resources; @@ -182,7 +182,7 @@ public class ServiceInstantiationRequestDetails { public final String productFamilyId; public final List> instanceParams; @JsonInclude(NON_EMPTY) public final List vfModules; - @JsonInclude(NON_NULL) public final String instanceName; + @JsonInclude(NON_EMPTY) public final String instanceName; public ServiceInstantiationVnf(ModelInfo modelInfo, CloudConfiguration cloudConfiguration, String platform, String lineOfBusiness, String productFamilyId, List> instanceParams, List vfModules, String instanceName) { this.modelInfo = modelInfo; diff --git a/vid-app-common/src/main/java/org/onap/vid/mso/model/VfModuleInstantiationRequestDetails.java b/vid-app-common/src/main/java/org/onap/vid/mso/model/VfModuleInstantiationRequestDetails.java index 4e6f074c2..3b6cd1d3d 100644 --- a/vid-app-common/src/main/java/org/onap/vid/mso/model/VfModuleInstantiationRequestDetails.java +++ b/vid-app-common/src/main/java/org/onap/vid/mso/model/VfModuleInstantiationRequestDetails.java @@ -7,9 +7,9 @@ * 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. @@ -20,8 +20,10 @@ package org.onap.vid.mso.model; -import com.fasterxml.jackson.annotation.JsonProperty; +import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -109,14 +111,14 @@ public class VfModuleInstantiationRequestDetails extends BaseResourceInstantiati } public static class RequestParametersVfModule extends BaseResourceInstantiationRequestDetails.RequestParameters { - private final boolean usePreload; + @JsonInclude(NON_NULL) private final Boolean usePreload; - public RequestParametersVfModule(List userParams, boolean usePreload) { - super(userParams); + public RequestParametersVfModule(List userParams, Boolean usePreload, String testApi) { + super(userParams, testApi); this.usePreload = usePreload; } - public boolean isUsePreload() { + public Boolean isUsePreload() { return usePreload; } } diff --git a/vid-app-common/src/main/java/org/onap/vid/mso/rest/AsyncRequestStatus.java b/vid-app-common/src/main/java/org/onap/vid/mso/rest/AsyncRequestStatus.java index 12bf20549..61e0d3af6 100644 --- a/vid-app-common/src/main/java/org/onap/vid/mso/rest/AsyncRequestStatus.java +++ b/vid-app-common/src/main/java/org/onap/vid/mso/rest/AsyncRequestStatus.java @@ -7,9 +7,9 @@ * 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. @@ -53,6 +53,7 @@ public class AsyncRequestStatus { public String requestId; public String requestScope; + public String requestType; /** * The instance ids. diff --git a/vid-app-common/src/main/java/org/onap/vid/mso/rest/RequestStatus.java b/vid-app-common/src/main/java/org/onap/vid/mso/rest/RequestStatus.java index 031eaec23..29356aa4d 100644 --- a/vid-app-common/src/main/java/org/onap/vid/mso/rest/RequestStatus.java +++ b/vid-app-common/src/main/java/org/onap/vid/mso/rest/RequestStatus.java @@ -43,6 +43,14 @@ import java.util.Map; }) public class RequestStatus { + public RequestStatus() {} + + public RequestStatus(String requestState, String statusMessage, String timestamp) { + this.requestState = requestState; + this.statusMessage = statusMessage; + this.timestamp = timestamp; + } + /** * percentage complete estimate from 0 to 100 * diff --git a/vid-app-common/src/main/java/org/onap/vid/properties/Features.java b/vid-app-common/src/main/java/org/onap/vid/properties/Features.java index ea047d698..c96efe6f5 100644 --- a/vid-app-common/src/main/java/org/onap/vid/properties/Features.java +++ b/vid-app-common/src/main/java/org/onap/vid/properties/Features.java @@ -29,22 +29,17 @@ public enum Features implements Feature { * Use /docs/feature-flags.md for details */ - FLAG_ASYNC_JOBS, CREATE_INSTANCE_TEST, EMPTY_DRAWING_BOARD_TEST, FLAG_ADD_MSO_TESTAPI_FIELD, - FLAG_ASYNC_INSTANTIATION, FLAG_SERVICE_MODEL_CACHE, - FLAG_UNASSIGN_SERVICE, FLAG_NETWORK_TO_ASYNC_INSTANTIATION, - FLAG_COLLECTION_RESOURCE_SUPPORT, FLAG_SHOW_ASSIGNMENTS, + FLAG_UNASSIGN_SERVICE, FLAG_FABRIC_CONFIGURATION_ASSIGNMENTS, FLAG_SHOW_VERIFY_SERVICE, // AKA POMBA - FLAG_DUPLICATE_VNF, FLAG_DEFAULT_VNF, FLAG_SETTING_DEFAULTS_IN_DRAWING_BOARD, - FLAG_PNP_INSTANTIATION, FLAG_RESTRICTED_SELECT, FLAG_5G_IN_NEW_INSTANTIATION_UI, FLAG_ASYNC_ALACARTE_VNF, @@ -52,7 +47,6 @@ public enum Features implements Feature { FLAG_PRESENT_PROVIDER_NETWORKS_ASSOCIATIONS, FLAG_ASYNC_ALACARTE_VFMODULE, FLAG_SUPPLEMENTARY_FILE, - FLAG_SHIFT_VFMODULE_PARAMS_TO_VNF, FLAG_EXP_ANY_ALACARTE_NEW_INSTANTIATION_UI, FLAG_1810_CR_LET_SELECTING_COLLECTOR_TYPE_UNCONDITIONALLY, FLAG_1810_CR_ADD_CLOUD_OWNER_TO_MSO_REQUEST, @@ -62,10 +56,25 @@ public enum Features implements Feature { FLAG_1902_NEW_VIEW_EDIT, FLAG_EXP_USE_DEFAULT_HOST_NAME_VERIFIER, FLAG_1902_VNF_GROUPING, + FLAG_1902_RETRY_JOB, + FLAG_VF_MODULE_RESUME_STATUS_CREATE, + FLAG_EXP_CREATE_RESOURCES_IN_PARALLEL, + FLAG_1906_COMPONENT_INFO, + FLAG_1906_INSTANTIATION_API_USER_VALIDATION, + FLAG_1906_AAI_SUB_DETAILS_REDUCE_DEPTH, + FLAG_1908_TRANSPORT_SERVICE_NEW_INSTANTIATION_UI, + FLAG_1908_COLLECTION_RESOURCE_NEW_INSTANTIATION_UI, + FLAG_1908_INFRASTRUCTURE_VPN, + FLAG_1908_RESUME_MACRO_SERVICE, + FLAG_1908_RELEASE_TENANT_ISOLATION, + FLAG_1908_A_LA_CARTE_VNF_NEW_INSTANTIATION_UI, + FLAG_FLASH_REPLACE_VF_MODULE, + FLAG_PNP_INSTANTIATION, FLAG_HANDLE_SO_WORKFLOWS, FLAG_CREATE_ERROR_REPORTS ; + public boolean isActive() { return FeatureContext.getFeatureManager().isActive(this); } diff --git a/vid-app-common/src/main/java/org/onap/vid/properties/VidProperties.java b/vid-app-common/src/main/java/org/onap/vid/properties/VidProperties.java index 24b72fdff..8331886c0 100644 --- a/vid-app-common/src/main/java/org/onap/vid/properties/VidProperties.java +++ b/vid-app-common/src/main/java/org/onap/vid/properties/VidProperties.java @@ -7,9 +7,9 @@ * 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. @@ -21,9 +21,9 @@ package org.onap.vid.properties; import org.apache.commons.lang3.StringUtils; +import org.onap.vid.model.ModelConstants; import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; import org.onap.portalsdk.core.util.SystemProperties; -import org.onap.vid.model.ModelConstants; /** * The Class VidProperties. */ @@ -38,59 +38,62 @@ public class VidProperties extends SystemProperties { /** The Constant VID_TRUSTSTORE_FILENAME. */ public static final String VID_TRUSTSTORE_FILENAME = "vid.truststore.filename"; - + /** The Constant VID_TRUSTSTORE_PASSWD_X. */ public static final String VID_TRUSTSTORE_PASSWD_X = "vid.truststore.passwd.x"; - + /** The Constant FILESEPARATOR. */ public static final String FILESEPARATOR = (System.getProperty("file.separator") == null) ? "/" : System.getProperty("file.separator"); - + /** The Constant LOG. */ private static final EELFLoggerDelegate LOG = EELFLoggerDelegate.getLogger(VidProperties.class); - public static final String VID_JOB_MAX_HOURS_IN_PROGRESS = "vid.asyncJob.maxHoursInProgress"; + public static final String VID_JOB_MAX_HOURS_IN_PROGRESS = "vid.asyncJob.maxHoursInProgress"; + + public static final String VID_THREAD_COUNT = "vid.thread.count"; + public static final String VID_THREAD_TIMEOUT = "vid.thread.timeout"; /** * Gets the asdc model namespace prefix property - * + * * @return the property value or a default value */ public static String getAsdcModelNamespace() { String methodName = "getAsdcModelNamespace "; String asdcModelNamespace = ModelConstants.DEFAULT_ASDC_MODEL_NAMESPACE; - try { - asdcModelNamespace = SystemProperties.getProperty(ModelConstants.ASDC_MODEL_NAMESPACE); - if ( asdcModelNamespace == null || asdcModelNamespace.isEmpty()) { - asdcModelNamespace = ModelConstants.DEFAULT_ASDC_MODEL_NAMESPACE; - } - } - catch ( Exception e ) { - LOG.error (EELFLoggerDelegate.errorLogger, methodName + "unable to find the value, using the default " - + ModelConstants.DEFAULT_ASDC_MODEL_NAMESPACE); - asdcModelNamespace = ModelConstants.DEFAULT_ASDC_MODEL_NAMESPACE; - } - return (asdcModelNamespace); + try { + asdcModelNamespace = SystemProperties.getProperty(ModelConstants.ASDC_MODEL_NAMESPACE); + if ( asdcModelNamespace == null || asdcModelNamespace.isEmpty()) { + asdcModelNamespace = ModelConstants.DEFAULT_ASDC_MODEL_NAMESPACE; + } + } + catch ( Exception e ) { + LOG.error (EELFLoggerDelegate.errorLogger, methodName + "unable to find the value, using the default " + + ModelConstants.DEFAULT_ASDC_MODEL_NAMESPACE); + asdcModelNamespace = ModelConstants.DEFAULT_ASDC_MODEL_NAMESPACE; + } + return (asdcModelNamespace); } /** * Gets the specified property value. If the property is not defined, returns a default value. - * + * * @return the property value or a default value */ public static String getPropertyWithDefault ( String propName, String defaultValue ) { String methodName = "getPropertyWithDefault "; String propValue = defaultValue; - try { - propValue = SystemProperties.getProperty(propName); - if ( propValue == null || propValue.isEmpty()) { - propValue = defaultValue; - } - } - catch ( Exception e ) { - LOG.error (EELFLoggerDelegate.errorLogger, methodName + "unable to find the value, using the default " - + defaultValue); - propValue = defaultValue; - } - return (propValue); + try { + propValue = SystemProperties.getProperty(propName); + if ( propValue == null || propValue.isEmpty()) { + propValue = defaultValue; + } + } + catch ( Exception e ) { + LOG.error (EELFLoggerDelegate.errorLogger, methodName + "unable to find the value, using the default " + + defaultValue); + propValue = defaultValue; + } + return (propValue); } public static long getLongProperty(String key) { @@ -98,16 +101,16 @@ public class VidProperties extends SystemProperties { } public static long getLongProperty(String key, long defaultValue) { - if (!containsProperty(key)) { - LOG.debug(EELFLoggerDelegate.debugLogger, "No such property: {}. {} value is used", key, defaultValue); - return defaultValue; - } - String configValue = getProperty(key); - if (StringUtils.isNumeric(configValue)) { - return Long.parseLong(configValue); - } else { - LOG.debug(EELFLoggerDelegate.debugLogger, "{} property value is not valid: {}. {} value is used", key, configValue, defaultValue); - return defaultValue; - } - } + if (!containsProperty(key)) { + LOG.debug(EELFLoggerDelegate.debugLogger, "No such property: {}. {} value is used", key, defaultValue); + return defaultValue; + } + String configValue = getProperty(key); + if (StringUtils.isNumeric(configValue)) { + return Long.parseLong(configValue); + } else { + LOG.debug(EELFLoggerDelegate.debugLogger, "{} property value is not valid: {}. {} value is used", key, configValue, defaultValue); + return defaultValue; + } + } } diff --git a/vid-app-common/src/main/java/org/onap/vid/services/AAIServiceTree.java b/vid-app-common/src/main/java/org/onap/vid/services/AAIServiceTree.java index 6199c4e58..d62d5d5d4 100644 --- a/vid-app-common/src/main/java/org/onap/vid/services/AAIServiceTree.java +++ b/vid-app-common/src/main/java/org/onap/vid/services/AAIServiceTree.java @@ -7,9 +7,9 @@ * 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. @@ -21,7 +21,6 @@ package org.onap.vid.services; import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.collect.ImmutableList; import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; import org.onap.vid.aai.AaiClientInterface; @@ -31,21 +30,24 @@ import org.onap.vid.asdc.parser.ServiceModelInflator; import org.onap.vid.exceptions.GenericUncheckedException; import org.onap.vid.model.ServiceModel; import org.onap.vid.model.aaiTree.AAITreeNode; +import org.onap.vid.model.aaiTree.NodeType; import org.onap.vid.model.aaiTree.ServiceInstance; import org.onap.vid.utils.Tree; +import org.springframework.http.HttpMethod; import org.springframework.stereotype.Component; import javax.inject.Inject; import javax.ws.rs.core.Response; import java.util.*; -import java.util.concurrent.*; -import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.ConcurrentSkipListSet; +import java.util.concurrent.ExecutorService; +import java.util.stream.Collectors; +import java.util.stream.Stream; -import static java.lang.Thread.sleep; import static java.util.Comparator.comparing; import static java.util.stream.Collectors.toSet; import static org.apache.commons.lang3.ObjectUtils.defaultIfNull; -import static org.onap.vid.services.AAITreeNodeBuilder.*; +import static org.onap.vid.utils.KotlinUtilsKt.JACKSON_OBJECT_MAPPER; @Component public class AAIServiceTree { @@ -60,38 +62,58 @@ public class AAIServiceTree { private final ServiceModelInflator serviceModelInflator; - private final ObjectMapper mapper = new ObjectMapper(); + private final ExecutorService executorService; private static final EELFLoggerDelegate LOGGER = EELFLoggerDelegate.getLogger(AAIServiceTree.class); public static final Tree AAI_TREE_PATHS = - new Tree<>(new AaiRelationship(SERVICE_INSTANCE)); + new Tree<>(new AaiRelationship(NodeType.SERVICE_INSTANCE)); static { - AAI_TREE_PATHS.addPath(toAaiRelationshipList(GENERIC_VNF, VG)); - AAI_TREE_PATHS.addPath(toAaiRelationshipList(NETWORK)); - AAI_TREE_PATHS.addPath(toAaiRelationshipList(GENERIC_VNF, NETWORK)); - AAI_TREE_PATHS.addPath(toAaiRelationshipList(INSTANCE_GROUP)); + AAI_TREE_PATHS.addPath(toAaiRelationshipList(NodeType.GENERIC_VNF, NodeType.VOLUME_GROUP)); + AAI_TREE_PATHS.addPath(toAaiRelationshipList(NodeType.GENERIC_VNF, NodeType.VF_MODULE)); + AAI_TREE_PATHS.addPath(toAaiRelationshipList(NodeType.GENERIC_VNF, NodeType.NETWORK, NodeType.VPN_BINDING)); + AAI_TREE_PATHS.addPath(toAaiRelationshipList(NodeType.NETWORK, NodeType.VPN_BINDING)); + AAI_TREE_PATHS.addPath(toAaiRelationshipList(NodeType.INSTANCE_GROUP, NodeType.GENERIC_VNF)); + AAI_TREE_PATHS.addPath(toAaiRelationshipList(NodeType.COLLECTION_RESOURCE, NodeType.INSTANCE_GROUP)); + AAI_TREE_PATHS.addPath(toAaiRelationshipList(NodeType.CONFIGURATION, NodeType.NETWORK, NodeType.VPN_BINDING)); + AAI_TREE_PATHS.addPath(toAaiRelationshipList(NodeType.CONFIGURATION, NodeType.VPN_BINDING)); + } + + public static List toAaiRelationshipList(NodeType... types) { + return Stream.of(types).map(AAIServiceTree.AaiRelationship::new).collect(Collectors.toList()); } @Inject public AAIServiceTree(AaiClientInterface aaiClient, AAITreeNodeBuilder aaiTreeNodeBuilder, AAITreeConverter aaiTreeConverter, VidService sdcService, - ServiceModelInflator serviceModelInflator) { + ServiceModelInflator serviceModelInflator, ExecutorService executorService) { this.aaiClient = aaiClient; this.aaiTreeNodeBuilder = aaiTreeNodeBuilder; this.aaiTreeConverter = aaiTreeConverter; this.sdcService = sdcService; this.serviceModelInflator = serviceModelInflator; + this.executorService = executorService; + } + + List buildAAITreeForUniqueResource(String getUrl, NodeType nodeType) { + return buildAAITreeForUniqueResourceFromCustomQuery(getUrl, null, HttpMethod.GET, nodeType); + } + + List buildAAITreeForUniqueResourceFromCustomQuery(String url, String payload, HttpMethod method, NodeType nodeType) { + Tree pathsToSearch = new Tree<>(new AAIServiceTree.AaiRelationship(nodeType)); + return buildAAITree(url, payload, method, pathsToSearch, false); } - public List buildAAITree(String getUrl, Tree pathsToSearch) { + public List buildAAITree(String url, String payload, HttpMethod method, Tree pathsToSearch, boolean enrichWithModelVersion) { ConcurrentSkipListSet nodesAccumulator = createNodesAccumulator(); - List aaiTreeNodes = fetchAAITree(getUrl, pathsToSearch, nodesAccumulator, true); + List aaiTreeNodes = fetchAAITree(url, payload, method, pathsToSearch, nodesAccumulator); - enrichNodesWithModelVersionAndModelName(nodesAccumulator); + if (enrichWithModelVersion) { + enrichNodesWithModelVersionAndModelName(nodesAccumulator); + } return aaiTreeNodes; } @@ -105,7 +127,7 @@ public class AAIServiceTree { //Used later to get the nodes UUID ConcurrentSkipListSet nodesAccumulator = createNodesAccumulator(); - AAITreeNode aaiTree = fetchAAITree(getURL, AAI_TREE_PATHS, nodesAccumulator, false).get(0); + AAITreeNode aaiTree = fetchAAITree(getURL, null, HttpMethod.GET, AAI_TREE_PATHS, nodesAccumulator).get(0); //Populate nodes with model-name & model-version (from aai) enrichNodesWithModelVersionAndModelName(nodesAccumulator); @@ -115,28 +137,28 @@ public class AAIServiceTree { //Populate nodes with model-customization-name (from sdc model) enrichNodesWithModelCustomizationName(nodesAccumulator, serviceModel); - return aaiTreeConverter.convertTreeToUIModel(aaiTree, globalCustomerId, serviceType, getInstantiationType(serviceModel)); + return aaiTreeConverter.convertTreeToUIModel(aaiTree, globalCustomerId, serviceType, getInstantiationType(serviceModel), getInstanceRole(serviceModel), getInstanceType(serviceModel)); } - private List fetchAAITree(String getUrl, Tree pathsToSearch, - ConcurrentSkipListSet nodesAccumulator, boolean partialTreeOnTimeout) { - ThreadPoolExecutor threadPool = getThreadPool(); - - List aaiTree = aaiTreeNodeBuilder.buildNode(SERVICE_INSTANCE, - getUrl, defaultIfNull(nodesAccumulator, createNodesAccumulator()), - threadPool, new ConcurrentLinkedQueue<>(), - new AtomicInteger(0), pathsToSearch); - - boolean timeoutOccurred = waitForTreeFetch(threadPool); + private String getInstanceType(ServiceModel serviceModel){ + if (serviceModel != null && serviceModel.getService() != null) { + return serviceModel.getService().getServiceType(); + } + return ""; + } - if (timeoutOccurred) { - if (!partialTreeOnTimeout) { - throw new GenericUncheckedException("Timeout on fetchAAITree. Fetched " + nodesAccumulator.size() + " nodes for url: " + getUrl); - } - LOGGER.warn(EELFLoggerDelegate.errorLogger, "Timeout on fetchAAITree for url: " + getUrl); + private String getInstanceRole(ServiceModel serviceModel) { + if (serviceModel != null && serviceModel.getService() != null) { + return serviceModel.getService().getServiceRole(); } + return ""; + } - return aaiTree; + private List fetchAAITree(String url, String payload, HttpMethod method, Tree pathsToSearch, + ConcurrentSkipListSet nodesAccumulator) { + return aaiTreeNodeBuilder.buildNode(NodeType.fromString(pathsToSearch.getRootValue().type), + url, payload, method, defaultIfNull(nodesAccumulator, createNodesAccumulator()), + executorService, pathsToSearch); } private ConcurrentSkipListSet createNodesAccumulator() { @@ -204,12 +226,12 @@ public class AAIServiceTree { private JsonNode getModels(AaiClientInterface aaiClient, Collection invariantIDs) { Response response = aaiClient.getVersionByInvariantId(ImmutableList.copyOf(invariantIDs)); try { - JsonNode responseJson = mapper.readTree(response.readEntity(String.class)); + JsonNode responseJson = JACKSON_OBJECT_MAPPER.readTree(response.readEntity(String.class)); return responseJson.get("model"); } catch (Exception e) { LOGGER.error(EELFLoggerDelegate.errorLogger, "Failed to getVersionByInvariantId from A&AI", e); } - return mapper.createObjectNode(); + return JACKSON_OBJECT_MAPPER.createObjectNode(); } private Set getModelInvariantIds(Collection nodes) { @@ -219,30 +241,6 @@ public class AAIServiceTree { .collect(toSet()); } - private boolean waitForTreeFetch(ThreadPoolExecutor threadPool) { - int timer = 60; - try { - //Stop fetching information if it takes more than 1 minute - while (threadPool.getActiveCount() != 0 && - timer > 0) { - sleep(1000); - timer--; - } - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new GenericUncheckedException(e); - } - threadPool.shutdown(); - return (timer == 0); - } - - private ThreadPoolExecutor getThreadPool() { - //Use at least one thread, and never more than 75% of the available thread. - int cores = Math.max((int)(Runtime.getRuntime().availableProcessors() * 0.75), 1); - BlockingQueue queue = new LinkedBlockingQueue<>(); - return new ThreadPoolExecutor(1, cores, 10, TimeUnit.SECONDS, queue); - } - public static class AaiRelationship { public final String type; @@ -251,6 +249,10 @@ public class AAIServiceTree { this.type = type; } + public AaiRelationship(NodeType nodeType) { + this.type = nodeType.getType(); + } + @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/vid-app-common/src/main/java/org/onap/vid/services/AAITreeNodeBuilder.java b/vid-app-common/src/main/java/org/onap/vid/services/AAITreeNodeBuilder.java index e06088264..d53eba8d3 100644 --- a/vid-app-common/src/main/java/org/onap/vid/services/AAITreeNodeBuilder.java +++ b/vid-app-common/src/main/java/org/onap/vid/services/AAITreeNodeBuilder.java @@ -7,9 +7,9 @@ * 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. @@ -21,66 +21,49 @@ package org.onap.vid.services; import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.collect.ImmutableList; import org.apache.commons.lang3.StringUtils; -import org.jetbrains.annotations.NotNull; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.commons.lang3.tuple.Pair; import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; +import org.onap.portalsdk.core.util.SystemProperties; import org.onap.vid.aai.AaiClientInterface; import org.onap.vid.aai.ExceptionWithRequestInfo; import org.onap.vid.aai.model.AaiGetNetworkCollectionDetails.Relationship; +import org.onap.vid.aai.model.AaiGetNetworkCollectionDetails.RelationshipData; import org.onap.vid.aai.model.AaiGetNetworkCollectionDetails.RelationshipList; +import org.onap.vid.aai.util.AAITreeNodeUtils; +import org.onap.vid.exceptions.GenericUncheckedException; import org.onap.vid.model.aaiTree.AAITreeNode; import org.onap.vid.model.aaiTree.FailureAAITreeNode; +import org.onap.vid.model.aaiTree.NodeType; +import org.onap.vid.mso.model.CloudConfiguration; +import org.onap.vid.properties.VidProperties; import org.onap.vid.utils.Streams; import org.onap.vid.utils.Tree; import org.onap.vid.utils.Unchecked; +import org.springframework.http.HttpMethod; import org.springframework.stereotype.Component; import javax.inject.Inject; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentLinkedQueue; -import java.util.concurrent.ConcurrentSkipListSet; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.atomic.AtomicInteger; +import java.util.*; +import java.util.concurrent.*; import java.util.stream.Collectors; import java.util.stream.Stream; import static java.util.stream.Collectors.*; +import static org.onap.vid.utils.KotlinUtilsKt.JACKSON_OBJECT_MAPPER; import static org.onap.vid.utils.Streams.not; @Component public class AAITreeNodeBuilder { + private static final String RESULTS = "results"; private AaiClientInterface aaiClient; - private final ObjectMapper mapper = new ObjectMapper(); - private static final EELFLoggerDelegate LOGGER = EELFLoggerDelegate.getLogger(AAITreeNodeBuilder.class); - //List of all the node types the tree should include - public static final String SERVICE_INSTANCE = "service-instance"; - public static final String GENERIC_VNF = "generic-vnf"; - public static final String NETWORK = "l3-network"; - public static final String FAILURE = "failure_node"; - public static final String COLLECTION_RESOURCE = "collection"; - public static final String CONFIGURATION = "configuration"; - public static final String PNF = "pnf"; - public static final String VF_MODULE = "vf-module"; - public static final String INSTANCE_GROUP = "instance-group"; - public static final String PORT = "l-interface"; - public static final String VG = "volume-group"; - public static final String VLAN_TAG = "vlan-tag"; - - //Hashmap that defines the node-type and the tag that should be used to find it's ID key in the JSON. - private static HashMap nodeTypeToIdKeyMap = generateTypeToIdKeyMap(); - - //Hashmap that defines the node-type and the tag that should be used to find it's NAMR key in the JSON. - private static HashMap nodeTypeToNameKeyMap = generateTypeToNameKeyMap(); public enum AAIBaseProperties { ORCHESTRATION_STATUS("orchestration-status"), @@ -102,63 +85,121 @@ public class AAITreeNodeBuilder { } } - public static List toAaiRelationshipList(String... types) { - return Stream.of(types).map(AAIServiceTree.AaiRelationship::new).collect(Collectors.toList()); - } - @Inject public AAITreeNodeBuilder(AaiClientInterface aaiClient) { this.aaiClient = aaiClient; } - public List buildNode(String nodeType, - String requestURL, - ConcurrentSkipListSet nodesAccumulator, ExecutorService threadPool, - ConcurrentLinkedQueue visitedNodes, - AtomicInteger nodesCounter, - Tree pathsTree) { + List buildNode(NodeType nodeType, + String requestURL, + String payload, + HttpMethod method, + ConcurrentSkipListSet nodesAccumulator, + ExecutorService threadPool, + Tree pathsTree) { - JsonNode topLevelJson = aaiClient.typedAaiGet(Unchecked.toURI(requestURL), JsonNode.class); + JsonNode jsonNode = aaiClient.typedAaiRest(Unchecked.toURI(requestURL), JsonNode.class, payload, method, false); - if (topLevelJson.has(nodeType) && topLevelJson.get(nodeType).isArray()) { - return Streams.fromIterable(topLevelJson.get(nodeType)) - .map(item -> parseNodeAndGetChildren(nodeType, requestURL, item, - nodesAccumulator, threadPool, visitedNodes, nodesCounter, pathsTree)) - .collect(toList()); - } else { - return ImmutableList.of(parseNodeAndGetChildren(nodeType, requestURL, topLevelJson, - nodesAccumulator, threadPool, visitedNodes, nodesCounter, pathsTree)); + List>> nodes = getNodesWithRelationships(jsonNode, nodeType, nodesAccumulator, pathsTree); + + String timeout = SystemProperties.getProperty(VidProperties.VID_THREAD_TIMEOUT); + long timeoutNum = Long.parseLong(StringUtils.defaultIfEmpty(timeout, "30")); + + for (Pair> entry : nodes) { + fetchChildrenAsync(threadPool, nodesAccumulator, entry.getKey(), entry.getValue(), pathsTree, timeoutNum); + + if (getNextLevelInPathsTree(pathsTree, NodeType.VF_MODULE.getType()) != null) { + getRelatedVfModules(threadPool, nodesAccumulator, requestURL, entry.getKey()); + } } + + return nodes.stream() + .map(Pair::getKey) + .collect(Collectors.toList()); } - private AAITreeNode parseNodeAndGetChildren(String nodeType, - String requestURL, - JsonNode topLevelJson, - ConcurrentSkipListSet nodesAccumulator, ExecutorService threadPool, - ConcurrentLinkedQueue visitedNodes, - AtomicInteger nodesCounter, - Tree pathsTree) { - AAITreeNode node = jsonToAaiNode(nodeType, topLevelJson, nodesAccumulator, nodesCounter); - - RelationshipList relationships = mapper.convertValue(topLevelJson.get(AAIBaseProperties.RELATIONSHIP_LIST.getAaiKey()), RelationshipList.class); - if (relationships != null) { - getChildren(threadPool, nodesAccumulator, relationships.getRelationship(), visitedNodes, node, nodesCounter, pathsTree); - } - if (StringUtils.equals(node.getType(), GENERIC_VNF)) { - getRelatedVfModules(threadPool, nodesAccumulator, requestURL, node, nodesCounter); + private List>> getNodesWithRelationships(JsonNode jsonNode, NodeType nodeType, + ConcurrentSkipListSet nodesAccumulator, + Tree pathsTree) { + if (isListOfKeyResults(jsonNode)) { + return Streams.fromIterable(jsonNode.get(RESULTS)) + .filter(item -> item.has(nodeType.getType())) + .map(item -> item.get(nodeType.getType())) + .map(item -> parseNodeAndFilterRelationships(item, nodeType, nodesAccumulator, pathsTree)) + .collect(Collectors.toList()); + } else if (isArray(jsonNode, nodeType)) { + return Streams.fromIterable(jsonNode.get(nodeType.getType())) + .map(item -> parseNodeAndFilterRelationships(item, nodeType, nodesAccumulator, pathsTree)) + .collect(Collectors.toList()); + } else { + return ImmutableList.of(parseNodeAndFilterRelationships(jsonNode, nodeType, nodesAccumulator, pathsTree)); } - return node; } - private AAITreeNode jsonToAaiNode(String nodeType, JsonNode topLevelJson, ConcurrentSkipListSet nodesAccumulator, AtomicInteger nodesCounter) { - AAITreeNode node = fillNodeMetaData(nodeType, topLevelJson, nodesCounter); + Pair> parseNodeAndFilterRelationships(JsonNode jsonNode, NodeType nodeType, + ConcurrentSkipListSet nodesAccumulator, + Tree pathsTree) { + AAITreeNode node = createAaiNode(nodeType, jsonNode, nodesAccumulator); + + enrichPlacementData(node); + + List filteredRelationships = getFilteredRelationships(jsonNode, pathsTree); + + return ImmutablePair.of(node, filteredRelationships); + } + + boolean isArray(JsonNode json, NodeType nodeType) { + return json != null && json.has(nodeType.getType()) && json.get(nodeType.getType()).isArray(); + } + + boolean isListOfKeyResults(JsonNode jsonNode) { + return jsonNode != null && jsonNode.has(RESULTS) && jsonNode.get(RESULTS).isArray(); + } + + AAITreeNode createAaiNode(NodeType nodeType, JsonNode jsonNode, ConcurrentSkipListSet nodesAccumulator) { + AAITreeNode node = jsonNodeToAaiNode(nodeType, jsonNode); nodesAccumulator.add(node); return node; } - private void getRelatedVfModules(ExecutorService threadPool, ConcurrentSkipListSet nodesAccumulator, String parentURL, AAITreeNode parentNode, AtomicInteger nodesCounter) { + private void addChildren(AAITreeNode node, Future> children) { + try { + node.addChildren(children.get()); + } catch (Exception e) { + node.getChildren().add(createFailureNode(e)); + } + } + + private Map convertRelationshipDataToMap(List relationshipData) { + return relationshipData.stream().collect( + Collectors.toMap(RelationshipData::getKey, RelationshipData::getValue)); + } + + void enrichPlacementData(AAITreeNode node){ + Optional tenantRelationShip = AAITreeNodeUtils.findFirstRelationshipByRelatedTo(node.getRelationshipList(), "tenant"); + enrichPlacementDataUsingTenantInfo(node, tenantRelationShip); + } + + void enrichPlacementDataUsingTenantInfo(AAITreeNode node, Optional tenantRelationShip) { + //no tenant relationship in this node - so no placement data + if (!tenantRelationShip.isPresent()) { + return; + } + try { + Map relationshipsDataMap = convertRelationshipDataToMap(tenantRelationShip.get().getRelationDataList()); + node.setCloudConfiguration(new CloudConfiguration( + relationshipsDataMap.get("cloud-region.cloud-region-id"), + relationshipsDataMap.get("tenant.tenant-id"), + relationshipsDataMap.get("cloud-region.cloud-owner"))); + } + catch (Exception exception) { + LOGGER.error("Failed to extract placement form tenant relationship of {}:{}", node.getType(), node.getId(), exception); + } + } + + private void getRelatedVfModules(ExecutorService threadPool, ConcurrentSkipListSet nodesAccumulator, String parentURL, AAITreeNode parentNode) { /* VNFs do not report their direct related-to vf-modules, so try directly fetching a resource URI. @@ -166,73 +207,100 @@ public class AAITreeNodeBuilder { threadPool.execute(() -> { // the response is an array of vf-modules - final JsonNode topLevelJson; + final JsonNode jsonNode; try { - topLevelJson = aaiClient.typedAaiGet(Unchecked.toURI(parentURL + "/vf-modules"), JsonNode.class); + jsonNode = aaiClient.typedAaiGet(Unchecked.toURI(parentURL + "/vf-modules"), JsonNode.class); } catch (ExceptionWithRequestInfo e) { if (e.getHttpCode().equals(404)) { // it's ok, as we're just optimistically fetching - // the /vf-modules uri; 404 says this time it was - // a bad guess + // the /vf-modules uri; 404 says this time it was a bad guess return; } else { throw e; } } - if (topLevelJson != null) { - parentNode.getChildren().addAll( - Streams.fromIterable(topLevelJson.get(VF_MODULE)) - .map(vfModuleNode -> jsonToAaiNode(VF_MODULE, vfModuleNode, nodesAccumulator, nodesCounter)) - .collect(toList()) - ); + if (isArray(jsonNode, NodeType.VF_MODULE)) { + + //create list of AAITreeNode represent the VfModules from AAI result + List vfModules = Streams.fromIterable(jsonNode.get(NodeType.VF_MODULE.getType())) + .map(vfModuleNode -> createAaiNode(NodeType.VF_MODULE, vfModuleNode, nodesAccumulator)) + .collect(toList()); + //enrich each of the VfModule with placement info + vfModules.forEach(vfModule-> enrichPlacementDataUsingTenantInfo( + vfModule, + AAITreeNodeUtils.findFirstRelationshipByRelatedTo(vfModule.getRelationshipList(), "vserver") + )); + //add all VfModules to children list of parent node + parentNode.getChildren().addAll(vfModules); } else { LOGGER.error(EELFLoggerDelegate.errorLogger, "Failed to get vf-modules for vnf " + parentNode.getId()); } }); } - private void getChildren(ExecutorService threadPool, ConcurrentSkipListSet nodesAccumulator, - List relationships, ConcurrentLinkedQueue visitedNodes, AAITreeNode parent, AtomicInteger nodesCounter, Tree pathsTree) { - for (Relationship relationship : relationships) { - createChildNode(threadPool, nodesAccumulator, relationship, visitedNodes, parent, nodesCounter, pathsTree); + List getFilteredRelationships(JsonNode json, Tree pathsTree) { + RelationshipList relationshipList = JACKSON_OBJECT_MAPPER.convertValue(json.get(AAIBaseProperties.RELATIONSHIP_LIST.getAaiKey()), RelationshipList.class); + if (relationshipList != null) { + return relationshipList.getRelationship().stream() + .filter(rel -> getNextLevelInPathsTree(pathsTree, rel.getRelatedTo()) != null) + .filter(rel -> !Objects.equals(rel.getRelatedTo(), NodeType.VF_MODULE.getType())) // vf-modules are handled separately + .collect(toList()); } + + return Collections.emptyList(); } - private void createChildNode(ExecutorService threadPool, ConcurrentSkipListSet nodesAccumulator, - Relationship relationship, ConcurrentLinkedQueue visitedNodes, AAITreeNode parent, AtomicInteger nodesCounter, Tree pathsTree) { - String newNodeType = relationship.getRelatedTo(); - Tree subTree = pathsTree.getSubTree(new AAIServiceTree.AaiRelationship(newNodeType)); - if (subTree!=null) { - String newNodeUrl = relationship.getRelatedLink(); - if (!visitedNodes.contains(newNodeUrl)) { - visitedNodes.add(newNodeUrl); - threadPool.execute(() -> { - try { - parent.addChildren(buildNode(newNodeType, newNodeUrl, nodesAccumulator, threadPool, visitedNodes, nodesCounter, subTree)); - } catch (Exception e) { - parent.getChildren().add(createFailureNode(e)); - } - } - ); + void fetchChildrenAsync(ExecutorService threadPool, ConcurrentSkipListSet nodesAccumulator, + AAITreeNode node, List relationships, Tree pathsTree, long timeout) { + + if (!relationships.isEmpty()) { + List>> tasks = relationships.stream() + .map(relationship -> + (Callable>) () -> + getChildNode(threadPool, nodesAccumulator, relationship.getRelatedTo(), + relationship.getRelatedLink(), pathsTree)) + .collect(Collectors.toList()); + + try { + int depth = pathsTree.getChildrenDepth(); + threadPool.invokeAll(tasks, timeout * depth, TimeUnit.SECONDS) + .forEach(future -> + addChildren(node, future) + ); + } catch (Exception e) { + throw new GenericUncheckedException(e); } } } - private AAITreeNode fillNodeMetaData(String nodeType, JsonNode model, @NotNull AtomicInteger nodesCounter) { + private List getChildNode(ExecutorService threadPool, ConcurrentSkipListSet nodesAccumulator, + String childNodeType, String childNodeUrl, + Tree pathsTree) { + + Tree subTree = getNextLevelInPathsTree(pathsTree, childNodeType); + + return buildNode(NodeType.fromString(childNodeType), childNodeUrl, null, HttpMethod.GET, nodesAccumulator, threadPool, subTree); + } + + Tree getNextLevelInPathsTree(Tree pathsTree, String nodeType) { + return pathsTree.getSubTree(new AAIServiceTree.AaiRelationship(nodeType)); + } + + //ADD TEST + private AAITreeNode jsonNodeToAaiNode(NodeType nodeType, JsonNode jsonNode) { AAITreeNode node = new AAITreeNode(); node.setType(nodeType); - node.setUniqueNumber(nodesCounter.getAndIncrement()); - node.setOrchestrationStatus(getStringDataFromJsonIfExists(model, AAIBaseProperties.ORCHESTRATION_STATUS.getAaiKey())); - node.setProvStatus(getStringDataFromJsonIfExists(model, AAIBaseProperties.PROV_STATUS.getAaiKey())); - node.setInMaint(getBooleanDataFromJsonIfExists(model, AAIBaseProperties.IN_MAINT.getAaiKey())); - node.setModelVersionId(getStringDataFromJsonIfExists(model, AAIBaseProperties.MODEL_VERSION_ID.getAaiKey())); - node.setModelCustomizationId(getStringDataFromJsonIfExists(model, AAIBaseProperties.MODEL_CUSTOMIZATION_ID.getAaiKey())); - node.setModelInvariantId(getStringDataFromJsonIfExists(model, AAIBaseProperties.MODEL_INVARIANT_ID.getAaiKey())); - node.setId(getStringDataFromJsonIfExists(model, nodeTypeToIdKeyMap.get(nodeType))); - node.setName(getStringDataFromJsonIfExists(model, nodeTypeToNameKeyMap.get(nodeType))); - node.setAdditionalProperties(aggregateAllOtherProperties(model, nodeType)); - + node.setOrchestrationStatus(getStringDataFromJsonIfExists(jsonNode, AAIBaseProperties.ORCHESTRATION_STATUS.getAaiKey())); + node.setProvStatus(getStringDataFromJsonIfExists(jsonNode, AAIBaseProperties.PROV_STATUS.getAaiKey())); + node.setInMaint(getBooleanDataFromJsonIfExists(jsonNode, AAIBaseProperties.IN_MAINT.getAaiKey())); + node.setModelVersionId(getStringDataFromJsonIfExists(jsonNode, AAIBaseProperties.MODEL_VERSION_ID.getAaiKey())); + node.setModelCustomizationId(getStringDataFromJsonIfExists(jsonNode, AAIBaseProperties.MODEL_CUSTOMIZATION_ID.getAaiKey())); + node.setModelInvariantId(getStringDataFromJsonIfExists(jsonNode, AAIBaseProperties.MODEL_INVARIANT_ID.getAaiKey())); + node.setId(getStringDataFromJsonIfExists(jsonNode, nodeType.getId())); + node.setName(getStringDataFromJsonIfExists(jsonNode, nodeType.getName())); + node.setAdditionalProperties(aggregateAllOtherProperties(jsonNode, nodeType)); + node.setRelationshipList(JACKSON_OBJECT_MAPPER.convertValue(jsonNode.get(AAIBaseProperties.RELATIONSHIP_LIST.getAaiKey()), RelationshipList.class)); return node; } @@ -241,7 +309,7 @@ public class AAITreeNodeBuilder { } private String getStringDataFromJsonIfExists(JsonNode model, String key) { - if (model.has(key)) { + if (!NodeType.NONE.equals(key) && model.has(key)) { return model.get(key).asText(); } return null; @@ -254,48 +322,17 @@ public class AAITreeNodeBuilder { return false; } - private Map aggregateAllOtherProperties(JsonNode model, String nodeType) { + Map aggregateAllOtherProperties(JsonNode model, NodeType nodeType) { Set ignoreProperties = Stream.of(AAIBaseProperties.values()) .map(AAIBaseProperties::getAaiKey).collect(toSet()); - return Streams.fromIterator(model.fields()) - .filter(not(field -> StringUtils.equals(field.getKey(), nodeTypeToIdKeyMap.get(nodeType)))) - .filter(not(field -> StringUtils.equals(field.getKey(), nodeTypeToNameKeyMap.get(nodeType)))) + .filter(not(field -> StringUtils.equals(field.getKey(), nodeType.getId()))) + .filter(not(field -> StringUtils.equals(field.getKey(), nodeType.getName()))) .filter(not(field -> ignoreProperties.contains(field.getKey()))) - .collect(toMap(Map.Entry::getKey, v -> v.getValue().asText())); - } - - private static HashMap generateTypeToIdKeyMap() { - HashMap result = new HashMap<>(); - result.put(SERVICE_INSTANCE, "service-instance-id"); - result.put(GENERIC_VNF, "vnf-id"); - result.put(NETWORK, "network-id"); - result.put(COLLECTION_RESOURCE, "collection-id"); - result.put(CONFIGURATION, "configuration-id"); - result.put(PNF, "pnf-id"); - result.put(VF_MODULE, "vf-module-id"); - result.put(INSTANCE_GROUP, "id"); - result.put(PORT, "l-interface-id"); - result.put(VG, "volume-group-id"); - result.put(VLAN_TAG, "vlan-id"); - - return result; + .collect(toMap(Map.Entry::getKey, v -> ifTextualGetAsText(v.getValue()))); } - private static HashMap generateTypeToNameKeyMap() { - HashMap result = new HashMap<>(); - result.put(SERVICE_INSTANCE, "service-instance-name"); - result.put(GENERIC_VNF, "vnf-name"); - result.put(NETWORK, "network-name"); - result.put(COLLECTION_RESOURCE, "collection-name"); - result.put(CONFIGURATION, "configuration-name"); - result.put(PNF, "pnf-name"); - result.put(VF_MODULE, "vf-module-name"); - result.put(INSTANCE_GROUP, "instance-group-name"); - result.put(PORT, "l-interface-name"); - result.put(VG, "volume-group-name"); - result.put(VLAN_TAG, "vlan-name"); - - return result; + private Object ifTextualGetAsText(JsonNode jsonNode) { + return jsonNode.isTextual() ? jsonNode.asText() : jsonNode; } -} +} \ No newline at end of file diff --git a/vid-app-common/src/main/java/org/onap/vid/services/AaiService.java b/vid-app-common/src/main/java/org/onap/vid/services/AaiService.java index 910b34112..76efbd0ea 100644 --- a/vid-app-common/src/main/java/org/onap/vid/services/AaiService.java +++ b/vid-app-common/src/main/java/org/onap/vid/services/AaiService.java @@ -48,7 +48,7 @@ public interface AaiService { SubscriberFilteredResults getFullSubscriberList(RoleValidator roleValidator); - AaiResponse getSubscriberData(String subscriberId, RoleValidator roleValidator); + AaiResponse getSubscriberData(String subscriberId, RoleValidator roleValidator, boolean omitServiceInstances); AaiResponse getServiceInstanceSearchResults(String subscriberId, String instanceIdentifier, RoleValidator roleProvider, List owningEntities, List projects); diff --git a/vid-app-common/src/main/java/org/onap/vid/services/AaiServiceImpl.java b/vid-app-common/src/main/java/org/onap/vid/services/AaiServiceImpl.java index d01f0f7ad..961f11096 100644 --- a/vid-app-common/src/main/java/org/onap/vid/services/AaiServiceImpl.java +++ b/vid-app-common/src/main/java/org/onap/vid/services/AaiServiceImpl.java @@ -24,6 +24,7 @@ package org.onap.vid.services; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import io.joshworks.restclient.http.HttpResponse; +import org.apache.commons.lang3.StringUtils; import org.apache.http.HttpStatus; import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; import org.onap.vid.aai.*; @@ -39,16 +40,19 @@ import org.onap.vid.exceptions.GenericUncheckedException; import org.onap.vid.model.ServiceInstanceSearchResult; import org.onap.vid.model.SubscriberList; import org.onap.vid.model.aaiTree.AAITreeNode; +import org.onap.vid.model.aaiTree.NodeType; import org.onap.vid.model.aaiTree.RelatedVnf; import org.onap.vid.roles.RoleValidator; import org.onap.vid.utils.Intersection; import org.onap.vid.utils.Tree; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpMethod; import javax.ws.rs.core.Response; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.util.*; +import java.util.concurrent.ExecutorService; import java.util.stream.Collectors; /** @@ -68,6 +72,8 @@ public class AaiServiceImpl implements AaiService { private AaiResponseTranslator aaiResponseTranslator; private AAITreeNodeBuilder aaiTreeNode; private AAIServiceTree aaiServiceTree; + private ExecutorService executorService; + private static final EELFLoggerDelegate LOGGER = EELFLoggerDelegate.getLogger(AaiServiceImpl.class); @@ -77,13 +83,15 @@ public class AaiServiceImpl implements AaiService { AaiOverTLSClientInterface aaiOverTLSClient, AaiResponseTranslator aaiResponseTranslator, AAITreeNodeBuilder aaiTreeNode, - AAIServiceTree aaiServiceTree) + AAIServiceTree aaiServiceTree, + ExecutorService executorService) { this.aaiClient = aaiClient; this.aaiOverTLSClient = aaiOverTLSClient; this.aaiResponseTranslator = aaiResponseTranslator; this.aaiTreeNode = aaiTreeNode; this.aaiServiceTree = aaiServiceTree; + this.executorService = executorService; } private List convertModelToService(Model model) { @@ -220,8 +228,8 @@ public class AaiServiceImpl implements AaiService { } @Override - public AaiResponse getSubscriberData(String subscriberId, RoleValidator roleValidator) { - AaiResponse subscriberResponse = aaiClient.getSubscriberData(subscriberId); + public AaiResponse getSubscriberData(String subscriberId, RoleValidator roleValidator, boolean omitServiceInstances) { + AaiResponse subscriberResponse = aaiClient.getSubscriberData(subscriberId, omitServiceInstances); String subscriberGlobalId = subscriberResponse.getT().globalCustomerId; for (ServiceSubscription serviceSubscription : subscriberResponse.getT().serviceSubscriptions.serviceSubscription) { String serviceType = serviceSubscription.serviceType; @@ -254,7 +262,7 @@ public class AaiServiceImpl implements AaiService { private List getServicesBySubscriber(String subscriberId, String instanceIdentifier, RoleValidator roleValidator) { - AaiResponse subscriberResponse = aaiClient.getSubscriberData(subscriberId); + AaiResponse subscriberResponse = aaiClient.getSubscriberData(subscriberId, false); String subscriberGlobalId = subscriberResponse.getT().globalCustomerId; String subscriberName = subscriberResponse.getT().subscriberName; ServiceSubscriptions serviceSubscriptions = subscriberResponse.getT().serviceSubscriptions; @@ -483,26 +491,37 @@ public class AaiServiceImpl implements AaiService { @Override public List searchGroupMembers(String globalCustomerId, String serviceType, String invariantId, String groupType, String groupRole) { String getURL = "business/customers/customer/" + - globalCustomerId + "/service-subscriptions/service-subscription/" + - serviceType + "/service-instances?model-invariant-id=" + invariantId; + globalCustomerId + "/service-subscriptions/service-subscription/" + + serviceType + "/service-instances?model-invariant-id=" + invariantId; - Tree pathsToSearch = new Tree<>(new AAIServiceTree.AaiRelationship(AAITreeNodeBuilder.SERVICE_INSTANCE)); - pathsToSearch.addPath(AAITreeNodeBuilder.toAaiRelationshipList(AAITreeNodeBuilder.GENERIC_VNF, AAITreeNodeBuilder.INSTANCE_GROUP)); + Tree pathsToSearch = new Tree<>(new AAIServiceTree.AaiRelationship(NodeType.SERVICE_INSTANCE)); + pathsToSearch.addPath(AAIServiceTree.toAaiRelationshipList(NodeType.GENERIC_VNF, NodeType.INSTANCE_GROUP)); //get all vnfs related to service-instances from the model-invariant-id - List aaiTree = aaiServiceTree.buildAAITree(getURL, pathsToSearch); + List aaiTree = aaiServiceTree.buildAAITree(getURL, null, HttpMethod.GET, pathsToSearch, true); //filter by instance-group-role & instance-group-type properties (from getAdditionalProperties) //only vnfs has related instance-group with the same groupType & groupRole - are filtered out. List filteredVnfs = filterByInstanceGroupRoleAndType(aaiTree, groupRole, groupType); //convert vnfs to expected result - return filteredVnfs.stream() + List convertedVnfs = filteredVnfs.stream() .map(RelatedVnf::from) - .map(this::enrichRelatedVnfWithCloudRegionAndTenant) .collect(Collectors.toList()); + + try { + return executorService.submit(() -> + convertedVnfs.parallelStream() + .map(this::enrichRelatedVnfWithCloudRegionAndTenant) + .collect(Collectors.toList()) + ).get(); + } catch (Exception e) { + LOGGER.error(EELFLoggerDelegate.errorLogger, "Search group Members - Failed to enrich vnf with cloud region", e); + return convertedVnfs; + } } + private List filterByInstanceGroupRoleAndType(List aaiTree, String groupRole, String groupType) { return aaiTree.stream() @@ -544,10 +563,10 @@ public class AaiServiceImpl implements AaiService { } private void getInstanceGroupInfoFromRelationship(org.onap.vid.aai.model.AaiGetNetworkCollectionDetails.Relationship relationship, List instanceGroupInfoList) { - if(relationship.getRelatedTo().equals("instance-group")){ + if(StringUtils.equals(relationship.getRelatedTo(),"instance-group")){ for(org.onap.vid.aai.model.AaiGetNetworkCollectionDetails.RelatedToProperty relatedToProperty: relationship.getRelatedToPropertyList()){ - if(relatedToProperty.getPropertyKey().equals("instance-group.instance-group-name")){ - instanceGroupInfoList.add(new InstanceGroupInfo(relatedToProperty.getPropertyValue())); + if(StringUtils.equals(relatedToProperty.getKey(),"instance-group.instance-group-name")){ + instanceGroupInfoList.add(new InstanceGroupInfo(relatedToProperty.getValue())); } } } diff --git a/vid-app-common/src/main/java/org/onap/vid/services/AsyncInstantiationBusinessLogic.java b/vid-app-common/src/main/java/org/onap/vid/services/AsyncInstantiationBusinessLogic.java index 603f13867..1202fc9e3 100644 --- a/vid-app-common/src/main/java/org/onap/vid/services/AsyncInstantiationBusinessLogic.java +++ b/vid-app-common/src/main/java/org/onap/vid/services/AsyncInstantiationBusinessLogic.java @@ -7,9 +7,9 @@ * 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. @@ -21,17 +21,15 @@ package org.onap.vid.services; import org.onap.vid.aai.model.ResourceType; -import org.onap.vid.changeManagement.RequestDetailsWrapper; import org.onap.vid.job.Job; -import org.onap.vid.model.JobAuditStatus; +import org.onap.vid.job.impl.JobSharedData; import org.onap.vid.model.ServiceInfo; -import org.onap.vid.model.serviceInstantiation.*; -import org.onap.vid.mso.model.*; +import org.onap.vid.model.serviceInstantiation.ServiceInstantiation; +import org.onap.vid.mso.RestObject; import org.onap.vid.mso.rest.AsyncRequestStatus; import java.util.Arrays; import java.util.List; -import java.util.Map; import java.util.UUID; import java.util.function.Consumer; @@ -43,23 +41,7 @@ public interface AsyncInstantiationBusinessLogic { List pushBulkJob(ServiceInstantiation request, String userId); - RequestDetailsWrapper generateMacroServiceInstantiationRequest(UUID uuid, ServiceInstantiation details, String optimisticUniqueServiceInstanceName, String userId); - - RequestDetailsWrapper generateALaCarteServiceInstantiationRequest(UUID uuid, ServiceInstantiation details, String optimisticUniqueServiceInstanceName, String userId); - - RequestDetailsWrapper generateALaCarteServiceDeletionRequest(UUID uuid, ServiceInstantiation details, String userId); - - RequestDetailsWrapper generateVnfInstantiationRequest(Vnf vnfDetails, ModelInfo serviceModelInfo, String serviceInstanceId, String userId); - - RequestDetailsWrapper generateVfModuleInstantiationRequest(VfModule vfModuleDetails, ModelInfo serviceModelInfo, String serviceInstanceId, ModelInfo vnfModelInfo, String vnfInstanceId, String vgInstanceId, String userId); - - RequestDetailsWrapper generateVolumeGroupInstantiationRequest(VfModule vfModuleDetails, ModelInfo serviceModelInfo, String serviceInstanceId, ModelInfo vnfModelInfo, String vnfInstanceId, String userId); - - RequestDetailsWrapper generateNetworkInstantiationRequest(Network networkDetails, ModelInfo serviceModelInfo, String serviceInstanceId, String userId); - - RequestDetailsWrapper generateInstanceGroupInstantiationRequest(InstanceGroup request, ModelInfo serviceModelInfo, String serviceInstanceId, String userId); - - List> buildVnfInstanceParams(List> currentVnfInstanceParams, List vfModules); + boolean isPartOfBulk(UUID jobId); String getServiceInstantiationPath(ServiceInstantiation serviceInstantiationRequest); @@ -67,32 +49,34 @@ public interface AsyncInstantiationBusinessLogic { String getVnfInstantiationPath(String serviceInstanceId); + String getVnfDeletionPath(String serviceInstanceId, String vnfInstanceId); + String getNetworkInstantiationPath(String serviceInstanceId); String getVfmoduleInstantiationPath(String serviceInstanceId, String vnfInstanceId); + String getVfModuleReplacePath(String serviceInstanceId, String vnfInstanceId, String vfModuleInstanceId); + + String getVfModuleDeletePath(String serviceInstanceId, String vnfInstanceId, String vfModuleInstanceId); + String getVolumeGroupInstantiationPath(String serviceInstanceId, String vnfInstanceId); String getInstanceGroupInstantiationPath(); + String getInstanceGroupMemberInstantiationPath(String vnfGroupInstanceId); + String getInstanceGroupDeletePath(String instanceGroupId); - String getOrchestrationRequestsPath(); + String getInstanceGroupMemberDeletePath(String vnfGroupInstanceId); - ServiceInfo getServiceInfoByJobId(UUID jobUUID); + String getNetworkDeletePath(String serviceInstanceId, String networkInstanceId); - List getAuditStatuses(UUID jobUUID, JobAuditStatus.SourceStatus source); + String getOrchestrationRequestsPath(); ServiceInfo updateServiceInfo(UUID jobUUID, Consumer serviceUpdater); ServiceInfo updateServiceInfoAndAuditStatus(UUID jobUuid, Job.JobStatus jobStatus); - void auditVidStatus(UUID jobUUID, Job.JobStatus jobStatus); - - void auditMsoStatus(UUID jobUUID, AsyncRequestStatus.Request msoRequestStatus); - - void auditMsoStatus(UUID jobUUID, String jobStatus, String requestId, String additionalInfo); - Job.JobStatus calcStatus(AsyncRequestStatus asyncRequestStatus); void handleFailedInstantiation(UUID jobUUID); @@ -109,5 +93,21 @@ public interface AsyncInstantiationBusinessLogic { String getUniqueName(String name, ResourceType resourceType); + ServiceInstantiation prepareServiceToBeUnique(ServiceInstantiation serviceInstantiation); + + ServiceInstantiation enrichBulkForRetry(ServiceInstantiation serviceInstantiation, UUID jobId); + + List retryJob(UUID jobId, String userId); + + List retryJob(ServiceInstantiation request, UUID oldJobId, String userId); + + void addResourceInfo(JobSharedData sharedData, Job.JobStatus jobStatus, String instanceId); + + void addFailedResourceInfo(JobSharedData sharedData, RestObject msoResponse); + + void updateResourceInfo(JobSharedData sharedData, Job.JobStatus jobStatus, AsyncRequestStatus message); + + ServiceInstantiation getBulkForRetry(UUID jobId); + String getResumeRequestPath(String requestId); } diff --git a/vid-app-common/src/main/java/org/onap/vid/services/AsyncInstantiationBusinessLogicImpl.java b/vid-app-common/src/main/java/org/onap/vid/services/AsyncInstantiationBusinessLogicImpl.java index 73056db71..92a6d5fd7 100644 --- a/vid-app-common/src/main/java/org/onap/vid/services/AsyncInstantiationBusinessLogicImpl.java +++ b/vid-app-common/src/main/java/org/onap/vid/services/AsyncInstantiationBusinessLogicImpl.java @@ -20,18 +20,28 @@ package org.onap.vid.services; -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.google.common.collect.ImmutableList; +import static org.apache.commons.lang3.ObjectUtils.defaultIfNull; +import static org.onap.vid.controller.MsoController.SVC_INSTANCE_ID; +import static org.onap.vid.controller.MsoController.VNF_INSTANCE_ID; +import static org.onap.vid.utils.KotlinUtilsKt.JACKSON_OBJECT_MAPPER; + import com.google.common.collect.ImmutableMap; +import java.io.IOException; +import java.time.ZonedDateTime; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.function.Consumer; import org.apache.commons.lang3.StringUtils; import org.hibernate.SessionFactory; import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; -import org.onap.portalsdk.core.service.DataAccessService; import org.onap.vid.aai.AaiClientInterface; import org.onap.vid.aai.ExceptionWithRequestInfo; import org.onap.vid.aai.model.ResourceType; -import org.onap.vid.changeManagement.RequestDetailsWrapper; +import org.onap.vid.dal.AsyncInstantiationRepository; import org.onap.vid.exceptions.DbFailureUncheckedException; import org.onap.vid.exceptions.GenericUncheckedException; import org.onap.vid.exceptions.MaxRetriesException; @@ -41,37 +51,26 @@ import org.onap.vid.job.Job.JobStatus; import org.onap.vid.job.JobAdapter; import org.onap.vid.job.JobType; import org.onap.vid.job.JobsBrokerService; +import org.onap.vid.job.impl.JobSharedData; import org.onap.vid.model.Action; -import org.onap.vid.model.JobAuditStatus; import org.onap.vid.model.NameCounter; +import org.onap.vid.model.ResourceInfo; import org.onap.vid.model.ServiceInfo; -import org.onap.vid.model.serviceInstantiation.*; +import org.onap.vid.model.serviceInstantiation.BaseResource; +import org.onap.vid.model.serviceInstantiation.ServiceInstantiation; import org.onap.vid.mso.MsoBusinessLogicImpl; import org.onap.vid.mso.MsoProperties; -import org.onap.vid.mso.model.*; -import org.onap.vid.mso.model.ServiceInstantiationRequestDetails.RequestParameters; -import org.onap.vid.mso.model.ServiceInstantiationRequestDetails.*; -import org.onap.vid.mso.model.VfModuleInstantiationRequestDetails.RequestParametersVfModule; -import org.onap.vid.mso.model.VfModuleInstantiationRequestDetails.UserParamMap; +import org.onap.vid.mso.MsoUtil; +import org.onap.vid.mso.RestObject; import org.onap.vid.mso.rest.AsyncRequestStatus; -import org.onap.vid.mso.rest.SubscriberInfo; +import org.onap.vid.mso.rest.RequestStatus; import org.onap.vid.properties.Features; import org.onap.vid.utils.DaoUtils; +import org.onap.vid.utils.TimeUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.togglz.core.manager.FeatureManager; -import java.sql.Timestamp; -import java.time.LocalDateTime; -import java.util.*; -import java.util.function.Consumer; -import java.util.stream.Collectors; - -import static org.apache.commons.lang3.ObjectUtils.defaultIfNull; -import static org.onap.vid.controller.MsoController.SVC_INSTANCE_ID; -import static org.onap.vid.controller.MsoController.VNF_INSTANCE_ID; -import static org.onap.vid.utils.Logging.debugRequestDetails; - @Service public class AsyncInstantiationBusinessLogicImpl implements AsyncInstantiationBusinessLogic { @@ -79,9 +78,6 @@ public class AsyncInstantiationBusinessLogicImpl implements private static final int MAX_RETRIES_GETTING_COUNTER = 100; private static final int MAX_RETRIES_GETTING_FREE_NAME_FROM_AAI = 10000; public static final String NAME_FOR_CHECK_AAI_STATUS = "NAME_FOR_CHECK_AAI_STATUS"; - private static final String VID_SOURCE = "VID"; - - private final DataAccessService dataAccessService; private final JobAdapter jobAdapter; @@ -89,12 +85,17 @@ public class AsyncInstantiationBusinessLogicImpl implements private final CloudOwnerService cloudOwnerService; + private final AsyncInstantiationRepository asyncInstantiationRepository; + private SessionFactory sessionFactory; private AaiClientInterface aaiClient; private FeatureManager featureManager; + private AuditService auditService; + + private int maxRetriesGettingFreeNameFromAai = MAX_RETRIES_GETTING_FREE_NAME_FROM_AAI; private static final EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(AsyncInstantiationBusinessLogicImpl.class); @@ -107,51 +108,34 @@ public class AsyncInstantiationBusinessLogicImpl implements .put("pending", JobStatus.IN_PROGRESS) .put("pendingmanualtask", JobStatus.PAUSE) .put("unlocked", JobStatus.IN_PROGRESS) + .put("aborted", JobStatus.COMPLETED_WITH_ERRORS) + .put("rolledback", JobStatus.FAILED) + .put("rolledbacktoassigned", JobStatus.FAILED) + .put("rolledbacktocreated", JobStatus.FAILED) .build(); @Autowired - public AsyncInstantiationBusinessLogicImpl(DataAccessService dataAccessService, - JobAdapter jobAdapter, + public AsyncInstantiationBusinessLogicImpl(JobAdapter jobAdapter, JobsBrokerService jobService, SessionFactory sessionFactory, AaiClientInterface aaiClient, FeatureManager featureManager, - CloudOwnerService cloudOwnerService) { - this.dataAccessService = dataAccessService; + CloudOwnerService cloudOwnerService, AsyncInstantiationRepository asyncInstantiationRepository, + AuditService auditService) { this.jobAdapter = jobAdapter; this.jobService = jobService; this.sessionFactory = sessionFactory; this.aaiClient = aaiClient; this.featureManager = featureManager; this.cloudOwnerService = cloudOwnerService; + this.asyncInstantiationRepository = asyncInstantiationRepository; + this.auditService = auditService; } @Override public List getAllServicesInfo() { - return dataAccessService.getList(ServiceInfo.class, filterByCreationDateAndNotDeleted(), orderByCreatedDateAndStatus(), null); - } - - private String filterByCreationDateAndNotDeleted() { - LocalDateTime minus3Months = LocalDateTime.now().minusMonths(3); - Timestamp filterDate = Timestamp.valueOf(minus3Months); - return " where" + - " hidden = false" + - " and deleted_at is null" + // don't fetch deleted - " and created >= '" + filterDate + "' "; - } - - private String orderByCreatedDateAndStatus() { - return " createdBulkDate DESC ,\n" + - " (CASE jobStatus\n" + - " WHEN 'COMPLETED' THEN 0\n" + - " WHEN 'FAILED' THEN 0\n" + - " WHEN 'COMPLETED_WITH_ERRORS' THEN 0\n" + - " WHEN 'IN_PROGRESS' THEN 1\n" + - " WHEN 'PAUSE' THEN 2\n" + - " WHEN 'PENDING' THEN 3\n" + - " WHEN 'STOPPED' THEN 3 END),\n" + - " statusModifiedDate "; + return asyncInstantiationRepository.getAllServicesInfo(); } JobType getJobType(ServiceInstantiation request) { @@ -171,19 +155,26 @@ public class AsyncInstantiationBusinessLogicImpl implements @Override public List pushBulkJob(ServiceInstantiation request, String userId) { + List uuids = new ArrayList<>(); Date createdBulkDate = Calendar.getInstance().getTime(); int bulkSize = request.getBulkSize(); UUID templateId = UUID.randomUUID(); for (int i = 0; i < bulkSize; i++) { - ServiceInfo.ServiceAction serviceAction = getAction(request); - JobType jobType = getJobType(request); - final String optimisticUniqueServiceInstanceName = getOptimisticUniqueServiceInstanceName(request); - Job job = jobAdapter.createServiceInstantiationJob(jobType, request, templateId, userId, optimisticUniqueServiceInstanceName, i); - UUID jobId = jobService.add(job); - dataAccessService.saveDomainObject(createServiceInfo(userId, request, jobId, templateId, createdBulkDate, optimisticUniqueServiceInstanceName, serviceAction), DaoUtils.getPropsMap()); - auditVidStatus(jobId, job.getStatus()); + ServiceInstantiation requestPerJob = prepareServiceToBeUnique(request); + ServiceInfo.ServiceAction serviceAction = getAction(requestPerJob); + JobType jobType = getJobType(requestPerJob); + final String optimisticUniqueServiceInstanceName = bulkSize>1 ? //only bulk with more than 1 service need to get multiple names + getOptimisticUniqueServiceInstanceName(requestPerJob.getInstanceName()) : requestPerJob.getInstanceName(); + Job job = jobAdapter.createServiceInstantiationJob(jobType, requestPerJob, templateId, userId, request.getTestApi(), optimisticUniqueServiceInstanceName, i); + UUID jobId = job.getUuid(); + + asyncInstantiationRepository.saveServiceInfo(createServiceInfo(userId, requestPerJob, jobId, templateId, createdBulkDate, optimisticUniqueServiceInstanceName, serviceAction)); + asyncInstantiationRepository.addJobRequest(jobId, requestPerJob); + auditService.auditVidStatus(jobId, job.getStatus()); uuids.add(jobId); + + jobService.add(job); } return uuids; } @@ -197,8 +188,8 @@ public class AsyncInstantiationBusinessLogicImpl implements } - private String getOptimisticUniqueServiceInstanceName(ServiceInstantiation request) { - return StringUtils.isNotEmpty(request.getInstanceName()) ? getUniqueNameFromDbOnly(request.getInstanceName()) : request.getInstanceName(); + private String getOptimisticUniqueServiceInstanceName(String instanceName) { + return StringUtils.isNotEmpty(instanceName) ? getUniqueNameFromDbOnly(instanceName) : instanceName; } protected ServiceInfo createServiceInfo(String userId, ServiceInstantiation serviceInstantiation, UUID jobId, UUID templateId, Date createdBulkDate, String optimisticUniqueServiceInstanceName, ServiceInfo.ServiceAction serviceAction) { @@ -224,359 +215,32 @@ public class AsyncInstantiationBusinessLogicImpl implements serviceInstantiation.getModelInfo().getModelName(), serviceInstantiation.getModelInfo().getModelVersion(), createdBulkDate, - serviceAction - ); - } - - - @Override - public RequestDetailsWrapper generateMacroServiceInstantiationRequest(UUID jobId, ServiceInstantiation payload, String optimisticUniqueServiceInstanceName, String userId) { - String serviceInstanceName = generateServiceName(jobId, payload, optimisticUniqueServiceInstanceName); - - List serviceInstantiationServiceList = generateServiceInstantiationServicesList(payload, serviceInstanceName, createServiceInstantiationVnfList(payload)); - - RequestParameters requestParameters = new RequestParameters(payload.getSubscriptionServiceType(), false, serviceInstantiationServiceList); - - ServiceInstantiationRequestDetails requestDetails = generateServiceInstantiationRequestDetails(payload,requestParameters,serviceInstanceName, userId); - - RequestDetailsWrapper requestDetailsWrapper = new RequestDetailsWrapper<>(requestDetails); - debugRequestDetails(requestDetailsWrapper, logger); - - return requestDetailsWrapper; + serviceAction, + false); } @Override - public RequestDetailsWrapper generateALaCarteServiceInstantiationRequest(UUID jobId, ServiceInstantiation payload, String optimisticUniqueServiceInstanceName, String userId) { - String serviceInstanceName = generateServiceName(jobId, payload, optimisticUniqueServiceInstanceName); - - List userParams = generateUserParamList(); - - RequestParameters requestParameters = new RequestParameters(payload.getSubscriptionServiceType(), true, userParams, payload.getTestApi()); - - ServiceInstantiationRequestDetails requestDetails = generateServiceInstantiationRequestDetails(payload,requestParameters,serviceInstanceName, userId); - - RequestDetailsWrapper requestDetailsWrapper = new RequestDetailsWrapper<>(requestDetails); - debugRequestDetails(requestDetailsWrapper, logger); - return requestDetailsWrapper; - } - - - @Override - public RequestDetailsWrapper generateALaCarteServiceDeletionRequest(UUID jobId, ServiceInstantiation payload, String userId){ - - ServiceDeletionRequestDetails.RequestParameters requestParameters = new ServiceDeletionRequestDetails.RequestParameters( true, payload.getTestApi()); - - ServiceDeletionRequestDetails.RequestInfo requestInfo = new ServiceDeletionRequestDetails.RequestInfo( - VID_SOURCE, - userId); - - ServiceDeletionRequestDetails requestDetails = new ServiceDeletionRequestDetails(payload.getModelInfo(), requestInfo, requestParameters); - - RequestDetailsWrapper requestDetailsWrapper = new RequestDetailsWrapper<>(requestDetails); - debugRequestDetails(requestDetailsWrapper, logger); - return requestDetailsWrapper; + public boolean isPartOfBulk(UUID jobId) { + if (jobId == null) { + return false; } - - @Override - public RequestDetailsWrapper generateVnfInstantiationRequest(Vnf vnfDetails, ModelInfo serviceModelInfo, String serviceInstanceId, String userId) { - - VnfInstantiationRequestDetails.RequestInfo requestInfo = new VnfInstantiationRequestDetails.RequestInfo( - getUniqueNameIfNeeded(vnfDetails.getInstanceName(), ResourceType.GENERIC_VNF), - vnfDetails.getProductFamilyId(), - VID_SOURCE, - vnfDetails.isRollbackOnFailure(), - userId); - CloudConfiguration cloudConfiguration = generateCloudConfiguration(vnfDetails.getLcpCloudRegionId(), vnfDetails.getTenantId()); - VnfInstantiationRequestDetails.Platform platform = new VnfInstantiationRequestDetails.Platform(vnfDetails.getPlatformName()); - VnfInstantiationRequestDetails.LineOfBusiness lineOfBusiness = new VnfInstantiationRequestDetails.LineOfBusiness(vnfDetails.getLineOfBusiness()); - VnfInstantiationRequestDetails.RequestParameters requestParameters = new VnfInstantiationRequestDetails.RequestParameters(generateUserParamList()); - VnfInstantiationRequestDetails.RelatedInstance serviceInstance = new VnfInstantiationRequestDetails.RelatedInstance(serviceModelInfo, serviceInstanceId); - List relatedInstanceList = new ArrayList<>(); - relatedInstanceList.add(serviceInstance); - return new RequestDetailsWrapper<>(new VnfInstantiationRequestDetails(vnfDetails.getModelInfo(), cloudConfiguration, requestInfo, platform, lineOfBusiness, relatedInstanceList, requestParameters)); + ServiceInfo serviceInfo = asyncInstantiationRepository.getServiceInfoByJobId(jobId); + UUID templateId = serviceInfo.getTemplateId(); + if (templateId != null) { + return getNumberOfJobsInBulk(templateId) > 1; } + return false; - @Override - public RequestDetailsWrapper generateVfModuleInstantiationRequest(VfModule vfModuleDetails, ModelInfo serviceModelInfo, String serviceInstanceId, ModelInfo vnfModelInfo, String vnfInstanceId, String vgInstanceId, String userId) { - - VfModuleInstantiationRequestDetails.RequestInfo requestInfo = new VfModuleInstantiationRequestDetails.RequestInfo( - getUniqueNameIfNeeded(vfModuleDetails.getInstanceName(), ResourceType.VF_MODULE), - null, - VID_SOURCE, - vfModuleDetails.isRollbackOnFailure(), - userId); - - //cloud configuration - CloudConfiguration cloudConfiguration = generateCloudConfiguration(vfModuleDetails.getLcpCloudRegionId(), vfModuleDetails.getTenantId()); - - //request parameters - List> userParams = aggregateAllInstanceParams(extractActualInstanceParams(vfModuleDetails.getInstanceParams()), vfModuleDetails.getSupplementaryParams()); - RequestParametersVfModule requestParameters = new RequestParametersVfModule(userParams, vfModuleDetails.isUsePreload()); - - //related instance list - VfModuleInstantiationRequestDetails.RelatedInstance serviceInstance = new VfModuleInstantiationRequestDetails.RelatedInstance(serviceModelInfo, serviceInstanceId); - VfModuleInstantiationRequestDetails.RelatedInstance vnfInstance = new VfModuleInstantiationRequestDetails.RelatedInstance(vnfModelInfo, vnfInstanceId); - List relatedInstanceList = new ArrayList<>(); - relatedInstanceList.add(serviceInstance); - relatedInstanceList.add(vnfInstance); - if (vgInstanceId != null) { - ModelInfo volumeGroupModel = new ModelInfo(); - volumeGroupModel.setModelType("volumeGroup"); - VfModuleInstantiationRequestDetails.RelatedInstance volumeGroupInstance = new VfModuleInstantiationRequestDetails.RelatedInstance(volumeGroupModel, vgInstanceId, vfModuleDetails.getVolumeGroupInstanceName()); - relatedInstanceList.add(volumeGroupInstance); - } - - return new RequestDetailsWrapper<>(new VfModuleInstantiationRequestDetails(vfModuleDetails.getModelInfo(), cloudConfiguration, requestInfo, relatedInstanceList, requestParameters)); } - protected CloudConfiguration generateCloudConfiguration(String lcpCloudRegionId, String tenantId) { - CloudConfiguration cloudConfiguration = new CloudConfiguration(); - cloudConfiguration.setLcpCloudRegionId(lcpCloudRegionId); - cloudConfiguration.setTenantId(tenantId); - cloudOwnerService.enrichCloudConfigurationWithCloudOwner(cloudConfiguration, lcpCloudRegionId); - return cloudConfiguration; - } - - @Override - public RequestDetailsWrapper generateVolumeGroupInstantiationRequest(VfModule vfModuleDetails, ModelInfo serviceModelInfo, String serviceInstanceId, ModelInfo vnfModelInfo, String vnfInstanceId, String userId) { - VolumeGroupRequestDetails.RequestInfo requestInfo = new VolumeGroupRequestDetails.RequestInfo( - getUniqueNameIfNeeded(vfModuleDetails.getVolumeGroupInstanceName(), ResourceType.VOLUME_GROUP), - null, - VID_SOURCE, - vfModuleDetails.isRollbackOnFailure(), - userId); - CloudConfiguration cloudConfiguration = generateCloudConfiguration(vfModuleDetails.getLcpCloudRegionId(), vfModuleDetails.getTenantId()); - - List> userParams = aggregateAllInstanceParams(extractActualInstanceParams(vfModuleDetails.getInstanceParams()), vfModuleDetails.getSupplementaryParams()); - RequestParametersVfModule requestParameters = new RequestParametersVfModule(userParams, vfModuleDetails.isUsePreload()); - - VfModuleInstantiationRequestDetails.RelatedInstance serviceInstance = new VfModuleInstantiationRequestDetails.RelatedInstance(serviceModelInfo, serviceInstanceId); - VfModuleInstantiationRequestDetails.RelatedInstance vnfInstance = new VfModuleInstantiationRequestDetails.RelatedInstance(vnfModelInfo, vnfInstanceId); - List relatedInstancs = ImmutableList.of(serviceInstance, vnfInstance); - - ModelInfo modelInfo = vfModuleDetails.getModelInfo(); - modelInfo.setModelType("volumeGroup"); - return new RequestDetailsWrapper<>(new VolumeGroupRequestDetails(modelInfo, cloudConfiguration, requestInfo, relatedInstancs, requestParameters)); - } - - protected List> aggregateAllInstanceParams(Map instanceParams, Map supplementaryParams) { - Map instanceParamsFinal = defaultIfNull(instanceParams, new HashMap<>()); - Map supplementaryParamsFinal = defaultIfNull(supplementaryParams, new HashMap<>()); - - if (!(instanceParamsFinal.isEmpty() && supplementaryParamsFinal.isEmpty())) { - //remove duplicate keys from instanceParams if exist in supplementaryParams - instanceParamsFinal = instanceParams.entrySet().stream().filter(m-> - !supplementaryParamsFinal.containsKey(m.getKey()) - ).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); - - //aggregate the 2 collections and format them as UserParamMap - UserParamMap aggregatedParams = new UserParamMap<>(); - aggregatedParams.putAll(instanceParamsFinal); - aggregatedParams.putAll(supplementaryParamsFinal); - - return ImmutableList.of(aggregatedParams); - } - - return Collections.emptyList(); - } - - @Override - public RequestDetailsWrapper generateNetworkInstantiationRequest(Network networkDetails, ModelInfo serviceModelInfo, String serviceInstanceId, String userId) { - - NetworkInstantiationRequestDetails.RequestInfo requestInfo = new NetworkInstantiationRequestDetails.RequestInfo( - getUniqueNameIfNeeded(networkDetails.getInstanceName(), ResourceType.L3_NETWORK), - networkDetails.getProductFamilyId(), - VID_SOURCE, - networkDetails.isRollbackOnFailure(), - userId); - CloudConfiguration cloudConfiguration = generateCloudConfiguration(networkDetails.getLcpCloudRegionId(), networkDetails.getTenantId()); - NetworkInstantiationRequestDetails.Platform platform = new NetworkInstantiationRequestDetails.Platform(networkDetails.getPlatformName()); - NetworkInstantiationRequestDetails.LineOfBusiness lineOfBusiness = new NetworkInstantiationRequestDetails.LineOfBusiness(networkDetails.getLineOfBusiness()); - NetworkInstantiationRequestDetails.RequestParameters requestParameters = new NetworkInstantiationRequestDetails.RequestParameters(generateUserParamList()); - NetworkInstantiationRequestDetails.RelatedInstance serviceInstance = new NetworkInstantiationRequestDetails.RelatedInstance(serviceModelInfo, serviceInstanceId); - List relatedInstanceList = new ArrayList<>(); - relatedInstanceList.add(serviceInstance); - return new RequestDetailsWrapper<>(new NetworkInstantiationRequestDetails(networkDetails.getModelInfo(), cloudConfiguration, requestInfo, platform, lineOfBusiness, relatedInstanceList, requestParameters)); - } - - @Override - public RequestDetailsWrapper generateInstanceGroupInstantiationRequest(InstanceGroup instanceGroupDetails, ModelInfo serviceModelInfo, String serviceInstanceId, String userId) { - InstanceGroupInstantiationRequestDetails.RequestInfo requestInfo = new InstanceGroupInstantiationRequestDetails.RequestInfo( - getUniqueNameIfNeeded(instanceGroupDetails.getInstanceName(), ResourceType.INSTANCE_GROUP), - null, - "VID", - instanceGroupDetails.isRollbackOnFailure(), - userId); - InstanceGroupInstantiationRequestDetails.RequestParameters requestParameters = new InstanceGroupInstantiationRequestDetails.RequestParameters(generateUserParamList()); - InstanceGroupInstantiationRequestDetails.RelatedInstance serviceInstance = new InstanceGroupInstantiationRequestDetails.RelatedInstance(serviceModelInfo, serviceInstanceId); - List relatedInstanceList = ImmutableList.of(serviceInstance); - return new RequestDetailsWrapper<>(new InstanceGroupInstantiationRequestDetails(instanceGroupDetails.getModelInfo(), requestInfo, relatedInstanceList, requestParameters)); - } - - // TODO - private List generateUserParamList() { - return Collections.emptyList(); - } - - protected List generateServiceInstantiationServicesList(ServiceInstantiation payload, String serviceInstanceName, ServiceInstantiationVnfList vnfList) { - List serviceInstantiationServiceList = new LinkedList<>(); - List> unFilteredInstanceParams = defaultIfNull(payload.getInstanceParams(), Collections.emptyList()); - List> filteredInstanceParams = removeUnNeededParams(unFilteredInstanceParams); - ServiceInstantiationService serviceInstantiationService = new ServiceInstantiationService( - payload.getModelInfo(), - serviceInstanceName, - filteredInstanceParams, - vnfList + private int getNumberOfJobsInBulk(UUID templateId) { + String hqlSelectJob = "from JobDaoImpl where templateId = :templateId"; + return DaoUtils.tryWithSessionAndTransaction(sessionFactory, session -> + session.createQuery(hqlSelectJob) + .setText("templateId", templateId.toString()) + .list() + .size() ); - serviceInstantiationServiceList.add(serviceInstantiationService); - return serviceInstantiationServiceList; - } - - private ServiceInstantiationRequestDetails generateServiceInstantiationRequestDetails(ServiceInstantiation payload, RequestParameters requestParameters, String serviceInstanceName, String userId) { - ServiceInstantiationRequestDetails.RequestInfo requestInfo = new ServiceInstantiationRequestDetails.RequestInfo(serviceInstanceName, - payload.getProductFamilyId(), - VID_SOURCE, - payload.isRollbackOnFailure(), - userId); - ServiceInstantiationOwningEntity owningEntity = new ServiceInstantiationOwningEntity(payload.getOwningEntityId(), payload.getOwningEntityName()); - SubscriberInfo subscriberInfo = generateSubscriberInfo(payload); - Project project = payload.getProjectName() != null ? new Project(payload.getProjectName()) : null; - return new ServiceInstantiationRequestDetails(payload.getModelInfo(), owningEntity, subscriberInfo, project, requestInfo, requestParameters); - } - - - protected SubscriberInfo generateSubscriberInfo(ServiceInstantiation payload) { - SubscriberInfo subscriberInfo = new SubscriberInfo(); - subscriberInfo.setGlobalSubscriberId(payload.getGlobalSubscriberId()); - return subscriberInfo; - } - - protected String generateServiceName(UUID jobId, ServiceInstantiation payload, String optimisticUniqueServiceInstanceName) { - String serviceInstanceName = null; - if(StringUtils.isNotEmpty(optimisticUniqueServiceInstanceName)) { - serviceInstanceName = peekServiceName(jobId, payload, optimisticUniqueServiceInstanceName); - } - return serviceInstanceName; - } - - protected String peekServiceName(UUID jobId, ServiceInstantiation payload, String optimisticUniqueServiceInstanceName) { - String serviceInstanceName; - // unique name already exist in service info. If it's free in AAI we use it - if (isNameFreeInAai(optimisticUniqueServiceInstanceName, ResourceType.SERVICE_INSTANCE)) { - serviceInstanceName = optimisticUniqueServiceInstanceName; - } - //otherwise we used the original service instance name (from payload) to get a new unique name from DB and AAI - else { - serviceInstanceName = getUniqueName(payload.getInstanceName(), ResourceType.SERVICE_INSTANCE); - } - - //update serviceInfo with new name if needed - try { - updateServiceInfo(jobId, x -> x.setServiceInstanceName(serviceInstanceName)); - } catch (Exception e) { - logger.error("Failed updating service name {} in serviceInfo", serviceInstanceName, e); - } - - return serviceInstanceName; - } - - @Override - public List> buildVnfInstanceParams(List> currentVnfInstanceParams, List vfModules){ - List> filteredVnfInstanceParams = removeUnNeededParams(currentVnfInstanceParams); - - if (!featureManager.isActive(Features.FLAG_SHIFT_VFMODULE_PARAMS_TO_VNF)) { - return filteredVnfInstanceParams; - } - - Map vnfInstanceParams = extractActualInstanceParams(filteredVnfInstanceParams); - vfModules.stream() - .map(x->extractActualInstanceParams(x.getInstanceParams())) - .forEach(vnfInstanceParams::putAll); - return vnfInstanceParams.isEmpty() ? Collections.emptyList() : ImmutableList.of(vnfInstanceParams); - } - - //Make sure we always get a one Map from InstanceParams - private Map extractActualInstanceParams(List> originalInstanceParams) { - if (originalInstanceParams==null || originalInstanceParams.isEmpty() || originalInstanceParams.get(0)==null) { - return new HashMap<>(); - } - return originalInstanceParams.get(0); - } - - private List> removeUnNeededParams(List> instanceParams) { - List keysToRemove = new ArrayList<>(); - if (instanceParams == null || instanceParams.isEmpty()) { - return Collections.emptyList(); - } - - for (String key : instanceParams.get(0).keySet()) { - for (String paramToIgnore : PARAMS_TO_IGNORE) - if ((key.equalsIgnoreCase(paramToIgnore))) { - keysToRemove.add(key); - } - } - - Map result = instanceParams.get(0).entrySet().stream() - .filter(entry->!keysToRemove.contains(entry.getKey())) - .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); - - return result.isEmpty() ? Collections.emptyList() : Collections.singletonList(result); - } - - private ServiceInstantiationVnfList createServiceInstantiationVnfList(ServiceInstantiation payload) { - CloudConfiguration cloudConfiguration = generateCloudConfiguration(payload.getLcpCloudRegionId(), payload.getTenantId()); - - Map vnfs = payload.getVnfs(); - List vnfList = new ArrayList<>(); - for (Vnf vnf : vnfs.values()) { - Map> vfModules = vnf.getVfModules(); - List convertedUnFilteredVfModules = convertVfModuleMapToList(vfModules); - List filteredVfModules = filterInstanceParamsFromVfModuleAndUniqueNames(convertedUnFilteredVfModules); - ServiceInstantiationVnf serviceInstantiationVnf = new ServiceInstantiationVnf( - vnf.getModelInfo(), - cloudConfiguration, - vnf.getPlatformName(), - vnf.getLineOfBusiness(), - payload.getProductFamilyId(), - buildVnfInstanceParams(vnf.getInstanceParams(), filteredVfModules), - filteredVfModules, - getUniqueNameIfNeeded(vnf.getInstanceName(), ResourceType.GENERIC_VNF) - ); - vnfList.add(serviceInstantiationVnf); - } - - return new ServiceInstantiationVnfList(vnfList); - } - - private List convertVfModuleMapToList(Map> vfModules) { - ObjectMapper mapper = new ObjectMapper(); - return vfModules.values().stream().flatMap(vfModule -> - vfModule.values().stream().map(item -> { - List> aggregatedParams = aggregateAllInstanceParams(extractActualInstanceParams(item.getInstanceParams()), item.getSupplementaryParams()); - List> aggregatedParamsConverted = mapper.convertValue(aggregatedParams, new TypeReference>(){}); - - return new VfModuleMacro( - item.getModelInfo(), - item.getInstanceName(), - item.getVolumeGroupInstanceName(), - aggregatedParamsConverted); - } - ) - ).collect(Collectors.toList()); - } - - private List filterInstanceParamsFromVfModuleAndUniqueNames(List unFilteredVfModules) { - return unFilteredVfModules.stream().map(vfModule -> - new VfModuleMacro( - vfModule.getModelInfo(), - getUniqueNameIfNeeded(vfModule.getInstanceName(), ResourceType.VF_MODULE), - getUniqueNameIfNeeded(vfModule.getVolumeGroupInstanceName(), ResourceType.VOLUME_GROUP), - removeUnNeededParams(vfModule.getInstanceParams()))) - .collect(Collectors.toList()); - } - - private String getUniqueNameIfNeeded(String name, ResourceType resourceType) { - return StringUtils.isNotEmpty(name) ? getUniqueName(name, resourceType) : null; } @Override @@ -599,6 +263,13 @@ public class AsyncInstantiationBusinessLogicImpl implements replaceFirst(SVC_INSTANCE_ID, serviceInstanceId); } + @Override + public String getVnfDeletionPath(String serviceInstanceId, String vnfInstanceId) { + return (MsoBusinessLogicImpl.validateEndpointPath(MsoProperties.MSO_REST_API_VNF_INSTANCE) + + '/' + vnfInstanceId) + .replaceFirst(SVC_INSTANCE_ID, serviceInstanceId).replaceFirst(VNF_INSTANCE_ID, vnfInstanceId); + } + @Override public String getNetworkInstantiationPath(String serviceInstanceId) { return MsoBusinessLogicImpl.validateEndpointPath(MsoProperties.MSO_REST_API_NETWORK_INSTANCE). @@ -612,6 +283,24 @@ public class AsyncInstantiationBusinessLogicImpl implements .replaceFirst(VNF_INSTANCE_ID, vnfInstanceId); } + @Override + public String getVfModuleReplacePath(String serviceInstanceId, String vnfInstanceId, String vfModuleInstanceId) + { + return MsoBusinessLogicImpl.validateEndpointPath(MsoProperties.MSO_REST_API_VF_MODULE_INSTANCE) + .replaceFirst(SVC_INSTANCE_ID, serviceInstanceId) + .replaceFirst(VNF_INSTANCE_ID, vnfInstanceId) + + "/" + vfModuleInstanceId + + "/replace"; + } + + @Override + public String getVfModuleDeletePath(String serviceInstanceId, String vnfInstanceId, String vfModuleInstanceId) { + return MsoBusinessLogicImpl.validateEndpointPath(MsoProperties.MSO_REST_API_VF_MODULE_INSTANCE) + .replaceFirst(SVC_INSTANCE_ID, serviceInstanceId) + .replaceFirst(VNF_INSTANCE_ID, vnfInstanceId) + + "/" + vfModuleInstanceId; + } + @Override public String getVolumeGroupInstantiationPath(String serviceInstanceId, String vnfInstanceId) { return MsoBusinessLogicImpl.validateEndpointPath(MsoProperties.MSO_REST_API_VOLUME_GROUP_INSTANCE) @@ -625,79 +314,64 @@ public class AsyncInstantiationBusinessLogicImpl implements } @Override - public String getInstanceGroupDeletePath(String instanceGroupId) { + public String getInstanceGroupMemberInstantiationPath(String vnfGroupInstanceId) { return MsoBusinessLogicImpl.validateEndpointPath(MsoProperties.MSO_REST_API_INSTANCE_GROUP) - + '/' + instanceGroupId; + + '/' + vnfGroupInstanceId + "/addMembers"; } @Override - public String getOrchestrationRequestsPath() { - return MsoBusinessLogicImpl.validateEndpointPath(MsoProperties.MSO_REST_API_GET_ORC_REQ); + public String getInstanceGroupDeletePath(String instanceGroupId) { + return MsoBusinessLogicImpl.validateEndpointPath(MsoProperties.MSO_REST_API_INSTANCE_GROUP) + + '/' + instanceGroupId; } @Override - public ServiceInfo updateServiceInfo(UUID jobUUID, Consumer serviceUpdater) { - ServiceInfo serviceInfo = getServiceInfoByJobId(jobUUID); - serviceUpdater.accept(serviceInfo); - dataAccessService.saveDomainObject(serviceInfo, DaoUtils.getPropsMap()); - return serviceInfo; + public String getInstanceGroupMemberDeletePath(String vnfGroupInstanceId){ + return MsoBusinessLogicImpl.validateEndpointPath(MsoProperties.MSO_REST_API_INSTANCE_GROUP) + + '/' + vnfGroupInstanceId + "/removeMembers"; } @Override - public ServiceInfo updateServiceInfoAndAuditStatus(UUID jobUuid, JobStatus jobStatus) { - auditVidStatus(jobUuid,jobStatus); - return updateServiceInfo(jobUuid, x -> setServiceInfoStatus(x, jobStatus)); - } - - private void setServiceInfoStatus(ServiceInfo serviceInfo, JobStatus jobStatus) { - serviceInfo.setJobStatus(jobStatus); - serviceInfo.setStatusModifiedDate(new Date()); - } - - public ServiceInfo getServiceInfoByJobId(UUID jobUUID) { - List serviceInfoList = dataAccessService.getList(ServiceInfo.class, String.format(" where jobId = '%s' ", jobUUID), null, null); - if (serviceInfoList.size() != 1) { - throw new GenericUncheckedException("Failed to retrieve job with uuid " + jobUUID + " from ServiceInfo table. Instances found: " + serviceInfoList.size()); - } - return serviceInfoList.get(0); + public String getNetworkDeletePath(String serviceInstanceId, String networkInstanceId) { + return (MsoBusinessLogicImpl.validateEndpointPath(MsoProperties.MSO_REST_API_NETWORK_INSTANCE) + + "/" + networkInstanceId) + .replaceFirst(SVC_INSTANCE_ID, serviceInstanceId); } - public List getAuditStatuses(UUID jobUUID, JobAuditStatus.SourceStatus source) { - return dataAccessService.getList( - JobAuditStatus.class, - String.format(" where SOURCE = '%s' and JOB_ID = '%s'",source, jobUUID), - " CREATED_DATE ", null); - } - - private JobAuditStatus getLatestAuditStatus(UUID jobUUID, JobAuditStatus.SourceStatus source){ - List list = getAuditStatuses(jobUUID,source); - return !list.isEmpty() ? list.get(list.size()-1) : null; + @Override + public String getResumeRequestPath(String requestId) { + return MsoBusinessLogicImpl.validateEndpointPath("mso.restapi.resume.orc.req") + .replaceFirst("", requestId); } @Override - public void auditVidStatus(UUID jobUUID, JobStatus jobStatus){ - JobAuditStatus vidStatus = new JobAuditStatus(jobUUID, jobStatus.toString(), JobAuditStatus.SourceStatus.VID); - auditStatus(vidStatus); + public String getOrchestrationRequestsPath() { + return MsoBusinessLogicImpl.validateEndpointPath(MsoProperties.MSO_REST_API_GET_ORC_REQ); } @Override - public void auditMsoStatus(UUID jobUUID, AsyncRequestStatus.Request msoRequestStatus){ - auditMsoStatus(jobUUID, msoRequestStatus.requestStatus.getRequestState(), msoRequestStatus.requestId, msoRequestStatus.requestStatus.getStatusMessage()); + public ServiceInfo updateServiceInfo(UUID jobUUID, Consumer serviceUpdater) { + ServiceInfo serviceInfo = asyncInstantiationRepository.getServiceInfoByJobId(jobUUID); + serviceUpdater.accept(serviceInfo); + asyncInstantiationRepository.saveServiceInfo(serviceInfo); + return serviceInfo; } @Override - public void auditMsoStatus(UUID jobUUID, String jobStatus, String requestId, String additionalInfo){ - JobAuditStatus msoStatus = new JobAuditStatus(jobUUID, jobStatus, JobAuditStatus.SourceStatus.MSO, - requestId != null ? UUID.fromString(requestId) : null, - additionalInfo); - auditStatus(msoStatus); + public ServiceInfo updateServiceInfoAndAuditStatus(UUID jobUuid, JobStatus jobStatus) { + auditService.auditVidStatus(jobUuid, jobStatus); + return updateServiceInfo(jobUuid, x -> setServiceInfoStatus(x, jobStatus)); } - private void auditStatus(JobAuditStatus jobAuditStatus){ - JobAuditStatus latestStatus = getLatestAuditStatus(jobAuditStatus.getJobId(), jobAuditStatus.getSource()); - if (latestStatus == null || !latestStatus.equals(jobAuditStatus)) - dataAccessService.saveDomainObject(jobAuditStatus, DaoUtils.getPropsMap()); + private boolean isRetryEnabledForStatus(JobStatus jobStatus) { + return featureManager.isActive(Features.FLAG_1902_RETRY_JOB) && + (jobStatus==JobStatus.COMPLETED_WITH_ERRORS || jobStatus==JobStatus.FAILED); + } + private void setServiceInfoStatus(ServiceInfo serviceInfo, JobStatus jobStatus) { + serviceInfo.setJobStatus(jobStatus); + serviceInfo.setStatusModifiedDate(new Date()); + serviceInfo.setRetryEnabled(isRetryEnabledForStatus(jobStatus)); } public Job.JobStatus calcStatus(AsyncRequestStatus asyncRequestStatus) { @@ -708,13 +382,8 @@ public class AsyncInstantiationBusinessLogicImpl implements @Override public void handleFailedInstantiation(UUID jobUUID) { - ServiceInfo serviceInfo = updateServiceInfoAndAuditStatus(jobUUID, JobStatus.FAILED); - List serviceInfoList = dataAccessService.getList( - ServiceInfo.class, - String.format(" where templateId = '%s' and jobStatus = '%s'", - serviceInfo.getTemplateId(), - JobStatus.PENDING), - null, null); + ServiceInfo serviceInfo = asyncInstantiationRepository.getServiceInfoByJobId(jobUUID); + List serviceInfoList = asyncInstantiationRepository.getServiceInfoByTemplateIdAndJobStatus(serviceInfo.getTemplateId(), JobStatus.PENDING); serviceInfoList.forEach(si -> updateServiceInfoAndAuditStatus(si.getJobId(), JobStatus.STOPPED)); } @@ -727,16 +396,16 @@ public class AsyncInstantiationBusinessLogicImpl implements @Override public void hideServiceInfo(UUID jobUUID) { - ServiceInfo serviceInfo = getServiceInfoByJobId(jobUUID); + ServiceInfo serviceInfo = asyncInstantiationRepository.getServiceInfoByJobId(jobUUID); if (!serviceInfo.getJobStatus().isFinal()) { - String message = String.format( "jobId %s: Service status does not allow hide service, status = %s", + String message = String.format("jobId %s: Service status does not allow hide service, status = %s", serviceInfo.getJobId(), serviceInfo.getJobStatus()); logger.error(EELFLoggerDelegate.errorLogger, message); throw new OperationNotAllowedException(message); } serviceInfo.setHidden(true); - dataAccessService.saveDomainObject(serviceInfo, DaoUtils.getPropsMap()); + asyncInstantiationRepository.saveServiceInfo(serviceInfo); } @Override @@ -818,7 +487,84 @@ public class AsyncInstantiationBusinessLogicImpl implements } } - throw new MaxRetriesException("find unused name for "+name, getMaxRetriesGettingFreeNameFromAai()); + throw new MaxRetriesException("can't find unused name for "+name, getMaxRetriesGettingFreeNameFromAai()); + } + + @Override + public ServiceInstantiation prepareServiceToBeUnique(ServiceInstantiation serviceInstantiation) { + try { + ServiceInstantiation clonedServiceInstantiation = JACKSON_OBJECT_MAPPER.readValue( + JACKSON_OBJECT_MAPPER.writeValueAsBytes(serviceInstantiation), ServiceInstantiation.class); + clonedServiceInstantiation.setBulkSize(1); + return replaceAllTrackById(clonedServiceInstantiation); + } catch (IOException e) { + throw new GenericUncheckedException(e); + } + + } + + private T replaceAllTrackById(T resource) { + resource.setTrackById(UUID.randomUUID().toString()); + resource.getChildren().forEach(this::replaceAllTrackById); + return resource; + } + + @Override + public List retryJob(ServiceInstantiation request, UUID jobId, String userId ) { + updateServiceInfo(jobId, si->si.setRetryEnabled(false)); + return pushBulkJob(request, userId); + } + + @Override + public List retryJob(UUID jobId, String userId) { + ServiceInstantiation serviceInstantiationRequest = asyncInstantiationRepository.getJobRequest(jobId); + enrichBulkForRetry(serviceInstantiationRequest, jobId); + + try { + logger.debug(EELFLoggerDelegate.debugLogger, "retry ServiceInstantiation request: "+ + JACKSON_OBJECT_MAPPER.writeValueAsString(serviceInstantiationRequest)); + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger, "failed to log retry of ServiceInstantiation request ", e); + } + return retryJob(serviceInstantiationRequest, jobId, userId); + } + + @Override + public ServiceInstantiation getBulkForRetry(UUID jobId) { + return enrichBulkForRetry( asyncInstantiationRepository.getJobRequest(jobId), jobId); + } + + @Override + public void addResourceInfo(JobSharedData sharedData, Job.JobStatus jobStatus, String instanceId) { + String trackById = ((BaseResource) sharedData.getRequest()).getTrackById(); + ResourceInfo resourceInfo = new ResourceInfo(trackById, sharedData.getRootJobId(), instanceId, jobStatus, null); + asyncInstantiationRepository.saveResourceInfo(resourceInfo); + } + + @Override + public void addFailedResourceInfo(JobSharedData sharedData, RestObject msoResponse) { + String trackById = ((BaseResource) sharedData.getRequest()).getTrackById(); + String errorMessage = MsoUtil.formatExceptionAdditionalInfo(msoResponse.getStatusCode(), msoResponse.getRaw()); + AsyncRequestStatus asyncRequestStatus = convertMessageToAsyncRequestStatus(errorMessage); + ResourceInfo resourceInfo = new ResourceInfo(trackById, sharedData.getRootJobId(), null, JobStatus.FAILED, asyncRequestStatus); + + asyncInstantiationRepository.saveResourceInfo(resourceInfo); + } + + @Override + public void updateResourceInfo(JobSharedData sharedData, JobStatus jobStatus, AsyncRequestStatus message) { + ResourceInfo resourceInfo = asyncInstantiationRepository.getResourceInfoByTrackId(((BaseResource) sharedData.getRequest()).getTrackById()); + resourceInfo.setJobStatus(jobStatus); + if (jobStatus.isFailure()) { + resourceInfo.setErrorMessage(message); + } + asyncInstantiationRepository.saveResourceInfo(resourceInfo); + } + + public AsyncRequestStatus convertMessageToAsyncRequestStatus(String message) { + RequestStatus requestStatus = new RequestStatus("FAILED", message, TimeUtils.zonedDateTimeToString(ZonedDateTime.now())); + AsyncRequestStatus.Request request = new AsyncRequestStatus.Request(requestStatus); + return new AsyncRequestStatus(request); } protected String getUniqueNameFromDbOnly(String name) { @@ -835,4 +581,35 @@ public class AsyncInstantiationBusinessLogicImpl implements return !aaiClient.isNodeTypeExistsByName(name, resourceType); } + @Override + public ServiceInstantiation enrichBulkForRetry(ServiceInstantiation serviceInstantiation, UUID jobId){ + Map resourceInfoByTrackId = asyncInstantiationRepository.getResourceInfoByRootJobId(jobId); + + return setResourceStatus(resourceInfoByTrackId, serviceInstantiation); + } + + protected String readStatusMsg(ResourceInfo resourceInfo){ + if(resourceInfo!=null && resourceInfo.getErrorMessage()!=null && resourceInfo.getErrorMessage().request != null &&resourceInfo.getErrorMessage().request.requestStatus != null ) { + return resourceInfo.getErrorMessage().request.requestStatus.getStatusMessage(); + } + return null; + } + + private T setResourceStatus(Map resourceInfoByTrackId, T resource) { + ResourceInfo resourceInfo = resourceInfoByTrackId.get(resource.getTrackById()); + if(resourceInfo != null) { + boolean failed = resourceInfo.getJobStatus().isFailure(); + resource.setIsFailed(failed); + resource.setStatusMessage(readStatusMsg(resourceInfo)); + if (!failed) { + // if(resource.getAction().equals(Action.Delete)){ + // TODO not yet implemented- completed after delete should remove the node + resource.setAction(Action.None); + resource.setInstanceId(resourceInfo.getInstanceId()); + } + } + resource.getChildren().forEach(child -> setResourceStatus(resourceInfoByTrackId, child)); + return resource; + } + } diff --git a/vid-app-common/src/main/java/org/onap/vid/services/AuditService.java b/vid-app-common/src/main/java/org/onap/vid/services/AuditService.java index ef60c321d..6370b1862 100644 --- a/vid-app-common/src/main/java/org/onap/vid/services/AuditService.java +++ b/vid-app-common/src/main/java/org/onap/vid/services/AuditService.java @@ -7,9 +7,9 @@ * 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. @@ -20,19 +20,31 @@ package org.onap.vid.services; -import org.onap.vid.model.JobAuditStatus; - import java.util.List; import java.util.UUID; +import org.onap.vid.job.Job; +import org.onap.vid.model.JobAuditStatus; +import org.onap.vid.mso.rest.AsyncRequestStatus; public interface AuditService { void setFailedAuditStatusFromMso(UUID jobUuid, String requestId, int statusCode, String msoResponse); - List getAuditStatusFromMsoByRequestId(UUID jobId, UUID requestId); - List getAuditStatusFromMsoByServiceInstanceId(UUID jobId, UUID serviceInstanceId); + List getAuditStatusFromMsoByInstanceId(JobAuditStatus.ResourceTypeFilter resourceTypeFilter, UUID instanceId, UUID jobId); List getAuditStatusFromMsoByJobId(UUID jobId); + + void auditVidStatus(UUID jobUUID, Job.JobStatus jobStatus); + + void auditMsoStatus(UUID jobUUID, AsyncRequestStatus.Request msoRequestStatus); + + void auditMsoStatus(UUID jobUUID, String jobStatus, String requestId, String additionalInfo); + + List retrieveRequestsFromMsoByServiceIdAndRequestTypeAndScope(String instanceId, String requestType, String modelType); + + List getAuditStatuses(UUID jobUUID, JobAuditStatus.SourceStatus source); + + JobAuditStatus getResourceAuditStatus(String trackById); } diff --git a/vid-app-common/src/main/java/org/onap/vid/services/AuditServiceImpl.java b/vid-app-common/src/main/java/org/onap/vid/services/AuditServiceImpl.java index 7fb126e23..287a771d3 100644 --- a/vid-app-common/src/main/java/org/onap/vid/services/AuditServiceImpl.java +++ b/vid-app-common/src/main/java/org/onap/vid/services/AuditServiceImpl.java @@ -7,9 +7,9 @@ * 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. @@ -20,22 +20,20 @@ package org.onap.vid.services; -import com.fasterxml.jackson.core.JsonParseException; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.apache.commons.lang3.StringUtils; -import org.onap.vid.exceptions.GenericUncheckedException; +import static org.apache.commons.lang3.ObjectUtils.notEqual; + +import org.jetbrains.annotations.NotNull; +import org.onap.vid.dal.AsyncInstantiationRepository; +import org.onap.vid.job.Job; import org.onap.vid.model.JobAuditStatus; -import org.onap.vid.mso.MsoBusinessLogicImpl; -import org.onap.vid.mso.MsoProperties; -import org.onap.vid.mso.RestMsoImplementation; -import org.onap.vid.mso.RestObject; +import org.onap.vid.mso.*; import org.onap.vid.mso.rest.AsyncRequestStatus; import org.onap.vid.mso.rest.AsyncRequestStatusList; import org.springframework.stereotype.Service; import javax.inject.Inject; -import java.io.IOException; import java.util.List; +import java.util.Objects; import java.util.UUID; import java.util.stream.Collectors; @@ -43,41 +41,20 @@ import java.util.stream.Collectors; @Service public class AuditServiceImpl implements AuditService{ - private final AsyncInstantiationBusinessLogic asyncInstantiationBL; private final RestMsoImplementation restMso; + private final AsyncInstantiationRepository asyncInstantiationRepository; @Inject - public AuditServiceImpl(AsyncInstantiationBusinessLogic asyncInstantiationBL, RestMsoImplementation restMso) { - this.asyncInstantiationBL = asyncInstantiationBL; + public AuditServiceImpl(RestMsoImplementation restMso, AsyncInstantiationRepository asyncInstantiationRepository) { this.restMso = restMso; + this.asyncInstantiationRepository = asyncInstantiationRepository; } @Override public void setFailedAuditStatusFromMso(UUID jobUuid, String requestId, int statusCode, String msoResponse){ final String failedMsoRequestStatus = "FAILED"; - String additionalInfo = formatExceptionAdditionalInfo(statusCode, msoResponse); - asyncInstantiationBL.auditMsoStatus(jobUuid, failedMsoRequestStatus, requestId, additionalInfo); - } - - private String formatExceptionAdditionalInfo(int statusCode, String msoResponse) { - String errorMsg = "Http Code:" + statusCode; - if (!StringUtils.isEmpty(msoResponse)) { - String filteredJson; - try { - ObjectMapper objectMapper = new ObjectMapper(); - filteredJson = StringUtils.defaultIfEmpty( - objectMapper.readTree(msoResponse).path("serviceException").toString().replaceAll("[\\{\\}]","") , - msoResponse - ); - } catch (JsonParseException e) { - filteredJson = msoResponse; - } catch (IOException e) { - throw new GenericUncheckedException(e); - } - - errorMsg = errorMsg + ", " + filteredJson; - } - return errorMsg; + String additionalInfo = MsoUtil.formatExceptionAdditionalInfo(statusCode, msoResponse); + auditMsoStatus(jobUuid, failedMsoRequestStatus, requestId, additionalInfo); } @Override @@ -87,64 +64,133 @@ public class AuditServiceImpl implements AuditService{ } @Override - public List getAuditStatusFromMsoByServiceInstanceId(UUID jobId, UUID serviceInstanceId) { - String filter = "serviceInstanceId:EQUALS:" + serviceInstanceId; - return getAuditStatusFromMso(jobId, filter, serviceInstanceId); + public List getAuditStatusFromMsoByInstanceId(JobAuditStatus.ResourceTypeFilter resourceTypeFilter, UUID instanceId, UUID jobId) { + String filter = resourceTypeFilter.getFilterBy() + ":EQUALS:" + instanceId; + return getAuditStatusFromMso(jobId, filter, instanceId); } @Override public List getAuditStatusFromMsoByJobId(UUID jobId) { - List auditStatuses = asyncInstantiationBL.getAuditStatuses(jobId, JobAuditStatus.SourceStatus.MSO); + List auditStatuses = getAuditStatuses(jobId, JobAuditStatus.SourceStatus.MSO); String instanceName = getInstanceNameFromServiceInfo(jobId); auditStatuses.stream().forEach(status -> - status.setInstanceName(instanceName) + status.setInstanceName(instanceName) ); return auditStatuses; } + @Override + public void auditVidStatus(UUID jobUUID, Job.JobStatus jobStatus){ + JobAuditStatus vidStatus = new JobAuditStatus(jobUUID, jobStatus.toString(), JobAuditStatus.SourceStatus.VID); + auditStatus(vidStatus); + } + @Override + public void auditMsoStatus(UUID jobUUID, AsyncRequestStatus.Request msoRequestStatus){ + auditMsoStatus(jobUUID, msoRequestStatus.requestStatus.getRequestState(), msoRequestStatus.requestId, msoRequestStatus.requestStatus.getStatusMessage()); + } + + @Override + public void auditMsoStatus(UUID jobUUID, String jobStatus, String requestId, String additionalInfo){ + JobAuditStatus msoStatus = new JobAuditStatus(jobUUID, jobStatus, JobAuditStatus.SourceStatus.MSO, + requestId != null ? UUID.fromString(requestId) : null, + additionalInfo); + auditStatus(msoStatus); + } - private List getAuditStatusFromMso(UUID jobId, String filter, UUID serviceInstanceId) { + private void auditStatus(JobAuditStatus jobAuditStatus){ + JobAuditStatus latestStatus = getLatestAuditStatus(jobAuditStatus.getJobId(), jobAuditStatus.getSource()); + if (notEqual(jobAuditStatus, latestStatus)) { + jobAuditStatus.setOrdinal(nextOrdinalAfter(latestStatus)); + asyncInstantiationRepository.addJobAudiStatus(jobAuditStatus); + } + } + + protected int nextOrdinalAfter(JobAuditStatus jobAuditStatus) { + return jobAuditStatus == null ? 0 : (jobAuditStatus.getOrdinal() + 1); + } + + private JobAuditStatus getLatestAuditStatus(UUID jobUUID, JobAuditStatus.SourceStatus source){ + List list = getAuditStatuses(jobUUID, source); + return !list.isEmpty() ? list.get(list.size()-1) : null; + } + + public List getAuditStatuses(UUID jobUUID, JobAuditStatus.SourceStatus source) { + return asyncInstantiationRepository.getAuditStatuses(jobUUID, source); + } + + @Override + //modelType is requestScope in MSO response + public List retrieveRequestsFromMsoByServiceIdAndRequestTypeAndScope(String instanceId, String requestType, String modelType) { + String filter = JobAuditStatus.ResourceTypeFilter.SERVICE.getFilterBy() + ":EQUALS:" + instanceId; + List msoStatuses = getAsyncRequestStatusListFromMso(filter); + return msoStatuses.stream() + .filter(x -> Objects.equals(x.request.requestType, requestType) && Objects.equals(x.request.requestScope, modelType)) + .map(x -> x.request) + .collect(Collectors.toList()); + } + + private List getAuditStatusFromMso(UUID jobId, String filter, UUID instanceId) { + + List msoStatuses = getAsyncRequestStatusListFromMso(filter); + + //add service name from service info for each audit status (in case that serviceInstanceId is null all statuses belong to service) + String userInstanceName = (instanceId == null && jobId != null) ? getInstanceNameFromServiceInfo(jobId) : null; + return convertMsoResponseStatusToJobAuditStatus(msoStatuses, userInstanceName); + } + + @NotNull + private List getAsyncRequestStatusListFromMso(String filter) { String path = MsoBusinessLogicImpl.validateEndpointPath(MsoProperties.MSO_REST_API_GET_ORC_REQS) + "filter=" + filter; RestObject msoResponse = restMso.GetForObject(path , AsyncRequestStatusList.class); if (msoResponse.getStatusCode() >= 400 || msoResponse.get() == null) { throw new BadResponseFromMso(msoResponse); } - - //add service name from service info for each audit status (in case that serviceInstanceId is null all statuses belong to service) - String userInstanceName = serviceInstanceId == null ? getInstanceNameFromServiceInfo(jobId): null; - return convertMsoResponseStatusToJobAuditStatus(msoResponse.get().getRequestList(), userInstanceName); + return msoResponse.get().getRequestList(); } private String getInstanceNameFromServiceInfo(UUID jobId) { - return asyncInstantiationBL.getServiceInfoByJobId(jobId).getServiceInstanceName(); + return asyncInstantiationRepository.getServiceInfoByJobId(jobId).getServiceInstanceName(); } protected List convertMsoResponseStatusToJobAuditStatus(List msoStatuses, String defaultName){ - return msoStatuses.stream().map(status -> { - UUID requestId = null; - String instanceName = defaultName; - String jobStatus = null; - String additionalInfo = null; - String created = null; - String instanceType = null; - - AsyncRequestStatus.Request request = status.request; - if(request != null) { + return msoStatuses.stream().map(status -> + convertAsyncRequestStatusToJobAuditStatus(status, defaultName) + ).collect(Collectors.toList()); + } + + private JobAuditStatus convertAsyncRequestStatusToJobAuditStatus(AsyncRequestStatus status, String defaultName){ + if (status == null) { + return null; + } + + UUID requestId = null; + String instanceName = defaultName; + String jobStatus = null; + String additionalInfo = null; + String created = null; + String instanceType = null; + + AsyncRequestStatus.Request request = status.request; + if(request != null) { + if (request.requestId != null) { requestId = UUID.fromString(request.requestId); - instanceName = extractInstanceName(instanceName, request); - instanceType = request.requestScope; - if(request.requestStatus != null) { - jobStatus = request.requestStatus.getRequestState(); - additionalInfo = request.requestStatus.getStatusMessage(); - if(!request.requestStatus.getAdditionalProperties().isEmpty()) { - created = request.requestStatus.getAdditionalProperties().get("finishTime") != null? request.requestStatus.getAdditionalProperties().get("finishTime").toString() : request.requestStatus.getTimestamp(); - } + } + instanceName = extractInstanceName(instanceName, request); + instanceType = request.requestScope; + if(request.requestStatus != null) { + jobStatus = request.requestStatus.getRequestState(); + additionalInfo = request.requestStatus.getStatusMessage(); + if(!request.requestStatus.getAdditionalProperties().isEmpty() && + request.requestStatus.getAdditionalProperties().get("finishTime") != null) { + created = request.requestStatus.getAdditionalProperties().get("finishTime").toString(); + } else { + created = request.requestStatus.getTimestamp(); } } - return new JobAuditStatus(instanceName, jobStatus, requestId, additionalInfo, created, instanceType); - }).collect(Collectors.toList()); + } + return new JobAuditStatus(instanceName, jobStatus, requestId, additionalInfo, created, instanceType); } private String extractInstanceName(String instanceName, AsyncRequestStatus.Request request) { @@ -154,6 +200,13 @@ public class AuditServiceImpl implements AuditService{ return instanceName; } + @Override + public JobAuditStatus getResourceAuditStatus(String trackById) { + AsyncRequestStatus asyncRequestStatus = asyncInstantiationRepository.getResourceInfoByTrackId(trackById).getErrorMessage(); + return convertAsyncRequestStatusToJobAuditStatus(asyncRequestStatus, null); + } + + public static class BadResponseFromMso extends RuntimeException { private final RestObject msoResponse; diff --git a/vid-app-common/src/main/java/org/onap/vid/services/CloudOwnerService.java b/vid-app-common/src/main/java/org/onap/vid/services/CloudOwnerService.java index 199fff0c7..f6b82c734 100644 --- a/vid-app-common/src/main/java/org/onap/vid/services/CloudOwnerService.java +++ b/vid-app-common/src/main/java/org/onap/vid/services/CloudOwnerService.java @@ -7,9 +7,9 @@ * 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. diff --git a/vid-app-common/src/main/java/org/onap/vid/services/RoleGenaratorServiceImpl.java b/vid-app-common/src/main/java/org/onap/vid/services/RoleGenaratorServiceImpl.java index 790dbfa55..a24a72e46 100644 --- a/vid-app-common/src/main/java/org/onap/vid/services/RoleGenaratorServiceImpl.java +++ b/vid-app-common/src/main/java/org/onap/vid/services/RoleGenaratorServiceImpl.java @@ -71,7 +71,7 @@ public class RoleGenaratorServiceImpl implements RoleGeneratorService { String availableRoles=""; HashMap servicesNames = new HashMap<>(); for (Subscriber subscriber: subscribers.customer) { - AaiResponse subscriberResponse = client.getSubscriberData(subscriber.globalCustomerId); + AaiResponse subscriberResponse = client.getSubscriberData(subscriber.globalCustomerId, true); for(ServiceSubscription service: subscriberResponse.getT().serviceSubscriptions.serviceSubscription) { servicesNames.put(service.serviceType,""); String roleName = "'" + subscriber.subscriberName + ModelConstants.ROLE_DELIMITER + service.serviceType + "'"; diff --git a/vid-app-common/src/main/java/org/onap/vid/services/VersionService.kt b/vid-app-common/src/main/java/org/onap/vid/services/VersionService.kt new file mode 100644 index 000000000..2fb3e0c08 --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/services/VersionService.kt @@ -0,0 +1,66 @@ +package org.onap.vid.services + +import com.fasterxml.jackson.module.kotlin.readValue +import org.apache.commons.lang3.StringUtils +import org.apache.commons.lang3.StringUtils.substringAfterLast +import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate +import org.onap.portalsdk.core.util.SystemProperties +import org.onap.vid.model.VersionAndFeatures +import org.onap.vid.utils.JACKSON_OBJECT_MAPPER +import org.springframework.stereotype.Service +import java.util.regex.Pattern +import javax.inject.Inject +import javax.servlet.ServletContext + +@Service +class VersionService +@Inject +constructor(internal var servletContext: ServletContext) { + + private val Logger = EELFLoggerDelegate.getLogger(VersionService::class.java) + + private val versionAndFeatures: VersionAndFeatures by lazy { + loadVersionAndFeatures() + } + + private fun readBuildNumber(): String { + val resource = servletContext.getResource("/app/vid/scripts/constants/version.json") + return JACKSON_OBJECT_MAPPER.readValue>(resource)["Version"]!! + } + + //protected so can be easily tested in UT + protected fun readFeatureSet(): String { + return SystemProperties.getProperty("features.set.filename") + } + + //protected so can be easily tested in UT + protected fun buildDisplayVersion(features: String, build: String): String { + val matcher = Pattern.compile("([^/]+?)(\\.features|$)").matcher(features) + val majorByFeatures = if (matcher.find()) matcher.group(1) else features + + val buildByVersion = StringUtils.defaultIfBlank(substringAfterLast(build, "."), build) + + return StringUtils.join(majorByFeatures, ".", buildByVersion) + } + + fun retrieveVersionAndFeatures(): VersionAndFeatures { + return try { + versionAndFeatures + } catch (exception: Exception) { + Logger.error("Failed to read build number or feature properties settings from version file", exception) + VersionAndFeatures.unknown + } + } + + private fun loadVersionAndFeatures(): VersionAndFeatures { + val featureSet = readFeatureSet(); + val build = readBuildNumber(); + val displayVersion = buildDisplayVersion(featureSet, build) + return VersionAndFeatures(featureSet, build, displayVersion) + } + + //might throw an exception + fun retrieveBuildNumber(): String { + return versionAndFeatures.build + } +} diff --git a/vid-app-common/src/main/java/org/onap/vid/utils/KotlinUtils.kt b/vid-app-common/src/main/java/org/onap/vid/utils/KotlinUtils.kt index 6866477c3..cf532624c 100644 --- a/vid-app-common/src/main/java/org/onap/vid/utils/KotlinUtils.kt +++ b/vid-app-common/src/main/java/org/onap/vid/utils/KotlinUtils.kt @@ -27,4 +27,4 @@ inline fun > getEnumFromMapOfStrings(map: Map, k return java.lang.Enum.valueOf(E::class.java, (map.getOrDefault(key, defaultValue.name) as String)) } -val JACKSON_OBJECT_MAPPER: ObjectMapper = jacksonObjectMapper() +@JvmField val JACKSON_OBJECT_MAPPER: ObjectMapper = jacksonObjectMapper() diff --git a/vid-app-common/src/main/java/org/onap/vid/utils/Tree.kt b/vid-app-common/src/main/java/org/onap/vid/utils/Tree.kt index 35e913d16..62453756f 100644 --- a/vid-app-common/src/main/java/org/onap/vid/utils/Tree.kt +++ b/vid-app-common/src/main/java/org/onap/vid/utils/Tree.kt @@ -7,9 +7,9 @@ * 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. @@ -41,6 +41,14 @@ data class Tree(private val root:Node) { } } + fun getChildrenDepth(): Int { + return getMaxDepth(root) - 1 + } + + private fun getMaxDepth(level:Node): Int { + return (level.children.map{getMaxDepth(it.value)}.max() ?: 0) + 1 + } + fun getSubTree(vararg path: T): Tree? { return getSubTree(path.asList()) } diff --git a/vid-app-common/src/main/resources/1712_ADIOD.zip b/vid-app-common/src/main/resources/1712_ADIOD.zip deleted file mode 100644 index de8fa7eb477beedcd42688e68e8a46f9448dfe63..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 89573 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%0Dp){b`631i@Q}kJxGoxGzsL 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 z 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 R{U(&hv}iik@I|CcEUfV%*5$?}xv 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 Bq4NL$ diff --git a/vid-app-common/src/main/resources/adiod.zip b/vid-app-common/src/main/resources/adiod.zip deleted file mode 100644 index 6e024234aaf968cd7515b52acca50420526f9475..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 79927 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 diff --git a/vid-app-common/src/main/resources/csar317927061915233480.zip b/vid-app-common/src/main/resources/csar317927061915233480.zip deleted file mode 100644 index d30f49f4dc9c0691167cc1a0557cde1042eb11b3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 63104 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%0A%pP3G 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 Edf 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%0DWX$?lxm?E@3) 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 diff --git a/vid-app-common/src/main/resources/mso_get_manual_task_by_request_id.json b/vid-app-common/src/main/resources/mso_get_manual_task_by_request_id.json deleted file mode 100644 index 004280bce..000000000 --- a/vid-app-common/src/main/resources/mso_get_manual_task_by_request_id.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "taskList":[ - { - "taskId":"daf4dd84-b77a-42da-a051-3239b7a9392c", - "type":"fallout", - "nfRole":"vSCP", - "subscriptionServiceType":"Mobility", - "originalRequestId":"za1234d1-5a33-55df-13ab-12abad84e335", - "originalRequestorId":"ss835w", - "errorSource":"A&AI", - "errorCode":"404", - "errorMessage":"Failed in A&AI 404", - "buildingBlockName":"DoCreateVfModule", - "buildingBlockStep":"invokeA&AI:getTenant", - "validResponses":[ - "rollback", - "abort", - "skip", - "retry" - ] - } - ] -} \ No newline at end of file diff --git a/vid-app-common/src/main/resources/pnf.zip b/vid-app-common/src/main/resources/pnf.zip deleted file mode 100644 index 541d89ecf4be1d775e0ff3368a24c6cdc746436d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33397 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 diff --git a/vid-app-common/src/main/resources/service-David-csar.csar b/vid-app-common/src/main/resources/service-David-csar.csar deleted file mode 100644 index fcf1c647bc7ee2b41ec14d4e03fd593dc06e4875..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 29894 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,n-z6B{jMGe=th})TaJ6Va;xCTD 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 diff --git a/vid-app-common/src/main/resources/service-VdbeSrv-csar.zip b/vid-app-common/src/main/resources/service-VdbeSrv-csar.zip deleted file mode 100644 index 0b8db2789e1605acc7c48e86985466e5898367a3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 70825 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

$<}hD*VYdrGrFRt#eJ z4TI|B{G$!)iKqW!5~D5sG8I?%q3GpA?U+N^4oby~S;p^TzR9I6Pp*tIVTVi^6BK$! zRab>nb&kmL_q$=9w?vh=ydTgXq*?wG*aX^^YES=|*`L=xnzydaozCm4ak)Mw6u8!N zJ2-I&YD$U=dkSAq-N5VVQcwQR{fYP;Ym5x_@b?AsSkP*JAA|;+J{qta=N%0D0D~QLR4| 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 diff --git a/vid-app-common/src/main/resources/service-vf-csar.zip b/vid-app-common/src/main/resources/service-vf-csar.zip deleted file mode 100644 index f0b0a98d70dafa9c3a2cead7bac963bc1ce9c5cb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 58363 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

ipx%~ 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

=9a^cZpY_T%y6zJ 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 diff --git a/vid-app-common/src/main/webapp/app/vid/scripts/modals/new-change-management/new-change-management.controller.js b/vid-app-common/src/main/webapp/app/vid/scripts/modals/new-change-management/new-change-management.controller.js index d5040b138..d9bc828fe 100644 --- a/vid-app-common/src/main/webapp/app/vid/scripts/modals/new-change-management/new-change-management.controller.js +++ b/vid-app-common/src/main/webapp/app/vid/scripts/modals/new-change-management/new-change-management.controller.js @@ -696,8 +696,8 @@   - lcpCloudRegionId == 'rdm5b'   - tenantId == '0675e0709bd7444a9e13eba8b40edb3c' - "url": "https://aai-conexus-e2e.ecomp.cci.att.com:8443/aai/v10/cloud-infrastructure/cloud-regions/cloud-region/att-aic/rdm5b/tenants/tenant/0675e0709bd7444a9e13eba8b40edb3c/vservers/vserver/932b330d-733e-427d-a519-14eebd261f70" - "url": "/aai/v11/cloud-infrastructure/cloud-regions/cloud-region/att-aic/rdm5b/tenants/tenant/0675e0709bd7444a9e13eba8b40edb3c/vservers/vserver/932b330d-733e-427d-a519-14eebd261f70" + "url": "https://aai-conexus-e2e.ecomp.cci.att.com:8443/aai/v10/cloud-infrastructure/cloud-regions/cloud-region/irma-aic/rdm5b/tenants/tenant/0675e0709bd7444a9e13eba8b40edb3c/vservers/vserver/932b330d-733e-427d-a519-14eebd261f70" + "url": "/aai/v11/cloud-infrastructure/cloud-regions/cloud-region/irma-aic/rdm5b/tenants/tenant/0675e0709bd7444a9e13eba8b40edb3c/vservers/vserver/932b330d-733e-427d-a519-14eebd261f70" */ var cloudRegionMatch = url.match(/\/cloud-regions\/cloud-region\/[^\/]+\/([^\/]+)/); diff --git a/vid-app-common/src/test/java/org/onap/vid/aai/AAITreeConverterTest.java b/vid-app-common/src/test/java/org/onap/vid/aai/AAITreeConverterTest.java index 5bdfd1207..560e6cb5f 100644 --- a/vid-app-common/src/test/java/org/onap/vid/aai/AAITreeConverterTest.java +++ b/vid-app-common/src/test/java/org/onap/vid/aai/AAITreeConverterTest.java @@ -25,17 +25,16 @@ import org.mockito.InjectMocks; import org.mockito.MockitoAnnotations; import org.onap.vid.aai.util.AAITreeConverter; import org.onap.vid.model.Action; -import org.onap.vid.model.aaiTree.AAITreeNode; -import org.onap.vid.model.aaiTree.Network; +import org.onap.vid.model.aaiTree.*; import org.onap.vid.model.aaiTree.ServiceInstance; -import org.onap.vid.model.aaiTree.VfModule; -import org.onap.vid.model.aaiTree.Vnf; +import org.onap.vid.mso.model.CloudConfiguration; import org.testng.annotations.BeforeTest; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import java.util.List; +import static org.hamcrest.CoreMatchers.*; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.emptyOrNullString; import static org.hamcrest.Matchers.hasKey; @@ -43,6 +42,7 @@ import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.not; import static org.onap.vid.asdc.parser.ToscaParserImpl2.Constants.A_LA_CARTE; +import static org.testng.Assert.assertNull; public class AAITreeConverterTest { @@ -59,28 +59,41 @@ public class AAITreeConverterTest { AAITreeNode aaiTree = generateAaiTreeToConvert(0, 0); - ServiceInstance result = aaiTreeConverter.convertTreeToUIModel(aaiTree, "global-customer-id", "service-type", A_LA_CARTE); + ServiceInstance result = aaiTreeConverter.convertTreeToUIModel(aaiTree, "global-customer-id", "service-type", A_LA_CARTE, "", ""); assertService(result, 0, 0, true); } @Test - public void testConvertTreeToUIModel_MultipleChildren() throws Exception { + public void testConvertTreeToUIModel_MultipleChildren() { AAITreeNode aaiTree = generateAaiTreeToConvert(2, 2); - ServiceInstance serviceInstance = aaiTreeConverter.convertTreeToUIModel(aaiTree, "global-customer-id", "service-type", null); + ServiceInstance serviceInstance = aaiTreeConverter.convertTreeToUIModel(aaiTree, "global-customer-id", "service-type", null, "", ""); assertService(serviceInstance, 2, 2, false); int nodesCounter = 0; assertThat(serviceInstance.getVnfs().entrySet(), hasSize(2)); - assertVnf(serviceInstance.getVnfs().get("vnf-model-version-id:00"+(nodesCounter++)), 0, 0, false); - assertVnf(serviceInstance.getVnfs().get("vnf-model-version-id:00"+(nodesCounter++)), 0, 0, false); + assertVnf(serviceInstance.getVnfs().get("vnf-instance-id" + (nodesCounter++)), 0, 0); + assertVnf(serviceInstance.getVnfs().get("vnf-instance-id" + (nodesCounter++)), 0, 0); assertThat(serviceInstance.getNetworks().entrySet(), hasSize(2)); - assertNetwork(serviceInstance.getNetworks().get("network-model-version-id:00"+(nodesCounter++)), false); - assertNetwork(serviceInstance.getNetworks().get("network-model-version-id:00"+(nodesCounter)), false); + assertNetwork(serviceInstance.getNetworks().get("network-instance-id" + (nodesCounter++)), false); + assertNetwork(serviceInstance.getNetworks().get("network-instance-id" + (nodesCounter++)), false); + + assertThat(serviceInstance.getVnfGroups().size(), equalTo(1)); + assertThat(serviceInstance.getVnfGroups().get("vnf-group-id" + (nodesCounter++)).getInstanceId(), startsWith("vnf-group-id")); + + assertThat(serviceInstance.getCollectionResources().size(), equalTo(1)); + CollectionResource cr = serviceInstance.getCollectionResources().get("cr-id" + (nodesCounter++)); + assertThat(cr.getInstanceId(), startsWith("cr-id")); + + assertThat(cr.getNcfs().size(), equalTo(1)); + assertThat(cr.getNcfs().get("ncf-id").getInstanceId(), startsWith("ncf-id")); + + assertThat(serviceInstance.getExistingVNFCounterMap().get("vnf-model-customization-id"), equalTo(2L)); + assertThat(serviceInstance.getExistingNetworksCounterMap().get("network-model-customization-id"), equalTo(2L)); } @DataProvider @@ -99,7 +112,7 @@ public class AAITreeConverterTest { int nodesCounter = 0; for (Boolean customizationName: vfModules) { - vnfTreeNode.getChildren().add(createVfModule(nodesCounter++, customizationName)); + vnfTreeNode.getChildren().add(createVfModule(customizationName)); } for (Boolean customizationName: networks) { @@ -108,24 +121,21 @@ public class AAITreeConverterTest { Vnf actualVnf = Vnf.from(vnfTreeNode); - assertVnf(actualVnf, vfModules.size(), networks.size(), false); + assertVnf(actualVnf, vfModules.size(), networks.size()); nodesCounter = 0; for (Boolean customizationName: vfModules) { String key = customizationName ? "vfModule key in model" : "vfModule-model-version-id"; assertThat(actualVnf.getVfModules(), hasKey(key)); - assertThat(actualVnf.getVfModules().get(key), hasKey(key + ":00" + nodesCounter)); - VfModule actualVfModule = actualVnf.getVfModules().get(key).get(key + ":00" + nodesCounter); + assertThat(actualVnf.getVfModules().get(key), hasKey("vfModule-instance-id")); + VfModule actualVfModule = actualVnf.getVfModules().get(key).get("vfModule-instance-id"); assertVfModule(actualVfModule, customizationName); - nodesCounter++; } for (Boolean customizationName: networks) { - String key = customizationName ? "network key in model" : "network-model-version-id"; - - assertThat(actualVnf.getNetworks(), hasKey(key + ":00" + nodesCounter)); - Network actualNetwork = actualVnf.getNetworks().get(key + ":00" + nodesCounter); + assertThat(actualVnf.getNetworks(), hasKey("network-instance-id" + nodesCounter)); + Network actualNetwork = actualVnf.getNetworks().get("network-instance-id" + nodesCounter); assertNetwork(actualNetwork, customizationName); nodesCounter++; } @@ -142,45 +152,79 @@ public class AAITreeConverterTest { private AAITreeNode createVnf(int uniqueNumber, boolean hasCustomizationName) { AAITreeNode vnfTreeNode = new AAITreeNode(); - vnfTreeNode.setId("vnf-instance-id"); + vnfTreeNode.setId("vnf-instance-id" + uniqueNumber); vnfTreeNode.setName("vnf-instance-name"); - vnfTreeNode.setType("generic-vnf"); + vnfTreeNode.setType(NodeType.GENERIC_VNF); vnfTreeNode.setModelVersionId("vnf-model-version-id"); + vnfTreeNode.setModelCustomizationId("vnf-model-customization-id"); if (hasCustomizationName) { vnfTreeNode.setModelCustomizationName("vnf model customization name"); vnfTreeNode.setKeyInModel("vnf key in model"); } - vnfTreeNode.setUniqueNumber(uniqueNumber); return vnfTreeNode; } - private AAITreeNode createVfModule(int uniqueNumber, boolean hasCustomizationName) { + private AAITreeNode createVnfGroup(int uniqueNumber) { + AAITreeNode treeNode = new AAITreeNode(); + treeNode.setId("vnf-group-id" + uniqueNumber); + treeNode.setType(NodeType.INSTANCE_GROUP); + treeNode.getAdditionalProperties().put("instance-group-type", "vnfGroup-type"); + return treeNode; + } + + private AAITreeNode createCollectionResource(int uniqueNumber) { + AAITreeNode treeNode = new AAITreeNode(); + treeNode.setId("cr-id" + uniqueNumber); + treeNode.setType(NodeType.COLLECTION_RESOURCE); + treeNode.getChildren().add(createNCF()); + return treeNode; + } + + private AAITreeNode createNCF() { + AAITreeNode treeNode = new AAITreeNode(); + treeNode.setId("ncf-id"); + treeNode.setType(NodeType.INSTANCE_GROUP); + treeNode.getAdditionalProperties().put("instance-group-type", "L3-NETWORK"); + return treeNode; + } + + @Test + public void givenPlacementIsNull_whenConvertToNetwork_relevantFieldsAreAlsoNull() { + AAITreeNode aaiTreeNode = new AAITreeNode(); + aaiTreeNode.setType(NodeType.NETWORK); + Network actualNetwork = Network.from(aaiTreeNode); + assertNull(actualNetwork.getCloudOwner()); + assertNull(actualNetwork.getLcpCloudRegionId()); + assertNull(actualNetwork.getTenantId()); + } + + private AAITreeNode createVfModule(boolean hasCustomizationName) { AAITreeNode vfModuleTreeNode = new AAITreeNode(); vfModuleTreeNode.setId("vfModule-instance-id"); vfModuleTreeNode.setName("vfModule-instance-name"); - vfModuleTreeNode.setType("vf-module"); + vfModuleTreeNode.setType(NodeType.VF_MODULE); vfModuleTreeNode.setModelVersionId("vfModule-model-version-id"); + vfModuleTreeNode.setModelCustomizationId("vfModule-model-customization-id"); if (hasCustomizationName) { vfModuleTreeNode.setModelCustomizationName("vfModule model customization name"); vfModuleTreeNode.setKeyInModel("vfModule key in model"); } - vfModuleTreeNode.setUniqueNumber(uniqueNumber); - + vfModuleTreeNode.setCloudConfiguration(new CloudConfiguration("lcpRegion2", "tenant3", "cloudOwner1")); return vfModuleTreeNode; } private AAITreeNode createNetwork(int uniqueNumber, boolean hasCustomizationName) { AAITreeNode networkTreeNode = new AAITreeNode(); - networkTreeNode.setId("network-instance-id"); + networkTreeNode.setId("network-instance-id" + uniqueNumber); networkTreeNode.setName("network-instance-name"); - networkTreeNode.setType("l3-network"); + networkTreeNode.setType(NodeType.NETWORK); networkTreeNode.setModelVersionId("network-model-version-id"); + networkTreeNode.setModelCustomizationId("network-model-customization-id"); if (hasCustomizationName) { networkTreeNode.setModelCustomizationName("network model customization name"); networkTreeNode.setKeyInModel("network key in model"); } - networkTreeNode.setUniqueNumber(uniqueNumber); - + networkTreeNode.setCloudConfiguration(new CloudConfiguration("auk51a", "b530fc990b6d4334bd45518bebca6a51", "att-nc")); return networkTreeNode; } @@ -196,17 +240,16 @@ public class AAITreeConverterTest { assertThat(serviceInstance.getIsALaCarte(), is(isALaCarte)); } - private void assertVnf(Vnf actualVnf, int expectedVfModules, int expectedNetworks, boolean hasCustomizationName) { - assertThat(actualVnf.getInstanceId(), is("vnf-instance-id")); + private void assertVnf(Vnf actualVnf, int expectedVfModules, int expectedNetworks) { + assertThat(actualVnf.getInstanceId(), containsString("vnf-instance-id")); assertThat(actualVnf.getInstanceName(), is("vnf-instance-name")); assertThat(actualVnf.getAction(), is(Action.None)); assertThat(actualVnf.getModelInfo().getModelType(), is("vnf")); assertThat(actualVnf.getModelInfo().getModelVersionId(), is("vnf-model-version-id")); assertThat(actualVnf.getVfModules().entrySet(), hasSize(expectedVfModules)); assertThat(actualVnf.getNetworks().entrySet(), hasSize(expectedNetworks)); - assertThat(actualVnf.getTrackById(), is(not(emptyOrNullString()))); - String expectedCustomizationName = hasCustomizationName ? "vnf model customization name" : null; - assertThat(actualVnf.getModelInfo().getModelCustomizationName(), is(expectedCustomizationName)); + assertThat(actualVnf.getTrackById(), containsString("vnf-instance-id")); + assertNull(actualVnf.getModelInfo().getModelCustomizationName()); } private void assertVfModule(VfModule actualVfModule, boolean hasCustomizationName) { @@ -215,20 +258,27 @@ public class AAITreeConverterTest { assertThat(actualVfModule.getAction(), is(Action.None)); assertThat(actualVfModule.getModelInfo().getModelType(), is("vfModule")); assertThat(actualVfModule.getModelInfo().getModelVersionId(), is("vfModule-model-version-id")); - assertThat(actualVfModule.getTrackById(), is(not(emptyOrNullString()))); + assertThat(actualVfModule.getTrackById(), is("vfModule-instance-id")); String expectedCustomizationName = hasCustomizationName ? "vfModule model customization name" : null; assertThat(actualVfModule.getModelInfo().getModelCustomizationName(), is(expectedCustomizationName)); + assertThat(actualVfModule.getCloudOwner(), is("cloudOwner1")); + assertThat(actualVfModule.getLcpCloudRegionId(), is("lcpRegion2")); + assertThat(actualVfModule.getTenantId(), is("tenant3")); } private void assertNetwork(Network actualNetwork, boolean hasCustomizationName) { - assertThat(actualNetwork.getInstanceId(), is("network-instance-id")); + assertThat(actualNetwork.getInstanceId(), containsString("network-instance-id")); assertThat(actualNetwork.getInstanceName(), is("network-instance-name")); assertThat(actualNetwork.getAction(), is(Action.None)); assertThat(actualNetwork.getModelInfo().getModelType(), is("network")); assertThat(actualNetwork.getModelInfo().getModelVersionId(), is("network-model-version-id")); - assertThat(actualNetwork.getTrackById(), is(not(emptyOrNullString()))); + assertThat(actualNetwork.getTrackById(), containsString("network-instance-id")); String expectedCustomizationName = hasCustomizationName ? "network model customization name" : null; assertThat(actualNetwork.getModelInfo().getModelCustomizationName(), is(expectedCustomizationName)); + assertThat(actualNetwork.getCloudOwner(), is("att-nc")); + assertThat(actualNetwork.getLcpCloudRegionId(), is("auk51a")); + assertThat(actualNetwork.getTenantId(), is("b530fc990b6d4334bd45518bebca6a51")); + } private AAITreeNode generateAaiTreeToConvert(int numberOfVnfs, int numberOfNetworks) { @@ -236,6 +286,7 @@ public class AAITreeConverterTest { AAITreeNode aaiTree = new AAITreeNode(); aaiTree.setId("service-instance-id"); aaiTree.setName("service-instance-name"); + aaiTree.setType(NodeType.SERVICE_INSTANCE); for (int i = 0; i < numberOfVnfs; i++) { aaiTree.getChildren().add(createVnf(counter++, false)); @@ -245,6 +296,9 @@ public class AAITreeConverterTest { aaiTree.getChildren().add(createNetwork(counter++, false)); } + aaiTree.getChildren().add(createVnfGroup(counter++)); + aaiTree.getChildren().add(createCollectionResource(counter++)); + return aaiTree; } -} +} \ No newline at end of file diff --git a/vid-app-common/src/test/java/org/onap/vid/aai/AaiClientTest.java b/vid-app-common/src/test/java/org/onap/vid/aai/AaiClientTest.java index fdeeb0076..b2d8e85fa 100644 --- a/vid-app-common/src/test/java/org/onap/vid/aai/AaiClientTest.java +++ b/vid-app-common/src/test/java/org/onap/vid/aai/AaiClientTest.java @@ -20,9 +20,51 @@ package org.onap.vid.aai; +import static java.util.stream.Collectors.toList; +import static org.apache.commons.lang3.StringUtils.equalsIgnoreCase; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsInAnyOrder; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.either; +import static org.hamcrest.Matchers.hasProperty; +import static org.hamcrest.Matchers.instanceOf; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.sameInstance; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.isNull; +import static org.mockito.ArgumentMatchers.nullable; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static org.onap.vid.utils.KotlinUtilsKt.JACKSON_OBJECT_MAPPER; +import static org.onap.vid.utils.Unchecked.toURI; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertNull; +import static org.testng.Assert.fail; + import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.collect.ImmutableList; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.net.URI; +import java.security.cert.CertificateException; +import java.util.ArrayList; +import java.util.Map; +import java.util.function.BiConsumer; +import java.util.function.Function; +import java.util.stream.Stream; +import javax.crypto.BadPaddingException; +import javax.net.ssl.SSLHandshakeException; +import javax.servlet.ServletContext; +import javax.ws.rs.ProcessingException; +import javax.ws.rs.client.Client; +import javax.ws.rs.core.Response; import org.apache.commons.lang3.builder.ReflectionToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; import org.apache.commons.lang3.exception.ExceptionUtils; @@ -32,10 +74,20 @@ import org.apache.http.HttpStatus; import org.mockito.Mockito; import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; import org.onap.portalsdk.core.util.SystemProperties; -import org.onap.vid.aai.model.AaiGetNetworkCollectionDetails.RelatedToProperty; import org.onap.vid.aai.model.AaiGetTenatns.GetTenantsResponse; -import org.onap.vid.aai.model.*; -import org.onap.vid.aai.util.*; +import org.onap.vid.aai.model.CustomQuerySimpleResult; +import org.onap.vid.aai.model.ModelVer; +import org.onap.vid.aai.model.ModelVersions; +import org.onap.vid.aai.model.PortDetailsTranslator; +import org.onap.vid.aai.model.Properties; +import org.onap.vid.aai.model.RelatedToProperty; +import org.onap.vid.aai.model.ResourceType; +import org.onap.vid.aai.model.SimpleResult; +import org.onap.vid.aai.util.AAIRestInterface; +import org.onap.vid.aai.util.CacheProvider; +import org.onap.vid.aai.util.HttpsAuthClient; +import org.onap.vid.aai.util.ServletRequestHelper; +import org.onap.vid.aai.util.SystemPropertyHelper; import org.onap.vid.controller.LocalWebConfig; import org.onap.vid.exceptions.GenericUncheckedException; import org.onap.vid.model.Subscriber; @@ -55,37 +107,6 @@ import org.testng.annotations.Test; import sun.security.provider.certpath.SunCertPathBuilderException; import sun.security.validator.ValidatorException; -import javax.crypto.BadPaddingException; -import javax.net.ssl.SSLHandshakeException; -import javax.servlet.ServletContext; -import javax.ws.rs.ProcessingException; -import javax.ws.rs.client.Client; -import javax.ws.rs.core.Response; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.net.URI; -import java.security.cert.CertificateException; -import java.util.ArrayList; -import java.util.Map; -import java.util.function.BiConsumer; -import java.util.function.Function; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import static org.apache.commons.lang3.StringUtils.equalsIgnoreCase; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.*; -import static org.mockito.ArgumentMatchers.nullable; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyBoolean; -import static org.mockito.Matchers.anyString; -import static org.mockito.Matchers.argThat; -import static org.mockito.Matchers.eq; -import static org.mockito.Matchers.isNull; -import static org.mockito.Mockito.*; -import static org.onap.vid.utils.Unchecked.toURI; -import static org.testng.Assert.*; - @ContextConfiguration(classes = {LocalWebConfig.class, SystemProperties.class}) @WebAppConfiguration public class AaiClientTest { @@ -345,7 +366,7 @@ public class AaiClientTest { Assert.assertTrue(response.t.length> 0); - Assert.assertEquals(tenants[0].cloudOwner,"att-aic-cloud-owner"); + Assert.assertEquals(tenants[0].cloudOwner,"irma-aic-cloud-owner"); } final String tenantResponseRaw ="" + @@ -355,10 +376,10 @@ public class AaiClientTest { "\"relationship-list\": {" + "\"relationship\": [{" + "\"related-to\": \"tenant\"," + - "\"related-link\": \"/aai/v11/cloud-infrastructure/cloud-regions/cloud-region/att-aic/AAIAIC25/tenants/tenant/092eb9e8e4b7412e8787dd091bc58e86\"," + + "\"related-link\": \"/aai/v11/cloud-infrastructure/cloud-regions/cloud-region/irma-aic/AAIAIC25/tenants/tenant/092eb9e8e4b7412e8787dd091bc58e86\"," + "\"relationship-data\": [{" + "\"relationship-key\": \"cloud-region.cloud-owner\"," + - "\"relationship-value\": \"att-aic-cloud-owner\"" + + "\"relationship-value\": \"irma-aic-cloud-owner\"" + "}," + "{" + "\"relationship-key\": \"cloud-region.cloud-region-id\"," + @@ -427,11 +448,11 @@ public class AaiClientTest { " {" + " \"related-to\": \"volume-group\"," + " \"relationship-label\": \"org.onap.relationships.inventory.Uses\"," + - " \"related-link\": \"/aai/v12/cloud-infrastructure/cloud-regions/cloud-region/att-aic/rdm5b/volume-groups/volume-group/66013ebe-0c81-44b9-a24f-7c6acba73a39\"," + + " \"related-link\": \"/aai/v12/cloud-infrastructure/cloud-regions/cloud-region/irma-aic/rdm5b/volume-groups/volume-group/66013ebe-0c81-44b9-a24f-7c6acba73a39\"," + " \"relationship-data\": [" + " {" + " \"relationship-key\": \"cloud-region.cloud-owner\"," + - " \"relationship-value\": \"att-aic\"" + + " \"relationship-value\": \"irma-aic\"" + " }," + " {" + " \"relationship-key\": \"cloud-region.cloud-region-id\"," + @@ -446,11 +467,11 @@ public class AaiClientTest { " {" + " \"related-to\": \"vserver\"," + " \"relationship-label\": \"org.onap.relationships.inventory.Uses\"," + - " \"related-link\": \"/aai/v12/cloud-infrastructure/cloud-regions/cloud-region/att-aic/rdm5b/tenants/tenant/db1818f7f2e34862b378bfb2cc520f91/vservers/vserver/5eef9f6d-9933-4bc6-9a1a-862d61309437\"," + + " \"related-link\": \"/aai/v12/cloud-infrastructure/cloud-regions/cloud-region/irma-aic/rdm5b/tenants/tenant/db1818f7f2e34862b378bfb2cc520f91/vservers/vserver/5eef9f6d-9933-4bc6-9a1a-862d61309437\"," + " \"relationship-data\": [" + " {" + " \"relationship-key\": \"cloud-region.cloud-owner\"," + - " \"relationship-value\": \"att-aic\"" + + " \"relationship-value\": \"irma-aic\"" + " }," + " {" + " \"relationship-key\": \"cloud-region.cloud-region-id\"," + @@ -490,7 +511,7 @@ public class AaiClientTest { GetTenantsResponse tenant = aaiClientMock.getHomingDataByVfModule("vnfInstanceId", "vfModuleId"); - Assert.assertEquals(tenant.cloudOwner,"att-aic"); + Assert.assertEquals(tenant.cloudOwner,"irma-aic" ); Assert.assertEquals(tenant.cloudRegionID,"rdm5b"); Assert.assertEquals(tenant.tenantID,"db1818f7f2e34862b378bfb2cc520f91"); @@ -601,7 +622,7 @@ public class AaiClientTest { // double each case to propagateExceptions = true/false, to verify that "don't propagate" really still work ImmutableList.of(l.getLeft(), l.getRight(), true).toArray(), ImmutableList.of(l.getLeft(), l.getRight(), false).toArray() - )).collect(Collectors.toList()).toArray(new Object[][]{}); + )).collect(toList()).toArray(new Object[][]{}); } private static UncheckedBiConsumer mockExceptionOnClientProvider(Exception e) { @@ -734,6 +755,83 @@ public class AaiClientTest { }; } + @Test + public void testGetLatestVersionByInvariantId() throws IOException { + + ModelVersions modelVersions = JACKSON_OBJECT_MAPPER.readValue("" + + "{\n" + + " \"results\": [\n" + + " {\n" + + " \"model\": {\n" + + " \"model-invariant-id\": \"f6342be5-d66b-4d03-a1aa-c82c3094c4ea\",\n" + + " \"model-type\": \"service\",\n" + + " \"resource-version\": \"1534274421300\"\n" + + " }\n" + + " },\n" + + " {\n" + + " \"model-ver\": {\n" + + " \"model-version-id\": \"a92f899d-a3ec-465b-baed-1663b0a5aee1\",\n" + + " \"model-name\": \"NCM_VLAN_SVC_ym161f\",\n" + + " \"model-version\": \"bbb\",\n" + + " \"distribution-status\": \"DISTRIBUTION_COMPLETE_OK\",\n" + + " \"model-description\": \"Network Collection service for vLAN tagging\",\n" + + " \"resource-version\": \"1534788756086\"\n" + + " }\n" + + " },\n" + + " {\n" + + " \"model-ver\": {\n" + + " \"model-version-id\": \"d2fda667-e92e-4cfa-9620-5da5de01a319\",\n" + + " \"model-name\": \"NCM_VLAN_SVC_ym161f\",\n" + + " \"model-version\": \"aaa\",\n" + + " \"distribution-status\": \"DISTRIBUTION_COMPLETE_OK\",\n" + + " \"model-description\": \"Network Collection service for vLAN tagging\",\n" + + " \"resource-version\": \"1534444087221\"\n" + + " }\n" + + " }]}", ModelVersions.class); + + + final AaiClient aaiClient = new AaiClient(null, null, null); + + assertThat(aaiClient.toModelVerStream(modelVersions).collect(toList()), + containsInAnyOrder( + hasProperty("modelVersionId", is("a92f899d-a3ec-465b-baed-1663b0a5aee1")), + hasProperty("modelVersionId", is("d2fda667-e92e-4cfa-9620-5da5de01a319")) + )); + + } + + @DataProvider + public static Object[][] versionsDataProvider() { + return new Object[][] { + { Stream.of("10","20","30"), "30" }, + { Stream.of("10","20","20"), "20" }, + { Stream.of("c","b","a"), "c" }, + { Stream.of("1.0","2.0","1.8"), "2.0" }, + { Stream.of("1.0.7","2.0.2","2.0.9"), "2.0.9" }, + { Stream.of("0","0","0"), "0" }, + { Stream.of("","10"), "10" }, + + }; + } + + @Test(dataProvider = "versionsDataProvider") + public void maxModelVer(Stream input, String expected) { + Stream modelVerStream = input.map(version -> { + ModelVer mv = new ModelVer(); + mv.setModelVersion(version); + return mv; + }); + + final AaiClient aaiClient = new AaiClient(null, null, null); + + assertThat(aaiClient.maxModelVer(modelVerStream), hasProperty("modelVersion", is(expected))); + } + + @Test(expectedExceptions = GenericUncheckedException.class) + public void maxModelVerException() { + final AaiClient aaiClient = new AaiClient(null, null, null); + aaiClient.maxModelVer(Stream.of(new ModelVer())); + } @Test(dataProvider = "cloudRegionAndTenantDataProvider") public void getCloudRegionAndTenantByVnfId(String tenantName, String cloudRegionId) throws JsonProcessingException { SimpleResult tenant = new SimpleResult(); diff --git a/vid-app-common/src/test/java/org/onap/vid/aai/AaiResponseTranslatorTest.java b/vid-app-common/src/test/java/org/onap/vid/aai/AaiResponseTranslatorTest.java index 12f7429eb..045488605 100644 --- a/vid-app-common/src/test/java/org/onap/vid/aai/AaiResponseTranslatorTest.java +++ b/vid-app-common/src/test/java/org/onap/vid/aai/AaiResponseTranslatorTest.java @@ -45,9 +45,9 @@ public class AaiResponseTranslatorTest { " \"results\": [{" + " \"id\": \"2979590232\"," + " \"node-type\": \"cloud-region\"," + - " \"url\": \"/aai/v12/cloud-infrastructure/cloud-regions/cloud-region/att-aic/SDNO-S-BcloudReg-E1802\"," + + " \"url\": \"/aai/v12/cloud-infrastructure/cloud-regions/cloud-region/irma-aic/SDNO-S-BcloudReg-E1802\"," + " \"properties\": {" + - " \"cloud-owner\": \"att-aic\"," + + " \"cloud-owner\": \"irma-aic\"," + " \"cloud-region-id\": \"THE-EXPECTED-REGION-ID\"," + " \"sriov-automation\": false," + " \"resource-version\": \"1513631040564\"" + @@ -122,7 +122,7 @@ public class AaiResponseTranslatorTest { "{" + " \"results\": [{" + " \"node-type\": \"cloud-region\"," + - " \"url\": \"/aai/v12/cloud-infrastructure/cloud-regions/cloud-region/att-aic/SDNO-S-BcloudReg-E1802\"," + + " \"url\": \"/aai/v12/cloud-infrastructure/cloud-regions/cloud-region/irma-aic/SDNO-S-BcloudReg-E1802\"," + " \"properties\": {" + " \"resource-version\": \"1513631040564\"" + " }" + diff --git a/vid-app-common/src/test/java/org/onap/vid/asdc/parser/ToscaParserImpl2Test.java b/vid-app-common/src/test/java/org/onap/vid/asdc/parser/ToscaParserImpl2Test.java index 91c480526..92d78d43e 100644 --- a/vid-app-common/src/test/java/org/onap/vid/asdc/parser/ToscaParserImpl2Test.java +++ b/vid-app-common/src/test/java/org/onap/vid/asdc/parser/ToscaParserImpl2Test.java @@ -20,11 +20,33 @@ package org.onap.vid.asdc.parser; +import static com.google.common.collect.Lists.newArrayList; +import static org.hamcrest.Matchers.aMapWithSize; +import static org.hamcrest.Matchers.allOf; +import static org.hamcrest.Matchers.hasKey; +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.onap.vid.asdc.parser.ToscaParserImpl2.Constants.ECOMP_GENERATED_NAMING_PROPERTY; +import static org.onap.vid.testUtils.TestUtils.assertJsonStringEqualsIgnoreNulls; + import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.UUID; +import java.util.stream.Collectors; +import java.util.stream.Stream; import net.javacrumbs.jsonunit.JsonAssert; import org.apache.commons.io.IOUtils; import org.apache.log4j.LogManager; @@ -43,7 +65,19 @@ import org.onap.vid.asdc.AsdcCatalogException; import org.onap.vid.asdc.AsdcClient; import org.onap.vid.asdc.local.LocalAsdcClient; import org.onap.vid.controller.ToscaParserMockHelper; -import org.onap.vid.model.*; +import org.onap.vid.model.CR; +import org.onap.vid.model.Network; +import org.onap.vid.model.NetworkCollection; +import org.onap.vid.model.Node; +import org.onap.vid.model.PortMirroringConfig; +import org.onap.vid.model.ResourceGroup; +import org.onap.vid.model.Service; +import org.onap.vid.model.ServiceModel; +import org.onap.vid.model.ServiceProxy; +import org.onap.vid.model.VNF; +import org.onap.vid.model.VfModule; +import org.onap.vid.model.VidNotions; +import org.onap.vid.model.VolumeGroup; import org.onap.vid.properties.Features; import org.testng.Assert; import org.testng.annotations.BeforeClass; @@ -52,22 +86,6 @@ import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import org.togglz.core.manager.FeatureManager; -import java.io.IOException; -import java.io.InputStream; -import java.nio.file.Path; -import java.util.*; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import static com.google.common.collect.Lists.newArrayList; -import static org.hamcrest.Matchers.*; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import static org.onap.vid.asdc.parser.ToscaParserImpl2.Constants.ECOMP_GENERATED_NAMING_PROPERTY; -import static org.onap.vid.testUtils.TestUtils.assertJsonStringEqualsIgnoreNulls; - public class ToscaParserImpl2Test { private final String myUUID = "myUUID"; @@ -101,7 +119,7 @@ public class ToscaParserImpl2Test { @Test(dataProvider = "expectedServiceModel") public void assertEqualsBetweenServices(String uuid, ToscaParserMockHelper mockHelper) throws Exception { - Service expectedService = mockHelper.getNewServiceModel().getService(); + Service expectedService = mockHelper.getServiceModel().getService(); Service actualService = toscaParserImpl2.makeServiceModel(getCsarPath(mockHelper.getUuid()), getServiceByUuid(mockHelper.getUuid())).getService(); assertJsonStringEqualsIgnoreNulls(om.writeValueAsString(expectedService), om.writeValueAsString(actualService)); } @@ -111,12 +129,12 @@ public class ToscaParserImpl2Test { final Path csarPath = getCsarPath(mockHelper.getUuid()); log.info("Comparing for csar " + csarPath); ServiceModel actualServiceModel = toscaParserImpl2.makeServiceModel(csarPath, getServiceByUuid(mockHelper.getUuid())); - assertJsonStringEqualsIgnoreNulls(om.writeValueAsString(mockHelper.getNewServiceModel()), om.writeValueAsString(actualServiceModel)); + assertJsonStringEqualsIgnoreNulls(om.writeValueAsString(mockHelper.getServiceModel()), om.writeValueAsString(actualServiceModel)); } @Test(dataProvider = "expectedServiceModel") public void assertEqualsBetweenNetworkNodes(String uuid, ToscaParserMockHelper mockHelper) throws Exception { - Map expectedNetworksMap = mockHelper.getNewServiceModel().getNetworks(); + Map expectedNetworksMap = mockHelper.getServiceModel().getNetworks(); Map actualNetworksMap = toscaParserImpl2.makeServiceModel(getCsarPath(mockHelper.getUuid()), getServiceByUuid(mockHelper.getUuid())).getNetworks(); for (Map.Entry entry : expectedNetworksMap.entrySet()) { Network expectedNetwork = entry.getValue(); @@ -130,7 +148,7 @@ public class ToscaParserImpl2Test { //Because we are not supporting the old flow, the JSON are different by definition. @Test(dataProvider = "expectedServiceModel") public void assertEqualsBetweenVnfsOfTosca(String uuid, ToscaParserMockHelper mockHelper) throws Exception { - Map expectedVnfsMap = mockHelper.getNewServiceModel().getVnfs(); + Map expectedVnfsMap = mockHelper.getServiceModel().getVnfs(); Map actualVnfsMap = toscaParserImpl2.makeServiceModel(getCsarPath(mockHelper.getUuid()), getServiceByUuid(mockHelper.getUuid())).getVnfs(); for (Map.Entry entry : expectedVnfsMap.entrySet()) { VNF expectedVnf = entry.getValue(); @@ -142,10 +160,12 @@ public class ToscaParserImpl2Test { } } + + @Test(dataProvider = "expectedServiceModel") public void assertEqualsBetweenCollectionResourcesOfTosca(String uuid, ToscaParserMockHelper mockHelper) throws Exception { - Map expectedVnfsMap = mockHelper.getNewServiceModel().getCollectionResource(); - Map actualCRsMap = toscaParserImpl2.makeServiceModel(getCsarPath(mockHelper.getUuid()), getServiceByUuid(mockHelper.getUuid())).getCollectionResource(); + Map expectedVnfsMap = mockHelper.getServiceModel().getCollectionResources(); + Map actualCRsMap = toscaParserImpl2.makeServiceModel(getCsarPath(mockHelper.getUuid()), getServiceByUuid(mockHelper.getUuid())).getCollectionResources(); if(!actualCRsMap.isEmpty()) { for (Map.Entry entry : expectedVnfsMap.entrySet()) { CR expectedCR = entry.getValue(); @@ -201,28 +221,28 @@ public class ToscaParserImpl2Test { @Test(dataProvider = "expectedServiceModel") public void assertEqualsBetweenVolumeGroups(String uuid, ToscaParserMockHelper mockHelper) throws Exception { Map actualVolumeGroups = toscaParserImpl2.makeServiceModel(getCsarPath(mockHelper.getUuid()), getServiceByUuid(mockHelper.getUuid())).getVolumeGroups(); - Map expectedVolumeGroups = mockHelper.getNewServiceModel().getVolumeGroups(); + Map expectedVolumeGroups = mockHelper.getServiceModel().getVolumeGroups(); assertJsonStringEqualsIgnoreNulls(om.writeValueAsString(expectedVolumeGroups), om.writeValueAsString(actualVolumeGroups)); } @Test(dataProvider = "expectedServiceModel") public void assertEqualsBetweenVfModules(String uuid, ToscaParserMockHelper mockHelper) throws Exception { Map actualVfModules = toscaParserImpl2.makeServiceModel(getCsarPath(mockHelper.getUuid()), getServiceByUuid(mockHelper.getUuid())).getVfModules(); - Map expectedVfModules = mockHelper.getNewServiceModel().getVfModules(); + Map expectedVfModules = mockHelper.getServiceModel().getVfModules(); assertJsonStringEqualsIgnoreNulls(om.writeValueAsString(expectedVfModules), om.writeValueAsString(actualVfModules)); } @Test(dataProvider = "expectedServiceModel") public void assertEqualsBetweenPolicyConfigurationNodes(String uuid, ToscaParserMockHelper mockHelper) throws Exception { Map actualConfigurations = toscaParserImpl2.makeServiceModel(getCsarPath(mockHelper.getUuid()), getServiceByUuid(mockHelper.getUuid())).getConfigurations(); - Map expectedConfigurations = mockHelper.getNewServiceModel().getConfigurations(); + Map expectedConfigurations = mockHelper.getServiceModel().getConfigurations(); JsonAssert.assertJsonEquals(actualConfigurations, expectedConfigurations); } @Test public void assertEqualsBetweenPolicyConfigurationByPolicyFalse() throws Exception { ToscaParserMockHelper mockHelper = new ToscaParserMockHelper(Constants.configurationByPolicyFalseUuid, Constants.configurationByPolicyFalseFilePath); - Map expectedConfigurations = mockHelper.getNewServiceModel().getConfigurations(); + Map expectedConfigurations = mockHelper.getServiceModel().getConfigurations(); Map actualConfigurations = toscaParserImpl2.makeServiceModel(getCsarPath(mockHelper.getUuid()), getServiceByUuid(mockHelper.getUuid())).getConfigurations(); setPprobeServiceProxy(expectedConfigurations); @@ -250,7 +270,7 @@ public class ToscaParserImpl2Test { final ToscaParserMockHelper mockHelper = new ToscaParserMockHelper("90fe6842-aa76-4b68-8329-5c86ff564407", "empty.json"); final ServiceModel serviceModel = toscaParserImpl2.makeServiceModel(getCsarPath(mockHelper.getUuid()), getServiceByUuid(mockHelper.getUuid())); - assertJsonStringEqualsIgnoreNulls("{ vfModules: { 201712488_adiodvpe10..201712488AdiodVpe1..ADIOD_vRE_BV..module-1: { inputs: { availability_zone_0: { } } } } }", om.writeValueAsString(serviceModel)); + assertJsonStringEqualsIgnoreNulls("{ vfModules: { 201712488_pasqualevpe10..201712488PasqualeVpe1..PASQUALE_vRE_BV..module-1: { inputs: { availability_zone_0: { } } } } }", om.writeValueAsString(serviceModel)); } @Test @@ -260,7 +280,7 @@ public class ToscaParserImpl2Test { assertJsonStringEqualsIgnoreNulls("" + "{ vnfs: " + - " { \"201712-488_ADIOD-vPE-1 0\": " + + " { \"201712-488_PASQUALE-vPE-1 0\": " + " { properties: { " + " ecomp_generated_naming: \"true\", " + " nf_naming: \"{naming_policy=SDNC_Policy.Config_MS_1806SRIOV_VPE_ADIoDJson, ecomp_generated_naming=true}\" " + @@ -278,14 +298,14 @@ public class ToscaParserImpl2Test { @Test(dataProvider = "expectedServiceModel") public void assertEqualsBetweenServiceProxyNodes(String uuid, ToscaParserMockHelper mockHelper) throws Exception { Map actualServiceProxies = toscaParserImpl2.makeServiceModel(getCsarPath(mockHelper.getUuid()), getServiceByUuid(mockHelper.getUuid())).getServiceProxies(); - Map expectedServiceProxies = mockHelper.getNewServiceModel().getServiceProxies(); + Map expectedServiceProxies = mockHelper.getServiceModel().getServiceProxies(); JsonAssert.assertJsonEquals(actualServiceProxies, expectedServiceProxies); } @Test(dataProvider = "expectedServiceModel") public void assertEqualsBetweenVnfGroups(String uuid, ToscaParserMockHelper mockHelper) throws Exception { Map actualVnfGroups = toscaParserImpl2.makeServiceModel(getCsarPath(mockHelper.getUuid()), getServiceByUuid(mockHelper.getUuid())).getVnfGroups(); - Map expectedVnfGroups = mockHelper.getNewServiceModel().getVnfGroups(); + Map expectedVnfGroups = mockHelper.getServiceModel().getVnfGroups(); JsonAssert.assertJsonEquals(actualVnfGroups, expectedVnfGroups); } @@ -342,7 +362,7 @@ public class ToscaParserImpl2Test { static final String vfWithAnnotationUuid = "f4d84bb4-a416-4b4e-997e-0059973630b9"; static final String vlUuid = "cb49608f-5a24-4789-b0f7-2595473cb997"; static final String crUuid = "76f27dfe-33e5-472f-8e0b-acf524adc4f0"; - static final String vfWithVfcGroup = "6bce7302-70bd-4057-b48e-8d5b99e686ca"; //service-VdbeSrv-csar.zip + static final String vfWithVfcGroup = "6bce7302-70bd-4057-b48e-8d5b99e686ca"; //service-VdorotheaSrv-csar.zip // public static final String PNFUuid = "68101369-6f08-4e99-9a28-fa6327d344f3"; static final String vfFilePath = "vf-csar.JSON"; static final String vlFilePath = "vl-csar.JSON"; @@ -358,6 +378,8 @@ public class ToscaParserImpl2Test { //public static final String vnfGroupingUuid = "4117a0b6-e234-467d-b5b9-fe2f68c8b0fc"; //public static final String vnfGroupingFilePath = "vnf-grouping-csar.json"; + public static final String QUANTITY = "quantity"; + } diff --git a/vid-app-common/src/test/java/org/onap/vid/asdc/parser/ToscaParserInflatorTest.java b/vid-app-common/src/test/java/org/onap/vid/asdc/parser/ToscaParserInflatorTest.java index 4c5cc9787..d6c080d55 100644 --- a/vid-app-common/src/test/java/org/onap/vid/asdc/parser/ToscaParserInflatorTest.java +++ b/vid-app-common/src/test/java/org/onap/vid/asdc/parser/ToscaParserInflatorTest.java @@ -20,7 +20,16 @@ package org.onap.vid.asdc.parser; +import static java.util.Collections.emptyMap; +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; + import com.google.common.collect.ImmutableMap; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Path; +import java.util.Map; +import java.util.UUID; import org.apache.commons.io.IOUtils; import org.apache.log4j.LogManager; import org.apache.log4j.Logger; @@ -41,16 +50,6 @@ import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; -import java.io.IOException; -import java.io.InputStream; -import java.nio.file.Path; -import java.util.Map; -import java.util.UUID; - -import static java.util.Collections.emptyMap; -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; - public class ToscaParserInflatorTest { private static final Logger log = LogManager.getLogger(ToscaParserInflatorTest.class); @@ -83,15 +82,15 @@ public class ToscaParserInflatorTest { @Test public void inflateFabricConfigurationModel_allIdsAreGiven() throws Exception { - final String fabricConfigurationUuid = "90fe6842-aa76-4b68-8329-5c86ff564407"; + final String fabricConfigurationUuid = "12344bb4-a416-4b4e-997e-0059973630b9"; final Map inflated = inflateModelByUuid(fabricConfigurationUuid); // see vf-with-annotation-csar.json assertThat(inflated, is(ImmutableMap.of( - "8df1892c-377d-460b-8a8d-fc8a116e9d92", doubleName("201712-488_ADIOD-vPE-1 0"), - "8d521692-7661-4296-b77e-a2058bb62e87", new Names("201712488AdiodVpe1..ADIOD_vRE_BV..module-1", "201712488_adiodvpe10..201712488AdiodVpe1..ADIOD_vRE_BV..module-1"), - "79fbee20-7fba-4166-ae4b-b94c869e7d8b", new Names("201712488AdiodVpe1..ADIOD_vPFE_BV..module-2","201712488_adiodvpe10..201712488AdiodVpe1..ADIOD_vPFE_BV..module-2"), - "806505b8-7a7c-47a2-acef-b4d26fe95a92", new Names("201712488AdiodVpe1..ADIOD_base_vPE_BV..module-0","201712488_adiodvpe10..201712488AdiodVpe1..ADIOD_base_vPE_BV..module-0") + "ea81d6f7-0861-44a7-b7d5-d173b562c350", doubleName("2017-488_PASQUALE-vPE 0"), + "a5d8df05-11cb-4351-96e0-b6d4168ea4df", new Names("2017488PasqualeVpe..PASQUALE_vRE_BV..module-1", "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vRE_BV..module-1"), + "b3e8b26e-cff0-49fc-a4e6-f3e16c8440fe", new Names("2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2","2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2"), + "040e591e-5d30-4e0d-850f-7266e5a8e013", new Names("2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0","2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0") ))); } diff --git a/vid-app-common/src/test/java/org/onap/vid/asdc/parser/VidNotionsBuilderTest.java b/vid-app-common/src/test/java/org/onap/vid/asdc/parser/VidNotionsBuilderTest.java index 788f78084..edaf7125f 100644 --- a/vid-app-common/src/test/java/org/onap/vid/asdc/parser/VidNotionsBuilderTest.java +++ b/vid-app-common/src/test/java/org/onap/vid/asdc/parser/VidNotionsBuilderTest.java @@ -7,9 +7,9 @@ * 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. @@ -30,28 +30,35 @@ import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import org.onap.sdc.tosca.parser.api.ISdcCsarHelper; import org.onap.sdc.tosca.parser.exceptions.SdcToscaParserException; -import org.onap.sdc.tosca.parser.impl.SdcToscaParserFactory; import org.onap.sdc.toscaparser.api.NodeTemplate; import org.onap.sdc.toscaparser.api.Property; import org.onap.sdc.toscaparser.api.elements.Metadata; import org.onap.vid.model.*; import org.onap.vid.properties.Features; +import org.onap.vid.testUtils.TestUtils; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeClass; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import org.togglz.core.manager.FeatureManager; -import java.util.LinkedHashMap; -import java.util.UUID; +import java.io.File; +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.*; import java.util.function.BiConsumer; +import static java.util.Collections.emptyList; +import static java.util.Collections.emptyMap; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.hasProperty; import static org.hamcrest.Matchers.is; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -import static org.testng.Assert.assertEquals; +import static org.onap.vid.model.VidNotions.*; +import static org.testng.AssertJUnit.assertEquals; public class VidNotionsBuilderTest { @@ -61,6 +68,10 @@ public class VidNotionsBuilderTest { @Mock private FeatureManager featureManagerMock; + private ServiceModel serviceModel; + + private ISdcCsarHelper csarHelper; + @BeforeClass public void initMocks() { MockitoAnnotations.initMocks(this); @@ -75,12 +86,12 @@ public class VidNotionsBuilderTest { public void VLNetworkWithPropertyNetworkTechnologyOVS_UIHintIsPositive() { ISdcCsarHelper csarHelper = mockForNonLegacyInstantiationUI(); - assertThat(vidNotionsBuilder.suggestInstantiationUI(csarHelper), is(VidNotions.InstantiationUI.NETWORK_WITH_PROPERTY_NETWORK_TECHNOLOGY_EQUALS_STANDARD_SRIOV_OR_OVS)); - assertThat(vidNotionsBuilder.suggestModelCategory(csarHelper) , is(VidNotions.ModelCategory.IS_5G_PROVIDER_NETWORK_MODEL)); + assertThat(vidNotionsBuilder.suggestInstantiationUI(csarHelper, serviceModel), is(InstantiationUI.NETWORK_WITH_PROPERTY_NETWORK_TECHNOLOGY_EQUALS_STANDARD_SRIOV_OR_OVS)); + assertThat(vidNotionsBuilder.suggestModelCategory(csarHelper, serviceModel) , is(ModelCategory.IS_5G_PROVIDER_NETWORK_MODEL)); } @NotNull - protected ISdcCsarHelper mockForNonLegacyInstantiationUI() { + private ISdcCsarHelper mockForNonLegacyInstantiationUI() { ISdcCsarHelper csarHelper = ToscaParserImpl2Test.getMockedSdcCsarHelper(UUID.randomUUID().toString()); NodeTemplate nodeTemplate = mock(NodeTemplate.class); @@ -98,15 +109,16 @@ public class VidNotionsBuilderTest { @DataProvider public static Object[][] anyAlacarteDataProvider() { return new Object[][] { - {"A-La-Carte", VidNotions.InstantiationUI.ANY_ALACARTE_NEW_UI}, - {"Macro", VidNotions.InstantiationUI.LEGACY}, + {"A-La-Carte", InstantiationUI.ANY_ALACARTE_NEW_UI}, + {"Macro", InstantiationUI.LEGACY}, }; } @Test(dataProvider = "anyAlacarteDataProvider") - public void FLAG_EXP_ANY_ALACARTE_NEW_INSTANTIATION_UI_is_active_UIHintIsPositive(String instantiationType, VidNotions.InstantiationUI expectedInstantiationUI) { + public void FLAG_EXP_ANY_ALACARTE_NEW_INSTANTIATION_UI_is_active_UIHintIsPositive(String instantiationType, InstantiationUI expectedInstantiationUI) { + initServiceModelAndscarHelperWithMocks(); + when(featureManagerMock.isActive(Features.FLAG_EXP_ANY_ALACARTE_NEW_INSTANTIATION_UI)).thenReturn(true); - ISdcCsarHelper csarHelper = ToscaParserImpl2Test.getMockedSdcCsarHelper(UUID.randomUUID().toString()); when(csarHelper.getServiceMetadata()).thenReturn(new Metadata(ImmutableMap.of( "instantiationType", instantiationType ))); @@ -119,12 +131,12 @@ public class VidNotionsBuilderTest { when(csarHelper.getServiceVlList()).thenReturn(ImmutableList.of(nodeTemplate)); - assertThat(vidNotionsBuilder.suggestInstantiationUI(csarHelper), is(expectedInstantiationUI)); + assertThat(vidNotionsBuilder.suggestInstantiationUI(csarHelper, serviceModel), is(expectedInstantiationUI)); } @Test public void VLNetworkWithPropertyNetworkTechnologyNot5G_UIHintIsNegative() { - ISdcCsarHelper csarHelper = ToscaParserImpl2Test.getMockedSdcCsarHelper(UUID.randomUUID().toString()); + initServiceModelAndscarHelperWithMocks(); NodeTemplate nodeTemplate = mock(NodeTemplate.class); @@ -135,85 +147,91 @@ public class VidNotionsBuilderTest { when(csarHelper.getServiceVlList()).thenReturn(ImmutableList.of(nodeTemplate)); - assertThat(vidNotionsBuilder.suggestInstantiationUI(csarHelper), is(VidNotions.InstantiationUI.LEGACY)); - assertThat(vidNotionsBuilder.suggestModelCategory(csarHelper) , is(VidNotions.ModelCategory.OTHER)); + assertThat(vidNotionsBuilder.suggestInstantiationUI(csarHelper, serviceModel), is(InstantiationUI.LEGACY)); + assertThat(vidNotionsBuilder.suggestModelCategory(csarHelper, serviceModel) , is(ModelCategory.OTHER)); } @Test - public void withoutMocks_givenZippedToscaFile_hasAnyNetworkWithPropertyEqualsToAnyOfYieldsTrue() throws SdcToscaParserException { - SdcToscaParserFactory factory = SdcToscaParserFactory.getInstance(); - ISdcCsarHelper csarHelper = factory.getSdcCsarHelper(getClass().getClassLoader().getResource("service-vl-csar.zip").getPath(),false); - + public void withoutMocks_givenZippedToscaFile_hasAnyNetworkWithPropertyEqualsToAnyOfYieldsTrue() throws SdcToscaParserException, IOException { + initServiceModelAndscarHelperWithRealCsar("/csars/service-vl-csar.zip"); assertThat(vidNotionsBuilder.isALaCarte(csarHelper), is(false)); assertThat(vidNotionsBuilder.hasAnyNetworkWithPropertyEqualsToAnyOf(csarHelper, "unexpected_property_name"), is(false)); assertThat(vidNotionsBuilder.hasAnyNetworkWithPropertyEqualsToAnyOf(csarHelper, "network_technology","Standard-SR-IOV"), is(true)); - assertThat(vidNotionsBuilder.suggestInstantiationUI(csarHelper), is(VidNotions.InstantiationUI.LEGACY)); + assertThat(vidNotionsBuilder.suggestInstantiationUI(csarHelper, serviceModel), is(InstantiationUI.LEGACY)); } - //@Test - //public void withoutMocks_givenZippedToscaFile_hasFabricConfigurationYieldsTrue() throws SdcToscaParserException { - // SdcToscaParserFactory factory = SdcToscaParserFactory.getInstance(); - // ISdcCsarHelper csarHelper = factory.getSdcCsarHelper(getClass().getClassLoader().getResource("service-fabric-configuration.zip").getPath(),false); - // - // assertThat(vidNotionsBuilder.isALaCarte(csarHelper), is(false)); - // assertThat(vidNotionsBuilder.hasFabricConfiguration(csarHelper), is(true)); - // assertThat(vidNotionsBuilder.suggestInstantiationUI(csarHelper), is(VidNotions.InstantiationUI.LEGACY)); - //} + @Test + public void withoutMocks_givenZippedToscaFile_hasFabricConfigurationYieldsTrue() throws SdcToscaParserException, IOException { + initServiceModelAndscarHelperWithRealCsar("/csars/service-fabric-configuration.zip"); + assertThat(vidNotionsBuilder.isALaCarte(csarHelper), is(false)); + assertThat(vidNotionsBuilder.hasFabricConfiguration(csarHelper), is(true)); + assertThat(vidNotionsBuilder.suggestInstantiationUI(csarHelper, serviceModel), is(InstantiationUI.LEGACY)); + } + + @Test(dataProvider = "trueAndFalse", dataProviderClass = TestUtils.class) + public void withoutMocks_givenZippedToscaFileOfTransportService_InstantiationUIAndCategoryAreRight(boolean flagValue) throws SdcToscaParserException, IOException { + initServiceModelAndscarHelperWithRealCsar("/csars/csarTransportWithPnfs.zip"); + when(featureManagerMock.isActive(Features.FLAG_1908_TRANSPORT_SERVICE_NEW_INSTANTIATION_UI)).thenReturn(flagValue); + + assertThat(vidNotionsBuilder.isALaCarte(csarHelper), is(false)); + assertThat(vidNotionsBuilder.suggestInstantiationUI(csarHelper, serviceModel), is(flagValue ? InstantiationUI.TRANSPORT_SERVICE : InstantiationUI.LEGACY)); + assertThat(vidNotionsBuilder.suggestModelCategory(csarHelper, serviceModel), is(ModelCategory.Transport)); + } + + @Test(dataProvider = "trueAndFalse", dataProviderClass = TestUtils.class) + public void withoutMocks_givenZippedToscaFileOfInfraStructureVpn_InstantiationUIIsRight(boolean flagValue) throws SdcToscaParserException, IOException { + initServiceModelAndscarHelperWithRealCsar("/csars/service-Infravpn-csar.zip"); + when(featureManagerMock.isActive(Features.FLAG_1908_INFRASTRUCTURE_VPN)).thenReturn(flagValue); + assertThat(vidNotionsBuilder.suggestInstantiationUI(csarHelper, serviceModel), is(flagValue ? InstantiationUI.INFRASTRUCTURE_VPN : InstantiationUI.LEGACY)); + assertThat(vidNotionsBuilder.suggestModelCategory(csarHelper, serviceModel), is(ModelCategory.INFRASTRUCTURE_VPN)); + } @Test public void uuidIsExactly1ffce89fEtc_UIHintIsPositive() { - ISdcCsarHelper csarHelper = ToscaParserImpl2Test.getMockedSdcCsarHelper(UUID.randomUUID().toString()); + initServiceModelAndscarHelperWithMocks(); when(csarHelper.getServiceMetadata()).thenReturn(new Metadata(ImmutableMap.of( "UUID", "95eb2c44-bff2-4e8b-ad5d-8266870b7717" ))); when(featureManagerMock.isActive(Features.FLAG_5G_IN_NEW_INSTANTIATION_UI)).thenReturn(true); - assertThat(vidNotionsBuilder.suggestInstantiationUI(csarHelper), is(VidNotions.InstantiationUI.SERVICE_UUID_IS_1ffce89f_ef3f_4cbb_8b37_82134590c5de)); - } - - - @DataProvider - public static Object[][] trueAndFalse() { - return new Object[][] {{true}, {false}}; + assertThat(vidNotionsBuilder.suggestInstantiationUI(csarHelper, serviceModel), is(InstantiationUI.SERVICE_UUID_IS_1ffce89f_ef3f_4cbb_8b37_82134590c5de)); } - @Test(dataProvider = "trueAndFalse") + @Test(dataProvider = "trueAndFalse", dataProviderClass = TestUtils.class) public void buildVidNotions_nullByFlag(boolean flagValue) { - ISdcCsarHelper csarHelper = ToscaParserImpl2Test.getMockedSdcCsarHelper(UUID.randomUUID().toString()); + initServiceModelAndscarHelperWithMocks(); when(featureManagerMock.isActive(Features.FLAG_5G_IN_NEW_INSTANTIATION_UI)).thenReturn(flagValue); - assertThat(vidNotionsBuilder.buildVidNotions(csarHelper, null), hasProperty("instantiationUI", is(VidNotions.InstantiationUI.LEGACY))); + assertThat(vidNotionsBuilder.buildVidNotions(csarHelper, serviceModel), hasProperty("instantiationUI", is(InstantiationUI.LEGACY))); } @DataProvider public static Object[][] ServiceRoleTypesDataProvider() { return new Object[][] { - {"gROUPING", VidNotions.InstantiationUI.SERVICE_WITH_VNF_GROUPING}, - {"", VidNotions.InstantiationUI.LEGACY}, + {"gROUPING", InstantiationUI.SERVICE_WITH_VNF_GROUPING}, + {"", InstantiationUI.LEGACY}, }; } @Test(dataProvider = "ServiceRoleTypesDataProvider") - public void testGetViewEditUITypeForResourceGroup(String serviceRole, VidNotions.InstantiationUI expectedViewEditUI) { - when(featureManagerMock.isActive(Features.FLAG_ASYNC_INSTANTIATION)).thenReturn(true); + public void testGetViewEditUITypeForResourceGroup(String serviceRole, InstantiationUI expectedViewEditUI) { + initServiceModelAndscarHelperWithMocks(); when(featureManagerMock.isActive(Features.FLAG_1902_VNF_GROUPING)).thenReturn(true); - ISdcCsarHelper csarHelper = ToscaParserImpl2Test.getMockedSdcCsarHelper(UUID.randomUUID().toString()); when(csarHelper.getServiceMetadata()).thenReturn(new Metadata(ImmutableMap.of( "serviceRole", serviceRole ))); - assertThat(vidNotionsBuilder.suggestViewEditUI(csarHelper, null), is(expectedViewEditUI)); + assertThat(vidNotionsBuilder.suggestViewEditUI(csarHelper, serviceModel), is(expectedViewEditUI)); } @DataProvider public static Object[][] macroToViewEditDataProvider() { return new Object[][] { - {"macro service + not excluded + needed flags are open", true, false, true, true, VidNotions.InstantiationUI.MACRO_SERVICE}, - {"not macro service", false, false, true, true, VidNotions.InstantiationUI.LEGACY}, - {"macro that shall be excluded because it has pnf", true, true, true, true, VidNotions.InstantiationUI.LEGACY}, - {"macro service + FLAG_ASYNC_INSTANTIATION off", true, false, false, true, VidNotions.InstantiationUI.LEGACY}, - {"macro service + FLAG_1902_NEW_VIEW_EDIT off", true, false, true, false, VidNotions.InstantiationUI.LEGACY}, + {"macro service + not excluded + needed flags are open", true, false, true, InstantiationUI.MACRO_SERVICE}, + {"not macro service", false, true, true, InstantiationUI.LEGACY}, + {"macro that shall be excluded because it has pnf", true, true, true, InstantiationUI.LEGACY}, + {"macro service + FLAG_1902_NEW_VIEW_EDIT off", true, false, false, InstantiationUI.LEGACY}, }; } @@ -222,19 +240,16 @@ public class VidNotionsBuilderTest { String testDescription, boolean isMacro, boolean isExcluded, - boolean isFlagAsyncInstantiationActive, boolean isFlag1902NewViewEdit, - VidNotions.InstantiationUI expectedViewEditUi) { + InstantiationUI expectedViewEditUi) { - ISdcCsarHelper csarHelper = mock(ISdcCsarHelper.class); - ServiceModel serviceModel = mock(ServiceModel.class); + initServiceModelAndscarHelperWithMocks(); //mock for is Macro String instantiationType = isMacro ? ToscaParserImpl2.Constants.MACRO : ToscaParserImpl2.Constants.A_LA_CARTE; Service service = mock(Service.class); when(serviceModel.getService()).thenReturn(service); when(service.getInstantiationType()).thenReturn(instantiationType); - when(featureManagerMock.isActive(Features.FLAG_ASYNC_INSTANTIATION)).thenReturn(isFlagAsyncInstantiationActive); when(featureManagerMock.isActive(Features.FLAG_1902_NEW_VIEW_EDIT)).thenReturn(isFlag1902NewViewEdit); //mock for isExcluded @@ -242,17 +257,16 @@ public class VidNotionsBuilderTest { when(serviceModel.getPnfs()).thenReturn(ImmutableMap.of("a", mock(Node.class))); } - VidNotions.InstantiationUI result = vidNotionsBuilder.suggestViewEditUI(csarHelper, serviceModel); + InstantiationUI result = vidNotionsBuilder.suggestViewEditUI(csarHelper, serviceModel); assertEquals(expectedViewEditUi, result); } @DataProvider public static Object[][] instantiationUIToViewEditDataProvider() { return new Object[][] { - {"network cloud(5G) service + needed flags are open", true, true, true, VidNotions.InstantiationUI.NETWORK_WITH_PROPERTY_NETWORK_TECHNOLOGY_EQUALS_STANDARD_SRIOV_OR_OVS}, - {"mocked service + needed flags are open", false, true, true, VidNotions.InstantiationUI.LEGACY}, - {"network cloud(5G) service + FLAG_ASYNC_INSTANTIATION is off", true, false, true, VidNotions.InstantiationUI.LEGACY}, - {"network cloud(5G) service + FLAG_1902_NEW_VIEW_EDIT is off", true, true, false, VidNotions.InstantiationUI.LEGACY}, + {"network cloud(5G) service + needed flags are open", true, true, InstantiationUI.NETWORK_WITH_PROPERTY_NETWORK_TECHNOLOGY_EQUALS_STANDARD_SRIOV_OR_OVS}, + {"mocked service + needed flags are open", false, true, InstantiationUI.LEGACY}, + {"network cloud(5G) service + FLAG_1902_NEW_VIEW_EDIT is off", true, false, InstantiationUI.LEGACY}, }; } @@ -261,12 +275,10 @@ public class VidNotionsBuilderTest { public void whenInstantiationUIIsNotLegacy_viewEditIsRight( String testDescription, boolean isInstantiationUINotLegacy, - boolean isFlagAsyncInstantiationActive, boolean isFlag1902NewViewEdit, - VidNotions.InstantiationUI expectedViewEditUi) { + InstantiationUI expectedViewEditUi) { ISdcCsarHelper csarHelper = isInstantiationUINotLegacy ? mockForNonLegacyInstantiationUI() : mock(ISdcCsarHelper.class); - when(featureManagerMock.isActive(Features.FLAG_ASYNC_INSTANTIATION)).thenReturn(isFlagAsyncInstantiationActive); when(featureManagerMock.isActive(Features.FLAG_1902_NEW_VIEW_EDIT)).thenReturn(isFlag1902NewViewEdit); ServiceModel serviceModel = mock(ServiceModel.class); @@ -274,7 +286,7 @@ public class VidNotionsBuilderTest { when(serviceModel.getService()).thenReturn(service); when(service.getInstantiationType()).thenReturn(ToscaParserImpl2.Constants.A_LA_CARTE); - VidNotions.InstantiationUI result = vidNotionsBuilder.suggestViewEditUI(csarHelper, serviceModel); + InstantiationUI result = vidNotionsBuilder.suggestViewEditUI(csarHelper, serviceModel); assertEquals(expectedViewEditUi, result); } @@ -282,7 +294,7 @@ public class VidNotionsBuilderTest { public static Object[][] mockerForMacroExcluded() { return new Object[][] { {"service with pnfs", (BiConsumer) (serviceModel, fm)->when(serviceModel.getPnfs()).thenReturn(ImmutableMap.of("a", mock(Node.class))), true}, - {"service with collection resource", (BiConsumer) (serviceModel, fm)->when(serviceModel.getCollectionResource()).thenReturn(ImmutableMap.of("a", mock(CR.class))), true}, + {"service with collection resource", (BiConsumer) (serviceModel, fm) -> when(serviceModel.getCollectionResources()).thenReturn(ImmutableMap.of("a", mock(CR.class))), true}, {"service with network + FLAG_NETWORK_TO_ASYNC_INSTANTIATION false ", (BiConsumer) (serviceModel, fm)->{ when(serviceModel.getNetworks()).thenReturn(ImmutableMap.of("a", mock(Network.class))); when(fm.isActive(Features.FLAG_NETWORK_TO_ASYNC_INSTANTIATION)).thenReturn(false);} @@ -290,7 +302,7 @@ public class VidNotionsBuilderTest { {"service with network + FLAG_NETWORK_TO_ASYNC_INSTANTIATION true", (BiConsumer) (serviceModel, fm)->{ when(serviceModel.getNetworks()).thenReturn(ImmutableMap.of("a", mock(Network.class))); when(fm.isActive(Features.FLAG_NETWORK_TO_ASYNC_INSTANTIATION)).thenReturn(true);} - , false}, + , false}, {"empty service + FLAG_NETWORK_TO_ASYNC_INSTANTIATION false", (BiConsumer) (serviceModel, fm)->when(fm.isActive(Features.FLAG_NETWORK_TO_ASYNC_INSTANTIATION)).thenReturn(false), false}, }; } @@ -302,9 +314,197 @@ public class VidNotionsBuilderTest { assertEquals(shallBeExcluded, vidNotionsBuilder.isMacroExcludedFromAsyncFlow(serviceModel)); } + @DataProvider + public static Object[][] toscaParserInstantiationTypeToVidNotion() { + return new Object[][] { + {ToscaParserImpl2.Constants.MACRO, InstantiationType.Macro}, + {ToscaParserImpl2.Constants.A_LA_CARTE, InstantiationType.ALaCarte}, + {ToscaParserImpl2.Constants.CLIENT_CONFIG, InstantiationType.ClientConfig}, + {"I dont know", InstantiationType.ClientConfig}, + {"", InstantiationType.ClientConfig} + }; + } + + @Test(dataProvider="toscaParserInstantiationTypeToVidNotion") + public void testSuggestInstantiationTypeWhenInstantiationUiLegacy(String toscaParserInstantiationType, InstantiationType expectedInstantiationType) { + ServiceModel serviceModel = mock(ServiceModel.class); + Service service = mock(Service.class); + when(serviceModel.getService()).thenReturn(service); + when(service.getInstantiationType()).thenReturn(toscaParserInstantiationType); + assertEquals(expectedInstantiationType, vidNotionsBuilder.suggestInstantiationType(serviceModel, ModelCategory.OTHER)); + } + + @DataProvider + public static Object[][] instantiationUIAndFeatureFlagsForInstantiationType() { + return new Object[][] { + {ModelCategory.Transport, Features.FLAG_1908_TRANSPORT_SERVICE_NEW_INSTANTIATION_UI, true, InstantiationType.Macro}, + {ModelCategory.Transport, Features.FLAG_1908_TRANSPORT_SERVICE_NEW_INSTANTIATION_UI, false, InstantiationType.ALaCarte}, + {ModelCategory.INFRASTRUCTURE_VPN, Features.FLAG_1908_INFRASTRUCTURE_VPN, true, InstantiationType.Macro}, + {ModelCategory.INFRASTRUCTURE_VPN, Features.FLAG_1908_INFRASTRUCTURE_VPN, false, InstantiationType.ALaCarte}, + {ModelCategory.OTHER, Features.FLAG_1908_INFRASTRUCTURE_VPN, true, InstantiationType.ALaCarte}, //not mapped InstantiationUI + }; + } + @Test(dataProvider="instantiationUIAndFeatureFlagsForInstantiationType") + public void testSuggestInstantiationTypeByModelCategoryAndFeatureFlags( + ModelCategory instantiationUI, + Features featureFlag, + boolean isFeatureOn, + InstantiationType expectedInstantiationType) { + ServiceModel serviceModel = mock(ServiceModel.class); + Service service = mock(Service.class); + when(serviceModel.getService()).thenReturn(service); + when(service.getInstantiationType()).thenReturn(ToscaParserImpl2.Constants.A_LA_CARTE); + when(featureManagerMock.isActive(featureFlag)).thenReturn(isFeatureOn); + assertEquals(expectedInstantiationType, vidNotionsBuilder.suggestInstantiationType(serviceModel, instantiationUI)); + } + @DataProvider + public static Object[][] FLAG_1908_COLLECTION_RESOURCE_NEW_INSTANTIATION_UIValueAndCollectionResourceForVidNotions() { + return new Object[][] { + {true, ImmutableMap.of("Some string", mock(CR.class)), InstantiationUI.SERVICE_WITH_COLLECTION_RESOURCE, ModelCategory.SERVICE_WITH_COLLECTION_RESOURCE}, + {true, Collections.EMPTY_MAP, InstantiationUI.LEGACY, ModelCategory.OTHER}, + {true, null, InstantiationUI.LEGACY, ModelCategory.OTHER}, + {false, ImmutableMap.of("Some string", mock(CR.class)), InstantiationUI.LEGACY, ModelCategory.SERVICE_WITH_COLLECTION_RESOURCE}, + {false, Collections.EMPTY_MAP, InstantiationUI.LEGACY, ModelCategory.OTHER}, + {false, null, InstantiationUI.LEGACY, ModelCategory.OTHER} + }; + } + @Test(dataProvider="FLAG_1908_COLLECTION_RESOURCE_NEW_INSTANTIATION_UIValueAndCollectionResourceForVidNotions") + public void testSuggestInstantiationUiAndModelCategoryByCollectionResourceAndFeatureFlag_FLAG_1908_COLLECTION_RESOURCE_NEW_INSTANTIATION_UI( + boolean featureFlagValue, + Map collectionResource, + VidNotions.InstantiationUI expectedInstantiationUi, + VidNotions.ModelCategory expectedModelCategory) { + initServiceModelAndscarHelperWithMocks(); + Service service = mock(Service.class); + when(service.getInstantiationType()).thenReturn(ToscaParserImpl2.Constants.MACRO); + when(serviceModel.getService()).thenReturn(service); + when(serviceModel.getCollectionResources()).thenReturn(collectionResource); + when(featureManagerMock.isActive(Features.FLAG_1908_COLLECTION_RESOURCE_NEW_INSTANTIATION_UI)).thenReturn(featureFlagValue); + VidNotions vidNotions = vidNotionsBuilder.buildVidNotions(csarHelper, serviceModel); + assertEquals(expectedInstantiationUi, vidNotions.getInstantiationUI()); + assertEquals(expectedModelCategory, vidNotions.getModelCategory()); + assertEquals(InstantiationUI.LEGACY, vidNotions.getViewEditUI()); + assertEquals(InstantiationType.Macro, vidNotions.getInstantiationType()); + } -} + @DataProvider + public static Object[][] givenCollectionResourceServiceDataProvider() { + return new Object[][]{ + {false, true, InstantiationUI.LEGACY}, + {true, false, InstantiationUI.LEGACY}, + {true, true, InstantiationUI.SERVICE_WITH_COLLECTION_RESOURCE} + }; + } + + @Test(dataProvider = "givenCollectionResourceServiceDataProvider") + public void givenCollectionResourceService_whenSuggestViewEdit_thenResultAccordingFeatureFlag( + boolean crFlag, boolean resumeFlag, VidNotions.InstantiationUI expectedViewEditUi) { + + //mock service with CR + ServiceModel mockServiceModel = mock(ServiceModel.class); + when(mockServiceModel.getCollectionResources()).thenReturn(ImmutableMap.of("a", mock(CR.class))); + + //mock feature flags + when(featureManagerMock.isActive(Features.FLAG_1908_COLLECTION_RESOURCE_NEW_INSTANTIATION_UI)).thenReturn(crFlag); + when(featureManagerMock.isActive(Features.FLAG_1908_RESUME_MACRO_SERVICE)).thenReturn(resumeFlag); + + assertEquals(expectedViewEditUi, vidNotionsBuilder.suggestViewEditUI(mock(ISdcCsarHelper.class), mockServiceModel)); + } + + @Test + public void whenServiceModelIsNull_thenInstantiationTypeIsClientConfig() { + assertEquals( InstantiationType.ClientConfig, vidNotionsBuilder.suggestInstantiationType(null, ModelCategory.OTHER)); + } + + @Test + public void whenServiceInServiceModelIsNull_thenInstantiationTypeIsClientConfig() { + assertEquals( InstantiationType.ClientConfig, vidNotionsBuilder.suggestInstantiationType(mock(ServiceModel.class), ModelCategory.OTHER)); + } + + @Test + public void whenInstantiationTypeInServiceModelIsNull_thenInstantiationTypeIsClientConfig() { + initServiceModelAndscarHelperWithMocks(); + Service service = mock(Service.class); + when(serviceModel.getService()).thenReturn(service); + when(service.getInstantiationType()).thenReturn(null); + assertEquals( InstantiationType.ClientConfig, vidNotionsBuilder.suggestInstantiationType(serviceModel, ModelCategory.OTHER)); + } + + private void initServiceModelAndscarHelperWithRealCsar(String path) throws SdcToscaParserException, IOException { + Path csarPath = Paths.get(new File(getClass().getResource(path).getPath()).getCanonicalPath()); + ToscaParserImpl2 toscaParser = new ToscaParserImpl2(vidNotionsBuilder); + org.onap.vid.asdc.beans.Service asdcServiceMetadata = mock(org.onap.vid.asdc.beans.Service.class); + when(asdcServiceMetadata.getVersion()).thenReturn("versions"); + serviceModel = toscaParser.makeServiceModel(csarPath, asdcServiceMetadata); + csarHelper = toscaParser.getSdcCsarHelper(csarPath); + } + + private void initServiceModelAndscarHelperWithMocks() { + csarHelper = ToscaParserImpl2Test.getMockedSdcCsarHelper(UUID.randomUUID().toString()); + serviceModel = mock(ServiceModel.class); + } + + @DataProvider + public static Object[][] VnfNcIndicationDataProvider() { + return new Object[][] { + {true, "VNF", InstantiationUI.A_LA_CARTE_VNF_SERVICE_ROLE}, + {false, "VNF", InstantiationUI.LEGACY}, + {false, "notVNF", InstantiationUI.LEGACY}, + {true, null, InstantiationUI.LEGACY}, + {true, "notVNF", InstantiationUI.LEGACY}, + {true, "vnf", InstantiationUI.A_LA_CARTE_VNF_SERVICE_ROLE}, + }; + } + + @Test (dataProvider = "VnfNcIndicationDataProvider") + public void whenServiceRoleVnf_thenInstantiationTypeNewUI(boolean flagOn, String serviceRole, InstantiationUI expectedViewEditUi){ + initServiceModelAndscarHelperWithMocks(); + + when(featureManagerMock.isActive(Features.FLAG_1908_A_LA_CARTE_VNF_NEW_INSTANTIATION_UI)).thenReturn(flagOn); + + when(csarHelper.getServiceMetadata()).thenReturn(new Metadata(serviceRole == null ? + emptyMap() : ImmutableMap.of(ToscaParserImpl2.Constants.SERVICE_ROLE, serviceRole) + )); + + assertEquals(expectedViewEditUi, vidNotionsBuilder.suggestInstantiationUI(csarHelper, serviceModel)); + } + + private static NodeTemplate mockNodeTemplateChild(boolean withFabricConfiguration) { + NodeTemplate child = mock(NodeTemplate.class); + when(child.getType()).thenReturn(withFabricConfiguration ? ToscaParserImpl2.Constants.FABRIC_CONFIGURATION_TYPE : "nothing"); + return child; + } + + private static ISdcCsarHelper mockServiceNodeTemplates(ISdcCsarHelper csarHelper, ImmutableList children) { + when(csarHelper.getNodeTemplateChildren(any())).thenReturn(children); + + NodeTemplate parent = mock(NodeTemplate.class); + List nodeTemplates = ImmutableList.of(parent); + + when(csarHelper.getServiceNodeTemplates()).thenReturn(nodeTemplates); + return csarHelper; + } + + @DataProvider + public static Object[][] csarHelpersForFabricConfiguration() { + ISdcCsarHelper csarHelperWithNoNodes = mock(ISdcCsarHelper.class); + when(csarHelperWithNoNodes.getServiceNodeTemplates()).thenReturn(emptyList()); + + return new Object[][] { + { "zero nodes", false, csarHelperWithNoNodes }, + { "single node with no child", false, mockServiceNodeTemplates(mock(ISdcCsarHelper.class), ImmutableList.of()) }, + { "single node with single fabric child", true, mockServiceNodeTemplates(mock(ISdcCsarHelper.class), ImmutableList.of(mockNodeTemplateChild(true))) }, + { "single node with single fabric child and single non-fabric", true, mockServiceNodeTemplates(mock(ISdcCsarHelper.class), ImmutableList.of( + mockNodeTemplateChild(true), mockNodeTemplateChild(true))) }, + }; + } + + @Test (dataProvider = "csarHelpersForFabricConfiguration") + public void hasFabricConfiguration(String desc, boolean shouldHaveFabricConfiguration, ISdcCsarHelper csarHelper) { + assertThat(desc, vidNotionsBuilder.hasFabricConfiguration(csarHelper), is(shouldHaveFabricConfiguration)); + } +} \ No newline at end of file diff --git a/vid-app-common/src/test/java/org/onap/vid/changeManagement/WorkflowRequestDetailTest.java b/vid-app-common/src/test/java/org/onap/vid/changeManagement/WorkflowRequestDetailTest.java index 38f15d7e5..fbaa763cf 100644 --- a/vid-app-common/src/test/java/org/onap/vid/changeManagement/WorkflowRequestDetailTest.java +++ b/vid-app-common/src/test/java/org/onap/vid/changeManagement/WorkflowRequestDetailTest.java @@ -19,15 +19,17 @@ */ package org.onap.vid.changeManagement; -import org.testng.annotations.Test; - import static com.google.code.beanmatchers.BeanMatchers.hasValidGettersAndSetters; import static org.hamcrest.MatcherAssert.assertThat; +import org.onap.vid.testUtils.TestUtils; +import org.testng.annotations.Test; + public class WorkflowRequestDetailTest { @Test public void shouldHaveProperSettersAndGetters() { + TestUtils.registerCloudConfigurationValueGenerator(); assertThat(WorkflowRequestDetail.class, hasValidGettersAndSetters()); } } diff --git a/vid-app-common/src/test/java/org/onap/vid/config/DataSourceConfig.java b/vid-app-common/src/test/java/org/onap/vid/config/DataSourceConfig.java index 43adc8cf1..15f849a58 100644 --- a/vid-app-common/src/test/java/org/onap/vid/config/DataSourceConfig.java +++ b/vid-app-common/src/test/java/org/onap/vid/config/DataSourceConfig.java @@ -63,7 +63,7 @@ public class DataSourceConfig { Resource[] mappingLocations = { new ClassPathResource("WEB-INF/fusion/orm/Fusion.hbm.xml"), new ClassPathResource("WEB-INF/fusion/orm/Workflow.hbm.xml"), - new ClassPathResource("WEB-INF/fusion/orm/RNoteBookIntegration.hbm.xml") +// new ClassPathResource("WEB-INF/fusion/orm/RNoteBookIntegration.hbm.xml") }; sessionFactory.setHibernateProperties(properties); diff --git a/vid-app-common/src/test/java/org/onap/vid/config/JobAdapterConfig.java b/vid-app-common/src/test/java/org/onap/vid/config/JobAdapterConfig.java index 7462a32b2..149fad354 100644 --- a/vid-app-common/src/test/java/org/onap/vid/config/JobAdapterConfig.java +++ b/vid-app-common/src/test/java/org/onap/vid/config/JobAdapterConfig.java @@ -7,9 +7,9 @@ * 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. @@ -21,33 +21,26 @@ package org.onap.vid.config; -import org.hibernate.SessionFactory; +import org.mockito.Mockito; import org.onap.vid.job.JobAdapter; -import org.onap.vid.job.JobsBrokerService; import org.onap.vid.job.impl.JobAdapterImpl; -import org.onap.vid.job.impl.JobsBrokerServiceInDatabaseImpl; -import org.onap.vid.properties.VidProperties; -import org.onap.portalsdk.core.service.DataAccessService; -import org.onap.portalsdk.core.util.SystemProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.transaction.annotation.EnableTransactionManagement; +import org.togglz.core.manager.FeatureManager; @Configuration @EnableTransactionManagement public class JobAdapterConfig { @Bean - public JobAdapter jobAdapter() { - return new JobAdapterImpl(); + public FeatureManager featureManager() { + return Mockito.mock(FeatureManager.class); } @Bean - public JobsBrokerService jobsBrokerService(DataAccessService dataAccessService, SessionFactory sessionFactory) { - int maxOpenedInstantiationRequestsToMso = Integer.parseInt(SystemProperties.getProperty(VidProperties.MSO_MAX_OPENED_INSTANTIATION_REQUESTS)); - int pollingIntervalSeconds = Integer.parseInt(SystemProperties.getProperty(VidProperties.MSO_ASYNC_POLLING_INTERVAL_SECONDS)); - - return new JobsBrokerServiceInDatabaseImpl(dataAccessService, sessionFactory, maxOpenedInstantiationRequestsToMso, pollingIntervalSeconds); + public JobAdapter jobAdapter(FeatureManager featureManager) { + return new JobAdapterImpl(featureManager); } -} +} \ No newline at end of file diff --git a/vid-app-common/src/test/java/org/onap/vid/config/JobCommandsConfigWithMockedMso.java b/vid-app-common/src/test/java/org/onap/vid/config/JobCommandsConfigWithMockedMso.java index 1fc46eeb9..c4f788689 100644 --- a/vid-app-common/src/test/java/org/onap/vid/config/JobCommandsConfigWithMockedMso.java +++ b/vid-app-common/src/test/java/org/onap/vid/config/JobCommandsConfigWithMockedMso.java @@ -28,6 +28,7 @@ import org.onap.vid.aai.util.HttpsAuthClient; import org.onap.vid.aai.util.SSLContextProvider; import org.onap.vid.aai.util.ServletRequestHelper; import org.onap.vid.aai.util.SystemPropertyHelper; +import org.onap.vid.dal.AsyncInstantiationRepository; import org.onap.vid.job.JobAdapter; import org.onap.vid.job.JobsBrokerService; import org.onap.vid.job.command.*; @@ -52,8 +53,13 @@ public class JobCommandsConfigWithMockedMso { } @Bean - public JobsBrokerService jobsBrokerService(DataAccessService dataAccessService, SessionFactory sessionFactory) { - return new JobsBrokerServiceInDatabaseImpl(dataAccessService, sessionFactory, 200, 0); + public VersionService versionService() { + return Mockito.mock(VersionService.class); + } + + @Bean + public JobsBrokerService jobsBrokerService(DataAccessService dataAccessService, SessionFactory sessionFactory, VersionService versionService) { + return new JobsBrokerServiceInDatabaseImpl(dataAccessService, sessionFactory, 200, 0,versionService); } @Bean @@ -76,9 +82,10 @@ public class JobCommandsConfigWithMockedMso { return new HttpsAuthClient("some random path", systemPropertyHelper, sslContextProvider, featureManager); } + @Bean - public JobAdapter jobAdapter() { - return new JobAdapterImpl(); + public JobAdapter jobAdapter(FeatureManager featureManager) { + return new JobAdapterImpl(featureManager); } @Bean @@ -100,119 +107,159 @@ public class JobCommandsConfigWithMockedMso { } @Bean - public AsyncInstantiationBusinessLogic asyncInstantiationBusinessLogic(DataAccessService dataAccessService, - JobAdapter jobAdapter, - JobsBrokerService jobsBrokerService, - SessionFactory sessionFactory, - AaiClientInterface aaiClient, - FeatureManager featureManager, - CloudOwnerService cloudOwnerService) { - return new AsyncInstantiationBusinessLogicImpl(dataAccessService, jobAdapter, jobsBrokerService, sessionFactory, aaiClient, featureManager, cloudOwnerService); + public MsoRequestBuilder msoRequestHandlerService(AsyncInstantiationBusinessLogic asyncInstantiationBusinessLogic, + CloudOwnerService cloudOwnerService, + AaiClientInterface aaiClient, + FeatureManager featureManager) { + return new MsoRequestBuilder(asyncInstantiationBusinessLogic, cloudOwnerService, aaiClient, featureManager); } - @Bean - @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) - public MacroServiceInstantiationCommand serviceInstantiationCommand() { - return new MacroServiceInstantiationCommand(); + public AsyncInstantiationRepository asyncInstantiationRepository(DataAccessService dataAccessService) { + return new AsyncInstantiationRepository(dataAccessService); } @Bean - @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) - public ServiceInProgressStatusCommand inProgressStatusCommand() { - return new ServiceInProgressStatusCommand(); + public AsyncInstantiationBusinessLogic asyncInstantiationBusinessLogic(JobAdapter jobAdapter, + JobsBrokerService jobsBrokerService, + SessionFactory sessionFactory, + AaiClientInterface aaiClient, + FeatureManager featureManager, + CloudOwnerService cloudOwnerService, + AsyncInstantiationRepository asyncInstantiationRepository, + AuditService auditService) { + return new AsyncInstantiationBusinessLogicImpl(jobAdapter, jobsBrokerService, sessionFactory, aaiClient, featureManager, cloudOwnerService, asyncInstantiationRepository, auditService); } - @Bean - @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) - public ALaCarteServiceInstantiationCommand aLaCarteServiceInstantiationCommand() { - return new ALaCarteServiceInstantiationCommand(); - } @Bean @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) public ALaCarteServiceCommand aLaCarteServiceCommand( AsyncInstantiationBusinessLogic asyncInstantiationBusinessLogic, JobsBrokerService jobsBrokerService, + MsoRequestBuilder msoRequestBuilder, MsoResultHandlerService msoResultHandlerService, JobAdapter jobAdapter, InProgressStatusService inProgressStatusService, WatchChildrenJobsBL watchChildrenJobsBL, - RestMsoImplementation restMso) { - return new ALaCarteServiceCommand(inProgressStatusService, watchChildrenJobsBL, asyncInstantiationBusinessLogic, jobsBrokerService, msoResultHandlerService, jobAdapter, restMso); + RestMsoImplementation restMso, + AuditService auditService) { + return new ALaCarteServiceCommand(inProgressStatusService, watchChildrenJobsBL, asyncInstantiationBusinessLogic, jobsBrokerService, msoRequestBuilder, msoResultHandlerService, jobAdapter, restMso, auditService); } @Bean @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) - public InstanceGroupCommand instanceGroupCommand( + public MacroServiceCommand macroServiceCommand( AsyncInstantiationBusinessLogic asyncInstantiationBusinessLogic, - MsoResultHandlerService msoResultHandlerService, InProgressStatusService inProgressStatusService, + JobsBrokerService jobsBrokerService, + MsoRequestBuilder msoRequestBuilder, + MsoResultHandlerService msoResultHandlerService, + JobAdapter jobAdapter, + InProgressStatusService inProgressStatusService, WatchChildrenJobsBL watchChildrenJobsBL, - RestMsoImplementation restMso) { - return new InstanceGroupCommand(asyncInstantiationBusinessLogic, restMso, msoResultHandlerService, inProgressStatusService, watchChildrenJobsBL); + RestMsoImplementation restMso, + AuditService auditService) { + return new MacroServiceCommand(inProgressStatusService, watchChildrenJobsBL, asyncInstantiationBusinessLogic, jobsBrokerService, msoRequestBuilder, msoResultHandlerService, jobAdapter, restMso, auditService); } - @Bean - @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) - public VnfInstantiationCommand vnfInstantiationCommand() { - return new VnfInstantiationCommand(); - } @Bean @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) - public VolumeGroupInstantiationCommand volumeGroupInstantiationCommand() { - return new VolumeGroupInstantiationCommand(); - } - - @Bean - @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) - public WatchingCommandBaseModule watchingCommandBaseModule() { - return new WatchingCommandBaseModule(); + public NetworkCommand networkCommand( + AsyncInstantiationBusinessLogic asyncInstantiationBusinessLogic, + RestMsoImplementation restMso, + MsoRequestBuilder msoRequestBuilder, + MsoResultHandlerService msoResultHandlerService, + InProgressStatusService inProgressStatusService, + WatchChildrenJobsBL watchChildrenJobsBL, + JobsBrokerService jobsBrokerService, + JobAdapter jobAdapter) { + return new NetworkCommand(asyncInstantiationBusinessLogic, restMso, msoRequestBuilder, msoResultHandlerService, + inProgressStatusService, watchChildrenJobsBL, jobsBrokerService, jobAdapter); } - @Bean @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) - public VolumeGroupInProgressStatusCommand volumeGroupInProgressStatusCommand() { - return new VolumeGroupInProgressStatusCommand(); + public InstanceGroupCommand instanceGroupCommand( + AsyncInstantiationBusinessLogic asyncInstantiationBusinessLogic, + MsoRequestBuilder msoRequestBuilder, + MsoResultHandlerService msoResultHandlerService, + InProgressStatusService inProgressStatusService, + WatchChildrenJobsBL watchChildrenJobsBL, + RestMsoImplementation restMso, + JobsBrokerService jobsBrokerService, + JobAdapter jobAdapter) { + return new InstanceGroupCommand(asyncInstantiationBusinessLogic, restMso, msoRequestBuilder, msoResultHandlerService, inProgressStatusService, watchChildrenJobsBL, jobsBrokerService, jobAdapter); } @Bean @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) - public VfmoduleInstantiationCommand vfmoduleInstantiationCommand() { - return new VfmoduleInstantiationCommand(); + public InstanceGroupMemberCommand instanceGroupMemberCommand ( + AsyncInstantiationBusinessLogic asyncInstantiationBusinessLogic, + MsoRequestBuilder msoRequestBuilder, + MsoResultHandlerService msoResultHandlerService, + InProgressStatusService inProgressStatusService, + WatchChildrenJobsBL watchChildrenJobsBL, + RestMsoImplementation restMso, + JobsBrokerService jobsBrokerService, + JobAdapter jobAdapter) { + return new InstanceGroupMemberCommand(asyncInstantiationBusinessLogic, restMso, msoRequestBuilder, msoResultHandlerService, inProgressStatusService, + watchChildrenJobsBL, jobsBrokerService, jobAdapter); } - @Bean - @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) - public WatchingCommand watchingCommandCommand() { - return new WatchingCommand(); - } @Bean @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) - public ResourceInProgressStatusCommand resourceInProgressStatusCommand() { - return new ResourceInProgressStatusCommand(); + public VnfCommand VnfCommand( + AsyncInstantiationBusinessLogic asyncInstantiationBusinessLogic, + RestMsoImplementation restMso, + MsoRequestBuilder msoRequestBuilder, + MsoResultHandlerService msoResultHandlerService, + InProgressStatusService inProgressStatusService, + WatchChildrenJobsBL watchChildrenJobsBL, + JobsBrokerService jobsBrokerService, + JobAdapter jobAdapter, + FeatureManager featureManager) { + return new VnfCommand(asyncInstantiationBusinessLogic, restMso, msoRequestBuilder, msoResultHandlerService, + inProgressStatusService, watchChildrenJobsBL, jobsBrokerService ,jobAdapter, + featureManager); } @Bean @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) - public VnfInProgressStatusCommand vnfInProgressStatusCommand() { - return new VnfInProgressStatusCommand(); + public VolumeGroupCommand volumeGroupCommand( + AsyncInstantiationBusinessLogic asyncInstantiationBusinessLogic, + RestMsoImplementation restMso, + MsoRequestBuilder msoRequestBuilder, + MsoResultHandlerService msoResultHandlerService, + InProgressStatusService inProgressStatusService, + WatchChildrenJobsBL watchChildrenJobsBL, + JobsBrokerService jobsBrokerService, + JobAdapter jobAdapter) { + return new VolumeGroupCommand(asyncInstantiationBusinessLogic, restMso, msoRequestBuilder, msoResultHandlerService, + inProgressStatusService, watchChildrenJobsBL, jobsBrokerService ,jobAdapter); } @Bean @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) - public InstanceGroupInstantiationCommand instanceGroupInstantiationCommand() { - return new InstanceGroupInstantiationCommand(); + public VfmoduleCommand VfmoduleCommand( + AsyncInstantiationBusinessLogic asyncInstantiationBusinessLogic, + RestMsoImplementation restMso, + MsoRequestBuilder msoRequestBuilder, + MsoResultHandlerService msoResultHandlerService, + InProgressStatusService inProgressStatusService, + WatchChildrenJobsBL watchChildrenJobsBL, + JobsBrokerService jobsBrokerService, + JobAdapter jobAdapter) { + return new VfmoduleCommand(asyncInstantiationBusinessLogic, restMso, msoRequestBuilder, msoResultHandlerService, + inProgressStatusService, watchChildrenJobsBL, jobsBrokerService, jobAdapter); } - @Bean - public AuditService auditService(AsyncInstantiationBusinessLogic asyncInstantiationBL, RestMsoImplementation msoClient) { - return new AuditServiceImpl(asyncInstantiationBL, msoClient); + public AuditService auditService(RestMsoImplementation msoClient, AsyncInstantiationRepository asyncInstantiationRepository) { + return new AuditServiceImpl(msoClient, asyncInstantiationRepository); } @Bean - public InProgressStatusService inProgressStatusService(AsyncInstantiationBusinessLogic asyncInstantiationBL, RestMsoImplementation restMso, AuditService auditService) { - return new InProgressStatusService(asyncInstantiationBL, restMso, auditService); + public InProgressStatusService inProgressStatusService(AsyncInstantiationBusinessLogic asyncInstantiationBL, RestMsoImplementation restMso, AuditService auditService, FeatureManager featureManager) { + return new InProgressStatusService(asyncInstantiationBL, restMso, auditService, featureManager); } @Bean diff --git a/vid-app-common/src/test/java/org/onap/vid/controller/AaiControllerTest.java b/vid-app-common/src/test/java/org/onap/vid/controller/AaiControllerTest.java index a60aa7ea6..2377c8055 100644 --- a/vid-app-common/src/test/java/org/onap/vid/controller/AaiControllerTest.java +++ b/vid-app-common/src/test/java/org/onap/vid/controller/AaiControllerTest.java @@ -21,8 +21,14 @@ package org.onap.vid.controller; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.ArgumentMatchers.booleanThat; import static org.mockito.BDDMockito.given; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; @@ -34,13 +40,16 @@ import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.Lists; import com.google.common.collect.Multimap; +import java.io.IOException; import java.util.Map; import java.util.UUID; +import javax.servlet.http.HttpServletRequest; import javax.ws.rs.core.Response; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; +import org.mockito.MockitoAnnotations; import org.mockito.junit.MockitoJUnitRunner; import org.onap.vid.aai.AaiResponse; import org.onap.vid.aai.AaiResponseTranslator.PortMirroringConfigData; @@ -53,14 +62,18 @@ import org.onap.vid.aai.model.PortDetailsTranslator.PortDetails; import org.onap.vid.aai.model.PortDetailsTranslator.PortDetailsError; import org.onap.vid.aai.model.PortDetailsTranslator.PortDetailsOk; import org.onap.vid.aai.util.AAIRestInterface; +import org.onap.vid.properties.Features; +import org.onap.vid.roles.Role; import org.onap.vid.model.VersionByInvariantIdsRequest; import org.onap.vid.roles.RoleProvider; +import org.onap.vid.roles.RoleValidator; import org.onap.vid.services.AaiService; import org.onap.vid.utils.SystemPropertiesWrapper; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.togglz.core.manager.FeatureManager; @RunWith(MockitoJUnitRunner.class) public class AaiControllerTest { @@ -76,12 +89,16 @@ public class AaiControllerTest { private RoleProvider roleProvider; @Mock private SystemPropertiesWrapper systemPropertiesWrapper; + + @Mock + private FeatureManager featureManager; + private MockMvc mockMvc; private AaiController aaiController; @Before public void setUp() { - aaiController = new AaiController(aaiService, aaiRestInterface, roleProvider, systemPropertiesWrapper); + aaiController = new AaiController(aaiService, aaiRestInterface, roleProvider, systemPropertiesWrapper, featureManager); mockMvc = MockMvcBuilders.standaloneSetup(aaiController).build(); } @@ -248,5 +265,42 @@ public class AaiControllerTest { .andExpect(status().isOk()) .andExpect(content().string(expectedResponse)); } + + @Test + public void getSubscriberDetailsOmitServiceInstances_reduceDepthEnabledAndOmitQueryParam() throws IOException { + getSubscriberDetailsOmitServiceInstances("some subscriber id", + true, true, true); + } + + @Test + public void getSubscriberDetailsOmitServiceInstances_reduceDepthDisabledAndOmitQueryParam() throws IOException { + getSubscriberDetailsOmitServiceInstances("another-subscriber-id-123", + false, true, false); + } + + @Test + public void getSubscriberDetailsOmitServiceInstances_reduceDepthDisabled() throws IOException { + getSubscriberDetailsOmitServiceInstances("123-456-789-123-345-567-6", + false, false, false); + } + + @Test + public void getSubscriberDetailsOmitServiceInstances_reduceDepthEnabled() throws IOException { + getSubscriberDetailsOmitServiceInstances("0000000000000000000000000", + true, false, false); + } + + private void getSubscriberDetailsOmitServiceInstances(String subscriberId, boolean isFlag1906AaiSubDetailsReduceDepthEnabled, + boolean omitServiceInstancesQueryParam, boolean omitServiceInstancesExpectedGetSubscriberDataParam) throws IOException { + when(featureManager.isActive(Features.FLAG_1906_AAI_SUB_DETAILS_REDUCE_DEPTH)).thenReturn(isFlag1906AaiSubDetailsReduceDepthEnabled); + HttpServletRequest request = mock(HttpServletRequest.class); + when(roleProvider.getUserRoles(request)).thenReturn(ImmutableList.of(mock(Role.class), mock(Role.class))); + AaiResponse subscriberData = mock(AaiResponse.class); + when(subscriberData.getT()).thenReturn(null); + when(subscriberData.getHttpCode()).thenReturn(200); + when(aaiService.getSubscriberData(any(), any(), anyBoolean())).thenReturn(subscriberData); + aaiController.getSubscriberDetails(request, subscriberId, omitServiceInstancesQueryParam); + verify(aaiService).getSubscriberData(argThat(subscriberId::equals), any(RoleValidator.class), booleanThat(b -> omitServiceInstancesExpectedGetSubscriberDataParam == b)); + } } diff --git a/vid-app-common/src/test/java/org/onap/vid/controller/AaiServiceInstanceStandardQueryControllerTest.java b/vid-app-common/src/test/java/org/onap/vid/controller/AaiServiceInstanceStandardQueryControllerTest.java index 2a8db9650..b036b4794 100644 --- a/vid-app-common/src/test/java/org/onap/vid/controller/AaiServiceInstanceStandardQueryControllerTest.java +++ b/vid-app-common/src/test/java/org/onap/vid/controller/AaiServiceInstanceStandardQueryControllerTest.java @@ -7,9 +7,9 @@ * 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. @@ -20,18 +20,20 @@ package org.onap.vid.controller; -import org.mockito.Answers; +import com.google.common.collect.ImmutableList; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.MockitoAnnotations; -import org.onap.vid.aai.util.ServiceInstanceStandardQuery; import org.onap.vid.asdc.AsdcCatalogException; import org.onap.vid.model.Service; import org.onap.vid.model.ServiceModel; import org.onap.vid.model.VidNotions; import org.onap.vid.model.VidNotions.ModelCategory; +import org.onap.vid.model.aaiTree.AAITreeNode; import org.onap.vid.properties.Features; +import org.onap.vid.services.AAIServiceTree; import org.onap.vid.services.VidService; +import org.springframework.http.HttpMethod; import org.springframework.mock.web.MockHttpServletRequest; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeClass; @@ -56,8 +58,9 @@ public class AaiServiceInstanceStandardQueryControllerTest { @Mock private VidService sdcService; - @Mock(answer = Answers.RETURNS_MOCKS) - private ServiceInstanceStandardQuery serviceInstanceStandardQuery; + @Mock + private AAIServiceTree aaiServiceTree; + //Don't use initMocks with @BeforeMethod //because AaiServiceInstanceStandardQueryController contains final members that can not be injected twice @@ -69,7 +72,7 @@ public class AaiServiceInstanceStandardQueryControllerTest { @AfterMethod public void resetMocks() { - reset(sdcService, featureManager, serviceInstanceStandardQuery); + reset(sdcService, featureManager); } @Test @@ -80,13 +83,14 @@ public class AaiServiceInstanceStandardQueryControllerTest { // - assert that AAI was accessed when(featureManager.isActive(Features.FLAG_PRESENT_PROVIDER_NETWORKS_ASSOCIATIONS)).thenReturn(true); + when(aaiServiceTree.buildAAITree(any(), any(), any(HttpMethod.class), any(), anyBoolean())).thenReturn(ImmutableList.of(mock(AAITreeNode.class))); final UUID randomModelUuid = UUID.randomUUID(); mockServiceModel(ModelCategory.IS_5G_PROVIDER_NETWORK_MODEL, randomModelUuid); doGetNetworksToVlansByServiceInstance(randomModelUuid); - verify(serviceInstanceStandardQuery).fetchServiceInstance(any(), any(), any()); + verify(aaiServiceTree).buildAAITree(any(), any(), any(HttpMethod.class), any(), anyBoolean()); } @Test @@ -103,7 +107,7 @@ public class AaiServiceInstanceStandardQueryControllerTest { mockServiceModel(ModelCategory.OTHER, randomModelUuid); assertThat(doGetNetworksToVlansByServiceInstance(randomModelUuid).serviceNetworks, hasSize(0)); - verifyZeroInteractions(serviceInstanceStandardQuery); + verifyZeroInteractions(aaiServiceTree); } @Test @@ -123,7 +127,7 @@ public class AaiServiceInstanceStandardQueryControllerTest { Service mockedService = mock(Service.class); when(mockedModel.getService()).thenReturn(mockedService); when(mockedService.getVidNotions()).thenReturn( - new VidNotions(instantiationUI, modelCategory, VidNotions.InstantiationUI.LEGACY) + new VidNotions(instantiationUI, modelCategory, VidNotions.InstantiationUI.LEGACY, VidNotions.InstantiationType.ALaCarte) ); when(sdcService.getService(randomModelUuid.toString())).thenReturn(mockedModel); @@ -137,4 +141,4 @@ public class AaiServiceInstanceStandardQueryControllerTest { "my service type", "my instance id"); } -} +} \ No newline at end of file diff --git a/vid-app-common/src/test/java/org/onap/vid/controller/LocalWebConfig.java b/vid-app-common/src/test/java/org/onap/vid/controller/LocalWebConfig.java index 7e50c8959..701f1c62a 100644 --- a/vid-app-common/src/test/java/org/onap/vid/controller/LocalWebConfig.java +++ b/vid-app-common/src/test/java/org/onap/vid/controller/LocalWebConfig.java @@ -44,6 +44,7 @@ import org.togglz.core.manager.FeatureManager; import javax.servlet.ServletContext; import java.io.File; +import java.util.concurrent.ExecutorService; @Configuration public class LocalWebConfig { @@ -66,8 +67,8 @@ public class LocalWebConfig { @Bean public AaiService getAaiService(AaiClientInterface aaiClient, AaiOverTLSClientInterface aaiOverTLSClient, - AaiResponseTranslator aaiResponseTranslator, AAITreeNodeBuilder aaiTreeNode, AAIServiceTree aaiServiceTree) { - return new AaiServiceImpl(aaiClient, aaiOverTLSClient, aaiResponseTranslator, aaiTreeNode, aaiServiceTree); + AaiResponseTranslator aaiResponseTranslator, AAITreeNodeBuilder aaiTreeNode, AAIServiceTree aaiServiceTree, ExecutorService executorService) { + return new AaiServiceImpl(aaiClient, aaiOverTLSClient, aaiResponseTranslator, aaiTreeNode, aaiServiceTree, executorService); } @Bean diff --git a/vid-app-common/src/test/java/org/onap/vid/controller/MsoControllerNewTest.java b/vid-app-common/src/test/java/org/onap/vid/controller/MsoControllerNewTest.java index a5222dd04..43edeebe9 100644 --- a/vid-app-common/src/test/java/org/onap/vid/controller/MsoControllerNewTest.java +++ b/vid-app-common/src/test/java/org/onap/vid/controller/MsoControllerNewTest.java @@ -20,24 +20,24 @@ package org.onap.vid.controller; +import static org.mockito.Mockito.mock; + +import javax.servlet.http.HttpServletRequest; import org.junit.Test; import org.onap.vid.mso.MsoBusinessLogicImpl; import org.onap.vid.mso.MsoInterface; +import org.onap.vid.mso.rest.MsoRestClientNew; import org.onap.vid.mso.rest.RequestDetails; import org.onap.vid.mso.rest.RequestDetailsWrapper; import org.onap.vid.services.CloudOwnerServiceImpl; import org.springframework.http.ResponseEntity; -import org.togglz.core.manager.FeatureManager; - -import javax.servlet.http.HttpServletRequest; - -import static org.mockito.Mockito.mock; public class MsoControllerNewTest { private MsoController createTestSubject() { try { - return new MsoController(new MsoBusinessLogicImpl(mock(MsoInterface.class),mock(FeatureManager.class)), new CloudOwnerServiceImpl(null, null)); + return new MsoController(new MsoBusinessLogicImpl(mock(MsoInterface.class)), mock(MsoRestClientNew.class), + new CloudOwnerServiceImpl(null, null)); } catch (Exception e) { return null; } diff --git a/vid-app-common/src/test/java/org/onap/vid/controller/MsoControllerTest.java b/vid-app-common/src/test/java/org/onap/vid/controller/MsoControllerTest.java index 02ab287be..a1b45590c 100644 --- a/vid-app-common/src/test/java/org/onap/vid/controller/MsoControllerTest.java +++ b/vid-app-common/src/test/java/org/onap/vid/controller/MsoControllerTest.java @@ -46,6 +46,7 @@ import org.junit.Before; import org.junit.Test; import org.onap.vid.mso.MsoBusinessLogic; import org.onap.vid.mso.MsoResponseWrapper; +import org.onap.vid.mso.rest.MsoRestClientNew; import org.onap.vid.mso.rest.Request; import org.onap.vid.mso.rest.RequestDetails; import org.onap.vid.mso.rest.Task; @@ -66,12 +67,14 @@ public class MsoControllerTest { private MockMvc mockMvc; private MsoBusinessLogic msoBusinessLogic; private CloudOwnerService cloudService; + private MsoRestClientNew msoRestClient; @Before public void setUp() { msoBusinessLogic = mock(MsoBusinessLogic.class); cloudService = mock(CloudOwnerService.class); - MsoController msoController = new MsoController(msoBusinessLogic, cloudService); + msoRestClient = mock(MsoRestClientNew.class); + MsoController msoController = new MsoController(msoBusinessLogic, msoRestClient, cloudService); mockMvc = MockMvcBuilders.standaloneSetup(msoController).build(); } diff --git a/vid-app-common/src/test/java/org/onap/vid/controller/ToscaParserMockHelper.java b/vid-app-common/src/test/java/org/onap/vid/controller/ToscaParserMockHelper.java index 2eedee9d7..9e77e99e3 100644 --- a/vid-app-common/src/test/java/org/onap/vid/controller/ToscaParserMockHelper.java +++ b/vid-app-common/src/test/java/org/onap/vid/controller/ToscaParserMockHelper.java @@ -22,25 +22,21 @@ package org.onap.vid.controller; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.module.kotlin.KotlinModule; -import org.apache.commons.io.IOUtils; -import org.apache.log4j.LogManager; -import org.apache.log4j.Logger; -import org.onap.vid.model.NewServiceModel; - import java.io.IOException; import java.io.InputStream; import java.nio.charset.StandardCharsets; +import org.apache.commons.io.IOUtils; +import org.apache.log4j.LogManager; +import org.apache.log4j.Logger; +import org.onap.vid.model.ServiceModel; -/** - * Created by moriya1 on 04/07/2017. - */ public class ToscaParserMockHelper { private static final Logger logger = LogManager.getLogger(ToscaParserMockHelper.class); private static final ObjectMapper om = new ObjectMapper(); private final String uuid; private final String filePath; - private final NewServiceModel newServiceModel; + private final ServiceModel serviceModel; public ToscaParserMockHelper(String uuid, String filePath) throws IOException { this.uuid = uuid; @@ -50,7 +46,7 @@ public class ToscaParserMockHelper { logger.info(jsonFile); String expectedJsonAsString = IOUtils.toString(jsonFile, StandardCharsets.UTF_8.name()); om.registerModule(new KotlinModule()); - this.newServiceModel = om.readValue(expectedJsonAsString, NewServiceModel.class); + this.serviceModel = om.readValue(expectedJsonAsString, ServiceModel.class); } public String getUuid() { @@ -61,7 +57,7 @@ public class ToscaParserMockHelper { return filePath; } - public NewServiceModel getNewServiceModel() { - return newServiceModel; + public ServiceModel getServiceModel() { + return serviceModel; } } diff --git a/vid-app-common/src/test/java/org/onap/vid/controller/VidControllerTest.java b/vid-app-common/src/test/java/org/onap/vid/controller/VidControllerTest.java index 39d3cddc7..484f4a034 100644 --- a/vid-app-common/src/test/java/org/onap/vid/controller/VidControllerTest.java +++ b/vid-app-common/src/test/java/org/onap/vid/controller/VidControllerTest.java @@ -178,7 +178,7 @@ public class VidControllerTest { private ServiceModel createServiceModel(int i) { ServiceModel model = new ServiceModel(); - model.setCollectionResource(ImmutableMap.of("resKey" + i, new CR())); + model.setCollectionResources(ImmutableMap.of("resKey" + i, new CR())); model.setNetworks(ImmutableMap.of("network" + i, new Network())); model.setPnfs(ImmutableMap.of("pnf" + i, new Node())); model.setServiceProxies(ImmutableMap.of("servProxy" + i, new ServiceProxy())); diff --git a/vid-app-common/src/test/java/org/onap/vid/dal/AsyncInstantiationRepositoryTest.java b/vid-app-common/src/test/java/org/onap/vid/dal/AsyncInstantiationRepositoryTest.java new file mode 100644 index 000000000..be5a44e82 --- /dev/null +++ b/vid-app-common/src/test/java/org/onap/vid/dal/AsyncInstantiationRepositoryTest.java @@ -0,0 +1,103 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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.vid.dal; + +import static net.javacrumbs.jsonunit.JsonMatchers.jsonEquals; +import static net.javacrumbs.jsonunit.core.Option.IGNORING_ARRAY_ORDER; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.collection.IsCollectionWithSize.hasSize; +import static org.hamcrest.core.IsEqual.equalTo; + +import com.google.common.collect.ImmutableList; +import java.time.ZonedDateTime; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.stream.Collectors; +import javax.inject.Inject; +import org.onap.portalsdk.core.service.DataAccessService; +import org.onap.portalsdk.core.util.SystemProperties; +import org.onap.vid.config.DataSourceConfig; +import org.onap.vid.config.MockedAaiClientAndFeatureManagerConfig; +import org.onap.vid.job.Job; +import org.onap.vid.model.ResourceInfo; +import org.onap.vid.model.serviceInstantiation.ServiceInstantiation; +import org.onap.vid.mso.rest.AsyncRequestStatus; +import org.onap.vid.mso.rest.RequestStatus; +import org.onap.vid.services.AsyncInstantiationBaseTest; +import org.onap.vid.utils.TimeUtils; +import org.springframework.test.context.ContextConfiguration; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +@ContextConfiguration(classes = {DataSourceConfig.class, SystemProperties.class, MockedAaiClientAndFeatureManagerConfig.class}) +public class AsyncInstantiationRepositoryTest extends AsyncInstantiationBaseTest { + + @Inject + private DataAccessService dataAccessService; + + @BeforeClass + void initServicesInfoService() { + createInstanceParamsMaps(); + } + + @Test + public void whenSaveNewRequest_thenRequestIsRetrieved() { + AsyncInstantiationRepository underTest = new AsyncInstantiationRepository(dataAccessService); + ServiceInstantiation serviceInstantiation = generateALaCarteWithVnfsServiceInstantiationPayload(); + UUID jobUuid = UUID.randomUUID(); + underTest.addJobRequest(jobUuid, serviceInstantiation); + ServiceInstantiation stored = underTest.getJobRequest(jobUuid); + assertThat(stored, jsonEquals(serviceInstantiation).when(IGNORING_ARRAY_ORDER)); + } + + private AsyncRequestStatus createAsyncRequestStatus(String message, String requestState){ + RequestStatus requestStatus = new RequestStatus(requestState, message, TimeUtils.zonedDateTimeToString(ZonedDateTime.now())); + AsyncRequestStatus.Request request = new AsyncRequestStatus.Request(requestStatus); + return new AsyncRequestStatus(request); + } + + @Test + public void getResourceInfoByRootJobId_returnsMapOfjobIdResources(){ + AsyncInstantiationRepository underTest = new AsyncInstantiationRepository(dataAccessService); + UUID jobId1= UUID.randomUUID(); + UUID jobId2= UUID.randomUUID(); + AsyncRequestStatus errorMessage= createAsyncRequestStatus("MSO failed resource", "FAILED"); + List requestInfoList= ImmutableList.of( + new ResourceInfo("aaaaaa",jobId1, "64f3123a-f9a8-4591-b481-d662134bcb52", Job.JobStatus.COMPLETED, null), + new ResourceInfo("bbbbbb",jobId1, "65f3123a-f9a8-4591-b481-kodj9ig87gdu", Job.JobStatus.COMPLETED_WITH_ERRORS, null), + new ResourceInfo("dddddd",jobId1, null, Job.JobStatus.FAILED, null), + new ResourceInfo("cccccc",jobId1, null, Job.JobStatus.FAILED, errorMessage), + new ResourceInfo("eeeeee",jobId2, null, Job.JobStatus.FAILED, null), + new ResourceInfo("ffffff",jobId2, "66f3123a-f9a8-4591-b481-ghfgh6767567", Job.JobStatus.COMPLETED, null) + ); + for(ResourceInfo info: requestInfoList){ + underTest.saveResourceInfo(info); + } + Map storedByTrackId = underTest.getResourceInfoByRootJobId(jobId1); + assertThat(storedByTrackId.values(), hasSize(4)); + assertThat(storedByTrackId.get("aaaaaa").getInstanceId(), equalTo("64f3123a-f9a8-4591-b481-d662134bcb52")); + assertThat(storedByTrackId.get("cccccc").getErrorMessage().request.requestStatus.getStatusMessage(), equalTo("MSO failed resource")); + assertThat(storedByTrackId.get("cccccc").getErrorMessage().request.requestStatus.getRequestState(), equalTo("FAILED")); + assertThat(storedByTrackId.get("dddddd").getErrorMessage(), equalTo(null)); + assertThat(storedByTrackId.values(), jsonEquals(requestInfoList.stream().filter(i-> i.getRootJobId().equals(jobId1)).collect(Collectors.toList())).when(IGNORING_ARRAY_ORDER)); + } +} diff --git a/vid-app-common/src/test/java/org/onap/vid/job/command/CommandUtilsTest.java b/vid-app-common/src/test/java/org/onap/vid/job/command/CommandUtilsTest.java index da300bf3e..ee43d1f72 100644 --- a/vid-app-common/src/test/java/org/onap/vid/job/command/CommandUtilsTest.java +++ b/vid-app-common/src/test/java/org/onap/vid/job/command/CommandUtilsTest.java @@ -7,9 +7,9 @@ * 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. diff --git a/vid-app-common/src/test/java/org/onap/vid/job/command/InProgressStatusServiceTest.java b/vid-app-common/src/test/java/org/onap/vid/job/command/InProgressStatusServiceTest.java index c8772ee76..125d2ed4c 100644 --- a/vid-app-common/src/test/java/org/onap/vid/job/command/InProgressStatusServiceTest.java +++ b/vid-app-common/src/test/java/org/onap/vid/job/command/InProgressStatusServiceTest.java @@ -7,9 +7,9 @@ * 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. @@ -20,8 +20,10 @@ package org.onap.vid.job.command; +import org.jetbrains.annotations.NotNull; import org.mockito.InjectMocks; import org.mockito.Mock; +import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import org.onap.vid.job.Job; import org.onap.vid.job.impl.JobSharedData; @@ -29,11 +31,16 @@ import org.onap.vid.model.serviceInstantiation.ServiceInstantiation; import org.onap.vid.mso.RestMsoImplementation; import org.onap.vid.mso.RestObject; import org.onap.vid.mso.rest.AsyncRequestStatus; -import org.onap.vid.services.AsyncInstantiationBaseTest; +import org.onap.vid.properties.Features; import org.onap.vid.services.AsyncInstantiationBusinessLogic; +import org.onap.vid.services.AuditService; +import org.onap.vid.services.AsyncInstantiationBaseTest; +import org.onap.vid.testUtils.TestUtils; import org.testng.annotations.BeforeClass; +import org.testng.annotations.BeforeMethod; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; +import org.togglz.core.manager.FeatureManager; import java.util.UUID; import java.util.stream.Stream; @@ -51,6 +58,12 @@ public class InProgressStatusServiceTest { @Mock private AsyncInstantiationBusinessLogic asyncInstantiationBL; + @Mock + private AuditService auditService; + + @Mock + private FeatureManager featureManager; + @InjectMocks private InProgressStatusService inProgressStatusService; @@ -59,10 +72,16 @@ public class InProgressStatusServiceTest { MockitoAnnotations.initMocks(this); } + @BeforeMethod + public void resetMocks() { + Mockito.reset(restMso); + Mockito.reset(asyncInstantiationBL); + } + @DataProvider public static Object[][] jobStatuses() { return Stream.of(Job.JobStatus.values()) - .map(student -> new Object[] { student }) + .map(status -> new Object[] { status }) .toArray(Object[][]::new); } @@ -71,16 +90,14 @@ public class InProgressStatusServiceTest { UUID jobUuid = UUID.randomUUID(); String userId = "mockedUserID"; + String testApi = "mockedTestApi"; String requestId = UUID.randomUUID().toString(); ServiceInstantiation serviceInstantiation = mock(ServiceInstantiation.class); when(asyncInstantiationBL.getOrchestrationRequestsPath()).thenReturn(""); - RestObject msoResponse = mock(RestObject.class); AsyncRequestStatus requestStatus = AsyncInstantiationBaseTest.asyncRequestStatusResponse(""); - - when(msoResponse.getStatusCode()).thenReturn(200); - when(msoResponse.get()).thenReturn(requestStatus); + RestObject msoResponse = createMockedAsyncRequestStatus(requestStatus, 200); when(restMso.GetForObject(contains(requestId), eq(AsyncRequestStatus.class))).thenReturn(msoResponse); when(asyncInstantiationBL.calcStatus(any())).thenReturn(expectedJobStatus); @@ -88,16 +105,60 @@ public class InProgressStatusServiceTest { ExpiryChecker expiryChecker = mock(ExpiryChecker.class); when(expiryChecker.isExpired(any())).thenReturn(false); - JobSharedData sharedData = new JobSharedData(jobUuid, userId, serviceInstantiation); + JobSharedData sharedData = new JobSharedData(jobUuid, userId, serviceInstantiation, testApi); Job.JobStatus actualJobStatus = inProgressStatusService.call(expiryChecker, sharedData, requestId); assertEquals(expectedJobStatus, actualJobStatus); - verify(asyncInstantiationBL).auditMsoStatus(eq(jobUuid), same(requestStatus.request)); - + verify(auditService).auditMsoStatus(eq(jobUuid), same(requestStatus.request)); + verify(asyncInstantiationBL).updateResourceInfo(eq(sharedData), eq(expectedJobStatus), eq(requestStatus)); //verify we don't update service info during this case, which shall stay in_progress verify(asyncInstantiationBL, never()).updateServiceInfo(any(), any()); + } + + @NotNull + protected RestObject createMockedAsyncRequestStatus(AsyncRequestStatus requestStatus, int statusCode) { + RestObject msoResponse = mock(RestObject.class); + when(msoResponse.getStatusCode()).thenReturn(statusCode); + when(msoResponse.get()).thenReturn(requestStatus); + return msoResponse; + } + + @Test(dataProvider = "trueAndFalse", dataProviderClass = TestUtils.class) + public void whenGetAsyncRequestStatus_thenRightResponseReturned(boolean isResumeFlagActive) { + String requestId = "abcRequest"; + String baseMso = "/fakeBase/v15"; + + when(asyncInstantiationBL.getOrchestrationRequestsPath()).thenReturn(baseMso); + when(featureManager.isActive(Features.FLAG_1908_RESUME_MACRO_SERVICE)).thenReturn(isResumeFlagActive); + + AsyncRequestStatus requestStatus = AsyncInstantiationBaseTest.asyncRequestStatusResponse(""); + RestObject mockedResponse = createMockedAsyncRequestStatus(requestStatus, 399); + String path = baseMso + "/" + requestId + (isResumeFlagActive ? "?format=detail" : ""); + when(restMso.GetForObject(eq(path), eq(AsyncRequestStatus.class))).thenReturn(mockedResponse); + + assertEquals(mockedResponse, inProgressStatusService.getAsyncRequestStatus(requestId)); + } + + @DataProvider + public static Object[][] getAsyncReturnErrorDataProvider() { + return new Object[][]{ + {AsyncInstantiationBaseTest.asyncRequestStatusResponse("xyz"), 400}, + {AsyncInstantiationBaseTest.asyncRequestStatusResponse("xyz"), 401}, + {AsyncInstantiationBaseTest.asyncRequestStatusResponse("xyz"), 500}, + {null, 200}, + }; + } + + @Test(dataProvider = "getAsyncReturnErrorDataProvider", expectedExceptions = InProgressStatusService.BadResponseFromMso.class) + public void whenGetAsyncReturnError_thenExceptionIsThrown(AsyncRequestStatus requestStatus, int statusCode) { + String requestId = "abcRequest"; + String baseMso = "/fakeBase/v15"; + when(asyncInstantiationBL.getOrchestrationRequestsPath()).thenReturn(baseMso); + RestObject mockedResponse = createMockedAsyncRequestStatus(requestStatus, statusCode); + when(restMso.GetForObject(eq(baseMso + "/" + requestId), eq(AsyncRequestStatus.class))).thenReturn(mockedResponse); + inProgressStatusService.getAsyncRequestStatus(requestId); } } diff --git a/vid-app-common/src/test/java/org/onap/vid/job/command/InstanceGroupCommandTest.java b/vid-app-common/src/test/java/org/onap/vid/job/command/InstanceGroupCommandTest.java index b4a5c64f5..c68c5f754 100644 --- a/vid-app-common/src/test/java/org/onap/vid/job/command/InstanceGroupCommandTest.java +++ b/vid-app-common/src/test/java/org/onap/vid/job/command/InstanceGroupCommandTest.java @@ -7,9 +7,9 @@ * 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. @@ -20,29 +20,35 @@ package org.onap.vid.job.command; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.eq; -import static org.mockito.Mockito.only; -import static org.mockito.Mockito.same; -import static org.mockito.Mockito.verify; - import com.google.common.collect.ImmutableMap; -import java.util.Optional; +import org.apache.commons.beanutils.BeanUtils; import org.mockito.Answers; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import org.onap.vid.job.JobAdapter; +import org.onap.vid.job.JobsBrokerService; import org.onap.vid.job.impl.JobSharedData; +import org.onap.vid.model.Action; import org.onap.vid.model.RequestReferencesContainer; import org.onap.vid.model.serviceInstantiation.InstanceGroup; import org.onap.vid.mso.RestMsoImplementation; import org.onap.vid.mso.model.ModelInfo; import org.onap.vid.services.AsyncInstantiationBusinessLogic; -import org.onap.vid.testUtils.TestUtils; import org.springframework.http.HttpMethod; import org.testng.annotations.BeforeMethod; +import org.testng.annotations.DataProvider; import org.testng.annotations.Test; +import java.util.Optional; +import java.util.Set; + +import static java.util.function.Function.identity; +import static java.util.stream.Collectors.toMap; +import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; + public class InstanceGroupCommandTest { @Mock(answer = Answers.RETURNS_MOCKS) @@ -53,11 +59,20 @@ public class InstanceGroupCommandTest { @Mock(answer = Answers.RETURNS_MOCKS) MsoResultHandlerService msoResultHandlerService; + @Mock(answer = Answers.RETURNS_MOCKS) + MsoRequestBuilder msoRequestBuilder; + @Mock WatchChildrenJobsBL watchChildrenJobsBL; @Mock(answer = Answers.RETURNS_MOCKS) AsyncInstantiationBusinessLogic asyncInstantiationBL; + @Mock(answer = Answers.RETURNS_MOCKS) + JobsBrokerService jobsBrokerService; + + @Mock(answer = Answers.RETURNS_MOCKS) + JobAdapter jobAdapter; + @Mock InProgressStatusService inProgressStatusService; @InjectMocks @@ -68,29 +83,41 @@ public class InstanceGroupCommandTest { command = null; MockitoAnnotations.initMocks(this); } - - @Test - public void createMyself_callsMso() { - final ModelInfo serviceModelInfo = setStrings(new ModelInfo()); + @DataProvider + public static Object[][] testApis() { + return new Object[][]{ + {"VNF_API"}, {null}}; + } + @Test(dataProvider = "testApis") + public void createMyself_callsMso(String testApi) { + final ModelInfo serviceModelInfo = setRandomStrings(new ModelInfo()); final String serviceInstanceId = "service-instance-id"; final String userId = "ff3223"; - command.init(new JobSharedData( - null, userId, instanceGroupRequest - ), ImmutableMap.of( + when(instanceGroupRequest.getAction()).thenReturn(Action.Delete); + + JobSharedData sharedData = new JobSharedData( + null, userId, instanceGroupRequest, testApi); + command.init(sharedData, ImmutableMap.of( "resourceModelInfos", ImmutableMap.of("SERVICE_MODEL_INFO", serviceModelInfo), "resourceInstancesIds", ImmutableMap.of("SERVICE_INSTANCE_ID", serviceInstanceId) )); command.createMyself(); - verify(asyncInstantiationBL).generateInstanceGroupInstantiationRequest( - same(instanceGroupRequest), eq(serviceModelInfo), eq(serviceInstanceId), eq(userId)); + verify(msoRequestBuilder).generateInstanceGroupInstantiationRequest( + same(instanceGroupRequest), eq(serviceModelInfo), eq(serviceInstanceId), eq(userId), eq(testApi)); verify(restMso, only()).restCall(eq(HttpMethod.POST), eq(RequestReferencesContainer.class), any(), any(), eq(Optional.empty())); - } - private ModelInfo setStrings(ModelInfo object) { - return TestUtils.setStringsInStringProperties(object); + private ModelInfo setRandomStrings(ModelInfo object) { + try { + Set fields = BeanUtils.describe(object).keySet(); + BeanUtils.populate(object, + fields.stream().collect(toMap(identity(), s -> randomAlphanumeric(4)))); + return object; + } catch (Exception e) { + throw new RuntimeException(e); + } } } diff --git a/vid-app-common/src/test/java/org/onap/vid/job/command/JobCommandFactoryTest.java b/vid-app-common/src/test/java/org/onap/vid/job/command/JobCommandFactoryTest.java index d7389ad0a..72336e5a9 100644 --- a/vid-app-common/src/test/java/org/onap/vid/job/command/JobCommandFactoryTest.java +++ b/vid-app-common/src/test/java/org/onap/vid/job/command/JobCommandFactoryTest.java @@ -7,9 +7,9 @@ * 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. @@ -105,7 +105,7 @@ public class JobCommandFactoryTest { final UUID uuid = UUID.randomUUID(); final Map data = ImmutableMap.of("foo", "bar"); - final JobSharedData sharedData = new JobSharedData(uuid, "userid", new MockedRequest(1,"a")); + final JobSharedData sharedData = new JobSharedData(uuid, "userid", new MockedRequest(1,"a"), "testApi"); when(job.getType()).thenReturn(jobType); when(job.getUuid()).thenReturn(uuid); @@ -119,4 +119,4 @@ public class JobCommandFactoryTest { assertThat(command, equalTo(mockCommand)); } -} +} \ No newline at end of file diff --git a/vid-app-common/src/test/java/org/onap/vid/job/command/MacroServiceCommandTest.java b/vid-app-common/src/test/java/org/onap/vid/job/command/MacroServiceCommandTest.java new file mode 100644 index 000000000..e4771611c --- /dev/null +++ b/vid-app-common/src/test/java/org/onap/vid/job/command/MacroServiceCommandTest.java @@ -0,0 +1,136 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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.vid.job.command; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.onap.vid.model.VidNotions.ModelCategory.INFRASTRUCTURE_VPN; +import static org.onap.vid.model.VidNotions.ModelCategory.IS_5G_FABRIC_CONFIGURATION_MODEL; +import static org.onap.vid.model.VidNotions.ModelCategory.IS_5G_PROVIDER_NETWORK_MODEL; +import static org.onap.vid.model.VidNotions.ModelCategory.OTHER; +import static org.onap.vid.model.VidNotions.ModelCategory.SERVICE_WITH_COLLECTION_RESOURCE; +import static org.onap.vid.model.VidNotions.ModelCategory.Transport; +import static org.testng.AssertJUnit.assertEquals; + +import com.google.common.collect.ImmutableList; +import java.util.Collections; +import java.util.List; +import java.util.UUID; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.onap.vid.job.Job; +import org.onap.vid.job.JobAdapter; +import org.onap.vid.job.JobsBrokerService; +import org.onap.vid.job.impl.JobSharedData; +import org.onap.vid.model.Action; +import org.onap.vid.model.VidNotions; +import org.onap.vid.model.serviceInstantiation.BaseResource; +import org.onap.vid.model.serviceInstantiation.ServiceInstantiation; +import org.onap.vid.mso.RestMsoImplementation; +import org.onap.vid.mso.rest.AsyncRequestStatus; +import org.onap.vid.services.AsyncInstantiationBusinessLogic; +import org.onap.vid.services.AuditService; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +public class MacroServiceCommandTest { + + @Mock + private InProgressStatusService inProgressStatusService; + + @Mock + private WatchChildrenJobsBL watchChildrenJobsB; + + @Mock + private AsyncInstantiationBusinessLogic asyncInstantiationBL; + + @Mock + private JobsBrokerService jobsBrokerService; + + @Mock + private MsoRequestBuilder msoRequestBuilder; + + @Mock + private MsoResultHandlerService msoResultHandlerService; + + @Mock + private JobAdapter jobAdapter; + + @Mock + private RestMsoImplementation restMso; + + @Mock + private AuditService auditService; + + @InjectMocks + private MacroServiceCommand macroServiceCommand; + + @DataProvider + public static Object[][] modelCategoryPre1806DataProvider() { + return new Object[][]{ + {IS_5G_PROVIDER_NETWORK_MODEL, false}, + {IS_5G_FABRIC_CONFIGURATION_MODEL, false}, + {Transport, true}, + {SERVICE_WITH_COLLECTION_RESOURCE, true}, + {INFRASTRUCTURE_VPN, true}, + {OTHER, false}, + }; + } + + @BeforeClass + public void initMocks() { + MockitoAnnotations.initMocks(this); + } + + @Test(dataProvider = "modelCategoryPre1806DataProvider") + public void testShouldUsePre1806Request(VidNotions.ModelCategory modelCategory, boolean expectedResult) { + ServiceInstantiation serviceInstantiation = mock(ServiceInstantiation.class); + VidNotions vidNotions = mock(VidNotions.class); + when(serviceInstantiation.getVidNotions()).thenReturn(vidNotions); + when(vidNotions.getModelCategory()).thenReturn(modelCategory); + assertEquals(macroServiceCommand.shouldUsePre1806Request(serviceInstantiation), expectedResult); + } + + @DataProvider + public static Object[][] MsoFilteredRequestsDataProvider() { + return new Object[][]{ + {Collections.EMPTY_LIST}, + {ImmutableList.of(new AsyncRequestStatus.Request())} + }; + } + + @Test(dataProvider = "MsoFilteredRequestsDataProvider") + public void givenResumeAction_whenCantRetrieveRequestIdFromMSO_thenJobIsFailed(List requests) { + String instanceId = UUID.randomUUID().toString(); + BaseResource baseResource = mock(BaseResource.class); + when(baseResource.getInstanceId()).thenReturn(instanceId); + when(baseResource.getAction()).thenReturn(Action.Resume); + macroServiceCommand.init(new JobSharedData(null, null, baseResource, null)); + when(auditService.retrieveRequestsFromMsoByServiceIdAndRequestTypeAndScope(eq(instanceId), any(), any())) + .thenReturn(requests); + assertEquals(macroServiceCommand.resumeMyself(), Job.JobStatus.FAILED); + } + +} diff --git a/vid-app-common/src/test/java/org/onap/vid/job/command/MsoResultHandlerServiceTest.java b/vid-app-common/src/test/java/org/onap/vid/job/command/MsoResultHandlerServiceTest.java new file mode 100644 index 000000000..5f958016b --- /dev/null +++ b/vid-app-common/src/test/java/org/onap/vid/job/command/MsoResultHandlerServiceTest.java @@ -0,0 +1,95 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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.vid.job.command; + +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.verify; +import static org.onap.vid.job.impl.AsyncInstantiationIntegrationTest.createResponse; +import static org.testng.AssertJUnit.assertEquals; + +import java.util.UUID; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.onap.vid.job.Job; +import org.onap.vid.job.impl.JobSharedData; +import org.onap.vid.model.RequestReferencesContainer; +import org.onap.vid.mso.RestObject; +import org.onap.vid.services.AsyncInstantiationBusinessLogic; +import org.onap.vid.services.AuditService; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +public class MsoResultHandlerServiceTest { + + @Mock + private AsyncInstantiationBusinessLogic asyncInstantiationBusinessLogic; + + @Mock + private AuditService auditService; + + @InjectMocks + private MsoResultHandlerService underTest; + + @BeforeClass + public void initMocks() { + MockitoAnnotations.initMocks(this); + } + + @DataProvider + public static Object[][] okStatusCodes() { + return new Object[][]{ + {200}, {202} , {300}, {399} + }; + } + + @Test(dataProvider = "okStatusCodes") + public void whenOkResponseFromMso_getResultsWithIdsAndCompleteWithNoAction(int statusCode) { + String instanceId = UUID.randomUUID().toString(); + String requestId = UUID.randomUUID().toString(); + JobSharedData sharedData = new JobSharedData(); + RestObject msoResponse = createResponse(statusCode, instanceId, requestId); + MsoResult expectedResult = new MsoResult(Job.JobStatus.COMPLETED_WITH_NO_ACTION, new MsoResourceIds(requestId, instanceId)); + MsoResult actualMsoResult = underTest.handleResponse(sharedData, msoResponse, "test desc"); + assertEquals(expectedResult, actualMsoResult); + verify(asyncInstantiationBusinessLogic).addResourceInfo(eq(sharedData), eq(Job.JobStatus.IN_PROGRESS), eq(instanceId)); + } + + @DataProvider + public static Object[][] notOkStatusCodes() { + return new Object[][]{ + {199}, {400} , {404}, {500} + }; + } + + @Test(dataProvider = "notOkStatusCodes") + public void whenNotOkFromMso_getResultsWithFailedStatus(int statusCode) { + Mockito.reset(asyncInstantiationBusinessLogic); + JobSharedData sharedData = new JobSharedData(); + RestObject msoResponse = createResponse(statusCode); + MsoResult expectedResult = new MsoResult(Job.JobStatus.FAILED); + MsoResult actualMsoResult = underTest.handleResponse(new JobSharedData(), msoResponse, "test desc"); + assertEquals(expectedResult, actualMsoResult); + verify(asyncInstantiationBusinessLogic).addFailedResourceInfo(eq(sharedData), eq(msoResponse)); + } +} diff --git a/vid-app-common/src/test/java/org/onap/vid/job/command/ResourceCommandTest.java b/vid-app-common/src/test/java/org/onap/vid/job/command/ResourceCommandTest.java index 9f252c5e8..2780e1515 100644 --- a/vid-app-common/src/test/java/org/onap/vid/job/command/ResourceCommandTest.java +++ b/vid-app-common/src/test/java/org/onap/vid/job/command/ResourceCommandTest.java @@ -7,9 +7,9 @@ * 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. @@ -20,29 +20,38 @@ package org.onap.vid.job.command; +import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import org.jetbrains.annotations.NotNull; +import org.onap.vid.exceptions.AbortingException; import org.onap.vid.exceptions.GenericUncheckedException; +import org.onap.vid.exceptions.TryAgainException; import org.onap.vid.job.Job; import org.onap.vid.job.JobAdapter; +import org.onap.vid.job.JobsBrokerService; import org.onap.vid.job.NextCommand; import org.onap.vid.job.impl.JobSharedData; import org.onap.vid.model.Action; -import org.onap.vid.model.serviceInstantiation.BaseResource; +import org.onap.vid.model.serviceInstantiation.*; import org.onap.vid.mso.RestMsoImplementation; +import org.onap.vid.mso.model.ModelInfo; import org.springframework.http.HttpMethod; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import javax.ws.rs.ProcessingException; -import java.util.Collections; -import java.util.Optional; +import java.util.*; +import java.util.stream.Collectors; import java.util.stream.Stream; +import static java.util.Collections.emptyList; +import static org.mockito.AdditionalAnswers.returnsFirstArg; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.*; import static org.onap.vid.job.command.ResourceCommandKt.ACTION_PHASE; import static org.onap.vid.job.command.ResourceCommandKt.INTERNAL_STATE; +import static org.onap.vid.job.command.ResourceCommandTest.FakeResourceCreator.*; +import static org.onap.vid.model.Action.*; import static org.onap.vid.utils.Logging.getMethodCallerName; import static org.testng.Assert.assertNull; import static org.testng.Assert.assertTrue; @@ -54,18 +63,32 @@ public class ResourceCommandTest { public static class MockCommand extends ResourceCommand { public MockCommand(InternalState mockState, Action mockPhase, Job.JobStatus mockedJobStatus) { - super(mock(RestMsoImplementation.class, RETURNS_MOCKS), mock(InProgressStatusService.class), mock(MsoResultHandlerService.class, RETURNS_MOCKS), mock(WatchChildrenJobsBL.class)); + this(mockState, mockPhase, mockedJobStatus, false); + } + public MockCommand(InternalState mockState, Action mockPhase, Job.JobStatus mockedJobStatus, boolean lateInit) { + super( + mock(RestMsoImplementation.class, RETURNS_MOCKS), + mock(InProgressStatusService.class), + mock(MsoResultHandlerService.class, RETURNS_MOCKS), + mock(WatchChildrenJobsBL.class), + mock(JobsBrokerService.class, RETURNS_MOCKS), + mock(JobAdapter.class, RETURNS_MOCKS)); this.mockedJobStatus = mockedJobStatus; this.mockState = mockState; this.mockPhase = mockPhase; - if (mockState==InternalState.INITIAL) { - init(mock(JobSharedData.class), Collections.emptyMap()); + if (!lateInit) { + init(); } - else { + when(this.getWatchChildrenJobsBL().cumulateJobStatus(any(), any())).thenReturn(mockedJobStatus); + } + + protected void init() { + if (mockState == InternalState.INITIAL) { + init(mock(JobSharedData.class), Collections.emptyMap()); + } else { init(mock(JobSharedData.class), ImmutableMap.of(INTERNAL_STATE, mockState.name(), ACTION_PHASE, mockPhase.name())); } - when(this.getWatchChildrenJobsBL().cumulateJobStatus(any(), any())).thenReturn(mockedJobStatus); } private final Job.JobStatus mockedJobStatus; @@ -76,7 +99,7 @@ public class ResourceCommandTest { @NotNull @Override public Job.JobStatus createChildren() { - if (mockState == InternalState.CREATING_CHILDREN || (mockState == InternalState.INITIAL && mockPhase== Action.Delete)) + if (mockState == InternalState.CREATING_CHILDREN || (mockState == InternalState.INITIAL && mockPhase== Delete)) return mockedJobStatus; throw (new RuntimeException("Not expected to call "+getMethodCallerName())); } @@ -95,7 +118,7 @@ public class ResourceCommandTest { @NotNull @Override - public MsoRestCallPlan planCreateMyselfRestCall(@NotNull CommandParentData commandParentData, @NotNull JobAdapter.AsyncJobRequest request, @NotNull String userId) { + public MsoRestCallPlan planCreateMyselfRestCall(@NotNull CommandParentData commandParentData, @NotNull JobAdapter.AsyncJobRequest request, @NotNull String userId, String testApi) { return mockedPlanOrThrow(InternalState.CREATE_MYSELF); } @@ -109,16 +132,19 @@ public class ResourceCommandTest { public static class MockCommandTestingStateMachine extends MockCommand { private final JobSharedData sharedData; + private final boolean isDescendantHasAction; public MockCommandTestingStateMachine(InternalState mockState, Action mockPhase, Job.JobStatus mockedJobStatus, boolean mockedNeedToDeleteMySelf) { - this(mockState, mockPhase, mockedJobStatus, mockedNeedToDeleteMySelf, false); + this(mockState, mockPhase, mockedJobStatus, mockedNeedToDeleteMySelf, false, true); } - public MockCommandTestingStateMachine(InternalState mockState, Action mockPhase, Job.JobStatus mockedJobStatus, boolean mockedNeedToDeleteMySelf, boolean isService) { - super(mockState, mockPhase, mockedJobStatus); + public MockCommandTestingStateMachine(InternalState mockState, Action mockPhase, Job.JobStatus mockedJobStatus, boolean mockedNeedToDeleteMySelf, boolean isService, boolean isDescendantHasAction) { + super(mockState, mockPhase, mockedJobStatus, true); this.mockedNeedToDeleteMySelf = mockedNeedToDeleteMySelf; this.isService = isService; this.sharedData = mock(JobSharedData.class, RETURNS_MOCKS); + this.isDescendantHasAction = isDescendantHasAction; + init(); } protected final boolean mockedNeedToDeleteMySelf; @@ -150,6 +176,11 @@ public class ResourceCommandTest { public JobSharedData getSharedData() { return sharedData; } + + @Override + protected boolean isDescendantHasAction(@NotNull Action phase) { + return isDescendantHasAction; + } } @DataProvider @@ -171,28 +202,28 @@ public class ResourceCommandTest { InternalState internalState, Job.JobStatus jobStatus, InternalState expectedState) { //there is no meaning to the constructor inputs here - MockCommandTestingStateMachine underTest = new MockCommandTestingStateMachine(InternalState.TERMINAL, Action.Delete, Job.JobStatus.FAILED, true); + MockCommandTestingStateMachine underTest = new MockCommandTestingStateMachine(InternalState.TERMINAL, Delete, Job.JobStatus.FAILED, true); assertEquals(expectedState, underTest.calcNextStateDeletePhase(jobStatus, internalState)); } @Test public void whenNoNeedToDeleteMyself_internalStateMovesFromWatchingToTerminal() { - MockCommandTestingStateMachine underTest = new MockCommandTestingStateMachine(InternalState.WATCHING, Action.Delete, Job.JobStatus.COMPLETED, false); + MockCommandTestingStateMachine underTest = new MockCommandTestingStateMachine(InternalState.WATCHING, Delete, Job.JobStatus.COMPLETED, false); assertEquals(InternalState.TERMINAL, underTest.calcNextStateDeletePhase(Job.JobStatus.COMPLETED, InternalState.WATCHING)); } @DataProvider public static Object[][] testShallStopJobDataProvider() { return new Object[][]{ - {Job.JobStatus.IN_PROGRESS, Action.None, false, false}, - {Job.JobStatus.COMPLETED_WITH_NO_ACTION, Action.None, false, false}, - {Job.JobStatus.COMPLETED, Action.None, false, false}, - {Job.JobStatus.FAILED, Action.None, false, true}, - {Job.JobStatus.COMPLETED_WITH_ERRORS, Action.None, false, true}, - {Job.JobStatus.COMPLETED_WITH_ERRORS, Action.None, true, false}, - {Job.JobStatus.FAILED, Action.None, true, false}, - {Job.JobStatus.FAILED, Action.Delete, true, true}, - {Job.JobStatus.FAILED, Action.Create, true, true}, + {Job.JobStatus.IN_PROGRESS, None, false, false}, + {Job.JobStatus.COMPLETED_WITH_NO_ACTION, None, false, false}, + {Job.JobStatus.COMPLETED, None, false, false}, + {Job.JobStatus.FAILED, None, false, true}, + {Job.JobStatus.COMPLETED_WITH_ERRORS, None, false, true}, + {Job.JobStatus.COMPLETED_WITH_ERRORS, None, true, false}, + {Job.JobStatus.FAILED, None, true, false}, + {Job.JobStatus.FAILED, Delete, true, true}, + {Job.JobStatus.FAILED, Create, true, true}, }; } @@ -200,7 +231,7 @@ public class ResourceCommandTest { @Test(dataProvider = "testShallStopJobDataProvider") public void testShallStopJob(Job.JobStatus jobStatus, Action action, boolean isService, boolean expectedResult) { //in this test, there is no meaning to constructor parameters besides isService - MockCommandTestingStateMachine underTest = new MockCommandTestingStateMachine(InternalState.WATCHING, Action.Delete, Job.JobStatus.COMPLETED, false, isService); + MockCommandTestingStateMachine underTest = new MockCommandTestingStateMachine(InternalState.WATCHING, Delete, Job.JobStatus.COMPLETED, false, isService, true); BaseResource mockedRequest = mock(BaseResource.class); when(underTest.getSharedData().getRequest()).thenReturn(mockedRequest); @@ -209,6 +240,94 @@ public class ResourceCommandTest { assertEquals(expectedResult, underTest.shallStopJob(jobStatus)); } + public static class FakeResourceCreator { + + public static Map convertToMap(List list) { + if (list==null) { + return null; + } + return list.stream().collect(Collectors.toMap(x-> UUID.randomUUID().toString(), x->x)); + } + + static ServiceInstantiation createService(List vnfs, List networks, List vnfGroups) { + return new ServiceInstantiation(mock(ModelInfo.class), null, null, null, null, null, null, null, null, null, null, null, null, null, null, + convertToMap(vnfs), + convertToMap(networks), + convertToMap(vnfGroups), + null, + null, false, 1, false,false,null, null, null, null, null, null, null); + } + + public static ServiceInstantiation createServiceWith2InstancesInEachLevel(Action action) { + return createService( + ImmutableList.of( + createVnf(ImmutableList.of(createVfModule(action), createVfModule(action)), action), + createVnf(ImmutableList.of(createVfModule(action), createVfModule(action)), action)), + ImmutableList.of( + createNetwork(action), + createNetwork(action)), + ImmutableList.of( + createGroup(ImmutableList.of(createMember(action), createMember(action)), action), + createGroup(ImmutableList.of(createMember(action), createMember(action)), action)) + ); + } + + static InstanceGroup createGroup(List groupMembers, Action action) { + return new InstanceGroup(mock(ModelInfo.class), null, action.name(), false, null, convertToMap(groupMembers), null, null, null); + } + + static InstanceGroupMember createMember(Action action) { + return new InstanceGroupMember(null, action.toString(), null, null, null); + } + + static Vnf createVnf(List vfModules, Action action) { + Map> vfModulesMap = new HashMap<>(); + vfModulesMap.put("abc",convertToMap(vfModules)); + + return new Vnf(mock(ModelInfo.class), null, null, action.toString(), null, null, null, null, null, null, false, null, vfModulesMap, null, null, null); + } + + static Vnf createVnf(Action action) { + return new Vnf(mock(ModelInfo.class), null, null, action.toString(), null, null, null, null, null, null, false, null,null, null, null, null); + } + + static VfModule createVfModule(Action action) { + return new VfModule(mock(ModelInfo.class), null, null, action.toString(), null, null, null, null, null, false, false, null, null, null, null); + } + + static Network createNetwork(Action action) { + return new Network(mock(ModelInfo.class), null, null, action.toString(), null, null, null, null, null, null, false, null, null, null, null); + } + } + + @DataProvider + public static Object[][] testIsDescendantHasActionDataProvider() { + return new Object[][]{ + {"empty service", Create, false, createService(emptyList(), emptyList(), emptyList())}, + {"instance group with None", Create, false, createService(emptyList(), emptyList(), ImmutableList.of(createGroup(emptyList(), None)))}, + {"instance group with Create", Create, true, createService(emptyList(), emptyList(), ImmutableList.of(createGroup(emptyList(), Create)))}, + {"instance group None + member Delete", Delete, true, createService(emptyList(), emptyList(), ImmutableList.of(createGroup(ImmutableList.of(createMember(Delete)), None)))}, + {"instance group None + member Create", Delete, false, createService(emptyList(), emptyList(), ImmutableList.of(createGroup(ImmutableList.of(createMember(Create)), None)))}, + {"instance group None + member Create + member Delete", Delete, true, + createService(emptyList(), emptyList(), ImmutableList.of(createGroup(ImmutableList.of(createMember(Create), createMember(Delete)), None)))}, + {"vnf Create", Delete, false, createService(ImmutableList.of(createVnf(emptyList(), Create)), emptyList(),emptyList())}, + {"vnf Create", Create, true, createService(ImmutableList.of(createVnf(emptyList(), Create)), emptyList(),emptyList())}, + {"vnf Create null VfModules internal map", Create, false, createService(ImmutableList.of(createVnf(null, Delete)), emptyList(),emptyList())}, + {"vnf Delete with null VfModules", Create, false, createService(ImmutableList.of(createVnf(Delete)), emptyList(),emptyList())}, + {"vnf None + VfModule Create", Create, true, createService(ImmutableList.of(createVnf(ImmutableList.of(createVfModule(Create)), None)), emptyList(),emptyList())}, + {"vnf None + VfModule None", Create, false, createService(ImmutableList.of(createVnf(ImmutableList.of(createVfModule(None)), None)), emptyList(),emptyList())}, + {"network Create", Create, true, createService(emptyList(), ImmutableList.of(createNetwork(Create)), emptyList())}, + {"network Delete", Create, false, createService(emptyList(), ImmutableList.of(createNetwork(Delete)), emptyList())}, + }; + } + + @Test(dataProvider = "testIsDescendantHasActionDataProvider") + public void testIsDescendantHasAction(String desc, Action action, boolean expectedResult, BaseResource request) { + //in this test, there is no meaning to constructor parameters + MockCommand underTest = new MockCommand(InternalState.WATCHING, Delete, Job.JobStatus.COMPLETED); + assertEquals(expectedResult, underTest.isDescendantHasAction(request, action)); + } + @DataProvider public static Object[][] testCallDataProvider() { return new Object[][]{ @@ -235,7 +354,7 @@ public class ResourceCommandTest { String description, InternalState internalState, Job.JobStatus currentStateResult, InternalState expectedNextState, Job.JobStatus expectedNextStatus) { - MockCommandTestingStateMachine underTest = new MockCommandTestingStateMachine(internalState, Action.Delete, currentStateResult, true); + MockCommandTestingStateMachine underTest = new MockCommandTestingStateMachine(internalState, Delete, currentStateResult, true); NextCommand nextCommand = underTest.call(); assertEquals(expectedNextStatus, nextCommand.getStatus()); @@ -250,12 +369,6 @@ public class ResourceCommandTest { } } - @Test(expectedExceptions = IllegalStateException.class) - public void whenCommandInUnMappedState_exceptionIsThrown() { - MockCommandTestingStateMachine underTest = new MockCommandTestingStateMachine(InternalState.TERMINAL, Action.Delete, Job.JobStatus.COMPLETED, true); - underTest.call(); - } - @DataProvider public static Object[][] InProgressDataProvider() { return Stream.of(Job.JobStatus.values()) @@ -266,7 +379,7 @@ public class ResourceCommandTest { @Test(dataProvider = "InProgressDataProvider") public void whenGetResultFromMso_InProgressReturnThem(Job.JobStatus mockedJobStatus) { Job.JobStatus expectedJobStatus = (mockedJobStatus== Job.JobStatus.PAUSE) ? Job.JobStatus.IN_PROGRESS : mockedJobStatus; - MockCommand underTest = new MockCommand(InternalState.IN_PROGRESS, Action.Delete, mockedJobStatus); + MockCommand underTest = new MockCommand(InternalState.IN_PROGRESS, Delete, mockedJobStatus); when(underTest.getInProgressStatusService().call(any(), any(), any())).thenReturn(mockedJobStatus); assertEquals(expectedJobStatus, underTest.inProgress()); } @@ -282,22 +395,22 @@ public class ResourceCommandTest { @Test(dataProvider = "InProgressExceptionsDataProvider") public void whenInProgressStatusServiceThrowException_InProgressReturnStatus(Exception exception, Job.JobStatus expectedJobStatus) { - MockCommand underTest = new MockCommand(InternalState.IN_PROGRESS, Action.Delete, expectedJobStatus); + MockCommand underTest = new MockCommand(InternalState.IN_PROGRESS, Delete, expectedJobStatus); when(underTest.getInProgressStatusService().call(any(), any(), any())).thenThrow(exception); assertEquals(expectedJobStatus, underTest.inProgress()); } @DataProvider public static Object[][] testIsNeedToDeleteMySelfDataProvider() { - return Stream.of(Action.values()) + return Stream.of(values()) .map(status -> new Object[] { status }) .toArray(Object[][]::new); } @Test(dataProvider = "testIsNeedToDeleteMySelfDataProvider") public void testIsNeedToDeleteMySelf(Action action) { - boolean expectedResult = (action== Action.Delete); - MockCommand underTest = new MockCommand(InternalState.DELETE_MYSELF, Action.Delete, Job.JobStatus.IN_PROGRESS); + boolean expectedResult = (action== Delete); + MockCommand underTest = new MockCommand(InternalState.DELETE_MYSELF, Delete, Job.JobStatus.IN_PROGRESS); BaseResource mockedBaseResource = mock(BaseResource.class); when(underTest.getSharedData().getRequest()).thenReturn(mockedBaseResource); when(mockedBaseResource.getAction()).thenReturn(action); @@ -315,9 +428,74 @@ public class ResourceCommandTest { @Test(dataProvider = "testWatchingDataProvider") public void testWatching(String desc, Job.JobStatus childrenJobsStatus, Job.JobStatus expectedJobStatus) { - MockCommand underTest = new MockCommand(InternalState.WATCHING, Action.Delete, Job.JobStatus.IN_PROGRESS); + MockCommand underTest = new MockCommand(InternalState.WATCHING, Delete, Job.JobStatus.IN_PROGRESS); when(underTest.getWatchChildrenJobsBL().retrieveChildrenJobsStatus(any())).thenReturn(childrenJobsStatus); assertEquals(expectedJobStatus, underTest.watchChildren()); } + @DataProvider + public static Object[][] testCalcInitialStateDataProvider() { + return new Object[][]{ + {Delete, true, Delete, InternalState.CREATING_CHILDREN}, + {Delete, false, Delete, InternalState.DELETE_MYSELF}, + {Delete, false, Create, InternalState.TERMINAL}, + {Delete, true, Create, InternalState.CREATING_CHILDREN}, + {Create, true, Create, InternalState.CREATE_MYSELF}, + {Create, false, Create, InternalState.CREATE_MYSELF}, + {Create, false, Delete, InternalState.TERMINAL}, + {Create, true, Delete, InternalState.CREATING_CHILDREN}, + {Create, true, Resume, InternalState.RESUME_MYSELF}, + {Delete, false, Resume, InternalState.TERMINAL}, + }; + } + + @Test(dataProvider = "testCalcInitialStateDataProvider") + public void testCalcInitialState(Action phase, boolean isDescendantHasAction, Action action, InternalState expectedState) { + ResourceCommand underTest = mock(ResourceCommand.class); + when(underTest.calcInitialState(any(), any())).thenCallRealMethod(); + when(underTest.isDescendantHasAction(eq(phase))).thenReturn(isDescendantHasAction); + when(underTest.getActionType()).thenReturn(action); + when(underTest.isNeedToDeleteMyself()).thenCallRealMethod(); + when(underTest.isNeedToCreateMyself()).thenCallRealMethod(); + when(underTest.isNeedToResumeMySelf()).thenCallRealMethod(); + + Map commandData = ImmutableMap.of(INTERNAL_STATE, InternalState.INITIAL.name()); + assertEquals(expectedState, underTest.calcInitialState(commandData, phase)); + } + + + //throw exception when call to create children + //create children is just example, it could be any other method that called by ResourceCommand.invokeCommand + public static class MockCommandThrowExceptionOnCreateChildren extends MockCommandTestingStateMachine { + + private final RuntimeException exceptionToThrow; + + public MockCommandThrowExceptionOnCreateChildren(RuntimeException exceptionToThrow) { + super(InternalState.CREATING_CHILDREN, Delete, Job.JobStatus.COMPLETED, true); + this.exceptionToThrow = exceptionToThrow; + doAnswer(returnsFirstArg()).when(this.getWatchChildrenJobsBL()).cumulateJobStatus(any(), any()); + } + + @NotNull + @Override + public Job.JobStatus createChildren() { + throw exceptionToThrow; + } + } + + @DataProvider + public static Object[][] exceptionAndStateProvider() { + return new Object[][]{ + {new TryAgainException(new Exception()), Job.JobStatus.RESOURCE_IN_PROGRESS}, + {new AbortingException(new Exception()), Job.JobStatus.FAILED}, + }; + } + + @Test(dataProvider = "exceptionAndStateProvider") + public void whenKnownExceptionThrownInCommandInvocation_thenStateIsAsExpected(RuntimeException exception, Job.JobStatus expectedNextStatus) { + MockCommandTestingStateMachine underTest = new MockCommandThrowExceptionOnCreateChildren(exception); + NextCommand nextCommand = underTest.call(); + assertEquals(expectedNextStatus, nextCommand.getStatus()); + } + } diff --git a/vid-app-common/src/test/java/org/onap/vid/job/command/ResourceInProgressStatusCommandTest.java b/vid-app-common/src/test/java/org/onap/vid/job/command/ResourceInProgressStatusCommandTest.java deleted file mode 100644 index 5b036f587..000000000 --- a/vid-app-common/src/test/java/org/onap/vid/job/command/ResourceInProgressStatusCommandTest.java +++ /dev/null @@ -1,60 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * VID - * ================================================================================ - * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * 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.vid.job.command; - -import org.mockito.InjectMocks; -import org.mockito.MockitoAnnotations; -import org.onap.vid.job.Job; -import org.onap.vid.job.NextCommand; -import org.testng.annotations.BeforeMethod; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.core.Is.is; - - -public class ResourceInProgressStatusCommandTest { - - @InjectMocks - private ResourceInProgressStatusCommand commandUnderTest = new ResourceInProgressStatusCommand(); - - @BeforeMethod - public void initMocks() { - MockitoAnnotations.initMocks(this); - } - - @DataProvider - public static Object[][] givenStatusToExpectedStatus() { - return new Object[][]{ - {Job.JobStatus.IN_PROGRESS, Job.JobStatus.IN_PROGRESS}, - {Job.JobStatus.FAILED, Job.JobStatus.FAILED}, - {Job.JobStatus.COMPLETED, Job.JobStatus.COMPLETED} - }; - } - - @Test(dataProvider = "givenStatusToExpectedStatus") - public void whenGetStatusFromMso_returnExpectedNextCommand(Job.JobStatus jobStatus, Job.JobStatus expectedNextStatus) { - NextCommand nextCommand = commandUnderTest.processJobStatus(jobStatus); - assertThat(nextCommand.getStatus(), is(expectedNextStatus)); - assertThat(nextCommand.getCommand(), is(commandUnderTest)); - } -} diff --git a/vid-app-common/src/test/java/org/onap/vid/job/command/ServiceInProgressStatusCommandTest.java b/vid-app-common/src/test/java/org/onap/vid/job/command/ServiceInProgressStatusCommandTest.java index 31dbc9f6d..787ff608d 100644 --- a/vid-app-common/src/test/java/org/onap/vid/job/command/ServiceInProgressStatusCommandTest.java +++ b/vid-app-common/src/test/java/org/onap/vid/job/command/ServiceInProgressStatusCommandTest.java @@ -7,9 +7,9 @@ * 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. @@ -20,22 +20,22 @@ package org.onap.vid.job.command; +import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import org.mockito.ArgumentCaptor; -import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.MockitoAnnotations; -import org.onap.portalsdk.core.util.SystemProperties; import org.onap.vid.job.*; import org.onap.vid.job.impl.JobSharedData; +import org.onap.vid.model.Action; import org.onap.vid.model.serviceInstantiation.Network; import org.onap.vid.model.serviceInstantiation.ServiceInstantiation; import org.onap.vid.model.serviceInstantiation.Vnf; -import org.onap.vid.mso.model.ModelInfo; +import org.onap.vid.mso.RestMsoImplementation; import org.onap.vid.properties.Features; import org.onap.vid.properties.VidProperties; import org.onap.vid.services.AsyncInstantiationBusinessLogic; -import org.springframework.core.env.Environment; +import org.onap.vid.services.AuditService; import org.testng.Assert; import org.testng.annotations.BeforeMethod; import org.testng.annotations.DataProvider; @@ -47,10 +47,9 @@ import java.time.ZoneOffset; import java.time.ZonedDateTime; import java.time.temporal.ChronoUnit; import java.util.Arrays; -import java.util.Map; -import java.util.TreeMap; import java.util.UUID; +import static java.util.Collections.emptyList; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.core.Is.is; @@ -58,7 +57,11 @@ import static org.mockito.Matchers.any; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.*; import static org.onap.vid.job.Job.JobStatus.*; +import static org.onap.vid.job.command.ResourceCommandKt.*; +import static org.onap.vid.job.command.ResourceCommandTest.FakeResourceCreator.*; +import static org.onap.vid.model.Action.Create; import static org.onap.vid.testUtils.TestUtils.testWithSystemProperty; +import static org.testng.AssertJUnit.assertEquals; public class ServiceInProgressStatusCommandTest { @@ -78,45 +81,29 @@ public class ServiceInProgressStatusCommandTest { @Mock private JobSharedData sharedData; - @Mock - private Environment environment; - @Mock private ServiceInstantiation request; @Mock private InProgressStatusService inProgressStatusService; - @InjectMocks - private ServiceInProgressStatusCommand command = new ServiceInProgressStatusCommand(); + @Mock + private WatchChildrenJobsBL watchChildrenJobsBL; - @DataProvider - public static Object[][] isNeedToCreateChildJobsDataProvider() { - return new Object[][]{ - {new TreeMap() , true, true, false}, - {null , true, true, false}, - {ImmutableMap.of("a",mock(Vnf.class)), false, true, false}, - {ImmutableMap.of("a",mock(Vnf.class)), true, false, false}, - {ImmutableMap.of("a",mock(Vnf.class)), true, true, true}, - }; - } + @Mock + private MsoResultHandlerService msoResultHandlerService; + + @Mock + private MsoRequestBuilder msoRequestBuilder; + + @Mock + private RestMsoImplementation restMsoImplementation; + + @Mock + private AuditService auditService; + + private ALaCarteServiceCommand command; - @DataProvider - public static Object[][] processJobStatusData() { - return new Object[][]{ - /* {MSO jobStatus, jobStartTime, isNeedToCreateChildJobs(), property vid.job.max.hoursInProgress, expected nextCommand.getStatus() } */ - {IN_PROGRESS, false, IN_PROGRESS}, - {FAILED, false, FAILED}, - {PAUSE, false, IN_PROGRESS}, - {COMPLETED, false, COMPLETED}, - {COMPLETED, true, IN_PROGRESS}, - {RESOURCE_IN_PROGRESS, false, RESOURCE_IN_PROGRESS}, - {PENDING, false, PENDING}, - {STOPPED, false, STOPPED}, - {COMPLETED_WITH_ERRORS, false, COMPLETED_WITH_ERRORS}, - {CREATING, false, CREATING} - }; - } @DataProvider public static Object[][] isExpiredJobStatusData() { @@ -138,32 +125,31 @@ public class ServiceInProgressStatusCommandTest { @BeforeMethod public void initMocks() { MockitoAnnotations.initMocks(this); - } - - @Test(dataProvider = "isNeedToCreateChildJobsDataProvider" ) - public void testIsNeedToCreateChildJobs(Map serviceVnfs, boolean isALaCarte, - boolean isFeatureEnabled, boolean expected) { - MockitoAnnotations.initMocks(this); - ServiceInstantiation serviceInstantiation = mock(ServiceInstantiation.class); - when(serviceInstantiation.getVnfs()).thenReturn(serviceVnfs); - when(serviceInstantiation.isALaCarte()).thenReturn(isALaCarte); - when(featureManager.isActive(Features.FLAG_ASYNC_ALACARTE_VNF)).thenReturn(isFeatureEnabled); - assertThat(command.isNeedToCreateChildJobs(serviceInstantiation), is(expected)); + command = new ALaCarteServiceCommand( + inProgressStatusService, + watchChildrenJobsBL, + asyncInstantiationBL, + jobsBrokerService, + msoRequestBuilder, + msoResultHandlerService, + jobAdapter, + restMsoImplementation, + auditService + ); } @Test public void whenGetFromMsoCompletedAndALaCarte_generateNewJobsForVnfs() { UUID uuid = UUID.randomUUID(); String userId = "mockedUserID"; - Vnf vnf1 = mock(Vnf.class); - Vnf vnf2 = mock(Vnf.class); - Network network1 = mock(Network.class); - ServiceInstantiation serviceInstantiation = mock(ServiceInstantiation.class); - when(serviceInstantiation.getVnfs()).thenReturn(ImmutableMap.of("a", vnf1, "b", vnf2)); - when(serviceInstantiation.getNetworks()).thenReturn(ImmutableMap.of("c", network1)); - when(serviceInstantiation.isALaCarte()).thenReturn(true); - when(serviceInstantiation.getModelInfo()).thenReturn(new ModelInfo()); - + String testApi = "VNF_API"; + Vnf vnf1 = createVnf(emptyList(), Create); + Vnf vnf2 = createVnf(emptyList(), Create); + Network network = createNetwork(Create); + ServiceInstantiation serviceInstantiation = createService( + ImmutableList.of(vnf1, vnf2), + ImmutableList.of(network), + emptyList()); when(featureManager.isActive(Features.FLAG_ASYNC_ALACARTE_VNF)).thenReturn(true); UUID uuid1 = UUID.fromString("12345678-1234-1234-1234-123456789012"); @@ -171,15 +157,25 @@ public class ServiceInProgressStatusCommandTest { UUID uuid3 = UUID.fromString("12345678-1234-1234-1234-123456789014"); when(jobsBrokerService.add(any())).thenReturn(uuid1).thenReturn(uuid2).thenReturn(uuid3); - JobSharedData sharedData = new JobSharedData(uuid, userId, serviceInstantiation); - command.init(sharedData, "", ""); + JobSharedData sharedData = new JobSharedData(uuid, userId, serviceInstantiation, testApi); + command.init(sharedData, ImmutableMap.of( + ACTION_PHASE, Action.Create.name(), + INTERNAL_STATE, InternalState.IN_PROGRESS.name() + )); when(inProgressStatusService.call(any(), eq(sharedData), any())).thenReturn(Job.JobStatus.COMPLETED); + when(watchChildrenJobsBL.cumulateJobStatus(Job.JobStatus.COMPLETED, COMPLETED_WITH_NO_ACTION)).thenReturn(COMPLETED); + when(watchChildrenJobsBL.cumulateJobStatus(Job.JobStatus.COMPLETED_WITH_NO_ACTION, COMPLETED)).thenReturn(COMPLETED); + when(msoResultHandlerService.getRequest(eq(sharedData))).thenReturn(serviceInstantiation); NextCommand nextCommand = command.call(); + assertEquals(IN_PROGRESS, nextCommand.getStatus()); + nextCommand = nextCommand.getCommand().call(); ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(JobAdapter.AsyncJobRequest.class); - verify(jobAdapter, times(2)).createChildJob(eq(JobType.VnfInstantiation), eq(Job.JobStatus.CREATING), argumentCaptor.capture(), eq(sharedData), any()); - verify(jobAdapter, times(1)).createChildJob(eq(JobType.NetworkInstantiation), eq(Job.JobStatus.CREATING), argumentCaptor.capture(), eq(sharedData), any()); - assertThat(argumentCaptor.getAllValues(), containsInAnyOrder(vnf1, vnf2, network1)); + verify(jobAdapter, times(1)).createChildJob(eq(JobType.NetworkInstantiation), argumentCaptor.capture(), eq(sharedData), any(), eq(0)); + verify(jobAdapter, times(1)).createChildJob(eq(JobType.VnfInstantiation), argumentCaptor.capture(), eq(sharedData), any(), eq(1)); + verify(jobAdapter, times(1)).createChildJob(eq(JobType.VnfInstantiation), argumentCaptor.capture(), eq(sharedData), any(), eq(2)); + + assertThat(argumentCaptor.getAllValues(), containsInAnyOrder(vnf1, vnf2, network)); verify(jobsBrokerService, times(3)).add(any()); @@ -187,41 +183,14 @@ public class ServiceInProgressStatusCommandTest { verify(asyncInstantiationBL, never()).updateServiceInfo(any(), any()); assertThat(nextCommand.getStatus(), is(Job.JobStatus.IN_PROGRESS)); - assertThat(nextCommand.getCommand().getType(), is(new WatchingCommand().getType())); - assertThat(nextCommand.getCommand().getData().get("childrenJobs"), is(Arrays.asList(uuid1.toString(), uuid2.toString(), uuid3.toString()))); - assertThat(nextCommand.getCommand().getData().get("isService"), is(true)); - } - - @Test(dataProvider = "processJobStatusData") - public void processJobStatusTest(Job.JobStatus jobStatus, boolean isNeedToCreateChildJobs, Job.JobStatus expectedStatus) { - - when(featureManager.isActive(Features.FLAG_ASYNC_ALACARTE_VNF)).thenReturn(true); - // All mocks under are used for isNeedToCreateChildJobs=true case - when(sharedData.getRequest()).thenReturn(request); - when(request.isALaCarte()).thenReturn(true); - Map vnfs = mock(Map.class); - ModelInfo modelInfo = mock(ModelInfo.class); - - // if vnfs.isEmpty -> isNeedToCreateChildJobs will return false - when(vnfs.isEmpty()).thenReturn(!isNeedToCreateChildJobs); - - when(request.getVnfs()).thenReturn(vnfs); - when(request.getModelInfo()).thenReturn(modelInfo); - command.instanceId = "MockInstId"; - - NextCommand nextCommand = command.processJobStatus(jobStatus); - Assert.assertEquals(nextCommand.getStatus(), expectedStatus); - if (isNeedToCreateChildJobs) { - Assert.assertEquals(nextCommand.getCommand().getClass(), WatchingCommand.class); - } else { - Assert.assertEquals(nextCommand.getCommand(), command); - } + assertThat(nextCommand.getCommand().getType(), is(JobType.ALaCarteService)); + assertThat(nextCommand.getCommand().getData().get(CHILD_JOBS), is(Arrays.asList(uuid1.toString(), uuid2.toString(), uuid3.toString()))); } @Test(dataProvider = "isExpiredJobStatusData") public void isExpiredJobStatusTest(ZonedDateTime jobStartTime, String configValue, boolean expectedResult) throws Exception { testWithSystemProperty(VidProperties.VID_JOB_MAX_HOURS_IN_PROGRESS, configValue, ()-> - Assert.assertEquals(command.getExpiryChecker().isExpired(jobStartTime), expectedResult) + Assert.assertEquals(command.getExpiryChecker().isExpired(jobStartTime), expectedResult) ); } } diff --git a/vid-app-common/src/test/java/org/onap/vid/job/command/WatchChildrenJobsBLTest.java b/vid-app-common/src/test/java/org/onap/vid/job/command/WatchChildrenJobsBLTest.java index 630c46438..a9a961db8 100644 --- a/vid-app-common/src/test/java/org/onap/vid/job/command/WatchChildrenJobsBLTest.java +++ b/vid-app-common/src/test/java/org/onap/vid/job/command/WatchChildrenJobsBLTest.java @@ -7,9 +7,9 @@ * 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. @@ -23,10 +23,10 @@ package org.onap.vid.job.command; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.MockitoAnnotations; -import org.onap.portalsdk.core.service.DataAccessService; import org.onap.vid.job.Job.JobStatus; import org.onap.vid.job.impl.JobDaoImpl; import org.onap.vid.utils.DaoUtils; +import org.onap.portalsdk.core.service.DataAccessService; import org.testng.annotations.BeforeClass; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; diff --git a/vid-app-common/src/test/java/org/onap/vid/job/command/WatchingCommandTest.java b/vid-app-common/src/test/java/org/onap/vid/job/command/WatchingCommandTest.java deleted file mode 100644 index cc0e66007..000000000 --- a/vid-app-common/src/test/java/org/onap/vid/job/command/WatchingCommandTest.java +++ /dev/null @@ -1,97 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * VID - * ================================================================================ - * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * 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.vid.job.command; - -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.onap.portalsdk.core.service.DataAccessService; -import org.onap.vid.job.Job; -import org.onap.vid.job.NextCommand; -import org.onap.vid.job.impl.JobSharedData; -import org.onap.vid.model.serviceInstantiation.ServiceInstantiation; -import org.onap.vid.services.AsyncInstantiationBusinessLogic; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; - -import java.util.List; -import java.util.UUID; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.core.Is.is; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.*; - -public class WatchingCommandTest { - - @Mock - private AsyncInstantiationBusinessLogic asyncInstantiationBL; - - @Mock - private DataAccessService dataAccessService; - - @Mock - private WatchChildrenJobsBL watchChildrenJobsBL; - - @InjectMocks - private WatchingCommand watchingCommand = new WatchingCommand(); - - - - @BeforeClass - public void initMocks() { - MockitoAnnotations.initMocks(this); - } - - @DataProvider - public static Object[][] testWatchingDataProvider() { - return new Object[][]{ - {"all children final, no failed child, is service", Job.JobStatus.COMPLETED, true, Job.JobStatus.COMPLETED}, - {"all children final, there is failed child, is service", Job.JobStatus.COMPLETED_WITH_ERRORS, true, Job.JobStatus.COMPLETED_WITH_ERRORS}, - {"not all children final, is service", Job.JobStatus.IN_PROGRESS, true, Job.JobStatus.IN_PROGRESS}, - {"all children final, no failed child, not service", Job.JobStatus.COMPLETED, false, Job.JobStatus.COMPLETED}, - {"all children final, there is failed child, not service", Job.JobStatus.COMPLETED_WITH_ERRORS, false, Job.JobStatus.COMPLETED_WITH_ERRORS}, - {"not all children final, not service", Job.JobStatus.IN_PROGRESS, false, Job.JobStatus.RESOURCE_IN_PROGRESS}, - }; - } - - - - @Test(dataProvider = "testWatchingDataProvider") - public void whenGetChildrenStatus_thenJobStatusAsExpected(String desc, Job.JobStatus childrenComulativeStatus, boolean isService, Job.JobStatus expectedCommandStatus) { - UUID jobUUID = UUID.randomUUID(); - JobSharedData sharedData = new JobSharedData(jobUUID, "mockedUserID", mock(ServiceInstantiation.class)); - List uuids = mock(List.class); - watchingCommand.init(sharedData, uuids, isService); - when(watchChildrenJobsBL.retrieveChildrenJobsStatus(eq(uuids))).thenReturn(childrenComulativeStatus); - when(watchChildrenJobsBL.cumulateJobStatus(eq(childrenComulativeStatus),eq(Job.JobStatus.COMPLETED))).thenReturn(childrenComulativeStatus); - - //execute command and verify - NextCommand nextCommand = watchingCommand.call(); - assertThat(nextCommand.getStatus(), is(expectedCommandStatus)); - if (!expectedCommandStatus.equals(Job.JobStatus.IN_PROGRESS) && isService) { - verify(asyncInstantiationBL).updateServiceInfoAndAuditStatus(jobUUID, expectedCommandStatus); - } else { - verify(asyncInstantiationBL, never()).updateServiceInfoAndAuditStatus(jobUUID, expectedCommandStatus); - } - } -} diff --git a/vid-app-common/src/test/java/org/onap/vid/job/impl/AsyncInstantiationIntegrationTest.java b/vid-app-common/src/test/java/org/onap/vid/job/impl/AsyncInstantiationIntegrationTest.java index 0b1fff3b2..498708d06 100644 --- a/vid-app-common/src/test/java/org/onap/vid/job/impl/AsyncInstantiationIntegrationTest.java +++ b/vid-app-common/src/test/java/org/onap/vid/job/impl/AsyncInstantiationIntegrationTest.java @@ -7,9 +7,9 @@ * 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. @@ -20,43 +20,55 @@ package org.onap.vid.job.impl; +import com.fasterxml.jackson.databind.JsonNode; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.mutable.MutableInt; +import org.jetbrains.annotations.NotNull; +import org.mockito.ArgumentCaptor; import org.mockito.Mockito; +import org.mockito.hamcrest.MockitoHamcrest; import org.onap.portalsdk.core.service.DataAccessService; import org.onap.portalsdk.core.util.SystemProperties; import org.onap.vid.asdc.AsdcCatalogException; -import org.onap.vid.config.DataSourceConfig; -import org.onap.vid.config.JobCommandsConfigWithMockedMso; -import org.onap.vid.config.MockedAaiClientAndFeatureManagerConfig; +import org.onap.vid.changeManagement.RequestDetailsWrapper; import org.onap.vid.job.Job; import org.onap.vid.job.Job.JobStatus; import org.onap.vid.job.JobType; import org.onap.vid.job.JobsBrokerService; import org.onap.vid.job.command.CommandUtils; import org.onap.vid.job.command.InternalState; -import org.onap.vid.model.Action; -import org.onap.vid.model.NameCounter; -import org.onap.vid.model.RequestReferencesContainer; -import org.onap.vid.model.ServiceInfo; +import org.onap.vid.model.*; +import org.onap.vid.model.serviceInstantiation.BaseResource; +import org.onap.vid.model.serviceInstantiation.InstanceGroup; import org.onap.vid.model.serviceInstantiation.ServiceInstantiation; import org.onap.vid.mso.RestMsoImplementation; import org.onap.vid.mso.RestObject; import org.onap.vid.mso.model.RequestReferences; import org.onap.vid.mso.rest.AsyncRequestStatus; +import org.onap.vid.mso.rest.AsyncRequestStatusList; import org.onap.vid.properties.Features; -import org.onap.vid.services.AsyncInstantiationBaseTest; import org.onap.vid.services.AsyncInstantiationBusinessLogic; +import org.onap.vid.services.AuditService; +import org.onap.vid.services.VersionService; import org.onap.vid.utils.DaoUtils; +import org.onap.vid.config.DataSourceConfig; +import org.onap.vid.config.JobCommandsConfigWithMockedMso; +import org.onap.vid.config.MockedAaiClientAndFeatureManagerConfig; +import org.onap.vid.services.AsyncInstantiationBaseTest; +import org.onap.vid.testUtils.TestUtils; +import org.springframework.http.HttpMethod; import org.springframework.test.context.ContextConfiguration; import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeMethod; import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; import org.togglz.core.manager.FeatureManager; import javax.inject.Inject; import javax.ws.rs.ProcessingException; +import java.io.IOException; import java.lang.reflect.Method; import java.util.*; import java.util.function.BiConsumer; @@ -66,7 +78,8 @@ import java.util.stream.IntStream; import java.util.stream.Stream; import static java.util.stream.Collectors.*; -import static net.javacrumbs.jsonunit.JsonMatchers.jsonPartEquals; +import static net.javacrumbs.jsonunit.JsonAssert.assertJsonEquals; +import static net.javacrumbs.jsonunit.JsonMatchers.*; import static org.hamcrest.CoreMatchers.*; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.hasProperty; @@ -77,7 +90,7 @@ import static org.mockito.ArgumentMatchers.endsWith; import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; import static org.onap.vid.job.Job.JobStatus.*; -import static org.onap.vid.model.JobAuditStatus.SourceStatus.MSO; +import static org.onap.vid.job.impl.JobSchedulerInitializer.WORKERS_TOPICS; import static org.onap.vid.model.JobAuditStatus.SourceStatus.VID; import static org.testng.AssertJUnit.*; @@ -96,6 +109,9 @@ public class AsyncInstantiationIntegrationTest extends AsyncInstantiationBaseTes public static String REQUEST_ID = UUID.randomUUID().toString(); public static String SERVICE_INSTANCE_ID = UUID.randomUUID().toString(); + @Inject + private VersionService versionService; + @Inject private JobsBrokerService jobsBrokerService; @@ -108,6 +124,9 @@ public class AsyncInstantiationIntegrationTest extends AsyncInstantiationBaseTes @Inject private AsyncInstantiationBusinessLogic asyncInstantiationBL; + @Inject + private AuditService auditService; + @Inject private RestMsoImplementation restMso; @@ -120,6 +139,7 @@ public class AsyncInstantiationIntegrationTest extends AsyncInstantiationBaseTes @BeforeClass void initServicesInfoService() { createInstanceParamsMaps(); + when(versionService.retrieveBuildNumber()).thenReturn("fakeBuild"); } @BeforeMethod @@ -131,10 +151,12 @@ public class AsyncInstantiationIntegrationTest extends AsyncInstantiationBaseTes @BeforeMethod void defineMocks() { + Mockito.reset(restMso); + Mockito.reset(aaiClient); mockAaiClientAnyNameFree(); } - //@Test + @Test public void whenPushNewBulk_thenAllServicesAreInPending() { pushMacroBulk(); @@ -144,8 +166,8 @@ public class AsyncInstantiationIntegrationTest extends AsyncInstantiationBaseTes private List pushMacroBulk() { ServiceInstantiation serviceInstantiation = generateMockMacroServiceInstantiationPayload(false, - createVnfList(instanceParamsMapWithoutParams, Collections.EMPTY_LIST, true), - 3, true,PROJECT_NAME, true); + createVnfList(instanceParamsMapWithoutParams, Collections.EMPTY_LIST, true), + 3, true,PROJECT_NAME, true); return asyncInstantiationBL.pushBulkJob(serviceInstantiation, USER_ID); } @@ -167,6 +189,10 @@ public class AsyncInstantiationIntegrationTest extends AsyncInstantiationBaseTes return createResponse(statusCode, SERVICE_INSTANCE_ID, REQUEST_ID); } + public static RestObject createResponseRandomIds(int statusCode) { + return createResponse(statusCode, UUID.randomUUID().toString(), UUID.randomUUID().toString()); + } + public static RestObject createResponse(int statusCode, String instanceId, String requestId) { RequestReferences requestReferences = new RequestReferences(); requestReferences.setRequestId(requestId); @@ -180,7 +206,7 @@ public class AsyncInstantiationIntegrationTest extends AsyncInstantiationBaseTes ImmutableList statusesToStrings(JobStatus... jobStatuses) { return Stream.of(jobStatuses).map( - Enum::toString).collect(ImmutableList.toImmutableList()); + Enum::toString).collect(ImmutableList.toImmutableList()); } /* @@ -190,81 +216,85 @@ public class AsyncInstantiationIntegrationTest extends AsyncInstantiationBaseTes Make sure service state is Completed successfully once we got from MSO complete, and that next job is peeked. Once a service in the bulk is failed, other services moved to Stopped, and no other jobs from the bulk are peeked. */ - //@Test + @Test public void testStatusesOfMacroServiceInBulkDuringBulkLifeCycle() { - when(restMso.PostForObject(any(), any(), eq(RequestReferencesContainer.class))).thenReturn(createResponse(200)); + + final String SERVICE_REQUEST_ID = UUID.randomUUID().toString(); + final String SERVICE_INSTANCE_ID = UUID.randomUUID().toString(); + final String SERVICE2_REQUEST_ID = UUID.randomUUID().toString(); + final String SERVICE2_INSTANCE_ID = UUID.randomUUID().toString(); + + when(restMso.restCall(eq(HttpMethod.POST), eq(RequestReferencesContainer.class), any(), any(), eq(Optional.empty()))) + .thenReturn(createResponse(200, SERVICE_INSTANCE_ID, SERVICE_REQUEST_ID)); + ImmutableList> expectedStatusesForVid = ImmutableList.of( - statusesToStrings(PENDING, IN_PROGRESS, COMPLETED), - statusesToStrings(PENDING, IN_PROGRESS, FAILED), - statusesToStrings(PENDING, STOPPED) + statusesToStrings(PENDING, IN_PROGRESS, COMPLETED), + statusesToStrings(PENDING, IN_PROGRESS, FAILED), + statusesToStrings(PENDING, STOPPED) ); ImmutableList> expectedStatusesForMso = ImmutableList.of( - ImmutableList.of(REQUESTED, IN_PROGRESS_STR, "not a state", FAILED_STR ,COMPLETE_STR), - ImmutableList.of(REQUESTED, FAILED_STR), - ImmutableList.of() + ImmutableList.of(REQUESTED, IN_PROGRESS_STR, "not a state", FAILED_STR ,COMPLETE_STR), + ImmutableList.of(REQUESTED, FAILED_STR), + ImmutableList.of() ); List uuids = pushMacroBulk(); - pullPendingJobAndAssertJobStatus(JobStatus.IN_PROGRESS, PENDING); - + UUID firstJobUuid = uuids.get(0); + UUID secondJobUuid = uuids.get(1); //assert that when get ProcessingException from restMso, status remain the same - when(restMso.GetForObject(any(), eq(AsyncRequestStatus.class))).thenThrow(new ProcessingException("fake message")); - Job job = pullJobProcessAndPushBack(JobStatus.IN_PROGRESS, JobStatus.IN_PROGRESS); - UUID firstHandledJobUUID = job.getUuid(); - listServicesAndAssertStatus(JobStatus.IN_PROGRESS, PENDING, job); + when(restMso.GetForObject(endsWith(SERVICE_REQUEST_ID), eq(AsyncRequestStatus.class))).thenThrow(new ProcessingException("fake message")); + processJobsCountTimesAndAssertStatus(firstJobUuid, 10, IN_PROGRESS, PENDING); //assert that when get IN_PROGRESS status from restMso, status remain IN_PROGRESS - when(restMso.GetForObject(any(), eq(AsyncRequestStatus.class))).thenReturn(asyncRequestStatusResponseAsRestObject(IN_PROGRESS_STR)); - job = pullJobProcessAndPushBack(JobStatus.IN_PROGRESS, JobStatus.IN_PROGRESS); - listServicesAndAssertStatus(JobStatus.IN_PROGRESS, PENDING, job); + when(restMso.GetForObject(endsWith(SERVICE_REQUEST_ID), eq(AsyncRequestStatus.class))).thenReturn(asyncRequestStatusResponseAsRestObject(IN_PROGRESS_STR)); + processJobsCountTimesAndAssertStatus(firstJobUuid, 10, IN_PROGRESS, PENDING); //assert that when get unrecognized status from restMso, status remain IN_PROGRESS - when(restMso.GetForObject(any(), eq(AsyncRequestStatus.class))).thenReturn(asyncRequestStatusResponseAsRestObject("not a state")); - job = pullJobProcessAndPushBack(JobStatus.IN_PROGRESS, JobStatus.IN_PROGRESS); - listServicesAndAssertStatus(JobStatus.IN_PROGRESS, PENDING, job); + when(restMso.GetForObject(endsWith(SERVICE_REQUEST_ID), eq(AsyncRequestStatus.class))).thenReturn(asyncRequestStatusResponseAsRestObject("not a state")); + processJobsCountTimesAndAssertStatus(firstJobUuid, 10, IN_PROGRESS, PENDING); //assert that when get non 200 status code during IN_PROGRESS, status remain IN_PROGRESS - when(restMso.GetForObject(any(), eq(AsyncRequestStatus.class))).thenReturn(asyncRequestStatusResponseAsRestObject(COMPLETE_STR, 404)); - job = pullJobProcessAndPushBack(JobStatus.IN_PROGRESS, JobStatus.IN_PROGRESS); - listServicesAndAssertStatus(JobStatus.IN_PROGRESS, PENDING, job); + when(restMso.GetForObject(endsWith(SERVICE_REQUEST_ID), eq(AsyncRequestStatus.class))).thenReturn(asyncRequestStatusResponseAsRestObject(COMPLETE_STR, 404)); + processJobsCountTimesAndAssertStatus(firstJobUuid, 10, IN_PROGRESS, PENDING); //when get job COMPLETE from MSO, service status become COMPLETED - when(restMso.GetForObject(any(), eq(AsyncRequestStatus.class))). - thenReturn(asyncRequestStatusResponseAsRestObject(COMPLETE_STR)); - job = pullJobProcessAndPushBack(JobStatus.IN_PROGRESS, COMPLETED); - List serviceInfoList = listServicesAndAssertStatus(COMPLETED, PENDING, job); - - + when(restMso.GetForObject(endsWith(SERVICE_REQUEST_ID), eq(AsyncRequestStatus.class))).thenReturn(asyncRequestStatusResponseAsRestObject(COMPLETE_STR)); + pullJobProcessAndPushBack(JobStatus.IN_PROGRESS, COMPLETED); + List serviceInfoList = listServicesAndAssertStatus(COMPLETED, PENDING, firstJobUuid); + + //for use later in the test Map expectedJobStatusMap = serviceInfoList.stream().collect( - Collectors.toMap(ServiceInfo::getJobId, x-> PENDING)); - expectedJobStatusMap.put(job.getUuid(), COMPLETED); + Collectors.toMap(ServiceInfo::getJobId, x-> PENDING)); + expectedJobStatusMap.put(firstJobUuid, COMPLETED); //when handling another PENDING job, statuses are : COMPLETED, IN_PROGRESS, PENDING - job = pullJobProcessAndPushBack(PENDING, JobStatus.IN_PROGRESS); - assertThat(job.getUuid(), not(equalTo(firstHandledJobUUID))); //assert different job was handled now - expectedJobStatusMap.put(job.getUuid(), JobStatus.IN_PROGRESS); + when(restMso.restCall(eq(HttpMethod.POST), eq(RequestReferencesContainer.class), any(), any(), eq(Optional.empty()))) + .thenReturn(createResponse(200, SERVICE2_INSTANCE_ID, SERVICE2_REQUEST_ID)); + when(restMso.GetForObject(endsWith(SERVICE2_REQUEST_ID), eq(AsyncRequestStatus.class))).thenReturn(asyncRequestStatusResponseAsRestObject(IN_PROGRESS_STR)); + processJobsCountTimes(10); + + expectedJobStatusMap.put(secondJobUuid, JobStatus.IN_PROGRESS); listServicesAndAssertStatus(expectedJobStatusMap); + //when get FAILED status from MSO statuses are : COMPLETED, FAILED, STOPPED - when(restMso.GetForObject(any(), eq(AsyncRequestStatus.class))). - thenReturn(asyncRequestStatusResponseAsRestObject(FAILED_STR)); - job = pullJobProcessAndPushBack(JobStatus.IN_PROGRESS, JobStatus.FAILED); - expectedJobStatusMap.put(job.getUuid(), JobStatus.FAILED); + when(restMso.GetForObject(any(), eq(AsyncRequestStatus.class))).thenReturn(asyncRequestStatusResponseAsRestObject(FAILED_STR)); + pullJobProcessAndPushBack(JobStatus.IN_PROGRESS, JobStatus.FAILED); + expectedJobStatusMap.put(secondJobUuid, JobStatus.FAILED); expectedJobStatusMap = expectedJobStatusMap.entrySet().stream().collect(Collectors.toMap( - e -> e.getKey(), e -> e.getValue() == PENDING ? JobStatus.STOPPED : e.getValue() + e -> e.getKey(), e -> e.getValue() == PENDING ? JobStatus.STOPPED : e.getValue() )); listServicesAndAssertStatus(expectedJobStatusMap); IntStream.range(0, uuids.size()).forEach(i -> { UUID uuid = uuids.get(i); - List msoStatuses = asyncInstantiationBL.getAuditStatuses(uuid, MSO).stream().map(x -> x.getJobStatus()).collect(Collectors.toList()); - List vidStatuses = asyncInstantiationBL.getAuditStatuses(uuid, VID).stream().map(x -> x.getJobStatus()).collect(Collectors.toList()); - assertThat(msoStatuses, is(expectedStatusesForMso.get(i))); + List vidStatuses = auditService.getAuditStatuses(uuid, VID).stream().map(x -> x.getJobStatus()).collect(Collectors.toList()); assertThat(vidStatuses, is(expectedStatusesForVid.get(i))); }); - // + + //assert no more jobs to pull assertFalse(jobsBrokerService.pull(PENDING, randomUuid()).isPresent()); assertFalse(jobsBrokerService.pull(JobStatus.IN_PROGRESS, randomUuid()).isPresent()); } @@ -273,8 +303,8 @@ public class AsyncInstantiationIntegrationTest extends AsyncInstantiationBaseTes @DataProvider public static Object[][] AlaCarteStatuses(Method test) { return new Object[][]{ - {COMPLETE_STR, JobStatus.COMPLETED, JobStatus.COMPLETED}, - {FAILED_STR, JobStatus.COMPLETED_WITH_ERRORS, JobStatus.FAILED}, + {COMPLETE_STR, JobStatus.COMPLETED}, + {FAILED_STR, JobStatus.COMPLETED_WITH_ERRORS}, }; } @@ -285,8 +315,8 @@ public class AsyncInstantiationIntegrationTest extends AsyncInstantiationBaseTes Make sure service state is Completed successfully once we got from MSO complete for the vnf job. status Creating */ - //@Test(dataProvider = "AlaCarteStatuses") - public void testStatusesOfServiceDuringALaCarteLifeCycleIgnoringVfModules(String msoVnfStatus, JobStatus expectedServiceStatus, JobStatus expectedVnfStatus) { + @Test(dataProvider = "AlaCarteStatuses") + public void testStatusesOfServiceDuringALaCarteLifeCycleIgnoringVfModules(String msoVnfStatus, JobStatus expectedServiceStatus) { /* [v] + push alacarte with 1 vnf [v] verify STATUS pending @@ -305,6 +335,7 @@ public class AsyncInstantiationIntegrationTest extends AsyncInstantiationBaseTes * not looking on audit (yet) */ + reset(restMso); when(featureManager.isActive(Features.FLAG_ASYNC_ALACARTE_VNF)).thenReturn(true); when(featureManager.isActive(Features.FLAG_ASYNC_ALACARTE_VFMODULE)).thenReturn(false); final String SERVICE_REQUEST_ID = UUID.randomUUID().toString(); @@ -315,39 +346,22 @@ public class AsyncInstantiationIntegrationTest extends AsyncInstantiationBaseTes //push alacarte with 1 vnf, verify STATUS pending UUID uuid = pushALaCarteWithVnf(); singleServicesAndAssertStatus(JobStatus.PENDING, uuid); - //mock mso to answer 200 of create service instance request, verify STATUS in progress - when(restMso.PostForObject(any(), endsWith("serviceInstances"), eq(RequestReferencesContainer.class))).thenReturn( - createResponse(200, SERVICE_INSTANCE_ID, SERVICE_REQUEST_ID)); - pullJobProcessAndPushBackWithTypeAssertion(JobStatus.PENDING, JobStatus.IN_PROGRESS, JobType.InProgressStatus); - singleServicesAndAssertStatus(JobStatus.IN_PROGRESS, uuid); - + when(restMso.restCall(eq(HttpMethod.POST), eq(RequestReferencesContainer.class), any(), endsWith("serviceInstances"), any())).thenReturn( + createResponse(200, SERVICE_INSTANCE_ID, SERVICE_REQUEST_ID)); //mock mso to answer COMPLETE for service instance create, job status shall remain IN_PROGRESS and type shall be Watching - reset(restMso); when(restMso.GetForObject(endsWith(SERVICE_REQUEST_ID), eq(AsyncRequestStatus.class))). - thenReturn(asyncRequestStatusResponseAsRestObject(COMPLETE_STR)); - pullJobProcessAndPushBackWithTypeAssertion(JobStatus.IN_PROGRESS, JobStatus.IN_PROGRESS, JobType.Watching); - singleServicesAndAssertStatus(JobStatus.IN_PROGRESS, uuid); - + thenReturn(asyncRequestStatusResponseAsRestObject(COMPLETE_STR)); //mock mso to answer 200 of create vnf instance request, pull+execute vnf job, STATUS resource in progress - reset(restMso); - when(restMso.PostForObject(any(), endsWith(SERVICE_INSTANCE_ID + "/vnfs"), eq(RequestReferencesContainer.class))).thenReturn( - createResponse(200, UUID.randomUUID().toString(), VNF_REQUEST_ID)); - pullJobProcessAndPushBackWithTypeAssertion(JobStatus.CREATING, JobStatus.RESOURCE_IN_PROGRESS, JobType.VnfInProgressStatus); - - //verify service job STATUS in progress - pullJobProcessAndPushBackWithTypeAssertion(JobStatus.IN_PROGRESS, JobStatus.IN_PROGRESS, JobType.Watching); - singleServicesAndAssertStatus(JobStatus.IN_PROGRESS, uuid); - - //mock mso to answer msoVnfStatus (COMPLETE/FAILED) for vnf creation status, - //job status shall be final (COMPLETE/COMPLETE_WITH_ERRORS) - reset(restMso); + when(restMso.restCall(eq(HttpMethod.POST), eq(RequestReferencesContainer.class), any(), endsWith(SERVICE_INSTANCE_ID + "/vnfs"), any())).thenReturn( + createResponse(200, UUID.randomUUID().toString(), VNF_REQUEST_ID)); when(restMso.GetForObject(endsWith(VNF_REQUEST_ID), eq(AsyncRequestStatus.class))).thenReturn( - asyncRequestStatusResponseAsRestObject(msoVnfStatus)); - pullJobProcessAndPushBack(JobStatus.RESOURCE_IN_PROGRESS, expectedVnfStatus, false); - singleServicesAndAssertStatus(JobStatus.IN_PROGRESS, uuid); - pullJobProcessAndPushBack(JobStatus.IN_PROGRESS, expectedServiceStatus, true); - singleServicesAndAssertStatus(expectedServiceStatus, uuid); + asyncRequestStatusResponseAsRestObject(msoVnfStatus)); + + processJobsCountTimesAndAssertStatus(uuid, 100, expectedServiceStatus); + verify(restMso, times(1)).restCall(eq(HttpMethod.POST), any(), any(), eq("/serviceInstantiation/v7/serviceInstances"), any()); + verify(restMso, times(1)).restCall(eq(HttpMethod.POST), any(), any(), endsWith(SERVICE_INSTANCE_ID + "/vnfs"), any()); + verify(restMso, times(2)).GetForObject(any(), any()); } @@ -361,13 +375,11 @@ public class AsyncInstantiationIntegrationTest extends AsyncInstantiationBaseTes And union these tests to single one. */ - //@Test + @Test public void testALaCarteLifeCycle1Vnf2VfModules() { String msoVnfStatus = COMPLETE_STR; - JobStatus expectedServiceStatus = IN_PROGRESS; - JobStatus expectedVnfStatus = RESOURCE_IN_PROGRESS; when(featureManager.isActive(Features.FLAG_ASYNC_ALACARTE_VNF)).thenReturn(true); when(featureManager.isActive(Features.FLAG_ASYNC_ALACARTE_VFMODULE)).thenReturn(true); final String SERVICE_REQUEST_ID = UUID.randomUUID().toString(); @@ -383,39 +395,27 @@ public class AsyncInstantiationIntegrationTest extends AsyncInstantiationBaseTes //push alacarte with 1 vnf, verify STATUS pending UUID uuid = pushALaCarteWithVnf(); singleServicesAndAssertStatus(JobStatus.PENDING, uuid); + reset(restMso); /*---------- service -----------*/ //mock mso to answer 200 of create service instance request, verify STATUS in progress - when(restMso.PostForObject(any(), endsWith("serviceInstances"), eq(RequestReferencesContainer.class))).thenReturn( - createResponse(200, SERVICE_INSTANCE_ID, SERVICE_REQUEST_ID)); - pullJobProcessAndPushBackWithTypeAssertion(JobStatus.PENDING, JobStatus.IN_PROGRESS, JobType.InProgressStatus); - singleServicesAndAssertStatus(JobStatus.IN_PROGRESS, uuid); + when(restMso.restCall(eq(HttpMethod.POST), eq(RequestReferencesContainer.class), any(), endsWith("serviceInstances"), any())).thenReturn( + createResponse(200, SERVICE_INSTANCE_ID, SERVICE_REQUEST_ID)); - //mock mso to answer COMPLETE for service instance create, job status shall remain IN_PROGRESS and type shall be Watching - reset(restMso); + //mock mso to answer COMPLETE for service instance create when(restMso.GetForObject(endsWith(SERVICE_REQUEST_ID), eq(AsyncRequestStatus.class))). - thenReturn(asyncRequestStatusResponseAsRestObject(COMPLETE_STR)); - pullJobProcessAndPushBackWithTypeAssertion(JobStatus.IN_PROGRESS, JobStatus.IN_PROGRESS, JobType.Watching); - singleServicesAndAssertStatus(JobStatus.IN_PROGRESS, uuid); + thenReturn(asyncRequestStatusResponseAsRestObject(COMPLETE_STR)); /*---------- vnf -----------*/ - //mock mso to answer 200 of create vnf instance request, pull+execute vnf job, STATUS resource in progress - reset(restMso); - when(restMso.PostForObject(any(), endsWith(SERVICE_INSTANCE_ID + "/vnfs"), eq(RequestReferencesContainer.class))).thenReturn( - createResponse(200, VNF_INSTANCE_ID, VNF_REQUEST_ID)); - pullJobProcessAndPushBackWithTypeAssertion(JobStatus.CREATING, JobStatus.RESOURCE_IN_PROGRESS, JobType.VnfInProgressStatus); - - //verify service job STATUS in progress - pullJobProcessAndPushBackWithTypeAssertion(JobStatus.IN_PROGRESS, JobStatus.IN_PROGRESS, JobType.Watching); - singleServicesAndAssertStatus(JobStatus.IN_PROGRESS, uuid); + //mock mso to answer 200 of create vnf instance request + when(restMso.restCall(eq(HttpMethod.POST), eq(RequestReferencesContainer.class), any(), endsWith(SERVICE_INSTANCE_ID + "/vnfs"), any())).thenReturn( + createResponse(200, VNF_INSTANCE_ID, VNF_REQUEST_ID)); //mock mso to answer msoVnfStatus (COMPLETE/FAILED) for vnf creation status, - //job status shall be final (COMPLETE/COMPLETE_WITH_ERRORS) - reset(restMso); when(restMso.GetForObject(endsWith(VNF_REQUEST_ID), eq(AsyncRequestStatus.class))). - thenReturn(asyncRequestStatusResponseAsRestObject(COMPLETE_STR)); + thenReturn(asyncRequestStatusResponseAsRestObject(COMPLETE_STR)); try { reset(commandUtils); @@ -425,113 +425,164 @@ public class AsyncInstantiationIntegrationTest extends AsyncInstantiationBaseTes } - pullJobProcessAndPushBackWithTypeAssertion(JobStatus.RESOURCE_IN_PROGRESS, JobStatus.RESOURCE_IN_PROGRESS, JobType.WatchingBaseModule); - singleServicesAndAssertStatus(JobStatus.IN_PROGRESS, uuid); - pullJobProcessAndPushBack(JobStatus.IN_PROGRESS, JobStatus.IN_PROGRESS, true); - singleServicesAndAssertStatus(JobStatus.IN_PROGRESS, uuid); - /*---------- vf Module without volume group name (base) -----------*/ - //vg name not exist, so vf module created immediately - pullJobProcessAndPushBackWithTypeAssertion(JobStatus.CREATING, JobStatus.RESOURCE_IN_PROGRESS, JobType.Watching); + //mock mso to answer 200 of create vfModule instance request, pull+execute volumeGroup job, STATUS resource in progress + when(restMso.restCall(eq(HttpMethod.POST), eq(RequestReferencesContainer.class), any(), endsWith(SERVICE_INSTANCE_ID + "/vnfs/" + VNF_INSTANCE_ID + "/vfModules"), any())).thenReturn( + createResponse(200, UUID.randomUUID().toString(), VG_REQUEST_ID)); + //mock mso to answer for vf module orchestration request + when(restMso.GetForObject(endsWith(VF_MODULE_REQUEST_ID), eq(AsyncRequestStatus.class))).thenReturn( + asyncRequestStatusResponseAsRestObject(COMPLETE_STR)); + + when(restMso.restCall(eq(HttpMethod.POST), eq(RequestReferencesContainer.class), any(), endsWith(SERVICE_INSTANCE_ID + "/vnfs/" + VNF_INSTANCE_ID + "/volumeGroups"), any())).thenReturn( + createResponse(200, VG_INSTANCE_ID, VG_REQUEST_ID)); + //mock mso to answer for volume group orchestration request + when(restMso.GetForObject(endsWith(VG_REQUEST_ID), eq(AsyncRequestStatus.class))).thenReturn( + asyncRequestStatusResponseAsRestObject(msoVnfStatus)); - //verify vnf/volumeGroup job STATUS still watching with resource in progress - pullMultipleJobsFindExpectedProcessAndPushBack(JobStatus.RESOURCE_IN_PROGRESS, JobType.Watching, JobStatus.RESOURCE_IN_PROGRESS, JobType.Watching); + /*---------- vfModule -----------*/ //mock mso to answer 200 of create vfModule instance request, pull+execute volumeGroup job, STATUS resource in progress - reset(restMso); - when(restMso.PostForObject(any(), endsWith(SERVICE_INSTANCE_ID + "/vnfs/" + VNF_INSTANCE_ID + "/vfModules"), eq(RequestReferencesContainer.class))).thenReturn( - createResponse(200, UUID.randomUUID().toString(), VF_MODULE_REQUEST_ID)); - pullJobProcessAndPushBackWithTypeAssertion(JobStatus.CREATING, JobStatus.RESOURCE_IN_PROGRESS, JobType.ResourceInProgressStatus); + when(restMso.restCall(eq(HttpMethod.POST), eq(RequestReferencesContainer.class), any(), endsWith(SERVICE_INSTANCE_ID + "/vnfs/" + VNF_INSTANCE_ID + "/vfModules"), any())).thenReturn( + createResponse(200, UUID.randomUUID().toString(), VF_MODULE_REQUEST_ID2)); //mock mso to answer for vf module orchestration request - reset(restMso); - when(restMso.GetForObject(endsWith(VF_MODULE_REQUEST_ID), eq(AsyncRequestStatus.class))).thenReturn( - asyncRequestStatusResponseAsRestObject(COMPLETE_STR)); - pullMultipleJobsFindExpectedProcessAndPushBack(JobStatus.RESOURCE_IN_PROGRESS, JobType.ResourceInProgressStatus, JobStatus.COMPLETED, JobType.ResourceInProgressStatus); - - //verify volume group become completed - pullMultipleJobsFindExpectedProcessAndPushBack(JobStatus.RESOURCE_IN_PROGRESS, JobType.Watching, JobStatus.COMPLETED, JobType.Watching); + when(restMso.GetForObject(endsWith(VF_MODULE_REQUEST_ID2), eq(AsyncRequestStatus.class))).thenReturn( + asyncRequestStatusResponseAsRestObject(COMPLETE_STR)); + + processJobsCountTimesAndAssertStatus(uuid, 200, COMPLETED); + verify(restMso, times(1)).restCall(eq(HttpMethod.POST), any(), any(), eq("/serviceInstantiation/v7/serviceInstances"), any()); + verify(restMso, times(1)).restCall(eq(HttpMethod.POST), any(), any(), endsWith(SERVICE_INSTANCE_ID + "/vnfs"), any()); + verify(restMso, times(1)).restCall(eq(HttpMethod.POST), any(), any(), endsWith(SERVICE_INSTANCE_ID + "/vnfs/" + VNF_INSTANCE_ID + "/volumeGroups"), any()); + verify(restMso, times(2)).restCall(eq(HttpMethod.POST), any(), any(), endsWith(SERVICE_INSTANCE_ID + "/vnfs/" + VNF_INSTANCE_ID + "/vfModules"), any()); + verify(restMso, times(5)).GetForObject(any(), any()); + } - //vnf become watching after volume group completed, and new volume group created - pullMultipleJobsFindExpectedProcessAndPushBack(JobStatus.RESOURCE_IN_PROGRESS, JobType.WatchingBaseModule, JobStatus.RESOURCE_IN_PROGRESS, JobType.Watching); + @Test + public void testALaCarteLifeCycle2Networks() { - /*---------- volume group & vf module (non base) -----------*/ + //Create Service with 2 networks, and make sure they created in sequence (and not in parallel) + //Config MSO to response 200 only to first network creation. And answer 500 for second one. + //Then MSO return in_progress some times (like 10 times), and then return COMPLETE. + //Only when MSO return COMPLETE for first network, config MSO to return 200 for second network creation - /*---------- volume group -----------*/ + final String SERVICE_REQUEST_ID = UUID.randomUUID().toString(); + final String SERVICE_INSTANCE_ID = UUID.randomUUID().toString(); + final String NETWORK_REQUEST_ID1 = UUID.randomUUID().toString(); + final String NETWORK_INSTANCE_ID1 = UUID.randomUUID().toString(); + //TODO use them later for different networks + final String NETWORK_REQUEST_ID2 = UUID.randomUUID().toString(); + final String NETWORK_INSTANCE_ID2 = UUID.randomUUID().toString(); - //mock mso to answer 200 of create volumeGroup instance request, pull+execute volumeGroup job, STATUS resource in progress - reset(restMso); - when(restMso.PostForObject(any(), endsWith(SERVICE_INSTANCE_ID + "/vnfs/" + VNF_INSTANCE_ID + "/volumeGroups"), eq(RequestReferencesContainer.class))).thenReturn( - createResponse(200, VG_INSTANCE_ID, VG_REQUEST_ID)); - pullJobProcessAndPushBackWithTypeAssertion(JobStatus.CREATING, JobStatus.RESOURCE_IN_PROGRESS, JobType.VolumeGroupInProgressStatus); - //verify vnf job STATUS still watching with resource in progress - pullMultipleJobsFindExpectedProcessAndPushBack(JobStatus.RESOURCE_IN_PROGRESS, JobType.Watching, JobStatus.RESOURCE_IN_PROGRESS, JobType.Watching); + NetworkDetails networkDetails1 = new NetworkDetails("LukaDoncic", "1"); + NetworkDetails networkDetails2 = new NetworkDetails("KevinDurant", "2"); - //mock mso to answer for volume group orchestration request reset(restMso); - when(restMso.GetForObject(endsWith(VG_REQUEST_ID), eq(AsyncRequestStatus.class))).thenReturn( - asyncRequestStatusResponseAsRestObject(msoVnfStatus)); - pullMultipleJobsFindExpectedProcessAndPushBack(JobStatus.RESOURCE_IN_PROGRESS, JobType.VolumeGroupInProgressStatus, JobStatus.RESOURCE_IN_PROGRESS, JobType.Watching); - /*---------- vfModule -----------*/ + /*---------- service -----------*/ - //mock mso to answer 200 of create vfModule instance request, pull+execute volumeGroup job, STATUS resource in progress - reset(restMso); - when(restMso.PostForObject(any(), endsWith(SERVICE_INSTANCE_ID + "/vnfs/" + VNF_INSTANCE_ID + "/vfModules"), eq(RequestReferencesContainer.class))).thenReturn( - createResponse(200, UUID.randomUUID().toString(), VF_MODULE_REQUEST_ID2)); - pullJobProcessAndPushBackWithTypeAssertion(JobStatus.CREATING, JobStatus.RESOURCE_IN_PROGRESS, JobType.ResourceInProgressStatus); + //mock mso to answer 200 of create service instance request, verify STATUS in progress + when(restMso.restCall(eq(HttpMethod.POST), eq(RequestReferencesContainer.class), any(), endsWith("serviceInstances"), any())).thenReturn( + createResponse(200, SERVICE_INSTANCE_ID, SERVICE_REQUEST_ID)); - //mock mso to answer for vf module orchestration request - reset(restMso); - when(restMso.GetForObject(endsWith(VF_MODULE_REQUEST_ID2), eq(AsyncRequestStatus.class))).thenReturn( - asyncRequestStatusResponseAsRestObject(COMPLETE_STR)); - pullMultipleJobsFindExpectedProcessAndPushBack(JobStatus.RESOURCE_IN_PROGRESS, JobType.ResourceInProgressStatus, JobStatus.COMPLETED, JobType.ResourceInProgressStatus); + //mock mso to answer COMPLETE for service instance create + when(restMso.GetForObject(endsWith(SERVICE_REQUEST_ID), eq(AsyncRequestStatus.class))). + thenReturn(asyncRequestStatusResponseAsRestObject(COMPLETE_STR)); + + final MutableInt secondNetworkCode = new MutableInt(500); + final MutableInt inProgressCount = new MutableInt(0); + + /*---------- network 1-----------*/ + + //mock mso to answer 200 of first create network instance request + when(restMso.restCall(eq(HttpMethod.POST), eq(RequestReferencesContainer.class), + MockitoHamcrest.argThat(jsonPartMatches("requestDetails.requestInfo.instanceName", equalTo(networkDetails1.name))) , + endsWith(SERVICE_INSTANCE_ID + "/networks"), any())).thenReturn( + createResponse(200, NETWORK_INSTANCE_ID1, NETWORK_REQUEST_ID1)); + + //mock mso to answer IN_PROGRESS 10 times, and only then COMPLETE for first network + //Once COMPLETE, second network creation will return 200 + when(restMso.GetForObject(endsWith(NETWORK_REQUEST_ID1), eq(AsyncRequestStatus.class))). + thenAnswer(x->{ + String status; + if (inProgressCount.getValue()<10) { + status = IN_PROGRESS_STR; + } else { + secondNetworkCode.setValue(200); + status = COMPLETE_STR; + } + inProgressCount.add(1); + return asyncRequestStatusResponseAsRestObject(status); + }); + + /*---------- network 2-----------*/ + + //mock MSO to return status code of secondNetworkCode (500 and 200 after first one COMPLETED) + when(restMso.restCall(eq(HttpMethod.POST), eq(RequestReferencesContainer.class), + MockitoHamcrest.argThat(jsonPartMatches("requestDetails.requestInfo.instanceName", equalTo(networkDetails2.name))) , + endsWith(SERVICE_INSTANCE_ID + "/networks"), any())).thenAnswer(x-> + createResponse(secondNetworkCode.intValue(), NETWORK_INSTANCE_ID2, NETWORK_REQUEST_ID2)); + +// when(restMso.restCall(eq(HttpMethod.POST), eq(RequestReferencesContainer.class), any() , endsWith(SERVICE_INSTANCE_ID + "/networks"), any())).thenReturn( +// createResponse(200, NETWORK_INSTANCE_ID1, NETWORK_REQUEST_ID1)); + //mock mso to answer COMPLETE for network creation status, + + when(restMso.GetForObject(endsWith(NETWORK_REQUEST_ID2), eq(AsyncRequestStatus.class))). + thenReturn(asyncRequestStatusResponseAsRestObject(COMPLETE_STR)); + + + /*---------- Create request and process it -----------*/ + //push alacarte with 2 networks, verify STATUS pending + when(featureManager.isActive(Features.FLAG_EXP_CREATE_RESOURCES_IN_PARALLEL)).thenReturn(false); + ServiceInstantiation serviceInstantiation = generateALaCarteWithNetworksPayload(ImmutableList.of(networkDetails1, networkDetails2)); + UUID uuid = asyncInstantiationBL.pushBulkJob(serviceInstantiation, USER_ID).get(0); + singleServicesAndAssertStatus(JobStatus.PENDING, uuid); - //execute twice - 1 for parent volume group, 1 for parent vnf - pullAllJobProcessAndPushBackByType(JobStatus.RESOURCE_IN_PROGRESS, JobType.Watching , JobStatus.COMPLETED); + processJobsCountTimesAndAssertStatus(uuid, 200, COMPLETED); - singleServicesAndAssertStatus(JobStatus.IN_PROGRESS, uuid); - pullJobProcessAndPushBack(JobStatus.IN_PROGRESS, JobStatus.COMPLETED, true); - singleServicesAndAssertStatus(JobStatus.COMPLETED, uuid); + //validate the mso request id is the right one + List serviceInfoList = asyncInstantiationBL.getAllServicesInfo(); + ServiceInfo serviceInfo = serviceInfoList.get(0); + assertThat(serviceInfo.getMsoRequestId(), is(UUID.fromString(SERVICE_REQUEST_ID))); + + /*---------- verify -----------*/ + verify(restMso, times(1)).restCall(eq(HttpMethod.POST), any(), any(), eq("/serviceInstantiation/v7/serviceInstances"), any()); + verify(restMso, times(2)).restCall(eq(HttpMethod.POST), any(), any(), endsWith(SERVICE_INSTANCE_ID + "/networks"), any()); + //get status + verify(restMso, times(1)).GetForObject(endsWith(SERVICE_REQUEST_ID), any()); + verify(restMso, times(11)).GetForObject(endsWith(NETWORK_REQUEST_ID1), any()); + verify(restMso, times(1)).GetForObject(endsWith(NETWORK_REQUEST_ID2), any()); } - //@Test + @Test public void testBadAaiResponseForSearchNamesAndBackToNormal() { when(aaiClient.isNodeTypeExistsByName(any(), any())).thenThrow(aaiNodeQueryBadResponseException()); - pushMacroBulk(); //JOB shall become IN_PROGRESS but service info is still pending - Job job = pullJobProcessAndPushBack(PENDING, JobStatus.IN_PROGRESS, true); - listServicesAndAssertStatus(PENDING, PENDING, job); + when(restMso.restCall(eq(HttpMethod.POST), eq(RequestReferencesContainer.class), any(), any(), eq(Optional.empty()))).thenReturn(createResponse(200)); + when(restMso.GetForObject(any(), eq(AsyncRequestStatus.class))). + thenReturn(asyncRequestStatusResponseAsRestObject(COMPLETE_STR)); - //JOB shall remain in IN_PROGRESS - job = pullJobProcessAndPushBack( JobStatus.IN_PROGRESS, JobStatus.IN_PROGRESS, true); - //make sure the job command is still ServiceInstantiation - assertThat(job.getType(), is(JobType.MacroServiceInstantiation)); - listServicesAndAssertStatus(PENDING, PENDING, job); + List uuids = pushMacroBulk(); + processJobsCountTimesAndAssertStatus(uuids.get(0), 5, IN_PROGRESS, PENDING); //JOB shall become IN_PROGRESS but service info is still pending //simulate AAI back to normal, AAI return name is free, and MSO return good response Mockito.reset(aaiClient); // must forget the "thenThrow" when(aaiClient.isNodeTypeExistsByName(any(), any())).thenReturn(false); - when(restMso.PostForObject(any(),any(), eq(RequestReferencesContainer.class))).thenReturn(createResponse(200)); - job = pullJobProcessAndPushBack( JobStatus.IN_PROGRESS, JobStatus.IN_PROGRESS, true); - listServicesAndAssertStatus(JobStatus.IN_PROGRESS, PENDING, job); + processJobsCountTimesAndAssertStatus(uuids.get(0), 30, COMPLETED, COMPLETED); - //when get job COMPLETE from MSO, service status become COMPLETED - when(restMso.GetForObject(any(), eq(AsyncRequestStatus.class))). - thenReturn(asyncRequestStatusResponseAsRestObject(COMPLETE_STR)); - job = pullJobProcessAndPushBack(JobStatus.IN_PROGRESS, COMPLETED); - listServicesAndAssertStatus(COMPLETED, PENDING, job); } - //@Test + @Test public void testAaiResponseNameUsedTillMaxRetries() { when(aaiClient.isNodeTypeExistsByName(any(), any())).thenReturn(true); + //simulate MSO to return good result, for making sure we failed because of AAI error + when(restMso.restCall(eq(HttpMethod.POST), eq(RequestReferencesContainer.class), any(), any(), eq(Optional.empty()))).thenReturn(createResponse(200)); + when(restMso.GetForObject(any(), eq(AsyncRequestStatus.class))). + thenReturn(asyncRequestStatusResponseAsRestObject(COMPLETE_STR)); + asyncInstantiationBL.setMaxRetriesGettingFreeNameFromAai(10); - pushMacroBulk(); - //JOB shall become IN_PROGRESS but service info is still pending - Job job = pullJobProcessAndPushBack(PENDING, JobStatus.FAILED, true); - listServicesAndAssertStatus(JobStatus.FAILED, JobStatus.STOPPED, job); + List uuids = pushMacroBulk(); + processJobsCountTimesAndAssertStatus(uuids.get(0), 20, FAILED, STOPPED); } private Job pullJobProcessAndPushBack(JobStatus topic, JobStatus expectedNextJobStatus) { @@ -559,22 +610,23 @@ public class AsyncInstantiationIntegrationTest extends AsyncInstantiationBaseTes return job.get(); } + private void simplePullJobProcessAndPushBack(JobStatus topic) { + Optional optionalJob = jobsBrokerService.pull(topic, randomUuid()); + optionalJob.ifPresent(job->{ + Job nextJob = jobWorker.executeJobAndGetNext(job); + jobsBrokerService.pushBack(nextJob); + }); + } + private Job pullJobProcessAndPushBackWithTypeAssertion(JobStatus topic, JobStatus expectedNextJobStatus, - JobType expectedNextJobType) { + JobType expectedNextJobType) { Job job = pullJobProcessAndPushBack(topic, expectedNextJobStatus, false); assertThat("job not ok: " + job.getData(), job.getType(), is(expectedNextJobType)); return job; } private Job pullJobProcessAndPushBackWithTypeAssertion(JobStatus topic, JobStatus expectedNextJobStatus, - JobType expectedNextJobType, int retries) { - return retryWithAssertionsLimit(retries, () -> { - return pullJobProcessAndPushBackWithTypeAssertion(topic, expectedNextJobStatus, expectedNextJobType); - }); - } - - private Job pullJobProcessAndPushBackWithTypeAssertion(JobStatus topic, JobStatus expectedNextJobStatus, - JobType expectedNextJobType, Action actionPhase, InternalState internalState, int retries) { + JobType expectedNextJobType, Action actionPhase, InternalState internalState, int retries) { return retryWithAssertionsLimit(retries, () -> { Job job = pullJobProcessAndPushBackWithTypeAssertion(topic, expectedNextJobStatus, expectedNextJobType); assertThat("job not ok: " + job.getData(), job.getData(), is(jsonPartEquals("actionPhase", actionPhase.name()))); @@ -598,49 +650,11 @@ public class AsyncInstantiationIntegrationTest extends AsyncInstantiationBaseTes // No success: throw new AssertionError("No luck while all of these assertion errors: " + history.stream() - .map(Throwable::getMessage) - .map(s -> s.replace('\n', ' ')) - .map(s -> s.replaceAll("\\s{2,}"," ")) - .distinct() - .collect(joining("\n ", "\n ", "")), history.peek()); - } - - private Job pullMultipleJobsFindExpectedProcessAndPushBack(JobStatus topic, JobType expectedCurrentJobType, JobStatus expectedNextJobStatus, - JobType expectedNextJobType) { - List pulledJobs = new ArrayList<>(); - Job lastJob = null; - while (lastJob == null || lastJob.getType() != expectedCurrentJobType) { - lastJob = pullJob(topic, false).get(); - if (lastJob.getType() != expectedCurrentJobType) { - pulledJobs.add(lastJob); - } - } - - Job nextJob = jobWorker.executeJobAndGetNext(lastJob); - assertThat(nextJob.getStatus(), is(expectedNextJobStatus)); - assertThat(nextJob.getType(), is(expectedNextJobType)); - - jobsBrokerService.pushBack(nextJob); - assertThat(jobsBrokerService.peek(nextJob.getUuid()).getStatus(), is(expectedNextJobStatus)); - - pulledJobs.forEach(job -> - jobsBrokerService.pushBack(job) - ); - - return nextJob; - } - - private void pullAllJobProcessAndPushBackByType(JobStatus topic, JobType commandType, JobStatus expectedFinalStatus) { - Map jobStatusMap = new HashMap<>(); - Optional job = pullJob(topic, false); - for (int i=0; i<1000 && job.isPresent() && job.get().getType() == commandType; i++) { - Job nextJob = jobWorker.executeJobAndGetNext(job.get()); - jobStatusMap.put(nextJob.getUuid(), nextJob.getStatus()); - jobsBrokerService.pushBack(nextJob); - job = jobsBrokerService.pull(topic, UUID.randomUUID().toString()); - } - assertThat(jobStatusMap.values(), everyItem(is(expectedFinalStatus))); - + .map(Throwable::getMessage) + .map(s -> s.replace('\n', ' ')) + .map(s -> s.replaceAll("\\s{2,}"," ")) + .distinct() + .collect(joining("\n ", "\n ", "")), history.peek()); } private Optional pullJob(JobStatus topic, boolean pullingAssertion) { @@ -665,49 +679,37 @@ public class AsyncInstantiationIntegrationTest extends AsyncInstantiationBaseTes } - //@Test + @Test public void whenPushNewBulk_andGetNoResponseFromMsoOnCreation_thenServiceMoveToFailedAndOtherToStopped() { - when(restMso.PostForObject(any(), any(), eq(RequestReferencesContainer.class))).thenReturn(createResponse(500)); - pushBulkPullPendingJobAndAssertJobStatus(JobStatus.FAILED, JobStatus.STOPPED); + when(restMso.restCall(eq(HttpMethod.POST), eq(RequestReferencesContainer.class), any(), any(), eq(Optional.empty()))).thenReturn(createResponse(500)); + //assert that when get ProcessingException from restMso, status remain the same + List uuids = pushMacroBulk(); + processJobsCountTimesAndAssertStatus(uuids.get(0), 30, JobStatus.FAILED, JobStatus.STOPPED); } - //@Test + @Test public void whenMsoStatusIsPendingManualTask_ThenJobStatusIsPaused() { - when(restMso.PostForObject(any(), any(), eq(RequestReferencesContainer.class))).thenReturn(createResponse(200)); - - Job firstJob = pushBulkPullPendingJobAndAssertJobStatus(JobStatus.IN_PROGRESS, PENDING); + when(restMso.restCall(eq(HttpMethod.POST), eq(RequestReferencesContainer.class), any(), any(), eq(Optional.empty()))).thenReturn(createResponse(200)); + when(restMso.GetForObject(any(), eq(AsyncRequestStatus.class))). + thenReturn(asyncRequestStatusResponseAsRestObject(PENDING_MANUAL_TASK)); //assert that when get ProcessingException from restMso, status remain the same - when(restMso.GetForObject(any(), eq(AsyncRequestStatus.class))). - thenReturn(asyncRequestStatusResponseAsRestObject(PENDING_MANUAL_TASK)); - Job job = pullJobProcessAndPushBack(JobStatus.IN_PROGRESS, JobStatus.IN_PROGRESS); - listServicesAndAssertStatus(PAUSE, PENDING, job); + List uuids = pushMacroBulk(); + processJobsCountTimesAndAssertStatus(uuids.get(0), 30, PAUSE, PENDING); - //The paused job is pulled and remain in pause state. Other jobs from bulk remain pending - job = pullJobProcessAndPushBack(JobStatus.IN_PROGRESS, JobStatus.IN_PROGRESS); - listServicesAndAssertStatus(PAUSE, PENDING, job); //the job get IN_PROGRESS response (simulate activate operation) and status changed to IN_PROGRESS when(restMso.GetForObject(any(), eq(AsyncRequestStatus.class))). - thenReturn(asyncRequestStatusResponseAsRestObject(IN_PROGRESS_STR)); - job = pullJobProcessAndPushBack(JobStatus.IN_PROGRESS, JobStatus.IN_PROGRESS); - listServicesAndAssertStatus(JobStatus.IN_PROGRESS, PENDING, job); + thenReturn(asyncRequestStatusResponseAsRestObject(IN_PROGRESS_STR)); + processJobsCountTimesAndAssertStatus(uuids.get(0), 30, IN_PROGRESS, PENDING); + //the job get COMPLETE response this job is copmpleted and then also other jobs when(restMso.GetForObject(any(), eq(AsyncRequestStatus.class))). - thenReturn(asyncRequestStatusResponseAsRestObject(COMPLETE_STR)); - job = pullJobProcessAndPushBack(JobStatus.IN_PROGRESS, COMPLETED); - listServicesAndAssertStatus(COMPLETED, PENDING, job); - - //Pulling PENDING job return another job - assertThat(jobsBrokerService.pull(PENDING, randomUuid()).get().getUuid(), not(equalTo(job.getUuid()))); - - - ImmutableList expectedStatusesForMso = ImmutableList.of(REQUESTED, PENDING_MANUAL_TASK, IN_PROGRESS_STR, COMPLETE_STR); - List msoStatuses = asyncInstantiationBL.getAuditStatuses(firstJob.getUuid(), MSO).stream().map(x -> x.getJobStatus()).collect(Collectors.toList()); - assertThat(msoStatuses, is(expectedStatusesForMso)); + thenReturn(asyncRequestStatusResponseAsRestObject(COMPLETE_STR)); + processJobsCountTimesAndAssertStatus(uuids.get(0), 200, COMPLETED, COMPLETED); ImmutableList expectedStatusesForVid = statusesToStrings(PENDING, IN_PROGRESS, PAUSE, IN_PROGRESS, COMPLETED); - List vidStatuses = asyncInstantiationBL.getAuditStatuses(firstJob.getUuid(), VID).stream().map(x -> x.getJobStatus()).collect(Collectors.toList()); + List vidStatuses = auditService.getAuditStatuses(uuids.get(0), VID).stream().map(x -> x.getJobStatus()).collect(Collectors.toList()); assertThat(vidStatuses, is(expectedStatusesForVid)); } @@ -718,65 +720,76 @@ public class AsyncInstantiationIntegrationTest extends AsyncInstantiationBaseTes private Job pullPendingJobAndAssertJobStatus(JobStatus pulledJobStatus, JobStatus otherJobsStatus) { Job job = pullJobProcessAndPushBack(PENDING, pulledJobStatus, false); - listServicesAndAssertStatus(pulledJobStatus, otherJobsStatus, job); + listServicesAndAssertStatus(pulledJobStatus, otherJobsStatus, job.getUuid()); return job; } - //@Test + @Test public void test2BulksLifeCyclesAreIndependent() { - pushMacroBulk(); - when(restMso.PostForObject(any(), any(), eq(RequestReferencesContainer.class))).thenReturn(createResponse(200)); - //push 2nd job, then when pulling first job the job become in_progress, other jobs (from 2 bulks) remain pending - Job firstJob = pushBulkPullPendingJobAndAssertJobStatus(JobStatus.IN_PROGRESS, PENDING); - //assert we can pull another job from pending from other template id - Job secondJob = pullJobProcessAndPushBack(PENDING, JobStatus.IN_PROGRESS, false); - assertThat(firstJob.getTemplateId(), not(equalTo(secondJob.getTemplateId()))); - - //assert no more PENDING jobs to pull - assertFalse(jobsBrokerService.pull(PENDING, randomUuid()).isPresent()); - - //when get FAILED status from MSO statuses for failed bulk are: FAILED, STOPPED, for other bulk: IN_PROGRESS, 2 pending - when(restMso.GetForObject(any(), eq(AsyncRequestStatus.class))). - thenReturn(asyncRequestStatusResponseAsRestObject(FAILED_STR)); - Job failedJob = pullJobProcessAndPushBack(JobStatus.IN_PROGRESS, JobStatus.FAILED, false); + final String SERVICE1_REQUEST_ID = UUID.randomUUID().toString(); + final String SERVICE1_INSTANCE_ID = UUID.randomUUID().toString(); + final String SERVICE2_REQUEST_ID = UUID.randomUUID().toString(); + final String SERVICE2_INSTANCE_ID = UUID.randomUUID().toString(); + final String SERVICE3_4_REQUEST_ID = UUID.randomUUID().toString(); + final String SERVICE3_4_INSTANCE_ID = UUID.randomUUID().toString(); + + + //create first bulk and make one job in progress + List firstBulksIDs = pushMacroBulk(); + when(restMso.restCall(eq(HttpMethod.POST), eq(RequestReferencesContainer.class), any(), any(), eq(Optional.empty()))) + .thenReturn(createResponse(200, SERVICE1_INSTANCE_ID, SERVICE1_REQUEST_ID)); + when(restMso.GetForObject(endsWith(SERVICE1_REQUEST_ID), eq(AsyncRequestStatus.class))). + thenReturn(asyncRequestStatusResponseAsRestObject(IN_PROGRESS_STR)); + processJobsCountTimesAndAssertStatus(firstBulksIDs.get(0), 30, IN_PROGRESS, PENDING); + + //create 2nd bulk, then when pulling first job the job become in_progress, other jobs (from 2 bulks) remain pending + when(restMso.restCall(eq(HttpMethod.POST), eq(RequestReferencesContainer.class), any(), any(), eq(Optional.empty()))) + .thenReturn(createResponse(200, SERVICE2_INSTANCE_ID, SERVICE2_REQUEST_ID)); + when(restMso.GetForObject(endsWith(SERVICE2_REQUEST_ID), eq(AsyncRequestStatus.class))). + thenReturn(asyncRequestStatusResponseAsRestObject(IN_PROGRESS_STR)); + List secondBulksIDs = pushMacroBulk(); + processJobsCountTimes(30); + Map statusCount = getJobStatusesCount(); + assertThat(statusCount.get(IN_PROGRESS), is(2L)); + assertThat(statusCount.get(PENDING), is(4L)); + + //return failed to first job + //first bulk statuses shall be: FAILED, STOPPED, STOPPED + //second bulk statuses shall be: IN_PROGRESS, PENDING, PENDING + when(restMso.GetForObject(endsWith(SERVICE1_REQUEST_ID), eq(AsyncRequestStatus.class))). + thenReturn(asyncRequestStatusResponseAsRestObject(FAILED_STR)); + processJobsCountTimes(30); Map> servicesByTemplateId = - asyncInstantiationBL.getAllServicesInfo() - .stream().collect(groupingBy(ServiceInfo::getTemplateId)); - assertServicesStatus(servicesByTemplateId.get(failedJob.getTemplateId()), JobStatus.FAILED, JobStatus.STOPPED, failedJob); - Job successJob = failedJob.getUuid().equals(firstJob.getUuid()) ? secondJob : firstJob; - assertServicesStatus(servicesByTemplateId.get(successJob.getTemplateId()), JobStatus.IN_PROGRESS, PENDING, successJob); - - //yet no more PENDING jobs to pull - assertFalse(jobsBrokerService.pull(PENDING, randomUuid()).isPresent()); - - //assert that job from non failed bulk can progress. - //When completed, failed bulk statuses: FAILED, STOPPED. Succeeded bulk statuses are : COMPLETED, 2 pending - when(restMso.GetForObject(any(), eq(AsyncRequestStatus.class))). - thenReturn(asyncRequestStatusResponseAsRestObject(COMPLETE_STR)); - pullJobProcessAndPushBack(JobStatus.IN_PROGRESS, COMPLETED, false); - servicesByTemplateId = - asyncInstantiationBL.getAllServicesInfo() - .stream().collect(groupingBy(ServiceInfo::getTemplateId)); - assertServicesStatus(servicesByTemplateId.get(failedJob.getTemplateId()), JobStatus.FAILED, JobStatus.STOPPED, failedJob); - assertServicesStatus(servicesByTemplateId.get(successJob.getTemplateId()), COMPLETED, PENDING, successJob); - - //advance other jobs of succeeded bulk till al of them reach to COMPLETED - pullJobProcessAndPushBack(PENDING, JobStatus.IN_PROGRESS, false); - pullJobProcessAndPushBack(JobStatus.IN_PROGRESS, COMPLETED, false); - pullJobProcessAndPushBack(PENDING, JobStatus.IN_PROGRESS, false); - pullJobProcessAndPushBack(JobStatus.IN_PROGRESS, COMPLETED, false); - servicesByTemplateId = - asyncInstantiationBL.getAllServicesInfo() - .stream().collect(groupingBy(ServiceInfo::getTemplateId)); - assertServicesStatus(servicesByTemplateId.get(failedJob.getTemplateId()), JobStatus.FAILED, JobStatus.STOPPED, failedJob); - assertServicesStatus(servicesByTemplateId.get(successJob.getTemplateId()), COMPLETED, COMPLETED, successJob); - + asyncInstantiationBL.getAllServicesInfo() + .stream().collect(groupingBy(ServiceInfo::getTemplateId)); + ServiceInfo failedJob = asyncInstantiationBL.getAllServicesInfo().stream().filter(x->x.getJobId().equals(firstBulksIDs.get(0))).findFirst().get(); + assertServicesStatus(servicesByTemplateId.get(failedJob.getTemplateId()), JobStatus.FAILED, JobStatus.STOPPED, failedJob.getJobId()); + ServiceInfo successJob = asyncInstantiationBL.getAllServicesInfo().stream().filter(x->x.getJobId().equals(secondBulksIDs.get(0))).findFirst().get(); + assertServicesStatus(servicesByTemplateId.get(successJob.getTemplateId()), JobStatus.IN_PROGRESS, PENDING, successJob.getJobId()); + + //return completed to all other jobs + when(restMso.restCall(eq(HttpMethod.POST), eq(RequestReferencesContainer.class), any(), any(), eq(Optional.empty()))) + .thenReturn(createResponse(200, SERVICE3_4_INSTANCE_ID, SERVICE3_4_REQUEST_ID)); + when(restMso.GetForObject(endsWith(SERVICE2_REQUEST_ID), eq(AsyncRequestStatus.class))). + thenReturn(asyncRequestStatusResponseAsRestObject(COMPLETE_STR)); + when(restMso.GetForObject(endsWith(SERVICE3_4_REQUEST_ID), eq(AsyncRequestStatus.class))). + thenReturn(asyncRequestStatusResponseAsRestObject(COMPLETE_STR)); + + processJobsCountTimes(30); + servicesByTemplateId = asyncInstantiationBL.getAllServicesInfo().stream().collect(groupingBy(ServiceInfo::getTemplateId)); + assertServicesStatus(servicesByTemplateId.get(failedJob.getTemplateId()), JobStatus.FAILED, JobStatus.STOPPED, failedJob.getJobId()); + assertServicesStatus(servicesByTemplateId.get(successJob.getTemplateId()), COMPLETED, COMPLETED, successJob.getJobId()); //assert no more PENDING jobs nor IN_PROGRESS jobs to pull assertFalse(jobsBrokerService.pull(PENDING, randomUuid()).isPresent()); assertFalse(jobsBrokerService.pull(JobStatus.IN_PROGRESS, randomUuid()).isPresent()); } + protected Map getJobStatusesCount() { + return asyncInstantiationBL.getAllServicesInfo().stream().collect(groupingBy(ServiceInfo::getJobStatus, counting())); + } + + @Test public void deploy2NewGroupsToServiceWith1ExistingGroup() { /* @@ -795,18 +808,7 @@ public class AsyncInstantiationIntegrationTest extends AsyncInstantiationBaseTes [v] + pull+execute (should NOT post to MSO) [v] verify STATUS in progress; TYPE watching ... - [v] verify job#2 *new* GROUP job STATUS completed with no action TYPE group INTERNAL STATE terminal PHASE delete - [v] verify job#3 *new* GROUP job STATUS completed with no action TYPE group INTERNAL STATE terminal PHASE delete - [v] verify job#4 *new* GROUP job STATUS completed with no action TYPE group INTERNAL STATE terminal PHASE delete - [v] + pull+execute job#1 (should NOT post to MSO) - [v] verify STATUS in progress; TYPE watching - [v] verify job#5 *new* GROUP job STATUS creating TYPE group INTERNAL STATE initial PHASE create - [v] verify job#6 *new* GROUP job STATUS creating TYPE group INTERNAL STATE initial PHASE create - [v] verify job#7 *new* GROUP job STATUS creating TYPE group INTERNAL STATE initial PHASE create - - [v] + pull+execute job#5 (should NOT post to MSO) - [v] verify job#5 STATUS completed with no action TYPE group INTERNAL STATE terminal PHASE create [v] + pull+execute job#1 [v] verify job#1 STATUS in progress; TYPE watching @@ -845,70 +847,265 @@ public class AsyncInstantiationIntegrationTest extends AsyncInstantiationBaseTes singleServicesAndAssertStatus(PENDING, uuid); // take from pending, put in-progress -> 3 delete-child were born - pullJobProcessAndPushBackWithTypeAssertion(PENDING, IN_PROGRESS, JobType.ALaCarteService, Action.Delete, InternalState.WATCHING, 1); - verifyQueueSizes(ImmutableMap.of( - IN_PROGRESS, 1, CREATING, 3 - )); - - Stream.of(1, 2, 3).forEach(i -> { - // take each child creating, put in-progress - verify_Job1InProgress.accept(Action.Delete, IN_PROGRESS); - pullJobProcessAndPushBackWithTypeAssertion(CREATING, RESOURCE_IN_PROGRESS, JobType.InstanceGroup, Action.Delete, null, 1); - - // execute each in-progress -> job is completed - verify_Job1InProgress.accept(Action.Delete, IN_PROGRESS); - pullJobProcessAndPushBackWithTypeAssertion(RESOURCE_IN_PROGRESS, COMPLETED/*_WITH_NO_ACTION*/, JobType.InstanceGroup,1); - }); + pullJobProcessAndPushBackWithTypeAssertion(PENDING, IN_PROGRESS, JobType.ALaCarteService, Action.Create, InternalState.INITIAL, 1); verifyQueueSizes(ImmutableMap.of( - IN_PROGRESS, 1, COMPLETED, 3 + IN_PROGRESS, 1 )); // take job #1 from phase delete to phase create -> 3 create-child were born verify_Job1InProgress.accept(Action.Create, IN_PROGRESS); verifyQueueSizes(ImmutableMap.of( - IN_PROGRESS, 1, CREATING, 3, COMPLETED, 3 + IN_PROGRESS, 1, PENDING_RESOURCE, 3 )); // prepare MSO mock - when(restMso.PostForObject(any(), endsWith("instanceGroups"), eq(RequestReferencesContainer.class))) - .thenReturn(createResponse(200, GROUP1_INSTANCE_ID, GROUP1_REQUEST_ID)) - .thenReturn(createResponse(200, GROUP2_INSTANCE_ID, GROUP2_REQUEST_ID)) - .thenReturn(null); + when(restMso.restCall(eq(HttpMethod.POST), eq(RequestReferencesContainer.class), any(), endsWith("instanceGroups"), eq(Optional.empty()))) + .thenReturn(createResponse(200, GROUP1_INSTANCE_ID, GROUP1_REQUEST_ID)) + .thenReturn(createResponse(200, GROUP2_INSTANCE_ID, GROUP2_REQUEST_ID)) + .thenReturn(null); when(restMso.GetForObject(argThat(uri -> StringUtils.endsWithAny(uri, GROUP1_REQUEST_ID, GROUP2_REQUEST_ID)), eq(AsyncRequestStatus.class))). - thenReturn(asyncRequestStatusResponseAsRestObject(COMPLETE_STR)); + thenReturn(asyncRequestStatusResponseAsRestObject(COMPLETE_STR)); - // take first "none" child from creating to completed + // take first "none" child from creating to COMPLETED_WITH_NO_ACTION // note there's no concrete mechanism that makes the first child be - // the "action=None" case, but that's what happens, and following line + // the "action=None" case, but that's what happens, and following lines // relies on that fact. - pullJobProcessAndPushBackWithTypeAssertion(CREATING, COMPLETED_WITH_NO_ACTION, JobType.InstanceGroupInstantiation, 1); + pullJobProcessAndPushBackWithTypeAssertion(PENDING_RESOURCE, COMPLETED_WITH_NO_ACTION, JobType.InstanceGroup, Action.Create, null, 1); // take each of next two children from creating to in-progress, then to completed // verify job #1 is watching, and MSO is getting requests Stream.of(1, 2).forEach(i -> { verify_Job1InProgress.accept(Action.Create, IN_PROGRESS); - pullJobProcessAndPushBackWithTypeAssertion(CREATING, RESOURCE_IN_PROGRESS, JobType.ResourceInProgressStatus); - verify(restMso, times(i)).PostForObject(any(), any(), any()); + pullJobProcessAndPushBackWithTypeAssertion(PENDING_RESOURCE, RESOURCE_IN_PROGRESS, JobType.InstanceGroup, Action.Create, InternalState.IN_PROGRESS, 1); + verify(restMso, times(i)).restCall(any(), any(), any(), any(), any()); verify_Job1InProgress.accept(Action.Create, IN_PROGRESS); - pullJobProcessAndPushBackWithTypeAssertion(RESOURCE_IN_PROGRESS, COMPLETED, JobType.ResourceInProgressStatus); + pullJobProcessAndPushBackWithTypeAssertion(RESOURCE_IN_PROGRESS, COMPLETED, JobType.InstanceGroup, Action.Create, null, 3); verify(restMso, times(i)).GetForObject(any(), any()); }); // job #1 is done as all children are done verify_Job1InProgress.accept(Action.Create, COMPLETED); - verifyQueueSizes(ImmutableMap.of(COMPLETED, 7)); + verifyQueueSizes(ImmutableMap.of(COMPLETED, 3, COMPLETED_WITH_NO_ACTION, 1)); + } + + @DataProvider + public static Object[][] createAndDeleteIntegrationTestDataProvider(Method test) { + return new Object[][]{ + {"create and delete both bad http code", createResponse(400), createResponse(500), null, null, FAILED, 0}, + {"create and delete success and status is success ", createResponseRandomIds(202), createResponseRandomIds(202), + asyncRequestStatusResponseAsRestObject(COMPLETE_STR), asyncRequestStatusResponseAsRestObject(COMPLETE_STR), COMPLETED, 2}, + {"create and delete success, create status FAILED, delete status COMPLETED", createResponseRandomIds(202), createResponseRandomIds(202), + asyncRequestStatusResponseAsRestObject(FAILED_STR), asyncRequestStatusResponseAsRestObject(COMPLETE_STR), COMPLETED_WITH_ERRORS, 2}, + {"create and delete success, create status FAILED, delete status FAILED", createResponseRandomIds(202), createResponseRandomIds(202), + asyncRequestStatusResponseAsRestObject(FAILED_STR), asyncRequestStatusResponseAsRestObject(FAILED_STR), FAILED, 2}, + {"create success but delete failed and status is success ", createResponseRandomIds(202), createResponseRandomIds(400), + asyncRequestStatusResponseAsRestObject(COMPLETE_STR), null, COMPLETED_WITH_ERRORS, 1}, + {"delete success but create failed and status is success ", createResponseRandomIds(400), createResponseRandomIds(202), + null, asyncRequestStatusResponseAsRestObject(COMPLETE_STR), COMPLETED_WITH_ERRORS, 1}, + {"delete success but create failed and status of delete is FAILED ", createResponseRandomIds(400), createResponseRandomIds(202), + null, asyncRequestStatusResponseAsRestObject(FAILED_STR), FAILED, 1} + }; + } + + //this test is going along with AsyncInstantiationALaCarteApiTest.viewEditVnfGroup__verifyStatusAndAudit API test + //The API test has only the happy flow scenario, while this test also test additional MSO responses (mostly non happy) + @Test(dataProvider="createAndDeleteIntegrationTestDataProvider") + public void vnfGropingIntegrationTest( + String desc, + RestObject createGroupResponse, + RestObject deleteGroupResponse, + RestObject createStatusResponse, + RestObject deleteStatusResponse, + JobStatus expectedJobStatus, + int getStatusCounter) throws IOException { + + UUID jobUUID = createAndDeleteIntegrationTest("/payload_jsons/VnfGroupCreate1Delete1None1Request.json", + "/serviceInstantiation/v7/instanceGroups", + createGroupResponse, + "/serviceInstantiation/v7/instanceGroups/VNF_GROUP1_INSTANCE_ID", + deleteGroupResponse, + createStatusResponse, + deleteStatusResponse, + expectedJobStatus, + getStatusCounter); + + ServiceInstantiation bulkForRetry = asyncInstantiationBL.getBulkForRetry(jobUUID); + InstanceGroup vnfGroupShouldBeDeleted = bulkForRetry.getVnfGroups().get("groupingservicefortest..ResourceInstanceGroup..0:001"); + InstanceGroup vnfGroupShouldBeCreated = bulkForRetry.getVnfGroups().get("groupingservicefortest..ResourceInstanceGroup..0"); + + if (deleteStatusResponse == null || deleteStatusResponse.get().request.requestStatus.getRequestState().equals(FAILED_STR)) { + assertThat(vnfGroupShouldBeDeleted.getAction(), equalTo(Action.Delete)); + assertErrorForResource(vnfGroupShouldBeDeleted, deleteGroupResponse, deleteStatusResponse); + } + + if (createStatusResponse == null || createStatusResponse.get().request.requestStatus.getRequestState().equals(FAILED_STR)) { + assertThat(vnfGroupShouldBeCreated.getAction(), equalTo(Action.Create)); + assertErrorForResource(vnfGroupShouldBeCreated, createGroupResponse, createStatusResponse); + } + } + + //this test is going along with AsyncInstantiationALaCarteApiTest3.delete1Create1VnfFromService API test + //The API test has only the happy flow scenario, while this test also test additional MSO responses (mostly non happy) + @Test(dataProvider="createAndDeleteIntegrationTestDataProvider") + public void vnfsIntegrationTest( + String desc, + RestObject createVnfResponse, + RestObject deleteVnfResponse, + RestObject createStatusResponse, + RestObject deleteStatusResponse, + JobStatus expectedJobStatus, + int getStatusCounter) throws IOException { + + createAndDeleteIntegrationTest("/payload_jsons/vnfDelete1Create1Request.json", + "/serviceInstantiation/v7/serviceInstances/f8791436-8d55-4fde-b4d5-72dd2cf13cfb/vnfs", + createVnfResponse, + "/serviceInstantiation/v7/serviceInstances/f8791436-8d55-4fde-b4d5-72dd2cf13cfb/vnfs/VNF_INSTANCE_ID", + deleteVnfResponse, + createStatusResponse, + deleteStatusResponse, + expectedJobStatus, + getStatusCounter); + } + + @Test(dataProvider="createAndDeleteIntegrationTestDataProvider") + public void vfModulesIntegrationTest( + String desc, + RestObject createVfModuleResponse, + RestObject deleteVfModuleResponse, + RestObject createStatusResponse, + RestObject deleteStatusResponse, + JobStatus expectedJobStatus, + int getStatusCounter) throws IOException, AsdcCatalogException { + + when(featureManager.isActive(Features.FLAG_ASYNC_ALACARTE_VFMODULE)).thenReturn(true); + reset(commandUtils); + when(commandUtils.isVfModuleBaseModule("6b528779-44a3-4472-bdff-9cd15ec93450", "f8360508-3f17-4414-a2ed-6bc71161e8db")).thenReturn(true); + when(commandUtils.isVfModuleBaseModule("6b528779-44a3-4472-bdff-9cd15ec93450", "25284168-24bb-4698-8cb4-3f509146eca5")).thenReturn(false); + + createAndDeleteIntegrationTest("/payload_jsons/vfModuleDelete1Create1None1Request.json", + "/serviceInstantiation/v7/serviceInstances/f8791436-8d55-4fde-b4d5-72dd2cf13cfb/vnfs/VNF_INSTANCE_ID/vfModules", + createVfModuleResponse, + "/serviceInstantiation/v7/serviceInstances/f8791436-8d55-4fde-b4d5-72dd2cf13cfb/vnfs/VNF_INSTANCE_ID/vfModules/VF_MODULE_INSTANCE_ID", + deleteVfModuleResponse, + createStatusResponse, + deleteStatusResponse, + expectedJobStatus, + getStatusCounter); + } + + //this test is going along with AsyncInstantiationALaCarteApiTest.delete1Create1NetworkFromService API test + //The API test has only the happy flow scenario, while this test also test additional MSO responses (mostly non happy) + @Test(dataProvider="createAndDeleteIntegrationTestDataProvider") + public void networksIntegrationTest( + String desc, + RestObject createNetworkResponse, + RestObject deleteNetworkResponse, + RestObject createStatusResponse, + RestObject deleteStatusResponse, + JobStatus expectedJobStatus, + int getStatusCounter) throws IOException { + + createAndDeleteIntegrationTest("/payload_jsons/networkDelete1Create1Request.json", + "/serviceInstantiation/v7/serviceInstances/f8791436-8d55-4fde-b4d5-72dd2cf13cfb/networks", + createNetworkResponse, + "/serviceInstantiation/v7/serviceInstances/f8791436-8d55-4fde-b4d5-72dd2cf13cfb/networks/NETWORK_INSTANCE_ID", + deleteNetworkResponse, + createStatusResponse, + deleteStatusResponse, + expectedJobStatus, + getStatusCounter); } + private UUID createAndDeleteIntegrationTest(String payload, + String createPath, + RestObject createResponse, + String deletePath, + RestObject deleteResponse, + RestObject createStatusResponse, + RestObject deleteStatusResponse, + JobStatus expectedJobStatus, + int getStatusCounter) throws IOException { + UUID jobUUID = asyncInstantiationBL.pushBulkJob( + TestUtils.readJsonResourceFileAsObject(payload, ServiceInstantiation.class), "userId") + .get(0); + + when(restMso.restCall(eq(HttpMethod.POST), eq(RequestReferencesContainer.class), any(), eq(createPath), any())).thenReturn(createResponse); + when(restMso.restCall(eq(HttpMethod.DELETE), eq(RequestReferencesContainer.class), any(), eq(deletePath), any())).thenReturn(deleteResponse); + if (createStatusResponse!=null) { + when(restMso.GetForObject(endsWith(createResponse.get().getRequestReferences().getRequestId()), eq(AsyncRequestStatus.class))).thenReturn(createStatusResponse); + } + if (deleteStatusResponse!=null) { + when(restMso.GetForObject(endsWith(deleteResponse.get().getRequestReferences().getRequestId()), eq(AsyncRequestStatus.class))).thenReturn(deleteStatusResponse); + } + + processJobsCountTimesAndAssertStatus(jobUUID, 40, expectedJobStatus); + + verify(restMso, times(1)).restCall(eq(HttpMethod.POST), any(), any(), eq(createPath), any()); + verify(restMso, times(1)).restCall(eq(HttpMethod.DELETE), any(), any(), eq(deletePath), any()); + verify(restMso, times(getStatusCounter)).GetForObject(any(), any()); + + return jobUUID; + } + + @Test + public void whenCreateTransportService_thanExpectedPre1806MacroRequestSent() throws IOException { + UUID jobUUID = asyncInstantiationBL.pushBulkJob(generatePre1806MacroTransportServiceInstantiationPayload(null, null),"az2016").get(0); + RestObject createResponse = createResponseRandomIds(202); + + when(restMso.restCall(eq(HttpMethod.POST), eq(RequestReferencesContainer.class), any(), eq("/serviceInstantiation/v7/serviceInstances"), any())) + .thenReturn(createResponse); + when(restMso.GetForObject(endsWith(createResponse.get().getRequestReferences().getRequestId()), eq(AsyncRequestStatus.class))) + .thenReturn(asyncRequestStatusResponseAsRestObject(COMPLETE_STR)); + processJobsCountTimesAndAssertStatus(jobUUID, 20, COMPLETED); + + JsonNode expectedJson = TestUtils.readJsonResourceFileAsObject("/payload_jsons/pre_1806_macro_without_cloudConfiguration.json", JsonNode.class); + ArgumentCaptor requestCaptor = ArgumentCaptor.forClass(RequestDetailsWrapper.class); + verify(restMso).restCall(any(), any(), requestCaptor.capture(), any(), any()); + requestCaptor.getAllValues().forEach(x->assertJsonEquals(expectedJson, x)); + } + + private void assertErrorForResource(BaseResource resource, + RestObject deleteOrCreateResponse, + RestObject statusResponse) { + JobAuditStatus auditStatus = auditService.getResourceAuditStatus(resource.getTrackById()); + assertThat(auditStatus, is(notNullValue())); + assertThat(auditStatus.getJobStatus(), equalTo(FAILED_STR)); + if (statusResponse == null) { + String errorMessage = "Http Code:" + deleteOrCreateResponse.getStatusCode() + ", " + RAW_DATA_FROM_MSO; + assertThat(auditStatus.getAdditionalInfo(), equalTo(errorMessage)); + assertThat(auditStatus.getRequestId(), is(nullValue())); + } else { + assertThat(auditStatus.getRequestId().toString(), equalTo(statusResponse.get().request.requestId)); + } + } + + protected void processJobsCountTimesAndAssertStatus(UUID serviceJobId, int times, JobStatus expectedStatus) { + processJobsCountTimes(times); + singleServicesAndAssertStatus(expectedStatus, serviceJobId); + } + + private void processJobsCountTimes(int times) { + for (int i = 0; i < times; i++) { + WORKERS_TOPICS.forEach(this::simplePullJobProcessAndPushBack); + } + } + + protected void processJobsCountTimesAndAssertStatus(UUID serviceJobId, int times, JobStatus expectedStatus, JobStatus otherJobsStatus) { + processJobsCountTimes(times); + listServicesAndAssertStatus(expectedStatus, otherJobsStatus, serviceJobId); + } + + private void verifyQueueSizes(ImmutableMap expected) { final Collection peek = jobsBrokerService.peek(); final Map jobTypes = peek.stream().collect(groupingBy(Job::getStatus, counting())); - assertThat(jobTypes, is(expected)); + assertThat(jobTypes, jsonEquals(expected)); } - private List listServicesAndAssertStatus(JobStatus pulledJobStatus, JobStatus otherJobsStatus, Job job) { + private List listServicesAndAssertStatus(JobStatus pulledJobStatus, JobStatus otherJobsStatus, UUID jobUUID) { List serviceInfoList = asyncInstantiationBL.getAllServicesInfo(); - assertServicesStatus(serviceInfoList, pulledJobStatus, otherJobsStatus, job); + assertServicesStatus(serviceInfoList, pulledJobStatus, otherJobsStatus, jobUUID); return serviceInfoList; } @@ -922,9 +1119,15 @@ public class AsyncInstantiationIntegrationTest extends AsyncInstantiationBaseTes return serviceInfo; } - private void assertServicesStatus(List serviceInfoList, JobStatus pulledJobStatus, JobStatus otherJobsStatus, Job job) { + private boolean isServiceOnStatus(JobStatus expectedStatus) { + List serviceInfoList = asyncInstantiationBL.getAllServicesInfo(); + assertEquals(1, serviceInfoList.size()); + return serviceInfoList.get(0).getJobStatus()==expectedStatus; + } + + private void assertServicesStatus(List serviceInfoList, JobStatus pulledJobStatus, JobStatus otherJobsStatus, UUID jobUUID) { serviceInfoList.forEach(si->{ - if (si.getJobId().equals(job.getUuid())) { + if (si.getJobId().equals(jobUUID)) { assertThat(si.getJobStatus(), is(pulledJobStatus)); } else { @@ -935,11 +1138,104 @@ public class AsyncInstantiationIntegrationTest extends AsyncInstantiationBaseTes private void listServicesAndAssertStatus(Map expectedJobStatusMap) { Map actualStatuses = asyncInstantiationBL.getAllServicesInfo() - .stream().collect(Collectors.toMap(ServiceInfo::getJobId, ServiceInfo::getJobStatus)); + .stream().collect(Collectors.toMap(ServiceInfo::getJobId, ServiceInfo::getJobStatus)); assertThat(actualStatuses.entrySet(), equalTo(expectedJobStatusMap.entrySet())); } private String randomUuid() { return UUID.randomUUID().toString(); } + + @Test + public void whenResumeService_thanExpectedResumeRequestSent() throws IOException { + String instanceId = "a565e6ad-75d1-4493-98f1-33234b5c17e2"; //from feRequestResumeMacroService.json + String originalRequestId = "894089b8-f7f4-418d-81da-34186fd32670"; //from msoResponseGetRequestsOfServiceInstance.json + String resumeRequestId = randomUuid(); + String userId = TestUtils.generateRandomAlphaNumeric(6); + + //prepare mocks for get all requests for instance id + RestObject getRequestByIdResponse = createAsyncRequestStatusListByInstanceId(); + when(restMso.GetForObject( + eq("/orchestrationRequests/v7?filter=serviceInstanceId:EQUALS:" + instanceId), + eq(AsyncRequestStatusList.class))) + .thenReturn(getRequestByIdResponse); + + //prepare mocks resume request + when(restMso.restCall(eq(HttpMethod.POST), eq(RequestReferencesContainer.class), isNull(), eq(String.format("/orchestrationRequests/v7/%s/resume", originalRequestId)), eq(Optional.of(userId)))) + .thenReturn(createResponse(202, instanceId, resumeRequestId)); + + //prepare mocks for get resume status + when(restMso.GetForObject(eq("/orchestrationRequests/v7/" + resumeRequestId), eq(AsyncRequestStatus.class))) + .thenReturn(asyncRequestStatusResponseAsRestObject(IN_PROGRESS_STR), + asyncRequestStatusResponseAsRestObject(IN_PROGRESS_STR), + asyncRequestStatusResponseAsRestObject(COMPLETE_STR)); + + + UUID jobUUID = asyncInstantiationBL.pushBulkJob(generateResumeMacroPayload(), userId).get(0); + processJobsCountTimesAndAssertStatus(jobUUID, 20, COMPLETED); + verify(restMso).GetForObject( + eq("/orchestrationRequests/v7?filter=serviceInstanceId:EQUALS:" + instanceId), + eq(AsyncRequestStatusList.class)); + verify(restMso).restCall(eq(HttpMethod.POST), eq(RequestReferencesContainer.class), isNull(), eq(String.format("/orchestrationRequests/v7/%s/resume", originalRequestId)), eq(Optional.of(userId))); + verify(restMso, times(3)).GetForObject(eq("/orchestrationRequests/v7/" + resumeRequestId), eq(AsyncRequestStatus.class)); + } + + @Test + public void givenResumeRequest_whenMsoReturnBadResponse_thanJobIsFailed() throws IOException { + //there is no mocks for restMSO which means restMso return bad response... + UUID jobUUID = asyncInstantiationBL.pushBulkJob(generateResumeMacroPayload(), "abc").get(0); + processJobsCountTimesAndAssertStatus(jobUUID, 20, FAILED); + } + + @NotNull + private RestObject createAsyncRequestStatusListByInstanceId() throws IOException { + AsyncRequestStatusList asyncRequestStatusList = TestUtils.readJsonResourceFileAsObject( + "/payload_jsons/resume/msoResponseGetRequestsOfServiceInstance.json", + AsyncRequestStatusList.class); + RestObject getRequestByIdResponse = new RestObject<>(); + getRequestByIdResponse.set(asyncRequestStatusList); + getRequestByIdResponse.setStatusCode(200); + return getRequestByIdResponse; + } + + private ServiceInstantiation generateResumeMacroPayload() throws IOException { + return TestUtils.readJsonResourceFileAsObject("/payload_jsons/resume/feRequestResumeMacroService.json", ServiceInstantiation.class); + } + + @Test + public void whenUpgradingAvfModule_thanExpectedReplaceRequestSent() throws IOException { + String instanceId = "5d49c3b1-fc90-4762-8c98-e800170baa55"; //from feRequestResumeMacroService.json + String replaceRequestId = randomUuid(); + String userId = "az2016"; + + + //prepare mocks resume request + when(restMso.restCall(eq(HttpMethod.POST), eq(RequestReferencesContainer.class), any(), eq("/serviceInstantiation/v7/serviceInstances/e9993045-cc96-4f3f-bf9a-71b2a400a956/vnfs/5c9c2896-1fe6-4055-b7ec-d0a01e5f9bf5/vfModules/5d49c3b1-fc90-4762-8c98-e800170baa55/replace"), eq(Optional.of(userId)))) + .thenReturn(createResponse(202, instanceId, replaceRequestId)); + + + when(restMso.GetForObject(eq("/orchestrationRequests/v7/" + replaceRequestId), eq(AsyncRequestStatus.class))) + .thenReturn(asyncRequestStatusResponseAsRestObject(IN_PROGRESS_STR), + asyncRequestStatusResponseAsRestObject(IN_PROGRESS_STR), + asyncRequestStatusResponseAsRestObject(COMPLETE_STR)); + + ///orchestrationRequests/v7/0174b25a-dd81-45b7-b4af-0057bcc30857 + + when(featureManager.isActive(Features.FLAG_ASYNC_ALACARTE_VFMODULE)).thenReturn(true); + enableAddCloudOwnerOnMsoRequest(); + + UUID jobUUID = asyncInstantiationBL.pushBulkJob(generateReplaceVfModulePayload(), userId).get(0); + processJobsCountTimesAndAssertStatus(jobUUID, 20, COMPLETED); + + + + JsonNode expectedJson = TestUtils.readJsonResourceFileAsObject("/payload_jsons/vfmodule/replace_vfmodule.json", JsonNode.class); + ArgumentCaptor requestCaptor = ArgumentCaptor.forClass(RequestDetailsWrapper.class); + verify(restMso).restCall(eq(HttpMethod.POST), eq(RequestReferencesContainer.class), requestCaptor.capture(), eq("/serviceInstantiation/v7/serviceInstances/e9993045-cc96-4f3f-bf9a-71b2a400a956/vnfs/5c9c2896-1fe6-4055-b7ec-d0a01e5f9bf5/vfModules/5d49c3b1-fc90-4762-8c98-e800170baa55/replace"), eq(Optional.of(userId))); + requestCaptor.getAllValues().forEach(x->assertJsonEquals(expectedJson, x)); + } + + private ServiceInstantiation generateReplaceVfModulePayload() throws IOException { + return TestUtils.readJsonResourceFileAsObject("/payload_jsons/vfmodule/replace_vfmodule_fe_input.json", ServiceInstantiation.class); + } } diff --git a/vid-app-common/src/test/java/org/onap/vid/job/impl/DeleteOldJobsSchedulerInitializerTest.java b/vid-app-common/src/test/java/org/onap/vid/job/impl/DeleteOldJobsSchedulerInitializerTest.java new file mode 100644 index 000000000..4944efa69 --- /dev/null +++ b/vid-app-common/src/test/java/org/onap/vid/job/impl/DeleteOldJobsSchedulerInitializerTest.java @@ -0,0 +1,55 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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.vid.job.impl; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.matchesPattern; +import static org.mockito.Mockito.mock; +import static org.onap.vid.testUtils.TestUtils.testWithSystemProperty; +import static org.testng.Assert.assertEquals; + +import org.onap.vid.job.JobsBrokerService; +import org.quartz.JobDetail; +import org.quartz.impl.triggers.CronTriggerImpl; +import org.testng.annotations.Test; + +public class DeleteOldJobsSchedulerInitializerTest { + + @Test + public void testCreateJobDetail() throws Exception { + testWithSystemProperty("vid.asyncJob.howLongToKeepOldJobsInDays", "7", ()-> { + JobsBrokerService mockBroker = mock(JobsBrokerService.class); + DeleteOldJobsSchedulerInitializer underTest = new DeleteOldJobsSchedulerInitializer(mockBroker, null); + JobDetail jobDetail = underTest.createJobDetail(); + assertEquals(DeleteOldJobsWorker.class, jobDetail.getJobClass()); + assertEquals(mockBroker, jobDetail.getJobDataMap().get("jobsBrokerService")); + assertEquals(604800L, jobDetail.getJobDataMap().get("secondsAgo")); + }); + } + + @Test + public void testCreateTrigger() { + DeleteOldJobsSchedulerInitializer underTest = new DeleteOldJobsSchedulerInitializer(null, null); + CronTriggerImpl trigger = (CronTriggerImpl) underTest.createTrigger(); + assertThat(trigger.getCronExpression(), matchesPattern("0 [1-5]?[0-9] 6 \\? \\* \\*")); + } + +} \ No newline at end of file diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/ALaCarteServiceInstantiationCommand.java b/vid-app-common/src/test/java/org/onap/vid/job/impl/DeleteOldJobsWorkerTest.java similarity index 52% rename from vid-app-common/src/main/java/org/onap/vid/job/command/ALaCarteServiceInstantiationCommand.java rename to vid-app-common/src/test/java/org/onap/vid/job/impl/DeleteOldJobsWorkerTest.java index 38d5ede8a..229e0cab1 100644 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/ALaCarteServiceInstantiationCommand.java +++ b/vid-app-common/src/test/java/org/onap/vid/job/impl/DeleteOldJobsWorkerTest.java @@ -7,9 +7,9 @@ * 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. @@ -18,24 +18,26 @@ * ============LICENSE_END========================================================= */ -package org.onap.vid.job.command; +package org.onap.vid.job.impl; -import org.onap.vid.changeManagement.RequestDetailsWrapper; -import org.onap.vid.job.JobCommand; -import org.onap.vid.mso.model.ServiceInstantiationRequestDetails; -import org.springframework.beans.factory.config.ConfigurableBeanFactory; -import org.springframework.context.annotation.Scope; -import org.springframework.stereotype.Component; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import org.onap.vid.job.JobsBrokerService; +import org.quartz.JobExecutionException; +import org.testng.annotations.Test; -@Component -@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) -public class ALaCarteServiceInstantiationCommand extends ServiceInstantiationCommand implements JobCommand { +public class DeleteOldJobsWorkerTest { - @Override - protected RequestDetailsWrapper generateServiceInstantiationRequest() { - return asyncInstantiationBL.generateALaCarteServiceInstantiationRequest( - getSharedData().getJobUuid(), getRequest(), optimisticUniqueServiceInstanceName, getSharedData().getUserId() - ); + @Test + public void whenExecuteInternal_thenCallToDeleteOldFinalJobs() throws JobExecutionException { + JobsBrokerService mockBroker = mock(JobsBrokerService.class); + long secondsAgo = 42L; + DeleteOldJobsWorker underTest = new DeleteOldJobsWorker(); + underTest.setJobsBrokerService(mockBroker); + underTest.setSecondsAgo(secondsAgo); + underTest.executeInternal(null); + verify(mockBroker).deleteOldFinalJobs(secondsAgo); } + } diff --git a/vid-app-common/src/test/java/org/onap/vid/job/impl/JobAdapterTest.java b/vid-app-common/src/test/java/org/onap/vid/job/impl/JobAdapterTest.java index f6785c37d..4e11b7e8b 100644 --- a/vid-app-common/src/test/java/org/onap/vid/job/impl/JobAdapterTest.java +++ b/vid-app-common/src/test/java/org/onap/vid/job/impl/JobAdapterTest.java @@ -7,9 +7,9 @@ * 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. @@ -26,10 +26,15 @@ import org.onap.vid.job.Job; import org.onap.vid.job.JobAdapter; import org.onap.vid.job.JobType; import org.onap.vid.job.command.JobCommandFactoryTest; +import org.onap.vid.properties.Features; +import org.onap.vid.testUtils.TestUtils; import org.testng.annotations.Test; +import org.togglz.core.manager.FeatureManager; import java.util.UUID; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotEquals; import static org.testng.AssertJUnit.assertNotNull; @@ -38,12 +43,14 @@ public class JobAdapterTest { @Test public void testCreateServiceInstantiationJob() { - JobAdapter jobAdapter = new JobAdapterImpl(); + FeatureManager featureManager = mock(FeatureManager.class); + JobAdapter jobAdapter = new JobAdapterImpl(featureManager); JobType jobType = JobType.NoOp; JobAdapter.AsyncJobRequest request = new JobCommandFactoryTest.MockedRequest(42,"nothing"); UUID templateId = UUID.randomUUID(); String userId = "ou012t"; + String testApi = "VNF_API"; String optimisticUniqueServiceInstanceName = "optimisticUniqueServiceInstanceName"; int indexInBulk = RandomUtils.nextInt(); Job job = jobAdapter.createServiceInstantiationJob( @@ -51,6 +58,7 @@ public class JobAdapterTest { request, templateId, userId, + testApi, optimisticUniqueServiceInstanceName, indexInBulk ); @@ -59,6 +67,7 @@ public class JobAdapterTest { assertEquals(job.getSharedData().getRequest(), request); assertEquals(job.getSharedData().getRequestType(), request.getClass()); assertEquals(job.getSharedData().getUserId(), userId); + assertEquals(job.getSharedData().getTestApi(), testApi); assertEquals(job.getSharedData().getJobUuid(), job.getUuid()); assertEquals(job.getSharedData().getRootJobId(), job.getUuid()); assertNotNull(job.getUuid()); @@ -68,13 +77,16 @@ public class JobAdapterTest { assertEquals(job.getStatus(), Job.JobStatus.PENDING); } - @Test - public void testCreateChildJob() { - - JobAdapter jobAdapter = new JobAdapterImpl(); + @Test(dataProvider = "trueAndFalse", dataProviderClass = TestUtils.class) + public void testCreateChildJob(boolean isFlagExpCreateResourcesInParallel) { + FeatureManager featureManager = mock(FeatureManager.class); + when(featureManager.isActive(Features.FLAG_EXP_CREATE_RESOURCES_IN_PARALLEL)).thenReturn(isFlagExpCreateResourcesInParallel); + Job.JobStatus expectedJobStatus = isFlagExpCreateResourcesInParallel ? Job.JobStatus.CREATING : Job.JobStatus.PENDING_RESOURCE; + JobAdapter jobAdapter = new JobAdapterImpl(featureManager); UUID templateId = UUID.randomUUID(); String userId = "ou012t"; + String testApi = "VNF_API"; String optimisticUniqueServiceInstanceName = "optimisticUniqueServiceInstanceName"; int indexInBulk = RandomUtils.nextInt(); Job grandJob = jobAdapter.createServiceInstantiationJob( @@ -82,39 +94,44 @@ public class JobAdapterTest { new JobCommandFactoryTest.MockedRequest(99, "anything"), templateId, userId, + testApi, optimisticUniqueServiceInstanceName, indexInBulk ); - Job.JobStatus jobStatus = Job.JobStatus.PAUSE; JobType jobType = JobType.NoOp; JobAdapter.AsyncJobRequest request = new JobCommandFactoryTest.MockedRequest(42,"nothing"); - Job parentJob = jobAdapter.createChildJob(jobType, jobStatus, request, grandJob.getSharedData(), ImmutableMap.of()); + Job parentJob = jobAdapter.createChildJob(jobType, request, grandJob.getSharedData(), ImmutableMap.of(), 1); assertEquals(parentJob.getType(), jobType); assertEquals(parentJob.getSharedData().getRequest(), request); assertEquals(parentJob.getSharedData().getRequestType(), request.getClass()); assertEquals(parentJob.getSharedData().getUserId(), userId); + assertEquals(parentJob.getSharedData().getTestApi(), testApi); assertEquals(parentJob.getSharedData().getJobUuid(), parentJob.getUuid()); assertNotNull(parentJob.getUuid()); assertNotEquals(parentJob.getUuid(), grandJob.getUuid()); - assertEquals(parentJob.getStatus(), jobStatus); + assertEquals(parentJob.getStatus(), expectedJobStatus); + assertEquals(parentJob.getTemplateId(), grandJob.getUuid()); + assertEquals(parentJob.getIndexInBulk().intValue(), 1); assertEquals(parentJob.getSharedData().getRootJobId(), grandJob.getUuid()); - Job.JobStatus jobStatus2 = Job.JobStatus.IN_PROGRESS; JobType jobType2 = JobType.AggregateState; JobAdapter.AsyncJobRequest request2 = new JobCommandFactoryTest.MockedRequest(66,"abc"); - Job job = jobAdapter.createChildJob(jobType2, jobStatus2, request2, parentJob.getSharedData(), ImmutableMap.of()); + Job job = jobAdapter.createChildJob(jobType2, request2, parentJob.getSharedData(), ImmutableMap.of(), 0); assertEquals(job.getType(), jobType2); assertEquals(job.getSharedData().getRequest(), request2); assertEquals(job.getSharedData().getRequestType(), request2.getClass()); assertEquals(job.getSharedData().getUserId(), userId); + assertEquals(job.getSharedData().getTestApi(), testApi); assertEquals(job.getSharedData().getJobUuid(), job.getUuid()); assertNotNull(job.getUuid()); assertNotEquals(job.getUuid(), parentJob.getUuid()); - assertEquals(job.getStatus(), jobStatus2); + assertEquals(job.getStatus(), expectedJobStatus); assertEquals(job.getSharedData().getRootJobId(), grandJob.getUuid()); + assertEquals(job.getTemplateId(), parentJob.getUuid()); + assertEquals(job.getIndexInBulk().intValue(), 0); } } diff --git a/vid-app-common/src/test/java/org/onap/vid/job/impl/JobWorkerTest.java b/vid-app-common/src/test/java/org/onap/vid/job/impl/JobWorkerTest.java index dc44d1520..e234ee969 100644 --- a/vid-app-common/src/test/java/org/onap/vid/job/impl/JobWorkerTest.java +++ b/vid-app-common/src/test/java/org/onap/vid/job/impl/JobWorkerTest.java @@ -7,9 +7,9 @@ * 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. @@ -33,6 +33,7 @@ import org.onap.vid.job.command.HttpCallCommand; import org.onap.vid.job.command.JobCommandFactory; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; +import org.togglz.core.manager.FeatureManager; import java.util.Map; import java.util.UUID; @@ -51,6 +52,9 @@ public class JobWorkerTest { @Mock private JobCommandFactory jobCommandFactory; + @Mock + private FeatureManager featureManager; + private final JobCommand jobCommand = mock(JobCommand.class); private Job jobUnderTest; private JobAdapter.AsyncJobRequest originalData; @@ -68,11 +72,12 @@ public class JobWorkerTest { }; originalType = JobType.MacroServiceInstantiation; - jobUnderTest = new JobAdapterImpl().createServiceInstantiationJob( + jobUnderTest = new JobAdapterImpl(featureManager).createServiceInstantiationJob( originalType, originalData, UUID.randomUUID(), "my user id", + "VNF_API", "optimisticUniqueServiceInstanceName", RandomUtils.nextInt() ); @@ -119,4 +124,4 @@ public class JobWorkerTest { assertThat(nextJob, jobMatcher); assertThat(jobAfter, equalTo(jobBefore)); } -} +} \ No newline at end of file diff --git a/vid-app-common/src/test/java/org/onap/vid/model/JobAuditStatusTest.java b/vid-app-common/src/test/java/org/onap/vid/model/JobAuditStatusTest.java index 2c41120ad..2f9e31ea6 100644 --- a/vid-app-common/src/test/java/org/onap/vid/model/JobAuditStatusTest.java +++ b/vid-app-common/src/test/java/org/onap/vid/model/JobAuditStatusTest.java @@ -35,11 +35,11 @@ public class JobAuditStatusTest { @DataProvider public static Object[][] AdditionalInfoSizes() { return new Object[][]{ - {5, 5}, - {1999,1999}, - {2000, 2000}, - {2001, 2000}, - {10000, 2000} + {5, 5}, + {1999,1999}, + {2000, 2000}, + {2001, 2000}, + {10000, 2000} }; } @@ -53,7 +53,7 @@ public class JobAuditStatusTest { @Test(dataProvider = "AdditionalInfoSizes") public void testAdditionalInfoMaxLengthInConstructor(int originalSize, int finalSize) { final String additionalInfo = StringUtils.repeat("a", originalSize); - JobAuditStatus jobAuditStatus = new JobAuditStatus(UUID.randomUUID(), "myJobStatus", JobAuditStatus.SourceStatus.MSO, UUID.randomUUID(), additionalInfo, new Date()); + JobAuditStatus jobAuditStatus = JobAuditStatus.createForTest(UUID.randomUUID(), "myJobStatus", JobAuditStatus.SourceStatus.MSO, UUID.randomUUID(), additionalInfo, new Date()); assertThat(jobAuditStatus.getAdditionalInfo().length(), is(finalSize)); } diff --git a/vid-app-common/src/test/java/org/onap/vid/model/aaiTree/VpnBindingKtTest.kt b/vid-app-common/src/test/java/org/onap/vid/model/aaiTree/VpnBindingKtTest.kt new file mode 100644 index 000000000..90c61d759 --- /dev/null +++ b/vid-app-common/src/test/java/org/onap/vid/model/aaiTree/VpnBindingKtTest.kt @@ -0,0 +1,16 @@ +package org.onap.vid.model.aaiTree + +import org.testng.Assert.assertEquals +import org.testng.annotations.Test + +class VpnBindingKtTest { + + @Test + fun whenFailedToParseRouteTarget_DefaultValuesAreReturned() { + val aaiTreeNode = AAITreeNode(); + aaiTreeNode.type = NodeType.VPN_BINDING + aaiTreeNode.additionalProperties["route-targets"] = 3 //just an object that can't be parsed into list of route targets + val vpnBinding = from(aaiTreeNode); + assertEquals(vpnBinding.routeTargets, listOf(RouteTarget("ParsingFailure", "ParsingFailure"))) + } +} \ No newline at end of file diff --git a/vid-app-common/src/test/java/org/onap/vid/mso/MsoBusinessLogicImplTest.java b/vid-app-common/src/test/java/org/onap/vid/mso/MsoBusinessLogicImplTest.java index 207e63579..4ddbc0f41 100644 --- a/vid-app-common/src/test/java/org/onap/vid/mso/MsoBusinessLogicImplTest.java +++ b/vid-app-common/src/test/java/org/onap/vid/mso/MsoBusinessLogicImplTest.java @@ -21,91 +21,83 @@ package org.onap.vid.mso; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.assertj.core.api.Assertions.tuple; +import static org.hamcrest.Matchers.allOf; +import static org.hamcrest.Matchers.hasEntry; +import static org.junit.Assert.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.ArgumentMatchers.endsWith; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.isA; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; +import static org.onap.vid.controller.MsoController.CONFIGURATION_ID; +import static org.onap.vid.controller.MsoController.REQUEST_TYPE; +import static org.onap.vid.controller.MsoController.SVC_INSTANCE_ID; +import static org.onap.vid.controller.MsoController.VNF_INSTANCE_ID; +import static org.onap.vid.mso.MsoBusinessLogicImpl.validateEndpointPath; + import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.collect.Lists; import com.google.gson.Gson; import io.joshworks.restclient.http.HttpResponse; +import java.io.IOException; +import java.net.URL; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.stream.Collectors; +import javax.ws.rs.BadRequestException; import org.apache.commons.io.IOUtils; import org.jetbrains.annotations.NotNull; -import org.mockito.hamcrest.MockitoHamcrest; -import org.onap.vid.changeManagement.WorkflowRequestDetail; -import org.onap.vid.model.SOWorkflowList; -import org.onap.vid.model.probes.ExternalComponentStatus; -import org.onap.vid.mso.rest.RequestList; -import org.onap.vid.mso.rest.RequestWrapper; -import org.springframework.test.context.testng.AbstractTestNGSpringContextTests; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; import org.mockito.ArgumentMatcher; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import org.mockito.hamcrest.MockitoHamcrest; import org.onap.portalsdk.core.util.SystemProperties; import org.onap.vid.changeManagement.ChangeManagementRequest; +import org.onap.vid.changeManagement.WorkflowRequestDetail; import org.onap.vid.controller.OperationalEnvironmentController; import org.onap.vid.exceptions.GenericUncheckedException; -import org.onap.vid.model.RequestReferencesContainer; +import org.onap.vid.model.SOWorkflowList; import org.onap.vid.model.SoftDeleteRequest; +import org.onap.vid.model.probes.ExternalComponentStatus; import org.onap.vid.mso.model.CloudConfiguration; import org.onap.vid.mso.model.ModelInfo; import org.onap.vid.mso.model.OperationalEnvironmentActivateInfo; import org.onap.vid.mso.model.OperationalEnvironmentDeactivateInfo; import org.onap.vid.mso.model.RequestInfo; import org.onap.vid.mso.model.RequestParameters; -import org.onap.vid.mso.model.RequestReferences; import org.onap.vid.mso.rest.OperationalEnvironment.OperationEnvironmentRequestDetails; import org.onap.vid.mso.rest.Request; import org.onap.vid.mso.rest.RequestDetails; import org.onap.vid.mso.rest.RequestDetailsWrapper; +import org.onap.vid.mso.rest.RequestList; +import org.onap.vid.mso.rest.RequestWrapper; import org.onap.vid.mso.rest.Task; -import org.onap.vid.properties.Features; import org.springframework.http.HttpStatus; import org.springframework.test.context.ContextConfiguration; -import org.togglz.core.manager.FeatureManager; - -import javax.ws.rs.BadRequestException; -import java.io.IOException; -import java.net.URL; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.UUID; -import java.util.stream.Collectors; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.tuple; -import static org.assertj.core.api.Assertions.assertThatExceptionOfType; -import static org.hamcrest.Matchers.allOf; -import static org.hamcrest.Matchers.hasEntry; -import static org.junit.Assert.assertEquals; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyBoolean; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.argThat; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.ArgumentMatchers.isA; -import static org.mockito.ArgumentMatchers.endsWith; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.mock; -import static org.onap.vid.controller.MsoController.CONFIGURATION_ID; -import static org.onap.vid.controller.MsoController.REQUEST_TYPE; -import static org.onap.vid.controller.MsoController.SVC_INSTANCE_ID; -import static org.onap.vid.controller.MsoController.VNF_INSTANCE_ID; -import static org.onap.vid.mso.MsoBusinessLogicImpl.validateEndpointPath; +import org.springframework.test.context.testng.AbstractTestNGSpringContextTests; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; @ContextConfiguration(classes = {SystemProperties.class}) public class MsoBusinessLogicImplTest extends AbstractTestNGSpringContextTests { private static final ObjectMapper objectMapper = new ObjectMapper(); - @Mock - private FeatureManager featureManager; - @Mock private MsoInterface msoInterface; @@ -126,7 +118,7 @@ public class MsoBusinessLogicImplTest extends AbstractTestNGSpringContextTests { @BeforeClass public void setUp() { MockitoAnnotations.initMocks(this); - msoBusinessLogic = new MsoBusinessLogicImpl(msoInterface, featureManager); + msoBusinessLogic = new MsoBusinessLogicImpl(msoInterface); } @Test @@ -282,39 +274,48 @@ public class MsoBusinessLogicImplTest extends AbstractTestNGSpringContextTests { assertThat(response).isEqualToComparingFieldByField(expectedResponse); } - @Test - public void shouldProperlyDeleteSvcInstanceWithProperParametersAndFalseFeatureFlag() { + @DataProvider + public Object[][] deleteSvcInstanceShouldDelete() { + return new Object[][]{{"Active"}, {"unexpected-status"}}; + } + + @DataProvider + public Object[][] deleteSvcInstanceShouldUnassign() { + return new Object[][]{{"Created"}, {"Pendingdelete"}, {"pending-Delete"}, {"Assigned"}}; + } + + + @Test(dataProvider = "deleteSvcInstanceShouldDelete") + public void shouldProperlyDeleteSvcInstanceWithProperParametersShouldDelete(String status) { // given - String endpointTemplate = "/serviceInstances/v5/%s"; + String endpointTemplate = "/serviceInstantiation/v7/serviceInstances/%s"; String serviceInstanceId = "3f93c7cb-2fd0-4557-9514-e189b7b04f9d"; String svcEndpoint = String.format(endpointTemplate, serviceInstanceId); RequestDetails requestDetails = new RequestDetails(); MsoResponseWrapper expectedResponse = createOkResponse(); given(msoInterface.deleteSvcInstance(requestDetails, svcEndpoint)).willReturn(expectedResponse); - given(featureManager.isActive(Features.FLAG_UNASSIGN_SERVICE)).willReturn(false); // when MsoResponseWrapper msoResponseWrapper = msoBusinessLogic - .deleteSvcInstance(requestDetails, serviceInstanceId, "unAssignOrDeleteParams"); + .deleteSvcInstance(requestDetails, serviceInstanceId, status); // then assertThat(msoResponseWrapper).isEqualToComparingFieldByField(expectedResponse); } - @Test - public void shouldProperlyDeleteSvcInstanceWithProperParametersAndTrueFeatureFlag() { + @Test(dataProvider = "deleteSvcInstanceShouldUnassign") + public void shouldProperlyDeleteSvcInstanceWithProperParametersShouldUnassign(String status) { // given - String endpointTemplate = "/serviceInstantiation/v5/serviceInstances/%s/unassign"; + String endpointTemplate = "/serviceInstantiation/v7/serviceInstances/%s/unassign"; String serviceInstanceId = "3f93c7cb-2fd0-4557-9514-e189b7b04f9d"; String svcEndpoint = String.format(endpointTemplate, serviceInstanceId); RequestDetails requestDetails = new RequestDetails(); MsoResponseWrapper expectedResponse = createOkResponse(); given(msoInterface.unassignSvcInstance(requestDetails, svcEndpoint)).willReturn(expectedResponse); - given(featureManager.isActive(Features.FLAG_UNASSIGN_SERVICE)).willReturn(true); // when MsoResponseWrapper msoResponseWrapper = msoBusinessLogic - .deleteSvcInstance(requestDetails, serviceInstanceId, "assigned"); + .deleteSvcInstance(requestDetails, serviceInstanceId, status); // then assertThat(msoResponseWrapper).isEqualToComparingFieldByField(expectedResponse); @@ -323,7 +324,7 @@ public class MsoBusinessLogicImplTest extends AbstractTestNGSpringContextTests { @Test public void shouldProperlyDeleteVnfWithProperParameters() { // when - String endpointTemplate = "/serviceInstances/v5/%s/vnfs/%s"; + String endpointTemplate = "/serviceInstantiation/v7/serviceInstances/%s/vnfs/%s"; String serviceInstanceId = "3f93c7cb-2fd0-4557-9514-e189b7b04f9d"; String vnfInstanceId = "testVnfInstanceTempId"; String vnfEndpoint = String.format(endpointTemplate, serviceInstanceId, vnfInstanceId); @@ -342,7 +343,7 @@ public class MsoBusinessLogicImplTest extends AbstractTestNGSpringContextTests { @Test public void shouldProperlyDeleteVfModuleWithProperParameters() { // when - String endpointTemplate = "/serviceInstances/v7/%s/vnfs/%s/vfModules/%s"; + String endpointTemplate = "/serviceInstantiation/v7/serviceInstances/%s/vnfs/%s/vfModules/%s"; String serviceInstanceId = "3f93c7cb-2fd0-4557-9514-e189b7b04f9d"; String vnfInstanceId = "testVnfInstanceTempId"; String vfModuleId = "testVfModuleId"; @@ -905,58 +906,6 @@ public class MsoBusinessLogicImplTest extends AbstractTestNGSpringContextTests { requestDetails.setModelInfo(modelInfo); } - @Test - public void shouldProperlyDeactivateAndCloudDeleteWithProperParameters() { - // given - String serviceInstanceId = "testServiceId"; - String vnfInstanceId = "testVnfInstanceId"; - String vfModuleInstanceId = "testVfModuleInstanceId"; - RequestDetails requestDetails = new RequestDetails(); - - String path = msoBusinessLogic.getDeactivateAndCloudDeletePath(serviceInstanceId, vnfInstanceId, vfModuleInstanceId); - - RequestReferences requestReferences = new RequestReferences(); - requestReferences.setInstanceId("testInstance"); - requestReferences.setRequestId("testRequest"); - - HttpResponse expectedResponse = HttpResponse.fallback(new RequestReferencesContainer(requestReferences)); - - MsoResponseWrapper2 responseWrapped = new MsoResponseWrapper2<>(expectedResponse); - - given(msoInterface.post(eq(path), any(RequestDetails.class), eq(RequestReferencesContainer.class))).willReturn(expectedResponse); - - // when - MsoResponseWrapper2 response = msoBusinessLogic.deactivateAndCloudDelete(serviceInstanceId, vnfInstanceId, vfModuleInstanceId, requestDetails); - - // then - assertThat(response).isEqualToComparingFieldByField(responseWrapped); - } - - @Test - public void shouldProperlyActivateFabricConfigurationWithProperParameters() { - // given - String serviceInstanceId = "testServiceId"; - RequestDetails requestDetails = new RequestDetails(); - - String path = msoBusinessLogic.getActivateFabricConfigurationPath(serviceInstanceId); - - RequestReferences requestReferences = new RequestReferences(); - requestReferences.setInstanceId("testInstance"); - requestReferences.setRequestId("testRequest"); - - HttpResponse expectedResponse = HttpResponse.fallback(new RequestReferencesContainer(requestReferences)); - - MsoResponseWrapper2 responseWrapped = new MsoResponseWrapper2<>(expectedResponse); - - given(msoInterface.post(eq(path), any(RequestDetails.class), eq(RequestReferencesContainer.class))).willReturn(expectedResponse); - - // when - MsoResponseWrapper2 response = msoBusinessLogic.activateFabricConfiguration(serviceInstanceId, requestDetails); - - // then - assertThat(response).isEqualToComparingFieldByField(responseWrapped); - } - @Test public void shouldProperlyUpdateVnfSoftwareWithProperParameters() { // given diff --git a/vid-app-common/src/test/java/org/onap/vid/mso/MsoOperationalEnvironmentTest.java b/vid-app-common/src/test/java/org/onap/vid/mso/MsoOperationalEnvironmentTest.java index 891192c75..0ea5f2947 100644 --- a/vid-app-common/src/test/java/org/onap/vid/mso/MsoOperationalEnvironmentTest.java +++ b/vid-app-common/src/test/java/org/onap/vid/mso/MsoOperationalEnvironmentTest.java @@ -25,6 +25,13 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableListMultimap; +import java.io.IOException; +import java.net.URL; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; import org.apache.commons.io.IOUtils; import org.apache.log4j.LogManager; import org.apache.log4j.Logger; @@ -40,17 +47,9 @@ import org.skyscreamer.jsonassert.JSONCompareMode; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; -import java.io.IOException; -import java.net.URL; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - public class MsoOperationalEnvironmentTest { - private MsoBusinessLogic msoBusinessLogic = new MsoBusinessLogicImpl(null,null); + private MsoBusinessLogic msoBusinessLogic = new MsoBusinessLogicImpl(null); private static final Logger logger = LogManager.getLogger(MsoOperationalEnvironmentTest.class); @Test(dataProvider = "getOperationalEnvironmentActivationPermutations") diff --git a/vid-app-common/src/test/java/org/onap/vid/mso/rest/MsoRestClientNewTest.java b/vid-app-common/src/test/java/org/onap/vid/mso/rest/MsoRestClientNewTest.java index d4abfae38..6cf7d487e 100644 --- a/vid-app-common/src/test/java/org/onap/vid/mso/rest/MsoRestClientNewTest.java +++ b/vid-app-common/src/test/java/org/onap/vid/mso/rest/MsoRestClientNewTest.java @@ -38,8 +38,8 @@ import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import java.util.Properties; import java.util.UUID; +import org.apache.commons.configuration.PropertiesConfiguration; import org.glassfish.grizzly.http.util.HttpStatus; import org.junit.AfterClass; import org.junit.BeforeClass; @@ -61,7 +61,7 @@ public class MsoRestClientNewTest { private static StubServer server; private static StubServer securedServer; - private static Properties props = new Properties(); + private static PropertiesConfiguration props = new PropertiesConfiguration(); private static String msoCreateServiceInstanceJson; private static String msoScaleOutVfModule; private final static String CREATE_INSTANCE_RESPONSE_STR = @@ -76,7 +76,7 @@ public class MsoRestClientNewTest { @BeforeClass - public static void start() throws IOException { + public static void start() throws Exception { server = new StubServer().run(); securedServer = new StubServer().secured().run(); @@ -109,7 +109,7 @@ public class MsoRestClientNewTest { @Test public void testCreateSvcInstance() throws Exception { - String endpoint = props.getProperty(MsoProperties.MSO_REST_API_CONFIGURATIONS); + String endpoint = props.getString(MsoProperties.MSO_REST_API_CONFIGURATIONS); endpoint = endpoint.replace(MsoController.SVC_INSTANCE_ID, SERVICE_INSTANCE_ID); try (MsoRestClientTestUtil closure = new MsoRestClientTestUtil( server, @@ -122,7 +122,7 @@ public class MsoRestClientNewTest { @Test public void testCreateVnf() throws Exception { - String endpoint = props.getProperty(MsoProperties.MSO_REST_API_VNF_INSTANCE); + String endpoint = props.getString(MsoProperties.MSO_REST_API_VNF_INSTANCE); endpoint = endpoint.replace(MsoController.SVC_INSTANCE_ID, SERVICE_INSTANCE_ID); try (MsoRestClientTestUtil closure = new MsoRestClientTestUtil( server, @@ -136,7 +136,7 @@ public class MsoRestClientNewTest { @Test public void testCreateNwInstance() throws Exception { - String endpoint = props.getProperty(MsoProperties.MSO_REST_API_NETWORK_INSTANCE); + String endpoint = props.getString(MsoProperties.MSO_REST_API_NETWORK_INSTANCE); String nw_endpoint = endpoint.replaceFirst(MsoController.SVC_INSTANCE_ID, SERVICE_INSTANCE_ID); try (MsoRestClientTestUtil closure = new MsoRestClientTestUtil( server, @@ -149,7 +149,7 @@ public class MsoRestClientNewTest { @Test public void testCreateVolumeGroupInstance() throws Exception { - String endpoint = props.getProperty(MsoProperties.MSO_REST_API_VOLUME_GROUP_INSTANCE); + String endpoint = props.getString(MsoProperties.MSO_REST_API_VOLUME_GROUP_INSTANCE); String vnf_endpoint = endpoint.replaceFirst(MsoController.SVC_INSTANCE_ID, SERVICE_INSTANCE_ID); vnf_endpoint = vnf_endpoint.replaceFirst(MsoController.VNF_INSTANCE_ID, SAMPLE_VNF_INSTANCE_ID); try (MsoRestClientTestUtil closure = new MsoRestClientTestUtil( @@ -163,7 +163,7 @@ public class MsoRestClientNewTest { @Test public void testCreateVfModuleInstance() throws Exception { - String endpoint = props.getProperty(MsoProperties.MSO_REST_API_VF_MODULE_INSTANCE); + String endpoint = props.getString(MsoProperties.MSO_REST_API_VF_MODULE_INSTANCE); String partial_endpoint = endpoint.replaceFirst(MsoController.SVC_INSTANCE_ID, SERVICE_INSTANCE_ID); String vf_module_endpoint = partial_endpoint.replaceFirst(MsoController.VNF_INSTANCE_ID, SAMPLE_VNF_INSTANCE_ID); @@ -195,7 +195,7 @@ public class MsoRestClientNewTest { @Ignore @Test public void testDeleteSvcInstance() throws Exception { - String endpoint = props.getProperty(MsoProperties.MSO_REST_API_SVC_INSTANCE); + String endpoint = props.getString(MsoProperties.MSO_REST_API_SVC_INSTANCE); endpoint = endpoint.replaceFirst(MsoController.SVC_INSTANCE_ID, SERVICE_INSTANCE_ID); @@ -211,7 +211,7 @@ public class MsoRestClientNewTest { @Ignore @Test public void testDeleteVnf() throws Exception { - String endpoint = props.getProperty(MsoProperties.MSO_REST_API_VNF_INSTANCE); + String endpoint = props.getString(MsoProperties.MSO_REST_API_VNF_INSTANCE); endpoint = endpoint.replaceFirst(MsoController.SVC_INSTANCE_ID, SERVICE_INSTANCE_ID); try (MsoRestClientTestUtil closure = new MsoRestClientTestUtil( @@ -226,7 +226,7 @@ public class MsoRestClientNewTest { @Ignore @Test public void testDeleteVfModule() throws Exception { - String endpoint = props.getProperty(MsoProperties.MSO_REST_API_VF_MODULE_INSTANCE); + String endpoint = props.getString(MsoProperties.MSO_REST_API_VF_MODULE_INSTANCE); String part_endpoint = endpoint.replaceFirst(MsoController.SVC_INSTANCE_ID, SERVICE_INSTANCE_ID); String vf_modules_endpoint = part_endpoint.replaceFirst(MsoController.VNF_INSTANCE_ID, SAMPLE_VNF_INSTANCE_ID); String delete_vf_endpoint = vf_modules_endpoint + '/' + SAMPLE_VNF_MODULE_ID; @@ -243,7 +243,7 @@ public class MsoRestClientNewTest { @Ignore @Test public void testDeleteVolumeGroupInstance() throws Exception { - String endpoint = props.getProperty(MsoProperties.MSO_REST_API_VOLUME_GROUP_INSTANCE); + String endpoint = props.getString(MsoProperties.MSO_REST_API_VOLUME_GROUP_INSTANCE); String svc_endpoint = endpoint.replaceFirst(MsoController.SVC_INSTANCE_ID, SERVICE_INSTANCE_ID); String vnf_endpoint = svc_endpoint.replaceFirst(MsoController.VNF_INSTANCE_ID, SAMPLE_VNF_INSTANCE_ID); String delete_volume_group_endpoint = vnf_endpoint + "/" + SAMPLE_VNF_MODULE_ID; @@ -260,7 +260,7 @@ public class MsoRestClientNewTest { @Ignore @Test public void testDeleteNwInstance() throws Exception { - String endpoint = props.getProperty(MsoProperties.MSO_REST_API_NETWORK_INSTANCE); + String endpoint = props.getString(MsoProperties.MSO_REST_API_NETWORK_INSTANCE); String svc_endpoint = endpoint.replaceFirst(MsoController.SVC_INSTANCE_ID, SERVICE_INSTANCE_ID); String delete_nw_endpoint = svc_endpoint + "/" + SAMPLE_NETWORK_INSTANCE_ID; @@ -275,7 +275,7 @@ public class MsoRestClientNewTest { @Test public void testGetOrchestrationRequest() { - String p = props.getProperty(MsoProperties.MSO_REST_API_GET_ORC_REQ); + String p = props.getString(MsoProperties.MSO_REST_API_GET_ORC_REQ); String path = p + "/" + SAMPLE_REQUEST_ID; try(MsoRestClientTestUtil closure = new MsoRestClientTestUtil( @@ -289,7 +289,7 @@ public class MsoRestClientNewTest { @Test public void testGetManualTasksByRequestId() { - String p = props.getProperty(MsoProperties.MSO_REST_API_GET_ORC_REQ); + String p = props.getString(MsoProperties.MSO_REST_API_GET_ORC_REQ); String path = p + "/" + UUID.randomUUID(); String validResponse = "" + "{ " @@ -376,7 +376,7 @@ public class MsoRestClientNewTest { @Test public void testSetConfigurationActiveStatus() throws Exception { - String endpoint = "/serviceInstances/v5//configurations/"; + String endpoint = "/serviceInstances/v7//configurations/"; endpoint = endpoint.replace(MsoController.SVC_INSTANCE_ID, SERVICE_INSTANCE_ID); endpoint = endpoint.replace(MsoController.CONFIGURATION_ID, SAMPLE_CONFIGURATION_ID); endpoint = endpoint + "/activate"; @@ -448,7 +448,7 @@ public class MsoRestClientNewTest { @Test public void testRemoveRelationshipFromServiceInstance() throws Exception { - String serviceEndpoint = props.getProperty(MsoProperties.MSO_REST_API_SVC_INSTANCE); + String serviceEndpoint = props.getString(MsoProperties.MSO_REST_API_SVC_INSTANCE); String removeRelationshipsPath = serviceEndpoint + "/" + SERVICE_INSTANCE_ID + "/removeRelationships"; try (MsoRestClientTestUtil closure = new MsoRestClientTestUtil( @@ -476,7 +476,7 @@ public class MsoRestClientNewTest { } @Test public void testScaleOutVfModule() throws IOException { - String serviceEndpoint = props.getProperty(MsoProperties.MSO_REST_API_VF_MODULE_SCALE_OUT); + String serviceEndpoint = props.getString(MsoProperties.MSO_REST_API_VF_MODULE_SCALE_OUT); String partial_endpoint = serviceEndpoint.replaceFirst(SVC_INSTANCE_ID, SERVICE_INSTANCE_ID); String vf_module_endpoint = partial_endpoint.replaceFirst(VNF_INSTANCE_ID, SAMPLE_VNF_INSTANCE_ID); try (MsoRestClientTestUtil closure = new MsoRestClientTestUtil( diff --git a/vid-app-common/src/test/java/org/onap/vid/mso/rest/RequestDetailsTest.java b/vid-app-common/src/test/java/org/onap/vid/mso/rest/RequestDetailsTest.java index 575ceab7c..7f30b0f2d 100644 --- a/vid-app-common/src/test/java/org/onap/vid/mso/rest/RequestDetailsTest.java +++ b/vid-app-common/src/test/java/org/onap/vid/mso/rest/RequestDetailsTest.java @@ -20,23 +20,24 @@ package org.onap.vid.mso.rest; +import static com.google.code.beanmatchers.BeanMatchers.hasValidBeanEqualsExcluding; +import static com.google.code.beanmatchers.BeanMatchers.hasValidGettersAndSettersExcluding; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.testng.AssertJUnit.assertEquals; + import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; +import java.util.Collections; +import java.util.List; +import java.util.Map; import org.assertj.core.api.AssertionsForClassTypes; import org.onap.vid.exceptions.NotFoundException; +import org.onap.vid.testUtils.TestUtils; +import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeMethod; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; -import java.util.Collections; -import java.util.List; -import java.util.Map; - -import static com.google.code.beanmatchers.BeanMatchers.hasValidBeanEqualsExcluding; -import static com.google.code.beanmatchers.BeanMatchers.hasValidGettersAndSettersExcluding; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.testng.AssertJUnit.assertEquals; - public class RequestDetailsTest { @@ -48,6 +49,10 @@ public class RequestDetailsTest { private static final ImmutableList LCP_CLOUD_REGION_ID_PATH = ImmutableList.of("requestDetails", "cloudConfiguration", "lcpCloudRegionId"); + @BeforeClass + public static void registerValueGenerator() { + TestUtils.registerCloudConfigurationValueGenerator(); + } @BeforeMethod public void setUp() { diff --git a/vid-app-common/src/test/java/org/onap/vid/services/AAITreeNodeBuilderTest.java b/vid-app-common/src/test/java/org/onap/vid/services/AAITreeNodeBuilderTest.java index 9cd9ebae8..c2a3f5d61 100644 --- a/vid-app-common/src/test/java/org/onap/vid/services/AAITreeNodeBuilderTest.java +++ b/vid-app-common/src/test/java/org/onap/vid/services/AAITreeNodeBuilderTest.java @@ -7,9 +7,9 @@ * 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. @@ -20,77 +20,100 @@ package org.onap.vid.services; +import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.util.concurrent.MoreExecutors; + +import org.apache.commons.lang3.tuple.Pair; +import org.jetbrains.annotations.NotNull; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import org.mockito.stubbing.Answer; import org.onap.vid.aai.AaiClientInterface; +import org.onap.vid.aai.model.AaiGetNetworkCollectionDetails.Relationship; +import org.onap.vid.aai.model.AaiGetNetworkCollectionDetails.RelationshipList; +import org.onap.vid.exceptions.GenericUncheckedException; import org.onap.vid.model.aaiTree.AAITreeNode; +import org.onap.vid.model.aaiTree.NodeType; +import org.onap.vid.mso.model.CloudConfiguration; +import org.onap.vid.utils.Tree; import org.onap.vid.utils.Unchecked; -import org.testng.Assert; -import org.testng.annotations.BeforeTest; +import org.onap.vid.testUtils.TestUtils; +import org.springframework.http.HttpMethod; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import java.io.IOException; import java.util.HashMap; -import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.List; +import java.util.Map; +import java.util.Optional; import java.util.concurrent.ConcurrentSkipListSet; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; import static java.util.Comparator.comparing; +import static net.javacrumbs.jsonunit.JsonMatchers.jsonEquals; +import static net.javacrumbs.jsonunit.core.Option.IGNORING_ARRAY_ORDER; +import static net.javacrumbs.jsonunit.core.Option.IGNORING_EXTRA_FIELDS; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.empty; +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.when; import static org.onap.vid.services.AAIServiceTree.AAI_TREE_PATHS; +import static org.onap.vid.utils.KotlinUtilsKt.JACKSON_OBJECT_MAPPER; +import static org.testng.Assert.assertNull; +import static org.testng.Assert.assertTrue; public class AAITreeNodeBuilderTest { - AAITreeNodeBuilder aaiTreeNodeBuilder; + private AAITreeNodeBuilder aaiTreeNodeBuilder; @Mock - AaiClientInterface aaiClientMock; + private AaiClientInterface aaiClientMock; - @Mock - ThreadPoolExecutor threadPoolMock; + private ExecutorService executorService; + private static final ObjectMapper mapper = new ObjectMapper(); - @BeforeTest + @BeforeClass public void initMocks() { MockitoAnnotations.initMocks(this); aaiTreeNodeBuilder = new AAITreeNodeBuilder(aaiClientMock); + executorService = MoreExecutors.newDirectExecutorService(); } - @Test - public void buildNode_buildGroupNode_NodeIsAsExpected(){ + private void buildNodeAndAssert(JsonNode inputNode, AAITreeNode expectedNode, NodeType nodeType){ ConcurrentSkipListSet nodesAccumulator = new ConcurrentSkipListSet<>(comparing(AAITreeNode::getUniqueNodeKey)); - ConcurrentLinkedQueue visitedNodes = new ConcurrentLinkedQueue<>(); - when(aaiClientMock.typedAaiGet(Unchecked.toURI("anyUrl"), JsonNode.class)).thenReturn(createGroupJson()); - - AAITreeNode groupNode = aaiTreeNodeBuilder.buildNode("instance-group", + when(aaiClientMock.typedAaiRest(Unchecked.toURI("anyUrl"), JsonNode.class, null, HttpMethod.GET, false)).thenReturn(inputNode); + AAITreeNode actualNode = aaiTreeNodeBuilder.buildNode( + nodeType, "anyUrl", + null, + HttpMethod.GET, nodesAccumulator, - threadPoolMock, - visitedNodes, - new AtomicInteger(0), - AAI_TREE_PATHS).get(0); - - AAITreeNode expectedGroupNode = createExpectedGroupNode(); - assertNodeIsAsExpected(expectedGroupNode,groupNode); + executorService, + AAI_TREE_PATHS.getSubTree(new AAIServiceTree.AaiRelationship(nodeType)) + ).get(0); + assertThat(actualNode, jsonEquals(expectedNode).when(IGNORING_ARRAY_ORDER, IGNORING_EXTRA_FIELDS).whenIgnoringPaths("relationshipList","children[0].relationshipList")); } - private void assertNodeIsAsExpected(AAITreeNode expectedGroupNode, AAITreeNode groupNode) { - Assert.assertEquals(groupNode.getId(), expectedGroupNode.getId()); - Assert.assertEquals(groupNode.getType(), expectedGroupNode.getType()); - Assert.assertEquals(groupNode.getName(), expectedGroupNode.getName()); - Assert.assertEquals(groupNode.getModelVersionId(), expectedGroupNode.getModelVersionId()); - Assert.assertEquals(groupNode.getModelInvariantId(), expectedGroupNode.getModelInvariantId()); - Assert.assertEquals(groupNode.getInMaint(), expectedGroupNode.getInMaint()); - Assert.assertEquals(groupNode.getAdditionalProperties(), expectedGroupNode.getAdditionalProperties()); + @Test + public void buildNode_buildGroupNode_NodeIsAsExpected() { + buildNodeAndAssert(createGroupJson(), createExpectedGroupNode(), NodeType.INSTANCE_GROUP); } private AAITreeNode createExpectedGroupNode() { AAITreeNode expectedNode = new AAITreeNode(); expectedNode.setId("c4fcf022-31a0-470a-b5b8-c18335b7af32"); - expectedNode.setType("instance-group"); + expectedNode.setType(NodeType.INSTANCE_GROUP); expectedNode.setName("Test vE-Flex"); expectedNode.setModelVersionId("Test vE-Flex"); expectedNode.setModelInvariantId("dd182d7d-6949-4b90-b3cc-5befe400742e"); @@ -103,8 +126,6 @@ public class AAITreeNodeBuilderTest { additionalProperties.put("resource-version","1533315433086"); additionalProperties.put("instance-group-function","vTSBC Customer Landing Network Collection"); expectedNode.setAdditionalProperties(additionalProperties); - - return expectedNode; } @@ -125,22 +146,7 @@ public class AAITreeNodeBuilderTest { " \"inMaint\": \"false\"," + " \"instance-group-function\": \"vTSBC Customer Landing Network Collection\"," + " \"relationship-list\": {" + - " \"relationship\": [{" + - " \"related-to\": \"generic-vnf\"," + - " \"relationship-label\": \"org.onap.relationships.inventory.MemberOf\" ," + - " \"related-link\": \"/aai/v14/network/generic-vnfs/generic-vnf/8c54c369-2876-4423-9b33-80f783f29082\" ," + - " \"relationship-data\": [{" + - " \"relationship-key\": \"generic-vnf.vnf-id\"," + - " \"relationship-value\": \"8c54c369-2876-4423-9b33-80f783f29082\"" + - " }" + - " ]," + - " \"related-to-property\": [{" + - " \"property-key\": \"generic-vnf.vnf-name\"," + - " \"property-value\": \"zrdm5bffad01\"" + - " }" + - " ]" + - " }" + - " ]" + + " \"relationship\": []" + " }" + " }"); } catch (IOException e) { @@ -148,4 +154,363 @@ public class AAITreeNodeBuilderTest { } return groupNode; } + + @Test + public void whenReadNetworkNode_thenNodeIsAsExpected() throws IOException { + JsonNode mockedAaiResponse = TestUtils.readJsonResourceFileAsObject("/getTopology/network.json", JsonNode.class); + + AAITreeNode expectedNetworkNode = new AAITreeNode(); + expectedNetworkNode.setId("94c86b39-bbbf-4027-8120-ff37c6d2493a"); + expectedNetworkNode.setName("AUK51a_oam_calea_net_1"); + expectedNetworkNode.setOrchestrationStatus("Assigned"); + expectedNetworkNode.setModelInvariantId("b9a9b549-0ee4-49fc-b4f2-5edc6701da68"); + expectedNetworkNode.setModelVersionId("77010093-df36-4dcb-8428-c3d02bf3f88d"); + expectedNetworkNode.setModelCustomizationId("e5f33853-f84c-4cdd-99f2-93846957aa18"); + expectedNetworkNode.setType(NodeType.NETWORK); + expectedNetworkNode.setCloudConfiguration(new CloudConfiguration("auk51a", "b530fc990b6d4334bd45518bebca6a51", "att-nc")); + + buildNodeAndAssert(mockedAaiResponse, expectedNetworkNode, NodeType.NETWORK); + } + + @Test + public void whenCloudRegionMissing_otherPlacementFieldsReadAsExpected() throws IOException { + + AAITreeNode node = new AAITreeNode(); + Optional tenantRelationShip = Optional.of( + JACKSON_OBJECT_MAPPER.readValue("{" + + " \"related-to\": \"tenant\"," + + " \"relationship-label\": \"org.onap.relationships.inventory.Uses\"," + + " \"related-link\": \"/aai/v14/cloud-infrastructure/cloud-regions/cloud-region/att-nc/auk51a/tenants/tenant/b530fc990b6d4334bd45518bebca6a51\"," + + " \"relationship-data\": [{" + + " \"relationship-key\": \"cloud-region.cloud-owner\"," + + " \"relationship-value\": \"att-nc\"" + + " }, {" + + " \"relationship-key\": \"tenant.tenant-id\"," + + " \"relationship-value\": \"b530fc990b6d4334bd45518bebca6a51\"" + + " }" + + " ]," + + " \"related-to-property\": [{" + + " \"property-key\": \"tenant.tenant-name\"," + + " \"property-value\": \"ecomp_ispt\"" + + " }" + + " ]" + + " }", Relationship.class) + ); + aaiTreeNodeBuilder.enrichPlacementDataUsingTenantInfo(node, tenantRelationShip); + assertEquals(new CloudConfiguration(null, "b530fc990b6d4334bd45518bebca6a51", "att-nc"), node.getCloudConfiguration()); + } + + @Test + public void whenTenantMissing_otherPlacementFieldsReadAsExpected() throws IOException { + + AAITreeNode node = new AAITreeNode(); + Optional tenantRelationShip = Optional.of( + JACKSON_OBJECT_MAPPER.readValue("{" + + " \"related-to\": \"tenant\"," + + " \"relationship-label\": \"org.onap.relationships.inventory.Uses\"," + + " \"related-link\": \"/aai/v14/cloud-infrastructure/cloud-regions/cloud-region/att-nc/auk51a/tenants/tenant/b530fc990b6d4334bd45518bebca6a51\"," + + " \"relationship-data\": [{" + + " \"relationship-key\": \"cloud-region.cloud-owner\"," + + " \"relationship-value\": \"att-nc\"" + + " }, {" + + " \"relationship-key\": \"cloud-region.cloud-region-id\"," + + " \"relationship-value\": \"auk51a\"" + + " }" + + " ]," + + " \"related-to-property\": [{" + + " \"property-key\": \"tenant.tenant-name\"," + + " \"property-value\": \"ecomp_ispt\"" + + " }" + + " ]" + + " }", Relationship.class) + ); + aaiTreeNodeBuilder.enrichPlacementDataUsingTenantInfo(node, tenantRelationShip); + assertEquals(new CloudConfiguration("auk51a", null, "att-nc"), node.getCloudConfiguration()); + } + + @Test + public void whenCloudOwnerMissing_otherPlacementFieldsReadAsExpected() throws IOException { + + AAITreeNode node = new AAITreeNode(); + Optional tenantRelationShip = Optional.of( + JACKSON_OBJECT_MAPPER.readValue("{" + + " \"related-to\": \"tenant\"," + + " \"relationship-label\": \"org.onap.relationships.inventory.Uses\"," + + " \"related-link\": \"/aai/v14/cloud-infrastructure/cloud-regions/cloud-region/att-nc/auk51a/tenants/tenant/b530fc990b6d4334bd45518bebca6a51\"," + + " \"relationship-data\": [{" + + " \"relationship-key\": \"tenant.tenant-id\"," + + " \"relationship-value\": \"b530fc990b6d4334bd45518bebca6a51\"" + + " }, {" + + " \"relationship-key\": \"cloud-region.cloud-region-id\"," + + " \"relationship-value\": \"auk51a\"" + + " }" + + " ]," + + " \"related-to-property\": [{" + + " \"property-key\": \"tenant.tenant-name\"," + + " \"property-value\": \"ecomp_ispt\"" + + " }" + + " ]" + + " }", Relationship.class) + ); + aaiTreeNodeBuilder.enrichPlacementDataUsingTenantInfo(node, tenantRelationShip); + assertEquals(new CloudConfiguration("auk51a", "b530fc990b6d4334bd45518bebca6a51", null), node.getCloudConfiguration()); + } + + @Test + public void whenThereIsNoTenantRelationship_thenPlacementIsNull() throws IOException { + AAITreeNode node = new AAITreeNode(); + aaiTreeNodeBuilder.enrichPlacementData(node); + assertNull(node.getCloudConfiguration()); + } + + + @Test + public void whenReadVnfNodeWithVfModule_thenNodeIsAsExpected() throws IOException { + JsonNode mockedAaiGetVnfResponse = TestUtils.readJsonResourceFileAsObject("/getTopology/vnf.json", JsonNode.class); + + //add mock for vfModule of the VNF + JsonNode mockedAaiGetVfModuleResponse = TestUtils.readJsonResourceFileAsObject("/getTopology/vfModule.json", JsonNode.class); + when(aaiClientMock.typedAaiGet(Unchecked.toURI("anyUrl/vf-modules"), JsonNode.class)).thenReturn(mockedAaiGetVfModuleResponse); + + CloudConfiguration expectedCloudConfiguration = new CloudConfiguration("dyh3b", "c8035f5ee95d4c62bbc8074c044122b9", "irma-aic"); + + AAITreeNode expectedVnfNode = createExpectedVnfTreeNode(expectedCloudConfiguration); + + AAITreeNode expectedVfModule = new AAITreeNode(); + expectedVfModule.setId("2cb6d41e-2bef-4cb2-80ce-c7815bcdcf4e"); + expectedVfModule.setName("dyh3brarf8000v_base"); + expectedVfModule.setOrchestrationStatus("Active"); + expectedVfModule.setModelInvariantId("3ecca473-b0c0-46ae-b0b7-bd2969d8b79f"); + expectedVfModule.setModelVersionId("5c35b764-e266-4498-af87-a88c4ba92dc4"); + expectedVfModule.setModelCustomizationId("06b4ece0-f6f8-4003-b445-653418292101"); + expectedVfModule.setType(NodeType.VF_MODULE); + expectedVfModule.setInMaint(false); + expectedVfModule.setCloudConfiguration(expectedCloudConfiguration); + + expectedVnfNode.addChildren(ImmutableList.of(expectedVfModule)); + + buildNodeAndAssert(mockedAaiGetVnfResponse, expectedVnfNode, NodeType.GENERIC_VNF); + } + + @NotNull + public static AAITreeNode createExpectedVnfTreeNode(CloudConfiguration expectedCloudConfiguration) { + AAITreeNode expectedVnfNode = new AAITreeNode(); + expectedVnfNode.setId("9a7a4dc1-8e5f-43fe-a360-7734c5f51382"); + expectedVnfNode.setName("dyh3brarf8000v"); + expectedVnfNode.setOrchestrationStatus("Active"); + expectedVnfNode.setModelInvariantId("b711997f-36b3-4a9b-8b37-71a0fc2ebd6d"); + expectedVnfNode.setModelVersionId("7f23e4f7-e44c-44df-b066-4cedc6950bfe"); + expectedVnfNode.setModelCustomizationId("401350be-0f56-481c-86d8-f32d573fec26"); + expectedVnfNode.setType(NodeType.GENERIC_VNF); + expectedVnfNode.setInMaint(true); + expectedVnfNode.setProvStatus("PREPROV"); + expectedVnfNode.setCloudConfiguration(expectedCloudConfiguration); + return expectedVnfNode; + } + + @DataProvider + public static Object[][] isArrayDataProvider() { + return new Object[][] { + {"Json Array", buildArrayJson(NodeType.GENERIC_VNF), true}, + {"Json Object", buildOneLevelJson(NodeType.GENERIC_VNF), false}, + {"Json Array with another node type", buildArrayJson(NodeType.SERVICE_INSTANCE), false}, + {"null json", null, false} + }; + } + + @Test(dataProvider = "isArrayDataProvider") + public void IsArrayType(String description, JsonNode jsonNode, boolean expectedResult) { + boolean isArray = aaiTreeNodeBuilder.isArray(jsonNode, NodeType.GENERIC_VNF); + assertEquals(expectedResult, isArray); + } + + @Test + public void jsonToAaiNodeTest() { + NodeType nodeType = NodeType.SERVICE_INSTANCE; + JsonNode node = buildOneLevelJson(nodeType); + ConcurrentSkipListSet nodesAccumulator = new ConcurrentSkipListSet<>(comparing(AAITreeNode::getUniqueNodeKey)); + + AAITreeNode aaiTreeNode = aaiTreeNodeBuilder.createAaiNode(nodeType, node, nodesAccumulator); + + assertEquals("any-instance-id", aaiTreeNode.getId()); + assertEquals("any-instance-name", aaiTreeNode.getName()); + assertTrue(nodesAccumulator.contains(aaiTreeNode)); + } + + @Test + public void getNextLevelInPathsTreeTest() { + Tree firstLevelTree = getPathsTree(); + + Tree secondLevelTree = aaiTreeNodeBuilder.getNextLevelInPathsTree(firstLevelTree, NodeType.GENERIC_VNF.getType()); + assertEquals(NodeType.GENERIC_VNF.getType(), secondLevelTree.getRootValue().type); + + Tree thirdLevelTree = aaiTreeNodeBuilder.getNextLevelInPathsTree(secondLevelTree, NodeType.INSTANCE_GROUP.getType()); + assertEquals(NodeType.INSTANCE_GROUP.getType(), thirdLevelTree.getRootValue().type); + } + + @Test + public void getNextLevelInPathsTreeTest_givenIrrelevantNode_expectedNull() { + Tree pathsTree = getPathsTree(); + + Tree subTree = aaiTreeNodeBuilder.getNextLevelInPathsTree(pathsTree, NodeType.INSTANCE_GROUP.getType()); + + assertNull(subTree); + } + + @Test + public void getRelationships_given2Relationships_expect1filtered() { + NodeType firstRelationship = NodeType.GENERIC_VNF; + NodeType secondRelationship = NodeType.INSTANCE_GROUP; + JsonNode jsonNode = buildOneLevelJson(NodeType.SERVICE_INSTANCE, firstRelationship, secondRelationship); + + List relationships = aaiTreeNodeBuilder.getFilteredRelationships(jsonNode, getPathsTree()); + + assertEquals(1, relationships.size()); + assertEquals(firstRelationship.getType(), relationships.get(0).getRelatedTo()); + } + + @Test + public void getRelationships_givenNoRelationships_expectedEmptyListTest() { + JsonNode jsonNode = buildOneLevelJson(NodeType.SERVICE_INSTANCE); + + List relationships = aaiTreeNodeBuilder.getFilteredRelationships(jsonNode, getPathsTree()); + + assertThat(relationships, is(empty())); + } + + @Test + public void getRelationships_given2RelationshipsNotExistInTreePaths_expectAllFiltered() { + NodeType firstRelationship = NodeType.CONFIGURATION; + NodeType secondRelationship = NodeType.INSTANCE_GROUP; + JsonNode jsonNode = buildOneLevelJson(NodeType.SERVICE_INSTANCE, firstRelationship, secondRelationship); + + List relationships = aaiTreeNodeBuilder.getFilteredRelationships(jsonNode, getPathsTree()); + + assertThat(relationships, is(empty())); + } + + @Test + public void aggregateAllOtherPropertiesTest() { + NodeType nodeType = NodeType.SERVICE_INSTANCE; + JsonNode jsonNode = buildOneLevelJson(nodeType, NodeType.GENERIC_VNF, NodeType.GENERIC_VNF); + ((ObjectNode) jsonNode).put("nf-role", "any-value"); + + Map additionalProps = aaiTreeNodeBuilder.aggregateAllOtherProperties(jsonNode, nodeType); + assertThat(additionalProps, is(ImmutableMap.of( + "nf-role", "any-value"))); + } + + @Test + public void parseNodeAndFilterRelationshipsTest() { + NodeType nodeType = NodeType.SERVICE_INSTANCE; + JsonNode jsonNode = buildOneLevelJson(NodeType.SERVICE_INSTANCE, NodeType.GENERIC_VNF, NodeType.NETWORK, NodeType.VF_MODULE); + ConcurrentSkipListSet nodesAccumulator = new ConcurrentSkipListSet<>(comparing(AAITreeNode::getUniqueNodeKey)); + + Pair> resultNode = aaiTreeNodeBuilder.parseNodeAndFilterRelationships(jsonNode, nodeType, + nodesAccumulator, getPathsTree()); + + assertEquals(nodeType, resultNode.getKey().getType()); + assertEquals(2, resultNode.getValue().size()); + assertEquals(NodeType.GENERIC_VNF.getType(), resultNode.getValue().get(0).getRelatedTo()); + assertEquals(NodeType.NETWORK.getType(), resultNode.getValue().get(1).getRelatedTo()); + } + + @Test(expectedExceptions = GenericUncheckedException.class ,expectedExceptionsMessageRegExp = "AAI node fetching failed.") + public void fetchChildrenAsyncTest_given2children_expected1Ok1Timeout() { + ConcurrentSkipListSet nodesAccumulator = new ConcurrentSkipListSet<>(comparing(AAITreeNode::getUniqueNodeKey)); + ExecutorService threadPool = Executors.newFixedThreadPool(5); + + AAITreeNode rootNode = createExpectedGroupNode(); + JsonNode relationshipJson = getRelationships(NodeType.GENERIC_VNF, NodeType.NETWORK); + List relationships = mapper.convertValue(relationshipJson, RelationshipList.class).getRelationship(); + + when(aaiClientMock.typedAaiRest(Unchecked.toURI(relationships.get(0).getRelatedLink()), JsonNode.class, null, HttpMethod.GET, false)) + .thenReturn(buildOneLevelJson(NodeType.GENERIC_VNF)); + + when(aaiClientMock.typedAaiRest(Unchecked.toURI(relationships.get(1).getRelatedLink()), JsonNode.class, null, HttpMethod.GET, false)) + .thenAnswer((Answer) invocation -> { + Thread.sleep(2000); + return buildOneLevelJson(NodeType.NETWORK); + }); + + aaiTreeNodeBuilder.fetchChildrenAsync(threadPool, nodesAccumulator, rootNode, relationships, getPathsTree(), 1); + + assertEquals(2, rootNode.getChildren().size()); + assertEquals(NodeType.GENERIC_VNF, rootNode.getChildren().get(0).getType()); + assertEquals(NodeType.NETWORK, rootNode.getChildren().get(1).getType()); + } + + @DataProvider + public Object[][] testIsListOfKeyResultsDataProvider() { + return new Object[][]{ + {"Node has results with several values", + "{\"results\":[{\"l3-network\":{}},{\"l3-network\":{}},{\"l3-network\":{}}]}", + true}, + {"Node has results with no values", + "{\"results\":[]}", + true}, + {"Node has results, but it isn't an array", + "{\"results\":{\"some-field\":{}}}", + false}, + {"Node doesn't have results", + "{\"l3-network\":[{},{}]}", + false}, + {"Node is null", + "null", + false}, + }; + } + + @Test(dataProvider = "testIsListOfKeyResultsDataProvider") + public void testIsListOfKeyResults(String testCase, String input, boolean expectedResult) throws IOException { + assertEquals(testCase + ": " + input, + expectedResult, aaiTreeNodeBuilder.isListOfKeyResults(new ObjectMapper().readTree(input))); + } + + private Tree getPathsTree() { + Tree pathsTree = new Tree<>(new AAIServiceTree.AaiRelationship(NodeType.SERVICE_INSTANCE)); + pathsTree.addPath(AAIServiceTree.toAaiRelationshipList(NodeType.GENERIC_VNF, NodeType.INSTANCE_GROUP)); + pathsTree.addPath(AAIServiceTree.toAaiRelationshipList(NodeType.NETWORK)); + + return pathsTree; + } + + private static JsonNode buildOneLevelJson(NodeType nodeType, NodeType...relationships) { + ObjectNode objectNode = mapper.createObjectNode(); + objectNode.put(nodeType.getId(), "any-instance-id"); + objectNode.put(nodeType.getName(), "any-instance-name"); + if (relationships.length > 0 ) { + objectNode.putPOJO("relationship-list", getRelationships(relationships)); + } + return objectNode; + } + + private static JsonNode buildArrayJson(NodeType nodeType) { + ObjectNode objectNode = mapper.createObjectNode(); + ArrayNode arrayNode = objectNode.putArray(nodeType.getType()); + arrayNode.add(buildOneLevelJson(nodeType)); + arrayNode.add(buildOneLevelJson(nodeType)); + + return objectNode; + } + + private static JsonNode getRelationship(String nodeType) { + ObjectNode relationship = mapper.createObjectNode(); + relationship.put("related-to", nodeType); + relationship.put("relationship-label", "org.onap.relationships.inventory.ComposedOf"); + relationship.put("related-link", "/aai/v12/network/" + nodeType + "s/" + nodeType + "/cf6f60cd-808d-44e6-978b-c663e00dba8d"); + return relationship; + } + + private static JsonNode getRelationships(NodeType...nodeTypes) { + ObjectNode relationshipList = mapper.createObjectNode(); + ArrayNode relationships = relationshipList.putArray("relationship"); + + for (NodeType nodeType: nodeTypes) { + relationships.add(getRelationship(nodeType.getType())); + } + + return relationshipList; + } + } diff --git a/vid-app-common/src/test/java/org/onap/vid/services/AaiServiceImplTest.java b/vid-app-common/src/test/java/org/onap/vid/services/AaiServiceImplTest.java index bb47180e4..09a53684f 100644 --- a/vid-app-common/src/test/java/org/onap/vid/services/AaiServiceImplTest.java +++ b/vid-app-common/src/test/java/org/onap/vid/services/AaiServiceImplTest.java @@ -21,16 +21,36 @@ package org.onap.vid.services; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.isNull; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.onap.vid.model.aaiTree.NodeType.SERVICE_INSTANCE; + import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import io.joshworks.restclient.http.HttpResponse; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import javax.ws.rs.core.Response; import org.apache.http.HttpStatus; import org.jetbrains.annotations.NotNull; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Mock; +import org.mockito.Spy; import org.mockito.junit.MockitoJUnitRunner; import org.onap.vid.aai.AaiClientInterface; import org.onap.vid.aai.AaiGetVnfResponse; @@ -70,721 +90,711 @@ import org.onap.vid.model.aaiTree.AAITreeNode; import org.onap.vid.model.aaiTree.RelatedVnf; import org.onap.vid.model.aaiTree.ServiceInstance; import org.onap.vid.roles.RoleValidator; - -import javax.ws.rs.core.Response; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; +import org.springframework.http.HttpMethod; @RunWith(MockitoJUnitRunner.class) public class AaiServiceImplTest { - private static final String GLOBAL_CUSTOMER_ID = "GLOBAL_CUSTOMER_ID"; - private static final String CLOUD_REGION_ID = "CLOUD_REGION_ID"; - private static final String VNF_TYPE = "VNF_TYPE"; - private static final String TENANT_ID = "TENANT_ID"; - private static final String TENANT_NAME = "TENANT_NAME"; - private static final String SERVICE_TYPE = "SERVICE_TYPE"; - private static final String CORRECT_VALUE = "CORRECT_VALUE"; - private static final String SUBSCRIBER_ID = "SUBSCRIBER_ID_EXPECTED"; - private static final String STATUS_TEXT = "STATUS_TEXT"; - private static final String GLOBAL_SUBSCRIBER_ID = "GLOBAL_SUBSCRIBER_ID"; - private static final String GLOBAL_SUBSCRIBER_ID_NULL_RESPONSE = "ID_NULL"; - private static final String VNF_INSTANCE_ID_OK = "VNF_INSTANCE_ID_OK"; - private static final String VNF_INSTANCE_ID_FAIL = "VNF_INSTANCE_ID_FAIL"; - private static final String PARENT_NAME = "PARENT_NAME"; - private static final String PARENT_ID = "PARENT_ID"; - private static final String INVARIANT_ID = "INVARIANT_ID"; - private static final String GROUP_TYPE_FAILING = "GROUP_TYPE_FAILING"; - private static final String GROUP_ROLE_OK = "GROUP_ROLE_OK"; - private static final String GROUP_ROLE_FAILING = "GROUP_ROLE_FAILING"; - private static final String group_type_ok = "GROUP_TYPE_OK"; - private static final String CLOUD_TYPE = "CLOUD_TYPE"; - - @Mock - private HttpResponse responseAllSubscribers; - @Mock - private AaiResponse aaiResponseOpEnvList; - @Mock - private AaiResponse aaiResponse; - @Mock - private AaiResponse aaiResponseJsonNode; - @Mock - private RoleValidator roleValidator; - - @Mock - private AaiClientInterface aaiClient; - @Mock - private AaiOverTLSClientInterface aaiOverTLSClient; - @Mock - private AaiResponseTranslator aaiResponseTranslator; - @Mock - private AAIServiceTree aaiServiceTree; - - @InjectMocks - private AaiServiceImpl aaiService; - - - @Test - public void shouldGetFullSubscriberListWithoutValidator() { - when(aaiOverTLSClient.getAllSubscribers()).thenReturn(responseAllSubscribers); - - HttpResponse actualResponse = aaiService.getFullSubscriberList(); - - assertThat(actualResponse).isEqualTo(responseAllSubscribers); - } - - @Test - public void shouldGetFullSubscriberListWithValidator() { - Subscriber subscriber = createSubscriber(); - SubscriberList subscriberList = new SubscriberList(Collections.singletonList(subscriber)); - - when(aaiOverTLSClient.getAllSubscribers()).thenReturn(responseAllSubscribers); - when(responseAllSubscribers.getBody()).thenReturn(subscriberList); - when(responseAllSubscribers.getStatusText()).thenReturn(STATUS_TEXT); - when(responseAllSubscribers.getStatus()).thenReturn(HttpStatus.SC_OK); - SubscriberFilteredResults expectedSubscribers = new SubscriberFilteredResults(roleValidator, subscriberList, - STATUS_TEXT, HttpStatus.SC_OK); - - SubscriberFilteredResults actualSubscribers = aaiService.getFullSubscriberList(roleValidator); - - assertThat(actualSubscribers.getHttpCode()).isEqualTo(expectedSubscribers.getHttpCode()); - assertThat(actualSubscribers.getErrorMessage()).isEqualTo(expectedSubscribers.getErrorMessage()); - } - - @Test - public void shouldGetOperationalEnvironments() { - when(aaiClient.getOperationalEnvironments(anyString(), anyString())) - .thenReturn(aaiResponseOpEnvList); - - AaiResponse expectedEnvList = - aaiService.getOperationalEnvironments(anyString(), anyString()); - - assertThat(expectedEnvList).isEqualTo(aaiResponseOpEnvList); - } - - @Test - public void shouldGetSubscriberData() { - Services services = createAaiResponseServices(); - AaiResponse aaiResponseServices = new AaiResponse<>(services, null, HttpStatus.SC_OK); - - when(aaiClient.getSubscriberData(SUBSCRIBER_ID)).thenReturn(aaiResponseServices); - when(roleValidator.isServicePermitted(eq(GLOBAL_CUSTOMER_ID), anyString())).thenReturn(Boolean.TRUE); - - AaiResponse actualResponse = aaiService.getSubscriberData(SUBSCRIBER_ID, roleValidator); - List actualServiceSubscriptions = ((AaiResponse) actualResponse) - .getT().serviceSubscriptions.serviceSubscription; - - assertThat(actualResponse).isEqualTo(aaiResponseServices); - assertThat(actualServiceSubscriptions).allMatch(s -> s.isPermitted); - } - - @Test - public void shouldGetServiceInstanceEmptySearchResults() { - ServiceInstancesSearchResults serviceInstancesSearchResults = new ServiceInstancesSearchResults(); - AaiResponse emptyResponse = new AaiResponse<>(serviceInstancesSearchResults, - null, HttpStatus.SC_OK); - - AaiResponse actualResponse = aaiService.getServiceInstanceSearchResults(null, null, - null, null, null); - - assertThat(actualResponse).isEqualToComparingFieldByFieldRecursively(emptyResponse); - } - - @Test - public void shouldGetVersionByInvariantId() { - Response response = mock(Response.class); - when(aaiClient.getVersionByInvariantId(any())).thenReturn(response); - - Response actualResponse = aaiService.getVersionByInvariantId(any()); - - assertThat(actualResponse).isEqualTo(response); - } - - @Test - public void shouldGetSpecificPnf() { - AaiResponse expectedResponse = new AaiResponse<>(Pnf.builder().build(), null, HttpStatus.SC_OK); - when(aaiClient.getSpecificPnf(anyString())).thenReturn(expectedResponse); - - AaiResponse actualResponse = aaiService.getSpecificPnf(anyString()); - - assertThat(actualResponse).isEqualTo(expectedResponse); - } - - @Test - public void shouldGetPnfData() { - when(aaiClient.getPNFData(anyString(), anyString(), anyString(), anyString(), anyString(), anyString(), - anyString())).thenReturn(aaiResponse); - - AaiResponse actualResponse = aaiService.getPNFData(anyString(), anyString(), anyString(), anyString(), - anyString(), anyString(), anyString()); - - assertThat(actualResponse).isEqualTo(aaiResponse); - } - - @Test - public void shouldGetServices() { - org.onap.vid.aai.model.AaiGetServicesRequestModel.Service s1 = - createService("ID1", "V1", "D1"); - org.onap.vid.aai.model.AaiGetServicesRequestModel.Service s2 = - createService("ID2", "V2", "D2"); - - GetServicesAAIRespone services = new GetServicesAAIRespone(); - services.service = Arrays.asList(s1, s2); - - AaiResponse aaiResponseServices = - new AaiResponse<>(services, null, HttpStatus.SC_OK); - - when(aaiClient.getServices()).thenReturn(aaiResponseServices); - - Object actualObjectOfResponse = aaiService.getServices(roleValidator).getT(); - - assertThat(actualObjectOfResponse).isNotNull(); - assertThat(((GetServicesAAIRespone) actualObjectOfResponse).service).allMatch(s -> s.isPermitted); - } - - @Test - public void shouldGetTenants() { - GetTenantsResponse tenant1 = new GetTenantsResponse("REGION_ID1", "CLOUD_OWNER1", - "TENANT_NAME1", "TENANT_ID1", true); - GetTenantsResponse tenant2 = new GetTenantsResponse("REGION_ID2", "CLOUD_OWNER2", - "TENANT_NAME2", "TENANT_ID2", false); - GetTenantsResponse[] tenants = {tenant1, tenant2}; - AaiResponse aaiGetTenantsResponse = new AaiResponse<>(tenants, - null, HttpStatus.SC_OK); - - when(aaiClient.getTenants(anyString(), anyString())).thenReturn(aaiGetTenantsResponse); - when(roleValidator.isTenantPermitted(anyString(), anyString(), anyString())) - .thenReturn(Boolean.TRUE); - - GetTenantsResponse[] actualResponses = aaiService - .getTenants(anyString(), anyString(), roleValidator).getT(); - - assertThat(actualResponses).isNotNull(); - assertThat(actualResponses.length).isEqualTo(2); - assertThat(actualResponses).allMatch(tenant -> tenant.isPermitted); - } - - @Test - public void shouldGetVNFDataWithoutFiltering() { - when(aaiClient.getVNFData(anyString(), anyString(), anyString())).thenReturn(aaiResponse); - - AaiResponse actualResponse = aaiService.getVNFData(anyString(), anyString(), anyString()); + private static final String GLOBAL_CUSTOMER_ID = "GLOBAL_CUSTOMER_ID"; + private static final String CLOUD_REGION_ID = "CLOUD_REGION_ID"; + private static final String VNF_TYPE = "VNF_TYPE"; + private static final String TENANT_ID = "TENANT_ID"; + private static final String TENANT_NAME = "TENANT_NAME"; + private static final String SERVICE_TYPE = "SERVICE_TYPE"; + private static final String CORRECT_VALUE = "CORRECT_VALUE"; + private static final String SUBSCRIBER_ID = "SUBSCRIBER_ID_EXPECTED"; + private static final String STATUS_TEXT = "STATUS_TEXT"; + private static final String GLOBAL_SUBSCRIBER_ID = "GLOBAL_SUBSCRIBER_ID"; + private static final String GLOBAL_SUBSCRIBER_ID_NULL_RESPONSE = "ID_NULL"; + private static final String VNF_INSTANCE_ID_OK = "VNF_INSTANCE_ID_OK"; + private static final String VNF_INSTANCE_ID_FAIL = "VNF_INSTANCE_ID_FAIL"; + private static final String PARENT_NAME = "PARENT_NAME"; + private static final String PARENT_ID = "PARENT_ID"; + private static final String INVARIANT_ID = "INVARIANT_ID"; + private static final String GROUP_TYPE_FAILING = "GROUP_TYPE_FAILING"; + private static final String GROUP_ROLE_OK = "GROUP_ROLE_OK"; + private static final String GROUP_ROLE_FAILING = "GROUP_ROLE_FAILING"; + private static final String group_type_ok = "GROUP_TYPE_OK"; + private static final String CLOUD_TYPE = "CLOUD_TYPE"; + + @Mock + private HttpResponse responseAllSubscribers; + @Mock + private AaiResponse aaiResponseOpEnvList; + @Mock + private AaiResponse aaiResponse; + @Mock + private AaiResponse aaiResponseJsonNode; + @Mock + private RoleValidator roleValidator; + + @Mock + private AaiClientInterface aaiClient; + @Mock + private AaiOverTLSClientInterface aaiOverTLSClient; + @Mock + private AaiResponseTranslator aaiResponseTranslator; + @Mock + private AAIServiceTree aaiServiceTree; + @Spy + private ExecutorService executorService = Executors.newFixedThreadPool(1); + + @InjectMocks + private AaiServiceImpl aaiService; + + @Test + public void shouldGetFullSubscriberListWithoutValidator() { + when(aaiOverTLSClient.getAllSubscribers()).thenReturn(responseAllSubscribers); + + HttpResponse actualResponse = aaiService.getFullSubscriberList(); + + assertThat(actualResponse).isEqualTo(responseAllSubscribers); + } + + @Test + public void shouldGetFullSubscriberListWithValidator() { + Subscriber subscriber = createSubscriber(); + SubscriberList subscriberList = new SubscriberList(Collections.singletonList(subscriber)); + + when(aaiOverTLSClient.getAllSubscribers()).thenReturn(responseAllSubscribers); + when(responseAllSubscribers.getBody()).thenReturn(subscriberList); + when(responseAllSubscribers.getStatusText()).thenReturn(STATUS_TEXT); + when(responseAllSubscribers.getStatus()).thenReturn(HttpStatus.SC_OK); + SubscriberFilteredResults expectedSubscribers = new SubscriberFilteredResults(roleValidator, subscriberList, + STATUS_TEXT, HttpStatus.SC_OK); + + SubscriberFilteredResults actualSubscribers = aaiService.getFullSubscriberList(roleValidator); + + assertThat(actualSubscribers.getHttpCode()).isEqualTo(expectedSubscribers.getHttpCode()); + assertThat(actualSubscribers.getErrorMessage()).isEqualTo(expectedSubscribers.getErrorMessage()); + } + + @Test + public void shouldGetOperationalEnvironments() { + when(aaiClient.getOperationalEnvironments(anyString(), anyString())) + .thenReturn(aaiResponseOpEnvList); + + AaiResponse expectedEnvList = + aaiService.getOperationalEnvironments(anyString(), anyString()); + + assertThat(expectedEnvList).isEqualTo(aaiResponseOpEnvList); + } + + @Test + public void shouldGetSubscriberData() { + Services services = createAaiResponseServices(); + AaiResponse aaiResponseServices = new AaiResponse<>(services, null, HttpStatus.SC_OK); + + when(aaiClient.getSubscriberData(SUBSCRIBER_ID, false)).thenReturn(aaiResponseServices); + when(roleValidator.isServicePermitted(eq(GLOBAL_CUSTOMER_ID), anyString())).thenReturn(Boolean.TRUE); + + AaiResponse actualResponse = aaiService.getSubscriberData(SUBSCRIBER_ID, roleValidator, false); + List actualServiceSubscriptions = ((AaiResponse) actualResponse) + .getT().serviceSubscriptions.serviceSubscription; + + assertThat(actualResponse).isEqualTo(aaiResponseServices); + assertThat(actualServiceSubscriptions).allMatch(s -> s.isPermitted); + } + + @Test + public void shouldGetServiceInstanceEmptySearchResults() { + ServiceInstancesSearchResults serviceInstancesSearchResults = new ServiceInstancesSearchResults(); + AaiResponse emptyResponse = new AaiResponse<>(serviceInstancesSearchResults, + null, HttpStatus.SC_OK); + + AaiResponse actualResponse = aaiService.getServiceInstanceSearchResults(null, null, + null, null, null); + + assertThat(actualResponse).isEqualToComparingFieldByFieldRecursively(emptyResponse); + } + + @Test + public void shouldGetVersionByInvariantId() { + Response response = mock(Response.class); + when(aaiClient.getVersionByInvariantId(any())).thenReturn(response); + + Response actualResponse = aaiService.getVersionByInvariantId(any()); + + assertThat(actualResponse).isEqualTo(response); + } + + @Test + public void shouldGetSpecificPnf() { + AaiResponse expectedResponse = new AaiResponse<>(Pnf.builder().build(), null, HttpStatus.SC_OK); + when(aaiClient.getSpecificPnf(anyString())).thenReturn(expectedResponse); + + AaiResponse actualResponse = aaiService.getSpecificPnf(anyString()); - assertThat(actualResponse).isEqualTo(aaiResponse); - } + assertThat(actualResponse).isEqualTo(expectedResponse); + } - @Test - public void shouldGetVNFDataWithFiltering() { - VnfResult vnfResult1 = createVnfResult("ID1", "generic-vnf"); - VnfResult vnfResult2 = createVnfResult("ID2", "service-instance"); - VnfResult vnfResult3 = createVnfResult("ID3", "anything-else"); + @Test + public void shouldGetPnfData() { + when(aaiClient.getPNFData(anyString(), anyString(), anyString(), anyString(), anyString(), anyString(), + anyString())).thenReturn(aaiResponse); - List vnfResults = Arrays.asList(vnfResult1, vnfResult2, vnfResult3); - AaiResponse aaiResponseGetVnfResponse = createAaiResponseVnfResponse(vnfResults); + AaiResponse actualResponse = aaiService.getPNFData(anyString(), anyString(), anyString(), anyString(), + anyString(), anyString(), anyString()); - vnfResults = Arrays.asList(vnfResult1, vnfResult2); - AaiResponse expectedResponseWithReturnedVnfs = createAaiResponseVnfResponse(vnfResults); - AaiResponse expectedResponseWithoutReturnedVnfs = new AaiResponse(); + assertThat(actualResponse).isEqualTo(aaiResponse); + } - when(aaiClient.getVNFData(GLOBAL_SUBSCRIBER_ID, SERVICE_TYPE)).thenReturn(aaiResponseGetVnfResponse); - when(aaiClient.getVNFData(GLOBAL_SUBSCRIBER_ID_NULL_RESPONSE, SERVICE_TYPE)).thenReturn(null); + @Test + public void shouldGetServices() { + org.onap.vid.aai.model.AaiGetServicesRequestModel.Service s1 = + createService("ID1", "V1", "D1"); + org.onap.vid.aai.model.AaiGetServicesRequestModel.Service s2 = + createService("ID2", "V2", "D2"); - AaiResponse actualResponseWithReturnedVnfs = - aaiService.getVNFData(GLOBAL_SUBSCRIBER_ID, SERVICE_TYPE); - AaiResponse actualResponseWithoutReturnedVnfs = - aaiService.getVNFData(GLOBAL_SUBSCRIBER_ID_NULL_RESPONSE, SERVICE_TYPE); + GetServicesAAIRespone services = new GetServicesAAIRespone(); + services.service = Arrays.asList(s1, s2); - assertThat(actualResponseWithReturnedVnfs) - .isEqualToComparingFieldByFieldRecursively(expectedResponseWithReturnedVnfs); - assertThat(actualResponseWithoutReturnedVnfs) - .isEqualToComparingFieldByField(expectedResponseWithoutReturnedVnfs); - } + AaiResponse aaiResponseServices = + new AaiResponse<>(services, null, HttpStatus.SC_OK); - @Test - public void shouldGetAaiZones() { - when(aaiClient.getAllAicZones()).thenReturn(aaiResponse); + when(aaiClient.getServices()).thenReturn(aaiResponseServices); - AaiResponse actualResponse = aaiService.getAaiZones(); + Object actualObjectOfResponse = aaiService.getServices(roleValidator).getT(); - assertThat(actualResponse).isEqualTo(aaiResponse); - } - - @Test - public void shouldGetAicZoneForPnf() { - ServiceRelationships relationsService = createServiceRelationships(); - AaiResponse expectedServiceInstanceResp = - new AaiResponse<>(relationsService, null, HttpStatus.SC_OK); - AaiResponse expectedResponse = new AaiResponse<>(CORRECT_VALUE, null, HttpStatus.SC_OK); + assertThat(actualObjectOfResponse).isNotNull(); + assertThat(((GetServicesAAIRespone) actualObjectOfResponse).service).allMatch(s -> s.isPermitted); + } - when(aaiClient.getServiceInstance(anyString(), anyString(), anyString())) - .thenReturn(expectedServiceInstanceResp); + @Test + public void shouldGetTenants() { + GetTenantsResponse tenant1 = new GetTenantsResponse("REGION_ID1", "CLOUD_OWNER1", + "TENANT_NAME1", "TENANT_ID1", true); + GetTenantsResponse tenant2 = new GetTenantsResponse("REGION_ID2", "CLOUD_OWNER2", + "TENANT_NAME2", "TENANT_ID2", false); + GetTenantsResponse[] tenants = {tenant1, tenant2}; + AaiResponse aaiGetTenantsResponse = new AaiResponse<>(tenants, + null, HttpStatus.SC_OK); - AaiResponse actualResponse = aaiService.getAicZoneForPnf(anyString(), anyString(), anyString()); + when(aaiClient.getTenants(anyString(), anyString())).thenReturn(aaiGetTenantsResponse); + when(roleValidator.isTenantPermitted(anyString(), anyString(), anyString())) + .thenReturn(Boolean.TRUE); - assertThat(actualResponse).isEqualToComparingFieldByField(expectedResponse); - } + GetTenantsResponse[] actualResponses = aaiService + .getTenants(anyString(), anyString(), roleValidator).getT(); - @Test - public void shouldGetNodeTemplateInstances() { - when(aaiClient.getNodeTemplateInstances(anyString(), anyString(), anyString(), - anyString(), anyString())).thenReturn(aaiResponse); + assertThat(actualResponses).isNotNull(); + assertThat(actualResponses.length).isEqualTo(2); + assertThat(actualResponses).allMatch(tenant -> tenant.isPermitted); + } - AaiResponse expectedResponse = aaiService.getNodeTemplateInstances(anyString(), anyString(), anyString(), - anyString(), anyString()); + @Test + public void shouldGetVNFDataWithoutFiltering() { + when(aaiClient.getVNFData(anyString(), anyString(), anyString())).thenReturn(aaiResponse); - assertThat(expectedResponse).isEqualTo(aaiResponse); - } + AaiResponse actualResponse = aaiService.getVNFData(anyString(), anyString(), anyString()); - @Test - public void shouldGetNetworkCollectionDetails() { - when(aaiClient.getNetworkCollectionDetails(anyString())).thenReturn(aaiResponse); - - AaiResponse expectedResponse = aaiService.getNetworkCollectionDetails(anyString()); + assertThat(actualResponse).isEqualTo(aaiResponse); + } - assertThat(expectedResponse).isEqualTo(aaiResponse); - } + @Test + public void shouldGetVNFDataWithFiltering() { + VnfResult vnfResult1 = createVnfResult("ID1", "generic-vnf"); + VnfResult vnfResult2 = createVnfResult("ID2", "service-instance"); + VnfResult vnfResult3 = createVnfResult("ID3", "anything-else"); - @Test - public void shouldGetInstanceGroupsByCloudRegion() { - AaiGetInstanceGroupsByCloudRegion aaiGetInstanceGroupsByCloudRegion = - mock(AaiGetInstanceGroupsByCloudRegion.class); - AaiResponse expectedResponse = - new AaiResponse<>(aaiGetInstanceGroupsByCloudRegion, null, HttpStatus.SC_OK); + List vnfResults = Arrays.asList(vnfResult1, vnfResult2, vnfResult3); + AaiResponse aaiResponseGetVnfResponse = createAaiResponseVnfResponse(vnfResults); - when(aaiClient.getInstanceGroupsByCloudRegion(anyString(), anyString(), anyString())) - .thenReturn(expectedResponse); - AaiResponse actualResponse = - aaiService.getInstanceGroupsByCloudRegion(anyString(), anyString(), anyString()); + vnfResults = Arrays.asList(vnfResult1, vnfResult2); + AaiResponse expectedResponseWithReturnedVnfs = createAaiResponseVnfResponse(vnfResults); + AaiResponse expectedResponseWithoutReturnedVnfs = new AaiResponse(); - assertThat(actualResponse).isEqualTo(expectedResponse); - } + when(aaiClient.getVNFData(GLOBAL_SUBSCRIBER_ID, SERVICE_TYPE)).thenReturn(aaiResponseGetVnfResponse); + when(aaiClient.getVNFData(GLOBAL_SUBSCRIBER_ID_NULL_RESPONSE, SERVICE_TYPE)).thenReturn(null); - @Test - public void shouldGetServicesByDistributionStatus() { - Result resultWithModelType = createResult("MODEL_TYPE1", "1"); - Result resultWithEmptyModelType = createResult(null, "2"); - Result resultWithoutModel = new Result(); - resultWithoutModel.setModel(null); - Result resultWithoutValidModel = createResultWithoutValidModel(); - List results = Arrays.asList(resultWithModelType, resultWithEmptyModelType, resultWithoutModel, - resultWithoutValidModel); + AaiResponse actualResponseWithReturnedVnfs = + aaiService.getVNFData(GLOBAL_SUBSCRIBER_ID, SERVICE_TYPE); + AaiResponse actualResponseWithoutReturnedVnfs = + aaiService.getVNFData(GLOBAL_SUBSCRIBER_ID_NULL_RESPONSE, SERVICE_TYPE); - GetServiceModelsByDistributionStatusResponse serviceModels = new GetServiceModelsByDistributionStatusResponse(); - serviceModels.setResults(results); + assertThat(actualResponseWithReturnedVnfs) + .isEqualToComparingFieldByFieldRecursively(expectedResponseWithReturnedVnfs); + assertThat(actualResponseWithoutReturnedVnfs) + .isEqualToComparingFieldByField(expectedResponseWithoutReturnedVnfs); + } - AaiResponse serviceModelsByDistributionStatusResponse - = new AaiResponse<>(serviceModels, null, HttpStatus.SC_OK); + @Test + public void shouldGetAaiZones() { + when(aaiClient.getAllAicZones()).thenReturn(aaiResponse); - Service[] expectedServices = { - createService("MODEL_TYPE1", "1"), - createService("", "2") - }; + AaiResponse actualResponse = aaiService.getAaiZones(); - when(aaiClient.getServiceModelsByDistributionStatus()).thenReturn(serviceModelsByDistributionStatusResponse); - Collection actualServices = aaiService.getServicesByDistributionStatus(); + assertThat(actualResponse).isEqualTo(aaiResponse); + } + + @Test + public void shouldGetAicZoneForPnf() { + ServiceRelationships relationsService = createServiceRelationships(); + AaiResponse expectedServiceInstanceResp = + new AaiResponse<>(relationsService, null, HttpStatus.SC_OK); + AaiResponse expectedResponse = new AaiResponse<>(CORRECT_VALUE, null, HttpStatus.SC_OK); + + when(aaiClient.getServiceInstance(anyString(), anyString(), anyString())) + .thenReturn(expectedServiceInstanceResp); + + AaiResponse actualResponse = aaiService.getAicZoneForPnf(anyString(), anyString(), anyString()); - assertThat(actualServices) - .hasSize(2) - .usingFieldByFieldElementComparator() - .containsExactly(expectedServices); - } + assertThat(actualResponse).isEqualToComparingFieldByField(expectedResponse); + } + + @Test + public void shouldGetNodeTemplateInstances() { + when(aaiClient.getNodeTemplateInstances(anyString(), anyString(), anyString(), + anyString(), anyString())).thenReturn(aaiResponse); + + AaiResponse expectedResponse = aaiService.getNodeTemplateInstances(anyString(), anyString(), anyString(), + anyString(), anyString()); + + assertThat(expectedResponse).isEqualTo(aaiResponse); + } - @Test - public void shouldReturnEmptyListOfServices() { - AaiResponse emptyResponse - = new AaiResponse<>(null, null, HttpStatus.SC_OK); + @Test + public void shouldGetNetworkCollectionDetails() { + when(aaiClient.getNetworkCollectionDetails(anyString())).thenReturn(aaiResponse); + + AaiResponse expectedResponse = aaiService.getNetworkCollectionDetails(anyString()); + + assertThat(expectedResponse).isEqualTo(aaiResponse); + } + + @Test + public void shouldGetInstanceGroupsByCloudRegion() { + AaiGetInstanceGroupsByCloudRegion aaiGetInstanceGroupsByCloudRegion = + mock(AaiGetInstanceGroupsByCloudRegion.class); + AaiResponse expectedResponse = + new AaiResponse<>(aaiGetInstanceGroupsByCloudRegion, null, HttpStatus.SC_OK); - when(aaiClient.getServiceModelsByDistributionStatus()).thenReturn(emptyResponse); - Collection actualServices = aaiService.getServicesByDistributionStatus(); + when(aaiClient.getInstanceGroupsByCloudRegion(anyString(), anyString(), anyString())) + .thenReturn(expectedResponse); + AaiResponse actualResponse = + aaiService.getInstanceGroupsByCloudRegion(anyString(), anyString(), anyString()); - assertThat(actualServices).isEqualTo(Collections.EMPTY_LIST); - } + assertThat(actualResponse).isEqualTo(expectedResponse); + } - @Test - public void shouldGetServiceInstanceAssociatedPnfs() { - ServiceRelationships relationsList = createServiceRelationships(); - LogicalLinkResponse logicalLinkResponse = new LogicalLinkResponse(); - logicalLinkResponse.setRelationshipList(relationsList.getRelationshipList()); + @Test + public void shouldGetServicesByDistributionStatus() { + Result resultWithModelType = createResult("MODEL_TYPE1", "1"); + Result resultWithEmptyModelType = createResult(null, "2"); + Result resultWithoutModel = new Result(); + resultWithoutModel.setModel(null); + Result resultWithoutValidModel = createResultWithoutValidModel(); + List results = Arrays.asList(resultWithModelType, resultWithEmptyModelType, resultWithoutModel, + resultWithoutValidModel); - AaiResponse aaiResponseLogicalLinkResponse = - new AaiResponse<>(logicalLinkResponse, null, HttpStatus.SC_OK); - AaiResponse aaiResponseServiceRelations = - new AaiResponse<>(relationsList, null, HttpStatus.SC_OK); + GetServiceModelsByDistributionStatusResponse serviceModels = new GetServiceModelsByDistributionStatusResponse(); + serviceModels.setResults(results); - when(aaiClient.getServiceInstance(anyString(), anyString(), anyString())) - .thenReturn(aaiResponseServiceRelations); - when(aaiClient.getLogicalLink(anyString())).thenReturn(aaiResponseLogicalLinkResponse); + AaiResponse serviceModelsByDistributionStatusResponse + = new AaiResponse<>(serviceModels, null, HttpStatus.SC_OK); + + Service[] expectedServices = { + createService("MODEL_TYPE1", "1"), + createService("", "2") + }; + + when(aaiClient.getServiceModelsByDistributionStatus()).thenReturn(serviceModelsByDistributionStatusResponse); + Collection actualServices = aaiService.getServicesByDistributionStatus(); + + assertThat(actualServices) + .hasSize(2) + .usingFieldByFieldElementComparator() + .containsExactly(expectedServices); + } + @Test + public void shouldReturnEmptyListOfServices() { + AaiResponse emptyResponse + = new AaiResponse<>(null, null, HttpStatus.SC_OK); - List expectedPnfs = Collections.singletonList(CORRECT_VALUE); - List actualPnfs = aaiService.getServiceInstanceAssociatedPnfs(anyString(), anyString(), anyString()); + when(aaiClient.getServiceModelsByDistributionStatus()).thenReturn(emptyResponse); + Collection actualServices = aaiService.getServicesByDistributionStatus(); - assertThat(actualPnfs).isEqualTo(expectedPnfs); - } + assertThat(actualServices).isEqualTo(Collections.EMPTY_LIST); + } - @Test - public void shouldGetPortMirroringConfigData() { - AaiResponseTranslator.PortMirroringConfigData expectedData - = mock(AaiResponseTranslator.PortMirroringConfigData.class); + @Test + public void shouldGetServiceInstanceAssociatedPnfs() { + ServiceRelationships relationsList = createServiceRelationships(); + LogicalLinkResponse logicalLinkResponse = new LogicalLinkResponse(); + logicalLinkResponse.setRelationshipList(relationsList.getRelationshipList()); - when(aaiClient.getCloudRegionAndSourceByPortMirroringConfigurationId(anyString())).thenReturn(aaiResponseJsonNode); - when(aaiResponseTranslator.extractPortMirroringConfigData(aaiResponseJsonNode)).thenReturn(expectedData); + AaiResponse aaiResponseLogicalLinkResponse = + new AaiResponse<>(logicalLinkResponse, null, HttpStatus.SC_OK); + AaiResponse aaiResponseServiceRelations = + new AaiResponse<>(relationsList, null, HttpStatus.SC_OK); + + when(aaiClient.getServiceInstance(anyString(), anyString(), anyString())) + .thenReturn(aaiResponseServiceRelations); + when(aaiClient.getLogicalLink(anyString())).thenReturn(aaiResponseLogicalLinkResponse); - AaiResponseTranslator.PortMirroringConfigData actualData = aaiService.getPortMirroringConfigData(anyString()); - assertThat(actualData).isEqualTo(expectedData); - } + List expectedPnfs = Collections.singletonList(CORRECT_VALUE); + List actualPnfs = aaiService.getServiceInstanceAssociatedPnfs(anyString(), anyString(), anyString()); + assertThat(actualPnfs).isEqualTo(expectedPnfs); + } - @Test - public void shouldGetInstanceGroupsByVnfInstanceId() { - List instanceGroupInfo = Collections.singletonList(new InstanceGroupInfo(CORRECT_VALUE)); - AaiGetRelatedInstanceGroupsByVnfId relatedInstanceGroups = new AaiGetRelatedInstanceGroupsByVnfId(); - relatedInstanceGroups.setRelationshipList(createRelationshipList()); - - AaiResponse correctCodeResponse = - new AaiResponse<>(relatedInstanceGroups, null, HttpStatus.SC_OK); - - AaiResponse> expectedCorrectCodeResponse = - new AaiResponse<>(instanceGroupInfo, null, HttpStatus.SC_OK); - AaiResponse expectedIncorrectCodeResponse = - new AaiResponse<>(relatedInstanceGroups, null, HttpStatus.SC_PAYMENT_REQUIRED); - List expectedCorrectResponseObject = expectedCorrectCodeResponse.getT(); - - when(aaiClient.getInstanceGroupsByVnfInstanceId(VNF_INSTANCE_ID_OK)).thenReturn(correctCodeResponse); - when(aaiClient.getInstanceGroupsByVnfInstanceId(VNF_INSTANCE_ID_FAIL)).thenReturn(expectedIncorrectCodeResponse); - - AaiResponse actualCorrectCodeResponse = aaiService.getInstanceGroupsByVnfInstanceId(VNF_INSTANCE_ID_OK); - AaiResponse actualIncorrectCodeResponse = aaiService.getInstanceGroupsByVnfInstanceId(VNF_INSTANCE_ID_FAIL); - - List actualCorrectResponseObject = - (List) actualCorrectCodeResponse.getT(); - - assertThat(actualCorrectResponseObject) - .usingFieldByFieldElementComparator() - .hasSameElementsAs(expectedCorrectResponseObject); - - assertThat(actualIncorrectCodeResponse).isEqualTo(expectedIncorrectCodeResponse); - } - - @Test - public void shouldGetHomingDataByVfModule() { - GetTenantsResponse expectedResponse = new GetTenantsResponse(); - when(aaiClient.getHomingDataByVfModule(anyString(), anyString())).thenReturn(expectedResponse); - - GetTenantsResponse actualResponse = aaiService.getHomingDataByVfModule(anyString(), anyString()); - assertThat(actualResponse).isEqualTo(expectedResponse); - } - - @Test - public void shouldSearchGroupMembers() { - Properties properties = createProperties(); - Map regionsAndTenants = createRegionsAndTenantsMap(properties); - - AAITreeNode validTreeNode = new AAITreeNode(); - addAdditionalPropertiesToAaiTreeNode(validTreeNode); - List validNodes = Arrays.asList(validTreeNode, validTreeNode); - - AAITreeNode validBranch = createTree(validNodes); - addAdditionalPropertiesToAaiTreeNode(validBranch); - List testedBranches = Collections.singletonList(validBranch); - - AAITreeNode testedTree = createTree(testedBranches); - - RelatedVnf expectedVnf = createExpectedVnf(validBranch); - List expectedResult = Collections.singletonList(expectedVnf); - - when(aaiServiceTree.buildAAITree(anyString(), any())).thenReturn(Collections.singletonList(testedTree)); - when(aaiClient.getCloudRegionAndTenantByVnfId(anyString())).thenReturn(regionsAndTenants); - - List actualGroupMembers = aaiService.searchGroupMembers(GLOBAL_CUSTOMER_ID, SERVICE_TYPE, - INVARIANT_ID, GROUP_TYPE_FAILING, GROUP_ROLE_FAILING); - - assertThat(actualGroupMembers) - .usingFieldByFieldElementComparator() - .hasSameElementsAs(expectedResult); - } - - @Test - public void shouldGetPortMirroringSourcePorts() { - PortDetailsTranslator.PortDetails details = mock(PortDetailsTranslator.PortDetails.class); - List expectedDetailsList = Arrays.asList( - details, details, details - ); - - when(aaiClient.getPortMirroringSourcePorts(anyString())).thenReturn(expectedDetailsList); - List actualDetails = aaiService.getPortMirroringSourcePorts(anyString()); - - assertThat(actualDetails).isEqualTo(expectedDetailsList); - } - - @Test - public void shouldGetAAIServiceTree() throws JsonProcessingException { - ServiceInstance serviceInstance = mock(ServiceInstance.class); - String expectedResult = new ObjectMapper().writeValueAsString(serviceInstance); - - when(aaiServiceTree.getServiceInstanceTopology(anyString(), anyString(), anyString())) - .thenReturn(serviceInstance); - String actualResult = aaiService.getAAIServiceTree(anyString(), anyString(), anyString()); - - assertThat(actualResult).isEqualTo(expectedResult); - } - - @NotNull - private Map createRegionsAndTenantsMap(Properties properties) { - Map regionsAndTenants = new HashMap<>(); - regionsAndTenants.put("tenant", properties); - regionsAndTenants.put("cloud-region", properties); - return regionsAndTenants; - } - - private Properties createProperties() { - Properties properties = new Properties(); - properties.setTenantId(TENANT_ID); - properties.setTenantName(TENANT_NAME); - properties.setCloudRegionId(CLOUD_REGION_ID); - return properties; - } - - @NotNull - private RelatedVnf createExpectedVnf(AAITreeNode validBranch) { - RelatedVnf expectedVnf = RelatedVnf.from(validBranch); - expectedVnf.setTenantId(TENANT_ID); - expectedVnf.setTenantName(TENANT_NAME); - expectedVnf.setLcpCloudRegionId(CLOUD_REGION_ID); - expectedVnf.setServiceInstanceId(PARENT_ID); - expectedVnf.setServiceInstanceName(PARENT_NAME); - expectedVnf.setInstanceType(VNF_TYPE); - - return expectedVnf; - } - - - private AAITreeNode createTree(List children) { - AAITreeNode tree = new AAITreeNode(); - tree.addChildren(children); - tree.setId(PARENT_ID); - tree.setName(PARENT_NAME); - return tree; - } - - private void addAdditionalPropertiesToAaiTreeNode(AAITreeNode tree) { - Map additionalProperties = new HashMap<>(); - additionalProperties.put("instance-group-role", GROUP_ROLE_OK); - additionalProperties.put("instance-group-type", group_type_ok); - additionalProperties.put("vnf-type", VNF_TYPE); - additionalProperties.put("cloud-region", CLOUD_TYPE); - tree.setAdditionalProperties(additionalProperties); - } - - private org.onap.vid.asdc.beans.Service createService(String category, String suffix) { - return new Service.ServiceBuilder() - .setUuid("MODELVER_VERSION_ID" + suffix) - .setInvariantUUID("MODEL_INVARIANT_NAME" + suffix) - .setCategory(category) - .setVersion("MODELVER_VERSION" + suffix) - .setName("MODELVER_NAME" + suffix) - .setDistributionStatus("MODELVER_DIST_STATUS" + suffix) - .setToscaModelURL(null) - .setLifecycleState(null) - .setArtifacts(null) - .setResources(null) - .build(); - } - - @NotNull - private Result createResultWithoutValidModel() { - ModelVers modelVers = new ModelVers(); - modelVers.setModelVer(Collections.singletonList(new ModelVer())); - - Model model = new Model(); - model.setModelVers(modelVers); - - Result result1 = new Result(); - result1.setModel(model); - return result1; - } - - @NotNull - private Result createResult(String modelType, String suffix) { - ModelVer modelVer = new ModelVer(); - modelVer.setModelVersionId("MODELVER_VERSION_ID" + suffix); - modelVer.setModelVersion("MODELVER_VERSION" + suffix); - modelVer.setModelName("MODELVER_NAME" + suffix); - modelVer.setDistributionStatus("MODELVER_DIST_STATUS" + suffix); - - ModelVers modelVers = new ModelVers(); - modelVers.setModelVer(Collections.singletonList(modelVer)); - - Model model = new Model(); - model.setModelType(modelType); - model.setModelInvariantId("MODEL_INVARIANT_NAME" + suffix); - model.setModelVers(modelVers); - - Result result = new Result(); - result.setModel(model); - return result; - } - - @NotNull - private ServiceRelationships createServiceRelationships() { - RelationshipList relationsList = createRelationshipList(CORRECT_VALUE); - ServiceRelationships relationsService = new ServiceRelationships(); - relationsService.setRelationshipList(relationsList); - return relationsService; - } - - @NotNull - private RelationshipList createRelationshipList(String expectedValue) { - List relationsDataList = createRelationshipDataList(expectedValue); - return createRelationshipList(relationsDataList); - } - - @NotNull - private RelationshipList createRelationshipList(List relationsDataList) { - Relationship relation1 = crateRelationship("any", relationsDataList); - Relationship relation2 = crateRelationship("zone", relationsDataList); - Relationship relation3 = crateRelationship("logical-link", relationsDataList); - Relationship relation4 = crateRelationship("lag-interface", relationsDataList); - Relationship relation5 = crateRelationship("pnf", relationsDataList); - - RelationshipList relationsList = new RelationshipList(); - relationsList.setRelationship(Arrays.asList(relation1, relation2, relation3, relation4, relation5)); - return relationsList; - } - - @NotNull - private List createRelationshipDataList(String expectedValue) { - RelationshipData relationData1 = createRelationshipData("any-key", "incorrect_key"); - RelationshipData relationData2 = createRelationshipData("zone.zone-id", expectedValue); - RelationshipData relationData3 = createRelationshipData("logical-link.link-name", expectedValue); - RelationshipData relationData4 = createRelationshipData("pnf.pnf-name", expectedValue); - - return Arrays.asList(relationData1, relationData2, relationData3, relationData4); - } - - @NotNull - private Relationship crateRelationship(String relatedTo, List relationsDataList) { - Relationship relation = new Relationship(); - relation.setRelatedTo(relatedTo); - relation.setRelationDataList(relationsDataList); - return relation; - } - - @NotNull - private RelationshipData createRelationshipData(String key, String value) { - RelationshipData relationData = new RelationshipData(); - relationData.setRelationshipKey(key); - relationData.setRelationshipValue(value); - return relationData; - } - - private org.onap.vid.aai.model.AaiGetNetworkCollectionDetails.RelationshipList createRelationshipList() { - RelatedToProperty property1 = - createRelatedToProperty("instance-group.instance-group-name", CORRECT_VALUE); - RelatedToProperty property2 = - createRelatedToProperty("anything-key", "anything-value"); - List properties = Arrays.asList(property1, property2); - - org.onap.vid.aai.model.AaiGetNetworkCollectionDetails.Relationship relationship1 = - createRelationship("instance-group", properties); - org.onap.vid.aai.model.AaiGetNetworkCollectionDetails.Relationship relationship2 = - createRelationship("any-key", properties); - - List relationships = - Arrays.asList(relationship1, relationship2); - - org.onap.vid.aai.model.AaiGetNetworkCollectionDetails.RelationshipList relationshipList = - new org.onap.vid.aai.model.AaiGetNetworkCollectionDetails.RelationshipList(); - relationshipList.setRelationship(relationships); - - return relationshipList; - } - - @NotNull - private org.onap.vid.aai.model.AaiGetNetworkCollectionDetails.Relationship createRelationship(String relatedTo, - List relatedToPropertyList) { - org.onap.vid.aai.model.AaiGetNetworkCollectionDetails.Relationship relationship1 = - new org.onap.vid.aai.model.AaiGetNetworkCollectionDetails.Relationship(); - relationship1.setRelatedTo(relatedTo); - relationship1.setRelatedToPropertyList(relatedToPropertyList); - return relationship1; - } - - @NotNull - private RelatedToProperty createRelatedToProperty(String key, String value) { - RelatedToProperty prop = new RelatedToProperty(); - prop.setPropertyKey(key); - prop.setPropertyValue(value); - return prop; - } - - @NotNull - private AaiResponse createAaiResponseVnfResponse(List vnfResults) { - AaiGetVnfResponse vnfResponse = new AaiGetVnfResponse(); - vnfResponse.setResults(vnfResults); - return new AaiResponse<>(vnfResponse, null, HttpStatus.SC_OK); - } - - private VnfResult createVnfResult(String id, String nodeType) { - VnfResult result = new VnfResult(); - result.setJsonId(id); - result.setJsonNodeType(nodeType); - return result; - } - - - private org.onap.vid.aai.model.AaiGetServicesRequestModel.Service createService(String serviceId, - String resourceVersion, - String serviceDescription) { - org.onap.vid.aai.model.AaiGetServicesRequestModel.Service service - = new org.onap.vid.aai.model.AaiGetServicesRequestModel.Service(); - service.isPermitted = false; - service.resourceVersion = resourceVersion; - service.serviceDescription = serviceDescription; - service.serviceId = serviceId; - return service; - } - - @NotNull - private Services createAaiResponseServices() { - ServiceSubscription sub1 = new ServiceSubscription(); - sub1.isPermitted = false; - sub1.serviceType = "serviceSubsType1"; - - ServiceSubscription sub2 = new ServiceSubscription(); - sub2.isPermitted = true; - sub2.serviceType = "serviceSubsType2"; - - ServiceSubscriptions serviceSubs = new ServiceSubscriptions(); - serviceSubs.serviceSubscription = Collections.singletonList(sub2); - - Services services = new Services(); - services.globalCustomerId = GLOBAL_CUSTOMER_ID; - services.resourceVersion = "v-1"; - services.subscriberName = "name-1"; - services.subscriberType = "type-1"; - services.serviceSubscriptions = serviceSubs; - return services; - } - - @NotNull - private Subscriber createSubscriber() { - Subscriber subscriber = new Subscriber(); - subscriber.globalCustomerId = "id-1"; - subscriber.resourceVersion = "v-1"; - subscriber.subscriberName = "name-1"; - subscriber.subscriberType = "type-1"; - return subscriber; - } + @Test + public void shouldGetPortMirroringConfigData() { + AaiResponseTranslator.PortMirroringConfigData expectedData + = mock(AaiResponseTranslator.PortMirroringConfigData.class); + + when(aaiClient.getCloudRegionAndSourceByPortMirroringConfigurationId(anyString())) + .thenReturn(aaiResponseJsonNode); + when(aaiResponseTranslator.extractPortMirroringConfigData(aaiResponseJsonNode)).thenReturn(expectedData); + + AaiResponseTranslator.PortMirroringConfigData actualData = aaiService.getPortMirroringConfigData(anyString()); + assertThat(actualData).isEqualTo(expectedData); + } + + + @Test + public void shouldGetInstanceGroupsByVnfInstanceId() { + List instanceGroupInfo = Collections.singletonList(new InstanceGroupInfo(CORRECT_VALUE)); + AaiGetRelatedInstanceGroupsByVnfId relatedInstanceGroups = new AaiGetRelatedInstanceGroupsByVnfId(); + relatedInstanceGroups.setRelationshipList(createRelationshipList()); + + AaiResponse correctCodeResponse = + new AaiResponse<>(relatedInstanceGroups, null, HttpStatus.SC_OK); + + AaiResponse> expectedCorrectCodeResponse = + new AaiResponse<>(instanceGroupInfo, null, HttpStatus.SC_OK); + AaiResponse expectedIncorrectCodeResponse = + new AaiResponse<>(relatedInstanceGroups, null, HttpStatus.SC_PAYMENT_REQUIRED); + List expectedCorrectResponseObject = expectedCorrectCodeResponse.getT(); + + when(aaiClient.getInstanceGroupsByVnfInstanceId(VNF_INSTANCE_ID_OK)).thenReturn(correctCodeResponse); + when(aaiClient.getInstanceGroupsByVnfInstanceId(VNF_INSTANCE_ID_FAIL)) + .thenReturn(expectedIncorrectCodeResponse); + + AaiResponse actualCorrectCodeResponse = aaiService.getInstanceGroupsByVnfInstanceId(VNF_INSTANCE_ID_OK); + AaiResponse actualIncorrectCodeResponse = aaiService.getInstanceGroupsByVnfInstanceId(VNF_INSTANCE_ID_FAIL); + + List actualCorrectResponseObject = + (List) actualCorrectCodeResponse.getT(); + + assertThat(actualCorrectResponseObject) + .usingFieldByFieldElementComparator() + .hasSameElementsAs(expectedCorrectResponseObject); + + assertThat(actualIncorrectCodeResponse).isEqualTo(expectedIncorrectCodeResponse); + } + + @Test + public void shouldGetHomingDataByVfModule() { + GetTenantsResponse expectedResponse = new GetTenantsResponse(); + when(aaiClient.getHomingDataByVfModule(anyString(), anyString())).thenReturn(expectedResponse); + + GetTenantsResponse actualResponse = aaiService.getHomingDataByVfModule(anyString(), anyString()); + assertThat(actualResponse).isEqualTo(expectedResponse); + } + + @Test + public void shouldSearchGroupMembers() { + Properties properties = createProperties(); + Map regionsAndTenants = createRegionsAndTenantsMap(properties); + + AAITreeNode validTreeNode = new AAITreeNode(); + addAdditionalPropertiesToAaiTreeNode(validTreeNode); + List validNodes = Arrays.asList(validTreeNode, validTreeNode); + + AAITreeNode validBranch = createTree(validNodes); + addAdditionalPropertiesToAaiTreeNode(validBranch); + List testedBranches = Collections.singletonList(validBranch); + + AAITreeNode testedTree = createTree(testedBranches); + + RelatedVnf expectedVnf = createExpectedVnf(validBranch); + List expectedResult = Collections.singletonList(expectedVnf); + + when(aaiServiceTree.buildAAITree(anyString(), isNull(), eq(HttpMethod.GET), any(), anyBoolean())) + .thenReturn(Collections.singletonList(testedTree)); + when(aaiClient.getCloudRegionAndTenantByVnfId(anyString())).thenReturn(regionsAndTenants); + + List actualGroupMembers = aaiService.searchGroupMembers(GLOBAL_CUSTOMER_ID, SERVICE_TYPE, + INVARIANT_ID, GROUP_TYPE_FAILING, GROUP_ROLE_FAILING); + + assertThat(actualGroupMembers) + .usingFieldByFieldElementComparator() + .hasSameElementsAs(expectedResult); + } + + @Test + public void shouldGetPortMirroringSourcePorts() { + PortDetailsTranslator.PortDetails details = mock(PortDetailsTranslator.PortDetails.class); + List expectedDetailsList = Arrays.asList( + details, details, details + ); + + when(aaiClient.getPortMirroringSourcePorts(anyString())).thenReturn(expectedDetailsList); + List actualDetails = aaiService.getPortMirroringSourcePorts(anyString()); + + assertThat(actualDetails).isEqualTo(expectedDetailsList); + } + + @Test + public void shouldGetAAIServiceTree() throws JsonProcessingException { + ServiceInstance serviceInstance = mock(ServiceInstance.class); + String expectedResult = new ObjectMapper().writeValueAsString(serviceInstance); + + when(aaiServiceTree.getServiceInstanceTopology(anyString(), anyString(), anyString())) + .thenReturn(serviceInstance); + String actualResult = aaiService.getAAIServiceTree(anyString(), anyString(), anyString()); + + assertThat(actualResult).isEqualTo(expectedResult); + } + + @NotNull + private Map createRegionsAndTenantsMap(Properties properties) { + Map regionsAndTenants = new HashMap<>(); + regionsAndTenants.put("tenant", properties); + regionsAndTenants.put("cloud-region", properties); + return regionsAndTenants; + } + + private Properties createProperties() { + Properties properties = new Properties(); + properties.setTenantId(TENANT_ID); + properties.setTenantName(TENANT_NAME); + properties.setCloudRegionId(CLOUD_REGION_ID); + return properties; + } + + @NotNull + private RelatedVnf createExpectedVnf(AAITreeNode validBranch) { + RelatedVnf expectedVnf = RelatedVnf.from(validBranch); + expectedVnf.setTenantId(TENANT_ID); + expectedVnf.setTenantName(TENANT_NAME); + expectedVnf.setLcpCloudRegionId(CLOUD_REGION_ID); + expectedVnf.setServiceInstanceId(PARENT_ID); + expectedVnf.setServiceInstanceName(PARENT_NAME); + expectedVnf.setInstanceType(VNF_TYPE); + + return expectedVnf; + } + + + private AAITreeNode createTree(List children) { + AAITreeNode tree = new AAITreeNode(); + tree.addChildren(children); + tree.setId(PARENT_ID); + tree.setName(PARENT_NAME); + tree.setType(SERVICE_INSTANCE); + return tree; + } + + private void addAdditionalPropertiesToAaiTreeNode(AAITreeNode tree) { + Map additionalProperties = new HashMap<>(); + additionalProperties.put("instance-group-role", GROUP_ROLE_OK); + additionalProperties.put("instance-group-type", group_type_ok); + additionalProperties.put("vnf-type", VNF_TYPE); + additionalProperties.put("cloud-region", CLOUD_TYPE); + tree.setAdditionalProperties(additionalProperties); + } + + private org.onap.vid.asdc.beans.Service createService(String category, String suffix) { + return new Service.ServiceBuilder() + .setUuid("MODELVER_VERSION_ID" + suffix) + .setInvariantUUID("MODEL_INVARIANT_NAME" + suffix) + .setCategory(category) + .setVersion("MODELVER_VERSION" + suffix) + .setName("MODELVER_NAME" + suffix) + .setDistributionStatus("MODELVER_DIST_STATUS" + suffix) + .setToscaModelURL(null) + .setLifecycleState(null) + .setArtifacts(null) + .setResources(null) + .build(); + } + + @NotNull + private Result createResultWithoutValidModel() { + ModelVers modelVers = new ModelVers(); + modelVers.setModelVer(Collections.singletonList(new ModelVer())); + + Model model = new Model(); + model.setModelVers(modelVers); + + Result result1 = new Result(); + result1.setModel(model); + return result1; + } + + @NotNull + private Result createResult(String modelType, String suffix) { + ModelVer modelVer = new ModelVer(); + modelVer.setModelVersionId("MODELVER_VERSION_ID" + suffix); + modelVer.setModelVersion("MODELVER_VERSION" + suffix); + modelVer.setModelName("MODELVER_NAME" + suffix); + modelVer.setDistributionStatus("MODELVER_DIST_STATUS" + suffix); + + ModelVers modelVers = new ModelVers(); + modelVers.setModelVer(Collections.singletonList(modelVer)); + + Model model = new Model(); + model.setModelType(modelType); + model.setModelInvariantId("MODEL_INVARIANT_NAME" + suffix); + model.setModelVers(modelVers); + + Result result = new Result(); + result.setModel(model); + return result; + } + + @NotNull + private ServiceRelationships createServiceRelationships() { + RelationshipList relationsList = createRelationshipList(CORRECT_VALUE); + ServiceRelationships relationsService = new ServiceRelationships(); + relationsService.setRelationshipList(relationsList); + return relationsService; + } + + @NotNull + private RelationshipList createRelationshipList(String expectedValue) { + List relationsDataList = createRelationshipDataList(expectedValue); + return createRelationshipList(relationsDataList); + } + + @NotNull + private RelationshipList createRelationshipList(List relationsDataList) { + Relationship relation1 = crateRelationship("any", relationsDataList); + Relationship relation2 = crateRelationship("zone", relationsDataList); + Relationship relation3 = crateRelationship("logical-link", relationsDataList); + Relationship relation4 = crateRelationship("lag-interface", relationsDataList); + Relationship relation5 = crateRelationship("pnf", relationsDataList); + + RelationshipList relationsList = new RelationshipList(); + relationsList.setRelationship(Arrays.asList(relation1, relation2, relation3, relation4, relation5)); + return relationsList; + } + + @NotNull + private List createRelationshipDataList(String expectedValue) { + RelationshipData relationData1 = createRelationshipData("any-key", "incorrect_key"); + RelationshipData relationData2 = createRelationshipData("zone.zone-id", expectedValue); + RelationshipData relationData3 = createRelationshipData("logical-link.link-name", expectedValue); + RelationshipData relationData4 = createRelationshipData("pnf.pnf-name", expectedValue); + + return Arrays.asList(relationData1, relationData2, relationData3, relationData4); + } + + @NotNull + private Relationship crateRelationship(String relatedTo, List relationsDataList) { + Relationship relation = new Relationship(); + relation.setRelatedTo(relatedTo); + relation.setRelationDataList(relationsDataList); + return relation; + } + + @NotNull + private RelationshipData createRelationshipData(String key, String value) { + RelationshipData relationData = new RelationshipData(); + relationData.setRelationshipKey(key); + relationData.setRelationshipValue(value); + return relationData; + } + + private org.onap.vid.aai.model.AaiGetNetworkCollectionDetails.RelationshipList createRelationshipList() { + RelatedToProperty property1 = + createRelatedToProperty("instance-group.instance-group-name", CORRECT_VALUE); + RelatedToProperty property2 = + createRelatedToProperty("anything-key", "anything-value"); + List properties = Arrays.asList(property1, property2); + + org.onap.vid.aai.model.AaiGetNetworkCollectionDetails.Relationship relationship1 = + createRelationship("instance-group", properties); + org.onap.vid.aai.model.AaiGetNetworkCollectionDetails.Relationship relationship2 = + createRelationship("any-key", properties); + + List relationships = + Arrays.asList(relationship1, relationship2); + + org.onap.vid.aai.model.AaiGetNetworkCollectionDetails.RelationshipList relationshipList = + new org.onap.vid.aai.model.AaiGetNetworkCollectionDetails.RelationshipList(); + relationshipList.setRelationship(relationships); + + return relationshipList; + } + + @NotNull + private org.onap.vid.aai.model.AaiGetNetworkCollectionDetails.Relationship createRelationship(String relatedTo, + List relatedToPropertyList) { + org.onap.vid.aai.model.AaiGetNetworkCollectionDetails.Relationship relationship1 = + new org.onap.vid.aai.model.AaiGetNetworkCollectionDetails.Relationship(); + relationship1.setRelatedTo(relatedTo); + relationship1.setRelatedToPropertyList(relatedToPropertyList); + return relationship1; + } + + @NotNull + private RelatedToProperty createRelatedToProperty(String key, String value) { + RelatedToProperty prop = new RelatedToProperty(); + prop.setKey(key); + prop.setValue(value); + return prop; + } + + @NotNull + private AaiResponse createAaiResponseVnfResponse(List vnfResults) { + AaiGetVnfResponse vnfResponse = new AaiGetVnfResponse(); + vnfResponse.setResults(vnfResults); + return new AaiResponse<>(vnfResponse, null, HttpStatus.SC_OK); + } + + private VnfResult createVnfResult(String id, String nodeType) { + VnfResult result = new VnfResult(); + result.setJsonId(id); + result.setJsonNodeType(nodeType); + return result; + } + + + private org.onap.vid.aai.model.AaiGetServicesRequestModel.Service createService(String serviceId, + String resourceVersion, + String serviceDescription) { + org.onap.vid.aai.model.AaiGetServicesRequestModel.Service service + = new org.onap.vid.aai.model.AaiGetServicesRequestModel.Service(); + service.isPermitted = false; + service.resourceVersion = resourceVersion; + service.serviceDescription = serviceDescription; + service.serviceId = serviceId; + return service; + } + + @NotNull + private Services createAaiResponseServices() { + ServiceSubscription sub1 = new ServiceSubscription(); + sub1.isPermitted = false; + sub1.serviceType = "serviceSubsType1"; + + ServiceSubscription sub2 = new ServiceSubscription(); + sub2.isPermitted = true; + sub2.serviceType = "serviceSubsType2"; + + ServiceSubscriptions serviceSubs = new ServiceSubscriptions(); + serviceSubs.serviceSubscription = Collections.singletonList(sub2); + + Services services = new Services(); + services.globalCustomerId = GLOBAL_CUSTOMER_ID; + services.resourceVersion = "v-1"; + services.subscriberName = "name-1"; + services.subscriberType = "type-1"; + services.serviceSubscriptions = serviceSubs; + return services; + } + + @NotNull + private Subscriber createSubscriber() { + Subscriber subscriber = new Subscriber(); + subscriber.globalCustomerId = "id-1"; + subscriber.resourceVersion = "v-1"; + subscriber.subscriberName = "name-1"; + subscriber.subscriberType = "type-1"; + return subscriber; + } } diff --git a/vid-app-common/src/test/java/org/onap/vid/services/AsyncInstantiationBaseTest.java b/vid-app-common/src/test/java/org/onap/vid/services/AsyncInstantiationBaseTest.java index 401a56c58..4cab99816 100644 --- a/vid-app-common/src/test/java/org/onap/vid/services/AsyncInstantiationBaseTest.java +++ b/vid-app-common/src/test/java/org/onap/vid/services/AsyncInstantiationBaseTest.java @@ -25,11 +25,16 @@ import com.google.common.collect.ImmutableMap; import org.onap.vid.aai.AaiClientInterface; import org.onap.vid.aai.ExceptionWithRequestInfo; import org.onap.vid.model.Action; +import org.onap.vid.model.VidNotions; +import org.onap.vid.model.VidNotions.InstantiationType; +import org.onap.vid.model.VidNotions.InstantiationUI; +import org.onap.vid.model.VidNotions.ModelCategory; import org.onap.vid.model.serviceInstantiation.*; import org.onap.vid.mso.RestObject; import org.onap.vid.mso.model.ModelInfo; import org.onap.vid.mso.rest.AsyncRequestStatus; import org.onap.vid.mso.rest.RequestStatus; +import org.onap.vid.properties.Features; import org.onap.vid.utils.TimeUtils; import org.springframework.http.HttpMethod; import org.springframework.test.context.testng.AbstractTestNGSpringContextTests; @@ -38,14 +43,18 @@ import org.togglz.core.manager.FeatureManager; import javax.inject.Inject; import java.time.ZonedDateTime; import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import static java.util.Collections.emptyList; import static java.util.Collections.emptyMap; -import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.when; public class AsyncInstantiationBaseTest extends AbstractTestNGSpringContextTests { public static final String OWNING_ENTITY_ID = "038d99af-0427-42c2-9d15-971b99b9b489"; + public static final String JULIO_ERICKSON = "JULIO ERICKSON"; public static final String PACKET_CORE = "PACKET CORE"; public static final String PROJECT_NAME = "{some project name}"; public static final String SUBSCRIBER_ID = "{some subscriber id}"; @@ -98,7 +107,7 @@ public class AsyncInstantiationBaseTest extends AbstractTestNGSpringContextTests return new ServiceInstantiation ( modelInfo, AsyncInstantiationBusinessLogicTest.OWNING_ENTITY_ID, - AsyncInstantiationBusinessLogicTest.PACKET_CORE, + AsyncInstantiationBusinessLogicTest.JULIO_ERICKSON, projectName, AsyncInstantiationBusinessLogicTest.SUBSCRIBER_ID, AsyncInstantiationBusinessLogicTest.SUBSCRIBER_NAME, @@ -114,6 +123,7 @@ public class AsyncInstantiationBaseTest extends AbstractTestNGSpringContextTests vnfs, networks, vnfGroups, + null, instanceParams, isPause, bulkSize, @@ -121,8 +131,8 @@ public class AsyncInstantiationBaseTest extends AbstractTestNGSpringContextTests isAlacarte, testApi, instanceId, - action.name() - ); + action.name(), + UUID.randomUUID().toString(), null, null, null); } private List> createInstanceParams() { @@ -146,10 +156,12 @@ public class AsyncInstantiationBaseTest extends AbstractTestNGSpringContextTests if (isAlacarte) { vfModuleInfo.setModelInvariantId("22222222-f63c-463e-ba94-286933b895f9"); vfModuleInfo.setModelVersion("10.0"); - return new VfModule(vfModuleInfo, instanceName, volumeGroupInstanceName, Action.Create.name(), "mdt1", null, "88a6ca3ee0394ade9403f075db23167e", instanceParams, supplementaryParams, false, true, null); + return new VfModule(vfModuleInfo, instanceName, volumeGroupInstanceName, Action.Create.name(), "mdt1", null, + "88a6ca3ee0394ade9403f075db23167e", instanceParams, supplementaryParams, false, true, null, UUID.randomUUID().toString(), null, null); } - return new VfModule(vfModuleInfo, instanceName, volumeGroupInstanceName, Action.Create.name(), null, null, null, instanceParams, supplementaryParams, false, false, null); + return new VfModule(vfModuleInfo, instanceName, volumeGroupInstanceName, Action.Create.name(), null, null, null, + instanceParams, supplementaryParams, false, false, null, UUID.randomUUID().toString(), null, null); } protected ModelInfo createVnfModelInfo(boolean isAlacarte) { @@ -167,19 +179,20 @@ public class AsyncInstantiationBaseTest extends AbstractTestNGSpringContextTests return vnfModelInfo; } - private ModelInfo createNetworkModelInfo(boolean isAlacarte) { - ModelInfo vnfModelInfo = new ModelInfo(); - vnfModelInfo.setModelType("network"); - vnfModelInfo.setModelName("2016-73_MOW-AVPN-vPE-BV-L"); - vnfModelInfo.setModelVersionId("7f40c192-f63c-463e-ba94-286933b895f8"); - vnfModelInfo.setModelCustomizationName("2016-73_MOW-AVPN-vPE-BV-L 0"); - vnfModelInfo.setModelCustomizationId("ab153b6e-c364-44c0-bef6-1f2982117f04"); + private ModelInfo createNetworkModelInfo(boolean isAlacarte, String modelCustomizationId) + { + ModelInfo modelInfo = new ModelInfo(); + modelInfo.setModelType("network"); + modelInfo.setModelName("2016-73_MOW-AVPN-vPE-BV-L"); + modelInfo.setModelVersionId("7f40c192-f63c-463e-ba94-286933b895f8"); + modelInfo.setModelCustomizationName("2016-73_MOW-AVPN-vPE-BV-L 0"); + modelInfo.setModelCustomizationId(modelCustomizationId); //added two conditional fields according to MSO AID - needed only in alacarte if (isAlacarte) { - vnfModelInfo.setModelInvariantId("11111111-f63c-463e-ba94-286933b895f9"); - vnfModelInfo.setModelVersion("10.0"); + modelInfo.setModelInvariantId("11111111-f63c-463e-ba94-286933b895f9"); + modelInfo.setModelVersion("10.0"); } - return vnfModelInfo; + return modelInfo; } private ModelInfo createModelInfo() { @@ -214,21 +227,33 @@ public class AsyncInstantiationBaseTest extends AbstractTestNGSpringContextTests vfModules.get(vfModuleModelName).put(vfModuleModelName + ":002", vfModule2); Vnf vnf = new Vnf(vnfModelInfo, "a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb", (isUserProvidedNaming ? VNF_NAME : null), Action.Create.name(), - "platformName", "mdt1", null, "88a6ca3ee0394ade9403f075db23167e", vnfInstanceParams,"lineOfBusinessName" , false, null, vfModules); + "platformName", "mdt1", null, "88a6ca3ee0394ade9403f075db23167e", vnfInstanceParams,"lineOfBusinessName" , false, null, vfModules, + UUID.randomUUID().toString(), null, null); vnfs.put(vnf.getModelInfo().getModelName(), vnf); return vnfs; } - protected Map createNetworkList(List vnfInstanceParams, boolean isUserProvidedNaming, boolean isALaCarte) { - Map networks = new HashMap<>(); - ModelInfo networkModelInfo = createNetworkModelInfo(isALaCarte); + public static class NetworkDetails { + + public NetworkDetails(String name, String modelCustomizationId) { + this.name = name; + this.modelCustomizationId = modelCustomizationId; + } + + public String name; + public String modelCustomizationId; + } - Network network = new Network(networkModelInfo, "a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb", isUserProvidedNaming ? VNF_NAME : null, Action.Create.name(), - "platformName", "mdt1", null, "88a6ca3ee0394ade9403f075db23167e", vnfInstanceParams,"lineOfBusinessName" , false, null); - networks.put(network.getModelInfo().getModelName(), network); - return networks; + protected Map createNetworkList(List instanceParams, List networkDetails, boolean isALaCarte) { + Stream networkStream = networkDetails.stream().map( + details->new Network(createNetworkModelInfo(isALaCarte, details.modelCustomizationId), "a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb", + details.name, Action.Create.name(), + "platformName", "mdt1", null, "88a6ca3ee0394ade9403f075db23167e", instanceParams,"lineOfBusinessName" , + false, null, UUID.randomUUID().toString(), null, null)); +// I can't tell why compiler don't like the statement if it's only one line... + return networkStream.collect(Collectors.toMap(network -> network.getModelInfo().getModelCustomizationId(), network -> network)); } protected InstanceGroup createInstanceGroup(boolean isUserProvidedNaming, Action action) { @@ -241,7 +266,7 @@ public class AsyncInstantiationBaseTest extends AbstractTestNGSpringContextTests modelInfo.setModelInvariantId("11111111-f63c-463e-ba94-286933b895f9"); modelInfo.setModelVersion("10.0"); - return new InstanceGroup(modelInfo, (isUserProvidedNaming ? VNF_GROUP_NAME : null), action.name(), false, null); + return new InstanceGroup(modelInfo, (isUserProvidedNaming ? VNF_GROUP_NAME : null), action.name(), false, null, emptyMap(), UUID.randomUUID().toString(), null, null); } protected ModelInfo createServiceModelInfo() { @@ -277,11 +302,11 @@ public class AsyncInstantiationBaseTest extends AbstractTestNGSpringContextTests return asyncRequestStatus; } - protected RestObject asyncRequestStatusResponseAsRestObject(String msoStatus) { + public static RestObject asyncRequestStatusResponseAsRestObject(String msoStatus) { return asyncRequestStatusResponseAsRestObject(msoStatus, 200); } - protected RestObject asyncRequestStatusResponseAsRestObject(String msoStatus, int httpStatusCode) { + public static RestObject asyncRequestStatusResponseAsRestObject(String msoStatus, int httpStatusCode) { RestObject restObject = new RestObject<>(); restObject.set(asyncRequestStatusResponse(msoStatus)); restObject.setStatusCode(httpStatusCode); @@ -302,6 +327,12 @@ public class AsyncInstantiationBaseTest extends AbstractTestNGSpringContextTests return serviceInstantiation; } + protected ServiceInstantiation generateALaCarteWithNetworksPayload(List networkDetails) { + Map networks = createNetworkList(emptyList(), networkDetails, true); + ServiceInstantiation serviceInstantiation = generateMockALaCarteServiceInstantiationPayload(false, emptyMap(), networks, emptyMap(), 1, true, PROJECT_NAME, false, "VNF_API"); + return serviceInstantiation; + } + protected ServiceInstantiation generateALaCarteUpdateWith1ExistingGroup2NewGroupsPayload() { final InstanceGroup instanceGroup1 = createInstanceGroup(true, Action.None); final InstanceGroup instanceGroup2 = createInstanceGroup(false, Action.Create); @@ -315,4 +346,38 @@ public class AsyncInstantiationBaseTest extends AbstractTestNGSpringContextTests 1, true, PROJECT_NAME, false, true, "VNF_API", Action.None, "1234567890"); } + + protected void enableAddCloudOwnerOnMsoRequest() { + enableAddCloudOwnerOnMsoRequest(true); + } + + protected void enableAddCloudOwnerOnMsoRequest(boolean isActive) { + // always turn on the feature flag + when(featureManager.isActive(Features.FLAG_1810_CR_ADD_CLOUD_OWNER_TO_MSO_REQUEST)).thenReturn(isActive); + when(aaiClient.getCloudOwnerByCloudRegionId(anyString())).thenReturn("irma-aic"); + } + + protected ServiceInstantiation generateALaCarteServiceInstantiationPayload() { + return generateMockALaCarteServiceInstantiationPayload(false, Collections.EMPTY_MAP, Collections.EMPTY_MAP, Collections.EMPTY_MAP, 1, true, PROJECT_NAME, false, "VNF_API"); + } + + protected ServiceInstantiation generateMacroMockServiceInstantiationPayload(boolean isPause, Map vnfs) { + return generateMockMacroServiceInstantiationPayload(isPause, vnfs, 1, true, PROJECT_NAME, false); + } + + protected ServiceInstantiation generatePre1806MacroTransportServiceInstantiationPayload(String tenantId, String lcpCloudRegionId) { + List> instanceParams = ImmutableList.of(ImmutableMap.of("someUserParam","someValue", "anotherUserParam","anotherValue")); + ServiceInstantiation serviceInstantiation = new ServiceInstantiation(createServiceModelInfo(), "038d99af-0427-42c2-9d15-971b99b9b489", + "JULIO ERICKSON", "some_project_name", "some_subscriber_id", "some_subscriber_name", + "a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb", null, "MOG", lcpCloudRegionId, null, tenantId, + null, null, null, Collections.EMPTY_MAP, Collections.EMPTY_MAP, Collections.EMPTY_MAP, Collections.EMPTY_MAP, instanceParams, false, 1, false, false, + null, null, null, null, null, null, + new VidNotions(InstantiationUI.TRANSPORT_SERVICE, ModelCategory.Transport, InstantiationUI.TRANSPORT_SERVICE, InstantiationType.Macro) + ); + return serviceInstantiation; + } + + protected void mockAaiClientAaiStatusOK() { + when(aaiClient.isNodeTypeExistsByName(eq(AsyncInstantiationBusinessLogicImpl.NAME_FOR_CHECK_AAI_STATUS), any())).thenReturn(false); + } } diff --git a/vid-app-common/src/test/java/org/onap/vid/services/AsyncInstantiationBusinessLogicTest.java b/vid-app-common/src/test/java/org/onap/vid/services/AsyncInstantiationBusinessLogicTest.java index 21b8f3f00..e2d182c06 100644 --- a/vid-app-common/src/test/java/org/onap/vid/services/AsyncInstantiationBusinessLogicTest.java +++ b/vid-app-common/src/test/java/org/onap/vid/services/AsyncInstantiationBusinessLogicTest.java @@ -7,9 +7,9 @@ * 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. @@ -20,69 +20,13 @@ package org.onap.vid.services; -import static com.google.common.collect.Maps.newHashMap; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.contains; -import static org.hamcrest.Matchers.hasItem; -import static org.hamcrest.Matchers.hasItems; -import static org.hamcrest.Matchers.hasProperty; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.matchesPattern; -import static org.hamcrest.Matchers.not; -import static org.hamcrest.core.Every.everyItem; -import static org.hamcrest.core.IsEqual.equalTo; -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.anyInt; -import static org.mockito.Mockito.anyString; -import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import static org.onap.vid.job.Job.JobStatus.COMPLETED; -import static org.onap.vid.job.Job.JobStatus.FAILED; -import static org.onap.vid.job.Job.JobStatus.IN_PROGRESS; -import static org.onap.vid.job.Job.JobStatus.PAUSE; -import static org.onap.vid.job.Job.JobStatus.PENDING; -import static org.onap.vid.job.Job.JobStatus.STOPPED; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertFalse; -import static org.testng.Assert.assertNotNull; -import static org.testng.Assert.assertNull; -import static org.testng.Assert.assertTrue; - -import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; -import java.io.IOException; -import java.lang.reflect.Method; -import java.net.URL; -import java.time.Instant; -import java.time.LocalDateTime; -import java.time.ZoneId; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Comparator; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.stream.Collectors; -import java.util.stream.IntStream; -import javax.inject.Inject; -import net.javacrumbs.jsonunit.JsonAssert; import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.time.DateUtils; import org.hibernate.SessionFactory; +import org.jetbrains.annotations.NotNull; import org.json.JSONException; import org.mockito.ArgumentCaptor; import org.mockito.Mock; @@ -97,48 +41,64 @@ import org.onap.vid.aai.model.ResourceType; import org.onap.vid.changeManagement.RequestDetailsWrapper; import org.onap.vid.config.DataSourceConfig; import org.onap.vid.config.MockedAaiClientAndFeatureManagerConfig; -import org.onap.vid.exceptions.GenericUncheckedException; +import org.onap.vid.dal.AsyncInstantiationRepository; import org.onap.vid.exceptions.MaxRetriesException; +import org.onap.vid.exceptions.NotFoundException; import org.onap.vid.exceptions.OperationNotAllowedException; import org.onap.vid.job.Job; import org.onap.vid.job.Job.JobStatus; import org.onap.vid.job.JobAdapter; import org.onap.vid.job.JobType; import org.onap.vid.job.JobsBrokerService; +import org.onap.vid.job.command.MsoRequestBuilder; +import org.onap.vid.job.command.ResourceCommandTest.FakeResourceCreator; import org.onap.vid.job.impl.JobDaoImpl; import org.onap.vid.job.impl.JobSharedData; -import org.onap.vid.model.Action; -import org.onap.vid.model.JobAuditStatus; -import org.onap.vid.model.JobAuditStatus.SourceStatus; -import org.onap.vid.model.NameCounter; -import org.onap.vid.model.ServiceInfo; -import org.onap.vid.model.serviceInstantiation.InstanceGroup; -import org.onap.vid.model.serviceInstantiation.Network; +import org.onap.vid.model.*; +import org.onap.vid.model.serviceInstantiation.BaseResource; import org.onap.vid.model.serviceInstantiation.ServiceInstantiation; -import org.onap.vid.model.serviceInstantiation.VfModule; import org.onap.vid.model.serviceInstantiation.Vnf; import org.onap.vid.mso.MsoOperationalEnvironmentTest; -import org.onap.vid.mso.model.InstanceGroupInstantiationRequestDetails; +import org.onap.vid.mso.RestObject; import org.onap.vid.mso.model.ModelInfo; -import org.onap.vid.mso.model.NetworkInstantiationRequestDetails; -import org.onap.vid.mso.model.ServiceDeletionRequestDetails; import org.onap.vid.mso.model.ServiceInstantiationRequestDetails; -import org.onap.vid.mso.model.VfModuleInstantiationRequestDetails; -import org.onap.vid.mso.model.VfModuleMacro; -import org.onap.vid.mso.model.VnfInstantiationRequestDetails; -import org.onap.vid.mso.model.VolumeGroupRequestDetails; import org.onap.vid.mso.rest.AsyncRequestStatus; +import org.onap.vid.mso.rest.RequestStatus; import org.onap.vid.properties.Features; import org.onap.vid.testUtils.TestUtils; import org.onap.vid.utils.DaoUtils; +import org.onap.vid.utils.TimeUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.testng.Assert; -import org.testng.annotations.AfterMethod; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeMethod; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; +import org.testng.annotations.*; + +import javax.inject.Inject; +import java.io.IOException; +import java.lang.reflect.Method; +import java.net.URL; +import java.time.*; +import java.util.Optional; +import java.util.*; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import static net.javacrumbs.jsonunit.JsonAssert.assertJsonEquals; +import static net.javacrumbs.jsonunit.JsonAssert.whenIgnoringPaths; +import static net.javacrumbs.jsonunit.JsonMatchers.jsonEquals; +import static net.javacrumbs.jsonunit.core.Option.IGNORING_ARRAY_ORDER; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; +import static org.hamcrest.core.Every.everyItem; +import static org.hamcrest.core.IsEqual.equalTo; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.*; +import static org.onap.vid.job.Job.JobStatus.*; +import static org.onap.vid.testUtils.TestUtils.generateRandomAlphaNumeric; +import static org.testng.Assert.*; @ContextConfiguration(classes = {DataSourceConfig.class, SystemProperties.class, MockedAaiClientAndFeatureManagerConfig.class}) public class AsyncInstantiationBusinessLogicTest extends AsyncInstantiationBaseTest { @@ -152,24 +112,42 @@ public class AsyncInstantiationBusinessLogicTest extends AsyncInstantiationBaseT @Mock private JobsBrokerService jobsBrokerServiceMock; + private AsyncInstantiationRepository asyncInstantiationRepository; + + private AuditService auditService; @Autowired private SessionFactory sessionFactory; private AsyncInstantiationBusinessLogicImpl asyncInstantiationBL; + protected MsoRequestBuilder msoRequestBuilder; + private int serviceCount = 0; private static final String UPDATE_SERVICE_INFO_EXCEPTION_MESSAGE = - "Failed to retrieve job with uuid .* from ServiceInfo table. Instances found: .*"; + "Failed to retrieve class .*ServiceInfo with jobId .* from table. no resource found"; private static final String DELETE_SERVICE_INFO_STATUS_EXCEPTION_MESSAGE = "Service status does not allow deletion from the queue"; + private String uuidRegex = "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}"; + private org.hamcrest.Matcher uuidRegexMatcher = is(matchesPattern(uuidRegex)); + + @BeforeClass void initServicesInfoService() { MockitoAnnotations.initMocks(this); - asyncInstantiationBL = new AsyncInstantiationBusinessLogicImpl(dataAccessService, jobAdapterMock, jobsBrokerServiceMock, sessionFactory, aaiClient, featureManager, cloudOwnerService); + AsyncInstantiationRepository realAsyncInstantiationRepository = new AsyncInstantiationRepository(dataAccessService); + asyncInstantiationRepository = spy(realAsyncInstantiationRepository); + + auditService = new AuditServiceImpl(null, asyncInstantiationRepository); + + AsyncInstantiationBusinessLogicImpl realAsyncInstantiationBL = new AsyncInstantiationBusinessLogicImpl(jobAdapterMock, jobsBrokerServiceMock, sessionFactory, aaiClient, featureManager, cloudOwnerService, asyncInstantiationRepository, auditService); + asyncInstantiationBL = Mockito.spy(realAsyncInstantiationBL); + + msoRequestBuilder = new MsoRequestBuilder(asyncInstantiationBL, cloudOwnerService, aaiClient, featureManager); + createInstanceParamsMaps(); } @@ -182,16 +160,6 @@ public class AsyncInstantiationBusinessLogicTest extends AsyncInstantiationBaseT enableAddCloudOwnerOnMsoRequest(); } - private void enableAddCloudOwnerOnMsoRequest() { - enableAddCloudOwnerOnMsoRequest(true); - } - - private void enableAddCloudOwnerOnMsoRequest(boolean isActive) { - // always turn on the feature flag - when(featureManager.isActive(Features.FLAG_1810_CR_ADD_CLOUD_OWNER_TO_MSO_REQUEST)).thenReturn(isActive); - when(aaiClient.getCloudOwnerByCloudRegionId(anyString())).thenReturn("att-aic"); - } - @BeforeMethod void resetServiceCount() { serviceCount = 0; @@ -215,13 +183,13 @@ public class AsyncInstantiationBusinessLogicTest extends AsyncInstantiationBaseT uuid = UUID.randomUUID(); addNewJob(uuid); createdDate = NOW.minusYears(1); - addNewServiceInfo(uuid, userId, "Old", createdDate, createdDate, COMPLETED, false); + addNewServiceInfo(uuid, userId, "Old", createdDate, createdDate, COMPLETED, false, false); uuid = UUID.randomUUID(); addNewJob(uuid); createdDate = NOW.minusDays(20); modifiedDate = NOW.minusDays(19); - addNewServiceInfo(uuid, userId, "Hidden", createdDate, modifiedDate, PAUSE, true); + addNewServiceInfo(uuid, userId, "Hidden", createdDate, modifiedDate, PAUSE, true, false); createNewTestServicesInfo(String.valueOf(userId)); } @@ -236,20 +204,20 @@ public class AsyncInstantiationBusinessLogicTest extends AsyncInstantiationBaseT addNewJob(uuid); createdDate = NOW.minusDays(40); - addNewServiceInfo(uuid, userId, "service instance 5", createdDate, createdDate, COMPLETED, false); - addNewServiceInfo(uuid, userId, "service instance 6", createdDate, createdDate, STOPPED, false); + addNewServiceInfo(uuid, userId, "service instance 5", createdDate, createdDate, COMPLETED, false, false); + addNewServiceInfo(uuid, userId, "service instance 6", createdDate, createdDate, STOPPED, false, false); uuid = UUID.randomUUID(); addNewJob(uuid); createdDate = NOW.minusDays(20); modifiedDate = NOW.minusDays(10); - addNewServiceInfo(uuid, userId, "service instance 4", createdDate, modifiedDate, STOPPED, false); - addNewServiceInfo(uuid, userId, "service instance 2", createdDate, modifiedDate, COMPLETED, false); - addNewServiceInfo(uuid, userId, "service instance 3", createdDate, modifiedDate, PAUSE, false); + addNewServiceInfo(uuid, userId, "service instance 4", createdDate, modifiedDate, STOPPED, false, false); + addNewServiceInfo(uuid, userId, "service instance 2", createdDate, modifiedDate, COMPLETED, false, false); + addNewServiceInfo(uuid, userId, "service instance 3", createdDate, modifiedDate, PAUSE, false, false); modifiedDate = NOW.minusDays(19); - addNewServiceInfo(uuid, userId, "service instance 1", createdDate, modifiedDate, FAILED, false); + addNewServiceInfo(uuid, userId, "service instance 1", createdDate, modifiedDate, FAILED, false, false); // Job to a different user @@ -257,7 +225,7 @@ public class AsyncInstantiationBusinessLogicTest extends AsyncInstantiationBaseT addNewJob(uuid); createdDate = NOW.minusMonths(2); - addNewServiceInfo(uuid, "2221", "service instance 7", createdDate, createdDate, COMPLETED, false); + addNewServiceInfo(uuid, "2221", "service instance 7", createdDate, createdDate, COMPLETED, false, false); } @@ -269,7 +237,7 @@ public class AsyncInstantiationBusinessLogicTest extends AsyncInstantiationBaseT uuid = UUID.randomUUID(); addNewJob(uuid, status); - addNewServiceInfo(uuid, null, "service instance 1", NOW, NOW, status, false); + addNewServiceInfo(uuid, null, "service instance 1", NOW, NOW, status, false, false); return uuid; @@ -292,7 +260,7 @@ public class AsyncInstantiationBusinessLogicTest extends AsyncInstantiationBaseT .toLocalDateTime(); } - private void addNewServiceInfo(UUID uuid, String userId, String serviceName, LocalDateTime createDate, LocalDateTime statusModifiedDate, Job.JobStatus status, boolean isHidden) { + private void addNewServiceInfo(UUID uuid, String userId, String serviceName, LocalDateTime createDate, LocalDateTime statusModifiedDate, JobStatus status, boolean isHidden, boolean retryEnabled) { ServiceInfo serviceInfo = new ServiceInfo(); serviceInfo.setJobId(uuid); serviceInfo.setUserId(userId); @@ -302,6 +270,7 @@ public class AsyncInstantiationBusinessLogicTest extends AsyncInstantiationBaseT serviceInfo.setPause(false); serviceInfo.setOwningEntityId("1234"); serviceInfo.setCreatedBulkDate(toDate(createDate)); + serviceInfo.setRetryEnabled(retryEnabled); serviceInfo.setHidden(isHidden); dataAccessService.saveDomainObject(serviceInfo, getPropsMap()); @@ -334,6 +303,39 @@ public class AsyncInstantiationBusinessLogicTest extends AsyncInstantiationBaseT dataAccessService.saveDomainObject(jobDao, getPropsMap()); } + private ServiceInstantiation addOriginalService(UUID jobId, String userID){ + addNewServiceInfo(jobId, userID, "name", LocalDateTime.now(), LocalDateTime.now(), COMPLETED_WITH_ERRORS, false, true); + assertThat(asyncInstantiationRepository.getServiceInfoByJobId(jobId).isRetryEnabled(), is(true)); + ServiceInstantiation originalServiceInstantiation = prepareServiceInstantiation(true, 1); + doReturn(originalServiceInstantiation).when(asyncInstantiationRepository).getJobRequest(jobId); + return originalServiceInstantiation; + } + + private void assertRetryDisabled(UUID jobId){ + assertThat(asyncInstantiationRepository.getServiceInfoByJobId(jobId).isRetryEnabled(), is(false)); + } + + private void assertNewJobExistsAsExpectedAfterRetry(List newJobIds, ServiceInstantiation expectedServiceInstantiation, UUID jobId, String userId){ + assertThat(newJobIds, hasSize(1)); + assertThat(newJobIds.get(0), not(equalTo(jobId))); + + ArgumentCaptor requestsCaptor = ArgumentCaptor.forClass(ServiceInstantiation.class); + ArgumentCaptor uuidsCaptor = ArgumentCaptor.forClass(UUID.class); + ArgumentCaptor jobTypeCaptor = ArgumentCaptor.forClass(JobType.class); + + verify(asyncInstantiationRepository).addJobRequest(uuidsCaptor.capture(), requestsCaptor.capture()); + verify(jobAdapterMock).createServiceInstantiationJob(jobTypeCaptor.capture(), requestsCaptor.capture(), uuidsCaptor.capture(), eq(userId), any(), anyString(), anyInt()); + verify(jobsBrokerServiceMock).add(any()); + + requestsCaptor.getAllValues().forEach(x->assertJsonEquals(expectedServiceInstantiation, x, whenIgnoringPaths( + "trackById", + "vnfs.2016-73_MOW-AVPN-vPE-BV-L.trackById", + "vnfs.2016-73_MOW-AVPN-vPE-BV-L.vfModules.201673MowAvpnVpeBvL..AVPN_base_vPE_BV..module-0.201673MowAvpnVpeBvL..AVPN_base_vPE_BV..module-0:001.trackById", + "vnfs.2016-73_MOW-AVPN-vPE-BV-L.vfModules.201673MowAvpnVpeBvL..AVPN_base_vPE_BV..module-0.201673MowAvpnVpeBvL..AVPN_base_vPE_BV..module-0:002.trackById" + ))); + + } + @Test public void testServiceInfoAreOrderedAsExpected() { int userId = 2222; @@ -343,6 +345,12 @@ public class AsyncInstantiationBusinessLogicTest extends AsyncInstantiationBaseT assertThat("Services aren't ordered as expected", serviceInfoListResult, equalTo(expectedOrderServiceInfo)); } + @Test + public void whenNewServiceInfoCreated_isRetryEnablesIsFalse() { + UUID uuid = createServicesInfoWithDefaultValues(PENDING); + assertFalse(asyncInstantiationRepository.getServiceInfoByJobId(uuid).isRetryEnabled()); + } + @Test public void testServiceInfoAreFilteredAsExpected() { int userId = 2222; @@ -364,9 +372,9 @@ public class AsyncInstantiationBusinessLogicTest extends AsyncInstantiationBaseT defineMocks(); ServiceInstantiation serviceInstantiationPayload = generateMockMacroServiceInstantiationPayload(isPause, createVnfList(vfModuleInstanceParamsMap, vnfInstanceParams, true), 2, true, PROJECT_NAME, false); final URL resource = this.getClass().getResource("/payload_jsons/bulk_service_request_unique_names.json"); - when(jobAdapterMock.createServiceInstantiationJob(any(), any(), any(), any(), anyString(), any())).thenAnswer(invocation -> { + when(jobAdapterMock.createServiceInstantiationJob(any(), any(), any(), any(), any(), anyString(), any())).thenAnswer(invocation -> { Object[] args = invocation.getArguments(); - return new MockedJob((String)args[4]); + return new MockedJob((String)args[5]); }); when(jobsBrokerServiceMock.add(any(MockedJob.class))).thenAnswer((Answer) invocation -> { @@ -376,13 +384,13 @@ public class AsyncInstantiationBusinessLogicTest extends AsyncInstantiationBaseT return job.getUuid(); }); - when(featureManager.isActive(Features.FLAG_SHIFT_VFMODULE_PARAMS_TO_VNF)).thenReturn(true); + when(asyncInstantiationBL.isPartOfBulk(any())).thenReturn(true); List uuids = asyncInstantiationBL.pushBulkJob(serviceInstantiationPayload, "az2016"); for (int i = 0; i < 2; i++) { UUID currentUuid = uuids.get(i); RequestDetailsWrapper result = - asyncInstantiationBL.generateMacroServiceInstantiationRequest(currentUuid, serviceInstantiationPayload, + msoRequestBuilder.generateMacroServiceInstantiationRequest(currentUuid, serviceInstantiationPayload, MockedJob.getJob(currentUuid).getOptimisticUniqueServiceInstanceName(), "az2016"); String unique = i==0 ? "" : String.format("_00%s", i); String expected = IOUtils.toString(resource, "UTF-8") @@ -403,7 +411,9 @@ public class AsyncInstantiationBusinessLogicTest extends AsyncInstantiationBaseT } protected void verifySearchNodeTypeByName(String unique, String resourceName, ResourceType serviceInstance) { - verify(aaiClient, times(1)).isNodeTypeExistsByName(resourceName + unique, serviceInstance); + String uniqueName = resourceName + unique; + verify(aaiClient, times(1)).isNodeTypeExistsByName(uniqueName, serviceInstance); + when(aaiClient.isNodeTypeExistsByName(uniqueName, serviceInstance)).thenReturn(true); } private HashMap getPropsMap() { @@ -423,25 +433,115 @@ public class AsyncInstantiationBusinessLogicTest extends AsyncInstantiationBaseT @Test(dataProvider="dataProviderForInstanceNames") public void pushBulkJob_bulkWithSize3_instancesNamesAreExactlyAsExpected(boolean isUserProvidedNaming, List expectedNames) { - int bulkSize = 3; + final ServiceInstantiation request = prepareServiceInstantiation(isUserProvidedNaming, 3); + + + asyncInstantiationBL.pushBulkJob(request, "myUserId"); + List serviceInfoList = dataAccessService.getList(ServiceInfo.class, getPropsMap()); + assertEquals(serviceInfoList.stream().map(ServiceInfo::getServiceInstanceName).collect(Collectors.toList()), expectedNames); + } + + protected ServiceInstantiation prepareServiceInstantiation(String projectName, boolean isUserProvidedNaming, int bulkSize) { final ServiceInstantiation request = generateMockMacroServiceInstantiationPayload( false, createVnfList(instanceParamsMapWithoutParams, Collections.EMPTY_LIST, true), - bulkSize, isUserProvidedNaming, PROJECT_NAME, true + bulkSize, isUserProvidedNaming, projectName, true ); // in "createServiceInstantiationJob()" we will probe the service, with the generated names configureMockitoWithMockedJob(); + return request; + } + protected ServiceInstantiation prepareServiceInstantiation(boolean isUserProvidedNaming, int bulkSize) { + return prepareServiceInstantiation(PROJECT_NAME, isUserProvidedNaming, bulkSize); + } - asyncInstantiationBL.pushBulkJob(request, "myUserId"); - List serviceInfoList = dataAccessService.getList(ServiceInfo.class, getPropsMap()); - assertEquals(serviceInfoList.stream().map(ServiceInfo::getServiceInstanceName).collect(Collectors.toList()), expectedNames); + + @Test + public void whenPushBulkJob_thenJobRequestIsSaveInJobRequestDb() { + Mockito.reset(asyncInstantiationRepository); + int bulkSize = 3; + final ServiceInstantiation request = prepareServiceInstantiation(true, bulkSize); + when(jobsBrokerServiceMock.add(any())).thenReturn(UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID()); + List jobIds = asyncInstantiationBL.pushBulkJob(request, "abc"); + + ArgumentCaptor asyncJobRequestCaptor = ArgumentCaptor.forClass(JobAdapter.AsyncJobRequest.class); + ArgumentCaptor requestsCaptor = ArgumentCaptor.forClass(ServiceInstantiation.class); + ArgumentCaptor uuidsCaptor = ArgumentCaptor.forClass(UUID.class); + verify(asyncInstantiationRepository, times(bulkSize)).addJobRequest(uuidsCaptor.capture(), requestsCaptor.capture()); + verify(jobsBrokerServiceMock, times(bulkSize)).add(any()); + verify(jobAdapterMock, times(bulkSize)).createServiceInstantiationJob(any(), asyncJobRequestCaptor.capture(), any(), any(), any(), any(), any()); + + //verify that all for each job we saved an row in jobRequest table + assertThat(uuidsCaptor.getAllValues(), containsInAnyOrder(jobIds.toArray())); + + //assert that each real job we created with the adaptor, request is save in jobRequest table + assertThat(requestsCaptor.getAllValues(), containsInAnyOrder(asyncJobRequestCaptor.getAllValues().toArray())); + + assertThat(requestsCaptor.getAllValues(),everyItem(hasProperty("bulkSize", is(1)))); + + //assert that the requests that save in DB are the same as original request expect of the trackById + requestsCaptor.getAllValues().forEach(x->assertJsonEquals(request, x, whenIgnoringPaths( + "bulkSize", + "trackById", + "vnfs.2016-73_MOW-AVPN-vPE-BV-L.trackById", + "vnfs.2016-73_MOW-AVPN-vPE-BV-L.vfModules.201673MowAvpnVpeBvL..AVPN_base_vPE_BV..module-0.201673MowAvpnVpeBvL..AVPN_base_vPE_BV..module-0:001.trackById", + "vnfs.2016-73_MOW-AVPN-vPE-BV-L.vfModules.201673MowAvpnVpeBvL..AVPN_base_vPE_BV..module-0.201673MowAvpnVpeBvL..AVPN_base_vPE_BV..module-0:002.trackById" + ))); + + //assert that each trackById on all bulk jobs is unique + Set usedUUID = new HashSet<>(); + requestsCaptor.getAllValues().forEach(x->assertTrackByIdRecursively(x, uuidRegexMatcher, usedUUID)); + } + + @Test + public void whenRetryJob_prevJobRetryIsDisabled() { + reset(asyncInstantiationRepository); + UUID jobId = UUID.randomUUID(); + String userID = generateRandomAlphaNumeric(8); + addOriginalService(jobId, userID); + doReturn(mock(Map.class)).when(asyncInstantiationRepository).getResourceInfoByRootJobId(jobId); + asyncInstantiationBL.retryJob(jobId, userID); + assertRetryDisabled(jobId); + } + + @Test + public void whenRetryJobWithEditedData_prevJobRetryIsDisabled() { + reset(asyncInstantiationRepository); + UUID jobId = UUID.randomUUID(); + String userID = generateRandomAlphaNumeric(8); + addOriginalService(jobId, userID); + ServiceInstantiation editedServiceInstantiation = prepareServiceInstantiation("editedProjectName", true, 1); + asyncInstantiationBL.retryJob(editedServiceInstantiation, jobId, userID); + assertRetryDisabled(jobId); + } + + @Test + public void retryJobWithEditedData_expectedNewJobDifferentData() { + reset(asyncInstantiationRepository); + UUID jobId = UUID.randomUUID(); + String userID = generateRandomAlphaNumeric(8); + addOriginalService(jobId, userID); + ServiceInstantiation editedServiceInstantiation = prepareServiceInstantiation("editedProjectName", true, 1); + List newJobIds = asyncInstantiationBL.retryJob(editedServiceInstantiation, jobId, userID); + assertNewJobExistsAsExpectedAfterRetry(newJobIds, editedServiceInstantiation, jobId, userID); + } + + @Test + public void retryJob_expectedNewJob() { + reset(asyncInstantiationRepository); + UUID jobId = UUID.randomUUID(); + String userID = "az2016"; + ServiceInstantiation originalServiceInstantiation = addOriginalService(jobId, userID); + doReturn(mock(Map.class)).when(asyncInstantiationRepository).getResourceInfoByRootJobId(jobId); + List newJobIds = asyncInstantiationBL.retryJob(jobId, userID); + assertNewJobExistsAsExpectedAfterRetry(newJobIds, originalServiceInstantiation, jobId, userID); } - @Test(dataProvider = "aLaCarteAndMacroPayload") + @Test (dataProvider = "aLaCarteAndMacroPayload") public void generateMockServiceInstantiationPayload_serializeBackAndForth_sourceShouldBeTheSame(ServiceInstantiation serviceInstantiationPayload) throws IOException { ObjectMapper mapper = new ObjectMapper(); final String asString = mapper.writeValueAsString(serviceInstantiationPayload); @@ -449,7 +549,7 @@ public class AsyncInstantiationBusinessLogicTest extends AsyncInstantiationBaseT final ServiceInstantiation asObject = mapper.readValue(asString, ServiceInstantiation.class); final String asString2 = mapper.writeValueAsString(asObject); - JsonAssert.assertJsonEquals(asString, asString2); + assertJsonEquals(asString, asString2); } @DataProvider @@ -517,10 +617,6 @@ public class AsyncInstantiationBusinessLogicTest extends AsyncInstantiationBaseT }; } - private ServiceInstantiation generateMacroMockServiceInstantiationPayload(boolean isPause, Map vnfs) { - return generateMockMacroServiceInstantiationPayload(isPause, vnfs, 1, true, PROJECT_NAME, false); - } - @Test public void testUpdateServiceInfo_WithExistingServiceInfo_ServiceInfoIsUpdated() { UUID uuid = createFakedJobAndServiceInfo(); @@ -550,12 +646,12 @@ public class AsyncInstantiationBusinessLogicTest extends AsyncInstantiationBaseT return uuid; } - @Test(expectedExceptions = GenericUncheckedException.class, expectedExceptionsMessageRegExp = UPDATE_SERVICE_INFO_EXCEPTION_MESSAGE) + @Test(expectedExceptions = NotFoundException.class, expectedExceptionsMessageRegExp = UPDATE_SERVICE_INFO_EXCEPTION_MESSAGE) public void testUpdateServiceInfo_WithNonExisting_ThrowException() { asyncInstantiationBL.updateServiceInfo(UUID.randomUUID(), x -> x.setServiceInstanceName("not matter")); } - @Test(expectedExceptions = GenericUncheckedException.class, expectedExceptionsMessageRegExp = UPDATE_SERVICE_INFO_EXCEPTION_MESSAGE) + @Test(expectedExceptions = NotFoundException.class, expectedExceptionsMessageRegExp = UPDATE_SERVICE_INFO_EXCEPTION_MESSAGE) public void testUpdateServiceInfo_WithDoubleServiceWithSameJobUuid_ThrowException() { UUID uuid = createFakedJobAndServiceInfo(); ServiceInfo serviceInfo = new ServiceInfo(); @@ -584,219 +680,10 @@ public class AsyncInstantiationBusinessLogicTest extends AsyncInstantiationBaseT @Test public void testCreateVnfEndpoint_useProvidedInstanceId() { String path = asyncInstantiationBL.getVnfInstantiationPath("myGreatId"); - assertThat(path, matchesPattern("/serviceInstances/v./myGreatId/vnfs")); - } - - @Test - public void createServiceInfo_WithUserProvidedNamingFalse_ServiceInfoIsAsExpected() throws IOException { - createMacroServiceInfo_WithUserProvidedNamingFalse_ServiceInfoIsAsExpected(true); - } - - @Test - public void createServiceInfo_WithUserProvidedNamingFalseAndNoVfmodules_ServiceInfoIsAsExpected() throws IOException { - createMacroServiceInfo_WithUserProvidedNamingFalse_ServiceInfoIsAsExpected(false); - } - - private void createMacroServiceInfo_WithUserProvidedNamingFalse_ServiceInfoIsAsExpected(boolean withVfmodules) throws IOException { - when(featureManager.isActive(Features.FLAG_SHIFT_VFMODULE_PARAMS_TO_VNF)).thenReturn(true); - - ServiceInstantiation serviceInstantiationPayload = generateMockMacroServiceInstantiationPayload(true, - createVnfList(vfModuleInstanceParamsMapWithParamsToRemove, Collections.EMPTY_LIST, false), - 1, - false, PROJECT_NAME, true); - URL resource; - if (withVfmodules) { - resource = this.getClass().getResource("/payload_jsons/bulk_service_request_ecomp_naming.json"); - } else { - // remove the vf modules - serviceInstantiationPayload.getVnfs().values().forEach(vnf -> vnf.getVfModules().clear()); - resource = this.getClass().getResource("/payload_jsons/bulk_service_request_no_vfmodule_ecomp_naming.json"); - } - - RequestDetailsWrapper result = - asyncInstantiationBL.generateMacroServiceInstantiationRequest(null, serviceInstantiationPayload, serviceInstantiationPayload.getInstanceName(), "az2016"); - - String expected = IOUtils.toString(resource, "UTF-8"); - MsoOperationalEnvironmentTest.assertThatExpectationIsLikeObject(expected, result); - } - - @Test - public void createALaCarteService_WithUserProvidedNamingFalse_RequestDetailsIsAsExpected() throws IOException { - ServiceInstantiation serviceInstantiationPayload = generateMockALaCarteServiceInstantiationPayload(false, - newHashMap(), - newHashMap(), - newHashMap(), - 1, - false, PROJECT_NAME, true, null); - - RequestDetailsWrapper result = - asyncInstantiationBL.generateALaCarteServiceInstantiationRequest(null, serviceInstantiationPayload, serviceInstantiationPayload.getInstanceName(), "az2016"); - - URL resource = this.getClass().getResource("/payload_jsons/bulk_alacarte_service_request_naming_false.json"); - String expected = IOUtils.toString(resource, "UTF-8"); - MsoOperationalEnvironmentTest.assertThatExpectationIsLikeObject(expected, result); - } - - @Test - public void generateALaCarteServiceInstantiationRequest_withVnfList_HappyFllow() throws IOException { - ServiceInstantiation serviceInstantiationPayload = generateALaCarteWithVnfsServiceInstantiationPayload(); - RequestDetailsWrapper result = - asyncInstantiationBL.generateALaCarteServiceInstantiationRequest(null, serviceInstantiationPayload, serviceInstantiationPayload.getInstanceName(), "az2016"); - - String serviceExpected = IOUtils.toString(this.getClass().getResource("/payload_jsons/bulk_alacarte_service_request.json"), "UTF-8"); - MsoOperationalEnvironmentTest.assertThatExpectationIsLikeObject(serviceExpected, result); + assertThat(path, equalTo("/serviceInstantiation/v7/serviceInstances/myGreatId/vnfs")); } - @Test(dataProvider = "createVnfParameters") - public void createVnfRequestDetails_detailsAreAsExpected(boolean isFlagAddCloudOwnerActive, boolean isUserProvidedNaming, String file) throws IOException { - final List vnfList = new ArrayList<>(createVnfList(new HashMap<>(), null, isUserProvidedNaming, true).values()); - ModelInfo siModelInfo = createServiceModelInfo(); - String serviceInstanceId = "aa3514e3-5a33-55df-13ab-12abad84e7aa"; - - //we validate that the asyncInstantiationBL call to getUniqueName by simulate that aai retrun that original - //vnf name is used, and only next picked name is free. - Mockito.reset(aaiClient); - mockAaiClientAaiStatusOK(); - when(aaiClient.isNodeTypeExistsByName(eq(VNF_NAME), eq(ResourceType.GENERIC_VNF))).thenReturn(true); - when(aaiClient.isNodeTypeExistsByName(eq(VNF_NAME+"_001"), eq(ResourceType.GENERIC_VNF))).thenReturn(false); - enableAddCloudOwnerOnMsoRequest(isFlagAddCloudOwnerActive); - - String expected = IOUtils.toString(this.getClass().getResource(file), "UTF-8"); - final RequestDetailsWrapper result = asyncInstantiationBL.generateVnfInstantiationRequest(vnfList.get(0), siModelInfo, serviceInstanceId, "pa0916"); - MsoOperationalEnvironmentTest.assertThatExpectationIsLikeObject(expected, result); - } - - @DataProvider - public static Object[][] createVnfParameters() { - return new Object[][]{ - {true, true, "/payload_jsons/bulk_vnf_request.json"}, - {false, true, "/payload_jsons/bulk_vnf_request_without_cloud_owner.json"}, - {true, false, "/payload_jsons/bulk_vnf_request_without_instance_name.json"}, - }; - } - - @DataProvider - public static Object[][] vfModuleRequestDetails(Method test) { - return new Object[][]{ - {"cc3514e3-5a33-55df-13ab-12abad84e7cc", true, "/payload_jsons/vfmodule_instantiation_request.json"}, - {null, true, "/payload_jsons/vfmodule_instantiation_request_without_volume_group.json"}, - {null, false, "/payload_jsons/vfmodule_instantiation_request_without_instance_name.json"} - }; - } - - @Test(dataProvider = "vfModuleRequestDetails") - public void createVfModuleRequestDetails_detailsAreAsExpected(String volumeGroupInstanceId, boolean isUserProvidedNaming, String fileName) throws IOException { - - ModelInfo siModelInfo = createServiceModelInfo(); - ModelInfo vnfModelInfo = createVnfModelInfo(true); - List> instanceParams = ImmutableList.of(ImmutableMap.of("vmx_int_net_len", "24", - "vre_a_volume_size_0" , "120")); - Map supplementaryParams = ImmutableMap.of("vre_a_volume_size_0" , "100", - "availability_zone_0" , "mtpocdv-kvm-az01"); - VfModule vfModule = createVfModule("201673MowAvpnVpeBvL..AVPN_vRE_BV..module-1", "56e2b103-637c-4d1a-adc8-3a7f4a6c3240", - "72d9d1cd-f46d-447a-abdb-451d6fb05fa8", instanceParams, supplementaryParams, - (isUserProvidedNaming ? "vmxnjr001_AVPN_base_vRE_BV_expansion": null), "myVgName", true); - - String serviceInstanceId = "aa3514e3-5a33-55df-13ab-12abad84e7aa"; - String vnfInstanceId = "bb3514e3-5a33-55df-13ab-12abad84e7bb"; - - Mockito.reset(aaiClient); - mockAaiClientAaiStatusOK(); - enableAddCloudOwnerOnMsoRequest(); - when(aaiClient.isNodeTypeExistsByName(eq("vmxnjr001_AVPN_base_vRE_BV_expansion"), eq(ResourceType.VF_MODULE))).thenReturn(false); - - String expected = IOUtils.toString(this.getClass().getResource(fileName), "UTF-8"); - final RequestDetailsWrapper result = asyncInstantiationBL.generateVfModuleInstantiationRequest( - vfModule, siModelInfo, serviceInstanceId, - vnfModelInfo, vnfInstanceId, volumeGroupInstanceId, "pa0916"); - MsoOperationalEnvironmentTest.assertThatExpectationIsLikeObject(expected, result); - } - - @DataProvider - public static Object[][] expectedAggregatedParams() { - return new Object[][]{ - {ImmutableMap.of("a", "b", "c", "d"), ImmutableMap.of("e", "f", "g", "h"), ImmutableList.of(ImmutableMap.of("c", "d", "a", "b", "e", "f", "g", "h"))}, - {ImmutableMap.of("a", "b", "c", "g"), ImmutableMap.of("c", "d", "e", "f"), ImmutableList.of(ImmutableMap.of("a", "b", "c", "d", "e", "f"))}, - {ImmutableMap.of(), ImmutableMap.of("c", "d", "e", "f"), ImmutableList.of(ImmutableMap.of("c", "d", "e", "f"))}, - {ImmutableMap.of("a", "b", "c", "g"), ImmutableMap.of(), ImmutableList.of(ImmutableMap.of("a", "b", "c", "g"))}, - {ImmutableMap.of(), ImmutableMap.of(), ImmutableList.of()}, - {null, ImmutableMap.of(), ImmutableList.of()}, - {ImmutableMap.of(), null, ImmutableList.of()}, - }; - } - - @Test(dataProvider = "expectedAggregatedParams") - public void testAggregateInstanceParamsAndSuppFile(Map instanceParams, Map suppParams, List> expected) { - List> aggParams = ((AsyncInstantiationBusinessLogicImpl)asyncInstantiationBL).aggregateAllInstanceParams(instanceParams, suppParams); - assertThat("Aggregated params are not as expected", aggParams, equalTo(expected)); - } - - @DataProvider - public static Object[][] expectedNetworkRequestDetailsParameters() { - return new Object[][]{ - {true, "/payload_jsons/network_instantiation_request.json"}, - {false, "/payload_jsons/network_instantiation_request_without_instance_name.json"} - }; - } - - @Test(dataProvider = "expectedNetworkRequestDetailsParameters") - public void createNetworkRequestDetails_detailsAreAsExpected(boolean isUserProvidedNaming, String filePath) throws IOException { - - final List networksList = new ArrayList<>(createNetworkList(null, isUserProvidedNaming, true).values()); - ModelInfo siModelInfo = createServiceModelInfo(); - String serviceInstanceId = "aa3514e3-5a33-55df-13ab-12abad84e7aa"; - - Mockito.reset(aaiClient); - mockAaiClientAaiStatusOK(); - enableAddCloudOwnerOnMsoRequest(); - when(aaiClient.isNodeTypeExistsByName(eq(VNF_NAME), eq(ResourceType.L3_NETWORK))).thenReturn(true); - when(aaiClient.isNodeTypeExistsByName(eq(VNF_NAME+"_001"), eq(ResourceType.L3_NETWORK))).thenReturn(false); - - String expected = IOUtils.toString(this.getClass().getResource(filePath), "UTF-8"); - final RequestDetailsWrapper result = asyncInstantiationBL.generateNetworkInstantiationRequest(networksList.get(0), siModelInfo, serviceInstanceId, "pa0916"); - MsoOperationalEnvironmentTest.assertThatExpectationIsLikeObject(expected, result); - } - - @Test - public void createInstanceGroupRequestDetails_detailsAreAsExpected() throws IOException { - - final InstanceGroup instanceGroup = createInstanceGroup(true, Action.Create); - ModelInfo siModelInfo = createServiceModelInfo(); - String serviceInstanceId = "aa3514e3-5a33-55df-13ab-12abad84e7aa"; - - Mockito.reset(aaiClient); - mockAaiClientAaiStatusOK(); - enableAddCloudOwnerOnMsoRequest(); - when(aaiClient.isNodeTypeExistsByName(eq(VNF_GROUP_NAME), eq(ResourceType.INSTANCE_GROUP))).thenReturn(true); - when(aaiClient.isNodeTypeExistsByName(eq(VNF_GROUP_NAME+"_001"), eq(ResourceType.INSTANCE_GROUP))).thenReturn(false); - - String expected = IOUtils.toString(this.getClass().getResource("/payload_jsons/instance_group_instantiation_request.json"), "UTF-8"); - final RequestDetailsWrapper result = asyncInstantiationBL.generateInstanceGroupInstantiationRequest(instanceGroup, siModelInfo, serviceInstanceId, "az2018"); - MsoOperationalEnvironmentTest.assertThatExpectationIsLikeObject(expected, result); - } - - @Test - public void checkIfNullProjectNameSentToMso(){ - ServiceInstantiation serviceInstantiationPayload = generateMockMacroServiceInstantiationPayload(true, - createVnfList(vfModuleInstanceParamsMapWithParamsToRemove, Collections.EMPTY_LIST, false), - 1, - false,null,false); - RequestDetailsWrapper result = - asyncInstantiationBL.generateMacroServiceInstantiationRequest(null, serviceInstantiationPayload, serviceInstantiationPayload.getInstanceName(), "az2016"); - JsonNode jsonNode = new ObjectMapper().valueToTree(result.requestDetails); - Assert.assertTrue(jsonNode.get("project").isNull()); - serviceInstantiationPayload = generateMockMacroServiceInstantiationPayload(true, - createVnfList(vfModuleInstanceParamsMapWithParamsToRemove, Collections.EMPTY_LIST, false), - 1, - false,"not null",false); - result = asyncInstantiationBL.generateMacroServiceInstantiationRequest(null, serviceInstantiationPayload, serviceInstantiationPayload.getInstanceName(), "az2016"); - jsonNode = new ObjectMapper().valueToTree(result.requestDetails); - Assert.assertTrue(jsonNode.get("project").get("projectName").asText().equalsIgnoreCase("not null")); - - - - } @Test public void pushBulkJob_macroServiceverifyCreatedDateBehavior_createdDateIsTheSameForAllServicesInSameBulk() { @@ -853,7 +740,9 @@ public class AsyncInstantiationBusinessLogicTest extends AsyncInstantiationBaseT Mockito.reset(jobAdapterMock); final Job job = mock(Job.class); when(job.getStatus()).thenReturn(PENDING); - when(jobAdapterMock.createServiceInstantiationJob(any(), any(), any(), any(), any(), any())).thenReturn(job); + when(job.getUuid()).thenReturn(UUID.fromString("db2c5ed9-1c19-41ce-9cb7-edf0d878cdeb")); + when(jobAdapterMock.createServiceInstantiationJob(any(), any(), any(), any(), any(), any(), any())).thenReturn(job); + when(jobsBrokerServiceMock.add(job)).thenReturn(UUID.randomUUID()); } @DataProvider @@ -869,7 +758,11 @@ public class AsyncInstantiationBusinessLogicTest extends AsyncInstantiationBaseT {"Paused", JobStatus.PAUSE}, {"Pause", JobStatus.PAUSE}, {"PENDING_MANUAL_TASK", JobStatus.PAUSE}, - {"UNLOCKED", JobStatus.IN_PROGRESS} + {"UNLOCKED", JobStatus.IN_PROGRESS}, + {"AbORtEd", COMPLETED_WITH_ERRORS}, + {"RoLlED_baCK", FAILED}, + {"ROllED_BAcK_To_ASsIGnED", FAILED}, + {"rOLLED_bACK_tO_CrEATeD", FAILED}, }; } @@ -879,131 +772,6 @@ public class AsyncInstantiationBusinessLogicTest extends AsyncInstantiationBaseT assertThat(asyncInstantiationBL.calcStatus(asyncRequestStatus), equalTo(expectedJobStatus)); } - private void createNewAuditStatus(JobAuditStatus auditStatus) - { - Date createdDate= auditStatus.getCreated(); - dataAccessService.saveDomainObject(auditStatus, getPropsMap()); - setDateToStatus(auditStatus.getSource(), auditStatus.getJobStatus(), createdDate); - } - - - - private static final String MSO_ARBITRARY_STATUS = "completed mso status"; - - @DataProvider - public static Object[][] auditStatuses(Method test) { - return new Object[][]{ - { - SourceStatus.VID, - new String[]{ JobStatus.PENDING.toString(), JobStatus.IN_PROGRESS.toString()} - }, - { SourceStatus.MSO, - new String[]{ JobStatus.IN_PROGRESS.toString(), MSO_ARBITRARY_STATUS } - } - }; - - } - - private void setDateToStatus(SourceStatus source, String status, Date date) { - List jobAuditStatusList = dataAccessService.getList(JobAuditStatus.class, getPropsMap()); - DaoUtils.tryWithSessionAndTransaction(sessionFactory, session -> { - jobAuditStatusList.stream() - .filter(auditStatus -> source.equals(auditStatus.getSource()) && status.equals(auditStatus.getJobStatus())) - .forEach(auditStatus -> { - auditStatus.setCreated(date); - session.saveOrUpdate(auditStatus); - }); - return 1; - }); - } - - - @Test(dataProvider = "auditStatuses") - public void givenSomeAuditStatuses_getStatusesOfSpecificSourceAndJobId_getSortedResultsMatchingToParameters(SourceStatus expectedSource, String [] expectedSortedStatuses){ - UUID jobUuid = UUID.randomUUID(); - List auditStatusList = com.google.common.collect.ImmutableList.of( - new JobAuditStatus(jobUuid, IN_PROGRESS.toString(), SourceStatus.VID, toDate(LocalDateTime.now().minusHours(2))), - new JobAuditStatus(jobUuid, IN_PROGRESS.toString(), SourceStatus.MSO, UUID.randomUUID(),"",toDate(LocalDateTime.now().minusHours(30))), - new JobAuditStatus(jobUuid, MSO_ARBITRARY_STATUS, SourceStatus.MSO, UUID.randomUUID(),"",toDate(LocalDateTime.now().minusHours(3))), - new JobAuditStatus(jobUuid, PENDING.toString(), SourceStatus.VID, toDate(LocalDateTime.now().minusHours(3))), - new JobAuditStatus(UUID.randomUUID(), PENDING.toString(), SourceStatus.VID, toDate(LocalDateTime.now().minusHours(3)))); - auditStatusList.forEach((auditStatus) -> createNewAuditStatus(auditStatus)); - List statuses = asyncInstantiationBL.getAuditStatuses(jobUuid, expectedSource); - List statusesList = statuses.stream().map(status -> status.getJobStatus()).collect(Collectors.toList()); - Assert.assertTrue(statuses.stream().allMatch(status -> (status.getSource().equals(expectedSource)&& status.getJobId().equals(jobUuid))),"Only statuses of " + expectedSource + " for " + jobUuid + " should be returned. Returned statuses: " + String.join(",", statusesList )); - assertThat(statusesList, contains(expectedSortedStatuses)); - } - - - - @Test - public void addSomeVidStatuses_getThem_verifyGetInsertedWithoutDuplicates(){ - ImmutableList statusesToBeInserted = ImmutableList.of(PENDING, IN_PROGRESS, IN_PROGRESS, COMPLETED); - UUID jobUuid = UUID.randomUUID(); - statusesToBeInserted.forEach(status-> - { - asyncInstantiationBL.auditVidStatus(jobUuid, status); - }); - List statusesFromDB = asyncInstantiationBL.getAuditStatuses(jobUuid, SourceStatus.VID).stream().map(auditStatus -> auditStatus.getJobStatus()).collect(Collectors.toList()); - List statusesWithoutDuplicates = statusesToBeInserted.stream().distinct().map(x -> x.toString()).collect(Collectors.toList()); - assertThat(statusesFromDB, is(statusesWithoutDuplicates)); - } - - @DataProvider - public static Object[][] msoAuditStatuses(Method test) { - UUID jobUuid = UUID.randomUUID(); - UUID requestId = UUID.randomUUID(); - return new Object[][]{ - { - jobUuid, - ImmutableList.of( - new JobAuditStatus(jobUuid, PENDING.toString(), SourceStatus.MSO, null, null), - new JobAuditStatus(jobUuid, IN_PROGRESS.toString(), SourceStatus.MSO, requestId, null), - new JobAuditStatus(jobUuid, IN_PROGRESS.toString(), SourceStatus.MSO, requestId, null), - new JobAuditStatus(jobUuid, IN_PROGRESS.toString(), SourceStatus.MSO, requestId, null), - new JobAuditStatus(jobUuid, COMPLETED.toString(), SourceStatus.MSO, requestId, null)), - ImmutableList.of(PENDING.toString(), IN_PROGRESS.toString(), COMPLETED.toString()), - "All distinct statuses should be without duplicates" - }, - { - jobUuid, - ImmutableList.of( - new JobAuditStatus(jobUuid, PENDING.toString(), SourceStatus.MSO, null, null), - new JobAuditStatus(jobUuid, IN_PROGRESS.toString(), SourceStatus.MSO, requestId, null), - new JobAuditStatus(jobUuid, IN_PROGRESS.toString(), SourceStatus.MSO, requestId, "aa"), - new JobAuditStatus(jobUuid, IN_PROGRESS.toString(), SourceStatus.MSO, requestId, "aa"), - new JobAuditStatus(jobUuid, IN_PROGRESS.toString(), SourceStatus.MSO, UUID.randomUUID(), "aa"), - new JobAuditStatus(jobUuid, COMPLETED.toString(), SourceStatus.MSO, requestId, null)), - ImmutableList.of(PENDING.toString(), IN_PROGRESS.toString(), IN_PROGRESS.toString(),IN_PROGRESS.toString(), COMPLETED.toString()), - "Statuses should be without duplicates only with same requestId and additionalInfo" - - } - }; - } - - @Test(dataProvider = "msoAuditStatuses") - public void addSomeMsoStatuses_getThem_verifyGetInsertedWithoutDuplicates(UUID jobUuid, ImmutableList msoStatuses, ImmutableList expectedStatuses, String assertionReason) { - msoStatuses.forEach(status -> { - asyncInstantiationBL.auditMsoStatus(status.getJobId(), status.getJobStatus(), status.getRequestId() != null ? status.getRequestId().toString() : null, status.getAdditionalInfo()); - }); - List statusesFromDB = asyncInstantiationBL.getAuditStatuses(jobUuid, SourceStatus.MSO).stream().map(auditStatus -> auditStatus.getJobStatus()).collect(Collectors.toList()); - assertThat( assertionReason, statusesFromDB, is(expectedStatuses)); - } - - @Test - public void addSameStatusOfVidAndMso_verifyThatBothWereAdded(){ - UUID jobUuid = UUID.randomUUID(); - JobStatus sameStatus = IN_PROGRESS; - asyncInstantiationBL.auditMsoStatus(jobUuid, sameStatus.toString(),null,null); - asyncInstantiationBL.auditVidStatus(jobUuid, sameStatus); - List list = dataAccessService.getList( - JobAuditStatus.class, - String.format(" where JOB_ID = '%s'", jobUuid), - null, null); - Assert.assertEquals(list.size(),2); - assertThat(list,everyItem(hasProperty("jobStatus", is(sameStatus.toString())))); - } - @DataProvider public static Object[][] msoRequestStatusFiles(Method test) { return new Object[][]{ @@ -1026,7 +794,7 @@ public class AsyncInstantiationBusinessLogicTest extends AsyncInstantiationBaseT doNothing().when(jobsBrokerServiceMock).delete(any()); UUID uuid = createServicesInfoWithDefaultValues(PENDING); asyncInstantiationBL.deleteJob(uuid); - assertNotNull(asyncInstantiationBL.getServiceInfoByJobId(uuid).getDeletedAt(), "service info wasn't deleted"); + assertNotNull(asyncInstantiationRepository.getServiceInfoByJobId(uuid).getDeletedAt(), "service info wasn't deleted"); } @Test(expectedExceptions = IllegalStateException.class, expectedExceptionsMessageRegExp = DELETE_SERVICE_INFO_STATUS_EXCEPTION_MESSAGE) @@ -1036,7 +804,7 @@ public class AsyncInstantiationBusinessLogicTest extends AsyncInstantiationBaseT try { asyncInstantiationBL.deleteJob(uuid); } catch (Exception e) { - assertNull(asyncInstantiationBL.getServiceInfoByJobId(uuid).getDeletedAt(), "service info shouldn't deleted"); + assertNull(asyncInstantiationRepository.getServiceInfoByJobId(uuid).getDeletedAt(), "service info shouldn't deleted"); throw e; } } @@ -1081,7 +849,7 @@ public class AsyncInstantiationBusinessLogicTest extends AsyncInstantiationBaseT try { asyncInstantiationBL.hideServiceInfo(uuid); } catch (Exception e) { - assertFalse(asyncInstantiationBL.getServiceInfoByJobId(uuid).isHidden(), "service info shouldn't be hidden"); + assertFalse(asyncInstantiationRepository.getServiceInfoByJobId(uuid).isHidden(), "service info shouldn't be hidden"); throw e; } } @@ -1126,16 +894,23 @@ public class AsyncInstantiationBusinessLogicTest extends AsyncInstantiationBaseT assertThat(asyncInstantiationBL.getUniqueName(name, type), equalTo(name+"_001")); } + @Test(enabled = false) //skip till we will handle macro bulk again... + public void whenNamedNotInUsedInAai_getSameNameTwice() { + String name = someCommonStepsAndGetName(); + ResourceType type = ResourceType.GENERIC_VNF; + when(aaiClient.isNodeTypeExistsByName(name, type)).thenReturn(false); + assertThat(asyncInstantiationBL.getUniqueName(name, type), equalTo(name)); + assertThat(asyncInstantiationBL.getUniqueName(name, type), equalTo(name)); + when(aaiClient.isNodeTypeExistsByName(name, type)).thenReturn(true); + assertThat(asyncInstantiationBL.getUniqueName(name, type), equalTo(name+"_001")); + } + private String someCommonStepsAndGetName() { mockAaiClientAaiStatusOK(); return UUID.randomUUID().toString(); } - private void mockAaiClientAaiStatusOK() { - when(aaiClient.isNodeTypeExistsByName(eq(AsyncInstantiationBusinessLogicImpl.NAME_FOR_CHECK_AAI_STATUS), any())).thenReturn(false); - } - - @Test(expectedExceptions=ExceptionWithRequestInfo.class) + @Test(expectedExceptions= ExceptionWithRequestInfo.class) public void whenAaiBadResponseCode_throwInvalidAAIResponseException() { String name = someCommonStepsAndGetName(); ResourceType type = ResourceType.SERVICE_INSTANCE; @@ -1171,7 +946,7 @@ public class AsyncInstantiationBusinessLogicTest extends AsyncInstantiationBaseT ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(JobType.class); asyncInstantiationBL.pushBulkJob(request, "myUserId"); - verify(jobAdapterMock).createServiceInstantiationJob(argumentCaptor.capture(),any(),any(),anyString(), anyString(), anyInt()); + verify(jobAdapterMock).createServiceInstantiationJob(argumentCaptor.capture(),any(),any(),anyString(), anyString(), anyString(), anyInt()); assertTrue(argumentCaptor.getValue().equals(JobType.ALaCarteServiceInstantiation)); } @@ -1184,198 +959,285 @@ public class AsyncInstantiationBusinessLogicTest extends AsyncInstantiationBaseT ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(JobType.class); asyncInstantiationBL.pushBulkJob(request, "myUserId"); - verify(jobAdapterMock).createServiceInstantiationJob(argumentCaptor.capture(),any(),any(),anyString(), anyString(), anyInt()); + verify(jobAdapterMock).createServiceInstantiationJob(argumentCaptor.capture(),any(),any(),anyString(), any(), anyString(), anyInt()); assertTrue(argumentCaptor.getValue().equals(JobType.MacroServiceInstantiation)); } - @Test - public void generateALaCarteServiceInstantiationRequest_verifyRequestIsAsExpected() throws IOException { - ServiceInstantiation serviceInstantiationPayload = generateALaCarteServiceInstantiationPayload(); - final URL resource = this.getClass().getResource("/payload_jsons/bulk_alacarte_service_request.json"); - RequestDetailsWrapper result = - asyncInstantiationBL.generateALaCarteServiceInstantiationRequest(null, serviceInstantiationPayload, serviceInstantiationPayload.getInstanceName(), "az2016"); - String expected = IOUtils.toString(resource, "UTF-8"); - MsoOperationalEnvironmentTest.assertThatExpectationIsLikeObject(expected, result); - } + @Test - public void generateALaCarteServiceDeletionRequest_verifyRequestIsAsExpected() throws IOException { - final URL resource = this.getClass().getResource("/payload_jsons/bulk_alacarte_service_deletion_request.json"); - String expected = IOUtils.toString(resource, "UTF-8"); + public void getALaCarteServiceDeletionPath_verifyPathIsAsExpected() { - ServiceInstantiation serviceDeletionPayload = generateALaCarteServiceDeletionPayload(); - RequestDetailsWrapper result = - asyncInstantiationBL.generateALaCarteServiceDeletionRequest(null, serviceDeletionPayload, "az2016"); + String expected = "/serviceInstantiation/v7/serviceInstances/f36f5734-e9df-4fbf-9f35-61be13f028a1"; - MsoOperationalEnvironmentTest.assertThatExpectationIsLikeObject(expected, result); + String result = asyncInstantiationBL.getServiceDeletionPath("f36f5734-e9df-4fbf-9f35-61be13f028a1"); + + assertThat(expected,equalTo(result)); } @Test - public void getALaCarteServiceDeletionPath_verifyPathIsAsExpected() throws IOException { + public void getResumeRequestPath_verifyPathIsAsExpected() { - String expected = "/serviceInstantiation/v./serviceInstances/f36f5734-e9df-4fbf-9f35-61be13f028a1"; + String expected = "/orchestrationRequests/v7/rq1234d1-5a33-55df-13ab-12abad84e333/resume"; - String result = asyncInstantiationBL.getServiceDeletionPath("f36f5734-e9df-4fbf-9f35-61be13f028a1"); + String result = asyncInstantiationBL.getResumeRequestPath("rq1234d1-5a33-55df-13ab-12abad84e333"); - assertThat(result, matchesPattern(expected)); + assertThat(expected, equalTo(result)); } @Test public void getInstanceGroupsDeletionPath_verifyPathIsAsExpected() { - assertEquals(asyncInstantiationBL.getInstanceGroupDeletePath("9aada4af-0f9b-424f-ae21-e693bd3e005b"), "/serviceInstantiation/v7/instanceGroups/9aada4af-0f9b-424f-ae21-e693bd3e005b"); } + @Test + public void whenLcpRegionNotEmpty_thenCloudRegionIdOfResourceIsLegacy() { + String legacyCloudRegion = "legacyCloudRegion"; + Vnf vnf = new Vnf(new ModelInfo(), null, null, Action.Create.name(), null, "anyCloudRegion", legacyCloudRegion, + null, null, null, false, null, null, UUID.randomUUID().toString(), null, null); + assertThat(vnf.getLcpCloudRegionId(), equalTo(legacyCloudRegion)); + } + + @Test + public void whenLcpRegionNotEmpty_thenCloudRegionIdOfServiceIsLegacy() { + String legacyCloudRegion = "legacyCloudRegion"; + ServiceInstantiation service = new ServiceInstantiation(new ModelInfo(), null, null, null, null, null, null, + null, null, "anyCloudRegion", legacyCloudRegion, null, null, null, null, null, null, null, null, null, + false, 1,false, false, null, null, Action.Create.name(), UUID.randomUUID().toString(), null, null, null); + assertThat(service.getLcpCloudRegionId(), equalTo(legacyCloudRegion)); + } + @DataProvider - public static Object[][] testBuildVnfInstanceParamsDataProvider(Method test) { + public static Object[][] getJobTypeByRequest_verifyResultAsExpectedDataProvider() { return new Object[][]{ - { - Collections.EMPTY_LIST, - ImmutableList.of( - ImmutableList.of(ImmutableMap.of("k1","v1","k2","v2")), - ImmutableList.of(ImmutableMap.of("k3","v3","k2","v2")) - ), - true, - ImmutableList.of(ImmutableMap.of("k1","v1","k2","v2","k3","v3")) - }, - { - ImmutableList.of(ImmutableMap.of("j1", "w1", "k1","v1", "vnf_name","w2", "vf_module_name","w3")), //vnf_name, vf_module_name are excluded - ImmutableList.of( - ImmutableList.of(ImmutableMap.of("k1","v1","k2","v2")), - ImmutableList.of(ImmutableMap.of("k3","v3","k2","v2")), - ImmutableList.of(Collections.EMPTY_MAP), - Collections.singletonList(null) - ), - true, - ImmutableList.of(ImmutableMap.of("k1","v1","k2","v2","k3","v3","j1", "w1")) - }, - { - Collections.EMPTY_LIST, - Arrays.asList(null, null), - true, - Collections.EMPTY_LIST //mso is expect to empty list and not list with empty map - }, - { - ImmutableList.of(Collections.EMPTY_MAP), - ImmutableList.of( - ImmutableList.of(Collections.EMPTY_MAP), - ImmutableList.of(Collections.EMPTY_MAP) - ), - true, - Collections.EMPTY_LIST //mso is expect to empty list and not list with empty map - }, - { - Collections.EMPTY_LIST, - ImmutableList.of( - ImmutableList.of(ImmutableMap.of("k1","v1","k2","v2")), - ImmutableList.of(ImmutableMap.of("k3","v3","k2","v2")) - ), - false, - Collections.EMPTY_LIST //mso is expect to empty list and not list with empty map - }, - { - ImmutableList.of(ImmutableMap.of("j1", "w1", "k1","v1", "vnf_name","w2", "vf_module_name","w3")), - ImmutableList.of( - ImmutableList.of(Collections.EMPTY_MAP) - ), - false, - ImmutableList.of(ImmutableMap.of("j1", "w1", "k1","v1")) - }, - { - ImmutableList.of(ImmutableMap.of("vnf_name","w2", "vf_module_name", "w3", "j2", "w2", "j4","w4")), - ImmutableList.of( - ImmutableList.of(ImmutableMap.of("k1","v1","k2","v2")), - ImmutableList.of(ImmutableMap.of("k3","v3","k2","v2")) - ), - false, - ImmutableList.of(ImmutableMap.of("j2", "w2", "j4","w4")) - }, - + {false, Action.Create, JobType.MacroServiceInstantiation}, + {true, Action.Create, JobType.ALaCarteServiceInstantiation}, + {true, Action.Delete, JobType.ALaCarteService}, }; } - @Test(dataProvider="testBuildVnfInstanceParamsDataProvider") - public void testBuildVnfInstanceParams(List> currentVnfInstanceParams, - List>> vfModulesInstanceParams, - boolean isFeatureActive, - List> expectedResult){ - when(featureManager.isActive(Features.FLAG_SHIFT_VFMODULE_PARAMS_TO_VNF)).thenReturn(isFeatureActive); - List vfModules = - vfModulesInstanceParams.stream().map(params-> new VfModuleMacro(new ModelInfo(), null, null, params)).collect(Collectors.toList()); - List> actual = asyncInstantiationBL.buildVnfInstanceParams(currentVnfInstanceParams, vfModules); - assertThat(actual, equalTo(expectedResult)); + @Test(dataProvider = "getJobTypeByRequest_verifyResultAsExpectedDataProvider") + public void getJobTypeByRequest_verifyResultAsExpected(boolean isALaCarte, Action action, JobType expectedJobType) { + ServiceInstantiation service = createServiceWithIsALaCarteAndAction(isALaCarte, action); + assertThat(asyncInstantiationBL.getJobType(service), equalTo(expectedJobType)); + } + @NotNull + protected ServiceInstantiation createServiceWithIsALaCarteAndAction(boolean isALaCarte, Action action) { + return new ServiceInstantiation(new ModelInfo(), null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, null, + false, 1, false, isALaCarte, null, null, action.name(), + UUID.randomUUID().toString(), null, null, null); } - @Test - public void whenLcpRegionNotEmpty_thenCloudRegionIdOfResourceIsLegacy() { - String legacyCloudRegion = "legacyCloudRegion"; - Vnf vnf = new Vnf(new ModelInfo(), null, null, Action.Create.name(), null, "anyCloudRegion", legacyCloudRegion, null, null, null, false, null, null); - assertThat(vnf.getLcpCloudRegionId(), equalTo(legacyCloudRegion)); + @DataProvider + public static Object[][] isRetryEnabledForStatusDataProvider(Method test) { + return new Object[][]{ + {FAILED, true, true}, + {COMPLETED_WITH_ERRORS, true, true}, + {COMPLETED_WITH_NO_ACTION, true, false}, + {COMPLETED, true, false}, + {IN_PROGRESS, true, false}, + {FAILED, false, false}, + {COMPLETED_WITH_ERRORS, false, false}, + {COMPLETED, false, false}, + }; + } + @Test(dataProvider = "isRetryEnabledForStatusDataProvider") + public void whenUpdateServiceInfoAndAuditStatus_thenServiceInfoRowIsUpdatedAndIsRetryIsRight( + JobStatus jobStatus, boolean isRetryfeatureEnabled, boolean expectedIsRetry) { + when(featureManager.isActive(Features.FLAG_1902_RETRY_JOB)).thenReturn(isRetryfeatureEnabled); + UUID uuid = createFakedJobAndServiceInfo(); + asyncInstantiationBL.updateServiceInfoAndAuditStatus(uuid, jobStatus); + ServiceInfo serviceInfo = ((List)dataAccessService.getList(ServiceInfo.class, getPropsMap())). + stream().filter(x->x.getJobId().equals(uuid)).findFirst().get(); + assertEquals(jobStatus, serviceInfo.getJobStatus()); + + //we don't test serviceInfo.getStatusModifiedDate() because it's too complicated + assertEquals(expectedIsRetry, serviceInfo.isRetryEnabled()); } @Test - public void whenLcpRegionNotEmpty_thenCloudRegionIdOfServiceIsLegacy() { - String legacyCloudRegion = "legacyCloudRegion"; - ServiceInstantiation service = new ServiceInstantiation(new ModelInfo(), null, null, null, null, null, null, - null, null, "anyCloudRegion", legacyCloudRegion, null, null, null, null, null, null, null, null, - false, 1,false, false, null, null, Action.Create.name()); - assertThat(service.getLcpCloudRegionId(), equalTo(legacyCloudRegion)); + public void givenServiceWithNullTrackByIds_whenReplaceTrackByIds_thenAllLevelsHasTrackByIdWithUUID() { + ServiceInstantiation serviceInstantiation = FakeResourceCreator.createServiceWith2InstancesInEachLevel(Action.Create); + //assert for the given that all trackById are null + assertTrackByIdRecursively(serviceInstantiation, is(nullValue()), new HashSet<>()); + ServiceInstantiation modifiedServiceInstantiation = asyncInstantiationBL.prepareServiceToBeUnique(serviceInstantiation); + assertTrackByIdRecursively(modifiedServiceInstantiation, uuidRegexMatcher, new HashSet<>()); + } + + private void assertTrackByIdRecursively(BaseResource baseResource, org.hamcrest.Matcher matcher, Set usedUuids) { + assertThat(baseResource.getTrackById(), matcher); + if (baseResource.getTrackById()!=null) { + assertThat(usedUuids, not(hasItem(baseResource.getTrackById()))); + usedUuids.add(baseResource.getTrackById()); + } + baseResource.getChildren().forEach(x->assertTrackByIdRecursively(x, matcher, usedUuids)); } @Test - public void createVolumeGroup_verifyResultAsExpected() throws IOException { - final URL resource = this.getClass().getResource("/payload_jsons/volumegroup_instantiation_request.json"); - VfModule vfModule = createVfModule("201673MowAvpnVpeBvL..AVPN_vRE_BV..module-1", - "56e2b103-637c-4d1a-adc8-3a7f4a6c3240", - "72d9d1cd-f46d-447a-abdb-451d6fb05fa8", - Collections.emptyList(), - Collections.emptyMap(), - "vmxnjr001_AVPN_base_vRE_BV_expansion", - "myVgName", - true); - vfModule.getModelInfo().setModelInvariantId("ff5256d2-5a33-55df-13ab-12abad84e7ff"); - vfModule.getModelInfo().setModelVersion("1"); - ModelInfo vnfModelInfo = createVnfModelInfo(true); - RequestDetailsWrapper result = - asyncInstantiationBL.generateVolumeGroupInstantiationRequest(vfModule, - createServiceModelInfo(), - "ff3514e3-5a33-55df-13ab-12abad84e7ff", - vnfModelInfo, - "vnfInstanceId", - "az2016"); - String expected = IOUtils.toString(resource, "UTF-8"); - MsoOperationalEnvironmentTest.assertThatExpectationIsLikeObject(expected, result); + public void givenServicefromDB_returnsTheBulkRequest() throws IOException { + ServiceInstantiation serviceInstantiation = TestUtils.readJsonResourceFileAsObject("/payload_jsons/VnfGroupCreate3Delete1None1Request.json", ServiceInstantiation.class); + UUID jobId = UUID.randomUUID(); + doReturn(serviceInstantiation).when(asyncInstantiationRepository).getJobRequest(jobId); + doReturn(mock(Map.class)).when(asyncInstantiationRepository).getResourceInfoByRootJobId(jobId); + ServiceInstantiation modifiedServiceInstantiation = asyncInstantiationBL.getBulkForRetry(jobId); + assertThat(modifiedServiceInstantiation, jsonEquals(serviceInstantiation).when(IGNORING_ARRAY_ORDER)); } @Test - public void getJobTypeByRequest_verifyResultAsExpected(){ - ServiceInstantiation service = new ServiceInstantiation(new ModelInfo(), null, null, null, null, null, null, - null, null, null, null, null, null, null, null, null, null, null, null, - false, 1,false, false, null, null, Action.Create.name()); - JobType jobType = asyncInstantiationBL.getJobType(service) ; - assertThat(jobType, equalTo(JobType.MacroServiceInstantiation)); - service = new ServiceInstantiation(new ModelInfo(), null, null, null, null, null, null, - null, null, null, null, null, null, null, null, null, null, null, null, - false, 1,false, true, null, null, Action.Create.name()); - jobType = asyncInstantiationBL.getJobType(service); - assertThat(jobType, equalTo(JobType.ALaCarteServiceInstantiation)); - service = new ServiceInstantiation(new ModelInfo(), null, null, null, null, null, null, - null, null, null, null, null, null, null, null, null, null, null, null, - false, 1,false, true, null, null, Action.Delete.name()); - jobType = asyncInstantiationBL.getJobType(service); - assertThat(jobType, equalTo(JobType.ALaCarteService)); + public void givenServiceFromDB_returnsResolvedData() throws IOException { + ServiceInstantiation serviceInstantiation = TestUtils.readJsonResourceFileAsObject("/payload_jsons/VnfGroupCreate3Delete1None1Request.json", ServiceInstantiation.class); + ServiceInstantiation expectedServiceInstantiation = TestUtils.readJsonResourceFileAsObject("/payload_jsons/VnfGroupCreate3Delete1None1RequestResolvedForRetry.json", ServiceInstantiation.class); + UUID jobId = UUID.randomUUID(); + AsyncRequestStatus asyncRequestStatus = TestUtils.readJsonResourceFileAsObject( + "/responses/mso/orchestrationRequestsVnf.json", + AsyncRequestStatus.class); + Map mockedResourceInfoMap = ImmutableMap.of( + "groupingservicefortest..ResourceInstanceGroup..0:001", new ResourceInfo("groupingservicefortest..ResourceInstanceGroup..0:001",jobId,"VNF_GROUP1_INSTANCE_ID", COMPLETED, asyncRequestStatus),// TODO case: delete completed + "ag5aav86u4j", new ResourceInfo("ag5aav86u4j",jobId, null, FAILED, asyncRequestStatus),// case: failed + "asedrftjko", new ResourceInfo("asedrftjko",jobId, "VNF_GROUP1_INSTANCE_ID_3", COMPLETED, asyncRequestStatus),//case: completed after retry failed + "rgedfdged4", new ResourceInfo("rgedfdged4", jobId,"VNF_GROUP1_INSTANCE_ID_4", COMPLETED, asyncRequestStatus ));// case: create completed + + doReturn(mockedResourceInfoMap).when(asyncInstantiationRepository).getResourceInfoByRootJobId(jobId); + ServiceInstantiation modifiedServiceInstantiation = asyncInstantiationBL.enrichBulkForRetry(serviceInstantiation,jobId); + assertThat(modifiedServiceInstantiation, jsonEquals(expectedServiceInstantiation).when(IGNORING_ARRAY_ORDER)); + } + + @DataProvider + public static Object[][] readStatusMsgDataProvider(Method test) throws IOException { + AsyncRequestStatus asyncRequestStatus = TestUtils.readJsonResourceFileAsObject( + "/responses/mso/orchestrationRequestsVnf.json", + AsyncRequestStatus.class); + return new Object[][]{ + {null, null}, + {new AsyncRequestStatus(), null}, + {new AsyncRequestStatus(new AsyncRequestStatus.Request()), null}, + {new AsyncRequestStatus(new AsyncRequestStatus.Request(new RequestStatus())), null}, + {asyncRequestStatus, "Vnf has been created successfully."} + }; + } + + @Test(dataProvider = "readStatusMsgDataProvider") + public void resourceInfoReadStatusMsg_returnsStatusMsgOrNull(AsyncRequestStatus asyncRequestStatus, String expected) { + ResourceInfo resourceInfo = new ResourceInfo("groupingservicefortest..ResourceInstanceGroup..0:001",UUID.randomUUID(),"VNF_GROUP1_INSTANCE_ID", COMPLETED, asyncRequestStatus); + String msg= asyncInstantiationBL.readStatusMsg(resourceInfo); + assertThat(msg, equalTo( expected)); + } + + @Test + public void testAddResourceInfoForOkResponse() { + reset(asyncInstantiationRepository); + String serviceInstanceId = "service-instance-id"; + UUID jobUuid = UUID.randomUUID(); + + asyncInstantiationBL.addResourceInfo(prepareSharedDataForAddResourceInfo(jobUuid), JobStatus.IN_PROGRESS, serviceInstanceId); + + ArgumentCaptor resourceInfoCaptor = ArgumentCaptor.forClass(ResourceInfo.class); + verify(asyncInstantiationRepository).saveResourceInfo(resourceInfoCaptor.capture()); + + ResourceInfo resourceInfo = resourceInfoCaptor.getValue(); + assertResourceInfoValues(resourceInfo, serviceInstanceId, jobUuid, JobStatus.IN_PROGRESS); + assertThat(resourceInfo.getErrorMessage(), is(nullValue())); + } + + private JobSharedData prepareSharedDataForAddResourceInfo(UUID jobUuid) { + ServiceInstantiation serviceInstantiation = mock(ServiceInstantiation.class); + when(serviceInstantiation.getTrackById()).thenReturn("track-by-id"); + return new JobSharedData(jobUuid, "", serviceInstantiation, ""); + } + + private void assertResourceInfoValues(ResourceInfo resourceInfo, String serviceInstanceId, UUID jobUuid, JobStatus jobStatus) { + assertThat(resourceInfo.getInstanceId(), equalTo(serviceInstanceId)); + assertThat(resourceInfo.getJobStatus(), equalTo(jobStatus)); + assertThat(resourceInfo.getRootJobId(), equalTo(jobUuid)); + assertThat(resourceInfo.getTrackById(), equalTo("track-by-id")); + } + + @DataProvider + public static Object[][] addResourceInfoWithError() { + String message = "Failed to create service instance"; + return new Object[][]{ + {500, message}, + {199, "{\"serviceException\":{\"messageId\":\"SVC2000\",\"text\":\"Error: " + message + "\"}}"} + }; } - protected ServiceInstantiation generateALaCarteServiceInstantiationPayload() { - return generateMockALaCarteServiceInstantiationPayload(false, Collections.EMPTY_MAP, Collections.EMPTY_MAP, Collections.EMPTY_MAP, 1, true, PROJECT_NAME, false, "VNF_API"); + @Test(dataProvider = "addResourceInfoWithError") + public void testAddResourceInfoForErrorResponse(int errorCode, String errorMessage) { + reset(asyncInstantiationRepository); + UUID jobUuid = UUID.randomUUID(); + + RestObject restObject = mock(RestObject.class); + when(restObject.getStatusCode()).thenReturn(errorCode); + when(restObject.getRaw()).thenReturn(errorMessage); + asyncInstantiationBL.addFailedResourceInfo(prepareSharedDataForAddResourceInfo(jobUuid), restObject); + + ArgumentCaptor resourceInfoCaptor = ArgumentCaptor.forClass(ResourceInfo.class); + verify(asyncInstantiationRepository).saveResourceInfo(resourceInfoCaptor.capture()); + + ResourceInfo resourceInfo = resourceInfoCaptor.getValue(); + assertResourceInfoValues(resourceInfo, null, jobUuid, JobStatus.FAILED); + assertThat(resourceInfo.getErrorMessage().request.requestStatus.getStatusMessage(), containsString("Failed to create service instance")); + assertThat(resourceInfo.getErrorMessage().request.requestStatus.getStatusMessage(), containsString(String.valueOf(errorCode))); + ZonedDateTime parsedDate = TimeUtils.parseZonedDateTime(resourceInfo.getErrorMessage().request.requestStatus.getTimestamp()); + assertThat(parsedDate.toLocalDate(), is(LocalDate.now())); + + doReturn(resourceInfo).when(asyncInstantiationRepository).getResourceInfoByTrackId(any()); + JobAuditStatus jobAuditStatus = auditService.getResourceAuditStatus(resourceInfo.getTrackById()); + assertThat(jobAuditStatus.getJobStatus(), equalTo("FAILED")); + assertThat(jobAuditStatus.getAdditionalInfo(), containsString("Failed to create service instance")); + assertThat(jobAuditStatus.getAdditionalInfo(), containsString(String.valueOf(errorCode))); + assertTrue(DateUtils.isSameDay(jobAuditStatus.getCreatedDate(), new Date())); } - private ServiceInstantiation generateALaCarteServiceDeletionPayload() { - return generateMockALaCarteServiceDeletionPayload(false, Collections.EMPTY_MAP, Collections.EMPTY_MAP, Collections.EMPTY_MAP, 1, true, PROJECT_NAME, false, "VNF_API", "1234567890"); + @DataProvider + public static Object[][] updateResourceInfoParameters() { + return new Object[][] { + {JobStatus.COMPLETED, "Instance was created successfully"}, + {JobStatus.FAILED, "Failed to create instance"} + }; + } + + @Test(dataProvider = "updateResourceInfoParameters") + public void testUpdateResourceInfo(JobStatus jobStatus, String message) { + reset(asyncInstantiationRepository); + UUID jobUuid = UUID.randomUUID(); + JobSharedData sharedData = new JobSharedData(jobUuid, "", mock(ServiceInstantiation.class),""); + + ResourceInfo resourceInfoMock = new ResourceInfo(); + resourceInfoMock.setTrackById(UUID.randomUUID().toString()); + doReturn(resourceInfoMock).when(asyncInstantiationRepository).getResourceInfoByTrackId(any()); + + AsyncRequestStatus asyncRequestStatus = asyncInstantiationBL.convertMessageToAsyncRequestStatus(message); + + asyncInstantiationBL.updateResourceInfo(sharedData, jobStatus, asyncRequestStatus); + + ArgumentCaptor resourceInfoCaptor = ArgumentCaptor.forClass(ResourceInfo.class); + verify(asyncInstantiationRepository).saveResourceInfo(resourceInfoCaptor.capture()); + + ResourceInfo resourceInfo = resourceInfoCaptor.getValue(); + assertThat(resourceInfo.getJobStatus(), equalTo(jobStatus)); + if (jobStatus == JobStatus.FAILED) { + assertThat(resourceInfo.getErrorMessage(), is(not(nullValue()))); + assertThat(resourceInfo.getErrorMessage().request.requestStatus.getStatusMessage(), equalTo(message)); + ZonedDateTime parsedDate = TimeUtils.parseZonedDateTime(resourceInfo.getErrorMessage().request.requestStatus.getTimestamp()); + assertThat(parsedDate.toLocalDate(), is(LocalDate.now())); + } else { + assertThat(resourceInfo.getErrorMessage(), is(nullValue())); + } + + JobAuditStatus jobAuditStatus = auditService.getResourceAuditStatus(resourceInfo.getTrackById()); + if (jobStatus == JobStatus.FAILED) { + assertThat(jobAuditStatus.getJobStatus(), equalTo("FAILED")); + assertThat(jobAuditStatus.getAdditionalInfo(), equalTo(message)); + } else { + assertThat(jobAuditStatus, is(nullValue())); + } + } static class MockedJob implements Job { @@ -1426,7 +1288,7 @@ public class AsyncInstantiationBusinessLogicTest extends AsyncInstantiationBaseT @Override public JobSharedData getSharedData() { - return new JobSharedData(uuid, "", null); + return new JobSharedData(uuid, "", null,""); } @Override @@ -1463,4 +1325,13 @@ public class AsyncInstantiationBusinessLogicTest extends AsyncInstantiationBaseT return optimisticUniqueServiceInstanceName; } } + + + @Test + public void testGetVfModuleReplacePath_asMSOexpected() + { + String path = asyncInstantiationBL.getVfModuleReplacePath("myService", "myVNF", "myVFModule"); + assertThat(path, equalTo("/serviceInstantiation/v7/serviceInstances/myService/vnfs/myVNF/vfModules/myVFModule/replace")); + + } } diff --git a/vid-app-common/src/test/java/org/onap/vid/services/AuditServiceImplTest.java b/vid-app-common/src/test/java/org/onap/vid/services/AuditServiceImplTest.java index bdb2a2834..ce5840bfc 100644 --- a/vid-app-common/src/test/java/org/onap/vid/services/AuditServiceImplTest.java +++ b/vid-app-common/src/test/java/org/onap/vid/services/AuditServiceImplTest.java @@ -19,71 +19,88 @@ */ package org.onap.vid.services; -import org.glassfish.grizzly.http.util.HttpStatus; import org.mockito.InjectMocks; import org.mockito.Mock; -import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.onap.vid.dal.AsyncInstantiationRepository; import org.onap.vid.model.JobAuditStatus; +import org.onap.vid.mso.RestMsoImplementation; +import org.onap.vid.mso.RestObject; +import org.onap.vid.mso.rest.AsyncRequestStatus; import org.onap.vid.mso.rest.AsyncRequestStatusList; import org.onap.vid.testUtils.TestUtils; -import org.testng.annotations.BeforeClass; +import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; -import java.io.IOException; -import java.util.Date; import java.util.List; -import java.util.UUID; -import static java.util.stream.Collectors.toList; import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.*; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.MockitoAnnotations.initMocks; +import static org.hamcrest.Matchers.equalTo; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.when; public class AuditServiceImplTest { + + @Mock + private RestMsoImplementation restMso; @Mock - private AsyncInstantiationBusinessLogic asyncInstantiationBL; + private AsyncInstantiationRepository asyncInstantiationRepository; @InjectMocks private AuditServiceImpl auditService; - @BeforeClass - public void init() { - initMocks(this); + @BeforeMethod + public void setUp() { + restMso = null; + asyncInstantiationRepository = null; + auditService = null; + MockitoAnnotations.initMocks(this); } @Test - public void setFailedAuditStatusFromMsoTest() { - - UUID jobUuid = UUID.randomUUID(); - String requestId = "1"; - int statusCode = HttpStatus.OK_200.getStatusCode(); - String msoResponse = "{}"; - - auditService.setFailedAuditStatusFromMso(jobUuid, requestId, statusCode, msoResponse); - - verify(asyncInstantiationBL, times(1)) - .auditMsoStatus( - Mockito.any(UUID.class), - Mockito.anyString(), - Mockito.anyString(), - Mockito.anyString()); + public void testGetRequestsIdsByServiceIdAndRequestTypeAndScope() throws Exception { + + String instanceId = "d40c8a82-cc04-45e5-a0f6-0c9394c8f8d2"; + //the request id in multipleOrchestrationRequestsServiceInstance.json + String expectedRequestId = "fab854bf-e53c-415e-b3cc-b6fcce8414b2"; + String msoBasePath = "/someMsoPath/v2019?"; + + AsyncRequestStatusList asyncRequestStatusList = TestUtils.readJsonResourceFileAsObject( + "/responses/mso/multipleOrchestrationRequestsServiceInstance.json", + AsyncRequestStatusList.class); + RestObject msoResponse = new RestObject<>(); + msoResponse.set(asyncRequestStatusList); + msoResponse.setStatusCode(200); + when(restMso.GetForObject(eq(msoBasePath + "filter=serviceInstanceId:EQUALS:" + instanceId), + eq(AsyncRequestStatusList.class))) + .thenReturn(msoResponse); + TestUtils.testWithSystemProperty("mso.restapi.get.orc.reqs", msoBasePath, () -> { + List result = auditService + .retrieveRequestsFromMsoByServiceIdAndRequestTypeAndScope(instanceId, "createInstance", "service"); + assertThat(result.size(), equalTo(1)); + assertThat(result.get(0).requestId, equalTo(expectedRequestId)); + assertThat(result.get(0).startTime, equalTo("Mon, 04 Mar 2019 20:47:15 GMT")); + }); } @Test - public void testConvertMsoResponseStatusToJobAuditStatus_missingDateFromMso_shouldNoError() throws IOException { - final AsyncRequestStatusList asyncRequestStatusList = TestUtils.readJsonResourceFileAsObject("/orchestrationRequestsByServiceInstanceId.json", AsyncRequestStatusList.class); - - AuditServiceImpl auditService = new AuditServiceImpl(null, null); - - final List jobAuditStatuses = auditService.convertMsoResponseStatusToJobAuditStatus(asyncRequestStatusList.getRequestList(), "foo"); - - final List dates = jobAuditStatuses.stream().map(JobAuditStatus::getCreatedDate).collect(toList()); - final List statuses = jobAuditStatuses.stream().map(JobAuditStatus::getJobStatus).collect(toList()); + public void nextOrdinalAfter_givenNull_returnZero() { + assertThat( + auditService.nextOrdinalAfter(null), + equalTo(0) + ); + } - assertThat(dates, containsInAnyOrder(notNullValue(), notNullValue(), nullValue())); - assertThat(statuses, containsInAnyOrder("COMPLETE", "COMPLETE", "IN_PROGRESS")); + @Test + public void nextOrdinalAfter_givenX_returnXplus1() { + final int x = 6; + final JobAuditStatus jobAuditStatus = new JobAuditStatus(); + jobAuditStatus.setOrdinal(x); + + assertThat( + auditService.nextOrdinalAfter(jobAuditStatus), + equalTo(x + 1) + ); } } diff --git a/vid-app-common/src/test/java/org/onap/vid/services/JobsBrokerServiceTest.java b/vid-app-common/src/test/java/org/onap/vid/services/JobsBrokerServiceTest.java index 85cf23edd..40546e967 100644 --- a/vid-app-common/src/test/java/org/onap/vid/services/JobsBrokerServiceTest.java +++ b/vid-app-common/src/test/java/org/onap/vid/services/JobsBrokerServiceTest.java @@ -7,9 +7,9 @@ * 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. @@ -21,57 +21,22 @@ package org.onap.vid.services; -import static java.util.concurrent.TimeUnit.MILLISECONDS; -import static java.util.stream.Collectors.toList; -import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.both; -import static org.hamcrest.Matchers.containsInAnyOrder; -import static org.onap.vid.job.Job.JobStatus.COMPLETED; -import static org.onap.vid.job.Job.JobStatus.CREATING; -import static org.onap.vid.job.Job.JobStatus.FAILED; -import static org.onap.vid.job.Job.JobStatus.IN_PROGRESS; -import static org.onap.vid.job.Job.JobStatus.PAUSE; -import static org.onap.vid.job.Job.JobStatus.PENDING; -import static org.onap.vid.job.Job.JobStatus.RESOURCE_IN_PROGRESS; -import static org.onap.vid.job.Job.JobStatus.STOPPED; -import static org.onap.vid.utils.Streams.not; -import static org.testng.Assert.assertNotNull; -import static org.testng.AssertJUnit.assertEquals; - import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; -import java.lang.reflect.Method; -import java.time.LocalDateTime; -import java.time.ZoneId; -import java.util.Arrays; -import java.util.Date; -import java.util.List; -import java.util.Optional; -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.ConcurrentSkipListSet; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import java.util.concurrent.TimeoutException; -import java.util.stream.IntStream; -import java.util.stream.Stream; -import javax.inject.Inject; import org.apache.commons.lang.RandomStringUtils; import org.apache.commons.lang3.RandomUtils; import org.apache.commons.lang3.builder.ReflectionToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; +import org.apache.commons.lang3.tuple.Pair; import org.apache.log4j.LogManager; import org.apache.log4j.Logger; import org.hibernate.SessionFactory; +import org.jetbrains.annotations.NotNull; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; import org.onap.portalsdk.core.domain.support.DomainVo; import org.onap.portalsdk.core.service.DataAccessService; import org.onap.portalsdk.core.util.SystemProperties; -import org.onap.vid.config.DataSourceConfig; -import org.onap.vid.config.JobAdapterConfig; import org.onap.vid.exceptions.GenericUncheckedException; import org.onap.vid.exceptions.OperationNotAllowedException; import org.onap.vid.job.Job; @@ -80,8 +45,12 @@ import org.onap.vid.job.JobType; import org.onap.vid.job.JobsBrokerService; import org.onap.vid.job.command.JobCommandFactoryTest; import org.onap.vid.job.impl.JobDaoImpl; +import org.onap.vid.job.impl.JobSchedulerInitializer; import org.onap.vid.job.impl.JobsBrokerServiceInDatabaseImpl; +import org.onap.vid.services.VersionService; import org.onap.vid.utils.DaoUtils; +import org.onap.vid.config.DataSourceConfig; +import org.onap.vid.config.JobAdapterConfig; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.testng.AbstractTestNGSpringContextTests; import org.testng.Assert; @@ -90,6 +59,31 @@ import org.testng.annotations.BeforeMethod; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; +import javax.inject.Inject; +import java.lang.reflect.Method; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.util.*; +import java.util.concurrent.*; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import java.util.stream.Stream; + +import static java.util.concurrent.TimeUnit.MILLISECONDS; +import static java.util.stream.Collectors.toList; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.both; +import static org.hamcrest.Matchers.containsInAnyOrder; +import static org.mockito.Mockito.when; +import static org.onap.vid.job.Job.JobStatus.*; +import static org.onap.vid.utils.Streams.not; +import static org.onap.vid.testUtils.TestUtils.generateRandomAlphaNumeric; +import static org.testng.Assert.assertNotNull; +import static org.testng.AssertJUnit.assertEquals; +import static org.testng.AssertJUnit.assertFalse; + @ContextConfiguration(classes = {DataSourceConfig.class, SystemProperties.class, JobAdapterConfig.class}) public class JobsBrokerServiceTest extends AbstractTestNGSpringContextTests { @@ -101,7 +95,7 @@ public class JobsBrokerServiceTest extends AbstractTestNGSpringContextTests { private final Set threadsIds = new ConcurrentSkipListSet<>(); - private final long FEW = 1000; + private final long FEW = 500; private final String JOBS_SHOULD_MATCH = "the jobs that added and those that pulled must be the same"; private final String JOBS_PEEKED_SHOULD_MATCH = "the jobs that added and those that peeked must be the same"; @@ -116,6 +110,23 @@ public class JobsBrokerServiceTest extends AbstractTestNGSpringContextTests { @Inject private SessionFactory sessionFactory; + @Mock + private VersionService versionService; + + @AfterMethod + public void threadsCounter() { + logger.info("participating threads count: " + threadsIds.size()); + threadsIds.clear(); + } + + @BeforeMethod + public void initializeBroker() { + MockitoAnnotations.initMocks(this); + when(versionService.retrieveBuildNumber()).thenReturn("aBuildNumber"); + broker = new JobsBrokerServiceInDatabaseImpl(dataAccessService, sessionFactory, 200, 0, versionService); + ((JobsBrokerServiceInDatabaseImpl) broker).deleteAll(); + } + /* - pulling jobs is limited to inserted ones - putting back allows getting the job again @@ -147,6 +158,7 @@ public class JobsBrokerServiceTest extends AbstractTestNGSpringContextTests { new JobCommandFactoryTest.MockedRequest(42,"nothing") , UUID.randomUUID(), userId, + null, "optimisticUniqueServiceInstanceName", RandomUtils.nextInt()); } @@ -234,18 +246,6 @@ public class JobsBrokerServiceTest extends AbstractTestNGSpringContextTests { threadsIds.add(Thread.currentThread().getId()); } - @AfterMethod - public void threadsCounter() { - logger.info("participating threads count: " + threadsIds.size()); - threadsIds.clear(); - } - - @BeforeMethod - public void initializeBroker() { - broker = new JobsBrokerServiceInDatabaseImpl(dataAccessService, sessionFactory, 200, 0); - ((JobsBrokerServiceInDatabaseImpl) broker).deleteAll(); - } - @Test public void givenSingleJob_getIt_verifySameJob() { final Job originalJob = waitForFutureJob(newJobAsync(broker)); @@ -254,6 +254,51 @@ public class JobsBrokerServiceTest extends AbstractTestNGSpringContextTests { assertThat(JOBS_SHOULD_MATCH, retrievedJob, is(originalJob)); } + @DataProvider + public static Object[][] allTopics() { + return JobSchedulerInitializer.WORKERS_TOPICS.stream() + .map(topic -> new Object[] { topic }) + .toArray(Object[][]::new); + } + + @Test(dataProvider = "allTopics") + public void givenJobFromSameBuild_pullJobs_jobIsPulled(Job.JobStatus topic) { + when(versionService.retrieveBuildNumber()).thenReturn("someVersion"); + Job mockedJob = createMockJob("user id", topic); + UUID uuid = broker.add(mockedJob); + assertEquals(uuid, broker.pull(topic, UUID.randomUUID().toString()).get().getUuid()); + } + + + @Test(dataProvider = "allTopics") + public void givenJobFromOtherBuild_pullJobs_noneIsPulled(Job.JobStatus topic) { + when(versionService.retrieveBuildNumber()).thenReturn("old"); + Job mockedJob = createMockJob("user id", topic); + broker.add(mockedJob); + when(versionService.retrieveBuildNumber()).thenReturn("new"); + assertFalse(broker.pull(topic, UUID.randomUUID().toString()).isPresent()); + } + + @Test + public void givenJobWithNullBuildAndJobWithRealBuild_pullJobs_jobsWithNonNullIsPulled() { + Job.JobStatus topic = PENDING; + + //push job with null build + when(versionService.retrieveBuildNumber()).thenReturn(null); + broker.add(createMockJob("user id", topic)); + + //push job with "aBuild" build + when(versionService.retrieveBuildNumber()).thenReturn("aBuild"); + UUID newJobId = broker.add(createMockJob("user id", topic)); + + //pull jobs while current build is still "aBuild". Only the non null build is pulled + assertEquals(newJobId, broker.pull(topic, UUID.randomUUID().toString()).get().getUuid()); + + //no more jobs to pull + assertFalse(broker.pull(topic, UUID.randomUUID().toString()).isPresent()); + } + + @Test public void givenManyJobs_getJobsAndPushThemBack_alwaysSeeAllOfThemWithPeek() throws InterruptedException { final List originalJobs = putALotOfJobs(broker); @@ -346,10 +391,10 @@ public class JobsBrokerServiceTest extends AbstractTestNGSpringContextTests { () -> createNewJob(14, UUID.randomUUID(), "userId", STOPPED,null, oldestDate), () -> createNewJob(22, UUID.randomUUID(), "userId", PENDING,null, oldestDate), () -> createNewJob(33, UUID.randomUUID(), "userId", PENDING,null, LocalDateTime.now().minusHours(2))), - 6, - 5, - PENDING, - "Broker should pull the only pending - first pending job by oldest job - ignore deleted,completed, failed, in-progress and stopped statuses" + 6, + 5, + PENDING, + "Broker should pull the only pending - first pending job by oldest job - ignore deleted,completed, failed, in-progress and stopped statuses" }, {ImmutableList.of( (Jobber)() -> createNewJob(11, UUID.randomUUID(), "userId", IN_PROGRESS, UUID.randomUUID().toString(), oldestDate), @@ -374,7 +419,7 @@ public class JobsBrokerServiceTest extends AbstractTestNGSpringContextTests { () -> createNewJob(22, UUID.randomUUID(), "userId", PENDING, UUID.randomUUID().toString(), oldestDate), () -> createNewJob(33, UUID.randomUUID(), "userId", PENDING, null, LocalDateTime.now().minusHours(2)), () -> createNewJob(12, UUID.randomUUID(), "userId", RESOURCE_IN_PROGRESS, UUID.randomUUID().toString(), oldestDate) - ), + ), 3, 2, PENDING, @@ -411,10 +456,10 @@ public class JobsBrokerServiceTest extends AbstractTestNGSpringContextTests { (Jobber)() -> createNewJob(11, sameTemplate, "userId", FAILED, null, oldestDate, DELETED), () -> createNewJob(22, sameTemplate, "userId", STOPPED,null, oldestDate), () -> createNewJob(33, sameTemplate, "userId", PENDING,null, LocalDateTime.now().minusHours(2))), - 3, - 2, - PENDING, - "Broker should pull pending job when there is another job from this template that was deleted, although failed" + 3, + 2, + PENDING, + "Broker should pull pending job when there is another job from this template that was deleted, although failed" }, { ImmutableList.of( (Jobber)() -> createNewJob(11, UUID.randomUUID(), "userA", IN_PROGRESS, null, oldestDate), @@ -475,10 +520,10 @@ public class JobsBrokerServiceTest extends AbstractTestNGSpringContextTests { () -> createNewJob(33, UUID.randomUUID(), "userId", IN_PROGRESS, null, LocalDateTime.now().minusHours(2)), () -> createNewJob(16, UUID.randomUUID(), "userId", RESOURCE_IN_PROGRESS, null, oldestDate) ), - 20, - 6, - IN_PROGRESS, - "Broker with in progress topic should pull only in-progress jobs - first in-progress job by oldest date - ignore all other statuses" + 20, + 6, + IN_PROGRESS, + "Broker with in progress topic should pull only in-progress jobs - first in-progress job by oldest date - ignore all other statuses" }, {ImmutableList.of( (Jobber)() -> createNewJob(11, UUID.randomUUID(), "userId", COMPLETED, null, oldestDate), @@ -541,14 +586,9 @@ public class JobsBrokerServiceTest extends AbstractTestNGSpringContextTests { @Test(dataProvider = "jobs") public void givenSomeJobs_pullNextJob_returnNextOrNothingAsExpected(List jobbers, int msoLimit, int expectedIndexSelected, Job.JobStatus topic, String assertionReason) { - JobsBrokerServiceInDatabaseImpl broker = new JobsBrokerServiceInDatabaseImpl(dataAccessService, sessionFactory, msoLimit, 20); - final List jobs = jobbers.stream().map(Jobber::toJob).collect(toList()); - for (JobDaoImpl job : jobs) { - Date modifiedDate = job.getModified(); - broker.add(job); - setModifiedDateToJob(job.getUuid(), modifiedDate); - } - Optional nextJob = broker.pull(topic, UUID.randomUUID().toString()); + JobsBrokerServiceInDatabaseImpl aBroker = new JobsBrokerServiceInDatabaseImpl(dataAccessService, sessionFactory, msoLimit, 20, versionService); + final List jobs = addJobsWithModifiedDate(jobbers, aBroker); + Optional nextJob = aBroker.pull(topic, UUID.randomUUID().toString()); boolean shouldAnyBeSelected = expectedIndexSelected >= 0; String pulledJobDesc = nextJob.map(job -> ". pulled job: " + job.toString()).orElse(". no job pulled"); Assert.assertEquals(nextJob.isPresent(), shouldAnyBeSelected, assertionReason+pulledJobDesc); @@ -557,10 +597,206 @@ public class JobsBrokerServiceTest extends AbstractTestNGSpringContextTests { } } + @NotNull + protected List addJobsWithModifiedDate(List jobbers, JobsBrokerService broker) { + final List jobs = jobbers.stream().map(Jobber::toJob).collect(toList()); + return addJobsWithModifiedDateByJobDao(jobs, broker); + } + + @NotNull + private List addJobsWithModifiedDateByJobDao(List jobs, JobsBrokerService broker) { + for (JobDaoImpl job : jobs) { + Date modifiedDate = job.getModified(); + broker.add(job); + setModifiedDateToJob(job.getUuid(), modifiedDate); + } + return jobs; + } + + @DataProvider + public static Object[][] jobsForTestingPendingResource(Method test) { + UUID templateId1 = UUID.fromString("311a9196-bbc5-47a1-8b11-bf0f9db1c7ca"); + UUID templateId2 = UUID.fromString("4f1522f9-642e-49f7-af75-a2f344085bcc"); + return new Object[][]{ + {ImmutableList.of( (Jobber) + () -> createNewJob(12, templateId1, "userId", PENDING_RESOURCE, null, LocalDateTime.now().minusSeconds(1), false), + () -> createNewJob(1, templateId2, "userId", CREATING, null, LocalDateTime.now().minusSeconds(1), false), + () -> createNewJob(2, UUID.randomUUID(), "userId", RESOURCE_IN_PROGRESS, null, LocalDateTime.now().minusSeconds(1), false), + () -> createNewJob(3, UUID.randomUUID(), "userId", IN_PROGRESS, null, LocalDateTime.now().minusSeconds(1), false), + () -> createNewJob(4, UUID.randomUUID(), "userId", COMPLETED, null, LocalDateTime.now().minusSeconds(1), false) + ), + 0, + "given there is only one in the queue in PENDING_RESOURCE and no other job with same templateId, then this job is selected" + }, + {ImmutableList.of( (Jobber) + () -> createNewJob(2, templateId1, "userId", PENDING_RESOURCE, null, LocalDateTime.now().minusSeconds(1), false), + () -> createNewJob(3, templateId1, "userId", PENDING_RESOURCE, null, LocalDateTime.now().minusSeconds(2), false), + () -> createNewJob(1, templateId1, "userId", PENDING_RESOURCE, null, LocalDateTime.now(), false) + ), + 2, + "given multiple jobs with same templateId in PENDING_RESOURCE, then job with lowest indexInBulk is selected" + }, + {ImmutableList.of( (Jobber) + () -> createNewJob(1, templateId2, "userId", PENDING_RESOURCE, null, LocalDateTime.now().minusSeconds(1), false), + () -> createNewJob(1, templateId1, "userId", PENDING_RESOURCE, null, LocalDateTime.now(), false) + ), + 1, + "given multiple jobs with same indexInBulk, then job with lowest templateId is selected" + }, + {ImmutableList.of( (Jobber) + () -> createNewJob(1, templateId1, "userId", PENDING_RESOURCE, null, LocalDateTime.now(), false), + () -> createNewJob(2, templateId2, "userId", PENDING_RESOURCE, null, LocalDateTime.now().minusSeconds(1), false) + ), + 0, + "given multiple jobs with different indexInBulk and different templateId, then job with lowest indexInBulk is selected" + }, + {ImmutableList.of( (Jobber) + () -> createNewJob(5, templateId1, "userId", PENDING_RESOURCE, null, LocalDateTime.now().minusMinutes(2), false), + () -> createNewJob(1, templateId1, "userId", PENDING_RESOURCE, "123", LocalDateTime.now(), false) + ), + -1, + "given there is already taken job with same templateId, then no job is selected" + }, + {ImmutableList.of( (Jobber) + () -> createNewJob(2, templateId1, "userId", PENDING_RESOURCE, null, LocalDateTime.now().minusMinutes(2), false), + () -> createNewJob(1, templateId1, "userId", PENDING_RESOURCE, "123", LocalDateTime.now(), false), + () -> createNewJob(9, templateId2, "userId", PENDING_RESOURCE, null, LocalDateTime.now(), false), + () -> createNewJob(8, templateId2, "userId", PENDING_RESOURCE, null, LocalDateTime.now(), false) + ), + 3, + "given 4 jobs, 2 jobs templateId1 but one of them is taken, and 2 jobs with templateId2, then select job with templateId2" + }, + {ImmutableList.of( (Jobber) + () -> createNewJob(5, templateId1, "userId", PENDING_RESOURCE, null, LocalDateTime.now().minusMinutes(1), false), + () -> createNewJob(1, templateId1, "userId", PENDING_RESOURCE, "123", LocalDateTime.now(), true) + ), + 0, + "given 2 jobs with same templateId, one of them is taken but deleted, then the other job is selected" + }, + {ImmutableList.of( (Jobber) + () -> createNewJob(5, templateId1, "userId", PENDING_RESOURCE, null, LocalDateTime.now().minusMinutes(1), false), + () -> createNewJob(1, templateId1, "userId", IN_PROGRESS, null, LocalDateTime.now(), false) + ), + -1, + "given 2 jobs with same templateId, one of them is IN_PROGRESS, then no job is selected" + }, + {ImmutableList.of( (Jobber) + () -> createNewJob(5, templateId1, "userId", PENDING_RESOURCE, null, LocalDateTime.now().minusMinutes(1), false), + () -> createNewJob(1, templateId1, "userId", RESOURCE_IN_PROGRESS, null, LocalDateTime.now(), false) + ), + -1, + "given 2 jobs with same templateId, one of them is RESOURCE_IN_PROGRESS, then no job is selected" + }, + {ImmutableList.of( (Jobber) + () -> createNewJob(6, templateId1, "userId", PENDING_RESOURCE, null, LocalDateTime.now().minusMinutes(2), false), + () -> createNewJob(5, templateId1, "userId", PENDING_RESOURCE, null, LocalDateTime.now().minusMinutes(1), false), + () -> createNewJob(1, templateId1, "userId", RESOURCE_IN_PROGRESS, null, LocalDateTime.now(), true) + ), + 1, + "given 3 jobs with same templateId, one of them is RESOURCE_IN_PROGRESS but deleted, then other job with lowest indexInBulk is selected" + }, + {ImmutableList.of( (Jobber) + () -> createNewJob(6, templateId1, "userId", PENDING_RESOURCE, null, LocalDateTime.now().minusMinutes(2), false), + () -> createNewJob(5, templateId1, "userId", PENDING_RESOURCE, null, LocalDateTime.now().minusMinutes(1), false), + () -> createNewJob(1, templateId1, "userId", RESOURCE_IN_PROGRESS, null, LocalDateTime.now(), false), + () -> createNewJob(12, templateId2, "userId", PENDING_RESOURCE, null, LocalDateTime.now().minusMinutes(2), false), + () -> createNewJob(11, templateId2, "userId", PENDING_RESOURCE, null, LocalDateTime.now(), false) + ), + 4, + "given 5 jobs, 3 with templateId1 that one of them is RESOURCE_IN_PROGRESS,"+ + "2 with templateId2 both in PENDING_RESOURCE, then job with lowest indexInBulk from templateId2 is selected" + + }, + {ImmutableList.of( (Jobber) + () -> createNewJob(6, templateId1, "userId", PENDING_RESOURCE, null, LocalDateTime.now().minusMinutes(2), true) + ), + -1, + "given 1 job in PENDING_RESOURCE but it's deleted, then no job is selected" + }, + {ImmutableList.of( (Jobber) + () -> createNewJob(20, templateId1, "userId", PENDING_RESOURCE, null, LocalDateTime.now().minusSeconds(1), false), + () -> createNewJob(1, templateId1, "userId", CREATING, null, LocalDateTime.now().minusSeconds(1), false), + () -> createNewJob(2, templateId1, "userId", COMPLETED, null, LocalDateTime.now().minusSeconds(1), false), + () -> createNewJob(3, templateId1, "userId", FAILED, null, LocalDateTime.now().minusSeconds(1), false), + () -> createNewJob(4, templateId1, "userId", COMPLETED_WITH_ERRORS, null, LocalDateTime.now().minusSeconds(1), false), + () -> createNewJob(5, templateId1, "userId", STOPPED, null, LocalDateTime.now().minusSeconds(1), false), + () -> createNewJob(6, templateId1, "userId", PAUSE, null, LocalDateTime.now().minusSeconds(1), false) + ), + 0, + "given multiple jobs with same templateId, 1 in PENDING_RESOURCE, and other are not in progress, "+ + "then the job in PENDING_RESOURCE is selected" + }, + {ImmutableList.of( (Jobber) + () -> createNewJob(1, UUID.randomUUID(), "userId", CREATING, null, LocalDateTime.now().minusSeconds(1), false), + () -> createNewJob(2, UUID.randomUUID(), "userId", COMPLETED, null, LocalDateTime.now().minusSeconds(1), false), + () -> createNewJob(3, UUID.randomUUID(), "userId", FAILED, null, LocalDateTime.now().minusSeconds(1), false), + () -> createNewJob(4, UUID.randomUUID(), "userId", COMPLETED_WITH_ERRORS, null, LocalDateTime.now().minusSeconds(1), false), + () -> createNewJob(5, UUID.randomUUID(), "userId", IN_PROGRESS, null, LocalDateTime.now().minusSeconds(1), false), + () -> createNewJob(6, UUID.randomUUID(), "userId", RESOURCE_IN_PROGRESS, null, LocalDateTime.now().minusSeconds(1), false) + ), + -1, + "given there is no job in PENDING_RESOURCE state, then no job is selected" + }, + {ImmutableList.of( (Jobber) + () -> createNewJob(6, null, "userId", PENDING_RESOURCE, null, LocalDateTime.now().minusMinutes(2), false) + ), + -1, + "given there is 1 job in PENDING_RESOURCE but without templateId, then no job is selected" + }, + }; + } + + @Test(dataProvider = "jobsForTestingPendingResource") + public void givenSomeJobs_pullPendingResource_returnNextOrNothingAsExpected(List jobbers, int expectedIndexSelected, String assertionReason) { + givenSomeJobs_pullNextJob_returnNextOrNothingAsExpected(jobbers, 1, expectedIndexSelected, PENDING_RESOURCE, assertionReason); + } + + public static JobDaoImpl createNewJob(Job.JobStatus status, String takenBy, long secondsOffset, boolean deleted) { + return createNewJob(1, UUID.randomUUID(), "af456", status, takenBy, LocalDateTime.now().minusSeconds(secondsOffset), deleted); + } + + @Test + public void givenSomeJobs_deleteOldFinalJobs_onlyExpectedJobsAreDeleted() { + long seconds = 999; + final List> jobs = ImmutableList.of( + //not final + Pair.of(createNewJob(IN_PROGRESS, null, seconds+1, false), true), + Pair.of(createNewJob(RESOURCE_IN_PROGRESS, null, seconds+1, false), true), + Pair.of(createNewJob(PENDING, null, seconds+1, false), true), + Pair.of(createNewJob(CREATING, null, seconds+1, false), true), + Pair.of(createNewJob(PENDING_RESOURCE, null, seconds+1, false), true), + Pair.of(createNewJob(PAUSE, null, seconds+1, false), true), + + //final + Pair.of(createNewJob(COMPLETED, null, seconds+1, false), false), + Pair.of(createNewJob(FAILED, null, seconds+1, false), false), + Pair.of(createNewJob(STOPPED, null, seconds+1, false), false), + Pair.of(createNewJob(COMPLETED_WITH_ERRORS, null, seconds+1, true), false), + Pair.of(createNewJob(COMPLETED_WITH_NO_ACTION, generateRandomAlphaNumeric(5), seconds+1, true), false), + + //final but not old + Pair.of(createNewJob(COMPLETED, generateRandomAlphaNumeric(5), seconds-2, false), true), + Pair.of(createNewJob(COMPLETED, generateRandomAlphaNumeric(5), seconds-400, false), true), + Pair.of(createNewJob(COMPLETED, generateRandomAlphaNumeric(5), 0, false), true) + ); + addJobsWithModifiedDateByJobDao(jobs.stream().map(Pair::getLeft).collect(Collectors.toList()), broker); + assertEquals(jobs.size(), broker.peek().size()); + + broker.deleteOldFinalJobs(seconds); + Stream> expectedJobs = jobs.stream() + .filter(Pair::getRight) + .map(x -> Pair.of( + x.getLeft().getUuid(), + x.getLeft().getStatus() + )); + assertThat(broker.peek().stream().map(x->Pair.of(x.getUuid(), x.getStatus())).collect(Collectors.toList()), + containsInAnyOrder(expectedJobs.toArray())); + } + @DataProvider public Object[][] topics() { return Arrays.stream(Job.JobStatus.values()) - .filter(not(t -> ImmutableList.of(PENDING, IN_PROGRESS, CREATING, RESOURCE_IN_PROGRESS).contains(t))) + .filter(not(t -> ImmutableList.of(PENDING, IN_PROGRESS, CREATING, RESOURCE_IN_PROGRESS, PENDING_RESOURCE).contains(t))) .map(v -> new Object[]{v}).collect(toList()).toArray(new Object[][]{}); } @@ -660,7 +896,7 @@ public class JobsBrokerServiceTest extends AbstractTestNGSpringContextTests { } @Test(dataProvider = "jobStatusesForSuccessDelete", expectedExceptions = NoJobException.class) - public void givenOneJob_deleteIt_canPeekOnItButCantPull(Job.JobStatus status) { + public void givenOneJob_deleteIt_canPeekOnItButCantPull(Job.JobStatus status) { final Job job = waitForFutureJob(newJobAsync(broker, status)); broker.delete(job.getUuid()); assertNotNull(((JobDaoImpl) broker.peek(job.getUuid())).getDeletedAt(), "job should be deleted"); diff --git a/vid-app-common/src/test/java/org/onap/vid/services/PortDetailsTranslatorTest.java b/vid-app-common/src/test/java/org/onap/vid/services/PortDetailsTranslatorTest.java index 117e4442f..33b8c7e3a 100644 --- a/vid-app-common/src/test/java/org/onap/vid/services/PortDetailsTranslatorTest.java +++ b/vid-app-common/src/test/java/org/onap/vid/services/PortDetailsTranslatorTest.java @@ -53,7 +53,7 @@ public class PortDetailsTranslatorTest { " {" + " \"id\": \"4876980240\"," + " \"node-type\": \"l-interface\"," + - " \"url\": \"/aai/v12/cloud-infrastructure/cloud-regions/cloud-region/att-aic/rdm5b/tenants/tenant/460f35aeb53542dc9f77105066483e83/vservers/vserver/15e46e2f-4b98-4e06-9644-f0e6e35cc79a/l-interfaces/l-interface/zrdm5bfprbVLBA005-vlbagent_aff_int_pktmirror_1_port-dr5jhyxva5ib\"," + + " \"url\": \"/aai/v12/cloud-infrastructure/cloud-regions/cloud-region/irma-aic/rdm5b/tenants/tenant/460f35aeb53542dc9f77105066483e83/vservers/vserver/15e46e2f-4b98-4e06-9644-f0e6e35cc79a/l-interfaces/l-interface/zrdm5bfprbVLBA005-vlbagent_aff_int_pktmirror_1_port-dr5jhyxva5ib\"," + " \"properties\": {" + " \"interface-name\": \"zrdm5bfprbVLBA005-vlbagent_aff_int_pktmirror_1_port-dr5jhyxva5ib\"," + " \"selflink\": \"https://network-aic.rdm5b.cci.att.com:9696/v2.0/ports/6de7bf87-6faa-4984-9492-18d1188b3d4a\"," + @@ -89,7 +89,7 @@ public class PortDetailsTranslatorTest { " {" + " \"id\": \"4876980240\"," + " \"node-type\": \"l-interface\"," + - " \"url\": \"/aai/v12/cloud-infrastructure/cloud-regions/cloud-region/att-aic/rdm5b/tenants/tenant/460f35aeb53542dc9f77105066483e83/vservers/vserver/15e46e2f-4b98-4e06-9644-f0e6e35cc79a/l-interfaces/l-interface/zrdm5bfprbVLBA005-vlbagent_aff_int_pktmirror_1_port-dr5jhyxva5ib\"," + + " \"url\": \"/aai/v12/cloud-infrastructure/cloud-regions/cloud-region/irma-aic/rdm5b/tenants/tenant/460f35aeb53542dc9f77105066483e83/vservers/vserver/15e46e2f-4b98-4e06-9644-f0e6e35cc79a/l-interfaces/l-interface/zrdm5bfprbVLBA005-vlbagent_aff_int_pktmirror_1_port-dr5jhyxva5ib\"," + " \"properties\": {" + " \"interface-name\": null," + " \"selflink\": \"https://network-aic.rdm5b.cci.att.com:9696/v2.0/ports/6de7bf87-6faa-4984-9492-18d1188b3d4a\"," + @@ -122,7 +122,7 @@ public class PortDetailsTranslatorTest { " {" + " \"id\": \"4876980240\"," + " \"node-type\": \"l-interface\"," + - " \"url\": \"/aai/v12/cloud-infrastructure/cloud-regions/cloud-region/att-aic/rdm5b/tenants/tenant/460f35aeb53542dc9f77105066483e83/vservers/vserver/15e46e2f-4b98-4e06-9644-f0e6e35cc79a/l-interfaces/l-interface/zrdm5bfprbVLBA005-vlbagent_aff_int_pktmirror_1_port-dr5jhyxva5ib\"," + + " \"url\": \"/aai/v12/cloud-infrastructure/cloud-regions/cloud-region/irma-aic/rdm5b/tenants/tenant/460f35aeb53542dc9f77105066483e83/vservers/vserver/15e46e2f-4b98-4e06-9644-f0e6e35cc79a/l-interfaces/l-interface/zrdm5bfprbVLBA005-vlbagent_aff_int_pktmirror_1_port-dr5jhyxva5ib\"," + " \"properties\": {" + " \"interface-name\": \"zrdm5bfprbVLBA005-vlbagent_aff_int_pktmirror_1_port-dr5jhyxva5ib\"," + " \"selflink\": \"https://network-aic.rdm5b.cci.att.com:9696/v2.0/ports/6de7bf87-6faa-4984-9492-18d1188b3d4a\"," + @@ -155,7 +155,7 @@ public class PortDetailsTranslatorTest { " {" + " \"id\": \"4876980240\"," + " \"node-type\": \"l-interface\"," + - " \"url\": \"/aai/v12/cloud-infrastructure/cloud-regions/cloud-region/att-aic/rdm5b/tenants/tenant/460f35aeb53542dc9f77105066483e83/vservers/vserver/15e46e2f-4b98-4e06-9644-f0e6e35cc79a/l-interfaces/l-interface/zrdm5bfprbVLBA005-vlbagent_aff_int_pktmirror_1_port-dr5jhyxva5ib\"," + + " \"url\": \"/aai/v12/cloud-infrastructure/cloud-regions/cloud-region/irma-aic/rdm5b/tenants/tenant/460f35aeb53542dc9f77105066483e83/vservers/vserver/15e46e2f-4b98-4e06-9644-f0e6e35cc79a/l-interfaces/l-interface/zrdm5bfprbVLBA005-vlbagent_aff_int_pktmirror_1_port-dr5jhyxva5ib\"," + " \"properties\": {" + " \"interface-name\": \"\"," + " \"selflink\": \"https://network-aic.rdm5b.cci.att.com:9696/v2.0/ports/6de7bf87-6faa-4984-9492-18d1188b3d4a\"," + @@ -188,7 +188,7 @@ public class PortDetailsTranslatorTest { " {" + " \"id\": \"4876980240\"," + " \"node-type\": \"l-interface\"," + - " \"url\": \"/aai/v12/cloud-infrastructure/cloud-regions/cloud-region/att-aic/rdm5b/tenants/tenant/460f35aeb53542dc9f77105066483e83/vservers/vserver/15e46e2f-4b98-4e06-9644-f0e6e35cc79a/l-interfaces/l-interface/zrdm5bfprbVLBA005-vlbagent_aff_int_pktmirror_1_port-dr5jhyxva5ib\"," + + " \"url\": \"/aai/v12/cloud-infrastructure/cloud-regions/cloud-region/irma-aic/rdm5b/tenants/tenant/460f35aeb53542dc9f77105066483e83/vservers/vserver/15e46e2f-4b98-4e06-9644-f0e6e35cc79a/l-interfaces/l-interface/zrdm5bfprbVLBA005-vlbagent_aff_int_pktmirror_1_port-dr5jhyxva5ib\"," + " \"properties\": {" + " \"interface-name\": \"zrdm5bfprbVLBA005-vlbagent_aff_int_pktmirror_1_port-dr5jhyxva5ib\"," + " \"selflink\": \"https://network-aic.rdm5b.cci.att.com:9696/v2.0/ports/6de7bf87-6faa-4984-9492-18d1188b3d4a\"," + diff --git a/vid-app-common/src/test/java/org/onap/vid/services/RoleGenaratorServiceImplTest.java b/vid-app-common/src/test/java/org/onap/vid/services/RoleGenaratorServiceImplTest.java index 2ad68dd93..2bf73eece 100644 --- a/vid-app-common/src/test/java/org/onap/vid/services/RoleGenaratorServiceImplTest.java +++ b/vid-app-common/src/test/java/org/onap/vid/services/RoleGenaratorServiceImplTest.java @@ -75,7 +75,7 @@ public class RoleGenaratorServiceImplTest { ServiceSubscription serviceSubscription = createServiceSubscription(); AaiResponse subscriberResponse = createServicesAaiResponse(serviceSubscription); - doReturn(subscriberResponse).when(aaiClientInterface).getSubscriberData(subscriber.globalCustomerId); + doReturn(subscriberResponse).when(aaiClientInterface).getSubscriberData(subscriber.globalCustomerId,false); String result = testSubject.generateRoleScript(firstRun); Assert.assertTrue(StringUtils.isNotBlank(result)); @@ -91,7 +91,7 @@ public class RoleGenaratorServiceImplTest { ServiceSubscription serviceSubscription = createServiceSubscription(); AaiResponse subscriberResponse = createServicesAaiResponse(serviceSubscription); - doReturn(subscriberResponse).when(aaiClientInterface).getSubscriberData(subscriber.globalCustomerId); + doReturn(subscriberResponse).when(aaiClientInterface).getSubscriberData(subscriber.globalCustomerId, false); String result = testSubject.generateRoleScript(firstRun); Assert.assertTrue(StringUtils.isNotBlank(result)); diff --git a/vid-app-common/src/test/java/org/onap/vid/testUtils/TestUtils.java b/vid-app-common/src/test/java/org/onap/vid/testUtils/TestUtils.java index 756d17534..5fc583274 100644 --- a/vid-app-common/src/test/java/org/onap/vid/testUtils/TestUtils.java +++ b/vid-app-common/src/test/java/org/onap/vid/testUtils/TestUtils.java @@ -20,10 +20,14 @@ package org.onap.vid.testUtils; +import static com.fasterxml.jackson.module.kotlin.ExtensionsKt.jacksonObjectMapper; import static java.util.function.Function.identity; import static java.util.stream.Collectors.toList; import static java.util.stream.Collectors.toMap; import static org.apache.commons.beanutils.PropertyUtils.getPropertyDescriptors; +import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; +import static org.apache.commons.text.CharacterPredicates.DIGITS; +import static org.apache.commons.text.CharacterPredicates.LETTERS; import static org.mockito.Matchers.any; import static org.mockito.Mockito.RETURNS_DEFAULTS; import static org.mockito.Mockito.mock; @@ -33,6 +37,7 @@ import static org.testng.Assert.fail; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.code.beanmatchers.BeanMatchers; import com.google.common.collect.ImmutableList; import java.beans.PropertyDescriptor; import java.io.ByteArrayInputStream; @@ -50,7 +55,9 @@ import javax.ws.rs.core.GenericType; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import org.apache.commons.beanutils.BeanUtils; +import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.reflect.MethodUtils; +import org.apache.commons.text.RandomStringGenerator; import org.apache.log4j.LogManager; import org.apache.log4j.Logger; import org.json.JSONArray; @@ -62,8 +69,9 @@ import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; import org.onap.portalsdk.core.util.SystemProperties; import org.onap.vid.asdc.beans.Service; +import org.onap.vid.mso.model.CloudConfiguration; import org.springframework.core.env.Environment; -import org.springframework.mock.env.MockEnvironment; +import org.testng.annotations.DataProvider; /** * Created by Oren on 6/7/17. @@ -127,13 +135,22 @@ public class TestUtils { return readJsonResourceFileAsObject(pathInResource, valueType, false); } - public static T readJsonResourceFileAsObject(String pathInResource, Class valueType, boolean ignoreUnknownProperties) - throws IOException { - ObjectMapper objectMapper = new ObjectMapper(); - objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, ignoreUnknownProperties); + public static T readJsonResourceFileAsObject(String pathInResource, Class valueType, + boolean failOnUnknownProperties) + throws IOException { + ObjectMapper objectMapper = jacksonObjectMapper() + .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, failOnUnknownProperties); return objectMapper.readValue( - TestUtils.class.getResource(pathInResource), - valueType); + TestUtils.class.getResource(pathInResource), + valueType); + } + + public static String readFileAsString(String pathInResource) { + try { + return IOUtils.toString(TestUtils.class.getResource(pathInResource), "UTF-8"); + } catch (IOException e) { + throw new RuntimeException(e); + } } public static String[] allPropertiesOf(Class aClass) { @@ -169,6 +186,12 @@ public class TestUtils { } } + public static void registerCloudConfigurationValueGenerator() { + BeanMatchers.registerValueGenerator(() -> new CloudConfiguration( + randomAlphabetic(7), randomAlphabetic(7), randomAlphabetic(7) + ), CloudConfiguration.class); + } + public static class JavaxRsClientMocks { private final javax.ws.rs.client.Client fakeClient; @@ -277,4 +300,18 @@ public class TestUtils { } } + private static RandomStringGenerator generator = new RandomStringGenerator.Builder() + .withinRange('0', 'z') + .filteredBy(LETTERS, DIGITS) + .build(); + + public static String generateRandomAlphaNumeric(int length) { + return generator.generate(length); + } + + @DataProvider + public static Object[][] trueAndFalse() { + return new Object[][]{{true}, {false}}; + } + } diff --git a/vid-app-common/src/test/resources/WEB-INF/conf/system.properties b/vid-app-common/src/test/resources/WEB-INF/conf/system.properties index 9cb5208da..bfd7ef985 100644 --- a/vid-app-common/src/test/resources/WEB-INF/conf/system.properties +++ b/vid-app-common/src/test/resources/WEB-INF/conf/system.properties @@ -1,23 +1,4 @@ -# Properties read by ECOMP Core library, epsdk-core.jar - -########################################################################## -# The following properties should NOT be changed by partner applications. -########################################################################## - -application_user_id = 30000 -post_default_role_id = 16 -clustered = true - -#Enable Fusion Mobile capabilities for the application -mobile_enable = false - -# Cache config file is needed on the classpath -cache_config_file_path = /WEB-INF/classes/cache.ccf -cache_switch = 199 -cache_load_on_startup = false - -user_name = fullName -decryption_key = AGLDdG4D04BKm2IxIWEr8o== +#DB Info #db.userName=XXXX #db.password=XXXX #db.connectionURL=jdbc:oracle:thin:@XXXX/XX @@ -63,6 +44,21 @@ files_path = /opt/app/vid/license #business_direct_menu_attribute_name = businessDirectMenuData application_name = Virtual Infrastructure Deployment +application_user_id = 30000 +post_default_role_id = 16 +clustered = true + +#Enable Fusion Mobile capabilities for the application +mobile_enable = false + +# Cache config file is needed on the classpath +cache_config_file_path = /WEB-INF/classes/cache.ccf +cache_switch = 199 +cache_load_on_startup = false + +user_name = fullName + +decryption_key = AGLDdG4D04BKm2IxIWEr8o== #element map files @@ -113,7 +109,7 @@ contact_us_link = https://wiki.web.att.com/display/EcompPortal/ECOMP+Portal+Home camunda_cockpit_link = https://cloopwf.client.research.att.com:8443/camunda/app/cockpit/default/#/dashboard # An Unique 128-bit value defined to identify a specific version # of an application deployed on a specific virtual machine. -# This value must be generated and updated by the application +# This value must be generated and updated by the application # which is using the ECOMP SDK at the time of its deployment. # Online Unique UUID generator - https://www.uuidgenerator.net/ instance_uuid=8da691c9-987d-43ed-a358-00ac2f35685d @@ -129,6 +125,19 @@ guard_notebook_url=https://rcloud.research.att.com/mini.html?notebook=a06a9cf142 #ueb_app_key = sYH0NJnsKmJC1B2A #ueb_app_secret = YOtknsT2wVFz9WISlSPDaAtd + +#Policy related properties +#simulator +policy.server.url=http://localhost:8080/pdp +policy.get.config=/api/getConfig +policy.ClientAuth= +policy.client.mechId= +policy.client.password= +policy.username= +policy.password= +policy.Authorization= +policy.environment= + #MSO related properties #simulator #mso.server.url=http://localhost:8089 @@ -145,47 +154,55 @@ mso.polling.interval.msecs=10000 mso.max.polls=10 mso.user.name=infraportal mso.password.x=OBF:1ghz1kfx1j1w1m7w1i271e8q1eas1hzj1m4i1iyy1kch1gdz -mso.restapi.svc.instance=/serviceInstances/v5 -mso.restapi.svc.instance.deleteAndUnassign=/serviceInstantiation/v5/serviceInstances -mso.restapi.vnf.instance=/serviceInstances/v5//vnfs -mso.restapi.vnf.changemanagement.instance=/serviceInstances/v5//vnfs// -mso.restapi.network.instance=/serviceInstances/v5//networks -mso.restapi.vf.module.instance=/serviceInstances/v7//vnfs//vfModules +mso.restapi.svc.instance=/serviceInstances/v7 +mso.restapi.svc.instance.deleteAndUnassign=/serviceInstantiation/v7/serviceInstances +mso.restapi.vnf.instance=${mso.restapi.serviceInstantiationApiRoot}/serviceInstances//vnfs +mso.restapi.vnf.changemanagement.instance=/serviceInstances/v7//vnfs// +mso.restapi.network.instance=${mso.restapi.serviceInstantiationApiRoot}/serviceInstances//networks mso.restapi.vf.module.scaleout=/serviceInstantiation/v7/serviceInstances//vnfs//vfModules/scaleOut +mso.restapi.vf.module.instance=${mso.restapi.serviceInstantiationApiRoot}/serviceInstances//vnfs//vfModules mso.restapi.workflow.invoke=/instanceManagement/v1/serviceInstances//vnfs//workflows/ -mso.restapi.volume.group.instance=/serviceInstances/v5//vnfs//volumeGroups -mso.restapi.instance.group=/serviceInstantiation/v7/instanceGroups -mso.restapi.get.orc.req=/orchestrationRequests/v5 -mso.restapi.get.orc.reqs=/orchestrationRequests/v5? +mso.restapi.volume.group.instance=/serviceInstances/v7//vnfs//volumeGroups +mso.restapi.instance.group=${mso.restapi.serviceInstantiationApiRoot}/instanceGroups +mso.restapi.get.orc.req=/orchestrationRequests/v7 +mso.restapi.get.orc.reqs=/orchestrationRequests/v7? +mso.restapi.resume.orc.req=/orchestrationRequests/v7//resume mso.restapi.get.man.tasks=/tasks/v1 mso.restapi.configurations=/serviceInstances/v6//configurations mso.restapi.configuration.instance=${mso.restapi.configurations} +mso.restapi.changeManagement.workflowSpecifications=/workflowSpecifications/v1/workflows?vnfModelVersionId= + +mso.restapi.serviceInstantiationApiRoot=/serviceInstantiation/v7 +mso.restapi.serviceInstanceCreate=${mso.restapi.serviceInstantiationApiRoot}/serviceInstances +mso.restapi.serviceInstanceAssign=${mso.restapi.serviceInstantiationApiRoot}/serviceInstances/assign -mso.restapi.operationalEnvironment.activate=${mso.restapi.operationalEnvironment}/activate -mso.restapi.operationalEnvironment=${mso.restapi.cloudResourcesApiRoot}/operationalEnvironments/ mso.restapi.cloudResourcesApiRoot=/cloudResources/v1 -mso.restapi.cloudResourcesRequestsApiRoot=/cloudResourcesRequests/v1 -mso.restapi.operationalEnvironment.cloudResourcesRequests.status=${mso.restapi.cloudResourcesRequestsApiRoot}?requestId= +mso.restapi.operationalEnvironment=${mso.restapi.cloudResourcesApiRoot}/operationalEnvironments/ + +mso.restapi.operationalEnvironment.activate=${mso.restapi.operationalEnvironment}/activate mso.restapi.operationalEnvironment.deactivate=${mso.restapi.operationalEnvironment}/deactivate mso.restapi.operationalEnvironment.create=${mso.restapi.cloudResourcesApiRoot}/operationalEnvironments -mso.restapi.serviceInstantiationApiRoot=/serviceInstantiation/v7 -mso.restapi.serviceInstanceCreate=${mso.restapi.serviceInstantiationApiRoot}/serviceInstances -mso.restapi.serviceInstanceAssign=${mso.restapi.serviceInstantiationApiRoot}/serviceInstances/assign -mso.restapi.changeManagement.workflowSpecifications=/workflowSpecifications/v1/workflows?vnfModelVersionId= +mso.restapi.cloudResourcesRequestsApiRoot=/cloudResourcesRequests/v1 +mso.restapi.operationalEnvironment.cloudResourcesRequests.status=${mso.restapi.cloudResourcesRequestsApiRoot}?requestId= vid.truststore.filename=/opt/app/vid/etc/vid_keystore.jks mso.dme2.client.timeout=30000 mso.dme2.client.read.timeout=120000 -scheduler.server.url= + +scheduler.server.url=http://localhost:8080/vidSimulator/scheduler + +##scheduler authentication credentials +scheduler.user.name=test1 +scheduler.password=test2 + scheduler.create.new.vnf.change.instance=/v1/ChangeManagement/schedules/ +scheduler.submit.new.vnf.change=/v1/ChangeManagement/schedules/{scheduleId}/approvals +scheduler.delete.schedule=/v1/ChangeManagement/schedules/%s scheduler.get.time.slots=/v1/ChangeManagement/schedules/ scheduler.get.schedules=/v1/ChangeManagement/schedules/scheduleDetails/ - -#vid.truststore.filename=/Users/Oren/Downloads/vid_keystore2.jks - vid.truststore.passwd.x=OBF:1wgg1wfq1uus1uui1x131x0r1x1v1x1j1uvo1uve1wg81wfi #mso.dme2.server.url=http://mso-api-handler-anap-v1.mso.ecomp.att.com/services/ecomp/mso? mso.dme2.server.url=http://mso-api-handler-anap-v1.mso.ecomp.att.com/services/ecomp/mso?version=1607&envContext=TEST&routeOffer=st_mtsnj @@ -203,3 +220,8 @@ mso.asyncPollingIntervalSeconds=0 # Only required for applications using WebJunction or FE/BE separation. For example: # app_base_url = https://www.e-access.att.com/app_junction/app_context/ +vid.asyncJob.howLongToKeepOldJobsInDays=7 + +# thread definition - count and timeout (in seconds) +vid.thread.count=50 +vid.thread.timeout=30 diff --git a/vid-app-common/src/test/resources/cr-csar.JSON b/vid-app-common/src/test/resources/cr-csar.JSON index b712cc779..97b39b2d2 100644 --- a/vid-app-common/src/test/resources/cr-csar.JSON +++ b/vid-app-common/src/test/resources/cr-csar.JSON @@ -21,7 +21,7 @@ "networks": { }, - "collectionResource": { + "collectionResources": { "MSO_Example 0": { "uuid": "4f8068d9-fb13-49fc-9e39-634d2094b659", "invariantUuid": "2fc1b3b8-b8ed-413e-add8-3d903cf2b458", @@ -75,5 +75,8 @@ "pnfs": { }, - "vnfGroups": {} + "vnfGroups": {}, + "vrfs": { + + } } \ No newline at end of file diff --git a/vid-app-common/src/test/resources/csars/1712_PASQUALE.zip b/vid-app-common/src/test/resources/csars/1712_PASQUALE.zip new file mode 100644 index 0000000000000000000000000000000000000000..bbfbd2368edd4454d3ed2f274691abf93721142e GIT binary patch literal 87747 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


(hXi zWdpk>D+;7gGQj5d*vq!In}g0O#NFM%s7G1uqpUNZ$l)6ttCX62Aragp@_?=={FPzG zFRmb(*V>7?X3r0zpvG)(^7{-W>|;wd5~uXMrEgX&?ToScePbyKoiIs<_`%$R`5H%Q z7xR+S(>iobjDSDmZ$|am23;fu{FAjaBPk#m4hH<{&7C8axRQ}ar>JW;RD?3dA(LGh z)txt=dXB5tX6)nRi;3`ZBhY(Y@Fo;FuDKF(Z_7uGe=l?VoLb{*p@1cHlMB(di{Pb$ zhwPA4W{%JFXz}4CH*80N-tr)ZGRV5p%#bPBTrii^aN(kTo$^t9l@Je7MdQ>#j}F#0 z$qIlcZ=xQa{(A8mv=_GQ7(jARjzJj|_ppywK!OgF=*W9>ac7l^Ot#M!*DtIK7C{8b z<^uLEW#e6Q(~Vg{Kg@j9qS9T{;s&!c)P{^xEQsgoW)K zpo2F!e%Uu8u!{Tql7-U+2~Qd}{ao&w=o@R$_z^#-0oFKzSYdH>a{!)IZE*m5fn{u~ zhKq029wQp#08j8;`}RzDTf*+pD=x*(#;{}zLoiX%5t1uqWzx?z2AtroqsbZ@HkB6; z*ONQMeO;L8shmGd&_joqnX_Ty63!gPn_cC^y;7qTajI+ZLm$=#ajxI39Y~Fc2t;00 zyA~R4$s);EPc64aGq2fXGX%6Pl?P$$7kRT?Iu{{zj|6gRBu!ssGEwg@kbB`(FU%_lKsZ(~h+=fki&P>JTr_HTnVA+s%G-4fCtT z+B6rkVps?+D)}3>BvpOTrJvgM@>zwZ1@(7rJ^1(ihVWBmK*hB?qmd!}YW1R840I5n z6Z6a?r&z&(IomBh2nmbLE>Lr+S zg|u8lDlI-NLbWB)OYUvXp|^GX!<7c9$>>-nTPJopx4_-0H3oh7^No^bh6)~^7ep29 z*x%n7gzM$DL7XqQ&j_I4?DpR;{@s4it?NsEmQ@S{gFIH8x3!*lK7bQoy>5kh7Z6`IgR&0n+88O$!0 zpTwyj>UDiAi0k%X2C^pzr$MsRlI?J@({2+QK`FY#QpQ3NbO|aW)K(My>7`5FeChU3 zUr|r47m1Cu+`qH2%kUs>b_*A)qCE+14Q)kTbULxr;@Hjkz@>l)9X)61Xwi`eiJhV2 zMfnoJBzNra7(XVn%dslx6Kb~+yugO@t)lS%*l8y;naA-hwOH*fO{Y#L;Mz9F_Rp;a z;$`+i%FE=An^RCQ6rSF_*f;Qy8coTPQAU}m2yf@VaYU88J?z}Pg;%QuubtnY_Ks3w z$Y!BfHb+{KUa^)=h!?Fa8cAA{&%6l8MrW_4R`q9tpnnt=F z_kyU4dsf07&(?5W7!8j18#$c5LBDz=p3{E1Dx;bWZ`uD2_BB~h-X`jIjM*+;3N?W@ z(cY4HWq-M_RJLW&E`nRui>zzwPo!0Jg57J=23YsCRvi|#>!oHalk!rWGWqCyDO=RI zk9JqNisS0m90i|HZp^86;}KX;zf<{YQ+H&_ ztgJ3M6;&A@r^J}WQ5xg~e`{^>=$*~KxMJJ@La!f}dRu(5e#$+e{?v+>WnD$5YN1o=Sc3M?Bg@)21=Zo?&e?2*aEQoZl2COgwie5rdS&+lrm!S*rX@1ds<%&7M zfA(l699O9u-z{VF#B8bk!F+QhTU8H$qiN^L?M!cppd~4gX5RcvF9P(oaM%ARC!J=; z%m088P>jVDzKysgy-CDrS9dPH^&4$@RYo+=`N(zfyU!1iq-a9YVD1=Kn@ZmYnP|t) z{V^-te@~@zM^yJ2DxDH*SjUwRyx>r{WJTWKD14gGDnZ+Q4r)kY-IE?y^$a7dAZUaW z)RDzvlnHNE{HLnAQi;a!L0W?8ji-jNeQ^#kbfU`mwIZNKnwDaQntV7IHzQlW=aihF zUtKS!;J6^7MuY>G(aLfy)(RZ{RAAB^7c;qTGv@5%^Hdewr^=?64Z^%SLM3Xs004hGF9FQqQmq?%$oqTTp8$x=f@;w1AY z3w>3Y1)dxJM8jQM=+u{07sX*aj@*HRdJuX2+|ITf7zBV6Rn*ao`sT?6aW$7j#e7VVs=~8}vH%HjCSi)Q9$i-aMZ4Sv%f8nHhKn{1 zc8tOEpSK()*L@&DR-P5HVeB?>7G1B8F`pL~*niTnt;4ufxg}tIBW7sD#J?ALj+w;H zi)U|a?qGQ>0^~avJ#KldR?=Z$>VfTeRS~2@08D8xz}GBve3I}P)Y9Z3Q%Fm5j6oUN zQo=M{3p5iGu!$IC26M}Q=pp;^_()f8bUY2*7#Ww(T}eRJ237`3A``FfKI;UqVjwYt zIkR7j(YYZpy4B_qYa8Li6M@W(#hFqxgX)PeFs!C=A^x^cqqzC~(`y}9E;NXFV?+4c9PlF> z&O!Xa6~1#8^TmX-og1=PGXeV#E&V=aeBypM7o=Tu8>FE<36X{|#W4$M_d_8HY;cHH z!QufzvL);(XIAXaVX@e#u;*_7Sb~b_(FAT<1l#cM1(xuVN=-z)aGh9YqjuyFX@gS6 z>63ZQ>vjvwcv!|nxq>N-B~`OC4)QtffgmYOz-TpdE+()uAS0y&af}ko#F_Q#d53q5i7q_@sYC6gfXE6=}I;EEb{7;d<)#V{f@uV`iGOvr9`tDwI8a%fIbmeAl6|F$f z^OA{FL9vk(Y-Ku_XyI6T2(uD$-KFuI4!U?}Qi8W}wO^R)gM3&Q;ul+Mzg#Gi`bas% zEiZQl4+C7keq4%Ot--X8lO515huoIM5jxmY230niG{ym8O|+)@4t#Z5WlssD|FQ0S zyhr8i47I!w{VMh%-B7wSAEH8g``Yo=H$I7tFDIdbY-LL!nG!*vPg!O9CQblf%0V04 z5HTWyKuWpOONTuqn7Xpg6(6iXVO2#meJP$yb@;YT1NMycR15nxz+(UnZs62EPkHlq zuu%KJ2z8ICvn$-mTtkT*h>+%(izp>^`xj^8*?_FXveMZ|%r)ckFt zQM|jdJEgYBhWOn7TL`2mL?zO8IQ0sk>g0HpW7bD1C+X86a@DXf(lqkj2U@102Uyuc$lJ#YJ8q-`^!I6db`_VJ?9Ov;vgCapM7 zrqnNB5NR6XLFPM#QA0zj3oCJ9xVkQpL#G~b&IKBfo^dCI-NG&+n|QUQ^f=0=HEMIs zPDmeZP)Yz%i}N4d@zYDdBZEAO1p?-6LOug;M|t6?bPjuXWP`k5gF2KgTlc?G zl+*&O@{hw_?wlUnSi14~Hw&PS08tMk1*BuOu<&c%^P0tY9+_$5f$bSu(miZF6lO*M zBu2R~jUE+2ck3fX2n2L<{w3+;SdCl?Mj<6doyrYoeEQ{JLijO|EWF5+_<=EHscxxn zb{s!t#1Ad#%TWjouUa$IFOn<-Hoevgr2S6UxU$!0UW91|@+@oeeV!k2d#MW@LJqPHBEdH`t=kU-B(>Oy&jv1UinMitla(C zjx%ETChJ^qXw08T3&WwMu2xxB3mLyS^(Tw1XIDFyGmw!(>kZz;ouKW8mx```IH4{$ zU~*dn;0nI7dVZWKY#3Yj0w~j`Xmj{x@%Tc4W1i-p^4yZQK?|Dwnwx` zrO|9=#R`ULg}U)-OGBkP^-w{a!88E1`}WsvnKT1E=YoB^C#cj)^Yzv<1sJ9Efe5S| z&>RY6Y7qQE3v4^{)GhvWNY)H0(!*96S?C<`Z+9kq<86nSmO#_DE{-!hMEhxcjoS$6 zEq>TFXGrFE%zsCOM-z=xnZM&;lgL0of7{gmnre4+u(dL=GW$v`!i(hlI|oEy8|D9EIi9$F6T8kjPHxEw$@t-IGZ8JRGopO#!yf z$D_lL77=cVx_`&2X7koK9d!TYxFJA3;56N=e!|E3p(HI)KShI-3RLo+co67Be4XShZ=L;K_J^(0!);Wmw97`Y|d4kkjb`8r3 zvS(w#|IeW6l$o^C=^r#MVS9`dwh&MZJz~DRQc8DhEv1Hdq2RU#Otjxt;QK1fla36{ z(bn@~If#1YV!6z_O(-FmU0Gc=vt>@bKXuCDBZv}zDbm}7Us&VNM3MP>TA*l58{b3wuYz)+qLhon0DQq|^Lj@Mgw6mdn@!+}^4S;K8VM4`?oogghY} zP+TVFA}D7(I7u}8rhEtXt!Q!n-L;5ZC_$@BN6Lg+pQG7tX5b=pT-e7;7fi#v))YI_ zPIPYFBR~&h`xREc1zuCiy-jz;Jn5Cmpk%Uo!d}t^>r%jLzr?rLKKIke+sA{eJ@bKa zDG`27vnUtDlw-&OG#qIJF$3mn>YF-=qS30@-X@2fV<;>KJd8_dO>56P-}fOMjf2~+a~V%@M6?0HQeJ5!Qyo`A^cF8pykuYfR*E6UOdVHh=?<>$*@D9 zpS`)anMob9+fFt*gCbwZq3!Ta?NsVm9hKV2Rl`Gf1LNHK@co8C$*%|JTWMK`3@`ec z+uTusjLWU57+>tg&daPX7~bzf=Z`J2TFRk=B3Qxj z8fENtT^rW#dRd)!g@$@NfXQ9)rOEb*6>C|&0oFr!zc{g#0_}6pY#Z)biob#X4M3sQ z*&-BwC&2zu1>yb|02$faI{=LSBeD61m--})+pjYri9NqX26S2hOW3yqH0%k=XBHsn zD23GfG;yfG$P&pVlpdb(m8bfxl@jxaCPBGT(xg4y&SvhVTJ>*= zPo6O!`?OV4l8Y}Tyc-mI%85(_BHb+izma-sU zGVB;I1?Om`M5dR(eFIbr;#5OQ4@D_~nlt?WlqfI$N^S?tn~2P$Q#xyp0n5~=@XOA_ z>XS26pP`WsXLUy=vO(h-7%M4NH$^t=S*?Yk%Muf&mt)o2MBVT4CKNecXpCa3j-Le$ z5yPozy5!<-lApk@q}F<&FamS`4H8ZX5(Q~3V6BsJcfJU{6(b5V zy!qoJ62kY5Rg?;AhA@GdPV!Rr*;*uXQ`24R0Ac&?Gij=@zh-9TvpXEoQbne0c!1^5 zF#hAe+)HC8DKjnGy{BJ5j|EiP?n4#*W9V_6JbvcsnJ2cBnNe_?oE4CoOH*%-%oqw2Pfy7HTaA~WY+W57WHl#PA4-}-3Pj}h;n+#+V!S|gY{>Dn zOer!M%DUW)VzKdA@Y-^_f&p&y_}itV?${nm&h(u(yOWGUv&COB_T2q6XC#VUApH5)pES4};6g2PfV(`TXU z5To3n5rwIl0`6n+0i%|Op(`!sIbd*o8fjM~r7-up=8yLZoMEC(ANtB;rsaHk==d6k z?P3K7e#!jGJcMH*7y}AS@h=zzq{4z4!OB4# zo*M}LEGp=IWur6F=|9yFet0F035Q6kbx~0GYw%{+FJnv*$6#R}S&L+IqUavkSO1jZ^a<#-@4HtdPxP><;bpC}c%9UqBEKouY+(ArBSjNFb><)Uhm$$rj;e-q3=KCH~ zBV9BZ{I#eY6xJSB;6h_@R(WO7*Qo?p4H-3s)Yao#Nuv(|jAtj7*?yYS~kLsVXgyrwhG)?X%y)Iq!==_EXmKzj<q6 z=zp<9`_MYBz!}3cr;Li}B7p0X+h>cda+*uX7P;B9S7Bd1j>`F^L}YC_fOQkNK-Qs+ z84brfv-Ifm^tr{=3h&y#6)`cm@#$M;D*YK)x`gXhrjWc-I=o|$XF#hdqV5@%Z@(Vg z^#Mp+S}Q1xA9h{htot07p}kg<1^DoZeTl_p@;|uK+n*0bHK*_M6bxR&tNF0c`UyuE ziA`zY`4#mkAjX=5e({U0BdfW{_>ooNogOIOc*C3lp5KsTtqdd_-+NEuL^Y0WaN_ssu}!q%b_+p<;0J(`m4eyRvSMU80+f^5Nm$tDCO_KOjiytG@K<4qaP(IqJ@&f%)NO z&Xv9ZEaPN~hL;{_DYov1#?xfergNwbauMTZ!QQA=VBV7}@{w2U(Rq1q1mP?1g*kXK z$fibh1@M=s^AtX5YA+3*vv@z`0^r?0dI=Xr%zU2ytM=yCIXsf^m*n9572aU~S0plW z23VOJnE?KiYIXjV3gdG9Gs%v0Wn@B>WBZ)W_uD|zM8^WTgW8kj0DFy8l~j&gZe!J8 zTf&N>WgWl)9ti=Al7;sA@*;UUx{B&qB-0W=duBVBYdpzjqZT0$bQoyA3VBKQsq`U# zyvKwsn{=8NKGPA4vzX+X(B1=80BYB4v^P!On$T1-_oI4tELGME|2)|oN||UNj5v5* z6x;#)8zZk}*td9Z74@Ywk9+9p?9RD+8SqLYL8cKQA-Cbj6Lr27;B*_w`eVg9Ps&m&L!RY7vMT6yQ^#@-!7gn9BquNw}j|gK8CgXAC>mx{>{=DsN zz*jD#zCKbAZSn4OHRcCUMTkUAa1;4Gw14%uzwmg;))|WHs$Q9!EYHv3twKEORSs@R z4$vL7aAQDGQRHcsL!@wKhvubX@wL4#1TY$r>tPD1ekLuII#69Kr|)*7Xi~IX2Cby3yv&~CQjp=*un)bl#k7~xp>4sxv!xn0D4N)*?$YQqdS6M!4n!Q zu%<7o`P!fONrR&&_2SP^(tQ&epdCJm0AW?pz$e#anmg0A^jF&{s9mF$#~teRs&rZ0 ziiP5|v>NBsG>(u0fCHz~hk_c=x(g6}<-2TGm zsbW-={qAtyvF$)|cEQFC%2~{~m^|f_b;J5X`Z}34(w;*N$_>HP55&$%J$S*K4Ccu@ zJ4rR@87WHX{qi#C2T##3O&+AtK&M|Y9Azsll%;5@=6XR{uTzo-rb9ezdn1OL>}7`mp?K9QTmL$I!bjg!6I9pyW@ zXEqzV`kvkEqC5&qrpENtjuu1E#vyM#eHz)XyOW37u&ng{UQBG>-zVN=9ic7k3CYM1 z`Cy2?4kue0N0DJ`a5o1O12aH*zjrC5NF@t)$IihKUGFl3P?hf5B0`Sn zfdDS*Gb=KdLH0Lu?*qa=D{U2UUftfY=KHbQ)y3PnNvj6OXr4=n*3P4YsmJro{T4jw z(^|yll?O`h5Ci3#+7N1%OB*->Azt1LA}I+~0@S2{V#d-EpblkGhK37avRw~RR8gwW zsAi339@YBz?r!cF)PkO9FNQnd=LmMIJ?W=7h^gnfOg}VE`Rycj^u}PLH?PkDW_v$> zHSZ-1`0E<^Z_w?Xxc}TGfT(r>)&~}45WXOju{ah+kt{_GK>8$#0*+$dbVl4MQdBSv z1phfziqvSE`YHl~Y_{uIoljQ@=Ald-Z+9$(oKVLmr5Q#{PDApB3?K;03u;vJ zGP9`2;(qaE-~i|xZE!zI2;e?WF{?_4h1eXHcGR6yxsh~pVxnQUle+a&aeO3D;5veb z*{Ch@hL<8R=3G;VO9{igz_Mc^01@eZ?zBb+vH(fJskr1l_l0oQR$-BKM}8&7H1HAH zN$_Yh#_Rn?ix5Kx$pIFFL3rsz(!^j)@b18<4O$AJ0#5OOzP+{RQFi$y$oDuUnl9WR z_$jf^&jYb`5aW9w-A7Ps0mCCY2!Q@=BPb#4FZOXd9PSg4pzKM_$2dgMBek*=)fB|( zCmNA3Etx{ML?e#}n|KWoBWAzZAF60OLK72{C$@QgeC$^u3QBHpzF3QM=^kg{jXf$b z#@~cs>*O2pcR8NE7dq#1yqw$ine>l{jr)j<Uu>#jU7tza8Kq2w%D4P;DS7;&X~c$fI22UPgB=lLC&XO((Q%a_! zA9wEK$ub~gA9FSm&f%>(hyO#2duv~}@jwg!^GjSCROOZ5vn_)p>)I3(c$ z2O1w!we%czU>lsION{acwL^urZ}?cV49EkIjiEf%SmE5!k{fxD;7v1gTB7I@3JGMI z9^L&%%>;G=%O~J=f8hKv*~gs7EmG!qwVZc*!sX!+!@8fwv1~DN^*zEL@-jvW)s>;( zIv_irl4C@(jC77s06l^0TiCJf)^&^vA`FGrLUQaCl9Vycv=>cpOglt}j@Q{q>ddcZ zz~B-ToXdHnw+!952GB|;*A}@rc+Y!rwggc&v1qm&ZgIXX?N`c|T4~iAFgg5Q81{2T zBC+1($l6-H)D_g{RjF*7JY@bbmGVn}C_RvDxfY}KdmFb6KjWo)aPq-ucfg=Wm5pd| zlv1v9b>gBumOQ2$Aj_3v!%LEB^K(pNvY{~>% zW}}3<1tXo;tDGd1@xjQh{!ODyi|0M~_+q4$anw-KIi%E7mHj;m@q6IFf*oD_+*z)@ zBQ{9R?4ZgF!W?Cb2c|MeLCxr_U=$hc$tid~r)IR*#62T39BA00zdyx0&UD#hmPA|P z$pl>Pajv|cilHyw@I|%^*q(k-DYy+}n~A{{9PRORak^O-TvtkPy9!(LZac0Y;XWZb z6tOUg#zx!#ljuA4tnMZS# zduIlK>teC)M@$6*Nfb` zt71g5dmAWdz_DO64W%3wlzZd81YFA+U_-w16_OEn7TWSnOUNoDId|0tJ zgL~0!#U&DxxEB>`+I+&|t@q&{p_aLt!7|BDnZPcbRk`tHRpF1IC#}LWR`NAK=d4Qj z#PjW=fBnsxoE~U-T06MmIscB1YX#?>pXSuej0>#Ou;G2=2a@~nn$Lx%62R(pX)XE& z|KG*8_by-a1P}n=^Pdk0*8eHKmUb?tPXAEEf0f>tL_zy30fdm-A5`Mc1t~Z?FBf?h zN7W?==@H9hWG#ANJV>{;PGN}O9^kcvB%LYHP|wF}Z{VnPAUug8NDTpNsHZ;h;5ACx zHf3{2|9S96upaTZJmGpr!{Q@1GNgeWQM%Y-Ly zTU}ep3+O=`=}isr%;Qa*-!RQ3TTw=o8-Kffw+5BFHiyso)=lcS`?uM;PvU*Sr?7ag8fAQBot#aL6yy>*R~8!%LQFq#22ij1;z0ij?vk`CvG zH6iSq$XPWaxW%H#LRm>wYyP2nyf+D`Y94)Q%;7x96M$T#x>T?!i2mUHw?`)78aC<^1%P z_X{o-7)b&Dm}>x!9NUOvT zFhzse0}5hVNj!!cK7a=%-G|QoT)o|x*|MXP z)M&ff*%9}{EbBKH!O&HIvR{@SK5jx36VSmqaejf101514iBpPZ$`VWb&sd$?|nmyOt|a9?Eus8CO2&jM2{=Z<>aEM7C4 zzkEJqUu6iEg(E9E+#}+LhuCjtpo(wr)07!m37l)SxNnOvMBav4iWGd>4ED^M0dy5# z6K=#-)SIWf?K|06^DAX@y!(gncbyIl4?0V@STJ_R?2W4^_yiyrjqEOV zG(h&>oQnojWNsjp=j}@|YmZc#UEm6A^wCGV3>49H-V+Q73Iuo|;5bWlXtHGo^EmQ! zF?d~jpL?0Vy%9y)vxhQo0pQ3rjRv3N)yL(61@y?7l8s_~Ng?OKEbn+IebG5*%k}6nVI%>p=L-S78=(NbvHO)BHS6O( zrte^`j>jl#>7Kd5vTfaZ;({{NgnbR$KoO*u8gy&Y9{>J1#7liAb6&Vv32SmlTs{`S z8|LYcoHr0HN{@$_R}M9Js4nPuT3LP%u;nuKtU_zntEC;)s)htR%q}y+t82O*i8MW& zSKj%ME?Ln;WZ26(Fs@QK@XNH(T>z~^&ATQ)ttHG{(L@aND^A`91A&qga%<>kpP$LE z)f74%p5voU*jTq&q3(JMV@=f@5EN^Ym=fRlU*FFklhdo0O^;2!x9TDU?q|aRC0C73 zdneOL1(mn`p>sxW&i7{q9QvD1IbNXC6qcUASy>S)>n_-0F5Qc6QNL!b++jN`E3fDl zicR`ObT_S3zhWpmH6ORJAcyjQxT6*V5Bdj{~R&GX{5Ndk~Nt zkh*2qm}S{gF+&;5Wh?b$L$3%NX#;>#Sgw~7w==MkTmJH+y6-g6t1H8j{(z2@Jz}>x zT_z{lxU7%OC{0gZcIlu;7T*fwy0b6N$LkClAHj8ylUXE>>iGRYFSZ?>D$vjbURDkW z9MO3Osm|hC={Nv1D{dp30_pVCB7obn8JbinDV{8a{Zp7)Y-;Hy{!Flv3g)_HI*mX; z*e|e_+GdvQ!@Pg7Faf$pK_?>T2lK}t1sKzpx3u7J#a~0+1jBg3crs8+eSM-qe34u> zy+yAO)v$89uUXTqi>s=L_-q5z!^FTs_k`8j)CWkNvOcSdjVJNrafZ-$e0FV3{Rq`q zRDP(2t^W#twjBUljDwdoSc?OHbq6g=`TY>#X=KHL;}yX$hKO&Nj*ep+)?>Owd7+sT z|A}DI!a`U!^GPub=uXo_S68;wwbZb$36rnpa?Ph=h8sMrw#E`OJU-$LsM0l5)$uy{ zf~Fw567PqrnsG_hGZ3$G9px0mCWPZZL9b*#d5Ib+CwPtcJx*zu6-D$P0Eu00Q<{?jCPJ^8dI6BtPA!ig-XLi!Oi)3Ii2 zx&lLRU~B>sQKUFwNJ-wa>v-r%#0(nD0-C=Q2AJW}(wii>MWOWGqOreaWV1|!jP4ug zOI8(Y&k*|;=T9ZzO#qI-P*+mFnPCJPwMOIJ=?IR>WJ?3`G92xCZhF_8(j25wzIBa= zlz}+?8kV76#YJ1&`Re%5$qU`O>Qsy+w@_Qmu7IS=7&cW5B%4_0pb-GY8C1kJ4rxu{ zw4ON}$3}#;Pv|(ura)JGT*4|Cm171AQmQ`E2 zUOyLK%W3fI_5cY=!13lIz5ZyLc}%i9#}S$?cGBkK`TO;EyCdKG@z=$dn@5JXjT0wM zP8w^<4MdC#Ncz9SF(j&3OSOi;4A^Ec?T5I#D1VmRAv1{{us4Jy2a{7wjs=diZzLEO?Z3&JvyR+q47rvJIJ=#GrM~WSv(;`_ zs{B!r>_6`xCu)8z4pXq{hM(x*w||3ZN)P?{;whMT(MytK^5K5<8HHxda{R{`P?Gk` zhnWV=wC^~(Jp3XdRj-Hd7Ug4z_JDS9KZZplufm3JQsy!^IjV`yxwl&-UB-<92|zbK zN^$R^d0?0dE^n`mKf$;`xGXXNlR`8eo~a>dSc!>>RcXqcENP4XwC-!E2&nv}X~=0l@RgHJ!!B z68WwB?a`l~q)`)|0_-csP6b`PaQQ_KeoUslt1t#PHbEPP?AJ$%A|7uZ4j}?ZN5*L5 z>QV`2Y;W&kNvCzSj;5=HZ$MUoP58Y|d)(K(AMJdsinxDfv)=oDyptc)KD_YZ!u`=% zlZT0)+_)n7UMfdGW-xZceL_>T{Uu9aWD3pR-QLoXgD2cSpB~}c=7_|4vS z3EO4Ln+(s`+s}X1(lz1gxJj25+`aF)f0`N2Uj1yHg&a?)T+M&N$x!6N-3T zqZT@g}1;&UvJuNkzXTXtX^PgiaS}DcOg2U=Cw4hgPkRdM&fHr88G@4jr zL>$*$*qCV0#&p`NDIXE})1f_u)7J%rIV1P6&(26g|0k|qczXRC0G_$>lzWl``$bY- zASoVEeU7BcVk|;wK_n^S?XZCCAP$$D=-$;8{rGM(Ifn46Kb~*JDK{>mjM%?9!j6uARu z0Co)UYJXMQx<-*B`)TwLL25gHQoCL28*`n> zxWvy0NwvJ}!(JYb-fWayu=f3`?L94qAx$65dU2;G!b83*S;BGLTj*Q9Tr4(+w-Qzmcg z65-%zM9k1K7tCU1=VqW7zIb$CVz6ovM6MW4Flh?DAZDTL(lZy0Cv`D26%FQ$SMmt? zE`DLUOu62;^pM^1;5`H*sP=Jy64Af*ErE|=I&)C=vE_3+p7hy@sN-e0Zx~S-JagFG zD}-=U5umU*>0&G?%btu`Y#Ev|G~UqgEE68^L~r7VU>ifYjx}S}_>F}VTPa!_`Mz2iJXGCl9dCQ82!aTrs$DEo%CW@&ms=ni_WkL}MH~19V%lLAZ z(^cvF=HjQnMFm1iwPQ+j8cp@OJjFwIczj`r0P+3I6a$%)kJ8{#wH1~To}M8>bwSZ% z8g3Y4AVCzs53njQz=D0;*b(0(0*Pe_gnjn~3cQZE1s;e->$7KD{QyPx>$DmBDe4ix zNEMv~a-OsmQk;shn03-pqRO?7g~W)}`y)OBX6 zHmWOR@Tpk!rIdp!nS+uu#fu~h`V=K)6jktGy9(j8DiYhV+@S*4xN!%ujPf;J(=u)* zZKFzwP?n8RuMiCW#$YN9ct)+MV@KA`K^b7?dpyRHq*fv!*vH97{;sb~Dvzmv~0qsTx)W?8WQA zibD<+Tgn%p{E>Ji|;=Sx;6 z)5TJ40-V(hqic3Ck2=9n&L?x3tekR|*)(dcrG;HnQRfC|sph2Q?^#v#X70EuNzJQ`8e4P?oOXwe{^<4XE7;siYY~p zvsNM4*LD5bj@vi~^T?CL0&LH}^zg+?`_NNE(e#zxM1*_%q=kK(kgm43uLhQQ+_=Kg zW|a{zJ`r8-l_pl5=FgGLALRhud)RzTr%?(6iPf6@C)<2EH%o1_rPs?aO#8EZ@e9s_ zz~xhZC;84#LnC-tHp%2DCne;%<@%OsJlQ~#Sg4sFL*lGtn8B!cI^4=2AFKKF<_i%8 zgr0N&M8ra&iTXAbd3K%@LDHLsV^dH4#XIEh*+iMu3Lr1)HjwFIM@ezVY0D+&wgytB zx|f+s_qQV|WC{~Bmd%Ck^UmXh*9U5I?7={>T1pai`}Zg_@EWZ9eJ!!fQItkTM_YZS znfBa)yJUS$OYQwFD{431-Q?(o{W#~3{3DTkrwBs=#TFCG5*xE^SP+x@Jl!r#u5~ni z|Gxv%+`ajcuCLvQZ|7CsEhzi)@l}SXSSF#x@CZCl;3~d6ny49zVVhVK37R% z>~P$&g6`I0u-pt<=*4XhsD)Mr-6Xck=SwMRkd6IUz-K^WO9QT;My(9ij57l`kXBX< z#m)P4O9j*5M&v@4Dm@JNudDq?*Fuh+#>`Y64FHFsLDKrat9S$@VPft$jgK||G<=nM zI&N?9glgY9fbpOUy+ka~9!FbF&{T_sL<;|WF^i*_f7QEfk013m7Bl67NKz!Tug?uS zAogL$Hiy#Xj>Ev|WJ+(FIjI#3R;p9U9@-CGQpiMh4f;Kk91tX5ATZ=UU zY~}`WXBQxSa~XmGSn&F?+<%9Vo1g$!r+>kGMRO&13i+`el5z`@vowNzP(@5@JBLF% zor7-5Wm0aKane3e%wWo;U&$BqIths&K9H$dm#$7MC)J&{4t5*0vp$`9LOdle_*P(4 zPVYVf&OC~%W$zdk@~4RMUeO^#z0;ZoNva(O%KU z=nBK|Nyhpj7F#fHq)eQoNh%WdS)c=+z_%e`KKcfSFtss_xR&u^fX=hPp8f)mVs-XS z_mEF2^T%x~{9_1?U%KJSv1L>hc4Q*u3<8jiH$aHZ>$C@4iI>2%F8-3RS-=avpoTz2 zF|P2(+WvKJnx z>8-ICPvq4opyw{Q%t@EaNI~>LKTLeL=t57C6>j=KJI@Q@di#wG!Zgx3I6R{8PJJ_e zS!JlIQY2L;p0`OosXp<(^xB9Gh2Ej@fyHUf%fxqj%<8=XQM`5L(!pD2T2`+m_veY< z&#IWF5F##^{i8m4>JHSp0gb{=un252fnOBI|!S-|YG~U%s3wafe*R z5)@ibO)mwB`V5iv-F++E>yEezkM9%ulPf!50*6q?toEYU!r`jv)w+Fq{$y&T)$8ht zTKw9?-)#9D!jY90_c`*Qs1D93k8ZZN*Ho((*ca{(U-e6xtT)Yc(+5?3bDfvwld zC19zq<|3Y49&a{Z%qzZ!-cm0Ky}Z|NVppmFRm&-aph^!uyyuyI%qsEejh}BGKni)c z{GW@fomWoYw26)od} zuq|whw|lNRuKq;w*8Z-|v|g_w79n}ks-!1Y=MSDGygzV$*apuz?^3I2yCy4zf|0b8X+yi~^C!IxBhP6`|6p3AI7rkzcD;3w%@_?BAOvyXob44?H!|KgKC+OSOnk8-IjqT2H@fH z1j6gXs&o5M*p{%EI;cgG`~u!GyCq>8`}GTlROLM4;8nDd8jfx$C9_ZD>a>u0`FFdN zo-I|#bKmx=nYtP-p`mN*hF0Sy@MS55=|WNsd_A1}v{QHl;KBaL%y|I@=00nh088$m z2y_UK%tZh*BRhjNs<`gq9TV}jTvqx*d?zz)vAtnZa_iU{0VT91Lq<>m7z0|q;HF`3 zqAqd}WC0UrzO>a*Kpq=(1rtN6SNlq`Vyzv6Do}0WW;GXEzZv?PY=ILp7vNp>h-L5w zn9}GgZTcK1N5~z7+0&53#l2{ao8j+w>z!mvTjI-%7WLtFE_u&Lv)ogKMOt#pN*QR0 z*=$ZJ-yf=X@~DFCW`pJ@z-FXU>|_QOpG7#97Uxg;)PbVW66;Gb^va=+-=qtRnK)Cfp-c8qcgf3)^gQ0dsuyRBE zmQ%1zS!T3-N)Bl{8}eGX-7hN>+cq=EaIzL2 zwJQ*8a{>IK&&kGV;s>Eg6zt)eQ&D>;;9dQA?m5Zm-3;q3ZX&Dwgm4WgRPM;PmT3`n z8Kcnf$NA~y;NXThiySz)w}q(~%s#Ho!Svr!8S?ZugJZeqPw->B3j?+*3Vl*Hm_kTxag=yUo)>el z5V}P4LV^al196SVgA=W4WBg~nL*PBV7$Ha3->PqLg9L0JDOZ~TCdinjfT8)5o#^~( zF@zn^<3X^@Gl$d#76T!n3(j2`=SQ7;a#Xt{3@X5Gt|mcdV=sn&fQr_~Ua@U7+4$Ga zn504BZcq0=NcUi1$X0KCyZJ_Z#l^p#|M8h|SnQsOK0?KOxg> zGT!C*Nb&Z-AE+wp5weG}BA=I21NM9NfM`nUGj#Q~*KoCB_D2K@SZ+42+?nL>{qJmv z5uam@^rA@vKSS&}pPNxx>-q+&uA4c*U&5>`Ai1F$6-S$QnOmTx*o6a=r1Ao1aaW8O z+1W*`8si*VQ~B;-E`RIO9Q$gyG3s*``dD#e7}jWSEs9^136WfuYOe_H0)2v3n2;VT zX#$i7Y66mvRE%1J&CAa(?hni-opI8U={>lR_*O7Pp{1W&X*WR|;5;~V2Pfq^*Xv7B zPvYAF%?0bNzE0XFSWJw0JhUo#r0+DV?fc!~x6I!->K{4aZb;Mw7==sx?9180CuKd< z1d0NO7&+egS{%~y^6qGHh=c2M;$|B`IUI1AE>t=cGe1e)WQmdYYXf)u3pZbtx)9PhYludesfppK}b%hlWiM7;;ltwIUCr4s$VeD)V7Gn?t zZlo|!<=^+9n2@{vr9UW%idps4=k*|`ur{5+sejCNCKh>YfXIEd%= zZb>P3h_K9+8RS0p>@M{$s+15foG+BFcp^*UY?j3W7Z%fePPVn@d?>;lL7>b{E7USN z1D-qNB1bS&;0FDXb1UQ80p6p&EP0KLZ2yEbgl1P}=BCHH>eR4teIf__x@C1lBStfG zg^fgr7VSdmJq}Yb=v(^HEJm#De)){n+R-cZccO%Sm2xg^#7B%T+@Zs|L3dt&{q&oV zf8keJT@C8TY>-l!?-X;0$4R(lWIiQchJdR{Whw)l#oAsNE&OD5U>^mAB8#ZKwFfl4 z?zRx7M{j+AY0rf$)WaxNrZY8@rDoKG;4qAVxd5P{NL{O8(>wjFJ_k4&go3< zd#oUpy08i}i5WH+#_a@GsNHVoiTW-C{oF09De*yG*y?bPyw+;q$YSO+K;b@yX28#2?zr5ZT& zi7@Qr10>YTj`hjkkiStz4t8VKBK#=+o@JvXD(%xbIkUfojobEA3KgE`zVQD0}upFyuy#nF2(;TcU^YgCe|O4Z7W zT771ceK%fVl|8g+K9@2Ks%Q zZzPy0k{)eS#a8H#mWJ9*aUkl^Xmf#FFc(?RprL&G$!xUZ6Jn|B(gMHXRAjZ(>6DRt zZIXJ}q_ED9k~ev+@##ZJ=}+ip1W4yE{N30BLuh;B=8AXI!8{^so(^BvGK-{j=u!+2; zHcaR=%uAYx6WL;FvYUYt_KDqvekTEo=8vaZn%A9h8PVOQ5n-6poZ|o@4w~KpWOMH> z4hZRryrkamXMR!lvbAmh-__sGU62kHwh)DiwPdgxe@^_Jezdk1+!g^V@AD!-6&PF9 zDJW?tbz4HxbBzbq%%gIPiTVHNOojXj_4PkYuO;hW6Nx&Qa+{w&4l}jZXJ|;RI?<$`@ZZuK)_UJdBtCX3VI3fQw;I=5sFpL&PnA6g^!c?P zNXZ^d(Fr_cL3JN~WO>_geUJ=}`)QbQtp7XAf0rcBIvPwONZ-r#vV!9%ZkA>y~pVaj1ayPbsn5B$qhqddnMW z!-J8aiZ@S4W}BJ(Yy9lq2;x>+T{+cK>SMy5bN(;+E*j#}V>2X6+jYoCT55{2&Qv05 zDgsZi3T)ea_P(nfv2$1Vwm;-I=o`UmevFGCEstdFuqI2FJhuCEGp|Lrz>vonNbK3MX2ywI0FSILS+FrAfFZZgO;mUiOx?Ffv5dw$h zbv8st%KtHEu~}xmpDq{bW8z4mLX!2>fl@6Ma&df%y}*0%rEKNG+~KzMW99S&xd-Yz zQ<*o@0s~Fb*fFoV?qf;aSL*z_imxTNqvt|d|GDBnZ%sg#{pWm9#rLe5_faYDyIl5P zk56=cACe7*W-VM|!4q>uv{#zXCh0XiJ-Zp`TF<&*8xtQl`uWuqa!n5WGwX(GJsAz7 zuB+}!2cDKSzkF%mR_PSoz4yL>GMCq9Zs3`Gxy%?{goe(7qrgH zYBRhm{+iF2mj;ox23DRUI+D_ITV|WECUBUiFcn$`5P9X2yr zs8EMa?nOosFq%EVL2j%@R{NnQ$`l|Z7qhN4rYlo5U8w5cv$e}~jX<0gRxasz{t@HE zqH$z>Ip9@U;YZ=hTFSL4<#qS_h6zW9o{^A#NjXL|OHYsqFFoJ1MWLN!R>P)OTKRM4 zP4Iz7;(M5NA-bF68j}+*+HgC^<~(fFdUbBjDJw-#<5WsQeMcji>l-`8g5%U8LhhNG z!nwbZMiv_BUy&>Asyd3cjvf*|G@QpouacOEAP(y(r%mKMjSX0p$iVVJ4;_9*$W?H@ z2K~)_6ED`eIzc)gQSgT61xd`k0IhPwMf;*^sLEsQkJr;i8)TXh0ydB00JZ?xQcqLCp{wWN9a0%!JmlySOrEt{Dc~QcAS7%i`)EK+C~VA3LeA64r^KN%sv?xlK#l2YZuC! z$8JeF7gqt~dLF4sp$S(JMP?m^o;`L@qnzrKRP)|;ilmiAQkbZP_dqlcPA|&*)r>lH zquW0ED4fE#d0(+}H>5FIozT;!-G|Dx_Q6EtQMSIho{!ogO@-q{-})*vs5I8W+TRy4 zc^)0UVu^)hsvJtMp65W$lut4{RR0|I)CA zx}OX{r3CTrv0N*II}09&-H7FMl0JDZhVQBe3FHgOmnS?^hVWB>>OXS}8;eJ6j)LiT zj!7W&F!N6+01gTHNLRo|zAzT@l_`&d>}FZLhUosIZbSOQSfG`4v!ff$<8DZQ*e7G# zB!`v@Vv%d4)&eABL9NEgOE<%%x+YuKiQ6?|r-U@bzG^ec=0MmoyNo3ts!osrddw`89Nk7f zGeFHaR}2xjRuIJK;316;6_Dtz7+DPbT4-idi)HiUd3c=~nI5rdrkUD8i_A7>xc8Z~Irg!Y z(M1?A`yreBu8l&jUdG=PF8`bM<}{ z008_kAOM2@XO;g+@MU6PWM^bz;owj(bawogHD#*iV9NMENmI1{L$d!5Lz4e|b=|*M zgRRN8n@SKK|$ADy9k24~1gQ#7kkw6m~e(g)yA`1mahAIb)t&RH@$ zE~B|Hyi0>^p7($+rVsAId6&wQ zr8#K$JfL?8zK^T|5R%7b%>uw&?&dQwg_%7Yf^ro1wOgKskM5^d;{#93lu zUW>%Ao43-gq&q%82H^OuZbR`uirm|8fd|`83|+8t@$H()?a_V~d<%I;uS*qpEFNCBna98#q@DiCtd2SjMj&n^ z8h7GkV=p!}8QyMTz<3>=r$3eA)1CchCq+$8J|c2v!3~d?d579HDI)Ba{A%#+)U)dH z`Ls)lPhe753%Ha&VZ7Mg_TGB1tT#lqx^ZC2q{nA*bP#gY_U|1!yg9Obcsw2-EQ{F1t~tz^|FYxUfj=Rz zj-b(Kmzr2M8!(pq(%^g)9Q9-6z|w)4xb0xa(b0P!uCHC`#y1JxK75DmmoO4P?WP5W z?K}k4dz?TMV@t-`Smn=qW(fYCUO6pw{!NeZE;{!phc7)nS+^i#Yy2}|y;_aA zk#RIPHM#$kh(JX`$Co`Xnzit}Fe_>A!r9H!iGh849vBHr>(k7l zle&}oB%t*;?jSyT|3c`^dWKWT?s}~wra$EpR9r}suEWc}B@c8!Pit%|r99gdaZ?L# zTDl3i4TIOJ92Hq{)W#S#5yUX;E$_az0{_zV90$a$kFt5F7HNxD zOJlojN}PFnP)*hw@mIRp-hSh8waWWC!ZqJ>UU_Rj`eCpDC#}}jljj$v>$%@V|Ec-j zfP?1el;Sndd~pBoTiz}8-{UloG5tb8kn{HFSpu6sT@UT;Bm_WGZL ztGlU}CkNl4Q55t__ITD5I|5&LVPC7o?x>FOf|clGxs9onv|M`7v?nurm~TR2|8LXb z4WEe2WthBr-58JoqnTD(Jn)d3)6SzbINPPnxwe2@j}0(ibao`s_4VRaZ)FcUI7vw( zgN_lASK%n4vMp0;2U%mG)x=&T`Mle@ma1aim>z`Uzkp8koVx9igC6Qc6zf5(4sJ3o zvO56n=l(xG9`4e+|9Fj$kVV}|+NY)uI4vY(8zMU};=jyE&w`#N(K_7-y+drnb+jK> zL7t3!_)lgg9)fkWCL5g$GveL-@5f>DZ(A60v(`6Wsg#ofMc8AZ77xdphyJ>}ezgE7 zlb(p$k4V|cCJ5qp5V8O!?rewY4I}=9%njs9=s*%wa0!Y7o@07< zqO&Ckw7L%}ro8WkS${VWY+Rq3OjrNGn;ze8o8|A>F<~!2jmx6dAx@5`gjbjUeLsw3 z6BU$((A08`{0@w~OZO^F7lIBNo&J8!8XfQT_x|wncU2dZPRf~8RBnBJ)o;|57d>0P zem?rRT-9!$S*L%)U3_UKrzX+5Nr2)_f^spw@b2&&L(X!Q*fh9WDEDvJVCM4*elxwcev&#tS#ug`b}x#G6h&<*(&gQTc7HKssJ^(lc*nO6C-B@YO`Dp4 ze)ZiS==NedKB$Z41Vgqq8Ot7fG>q9`uuNKr^E>W0cvTc6r%sCS0vi_Bya3#0%p}1$3cKi3mdP zCE<5&?@dT4xmhB2{;PbB9RGaSm9WG6Y;w<XHijJKX{;v@*g8KL?wUu_)lEJgI78PqRht~>cd`5jRSq?*evnG7p zqUWcVMMCp7J$b*Bt%r1i%z6>Cn{~KzJcjcGhQEW2FP7HS^a#(&6kH_xAU#3C2Q@~~ zHFf`P!L}5$^SSR`#EutR+I{}^)nzWXtB;k|Avo30&_t+q3AgFmzcY8oiN!E^dgi-} zOS7wunt26wN&dJxF_p)u+L1h;@Er{_ZDK_~md%H}V!6yeA9i*e#n;j(P}`ZhI4N=< z$}6c>kyoMF&eW2}VT9><-@B8Wa`+nm5 zvaQs1PL0GJM*jbB_D<1}c2U=8%udpAcWm3Xt%_~iR>vLNwrx8d+jhnF$@_i(8E5>r zXRM1FqwZ?&dM4Jh_nM!_YhR{*i;Z7asSewXfjJ*~-RSY3_p~H}ul|E7I6~~xCwiz8 zk0(9w>^1MStPwC_dA#0>!c@gSyae&XDa|ceYfTyvavnFWqd$s6F z{nnO|{&-lEqgnlPe4>r*%N2;7kX+r_fDQu%9wVV_sJ4W>By-%8mz{|ABnoe zbOwa zXAVBoiZkv4KyR8+J7m6@1c}cD4TgVqZA-od4RyjF>=$l6H$t!tR+c0zujtH__Bemr z5b3=yRmMvdQ>8t4&z7iQmo%>WW{**1M{&B&l2fS^UHAC_SD4C_w~x}+H>dEpo*`xv zh!iZw7}3kG;2)pNX|T=pW72vUH;Y!SD7&X9Vsl*W(2CCT5O#WRDL~i8_^x#H!P{rO zA=S+AN6cxzge-)C98vYVJza7HOr(KVs|=QVtwz3{BEtvvwYKB)NxQ2xhsTRC?dfwg ztK$K?QjmGys5xJ-xny>v_$$yUkYn237fZ=})T!vC;b=g|3@4a8NP|)@&Tqp{MW85M#FN|{k32Q8Jknxv}1~m_@=={S-fp?oJ?JtWMc{@Rg%>6(@9UZQ>Qz0;3SEBt2 zY>m4b?WP7AcS$zZ!na}SqINNL!iJWuM=DZ9EM>{Ggpuz!RHw~n$$ot|E@Jz(18}+& z7w4QJ8j0zw+6dfFIy|_!q~DLGIfKy=3#ONy~0{wKQ77N z==;H<(wufEBYA%w$j!(LJI0-N8oX(VKUed=#T~NP#J?N=V0Fa1w9zXUj#4oSU;aP5^hb- z1RmYZS)cq2Rv+rYTXPxPA~Vr(*|5(pguxA2K@yJ}!n*1+v7DW4{f#qekMl%L#)S$F#~ z@`BqjmKLC$pj%e!jScShVhdxBhwj0rw(n_n79ahTSE9%{MKt0cXOq;~_3cHmVL6 z7BcpJ0`oVj2+oMbVX|!m2li#NUhuy{Zee*+|C3u?;_qdknxj4q{O&;Ay$b+e0?~_$qq?PF51;f zLsO2~l6RxbWmMtU!^Q|aL~Pk1$HrhGQQMJ2cY zow*axlpvfbtZh=Ee7=w9WsgcgSL5|CEKn!9p}l?>sd)7ZTKoscu!{=X03%}mb87#y zwbMu|^QaL8A?No$2l;*OyWv>1CS$BWJWvJOzY^!7n#KJ z>DW<4ZpF5PsIhE4+E6U5z|O}P6wQ*(@69*!mn}iI{n1jr%jO(4sI{PxQ`~6@5+pn? zO>O4XlL`BXPVx}zr1_cA;1iEqRXH_#IyX1JNLOlG1o-W~+37Im0A_9n&?$W>QUPt0 zCy!8F=&D=`gTrUe<&`Ow(%Ci;`UBhK;bI_kksP1pqbWdeiyqR4Gk4XC^O#Gnz@A!_ zqzN$-QboMhi`k1=P6paN6N?4s4eGtiFl)U7zXM-E){6-d3f~RVT?^jbJF}_HF|{6y z=xUhO=2-*=Y7t5&(ayF;QY#m}($>wWcP~q}x2p=vG_=mAL3Dd93{OkNhzYt$-YyH3 z7b%vU+ycXr?8!E+)WL7r1nUt&As6Y6ni>bf)8F9;&KN7{)zmh7+G=)?m)>eh!c!5O zF3eyXpL1U$<5|N?CvhpKTY4Mf`WFKT!on8Z+_Zk4z1^qMb3(tVI`{JaT&hk{@@ba{ zE#B=c@)>CSDTT9l{#ag!QjOp0Yp$ikKbJ1Gx+`Q*^dPy@9?&lpdIwKG?xD@I(CS{9 zX2H8T#uV!DNx#V+&R^y!0yflB_!l=N0nHL|=sS5OyRjWwOY|po*>VNus5U_jFZ%+m z8&XGt7vE({U1RRo!K9EU-Y6?CMRtbT-d$TvhdtS_cON8XyYK-iyYpk20q(tQCIj-2 zPxz0`r4PKIXctD+O)}h7V~jt8tx$R^2WyjfXx1BqQ*HE8;NsT^pKMrvA; zP&*p!v;cvm;3L%?-8IQ4B@c9co4=&Lvj~1c{0bHkFKvK;0{x%L`xQh1AS!1fTw2Dl zECHP*MBG$vwF=m|ZkDevFq_upK)&YJ-L&|&tJc)AWcw?&T68{1IwbpavS7)`7WIzM zUsVVP0yO7~#gybH^#FUL>u_5PM{|&R&{ggLYuEanw%#<@>o(qSy7nK_-i$SD+HT8w zg!m06T9@(x=f0M1-_*HW^2k{I$yx|j9k+x2R_jtb068sj4eu`2oM6(+SidP!0M-+k zmhHdXdtP;o6`t+C5&9ix1;5C^D2x*1X^5H-E3 z>BrsD)B}3e{b&_;^TV*JF813W=6SLzJ}%?I9(=gijiLIBy6Z}44|W&hMUHc_SQqcW zn`pD~q&{qtz;6iON49vLa@XxT90hp6dilJTFGlEak)3pAAvjRxqKR z0K*adFIbR|&Wi-dN$>KFk31im6ZCKal;m`#fd2{Vl0T?uAROip?ic$XsVTZUp~1pPQzZ@i-eWpU80+w3i1P!8!o^79|V6<)L#_yjK!lEa|Pc~yw%N{Ig{+t{d3I5J5@ zerJN1dX*c;S7<^N$2B`{z1V@j_nh>a#Eq^!m@RW}&_TgZGTn zzf`=6Li21pxdzb{AGA%7@B_9a3OPpq;Wmke#2tVHo7s(HCVh~t6&Hc-uOjRVRtLSR z_IhxQd9YQ*5)2S25QEYLw)p5H1HhpoXL^bLD>O6YI=zwc{!pAB`e5I?2t46bnrT}2 zTae_6Oz@1X6U_}f zZADHKnD_>VZf1CvC{-67G2c3c<*9#hpl^nWJ+PyJ8=j-;X_))a#`EEhs>% zi6C-eF42i|^)UKnG@`=^g~qp}L}3@P2CHt!yjXwcdUJQd1U$|b+s%q;(edUu>#Z3(F`S!~=F;J^uspabFT-fOnQZ1*ktU$cAopqKQ3j=1DKl6v?P2K3<4 z26^)pO*va_dR+t}f_S}Lz<=V<_dGNpE9O3e?Nae zAjwG%E*&ke_C-GGwGQ<|E?kL3G-~P)8=m##RUzEM9?9Yhpj(L=isq%UZqi#WSnaa=f(3#GoMNxCzmUpDp<7by7h>rjld~zAhoK#g=>r1YfG5p!=YqriEH5v4G_4zY}Zx+ zal+z(Qh=iP4`vE7_^bRS14Mf8@o97Gp;V^$GIAa7B*ED1x?QPuZY5u-2V0K*bMTI3 z!ogf1}^^Iq6&ufwwNgV z%_&*K7QltfA1zD8RihRE^Aa|SUq4nX$XzgOcnu9XKQB5CZuYm$F;v*pPr3sh6Buoc z<+5^PX7QT1`dIl!K_5$YDhH@~imY$)Q2t-?@EPU{{G^^$YYa1Symy)K#e2x<(cR>y zEpDOXjb!G99*&o#69=o3I!#IE$Sm!L{ek#HE}xiz&@(PMBG>QiO=VMrBoi@kWKN#AJM*^uStXgJFR5L|n^ z;t#6k>>i2#(o6*2STSr-Y59tdPI~IpS;}R`;I_%{J$j3RP{AcxK%e1ZY910_Hs7=Q z_mGNZm;w?Om40XdY|SC?+L=6Q7@6IfX8Y-##S89=6Si-nbXI3=$3ZmbKM0CD>p*K% zVMSFgfgk_>%!?P2n<%_GSz=ycRpT?aKCyKXz(@(=w*fUI10LkBwq&K}G@(2=VGFG^ zK9w4VM7Cxy;Zq9=Ej0n#f0zlP=Bons1RQ4H5FrI{Sw`Y#aV@Xx!7>Jm{XI%kZ+7+h ziMT@ZwO2ByW212CJ;uUck;?WD9f#V;A<`-W0HD}4pKw!3gy3?bWal73*qk*DIwQ28 zc*ctliJ;v^eqh8M$5^v?B#)gpLZ0apjKQ<#7UL6H1Mjn(fV``FE4Pd*O#a{`Q3(xRc{{=k>`Kd zmfcTNP=d%UOydX()P4zMYSj$Y-j+|Y_hfQe4$_=2i@QajXh9ofi3i`GRD%nB1<^X? z#JosPjdQCk3C=z7WFwgnhq<^Q0Vv4mo2!ch{)Q9J8+8Wnt!5vJ+zQ?bZuZuEj5xmd z0OfQ-;nhyS0WLzq+e(d}=5@88qyQ?LK>pZj=Kr3W*-L^|XS+83|{b@T`Z?QZJAZps&~*2FoCZF z@cSC+61WD=e@7K$T%$<(YlJaBn(UHw)DrBb@an!Li zDYmB3e+N6VaQ@`&EOET%K%bDl1bEA56f#6Kxmbw7C*FXcue(f*H+IT6&uOMl!<1(M zkjfQW4oLFKw}+|lqJe4|b6L?bq5#n?rBj$(4h8LXxS?}eb_!z9!5S@F(L~lP@mE%7 z1?*$_!AxZ}dWWPb%~n;z^;_*4S^6qsb(3;U>KUyEWqUmPY+Oq^6*{mLwruc(#b%n5 zR@ORh$t1J_{#tF=<5a3ylAB7UDpKjTanv|e(QJf(C;um4>{G2Ul(4J=io*J6g^hmx zYW3Ej)KtZ!mfRdq!p&b5QO3k^J-|CUh%VlaR*^+@$tab!W-OmHEC0@Xo9Q@|@IM%v z5%Tz1q|Az4-lRP7E;Nkq>v;5m*Xt@9b`4W#gGi^l8j|HU!UQNYXcEpU7KDn3)9b|w z{yv36XHcnPYt@DdF%9+8yYIsA7Q8#SaCo^kL*TK?;B1hsfz5b>amxi>N5K(>nu}BM zrKON4Aa0UFtso1a_9@o7IwughsIj$#_P35T3Op$82a!JD{J z;10K%0U<b_u~XtS5Q(j4}DbbI!5v`1XGYekGkyqlbLMkSNWY$AaId zr^{Dk>Q?)Gk6aJ# zvd-6U!ILCbGycWt=L3Jjw>}Cwo&^Du!?N2EbbJhzpBD^H;CqI`|Lr`#?SF=`Xv^(Y zFK92Q!n|ygHexP}coaf_OUcCo$Wj*B_ay2GpS_nJ=WP<-KU3xu)2Q8rvUpHMf53Fr zU>9=VL2h>cljGEf;_&lE&GEDT4LETP&hbh1nd)kex;9WwMBNqd>WSv4$Pp-h{;OWH z)_*0?K1o2f!bCKhd?9{{6GT|*)8*Qjk1MvJet_rlZyF|b?g3`Ri2$bXWw788a7D?oy>4#i_hE%lfnE`Ou&2~mqGe>9< zRl%PAZM6@cdgfb_om1=8kxY6v`urC&?T#)pPylg&>YwCtt|cjn;-aFW2?-287*}vt z@PeOFLb!!u3~;QCV5H*YNjO89;z8YbA?-J3Kh;Qr766a-*b;~(a<0igysAVns7xkk zc~Abbbd8}HP@7MJ_MKw&2|CcksrEW@jX4?{{ZgfoU^33LAt|G(LYqJRap)5q$q%U~ z)CuJ#6Sh1fu>7-zP;ZShKkQpU<7xfbTy!)gIia(8Yz3RS*5(pw)^kQlo)JFq*jolW5K3Zdkc zCYlDdRthts(dfDS|4DAcn$}Bqc=q^WVDM0fI)&xbBQpW(N<<(b$bA8rCpjT^&Ud5u z&9dMXb{SH`iLx}j+~StN+(BEm&mvV=e(jW%W>@fxw%>y<3=6L?*9?L8LWHxx@ttLX zIm_7Tn!v^uk}Ex7ZkFY64$~NEv}`^n%>qi~!Jr@Quo9kCv?Y5$*6W?>*>(j+C9E|4xB3bpY=gI=P_Gf~RU<0!T2 zG0}NDs8Y!&%?z8B8Yf2oZOppUAtC=JAyJ%*SYUIF^e|+*fEngjWd{itg{q`~|Lr9z zTi2afP?xi@&yqVr(*@d&_kDj`!Mw_E(YzPE9i&&c93SbJJgWogGQ%15?1vH$=ei~l zx_qTqhULJ{=|4O4Pns{EQh%N`m_e);5@-Bd$@x8CYsv1VQ0oxN(ScLrZ#jB<1b}_( z#qPr<<)S+Ivr-qR1S6G~b;B3*GJX~F=n}u;z#g7Lqg7R=C%;#2g-M4|KWe~I8k@KpCy@m^yyCu}f=?B_elsDqzYJ-+$qllM1k!eArH0k|6d^$S!0-;1->(EcH zU8?LvArEIy&52fyW6SRi66i&47~O?{Q>cMTl%aTCpG3LjFmS&Z82{smd*CWOc|Jvq znwxXZiK*;%gocAz_p!)!+wfIz(jwZdFxVtnyW!`F!xq5irfe++*NU@V5nh;@u{ zF1$UG0DpO3QG)qoI1{b3chk*>2$7uh3*qQ{5{F9vnqoa{VHk+<{|F^=&-fLu_^hfB zH~3hDQH(Wa^D}l)V1B9^cB#CQ!L}J}8AhJTz9vG{_Zo&QpPh%|V{xl4>2X;>5mbQ| ze!ssV__(~f@}Ik<_odnbouvJ9bij?_p3|Abd%EJDpy1EefQ3txca7~qTrJSfnVw+q zIU+#*@Q0(imb*AD|%Y|Njm?{$Ix(|2y*N;tu~mnQb5- z-3^uQ5_CR+1HZ2SrD0|%l|h`X#B0T8+53HX z7j-qJGQrgDwaU90Eq`7}(>nY_w&q-T@TPwR+I!CTaPBx^( zS7jMSjJ`RAmb`tZMdSsJxVfd|$Q4lzxt}QoItw$$UCPNAR~(@kSjr%1m5i$o%urQX zb5t9qQVFg(pAq;Ft&jGG1Zf-Ui>4{eGXhG1`{=w$DjI22RQFcu%Vz9fK5mZ>U^X@M zv0$t?SaCC2BV(Cg8_!$mAt-24v!-2${VR7@Mb80J9>SFQyGz8*5H|ZGtoPl|Km1T| z=HCdsd6G<7K9PgBi)yImatYQ}OjdbT23dmjgs~tqVrL*9vIv3$u1r&wG4I62GU+Iz z^^I{SbkU*?c9i3l6CHc@qe~iZ;cuJoTz8KuMY6=k!fMoEf z1$?9?p>_^8w?HJ`0?K>L0K)Bqut)fvtZFILqg30WeIYeTpYiB5K}F)0!bd$OfZ8i) zhc&w<)x%>$UCLYq^4qv$a3*aT3VxevT$YaE*=_93!bnztf=oa*XpV`|&5hCzYc>8B ztCVaz9U{KVC{~?9TG&RKqnp6loQBUS59fjXjXPW{y1+xzMLq>hgAA1u?PZUh5yHo0 zc$eKjj56d#4c`;<#s*NwG;o)kElO82LIu{L5J=&>-#83N-4SZ=n7|M zTYs$<1>1hOjHLQgDo-ULyJVc>YAe=6w6qlM;D z*5?S|?@cn9DtU1!$w%l>r<;Oe9g*4Z<8u_w<7qqw4VX{6epV5Hu0p?qY@Q|Bf7ZIL7R6XxBu3UC<1lm#2Y)lC9tJCnT?< zBV~tKg@gS|1S=lrc2!e~PkvD_1K-?k8<5$=bG!`2+@lIgfND6;*aR@0Jd-FXkN%PJ z6Jn{tFh;gk)uk%3d^MI6(7`bDEZCl==c^@=CMJD~W85aXcc{?2jfT}l7#bQ3;wa-G zWG$;a6FkZ^*EcEfxZwXKQ)-Zonq=8b6qsouaIGYjSdQe^i}icEcIcqgQlBdACSZRY z>KI&M4pnT09*hHYGmOrxg*UM4=U><>s$^?M{xMAh#}k+nNm7<2T7M`FK0u-}fVb<} z+tbze_0$PdD3=?STW%B$TwuF6%`+GAZG0v%ioUK6e#rVTxDK)G{Da4tr!x~d-3p^O zfGB2#KVk#w?Yt0k7!DHLSY$dM@!Cw3omyBCk@v(@RQtUm-FkE(i$I4}LpbhpqC1nPA7Uh-@FNtHN*RxTwQoxXZr2bM*2 zP+y4Ln=H8#D{%-PS)AACvK6u-{WvUT1c_~^@)6Vsm3cN+VR9pVc;u52B;AunjiMb+ zHJ_EN>dlspb&^+&@-uA}Pb=w{CdTFFy_E8hiE|-h@N^Wf(mdh_7zN8Tv8B~LPg9fK ziy-J1X(FViCdc09AbrU?z0l^!6l9wqmUD@6SCz%P9j33|Jn$86XZJ^|?Zk5of`g(p zD${y*Ik_s6lrKnH5SBS5>K)#m7e|sy6_+NkT9W`{AlYi$NLGI)q+2S>HrPS|D{1z5 zfMQOQOaqIF3~iw*2s4-lRAuacb;Ly*DDfpQs=%B>pYz zX??y*Pw5b*tm6GyiUW2(MvgLskDSw`!91j?AxYubKof)wO{!pTcne0pKkom zyLR3&I~2ncCfEC^3a#*nK29ogl#h~z>L&Y=tNyeUbI~fh=FmmYW0pLs&&wu3wc4;j&!>CFrQCk}!Ah8@3-&Q8Rz zEed)huM0K}Du({V8%XyM6^g3BSOR$V*itdx=EWKcZ95PX3JaTEkS2w2l*z9&A_inL zAggd&nr7VB-xV6XPwU+@RMl5CssUnd{B66ytO9)iHo<4H^I9M%E2JJ#vK9 zM}I-AYc{BG@VT>arOPtGm1^i5h{}&1Y5v(vrC+PsWe#=t$ zBvlp%Cp_b0tz~fWYtPct2?RL1FiM))x3#y-(OwZ1-_ECd{PDxcRvd))#9->4rfK8h zX7D$DqP7L2$s_RR0?OeE=ZuaPMFcpftc?<&qK~0Em7k&JuOv+25@a{%ZIO)KB96TQ z$!ofLzFuC|-~FbJa=5e=>|E&k0j$u84USrw`NT28mx03Ducp%+#=IiwE0f~kg`2TI z1(lJ1dypkZAXhxnf%XdC1&xRxLD@B{AV)4cJ&z+8B%zacMMf*BAiM=1zZ{Oj}xf=6ITMW?cb@K1QxKgDAl0ZbN8$3$LgSzNbi zOy`Y`!v5Kzj`WJF^{3cH-k zZe0oO^ldjdcIy4DC2hfNIHYOnf{id0wOz0HlGalz05HJL7J3(93`fi2!E zLb-%sVdtrwoe1BjMKgVr-svIWqoM7``TFDq5LnJyktEqIWg0owy?QKkR+K%ndf4Xj z`EY&+qDYLm;vLuTU!`({w5FXc&8{m`lrJ!P9|7z&#SYu~`*# z)VFR~5n6wL@Sdh!#&VbTG5K^cHfE^@+z)2#LXBhx!yXvuLEGxAYC-#f-)IVE9Ns7F zD}lP6iLSv}$Prbc^2!xY=^Z{EZrKP2Tlc0sWoz2QB4Xe}#E>~I#f>(Nfp2AyYP7aN z)D4OfVgCyiZK)OIQp*%+LH}HcQxCjZq3W8d6hoi8RcEDMH$UEe^ z6sNzB8Qx@S-;I^AD;uhZh2I(C2M2p$R(FK8e-hpl0pruyP<@Q|5LDjuc^1JsxLzRkkz-8EhP#`rvp7 z!volM`R3r2^Ka2XboIV?as8E6k)T2_n{LN|)!NebT(gQ8p#}m#}R;qrO zfvZB`ZK#i=3^XZ}AVSs@AvDxj@#s2&?dL0_u_cJx0t14G|fw<6OLj{O_%aoe9n>EZtyqS+A2Fr(0Kx z<8yU3E{~2nI8BuS%rBD7%TYHSUJI*pzs(%6BJJTw)qJPMrQ-VJx5JT{S4P3kp)ZOx z^Q94t;AIRB26J(pLLzS-Cq=uI9MEyx+c3afCF0B-YIW@xex0|dq;2*TMT>WL;(Aq? z1?02_MRtY8>huFRgLq(4pPaWe?-6O13_FUGyEbN67s5JXbiY6Wg;uKMJwGFP^)-1i z(r8mLV`ZFy` zMru^Zb>wb|nx>#ky;dwMz#JWJWf`U~3qC7DJ~~_+0h5Jg^xL?(I;E5}g91@?s|R(k zR}_&ceJ`%6K#X|#aI>0?rn2(y}=T6ivArCY@ZS)lYbf*?!?Hi})pqr(Gc{j{xJ zk>5r=`_R{_Vu?GomZYN^KaR$EsfHgLx0VOIRed9o%F75Zd_nE8ebM8=A%D?VB3j#b zE>I_6NAtdxxFv1`{wOl-mmW=pbsT@Ua70PG_`B9veq}z^<$}sE6IeEAdx8(V7n zJ1!1-QH5?sxp40ttCO1#4=pbjL*!Pz4tE!}zP^gi{5d)py2h*1h;d7=EgR`-MvL0NsvWp79ZKjJB884?avNBKn`tmx-Qa#Q@ zsc0n>1MDafS06h|K3HzV@=6(W0DF`b&IdxJFs4=cPu2LRRM^Z$J;eYf)#Cl|d}I-q z5s-j1lOF*;;f7?TVmZ3k%Hz%I2suPQKKs#||#p)3R#gt-5m@v@!L(aR3zLgDZWGtZxfA9`80d($1Ohc1uN#togZ z=;Tu9MAPV~795=$+G<-hkSw21!|=+xs)w4Y$w1a=D-IrcFGY=B(Uj*|N0W@d5`Niw z%Ude?Ipo`75~F>j(>CooO+)1?C8uXBMm$;9;A3FKo>p=a{@P=%IJY2H(JEdQvW73_ z6eTYb$m?588gnyXNNh(?l5|#^i~N3NK)K9bw6$;$m(fuXSGakoP#DTh+KK9b?UESV z*K+-R(#9rm9(obSi9c9MwmWDyWRcTzqyRPo!Oqk;;V!lYsno%7GVcV8ZPTIx@lH)u zhePiBlBS^v1eQc<$Wuv_SO)S%16W-qVBasA=l#(NGMa)(4{L zezuN3e$ujGLj-?y3Gx?RTRFiu0D1|%toAbWmjL4cCD}Kf^`L~K&e$+$Ns4J(z zuv|WND0MD2n+$+^1RC^+QjxW6jv0vT9j2Q4h6l;b)rB*%z&x2?Rf=lTuc_5yj{@b8 zzNLAS$;VCdhIn6ZcH-#x7t7@owho}}Kpm=Eo%QixtC#A05x{NKrKti)XY@Tqv0AL- zHICvDw#?dt`$4QickKa6ydYufiQ4h{%37ymJ;disZJK3mq1t9_#A0)2l}ms9NaFF- z-K>39{0(~&m|z$0y>u;bM_Yo*RkyUVss~~S-J)VguaE!JgBr&NlQ2$G+idx7?_XOk zyLpqG=ygP_tj2A$Si$N~M4e?ROS@K+Dq*Vr1dA%FvgG3$Y@6|h308I9N!hPq4K zNR9By?;7bLm9{u6hcuJ*BbOOqTvbtP5@~2ILUt1fa~6>RXG_5E94U0@7Yu83{?8CK zjY`u-oq3HNZ4c!4X8D@32qZ47rgbRX-16aH)b9Xr=opWMK;BD+0p-Y(lk&PI*W-5G zG4g{e3|fjp8xoQL$!Fdi-E*3X0hG=u^IH}Rb#&8kO64&XpHkLcBMaSoA2cXI9;sVn z?-Q~BO>w?V$sFa=3H*&11x`eXS_rGZl^zs=E-|Y!B^q3r)Q4aza}V#14z6B(%Mw!0 ztB&Z;&Tg(Nu>e^t2f#eY2xe#7aYq=%YH(xpAeyU37%{Oap0CBQ>tJ(iED25{JI*#} z)L%)rpadI}e(GWHAElM7--B+$&-`O2(`}v_@Y~kq3w!0enVkrxC7wc{5z9PKh*k!l zKvVCC-x!M(|E5XJI+U7Q=!vmwnyy-isEun$Ok!xT#JpttA6|UMKAxvV!QHs`ajj)6 zp&Gn0da_5DC0s(C{Z2Iv)2DqCMAnTJvv?3Y?I#hFaV*)O!hu9&o5oPzR`ab_t2gaDX6SuFh*Jz< zVXUDUhhafxRoH@llb(jT%Ez0d<23Oy{}v;gVnzo?m1|$?$g_x!Ey8+sX^q%m_RpVP zHE8D8$?oPduUUnIwoG`wsekpxbm;n2)3F36&>-fWCLM!vu)W}jX%YibOlG|-84HEsh8?suKY7&f6#BEVUxLj8B4fLCwLCae-Q1exlWCaZwq*R4 zSMSAxK;m@v`i!}Y)?i&u$a{N1O&9!;TftAU{eIICZ(R(-m5P310Ew-WYMO!8i`59R%aWw~ixVXsZZnR!;?kz5;f&-L83vBs&(i~^t4(nV2En}a6A@x1drv)e|HvAu4)-C+dBj?Vz#ydC68Z8f3C(FgIB z->JmY=T07!2hvTg3aI0!Z1i4Mz21!mmiV%bXbWY18ILGeR1kw|i9`}Wha4>?$-yJ~ z?Wut!^qEFB-n-nSP56O2#SRiQLx<>YgC_J zOyb$%do9SgzCCHRYY~0HM@aHjSOf?CQ%E*zPPypSad+nSO;zT`ldm%gzSxu~( z3luTdC8Cy#ZT1(3_-siurTjfs&u^6?wj#v%aA586Fsm_FG#Kx@pO<*^MswUddY8>3 z=np!S-fqfok$%%uUj@X5H~SYMQcocz`RNNyA_x}5*^Uj4V$X;qm&7}dbAQk4BO;h; z+{f~$joyPEHO)g#lZp~4Ts+vh5OJ5L1(s&oe8E+Q5BL0+13qAPkLw30%MU>Y9cF{u zN+9A_y*5t%=ZFmkb1$361+j|#0xoC8P};>wKJ;OoSE;J>*vH~ z$@+4QZI5@>cDLWxX-lyz?T#{HtNotK%QonHOH7aN`~CXJOQ_vdPj|uBKZC@R{kwr? z*3QO9t3!yxmvy)A@7o4Gg{=0Nksc?OJKS<870we@AyWc?tbl`<&J1ZEludVnvoA-niq#x%;zFBHF{?l*2W{-@zv%K3fdfuG*Yd*(Q2qPL) z|BekoNs$yFF1U$dk>@3&`p7>esFNQdkHa&f-buNqrYqtsqRi4Dw!OuWXkrHM$H9v; zdQpRuA`&R<{bG9T*pu?)?TF{m&8;q+Czs_o&Vwy+OSkv@{xD15 zxd|+W9gri$msExmLn8RaTb^=i(Itb3`a$uvbTT!s74z!FO$8Pj!7d)$qM9V2m{C&} ziI6I8>6Cwbysp;M{bJem;rz6Iv1!$3E#H*&BK(VlFXYPm-^Aa4=zP1vD1<@7tGiIe z(1AAU`7b`w<8kvjE6BnBaF%{zXVQ7cQp6)W9yXhszFgdblQ0!VbI$Pa3)V{CD3jmk z`@t}AD6GaJzODvU@nZQZx2qzH(@u-TtXZLp^WzSj1#c&k49J?}D^D}5;P&A3~i*ne#nMSmJ@858UQ65ZRI%Hx?52N92ZMI5*jhCV(mUm2XF|w#z z{JVUJ`F-{~#*3Hi9sCdP)>$i@m($9~Iu0064@KNvCN?OA{ zM*80^C!SjLv}KfhTjMq?-;UY**7Iwpd`9B4Y*53jV5Sv#7IvYm6Eh?yA9%i2*I?p)2w!y0vj0Wv(tRz})hAOhN(}b4Cgb9r!HedAQNX zj|~y<4(zEE=Ng6TS(`dzAz2Fx@GnTPlhYQBjlK={{ z-JcVR=p1oW8B^L*joc^h{r*0~Um-h)F}GvhG*b+RRHd92%M}d1=)_(D_!9u&!I@zb z*|SSWa!d+?;`siVV%vO4RZ*9Wr!7Z%0j-LKALP{Yd7F$Vjv&^b%{i_noVqU4=*FA0 znx5krAQirtO8YWT15Og)W6Qy(N7VcDHBIM!fNj{w!9%y0KU*cbg9+2FLqE9Hs`aIj zf;a9VB<|+y<+M1{x(Qwe#{Q)pG6i^n+iGe&Ugl~U9DT<7mMb%W1F8c?IajF;d@bjz zCi65hXC@r`gP%}egNvPiQ4~&8tkoP)F9IuT1tl=y$fL(3-H3D4J?g0a>nk3it>R8- zRCO)k?WYEJ$i57D77T5Oce$y*>pFB0LLy&|2;7 zPyaP5>xaaFB|Ro3hD^jD0wI`?S95ki8EdC0@{+>6tZqNPP44-mUSx?<9*%p{F;`5x z4i6RXCJ(b5;OTPiN{*vm#>_C{?(i;MZ|;G)@5_7F2+POF!%Z$M)my{5dHNrN-^0uL z{ET$Z@SL;dN|7E#Vhkx517hMp1)=9S6`sE5#>)B|LR}4hTb;2T#=8QRG!c%(yi)+w zl7k&j+&yUUjHJa|>Wq4hJJsp)f#cR@RE}!=kj0JF zH=b@=6vVRxDf}Cd$lIK?G4!8 z7#teujz_Nfuig@1hrHs7|I6Cn9vPc=MJ@3%wssuze1mbtPN9D%-{{8iP5DUU_ujZ6 ze>@+o-J;don$?0>g6Nj!{82aJ<+I>S)YBEg z`e7Q$A)Y^xcnF&UnPy}AIiqLk=Cy#s0WjVspXvRJ1Abr(y;gCE2@5%{;08fEDrQre)hr1Z`Cpu67jUaH(?5sgqNaZY z<1}5-io4Ck128>Dy54AA*&+v6#w#hZNR#=qid9obx(^FQ(F!TokHpAXnrhmWxC~V& zPx3@&JJl1xi^&sm>{fd)fRQ=AN1(Ew(fINRwOD5rBG;2_e%dLD1#@q5QjDH=om*|Y z^!T4{cgIhnuUW_ga+p=)EzNUYJzh?CsN6c7zHelDpWW(5U!CD8tFkYV?EL5zlQ}nJ z6<_-wq2!FbEGNTg8aRvoa?SQF_{M@eN4mys%*ze$1a4I%jcFiba6O~_MAG%C9X|X~ zxPHk)swmuThun-t&zW&@)|h2>9c5P>u&0mbVT=M0(C%=W?oDITL=u=2QL6!OhwMPA zr$U1En>QrX*m}uS0)u1oQR8+0VT)-<_I%#p5y-OGv>fO^*c_^{Trz0?-pkP2`u^2UO%VeB&@OFjqN(H(N`Yqy?yBJkw{CF16g#pw#zt4yq?h46%B5UlmkEl|%+q z#lZ;(!w)o^ga1m2mZfEem?nOiiB&$9)M;^si1@YO(z!)U5}6&}4D(uCb-RJuAN-PB zRC)8<6w{6))Z96ce?xUiny01(*j%a1#{TaS*jk87^r<%{a@Xj7DkN-Dnav1`qRGpc z#_?PywP8`{S#_UNbKBE%P^Cyhd74QLbJc=-(A6x?gVWMG9IisQkN^6?QpARV#19+z za7{$QW9~IZnX}*NlEIdtDx~hA*Wq0Sx}056A3JIOQMF!OUQ$Pwk#}lUw6{hVrN+sq z6+_qHQ9Je)9~sKYxgwJ;f()`bnmDK*$z6{04!UEpwo}kJc{}a)%=UyWH9RpkbH5sl;cs~(TYE>x)3-lM%w4A=ub$|<-qCB;V)bG4T8;F1Q4)4ZcSp@hX+}id z7dx+wnY@}jG?x^ImR5@u$Ti7gv|3@>JA@HWR)Aw7LSP0-j~>87hbfkn8%0wW9qOvWhEz5I3sm<>?J z0sw^+<>`Zg3ov(K(s^i7{Q;_joiJe+!oNZR2NQE>hSCH)cqp>fhFtCis@NbLgg;~E zYM9FQbddDAoH-zCJEq79P~dfl@{%K1vvlaASO7@)x6c1Seqh=Gi$dhX;9(F%;=MB-D5k;0JN zOO3Y`bU=8LbK$bHvrY6*X<1SQJZYP-xp(i3Uc8O@bbxB?mW?nufC~Zjb5*P8>J%9g zy|1?Gnwdm5SVTf@wM(0W3%_QIkf=QxJvE{v2|Yn3mj!;hiS^IGa4`lPF_Bsaa_e5K zt3pc%&6!5Pr$<{yk?vnUW|A4YBAA>fvqq~E#O@UueE|DeX4CJ&ymK~&#^0`$O9>)I z4Nwqs013lyx;a`i#+!nZp4?Eyh6RGFQKlo2M$`T2M-5+g^NC3-t(?zH9=ShE+KUyY zD6Ip=szTV$=_t!`8XZuJ;1~SmsXs@)WpzwAek0&9|R#4Xov_WY@iLo5|Bg0$lY)ni4x70`p@S`>#KhkwxEV-v`a8x zjG2WG2pGh5T>;ZQOeCYVX@nM_b0>d{$A|zNNI^2-pTkl1PrGen7Yh7{>b8cnuz1$I z2n;e9CV^QjuXICTNo#{x*_D=98pG}|ed1VF^I*d5(4Uj!>a5tq%6D2RWbI`}HFNc~ zHwgt&t26L{1dlwd;;i02EX~sCp@%Z#%k*Fd!2{e?Efz)c$3T&Og;LwU%IketH_c_O~Ho z-zby;C__--YuW2$!9Vx?reh~aME8^^O#LTY&rfa-0RhwY7dSYViTcrhs@Z}U>M{y# z5ky6%0}<{*zX>if)SA@?A5{H-MY6M3C$CKljLBJ2QFCzz5ijWS2^|0vGpu35QD@&e2*knYAMTAi> zKV(X`C<&qEzJ9R9A?v=HazyH{e+UAn>esUVwnt3ojGvX1h>wRA!DTRSx$uhu#$b=NK&eJVv7V@wL>bAQ0 z7@1EJC!f}1M2>)l&C^#sEUY82qc|m{IzDZKebgd*A17a5}$2EokS-M`T*8$Se`)LI!uu%m= zg|7}R9O|TSNhEYzuWY}y)E@V{d=Z*&AkpfpNW+X_suEt5$dXHqaBmJf6 zB5!_aw*g!V8J~N6pb}T?&ibhBT4|68*i+#onbKSZ0+8_CEr7ld3jhK_PS9Dr93Y5S z@Ksmz7x8E(BtHJ+wEw~t&7me}2mw@6@kzpn&ARh(UoqN` zMjy(9=?CEqc!(*Yk4_%e7o`fhlnI-UNxVchhf-b^Jw@?cxOuyY?1vDgq#(Ks83`AA z8E^)LYe|&kXQWx%1r-p_$iW#E+QYjG7Qn{tZ9yCcetXz4Ms?T4``>TlPY4eIPR1Qu zehDmQkeCy|p3r`Hnih;G~-WjwB#Jhyy?{2be&@M4lBn zFF_5cpaDQ2b8J9pC(NLtfCB`|9|Q;h3XPCICC~%}M6UVK%nURI^9j=83q=~T=imRS zri${9rTc&Cpf>ZSl~(`)0GI;<0LcBfbYO@7p@Zu7PX|@l-qyj@#Z=DT#MD{B)X+uE z*2B%g%=CZCqyBd+;gBTxxGe&Nk-HC+ZKp<4?$+#gwU@kBrJ@zJi4`n^Y|%jhK<$~f zJC4`Z2fLP@f;Ycu2A*&>2n$lT$@21Q$eVD!`9i}7Gtd?8m>X2Dom1Q13&y};h?!7E zQ?Yv}8J-+GKGy2wlisODo`KG7Qqz_yj|`S&KCoXiCqKD;hyUc*zXo zocr!|@|5afITuky0P=N#I9Te&?%61(KL6l*XMh;9ZP=aGSH>1>kX^8> zx=hA7izkDJy^WdNl`bpet(K7erTi^=C$9c$>zMWNdFbCWgeDGmMT_F=57)KNFp zYKN**=(d9W7}#f>Z_7D8z-5M8{K#7Vk~KvNrNc{U)G}jo#lL=-^&~H|$QfPIlb#|Q zZo98D-oCd`7~Ddiz`VZ6C8NLkoA&=zI2Ydx^XfkUWBLy;vj4vUg98JbXShnmq|pwv4ikvcQsL ztxOxxG>I%*C!Rg@kt!6Cnfoecnn7Je6YiLz*O4?8(4Z03caJ_x8w_V< zYf&J5td^%32UhFtzq%8si^1&kTC1;=#I%*etkp~PQ8)vkadnvdmfD$6x4&-l(j|O0 zx9!@T?0E2P8th|1^7}Ou;HmuUN2u&5YK^C$8sl#J(Z|I8unODXS5#)tbms9}@E7R6 z;-waH^EKw5db7+h0D$6uijA90LgJMF_8#tRK)3$0%q;~pqJ zqBfEAd==0&O$VF7E1iX~cgA$VzDM=OVONf3ouf8BGJ6d8QZduhkHT`CP+#G>zIi(H zwL)K&^-|a8M|{AK=y>5Qpx*i!Y9mA$PCFCq0Dkv^U}MQtE)2@8Ft!PGyR+h|f4Tqh zp(^6?u z#z*5WuKu=JPk#*dZl`MWBjMbOCQc4RVf)-y*GR+Zlq*ubk!MJQd+tg!$4wVW zOWl;Y%ccX1e4B_sV~{n)Q`_lIlm=xz7b+{UB%=ucoB8T#xm0!J$!ok$TsJRF5n;bH zDHRziE&AKbME?lG|Hzgf_OS|(x8O1UxtMQK7QyD)Op?`n%}5umEwyxI#gw*hB^gXF zYdfVUXqa8dQzS>#I^c^X33%FuHS=99<_&=*;kT7`3@fyxYGC*Dy18geJO8X3Pl?HK zHj6S4`Jp>dIV`WNg@g*Bk7cDo_Kt>8?g@%zq|q8Y{)d4*f&#zBzk|PIuH8>MnGX3f zk(xgLsg+(W9v?aCT_OEt2aWyt{2hO>OZV`<;`!dfFVtOc@irtBJO_tH%>@LbRg-WH8+hrH^_aiRlNSewKRrdHz z51E=(3V|nz7&B~ll+K(!wa_&F;Zc1^M`E`TATsqk5Sjh@%kN0;PPsRV2meePl?*qv z2Ge>Q3PQ(x$vDd?iJ?+VP4d9lhWzdHp_bmM$;>u$`-m z9jI!yn0}Iu=KG?Kt9CMxn+Bme5{a1!UZGP8R$j@Jbn`AnCzzChn}iOHnwb6^L5&g_ zHqCrN;8re%x32Wub$04}Wft;sOH92ihPyBkW&t||&iwT;=KK9Qc%a;(lP#_d{AR5(nZv??eNk#Z|37U!j#*E*l{ z1}zo7gcTG(+3_o`X3lTb@gb+OTVDvaB6v8fp1RsNF_)j;4m?4Qm;#&V$OsL2hk#+E zf5X2f5Nbc4Icob$vvN2k@#@C6^Q5raZ~-dV3BDJ^;1A?8-XcFLo1I7An-U=LjMp0d zwVW1X)5Ilc4C{oFMT^LJsg?{06n7j;Em;1EoLMEph#}!p{8m0n=%{Nq7RI2cA8V*b zjQUccv4||K0zsycSiew9(%vwnTPoI-FFgIR={DdM{-;|^mX#$ws*xkpy3Br|(3l;A zZqrDNH{Vc`u?Px}%|X=}2eP9Q6BZL50W56Dz!|F>?vVkuHU~^T9nH7c@%Nf=)|mXSooeU0CCQ z($^GG&j~-TQM~ctH-(>tq;Z8%r~pSYhBZqcmr2yZuO&+#gX`kRUbLW76S{&;t-N{V zaDd`MW#D2J0Uya1#63hp^16r1o;h^v@nCt2sJi$Q!puJFd=gQnrkx{n*qoYC*elMW z+aTEkC9NB9k^8K+4)*-TY$Mhf>)*%Z2|SUV?}tI4xLx(fwm0Z`3l zY0Q0!!HpYmVXN-cLK5g`1ZOANnsSd@(8wK)$END&1~4EhJWzcQS=UN|L9Botyqk^6 zTM(od>@t-z{cedddATc)GurK*;d8-2o_Aej4Q8WHqF0gk?<)=N=f}|!wl&fjt3=CX z@B&s&JrYXMw(>{kjA%Y?A(;lqrW0z(>4j-DL$vYh!44L$MA=Q^Au7)jau4nNLeTIU zq)Yln%qK;}kyeS8x#>Iu?!~U|@oof^+{0m1$K+1)5qNp8xWFaXUgel1$a8IG>^h~= z#w9uF zs}mig{6>P)vb&03>6GnmUrAj$KF++8`ntt8WE0{Yg%uC_7V}R-cxJvboJQ4Zm-yn_ zX3OsT6NU4tl97+YZK2`x>5Q8)x*DM_=|ey|(@{*X$D?y>x=daG=P4x@IOM(0do#r! z07feTgd~_EQcNv*YqxeEC(JTd?P(>N6}-F3Pzfe#p!S5EM7rLm;I~fLSdDi z)S~EAeK>zI9vlG_s$vVl?`QPH3#7=>^COv;diPp9`Qbu3xIZe3)Z)t0@I6nHUK`~` z+%&6(FTR4FnyMi$N5wgYc%d83KFkX~DD_m{SLzA`Cx|Wc1#{pZ%`6=Z8~FPxFBSS+ z&8y0Pi{=e#WP_+0|5C8DFO&+d40?UBln=XU*Z(*Xyp81x%N=!0`(svKsiE_?RdY3c z`G-NG05#o6PxoQ{OuQ^_j)b_WSV-%g*Nh6aJorvP>sr&OU=OEt&tu1gSP{Q4p=$x2 zXmMPEj74cxSI}uX)*$%wMvd?&mnTE>d8#(}1V{AnkS<-;uNT`_u72?U*Sgr`_H^4A z6#xL`6#zi|e@|Wf-<`N`bS2%3+f#SX>I{~0cA&Rq7(LINIIm3erfJ%iE=27)gdno$ zfDRc&HeasthIt?mfQTU6N4d{bv5KqyJ={J>O6Q;m=VXmGYjC!6u+PMgz~6D!gwgt- zuRr?)e_^k2byrW|y-|RWgZDp!2-a^A-`O07@cH?E{b+4cUj9j2kZ4V6p|VN}6Dg>1 zJGLa6Xl|u*Th<(CSsE4-023-F=bJ=knpPgpvY6_)w{2jZnt`f-qPq>?=|V@6*qewh zw`%|WIsN+mZvSv1$Gf`|(RATO22~&Xd-Y&YuvG-=i2Dul`AQh=?RbUwqYtX20I>)6 z{;MZIvHk}EbR0#1pq&EZq3_VWm72$QkYpUc{dTEL`x_jD(ChWP&H4cTm}rm879>HD zr%j=0%9NUZad55|T~(S?esK+auEDTo;#yM+q`elM%w?)XD$cnVNiYI9S*Upj z;R7w8d@})xROTEHKuRM=YF&l!c%Gk*HeIV;b7XHMX~a;+gji4<5B8=b0CC zGFvML%nNqOsO?RK$i1#03nd^-jcOTBSC9vtNQWa~4jRaitk|vrM~Ud4gcn-@qVySl zx)4IwwJ>jPxMPZq z5|j^N$P-79Ig}5lygP@FN%L zzlnu_eKZtm-ce?uFhWO!2jgciZ+|H{%0+c+;OZ~DS0lo5Mis2VBfT~phi4z&S5DiJ z&d-<}AiLXr!zr^y#B$3clgdTXgaw^V@E!5rXdC<+MrNPvR!bo+9rZkT_!2TN(z_3` z*JM<&@Dx8Wzq{vc;Bw%lVKw^wL^1g#z{fZ?kq*-3h6LCv)XieVEDIhzL5ncNj8OGG zX@8$cN>>>i8;J$$LY1|^Wd2aS<4}^v_jLZjgxny=i*eAmYAjv0R)%9Zhcos>`Suh) zW=pZJzgt8owF5Ig3u)8*qSjWvqXpGhw1l=|aE~wOS!sx+2!@oG+SpSi^(&=ge+5tR zx(_!6A#}n6U-JtN;Pr2Oo6)y15D<8zJw9EieP+*}Cu1^t=!m4lKQA*@gq{mVSK|$u z&1_N$jV22~-gG!0YivH6 zYN1OrkK_nEWI0>czf=b01VN6M$<$trddcl*1$Nbh?J^4mJW66~0<;#yf_z+3JZ4|^ z>TtVnk2&`+JD1a=T_?S$0LP1}&B?061#8do8vWRSy<9v<(!V}QpN5Cy8=X|^)w!R` zTRmw!H*0_m3R^M-RkmjeOhTugL2DMTcNPi{fTdMri(si854I=CD0dVYZHC}mCCQ?}D(;-MItC9GhgCg9 zt?VQytDp@>ca?N*CdR>!tW+dlI8V>biIM|p3IW+*O{6z2C5~SxiYk}3Zqy}HzgO6e zONs{|2UQei7>)fIL$uVGbGZh6^kR8s)6(qpd(L|~AC zv^X^TH-Nq5aI&+?GEAFDV+kxP&8p^!iUC^C*7h6QMoju*Y7CunqlQFl+=I-Tk43Z| z*g{cNYL&4mr&Yu5`PavMXH2#8g8GBhds`|i?2#Q6`aJ+n!$O1=lz?Nm3HFchGcGve zL@pZw2wwBVJ_HyVu~2RN?J8n`^&yzi!lC2yTRZfa3Ac`eY8GkRn`js%_FkgC>6f{V5581~eO_s+f9qhNS zw#la9g!!y$lIn?9_GW;tq{kcA-4PI zCCNnPMwvu@f#+#Pexn%f0?%?bP75s=JG{$E&Kf2Xkqwr@X@D@fX89yVEl0Wr1xy2U z=pbBNeoZ+`4hmXl3FGR6{Fj#O>Av4)Y)T2Os!$p%fuR>t9ar$xN((Khb*z33;FfV! z|B@Z_B)2xBiYKyN7Lse53iq|e;qv1y)H`lPrtJ=8vsRaO+qb9p;C656#q;EL=O9Xb zrS0t}=iBCVO8Vjtwny)?3`1`NW-$VE46r7$NFO85unM9w0y-8=o{||2tkA(+!dWwB zI&SgoAu}3cX&UJuK;PV5vutdCIq$J#SbSO!QGRB?Vsmd7oZS9Q3hUC=77|Ic1ue;$B@|E$-3X@m zfR4m|IS_8s7-pyZ@U0s$)V9#Z#rzJY6g2KV?_frBx}5&R@69>Gf*$+qQ6cK#+)uJIh-Q(K6=$%>?lN0>-xe=Y+MAuU zy{uufJPmR1r1deHDBt$4o3S(cK6FTZ;f4&($;wwIBoDQB%f>0|91KTB~B*E8}8$ef~dt)l<(RaC0z; zA}5|?QCIzQ!th>ja<>Nsk7RtoR0BAP8S1X|mPpwc#b04_^6YW$DM)~U32~QY==r>@ zi0bR-JVk^yWO%n%_T-1Wp8r;U$CQtBjL;zM!{LdQb9|D(!lYqCvEIiXpC8b>v4qX7 z4rI^;CoWx<**1c*e|%UgN9kByV_)S4s>vSQ-|!boMhavU-(rT=4{PnZ0lQ)xtunNLo3F_u1hkA znqxSS4bq91-S_)QRmB*Mmye=Y;ph{=KZ|oBl9xFnwtwCcb>sK&=+F4(@h-D=UD18W zx@5U9=rwL0)z9U-)30ziW^6xV=Qw`=4cqv!!daUXT~Z_P#Hlh~PGK4rFVEu5t?5HU zbaa2L;r^%#G)vdlfUeO{ifW^9TT%$bXwazzQSKP1AM9e-P~nP&p*N4&a-$zNRr0)X z*LHt*??U4d@x01Ggi0^))?}V$w@%%@{)8d;Q(^)`{*etV3yNdiiVA$cKgT#I7=L^N z)4i40H&U)MJ<(CwC>6UL46H#~12(Evl46J>9eKJyI^{XC;m>&`eL6lADnr_$X;9Yr zZXQ?~8K|P&hKETvgGwHMjuqO%q??NSeSIiyoaVSm!_IgpHtA&I(N<6ao})L)%;ROP zgl5zQcvLjVvRLojo(%=uU)gtQE^Jsy~PCvU*5beaiF zq4M5{+%Aij#8 zdMz_qZ&AH~eu92J!#s~|=@#nZ&b5%G#0Cy0qLjxut!}CILcy94NBT2$8~b=UDR?HjkvTD}S4w6xybA?8n?tK^;qunyaaqlL-TV28acq-XXB~T$ zd-6wdN-TESBo)^ZCpE9Tl#0dLEhdHpTTPC7?&EgqYm`XjN58X`^qy)_D-uEcT3#Bi$EP}P6>WA;gW9>gO=i7>VR0cphGtA8LaE+N(Ve6m>jAc>yRtk*l z_UR-`B$>Yp%va$i$&D;G1wJ7R^pzE9B1nqX!^J$}Ac(<0o&W`(p6 z%oTf$zGBlNS>VhCyTpD>{~0aFMPWH1~Hy6VgO{pL9a z9z3>lWaqQP9>))a5L!liBHSIf2k?Z0GiQvb(I7J$f~=S+#E%48k+Wl?N8-s|38n_% zF&dHyck+^(E#fYhJ(rEiB)>&vRF||wm}shyw4=4$xRC?dl15pG)~at}G(xuMr%xC$ zBA=k7M>zfaK1~F(LK<*p#nSlOawnID1F1z1w0qz|ff2LO`4LrY*6iAtB2q{S*PyPZ8*kPd{v0j7@n#FKn z-7G;w$$phg`b7NCTttQo_&-qiO@o+&{yXz2PJiR!z_lxEawC;r_@qe-Ka%wsaCHcG zOk>gRV*eJ@tUI$w>s9l2W8-_ZG8Wx44>@db!rn_l-6Yg`Fr+MOO@vc@V9%aX?0 zsHx<>>=>$;L0q<1#CkD28rMjW)Y(>!xb5kHYdnDenf!a*bDOWdF^LWr{W%=XpJV+T z>ipR}okjRDD6-!laD1XdsD!=?Gl!zsHS0_nH#xGghveK{lY;}k%=-C?FGxe7|jI?9FphEEi&%CG2vYcJ3E) zoGoL*F)NxuSAR>j95u|)Wm!;=st05#;wmk{CJhr({Gk4QDgMvaQ(I+-4>b?(St6^R}HZ zeLe1hiFwM)nYjH#Yui+N#kOs^iAJA!6#6^eOLl6@&c}YT+UHWbwSH%CJ?Dq@R?wvP%1%IQq6C`R6yGJl)PUTw#~A9Q z{S1pW+1M)4``=uwNG;}F(iOUjniI$m(+-yQ);|0;g7Ow5GCy{pJ@aTSF}NMlwRPuT zN}hK7w{iAQxiC%7gAFD{7Y{-2V_@^~*I=uX!JVVhYy^gnuVRW4Z{Yr6r5L60fkiL# zTc1u;;85KV9N?X9h(>J7W3?r`Z1eH3dt&z3l#w$7$Ikc_jM5Tu5U->=o}={{#w@4O zx+ZFiuMn-S;9mOZ<2}-4L@~If0IQPc9Yk!%P)l@lYG($HK-=KjAcT{Mf%sj)EFdD= z0ipExZcBveRavs{t;Wqa)SgtJ)X zuW@+>Qz_Z>^8n?X*T#Qo%L&{--n6~Xi3Ok$5c5fJM^D}zL-QiIv|6;KR? z=_7DYe;61O6>5M7?SX+Lea&O(<`8q@EQQ2$07Pc%R?(KG%Zf~LW;>cBwl^Bo_@q+R zyisLAiBB%&(8*-FqUJ`ZM5R4n^H#}vhMQCGL0GW3BtR;|RC!1;KV7b(jAnueOGhu} zA4~W9{{Dc?$gfPat~@BV%u9%D%v!)k5ioVQCevgz8*iE0fFQ0lawNN~KFYtNcV>(X z>-&PFVF8$O5XhrOGK$XeFAtSgd=eZ7V-nNRW-;yXGLfNJzcQa>j>u>=Nfl4r52680 zTt_X=4e%E1Sr4HX4IoHTT_@rQ*-=$0Syn*~eJTgHYw`&oB8Iv)*)2jkBv2@LwNJA3 zPnlp4amh;FV#eWb`CB_ zO0m3p{k_4VF=vbgnMihn*Ca2;-8K&#mn%ZrUKd4nnRm81j~*$Wwd4Qt4(!l^nSYU^ zt-^3w9#Ub5G56v3`(c%G%Q79-2iy(`;x1oi7V8(UU$!CzX4iJOGV79_cB{ERR^jT9 z)?#S{tZ~-#0#`6s%{SyaLU|tbbq--hVA-QvCoGGq{Z+JanD{BGep%Z?M zWF}HdKP!ACc-t|4_IvJKg-8ei2uzn`LY#GE$H{m8L~2*|+C9O#;wcQAC=otn%xJv% zu?RWlWfTCV1uv3`K>0Z`?1~DAK}%(WFg^=&gzxXP9!jm&bVEPV%yt(-Hqrp*tW?S%-AV60thAgF zSnIHAA5_OHV@$N<0ZfC?5%2?yPHEnJ5l)GIM+u|z+z@6(2FOaFMO5BtyFOG0`zS@_ z+?+BnzJ43;7=VP=Y}&~^&Yh~6^5{W3I*iZ$VwD9CL26%} zynwd9T&qbHOF6@K>8pdF3#F7&uF*seg11ol`aU{XTEmBD&$CCf-DmU+k9w5Q%og-t zb9t4oa*;&^9o7;upXG8;?^A_*^3qgptO6}jjzkUK<^iYA)JBszMSFMnfT>MO^SS_a zbDFVqm}ytI_goTlOj-LIdA~Fp4vJht6he0&Q}C5NzBqhpmvxMS!DMO=4NscMfI>Y% zcpCQ3%1Y-}5)~1|Zh)Hdt3Wvn)UOwh@Ht(LX+n&5!)k2G`6Z?iWl~%)`mLZY->YzZ)A4h z*JJt&Om9MG3!^hhaj_lL)^!z$(QxrNp{Bpmn7|7lM$Y<&Y|cJmC>8aVeIqB$(@F<- zOSlc#rR8}7xLyCA(b161XFfu(Eh1 zII3)F|6*!o$e61m3BXr`Vk^bOZ6nC4&czi`^ULKWoo~=yX-M&y>Y>+_eCP=^+*g1^ zh$3_E_^JN|w6-G*->{AER_mc-c$dS=-gjTg+*{x@DhK$Q*{osFIqwvYDDnRNrmt1i zs%#S9IQtN$HPqQx`OWjjE?`ZL?eE0o4_radG3&WQe_9vUl5R(G}hs@rpY zto`L~>~kpBHG&}XkZ|h*F9^Jjb|$bIIn6^nY!hqT8o}IY+#8r7o3dH|l**cv*5C=E z-f{U0{V6R}UmR5KYRup*LR<|g9_|D zeCPc^C_3jh1#vakwG<>0)WUD#!Y2MZFu5FuLp}<*H{J~uHE1#R^xqa@3 zf3QKae^WyKlvl{2ttz#DX13>DfZE}ojW)i=6hHdfA-tRTaW7x>-M<+&G-D8;w9-}Q z)Q-|Eto!ZF{^7PuX6~bI;fbsL6%4G@eu_icKAz61Ya~>T60DKjFy-y*+NMsJ7u#SD z`4@h(_CV9+xv#yKzdWHyQt!QhmfCHjZP2OtmVZdUDB48@0Iz(e2E*uhDjERSHr~Wv zVuWru!JF;y@B`}4#eu2=i_lsylb`ti*S;=RQ&-LcJOBVsAOL{a|CT-fzisQ{Zn+h6 z-1hVZrtMtwDQK%Gwso5_U1VHe$gPzo@mxcXVJI7B0i{a2GU@j*xd#CX?~milZaB4AR8tmTnR zIJu3t#Uu0a@BMnw&Lof6)XFr-s2EdLiD*tpW^t7+)T zqKl}dSuqb`~|pI_(GcBGOSn-<9AuPJHo`TVXu&7^UAw)G~VZaBgs zMZ0aa<;dH)lYt>v^!J{GJdoJwO8sPsd`TX3f&2FqDl`I7LWL6+2slX~49Y)nPbKK_ z0YiO4_xJkrhUhauO^m+m)s^gp3;RUHB8qq|_!NN`#5q9R@Ih{mj~$0_gkI@O|N8i~ z>+kWd?(!gIqiQYWKs?@lQO807?ExG|^%+kl?uQ zZ8;#-#gO7&`omUw$M_g;w^6@nljh{TxkAns33|BlnBF@b)%-N-PTZ=#nArQOvo)AP z*woq#?S#WFbD!#+lIh%uBsOu#M5rw%;e%{AI2$Ag;;~BcZXay(c!+rN=g=cU(IAqD zgh0Ih5R{IO7nOw=<`F%_BzgW>N+BI-RW35^a2+sq3q(|A;VyunfU2xq3fvPKUjpT` z*178x&gl(}OA`E=)kspYTJXAEV)0FdMiZw1n)=Fax22j@5rrYh#gH;Q^db10v*vBabC&~B4C%>3J zq8|-lS$#f?qDdGgm1JR%0lU+n4MmX$xHEL5*@TFjz$OIP2w;&nokZUN5;WJa6Psg_ zu@Ni^{x=m{URb+5@`t0nt*|RPO<00qst`XBr;Ma&V7s*3p9UU84Mf;5H#W>iw=O=? zg032~O^dTnEgu?|hPsf$oS1C1KMgemGT8eizqO$6DK?6Nh3Psy{S>SNQmlev7$Y_! zY!5B!))ctEkUC|u>oQlc>*-f_z%xv0MipR~3yxxW7aVVT^CP}f+Vh?ao#g zwuaN1XjBA0vx6k+%K{;|YOW5{b_!;K79of$*hP0G`g~*QTIr^oV4h2E(g5iO$Fi?z~Jer-CL8^GSUEH2RSvpDxwrB&?l-TNEZ3{dR<~f0v&Az|M*z`C!WvG1GKGIhmq0&U z0}(jWljl4m*P?N7-0g+567CwAIds~oC6o&aZ^ye{!>-~5*GH}a37xB}tFd60g(glu zqYr+0MTtfvNY+5;QFP`Tf2Nlkk}HfSz;!JYR}$&eqFtkQo2v;e%0d;j?N`}0rR1)a z79R#$KogaCx>fsYjkU06?rV1HLFfNefV6Cqo94``<3n5}O?F>y{^SFtB)Wbhz8Y>K zR&>FHRSUU<-9b_*xy-d#2Gpf4H9%U%6R?jhCQL2>@nJLP`GCZ3h2w_^SO!;e;v^i_ zQ9Wx#%i|jlr6)#I$I6mav23=fj7#N~KW)h9*Qz0pj2j}yL#nAJO{+iJ)BlB$0?(YJ7#VmrVj&mOBm|;A z;qb-j>B%PbYdt0pg%1*D;$&)$g0m<4Ab~F9fZhgl(33h2K0>8vdprysTSgL*$ve{| zy!E0f9=leKq9*a>!Vey!GYWpP;0-=+Ak_O=NR(|;xaS_poGlh;jceJciRTLTByb2o z_;_}IoqYUE)s39iMU+zrVw#ZSI=l`jX|$$xNNn7O;bY_o5Oa#KM!v=|Hw8wHguj5AP5WT)cH@XT2*UzH|;ygr`71u{Fsf zrF8jq`*(PD8ha1h8!=_Lsm+|09nU@rE37Wwd~(Le+jgm#V=0{nBI-88Hjyh1_7zwR zwSt3)_a{%n$!TO<9JpXYo!Eo&i}hZG7WIDyJ)d6L_hlzn(X`B5|An)sbhcc>IB)-E zhFB>oa(M{|-1XrB#mp*>YLAYwf&y}U0djk{1^`ZEvgY+X*Zvg-}yCM62M{sP`(I8eM3vwwW4 ziIJ@NFU5=A9x!y!jCc%&7d5$=7ZN*ZL>30O<#^$(`vnSb>>!Xds!IiIuBiSiR~hP3 z_Pp6^AS&&M;mP}tvVkJ=@RQ(Hmm-2bYUB%eSX|%g{jD`@>gy8exNXj*8C@TVKIm5K z51v*ZRW>?7Y9Ns3_EJN4Gb?)e)H2ER2$?@w_{Sto&Uy-D4UT{03fZ^8k zfbc_>SQtZ0k6u8$dGqUI{ZUqTG=B`@-&il7wiBb-YIp~Y7Rm$ZNQrt9=+7m~yCUj! z+6^INdp)+8}Dsr{uq^Mz^SiQWbfboBf!aIzn9A@7p+f%q2U z2k%~Q^-*YP>X-PEz(NA>F0e7}|U})v7m7fG)h`=V$6zdu)#SF^*R8Y*4AMt_0}T z!s_fMF?R0m59M6ZW*#OxYUs?IC3_T6A8o9xhViV(-a=AAhg%A@FouFF)Eg{NHZ zqBv>kEsGxlE?Kx029s><3^yQW%H#Kvqme=Zp=-1Jkzf216U?EcH6Sh&3kW=1os!KV z4vIrgDfwqwTpG8^mC>-_y8-4QXNE+6^=aHLH@CQtci~Xa-~K%5ED zuK?g-Lmfe-Y@!$_%9vL8tiMHyWXL0}=;9c!+D1<)s&s9@FEWLtD__=fHI%To*6rufB^VvjlDZ!+z@7E7V{#B>)9qS5^%NFNp9Y8P`GaMquSVxJ1Fxv#uKBCxH{Mzkg zM+tTd55K$EL=RFWH+b4)#vxpC@N(Eo7ay$%_Q$PTf$~HoG%(XpnMZo8a7$8b!~0W? z5HnTZkRE$-C!+|bsVj4QXIW3elpD~)oFN0nM5c<5Re|EfmN#*5rUPN-#g;Z_WH?^h zAo4qU@2KG>n}hFfW%;ptXXfaz2$*{ny>Sk@t0oObRGZW!qaK=^!Je@EunT@B^KUuO zo8z-u`M;RB_OvyAO{E^<4o&UFwzv&8V{rP0s&*>?*$L%A{mHLuim1g@-pnMOS~3@S zh_*J^9fgzDg1@WVv5d7i=daoOsqJwUdYd}|Z zdjHC>e7=lRrT@Hg1%qH1x4Uw*2ATR9PTTz1^E^G`ZNw(k}%6N0R>MYM1BC(8zI6<`5-8#))#rkseua`?XM(`-8t;H?W*$T z`YL6*5lusurFlq$p!Orq_m{a>yKT@@b?FFP^XgOlf!Z(SL;H9ePJP+mh z1nnJKXro9|scdmY-*0#5skIDGM7gRs-r5$cNRz7)wkO3~n`h<>pihmfRN#Wrw!TTb zsgL`;^7cWrw+}AD?JhC3*@jyBte@GUfi@RN4-!H{acN_DGpXQjSb)XpTZCNk} zL5eD!|6Vi=gEiAVc#V16U~V}2;y3~#Yc0U1XfX0E5!Iy^XCMDI5jgt>E4S;o;b>2g|pv`3xWY(;8>RH_6wq+nw&yLDmSl=b{p$j=ph+wt<*> zq$Ed;p3*N*7i*nPGS}w(f@($0ca+W-I>_g-@*(TuM0b~KSuyR^ZH;vBIf%oi#as34 z{7{H(^~f+-@WmLMd!wbgcOxSKmybKuhR#=CXD8`Y-)nz8ZaZ!y=kw{6@bmH!->t19qN)|HS8~8L*#zEMtz2y!?LgAH(l{c*bocW@FUuJnrq#ri4Xtv z#n95-@xbNX(@!4wt4nAf-gk^(mg`5^K$3{Pe$TXcC8>G#Q zyS>o{g)Y%QFVT-jH#1zjG_UqKqBZfC6HAO+?(gwT#=sZ{^R_*xQD%otXR9t6Kk)9Z zPD}4dB|rVnA*fk6HrdH1(zp9z1o+nq- z4XcCOudW9jp7*R0v={6Xi(eZLpJequ?$;&wXKwdeHwqVuc!9DXIl;}h>CM!)BCij$ zKKpAwf~Z4Z-=D6JdAXnX`z{;cij(Us5~!T=d^t4jw$^>-JF-?T_x9wxq&@nyUx+ee zQwRK4JLLR1(0qm`VJp6`7oYCiHrCAV?BCx^&^f!WKhhUViIOHsgN*gfxtI7?h&moT z#UjgDXlq_h=I8b{2Ab~-f6tIp^mg@QM9;2k-R!>KJfE*VI|kfl23?jXRANo;=3nv# zYC~^(;GA}6`!wo1VDo$yo>m@i&)AV?zPI(s)8yVC3ei|rLqr<2ag`6jF3>mGZw0kF$09NA3_5+s*S8UI!ZDat?h@6vd`Fx0Q5wXuW1_!*9`=Xn5S6nvDJPAte@s+J1vi$+{_nOYi*o;oa>? z?CJ6PW_@MU>(&|ljwf$Q#F<5(a4 z$rrJK&mOyvJ#X;72?%`Jl2Qk!$O|6qZi8>8BdVput(;!z?7RHrFeLl@x+I?ML?}A77;{I%z}BL>e3f&{KOL)~ezpM*o%hz&ls_2I~URCTWZtX1f3F zDtUaY{|owy zj_OjTsFCwf;WK31^iASpdJ@ekUeWTGvcVDCXSH@cw$r(bz<+(+q+mfi3$@Myj4uat z#HW)DpMQIk_d*@tn`(ru*co8Gc6i?;@@K0MtS3xvGEh7*d>Rfi0F;L3;|=3gP;vY(%K74Ac3-_8(3@h&7peUBk3Lbdf#7M4cQ++|Ua zP6wHjxYP~i3g_65%I=tmP;GwFmN;KkL5QrSEwx{*L2xpY8&_C0cb*al?Aayw;HjyG zS^jM43hd6i=%sK?IWk$WEzReH5;!F};pXw$JN`>5r5P+PZwUsfYuBx~8xPo5oa&DD z1-E1eA#dsrmUW zf7}Ekd~$YhKgq zLL4Jxp$l@Cgoc*t-+-I=@S2WMviydgwSpZW=HRp5McPFwx`XtIA^xxTUrQSxCK37( zL#hU++$%OR`P1L6Bnv@jNNJfxA`#)KOFqU?^3UZHyaBRdRFf}W^h!C128$pn3}KXL zbYEuF=wERE?rNbybRA9|@b+EPML0@oQk4-YWLUMCG4V|)7o>YhImkm}@Lhwv6y4LK z*!%17hBL^$k4PSd1U$(Jtv&?Fj*UK1dteO`C;u%lN5ed+oh|$i-KpV^Lz$T4SCkvxq38laFT50>Q0D%lSD@GN8qwXR` z@G3yY0Ql&b>IYhAVE*B?RbmPiFXw!KC*V^-;2X2mi(as6hCT0;%fZseroUIZn-Ul~ zhl8oXNcbVtSsnNvoWSSa0@y!(pmXlqeG(TvF(Ol`OW!tF)>2!02{Uz>M`BH<%KJq8MN2)GlBy&T(CqCplI%NHQv zNWT2}E?5xro6#kp4hKjKa%jCnUoVo_h^9wtesmHDJxHBz&L7eTyiE>-uBelOF?+sr zlk;-vW$hW}=?Zd?`*m%SbQx}-K$_9zlR}=qi$iKHZEf4P}?BGzrRsVqk-_09Sq%sK5 zES%%W<{}jU<~hJaLnzDIl*qp5)X!jmi=eI%WwR*n(YPSgfcEkLg<|AXERPgpENhhL ztb#jySy14$EC&@TMr`tAYvtuCp_3#EzqFoTca=14IE5r1EU41*dVU(!k?Jy~ zPUyl#wUT_KMC2=z(by)nrCYDgICsBjH!oi835^Z&ZeZVebWjE|F#@R{AA+DmshcA9 zACn0{HjxH5-kRsq6JIET(Kh|*LN8_ImlUDu=JdiWCZbJ+xuM@mVCdjfN+3e3U}TLF zpi;_Ei;sM8R8ELQ1q&-CokjE~!VFRXHKq+H%Orlo9(ts=b?FT$CWH{|p*bwzIt z2efnk{E4E%(bq{zgPVZ){KdD7Wbj$^(-9W% z3TrLxMN|%iYjlVNpX!(F$jr{(wC(dRQ~NXWMt=IW%XuRO=wQ*o5%dkES2vlc?cAmm*b3JxBw1 z0(y_^{erD50l7i&pJ|}K{5=9T4RZ3|94*?^k573w+8BRbi^o8ygIi72Y*hF21KYh) zxu8b6_B>!!xnwoHlgcIRW#9GcjTVB|ngrSwMQHbb)^2@AFrbqM<@NVw6Yw2{(nv0q`!dH0XF}c?$ZD;90oV=_F61GHh(q&ZObVGsMCwNcxksT zLF^Oj1bUDOsa6TzU#A*9N%l5jI^v=G{pf&iv+YBV-6rvZ(V{jEN>q=3-IT4YUZ}|t zJi2&D?~0SM)qJYy@M9ap<;rUYaBB2@#g;NZF<)AeU9B1I&W__q2eDQ2ZUa*Ern*gt z;n^D%POz(Ij>V-6*&(r$RT8kbhQEsh&hzcM_lLXFbDh4=O$Ezp{Cq^MNz%*;a`lr= zft6v?kyNEXpRNMFfDc3XtDgR$()xQLqZ(j&rKJ0~aaX#-yg4qEh~O&lDz@=;@&99b=Z3VpRJ`f$2bIIDRq^VZV-fNu z{}C84SxznS^%*Y;vf%9bZ)d}?5ksNLcOlCaF9aal5|D06dNlaE_s<)PlhJI;8dw`x zgJ8wMKaTxX?yDGH%lA32_Q@JI;F0bx`<2#V@To1Imo8P4lqhJIhWRkQBzJx_nF}Vz zIAj^1CgC<%e^#(d=`Pv^h00@dKbeo7kFE>~TkDNr)UL(~zKx6!*<8NV^Dq z;*Bwa&^gQ`Oh{9HWcuvPelca1=gZ7FLp9eC!()v?$V15rN%U1w^ z7z;m=66&#>%R_+E)r|I1)oXSXf5=u80h>Y_Id)?J#JT%FAr>eB-UP+;b|Z;2Zw>?T zmi1YnT4B!GycipgR%MX?wgB#F9%-x70~jabsVoScjx@o+GJ#Bl_VsGMoYW?r7!p;; z*+OS8C~)F{W_K#CYUGVEHw^4BAc)huodFYpEUpH%^cEM?MKQM>2k42fP#&fgT*v7@ z51>DOwy3d(z{OcHM&y@)6W4`B69DJnZMq@hRA&=ZP6mzK3a=ApDpZ&|&7E89|p3rkgq#(2nK zL7HJ{rKOi-AiPZYkEZ0LEl>M$_z1mtQ)$Am)%#V%8_1lQ8)GX6T6tNVXVxkAJ{2}v zW*u*#VFi}JIr zJT!wuveWA{=lCDt)^`%!Jc>D{Q^+$xG2N%3b$Fj}&Y9dhWHVQ9;XQ%XVgA?{Qpjih znAHNu7!SRGj_g>_%@S6(TSMK`n{nj~_}oHvdCps~7d)=|DM|~#Cb%tjm;HNdsbIqb zs;W?Lq{2f!OsE+*lqejR6#+*B{!0ye_x&e$B@EmF@NUk30FWvgh6;pR?o^!DJoKvf z$u}2Rb*z@XUB9)*Uqr)GcB)XYf1wYg0l^(Wg+X`_r-Q=$z$`M1ztq+bX7+KGAsp{P zO!JQkQq3APP`goF5V_B&K9eHEh;`$fy%N6gx4=S3cN?rKv-M)!jbpJ-?VaOU!Iui= z0ZCZW<}A4O&_i407&FcQnF(bhk0sPnYsjE_kfC4#cVsO`#BU>;E+W5@>_!gq>iMaH zl6!w^E43t2OX`2~{zLvlm|YstBF)o3TUul6q7NM?;@}Qj{Jgm0+hJgMCBco)m-hXgKs7I`T#6K_`uXOdaH~UE47i!Z~n7M(S!j zuFUk7Q!l|6aF|Mk zY4u6*Ti2n%K0;I1zLQ7?9N@kKcK6&N4ARVjW8Juf-a2`%Ol`t#V~zwDg+6aEhUlnj z{%?FJm^96mlk$TP$6FqK_B5N)MM!Tu>}p;pu|C!po)D{DW5VFRFf+}6)iCy4BR~x=$f=E*Vys+(?LK0 z!_uwW!iI|r;KBPHZ|9LOlFo|x^q+tk@zIOAS)@T!O9v`9h5owhFZnw%(LY1UU;{UT|`{op^RMd)B zzqmX$(U;qw*JzKY)}1~q%zQY`YNN_?u$!>`ft^XH$e|t44$DNUmLhY+nO-ToW%fm< z;p*%xf{c&Y!~i-?J}J^G>Z1DQWh)uW)5d1?qnqo+b&$%MQf7k=__b3baqMmg?@JJQ zLNB4oPj(Yzd9|ckm$(RSiKJf~o85%+-cLB;Vbt5CI4&jJRI%+`BdgRN=%E%J*ODIN zm@2xhxK$e%CR@`8y^?HAN2+)&6)K&_HyKyh%Af>Oyh@-HT`L}_IW z$u$!wVb*jg;g-pyzeF`)x&~NL*D5{21hvX`qKsLIyU)8$x@atRq|K@i1M*wY>Nrs> zvG&;P(#}dNMb(ZWAIWyXV&F_ofu3@ z?BZ0(*<5H6xvtT+#$S65a5?set4`NiZ3Ygh4{*A>pX~nTc2>lZ7rHMt{_G%bADyCv zoQIs}D3^nx1mg?>*r-rKOF zHJg+2dBtORr+1SN?37QmLKJZb5Q;cX5&&1wf!xviAboE-)(7`P&XTxZ=XaK@4yjAp zjVJzrT^f`OfU{Uc!8iqJ7Y|S&S`)3gK2SH#C!8n60Z+fg9W|8>G)h}Rx@jpo10IN` z^x8<^D&Q(1O*O@|=}1bnezP5C-0!U5EDJ zT;uIJQi#95jiioO{ONzc`CJp9yF3%0v&L3&H009Z$5wqnsL6=!k46$x$5u5Gfm{@Y z66s{q;~QGP?nGw4BM!T!GO*2J;d~}@zC}pOOQNz0eo~^cwjpZ5rO`;7pOri+^35It z6YggbRu@zXryzbFk|euSDwCLBB+XkK9lnlDtg7A~Y>hCiN z!<9MvtkeG%O?XAL-oGaKYj@@g{c*>0*B09IoVsi~gEsK6YQvv`r`w6K8fLReDvds} zrHbw#`9h7-PzH50Xfsc)ZJSusHYWZK7v1=01MK7`GJAd;i5M=mpGUwZFU$Y92-9$Gjj-&SO<$s~-CjPmLZKBV42^k8O#{bKkrw4SBf4GIN8~ z4N3$N;LP7SLXAtUVH*MPxam)hVt;1qYTS8(+l zZo84M>{;&6eM<7Mm3k%DI-Gtq7eo^$Dg_uQ{;FJI`CR9pqNEMq$N8RqEoSX(G)Hfb zo*Heumy{qiK&kh?sI%*PPlPe+i{%PlHIpOAA32{joBf)k9JqZZ2i_lER$wC$o+%Ts z=ma=*N=3*7^eGFY7@UgX=0lm=f@S(oEP;kg4i$FGCHpJU#CMf3mnl%uRrm(|BVYvV6602Ud|~jvm-y2;(o_thN({ zpmXD#^!Hhm-kVXSAok90tDF=fQ$efdFnR zXAAfzFpmIh3S?Rk2(oD>t7`f(S?I~^4(2`t*(oHv1(rUvnGQxn$W-mGH<_pxJ~|Wt zPa-Oinr!pG4vr=kw>vm>yzyYK5*_%Z|A~k)_)r{fLCo#Z>Wdd98E?+GrV5r#O0aLZ z^O(WQfa{caOz{-|gkOX7Ueu3dG#I&U@~)rdT-<{>~@|Fr_J z>eHjI@&4cFloc9`&QE!*u{A>`$YkZ&Ih`eNi7DDLVSv8cbt3m4_!$Ou`M|ZXo)MiP za=c6irrQ9VHywV!rUGB`pGqE3kgc2cjwpaNvnu&Q|isfPBnw$3drlgG+yRT9BqFZosR*H>icM zIIDOr09VzCdR9@lCN}b#G&|Xs*3qk95fillL)2Yn^WVMEP9)l^8uIJU5i|_DR{w@3 za7%f=n{WdNu7Gd%S6>mCmY|~sA|P1A3SR=0w2wgwI9Oz*1(+3R5tPRZWJglST2Em| zu+a9esDXPPP#(9D_aYI9#47tBa)4;FX~LVDF;G}Gc9=+icc_{Gz97C$5))zCD>=-C z6i($s{1ziEv{!7;C%vymN?NqI`d&V$J5N5Ahu7gmZ zD{^NA#YJ!|_~Y$+0@pxYVcVW@=ny@XtR*G_9HWCA;@uGXl&l!>4=jW1!IiGYVoe~x4ysjOKxL8T4O8k*b4zH3R zk-S+NPmYo76p?bjgw<3C<*q2fS2Mq;!+Zy)s%6JC zr}A9~;>Y3iIZ!Z;iaSIeRhzAz+|X;Q?J^g#gbu1)SjO0o`L`&evckTP0jU5s7AjVg zecgfA#VTF(+)?(#R87|r2xSGXYOob@g0&Ute}=Xg|34E9fZH${OT55oxBQc4JaixK z95hex^lgJUgsNX%eXwGWq|qwqPo`QwmAIRH4~C(T&kiG0xO)Y)9lrs0kzYZcer%8l zV&}gOYMBJ1n1xdTd$G0rbP?Zbdia5QGG@dUPTA4(DF4xlNA8cUAPjo5E^tp!ThxqWx4@Cd}d4gh92FdmNJx^i};A`^5ev>wljZ>Yc7zTK<9OxQ*PC8Qu1v1NY#Sxm}4{hZ}7|)STxI4 zXL2E3&f{blwUWB(&XxVwW>HP~(wOxkT2p)SD9mV5W*-5giPWq|uszSWknhkC6^srBY9 z7dQLT-_}gNrE4$$2Z7~u={pAs7XXNj0s`>=|I0V|-^`W&vP}NFT-;#*K%hV31Azaz zUGQ$W7I8IPf1-6}r;zh(PLkT4T{+8}x->9Lx=mNz_ahU`XWIm^W4M|5eI~U2Vpv6n zw06AEOxj{AtW=>&sgx>F!VzI(z&-Ws#`ux9%h1LYJH=no$>xjfd^81{Vz1N7D5Uh& z7{KHp0AIo9n7(fzc<{&nesOqy&2-AoZzDo|A=Mf0ES$iyD?g1Ruqvec(@DPLB zQ2lxv;uX5L+(=k<%4K=cI||<=o1OUmJ7_c*{uw1OJ&N!j*c+CEEu!OG-ganX5TYZU zXL|lO@Xnr4>m$(vu)VTrr-Na`xPI@;+&vm7l8(Jwcb60*o$Vi5P&)gz7xF{B?k!^I z{T4VP_A+Rn7NqGF0`HDvJcAEv$nV4Mh|Xv{5zVA)i}yc&w&>;iDqn`~i!d2iKw5=0 zC%g>8`f6^gajV!73@%@5%{%)+i-KQTYG=a;uY3;*@_c<@)pBFZJ-TJK8^207GMWqAJ(=>_2{J2kWY^%g5Vx+-|7??Tg_07 zkSFl87PM-2;_Z0?+;{Vs{=f}Ja0iHz69r5%93TM<9#C4Qhulw0Xips&+>*0VU8NO!rthfTTv*Bd=jJ}#LUjwN()S$&hC~sDZkUbWm4VxIX93O zUAXmZBnPo~PP9rOIkI4-h`V?45Hk*wg~$r)Hm~K~T+;@RQ>-$HR<~RE6@LO9o3TMo zgWOd1OVw0toZrr_dnMOa0CL&1lqyQjw;UON=qz~B*Rf&Dduof%yT_-Jt>#P~G~DaS zXfy?`{l${-@^!*#KhHGq!SvxLH{+BVD6K~;t30NM|K{EOkwOs9m}wQ*E~Vl}-S4_L ztdv1mOg)d!_ZI^^?F9!5I$F1%c+{ipkEJR`0 zAj;@l3WZM7?FZCXN-w1LZ~C~FVBnrd-G%AsM4`E~<}z?jC_G6q#Hml&G_R#C`5q@0DYLQ^92&bYYxIxsf@f0gl>_%uO=Xw{6YIKV) z+a<7RJ~(lWpwSAKf*2ozAa$LkUD~l(cYup*3n~Sji9&Z)S0Q&zIde$u10JDi2B0B zvoyxHlwLA)$4wJ=hI;d#n1P;n+~8u!cSfCL>$;J!VaAl(`I#}FG*KwRgRhA+-MFVu zW6H-Qr+TR>-Ka7G!7G8+D$FK~Q*Oa<$hTYjXZQET+Yd^o{rbWx*RJhTys^c9gqqq6 zle)Jmp4z1ouAg4mLd?OMak;jyY46_`xp?~hHz#PrrvG|$o;6{u{#xsp@1KIh+wSgd zJu*Od8T_FrjZ5Gh^=PJT4NeUvRo+9Rpp-DM&Jt&$(2@oj%O+Akk6a)+@o|{_e%#Sou2BsgEj< zb(@#hk9L`FaE<8S(zqTwWWw5RaYAv*V)7S&(nTa}R!rRI2CcvE8ZqM%`o%rxhniM4 zuUFaZ)`d2Y-f=eU6iE>ISgUmOhbB_$^ZZW34EbB0|K*5S)EvZEph~T;mJJxGtdrG! zstRV3mSmO;Z@VL`_TzG3r6WumMcYn(eqU2>G^*!fcLlE&1_ey^D)Oxog-qH0SAes+ z0d{a31p#*-x-gRTol(cmy-l4I;%&mS+d2qX%o8J#1_E&AFHO|ON})#m$*I2H(sG!8 z_X}J2^kl~$Qzsp}_dSJ?z*E1=j;)Y*Xc5uo7A_jaQX|X?4F!ZFQiY6{S+SB)iBc{J za<4815>G-P2~aG{=y7(~fV2#B3^2Ip?{GIn=;I~c`Z5v_bON65pUd942Or+GS)B&2 zmuruu*G=Wc4YooiA;iVipss}!#oJ+s?g!OK^%US_l~n#3mk;Aj`&fM6jV$=>@c3LI zy4!tv%A`Yb+U(x-3BuSUi|w`KCVhACNmyCqU$99jrMSUJZpHSacqAR+~Ib_P%9s53-Qj(a`7uw{{+ z$AO2Kk!x)BsXX*K)Tu)p@4Id0tdEXwuz>X;)=qzmgjp}?;IyaDhW;gnVw^R}rfFul37b`mTGId*(2N;K^PLnAiU zgu<$ZJ+5eq4$|s}lFoW3krcWeW#u^c=xsBcfv|Wz6owA+QIFZKG;s4x$x%N>v$WmH zMx;YhR^AH)NpfkE)GnEbkpj#1PSOazL4n}NvQ@0-p4nWsX#8L;P(wJzvNr4wO-fkn zT`h-Bmr<%yLB|Q-s;8jY!2p7qgzu^JiA2^Gh!Gw^bc%ukt0j80b0$vSjh=nS?wpos zxyiM3xegs`f=I$Ws@6Sd!;e@QKM$G3L-4}pJXv&BuAldW_rMPcexkyN1^mtgb{Gd_ zMjVff%nRg#-*A%^8v2pK_(qNib&4+mR_qpjze&oX$u$={Hg-H)UIln%n#P)N4e^t-(mFG=;5bIp7V7=B#&d#VK{*?pB0&exCU5 zmcz0tngL4%h8PcyT(fqEPWm8S`T%Gnr*D!Y$b%7kqDxxvQaftj0L?{9l!?mels7Bt z3vZ^rAg)#C?{ofZy_su+j8=<&CQ47z8R@1ky|TJcEauP2S0>3%*;mx6Po zNxsLAoC6_ol6>CiSZ2%!H*>7#Rozw@=sO@u;Uq#(xe1AE`iYHlvJ+O{1l%ZxFMTD! z9jr>*0|wc}xBgvt@D?nS%g8P}(D(QwMR7@!sF>d#sKC$E4@Ti)47?&M%BOcN@`RqW zhe=WTZ;pbW&M3SMeb5@zSbW5S6br6}me8tih#$6o?kxLm24%n}4>~$SAI!&eq8Txw z+~<)Pn}00vaMIM%brBok*dT7Qyv^~ns1LI zO1Tr|x+sFhOP4n=LcjaPSa7JuI8O|abXipC(aVSoFZZo3j~?u`3oNcdnai9E$vG@+({uUu*96lz_oV%m0kX`s^iQlQ`Vm&YU!Jf( zb@cKC9F7O^(qgJ-;Lu#>}wK5dPIb+~DQcCW^e3*V$^v;{O{Ecf5znC|r!1 zP~so`tqNQ2Qow&{sg1lorE5H7U*8g{6Zpqp9MAL^90Lp?k%Cq{XF3|a+jl!?LIi;* z@$AUevl*GmS!?Ibz!LvY5nqzy8?JGmD}J{pgl1hMkN*lB?;xg;BB&jLI7G`6M5 z-5NRkROkpqi<1V4Y_>@4q&0Dw=k&a4SYRU7$ z-CrqcDE>U#E9O5P8L)eyeO#X=Cr`WDD6aLxunR0)r8=~3zwNL1juMc1;g60_v=7$| zhW2Q|g1Mve(N?fZSaBTO3BYsXnkMMDO@I+loN(Uc{<+WHc=2qbe^#KCTQ2#>43;vh z`}3k?PBTPBOmASi{ypF2TcqRx9#?Hg$LDr}%F%VN`eAWQF}HJc<4l1P)bh-a{BF(G z#yTU={JxnrkuWb35>HHeBMH%MNaEO^N||iQ2&)zUca*~+O=2yHT(EaZDqgHDyO;=T z`iJz%OR$C{)Y44K6(p&$wVPlvLcOM0z_@BDXx5tX=lX zf^zSC{Dd-HBx__RYQv!Wxw2HuLl4P&^|C*ywaL`;6N2D-shN4=lkRA}iQoltR2mHL zaB=z`4O~Ds&#=70+4}agCdMsYsW8TDa}E{kbB%3z)5)QyU6S+Y$^5H$T(9K?Nnu71 zHvNV?gl-juK^xJNiqE=VU@0KQrc$1`Y^}tGeN5N0LT8OHTw*{ zG_e{V2Y2S;aPJUj=8P}4swI83S;TjuD^-*DErn*(O47^JVN_sN`YHK$C_2yr4#i2& zOUz`Y))r&6?TVoVv6uk`l2p zCLOubc}ka85kdd;YHF3}PMwbVVR^0*AC1x@ouI7_A!@>C9tfq&zMO_-DM7jl{CO=~ z(%N-}R8T|Rwt#=8`JojINk7Wl&1i4d3)AQ2k2G-LZ`tjyo3tO_#sZ!sa{A!KY2T~0 zA8Ti+L5wi=ve-&%qQ>W?bFX2hI|Vi@8`POvXV-XX7Pgi|9ESYQSQIB3AHh=lX6T9; zlJT9);>C8c6BeH}%#zon&?|V9$~*(}56ryPa}BA}LN_y3aF-s8n-^|5X30hKEd)oC z$mgb-@eS9jlQi|V&A%747QZ%y=gkz{LMRqI*#vVk(v*efY+Ib9?HPmr@r;Xg=hLj%4Qb%9R;^0>8L#s(iU*HF3ug6 zZgFO4-O7GX)-_uPxjTNjlA6nC$$0p_b2ml|B^j5?#&T% z&S?5-|4MQ+Fn1{6X@LgfIhN&%WtNOAXIji%A5jODzy_Nb?j!&^FKCs}Gvj4nRy8pD zJ~<-Ux$~-KXx_zZMYp{UOE*)g9-kwRJ~Sr(Feid@>~j8sHy3ufeMJo}*9P;61wKZ0 zQce<{NkQ3eYb)@e4yHK+>D|HFBHwa6k~U<7%P|Ih zXT&J*%SZ5~T|hW28ioWq3U+UQs7oIEgm#4i+#P8H?vl;U|EqsVc-%#cY29$^RU6T> zH_q>)^*!4EUtr}%^N_XzXr~bjydCW&X%DLP5F(mlB5o6|!c+GZ4XGk4iJr1*f;x%t z5v^tOZDd`2Buhrv(A|MB`qJRVzgQs4S0G%BkkJkP|2utBpI3cr+AJ+LB4w@FuI6xdEZWI=o-h)*EWE^avFsG z4YH7zbFy@ITqcfvk)h0URED%zslKg6LkqI4&8G?~#GYu)x+FwGKo!igrZ}S0Gzz`8 zd_0kzMD|Gc7iQ);MdnW_2{09fwEp>d4>)tST62N@065)kB^*hYf_l)nU zN7bEFdF`b_abDc7IGAw-XxWDez`H{Y2Ru_D`79(xaezTarita0g+cLVD^CTPkg#SD z8mZCeiv`3*W#`6U+*x&5Oq%Rb1qdyC-OfdL&BVklXoIbrmt4fGP<~mXlrHlQ#$gTk z?-hT1Io{naX4|Hb-b6xU8@O!|zkmxs1`4{|sR9WSq%yHDnGM zYf!d%w{mFl+qMi`{62TqkK^r~UW1U5)Eao;a2@WzuLzb9OFVjFk~olZ#62m;wX*G& znPaRl8-Z+&@k;aqIMNeID&>U5dqVp1H?6oTIK)r?0WLl=^Z~<_HJ6-YaQ>-Si7@D% z?&hD6CLSH8i~Pb)&~Akw%!Pq(n8>i-HtZ@7oKWF8ep^4NoQk1?ub;b_}r2gAS7ihKW#6c@>1iP?=1%<1R3=0C#_ zmjP>T1=cCmb1M>3RiA@P935^|2zf(vu4@K zb@C8`LhJMa)7XMYlHEXlKnDCioj!}w%`*br&MTM zKQwMCMj|jk1DJLA2?ZZQo*hkSf)^?XloVCNKm*;?c}ri!b%2dZNZ+->fI!Ku$KqDb z&L&;4#RnCgiBDGF8l4S>hrLG=+lsXiV=_>Y93`!mWz8GlwmDrS$yn4q-AY4UZD8i6 zZh`y2#-*6RDh+Tq|9jfyV zWHr@#!gA5-b5GPg7$4#B1QMtvaL!M>TLB471o@|M;=yjzSv1zB+tK5RGF9&IECaKP zwL7`l;wZZ%qfYrRm7GUPrcTJP!>hdq$sD8^OL)p2tmAPOX>J5_I%|ivX`Kb~W=8RC z|03t=v@Xd~+#_@7WK^#l3 zKX5>ZMj_w=T7{8BsSU*PPm5#t2@-C(4{t`}%y|H1 zStB_x&p0bbwhd|iqbva>X?QyxdqCzIAS-QpDKcn3pScTO+q_Vg@gT@6%09x?EgO&- zbIG!nDHPinx5hg^eKJccADO;HB3UidwO;q@5qJEKjKy-{wYT2D)sUNrgjjYO${Q>6 zOF%Q(Kf-xY;BgM=LW=ex0NbT?gz8c(&?&rNi0QTpg|37Ewqq>qGD5mJY!RDjEc{4@ z>C@aXM0~o_47Yxb+fnZ$%%mF{DwHv&8%jxEJfav^Cdsr|bu1osNhwE^c33`&E4In( zq+O^&8CUoBA73|4x&c-@IJF*JWU=JM09?WngQHy#Fj|4tX&*I4XCe}Di5>2cC2s6e zIOt2QWksQ+GfT1HqPPIRo93gwBdj%JK77g!#!5bNLC(S5=fEkg57vGhpeUa9@XvqkcQKQM*^(4? zozK1T%;@HUL#(VK6MirE5luLABg}jKT;?6sHq%U{YLiu7PMEUTWLcc>kFAI zQ)4fsr5>HPhq>ZaKo+ZptdRceilGi&#v##vU+(>C-;F4`QTA6#koWd8Z(xqscQwk+McKt$_%`OAaG{C;O5>rTzP zx46Pkx|T17=UtFf#cB1185b^{nsv*NQ!hxKzp{5)q*k|ik3@!YdLQRC3;l?v{Pw}M z?Q9-X&!^1^GB_V#o112oy!N^8jPSo&`N0jZ<|pt>pLpedbUDM(QjX&?4BEFgTWvIt z+wNs<(R_2=k{#3q3j=8}`aFwH8rc5Us< zdHcHg^xJu(@>xv+D>-$y+3fyqGy8y(zZI`Aqfky3U+BK6XTB<$ZIfNQOL=+hxgS-h znV*VFb^Vq)X1GqIf4zd+B0bwFmW-)t-Z7FB3%~5tGTkw$*5+EyQ`U3VG5^&|rpLZ_ z*j=Z;=as?L#NF2K`)=Rsoa8^fB5_6ao%S+*`|Gz~9txdfW*E9Ztt>jN;fnm@p9-J- zdmb_weG+3{&vA++;K5>^&F)(Fm-H%kXP4ip4$W;?sO8?*9X)~NPX3DmK7)qtwiqKu zHsEY}XrHE=iuKO2^32CIe;GkX2mz=rq-J3H$7rj{h8B$g!VhlX%6Fyoj}4e(}U5@7&d@6N%&ux;LFpY`+R zTbKfkasgsaWOKpnEY5N#kA)TpS0VT3Qx7MIkt%)HE!%>2A!{i4+3 z{L&)e2?wqfC3&f(B}Msp$p!H93_$bC=w{~`_wfA!-c2sTi*EKgRvczKXXd2<4@=0; zDa}Q_jvU==7MYn|&Ompc0J>Wj=43D}0*pPZ?)HN?x*)%(1h2Ct&OhDR$poAi=U`y4 zLNR&~9}c6P^YcoI5;JqkjLI^LN=g%R@={C6^NX_a+T-*~RVfA-p}CuYL4;yYvmmNH zptOc9fTuOQ%ew~*N?~CJ1~C*91hr62NH5ASEhxrj#@FQVm)^jDJPWiFlDc39DI1`g zQIMaLnVgx5)s(iibDY(HVFp@JAPqABOfNA(H6<}GFTW%aoTRWhC;UO{4}UfWhIv5$ z09QUB0cLYlgNjmfAjV{5V)t47-s2}G0^K78Od^s<1_96Sutha0v8W_7Eit(StJe-6 z%=zOCJUP5si2+yuAcIgRRAZ783lftubAb5;dm!!qupsgoFjxHs<_RfegBUJ(qMDSM zSCU!;bP;xQIwtQuxlD(Fq2dc81Mu2PB=Er-)ttQi6oe6S%-G8{9(cS9F#LBsS%GQ< zzJdf?PBCzROUj_i3mfV*7#Qq(Sr{Bq$|?RzR1@I^iID;5uoU2_DDd-A3Q`T>SqA-T zd0=^l<#ZHyaS3%s)*p>y^RyWlmi%R8Fh_9)$0D+v0ZOFcFd)M6EwRd0ZYmM5re!BfBc&H#J;EN(iAI#)Ryao!pElEdUCS zX2RW&LN5PM*XkiVM^ld?=fJ}R%c?y{>4&{o=ZEGj1_n^EzS^4+y|IY9WM>6dz@U0u Onqeo<>@PsA3=9Ckpd~c` literal 0 HcmV?d00001 diff --git a/vid-app-common/src/test/resources/csars/csarTransportWithPnfs.zip b/vid-app-common/src/test/resources/csars/csarTransportWithPnfs.zip new file mode 100644 index 0000000000000000000000000000000000000000..33225f9d61e20078f8bcb178b6d99cd6638dd83c GIT binary patch literal 33722 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 rN&n{g`$CHvZSME^^X-2Dl4?4N literal 0 HcmV?d00001 diff --git a/vid-app-common/src/main/resources/service-AmpPhSvc-csar.zip b/vid-app-common/src/test/resources/csars/service-AmpPhSvc-csar.zip similarity index 52% rename from vid-app-common/src/main/resources/service-AmpPhSvc-csar.zip rename to vid-app-common/src/test/resources/csars/service-AmpPhSvc-csar.zip index c1fb9e08a630042b8f71072f8078563d74779484..d8969d65fbf2a6d3bae22a8586afa102cf614f8a 100644 GIT binary patch delta 16977 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Ð7Y##`5H)c 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 APXGV_ delta 28089 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 NI)SwCL@$55`hROwz>5F? diff --git a/vid-app-common/src/test/resources/csars/service-Infravpn-csar.zip b/vid-app-common/src/test/resources/csars/service-Infravpn-csar.zip new file mode 100644 index 0000000000000000000000000000000000000000..403aacc8f529ec8c7d03cb74aa4c25fb3264a562 GIT binary patch literal 36957 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%0DkV!Pvl zQ+5REjc>)+EzA=~7X;TI@#7c}2R7W};F$XXXa-rYcC~F*iqCD43d_F|03&AMc%mvf zV1YuX>Cpfv<~-zQbp7%19F&f-bxU8zbs36z#`{Qd6(86aY|2|>YpqzE{;Ms_#wty? z7Js2;XH?QyVY${7gjmXY3c1xBpc|<1CuQdH0AJx9-%u9y?CL!yg{8sYdW(^QHK~=? z44SP;^>j6Qjm9Ia-ZP8)tVyKj6TL=zHS#cVn-Vxs$stfK%5x-__}vxfXrEYrAne3qS$YfIWSET)mj)?fU2B zS=T0}!0&R!EBua6^jZvh@gT59f_ZMQ2r&_ zseg-aEWhPTuA2X~*{RZBK9Cr5Cg$Y0?e&%BRh4ClbyGav+gy3GC>rdlVS%}N%Z>6t z)|Y|Er@p|IeVsR+=-q;@gVk?j*+#-kw>@;ghEeniE>ua2#5$(G_bDJa6;1a7N)q|^HXPX zc?oPkuv^@%`z1N%rXcdB+rik9&&z{K~L#f&YgRQPp>SIs<8 z!pIYbPr@I6`a?k`?ok!>{j?ZFd`f(n!HJW|fVE}Vh0M9T55Vq5*oL$RYbMkWCh0m# ze~Y)lUDgjpkhq1jwa>yf<-i2z^v7u@4a>uWnuh{#0jELmpyGq}_66QRzOMpVXIS0? zSOeIA)!*axL1*j#Qx5Y{3Bs%#Rtpv}K{)_8z-E$!KGpcPCRxz>l3Y~t89ZR|+gy3<&UJIa@na_2MaB6S zD2~9Ve8JM)5eVKj!2>-&llB%`I4wKrStxG3dGYe@Iee9TN(c)$2r0_bz)$%)eqL~965yo6 z?#Lh2xa8QohmQ>B09Q8P&b0YN=JvJ$)99#uWb?JtZ~d3HsV@^`{ed$F^LB%=ZteBH zZxbiK#`uBUXgs!+@L_g!?wJvq$MCNH3RhP1t!YgV9}gsuwbvrm0Sany9~fbO;SIf5 z|Dh$9`?GxEG&GdL(RlE5bK@23l(E4#`9*+vaaDHJAwo;T{tCsdb8I4R38J3pGY+0>1^lb3J=HD8fI&T&Y@4eyE`Q{~Oj-<44bLJS` zt9bxBv+r_U;$X+^?n_vTvrls=s%G;GJ}Z9VVS^-VhA^4cCCmZ#RAd2`9Qe9Q+k=$t zANo*ZZh{rxCgVB~@!H?kB-kTj-)^RRoMOe4-Rc4Fi0B%chuwNb02D0&=m_dUO)d(f zv85pbGoQd<6h4Z>X!0kJ7Z0YZt$Wcy@Cx}SECI5_zP%!?|1nK~`DZr_4LF>}n9xCMOU9;8qXytCh+0%>uHd2@h5?8g9J4uaRjy8Yc7r*~GbT{2Xafx! zJeL?Oiz`k|HrE7jWDSIr&;Tl}55&i|sv6JI0jTSC!oOB|&p!g9gDj^@c&N6jZna1G zxZ#0Q@%g==Y?4G+DFUF#F$2hfo;U>H(1hj;&>%t*P*A}D!f}ksMB@INjs&j#{-P^^ z9({^o851qYme3MJHs<`nMlAPjefur7zr4Wi@% zdivv7lR^n0=?9I7Ym>0a;Cd2ZgZcum!SbL0y_)_6_WC8bF-c zAO4Ft_;rw+z7-+={VJ>m(oUs($LZzRBS|w*=5tlOB=7Zdp)VaJwh)3<8vZRe`{Ko| zV}P|P)YtCguHrK`@cn2$+4wBFdG{fwTe=L==85~^V`ro4>>HN5>e?v$Ougk&ofGHN zh0A_zVn1FOzlj9BYLvL4noj1~M5AHtpS5Pw_%nV6@6wxG!Lv!)J*(qfzWTgMWv8Y) zhqq3W@svhJEj4`@d`feMNjsKs;BKbqSu@+zPA`Y2v*XPvEtS?~%3(k*&Ea1?$DmLm z%m`K8ZDTIbcg+rh&`|-2$r7zLZy16_;qbJX3= zE^*SW);KC`gSjgpcto#uwDL5C0CN5o65ieEM`a)XkR?j-9dS@R z4nP1qG<9@mPb|+Ob3x1RLPY9Fy?1r~>dnuzvk;!thkG zfx<6JZHIS*FMQJ{Xj)-PQtlrFl5+WLAL za-)Sfa2*37Q;$$x!>f6YS}6Ur?%;93=ia+}b>)9%3}RB>K7rjSB43xZ7C_jCDbj zX%s_hULdiL_;qb&%kPilV_{C?UibPPNEfz>Mo;s^k8~DZh})j^+hFqv6wlHTXE_E6 zt_?%J@IEJ4E4%}(x0vp+I`}%xpc^anmjYWRoUY=H_h9W(pU)1TPL)QhtiHUZEe^RI zwVcS49>cnW!NoSgQQ9PIhBLH(4i9IngMYWih^ahlnn;~+jLJxUciQ-=)WRp!u}0X? zF7x4Ox|NNEtVH^R>D*~as!Q>os?tYC_@Vr3s9BEzLs+SE!TdtG->p{MtK;)--i51e zQ(KT7vob$GPK*9)?w@zTT+b`lK|`U%BGakx$o;(fr|MrCA4J(_ zXu*yS%eysa?mL;auul$N_Ni(>Y$}Sw`+RP*-G5hlU~;q9$z}iWPv7lqwJ?I zt$Bmb{nJVyrLuhODVXsS)_FGt!zyAy5$8(Z90w=40vZ}FqaH+vP~N7} zv1qq{Tqy*DJ9>wAI4n^54T4*YrU`YpjTF_AF>SX;J*KaT-GTbO@B`7mSyJ9TeIA~TGc_IH z%=jJF>#=^@VOxZ6yF5TQHNEqnbAQANb%bwQs|EILU2CiaoZU^i)vLk8VDtrl&^*^@ zToIYs#J;0=llX{8KB?DFaYU@5v8>4io!I zU30i_a8^k9-v9wkASiZ(H{_d;*`CC24X*wJfkH$S*&-`2p8cR|@LWRR<(TK8@CQnP zTx`(n*Z`#NzJY7~wn!LfAcV}cU^rr*pNv0NF630Hf!?nj8nS)1##vItB=uu$U4sV6 zCqMM)D=!}*^g(rsVqILlOt-DQtBj%ZIH|xVPXRUupc$BK7t^OusDrp`%YiGFEtu+?v&sR z6+aLX>9O!u{P#^>FRFx=jvgMba)q%b3pr-({{mpL&U%Oe3e%sdU>q^-qSm|J=X#GX%a< zyK&5FJgD`^$y=NKF+Zy^iLd-mSD5LAS^451ij3afd*v-sVtJO!9A3HFfXFY0tkqIn zTj3ZT;~KZ;={13Y>$bgt#wHKmiH1CpPCA5 zm9owqEbLToufJ7*kv>_yH=c(!TP_-5zzv>NJ(UmWB3~gD3pa}*%Nm=ICCz0Iguyu! z@9s@{aAfS$bm*($wkl8wf9<_=y|}rG-N)|PdfQv?a3-Gbesgl9n|KUfq{TOz>ASKJ z@!^h<0Veaji-d`~ZM;zh<<*tw9cA!xqeojGCj?hZaxv zBQs_E#^xYuO%650-tb)O<2-w5I5R`@6P4d#8?a2Ep)H)#k*JfGV;^+a{gAG$a*}n5 zuH%48$ZP!jMb**3YSPVK%IO+zMp657_&65>;^oIMzu3?*z<-9YA1oTt>z+W1JFFW} zAdHXg`B*X^q2*c(xt4`e#W$dyqW-1tu^^VyAvR^(;^R6x-xZH_Tns6PKB4fp@S34}Gs4-?ps@XKd&~$@9xUldNs?493h))W#m<^s-O*ODU zg19;?0%t%d&m@GmhMYvIs39x0RgT!%E-{vLM##besp-Mw%f!Z%{OL!;rcBsECidcC zHKm-AD(}U>5!}iGZD4p8r?N|&2~O(9v2nKuZ>H&F(p7f0vsS~CCbCmMPU-^0$dCy- zCfl5Sj90%A`d@+ZM`T}7$0Nn7E3oB zJ?R> zOGHX)arDBOF^Z3(J(~9}STA$pbwRgn<5hSPH`ReC)@OoEG&#v;c!Ns0mHG{7<kDCcV9-#1Jnx)` zXNg_9<2Giah-cMo9ceGg2MmWPiIRmo_Eg(oWw`7&%JSpibwzAqwr$Ax$uAaxZC7q^ zzjVPyS40qy%}_o@9voC*JLVsaLIRNSf_IgI-*)c}5 zL=Y1QK7a-Y{s$0bgt*tg1x6Ky_1Z57XXwau2>}G)0bQdp@G^i-fu2P#MxtyWiRSbqO9hKv1Uva{lq?_MkKc!PXZzMBteK zUf+@^$RHL3JoOCw4BubGzv7~8z=T_+@q&yLnky?gW97yqDX%an$Vm|mA1gaeOm6F|TZgzJ zGqRsBQUBPd#?iT0uQ< z0K_`Lwt6pAN3ub*Ia!c{mgxh7q8Jfx`xf9cKk~{t2iA~od>cbmqW&55s+{mUTL~>@ zJVYfJvF!bZYw}hy|4W`ZZjC%^wh!|i2IzMl#@y&=lEtC%mPOVf4)8Zx=YE1CNC6<~ z+XLP~pMLl~L!_Alx&(^vyU)1essX+r+_ug2F`Wis8RuAFd;ok%okzH5fH&Yf#KXZy zY}6j(5G>`f2V{VqCW-vvLFM&$jrZ$^__e`;_JFu6^q^Sh)(q-{gKPf|%R6f)09|u0QMr3d*p5Az`3*URjzGs;n*uP8;F>7a39K zLg1G0l*2iBC2|){+3H5tljN47XpqM#8J;PV7&5|abA;xmgxuZ@+<##T9DE-27!lXq z=Li|4`?3itG;y6@1R4N`;l|V_bby5U7{J-*_`@H)xxCv7yAYt{uAtPcQq-}@`AgMu zOX49_@o&drbk(clP5Vieu~(jDH1e9rgt~<`iSp}(wsE?4DTNA~{oTFGqmSC>&Ie*r zSO1SSlUyjuv5-!i2g5rS?a+Hnxt#NIBHC9T<&RTp(yd-$(78B)r_A}M%%rEnj<43@ zvm7Q2aXDwHcQ@Tc{c$coL@1y*I)|=OdRPNB1{C^DE9Nhs5h!&za`^(Apqtu&7Gg5hgc`U7&^1g5uKe0+GUey7MI4}=gwP!v0^ z+(p3u;3`dlY?SQhi0|If`56+ZfYb5(; zXr?EmB_=kjI~Ftu7XWu%t%|!KsBUNn>=@);Umoe2!yh+Ic0Ch!+X2AV+}GQ|8lTq}eqRiMkR+X+0c5ZSjzs1*0FRkFtGQ_GTv{5yPz{^A$;ZbQ#3Ey)HMAAM?s5pD4+0I5H29q;aI%8TCqxqk|| zgr*Wf>tw9^8rNGs2B)!45DAa*&;tx?8P$xC6Oa)+6k%2fo<55jlCS&4qx3MTBTlw69o7)IOa`>E&F- zT>7YZBU>MB9wvkP9YvBd%3RQOorYANH` zUI`?;op|lzA)%iwpdyB{B>ZMu!?>QESQCPmC{(imEtv zxDv3i`}a2rjih5KoP`g4xeItJ7Ex*Z zU6_NNfv@r$Ge7={i@`rLlQrz=3{h2g2-dvrJ$hai$-fBx5%&WK|t{Lrf z$)DX>EmT&Iz;yA$HjFceCx}=p%D9Lm6yV_2zyLoLkfNJ^GzLqiLn9GW_fG{KoqF*| zCq`^yZZB<#{~k$oZfpN`^>@$@U_6fK*@vfVQyqJ)vW#=tV-#cnjjnzgWpemovPt+y z2Z};S5?RkY0YbT!GGWDe#JNx+U~uwxs<3i^RB3PUEr z8Xwq;t?W796axW_nT@Sv*^xypNpY-aTd7-zRO<6hIx!@gwbJSDGPbb`><3LgF{aZx z9g9W3G4uQHYHoD6yA@SNUTe73i zXro(}rGS)djJ8{&?jKSuY<2Z?53Y!~Svn22;o}r|NzO!-3po-(kvik+5zb-r6drKl z1~WHL(y5G6?^oK$AB06n<{fp5Lt6L1AFv89x!@r;b2Rh3;6mW@yw8MvyYqq7Y;?BC zvUHOp1|XaQh;;k*Gu{kJ@td8<{bKOa~g1N>izRNuoW}s z8C3XZr4^sfLD2tsfV~0xkP+U1Qkw?&`DPTeylws*VLs64&^nyM1cC2K$(fKLu=6U{ zZ-pj-BFZ)!3LOV?d~mmrQ7SLco*^Ne+kim%z&=lOlRzW>HE~~+q;s*Y6Mv{+{GBE^ z{u6(g`y6Ng1Vjm_`)FXR*$*IQJfb~u*egpReDRELgf>88I~1G@ZhPhMKn*f2XtZGO zURz0bpmwo%Wp>!!NP=_nAE2FU!=Ka z`C+KSg=aQbEJz%0>?%#L?KO^aJ0lnUpt}_NM0R$EO%(TAMEXfBL?QV*E^`W{86OL-M~1 z58*x9&1*E`j-rAJYn-(Fh4}#*w!PG4;s{mRvV@SU9}ukzL*I>3Q8!jPk%Ev8&*T>qxQJCi#w&NNo8}wB_^QSeClsUmpbDl z)gVPR7cq?qlP~Er9o`8#)dja}q|2p$@tB`Iz?FNEP`_&ix{Tir3|jh4iBtn_4nK-4 z^6}nYIE&hs>V%t5tUikm5BgqE&m+&dBJMECYHa4EI$y{#wt*#E?7DkH2ZCJ-PE;TX z!HOfp<(G-&uY&e`r|O@rJ%o0vds?p0Zmw@0sHGOITxEzqSt8`WOq!MUGt^dM221!y zAmu*bW*^wN_Ko~x!WyL5;50irNZGQ4F;oR!4D;SS-Inay?Cc(WOCw1|Jh4+{D8dh* z`;~!XTtfFFs)4|7a1=zy|NnL7+9nW$0{9^odN?(2;>;0&$f)KM|o z?VOafpcwZ(fpNCuzZl}+L56wUT)A^*9oWIIOyFScWctJ>psKf`uHk}ny!|222=EEO zA#Op4=Yq?xaD=`iPnsH(T5z)=eV7&U9+U*gK9p*aD&#;?eVC5p19EA5Igk{8QW1nu zQvC>BVsPnh6wjG4`IK!AE*cQ&a4h)mfeta~?~mN)rwXRHBZ8?SRI9fP=CpKXDC)0p zvz+?-LJG`-uqr^Yyy<(Ol6sB)vx<9m^r+(y`$sml!M6m@nqGLtNo6$|K(;gR@6YPc zG9=wATyQEITVSgkK38x|W`4z4BSG6dOXyEfRp|F!i0t45L2!aR5^!)7DdM}J@9#kb zh9V_Aou_MAll8q_j{ZnP0Fsd@DaFcHUFCl4H-awkHt=Pw*&j4_o0OtnYxhgKK-k^& zyblAPX__R+5N~IYEAX-4vbhE}hiILSqBDcp!Ng=Q*XTPD+c*uH){m1eR(LMD~0 zX&g=w9>v9KvGS)Ch353NX47&~T~+ScmB^|1Krn=**5 z7ZG(s&$xNOQTOI(?Zh>t*R}6mwaPBKk+oQJQrX$3H^RBSWNZ~1VA%9>e9_85==;Ni zeUi}+>Es3Zb@H!MMvgP)UMk1;4@|vXXr&+>NmpW=*`UFB8K@`_KvAEP={bM)v`@cL zAEdG^26arz)eC#-mDK2-F2`u4>lu#46;6#sbpYZTQOdBnWNAllj% zb-Qr;G@IbP=HE7V-2Qj+Eo1yC6mocvdmPsI7PkkC>BaLJ7`~miP^Xa94f>6&ObagS zPlGteBO-poC&v(#BQu0&{h{Tt@B?xCSO7@>JiQYfWQI=@gv2EM7jXkz) z+qP}nHuu=JvB$QpJLi7Act7_iyCNz&x}v*Fxw2L+n1k#e(F#Ha%!CN2Hq|c1^-}9< z>|_)-A3=PZTW#4o%GW7gawm_@k4XT7C=!%QE|$L)A$x?K^J|SiAUifLIL7oeH$?7t zi1Feg-J6t_n4I+6zWMlhTIEEUL3rUC(9cG`T|Zu-1J=)>-wQG#Pv@~1W&GrIKWsW6 zh40^1Jwjr+(RVXivM?$b89ufa&^Dx}+DcaO^)Sola|dPvLNVX!*e>GkP9;A~zdc}! zo%-AK;BxcuUr$yuiL}FU)CUD^viKhy9d3)fIo$jqeZvUw_VaOfqJ0B7ywpVNjy-$? zcf2s=Ab|dvlZ`F2>r!kgV;=y}WlKZ`NhcwN$s^JKxq$$$|FHvxI;*=!$dMJ}H6|r! zu7+5GzE$G8ZKv~eieAP&A6Jb-96q`!d6sDH=bX#Kj=O8cIE}(9d(=&QIh`HJjA|*( zdlhrhG2MpMchq#@77+BeTT1Wu+*!lA9dHGkxWR7a4q1Om%_=Ji?KS=j9pvO7Y{|65 zEcS5|H+h4v=lAWY;Wx&OzXA7lp}=6-^hO<$PLa~0fuhPk`If*eB%R;Xbjl-S4(kq< z+Z|#Sw0hlV{MEj5d~yoF$6^J<=O4El3W(n)#>MFmzq@!n?BaGyDc4CM_lLQeoDwq- z%2-*R3~ABj(7YvHuR;iidp~JF!EnCeH;$hS_vYal7OeGS8W3+q6d6eP*)=y?guny@ zQU8N(2n0pQs}wxt3fB)P2*B-35d@G`HtATkqhS3d2!u`I{&BRqUtO*^9h@0UqWG-Z z3h5_0D%Ci*tkxl4HN8?pjj`1EJ%!oUUed3_Khy2q0)MmefaW zLj?!u_kUV+Ru``$8-Q;D2EzdxoK@H1DEi*l>1*q61|Oou^YF8>PTHoX)Z%1QH8963 zrY$L6SY#`zQivLp=~0+OJ1#*2NIq5J24syRN!1+JoXx<-7KDPj?F4ncXaKHa)8vPW zLclK7KTe@CZT?17-mFKZi(x zU*GMJ%`zP1@L2H+{@*6xVF#qLdWD|6w8=VX>zR_|dz4UZkqD1C=$LE6jIux5xJgZp zL|Hm0&@~Ix{L+M7{vY`BUmq8{QC`)qfQ_53s9d-fC;MjaX~)0q~XHL0|~3@o=Th<^KqH= zJN*{ex#t?>UXmZa1ut)N2mDqhDdhzL!ZGDT6Y{t~W-o(meJ}ycdlUn6)5*>=5If48 zPl{DrwbciL0+y|X*G+up~JA!7two78gLc4&t?Ck@Q7Lk^WlwEx3^Bq}N-; zGeed3BV&m+Bph;7s4nB;j+9QlA^sN-xa(Nr+70t$smG zGHhHczR8Xc|K2l<{wx0M5&^a-2LcVL9$~(|Um?Og9iccp^eIgJzh7TgWbl%RxI4RG z29tbOnE!Rx02dB`k=1_}!i54T^7Id)D{B`32!H`7Lh|hZeC$KeCD0u3BLMH=qdeJt zydx<5#zDW0cmGo$tld7iyL+=Xcl%wWWejCS`%IJZfmspTsEokw=&z0zw^`=y*`~W2 z5$3iLCP2QAL=cd&uIE$Lm0 z_VOjCB5Kyz{NhM6FvmSUCCln$+`IHn_H8ECYIm3Ks2b^Dr!D^{Pg_rhpqnrc+mumB+8&<;JPp?#dZEE7(bl za6MI1tnnYnMri&68rO}}QUN=UKd!Vmv@+K@CWW!n2?CxzWL7x-m`yPLF8Dm`f3n4S z?7-i0=avOFDX}f<8pf&*d#tqgl z8rOmS;^lK~f_=ehg2ndv{9SG8z-VGHe&>Tayoq+5!veKK_f?VPzNZzbKe8d63!O&AqlE;s`xMV)A-b+_Xh={8!~u3@lDb4m|#u6X1ltZzn%(J1bW{wOE@U8jrUd> zBc4}Qi^}cN&0@6c->+AQ7gO~JnXY=I-Rzr`e9 z{(GgrC3FLkZ>-8mDiVr=tH#d~7;w~J(GJ8b4G%2M$}r{CFL)usyU@lL0B{9gOuDc;hE#C1w2Cv9QLY`N>$^KD9g>__nmTBr$HdWB^#{mj_M#+3rvbjmg z_wrq+cA(nFSn6SNh?c2zO*}YB!g!tt=PYsd5(I>2$Pk}TasR)kTqOvmbSGYI2&jk% zF2oAGza4E&@c1>k`q;uzTYqhLkzc)~Nd z5%4^*z92cx+~l|^^R*$=sKS?+!JG+povo`5@u^-eDc6rYa^$?zCA4S@0f z)8J-1DKjX5;hVxExE*lThdY-szpB9l2Wxo|3KaeaqXWNQ~!f1Tk4AmG|xi#g4CnX#(i&md$0T=f&O>SUHLp~ zS+sDfrqP!8Tr}39yposbS5ml)X8fTPs#&x$Z5OJ&Iq@`XU~BY(C&6X`u+{L{@!roD z=~t<(xI16VOUcBqmC>sKSkTN_MYG=%XotH54+b870&P&hBm_ms0SvXi?J)!y{4`Bb z=t*G@(|#`wfP|3L_rWhwss);+sE!%$93Xq-2L%)toTs`un)oi^-cEF7c*B!uul@B5 z;G;9y&|SQDJW9r1w{@UHDRxIC(+JP2X@co>Mx&|mQ&W{M(+wVM4ZuoRuF&jgpG&My zT+AD(+A%2b`(O~yAhJt6{PClDxt zK6+yiCMH~`VC&z&AV}e-D~toxj=pZZB^Fyf!rFCh+shFM(hvF90LzP=;3 zKk%aj*IB0ma^SE1q4>2>%;2782&#ny0E8gn3rJx%w-CP)c|j%-m9c^^8H1;=n6l(% zCx5JWCE<2>NP|!bromfuq~DnefrPGEHSQlf6DnwTJ_QaW+hadiAgq6od3a|Ka6i~@ zUyolD{?QMT_zm>~S`w@QFuxANfMEB5K8Q{sq0hX*D&(Tue6m?)ZITNgchbbtLGJ1B zUNQjDYE@?$!_}G)kP<5rWdN(*N2i3>0Z0QR!7}_cfGDJ80D&RQVEv`6F}(3HfI{oJ z`>tmYmT{-uRHO-2mg_(glI23m;fXtuz9TmB78A4f_ksI()BYhpBWsqMB`yupBKH~f zgs%h5*3@d&Ob-Es_~s+bHJ}bS=nqgD55D$MK5+JR&TctDTV!Ic;g&r-bea=hT^A3S zInIOq#SaR;!1=q@NvIJ46rwt#ux@%zD&wf~SM+y0rbWGQ(%BpEA93I!J5VK9A^rnJ zmcQ_;`Gbl9Qn{32hl{pNR(;&vD=0QCQmv%C8Rxq5w}y$8X3La!W#ptlg7><;l3F;LDV_|YWTj|PoV>bpWPUou;}YDc0v zwIXswiZ^{iSMXPiL!Ryw*jg@XqEI9-fWiP!P^YG)v4A0oUz@t>Wa6a(Z5^oA(>xabZHOAc;uZa|JgFC6rc zq1_Pdzdi>#bbA$V&_c8FhE!se(xbt>6N$u^9g6p-i1Z>RwUZbQlKRJ&?wM#J3fAvE z>&TLMO44?Iglit(&t)!kbCMVlfAArTgpx`1Qcz)ggv#+a?OrGU=^!kp79vwoXLMGIFO^cSM+Xt_bf$#IDiq zAFhM-lg@^e^1Vn^p2Tj;Zp)|Ljdf~Ha6d!W3)KwlnuSh>!>0yU(ZNnDvIR=BKv@A@ zmnUR%@`8F#Fo1-++vvuigl=Nj?8_0n0`wJPxF$jifhA!}_Iy$5ii6FSggMR{7!m^k zVAv}9o5>Ty!weB|66Li)>UEt3yGa+^1@L>Z@Nuk%WR?S;tNP$p%Ws3eS&rj4^1{Kw zA8ZJLWw^uS0UUbpD3qP(&%LTPI+LGlKfnb22_Qh`w?dR#crI1JMC9=pxkU8anACx2 z3mo0{SQN4oCMK38* z7oqZEhh>K08&p%px}CE`N@6UZ^}g9IqpFScwWFyN=#v3bVCz7@Li>>PA)Dr{oKq2AI3sd5YcC!Pt_9r%LWhZjyU{xXKre^E=n?Q4x#;!j*#rc8 zk)l9CW^Cd<5gwB9*L_J7d)xOB#q&cz@{)Q}h}mk!9`9QU1Q3K=0epRZ%oedbdQ-QO z?|cQ=EneU}xMQ^!)0xT*8%CW#OWq52xraU(+zb1OkMlBt5FU^*4Ln5zrfwk63658b zLM^**O-xE-hKFoxhA(pkH>>ji;50nI`wD(=#4gS}ApsQP1(aKc&f+S;Q3E1*N(-qh zS`YjZ!&lo-$6nFc=K!F_LM!N<5wP;)*)MC$8 z$QfTGceKfoGOOQ2YPHqBX!kVz&6ZJoLxW8)<`xWwaG13#81|%8^K&&?Cnp*a zFNcI>;Wtyc1AcINdwJ1k0~9+by{V^VJE0EuubHXid{uqGoZo-6qTJpgFpAheZ{r%V z57__!u!~kP-{MzRP2j&e3hK%%HT(R*W2l%^)2Avr2M_~hJZoy~4nwnLiRu0W3KO0dr}#$`XF1Auow*t?ev`WN>YST-tB1 z0Sm&{E$Z(p{XpSq4U$J{0)b22s`8QF)YR` zdvIs!Sp}>k!};2V97-V37{a8Gy^&OCr8lr?xgM{~dQL6QTjOv2da>8RZiPuS)Oa^>w5a?!-xSi)Zv{ zMuRVEt|7Unmx{U6i zyl4yWKi5Ula~4SHnWRo=Y9qB+{9O7hpDCnZKjBr_P4_O0=jD=SmWpPRJ{DW7S3CJB z@B8KO;;?=ch%q|0w;}b{Gz>JBKU53eN-U6(d(u~ZEY90P$|Pw}ZPsD1%AF0$oBta+ z&O?A~3V0hi>-9{6Zk!o(%Cuc--2p`N8v(VA$MOR;>$Gb=!fn%kl^p=@=0Y)h;2 zVPVBEypSAm{{OnH|L3*XN-QHlM-KoH9uEw_1b_n|Vq$7xYvF8RXX`}&f2UIWzuXls zb)?d=I2N~O>u!&EyVHY=yocAl$$ccqZb)*9?d-U)@c{=2`*#6c7rrj|0ekFQNC^=v zlZLY`oRHy5DizNvsCMpH7#0f*HcIWdTG_RPSA~BbIu63Zc$^xVcP}Ansxx?!el!K} zPy4{@e$JhxyI3Sz`3h|Mo>$-4&eC&PL9gX( zhCw^ahvgn;O7Y{^zIMVNJ1yqA@toGmz`DYW#?T3yeaJ~US8bj`ylVmTWpiIIUd*sQ z`f*>+&VXxRbhMN~_IPoihKWXoId8e;1;)bZ)jdI}%#f;|uEcj@ypX=YX z0$U@Ih4B4{v)YGLUK%n)>>>I2GF?H}EQHW?bIjymyWe+w`1hhZ(M+`08je2bMV8m` zWAhkAe=`<;i``fC@?<(9i=N9p9_Qe=BH;rra5;m2x^*;Y6BMZN!yw3Z zn}DnPbj{V1^SbMTCP4%&aBB;$w3DqP~ z69pso5lcb<7Z&z{IxcKH88C10c&V^O{#npB#$%{H&$dplQo31??Tz(|Q^2uM`jxE2 zX;KHunSiG6P!BzRqXki=k4IP2I4dP2ltJORynS;joXk`g~qU(Nxwje zduLNC{x#r6$3f4vHZ6c6tt$C@=Wa8$x!^9Sra~-m0?!#S63vBYi+n*AkHZj7!tO>cM?=i=v%#F-Aj zV^V5F^^T{9hnKHv9>1F&p9h!KC>zP?dbWo zL-Ah=AAFq@Pju`T@TmMawcIygGPY78P0y_TenQTsfqeKbrmatBrFp@UmN=CTd3W_; zrKuIC<(kY!Lz_TfgSL^jU?QG%ktF#c3Yr-!A@W}GYD*sE*wfV57lz9&IDZaf&^;l+NI-aaS$Zeq}Tw|l^={GvZby!!1?KRu2K6w1fWC}d^@BDP9@IN+!3Z6fXz3eRATndS-*uhc(XzJt^P=7c;_&E3S>19Yp zUju9+tEKi&RWFIKKi`hO2D3V=hA<%)u``NdjhyE$rh`^DVMe61kQel9slO3VZ~82C0k^5pwk^@@T86VgZld8bMqR{%U2BOVtR3s~i<-k=2Rqek zlmp%Wb$zyE?Scq9K++u6%k)2+AO{#rBNA;z&{{5|Yw zVD|Pk&djRs!t;PxXeK5}46rIDHZ2O!cD%;NaMc&Su{XPeJ6i|qV)Iuh(Qx>RknhyB z+prtkit!XZ?}nRiAy9!}k~v6VbU~E4U&F(|nDe&pey)4!A3FFJ0bXzJ)=pF)(`4)Bi_$f~Vg0i8?kCzK$`&PuL%zTWMiH}m;{ z064k}n;H1th^%u^WWh}BKjH(*slsl_4~-qOvD&csc?UF18$Wx|X06AlimNs|?cP@K zt*uhHQB6)ukPR({|N`J0(_~&{iz$k)1 zTzxDmYq3RDDP)g`bERULR%{~&)<%F0w_>f=GlYNXlDq7_;D({fuIELBgw>LTYCQfk zkTYn4+FRQ~2^!IGgp&m*4F!p&HQ zxFFm66T!N70%J@52-l;PUT^`%q>Ow2sZ#P1=7$uH8!z(87Sa_vS1)6RKSgG9Tm=TA z@-)6vH@*9%zYNSJ1~lAVXcNWshvby+6%m`pfNYCgNCQ)zHg6B-9HQ0ShYRM6A>%6S zGbYU&NLv*SdJm~!JKX=&*v=VYuiL-j(gkYA*dj=fZuR<(5>_VRI53X22^wPrbaL~b zb*6!~$+8mVHXIVp7u#Z?RkHrIV1j0k2~`nC#j_St4=ehl|Y?YRaK|uh~(xTMqc9|!CVf{@k&Ny zS{wCF1CT_2-nwp~*2raupzkG46^u;d1>&`s#rv>OsGQQhCKybw#px!4eH!(Ivz>JR z4yJPw+cej0ye7v-q{a}|s8lL|RQ>7GC`w*KMd9Mk<*)N6A<_yRbtt?Lju%rxvf-vN zdkmJ$>b5D?U^9$#$NtQ(Bu;8bswUniwHfhD&jUX zxTyK#CST?|XonA^n~Ax@PTSF}UBfs*;ecc(K!5eJELDwtV|lT%E-5Z6G!T z&*v-uCWlZ+#-^nnz}xUlX9|jQb6K<9A)Sv0_HsHt5>@=0s4EzankZq8)}LgZ2pu6M zEQ2;@)B29w?oT%z>xp@;E4&0zH~mO-QVCm2)+? z+1m4t$q!5ZgAUaG`nJaoBwA(D>2rD6zZOTZ#$vjE6~imrEI{s)?2A4vKrsVtVYe8?WiZtLLU^ES?28eF$Jr=Ljx-_>K0i| zl7^M6wJ?e|ybynvOG<1F#`=5`mSN{xHHwt9=pDgvo~PvetIVe(-P4ONbq(K;(-$W@ z>6*J^L#@3bf;7_s-Jef}!CJxY{Vtt&vPX4Dbl{q{Omu0~Mw69ET5clag8R@XKdIuY z@Ht*Gw?~dXwG7pmtajwOsx7uQQviqS5yQq=K~~t5H!4KgEx2^$QtPCM3J37N6Tyba zwJH>&>^{V%wG3|>!~SF$gVPj%SaLn6Q+YG^Ts`mlliS0V(TOwe$d)Q}t}9xA56LV)e>OlTxK!%#o>ZxO?P8TcM1)zg{9{m|O}0MU~QtF@Na z)C$Eq>3YE>oWHO}N&S&XGQKWqu1a%vkQ}`uR?8Bq_h{ej1jK)74pOpmY|JSAuZV!U!H`Dz(Yb$jy*Xu6!-D)Vq^Zp~0o1CEZfS+(d1WF=QRyCo&%LZ7B845wG27?tTT3KdpQW$K zsqi#rRn?~L3S=JFl5CRGwgXes&-{_JS6Tj~z%Wl=BvS4agCXZaL^z4UX+1f@aEP2U zV2g|I>23f^W$@13)BdgmP9#B3gBjv=Tb?iC<3Xn|OnSbYNP4bf9p%$icLyCoayv0Y zD1k+%Wb$R4rX`wEj3rxwUUUo1TtjGnnX}X3y4sq=<&Z8nJ45`>I65>Z^nzwU?-?)W z%&P&3m$Sr&s(LEPd^ZA=KM5??0muJAn_ z5ui|G1ZYSs?~^IWo5q|((sJpNz2j;dRpsywGF!N)XZ5qa zWF5;t!${@DUJB~^MwTQcYvVyQYlkrgdH`z&j4JJZ)z04;u&~mwN7hN8a%Fx`+yO!7 zcM1ej?GwIpXI}yi*$U3Q$qS#8FrSnqg=KG%A!u+{9%xBGD3}-QxalOAV-tYieWXJz zk8nfo#2`s89|KXp)9E04P$+6ZGs@5}aphrFXQbCL-p@{1oezK?;7!AEre}UJ`F9&! z48YceiqnhZx`Dfoq=o6t`#I7qL`;n#hI?l-=2^*TUWO&wV8oyOJdx4^Qy8yVToC;) z(@>vBs?l0pM#x{t<(j+A*9Xd2vE{)px$Sxp2eI4888hIChl5>|jC`8P;cxZ)?9&G^t+NRXQx*rG z)QD3?T^^m7WnqIWk%}Qo(19(M=`Stg*b`1J>>_SF`hwA zpiC?0CKIP(Un&7s*JmShmxUV#EaULe?5*vyF_)B~VGbG%n7jG0e*GvYyLO?mY)wtx zVwCYPO9iNNB{1+J9N)D3-%rbOa%jyc#Bqema#rFDI>Ag%#Eeop_KDi?Ckak#(gs^* z5{P=fcwgO9xB6Xf=GibJxuZ$bkU4v@S1?qOF&ILrBV?A@Tq`0yxXsQz$ckwbuOzA= zB)0Eh(p0pARuKD$^3^-zMJ5}u%stV&3TqvdPR_*DO*YfPAdaK3zeO+?611;;y zHve*R^$=R@l0cdsV8W2rA6vA8NGjim&WjPo@idOdUpj9C#^dj;#d?AxmB^4s z#=U(|qT^W3Hj512$`M)-wr(d9O>=Ck4!WAhj?hra(+X@tqF18K(^y%0&Q*XHu7QS; z5y}pdwy^A+vM_jJ(Q%}0tAnz$24bpnJ^3aQXwR{R<2`#9AdXVD(-9`fRB>#vG6`mH zjuYK11hm*$>Eujt6}Gy%7U9E1E4Tg}X#}*@jwQHs*T7nZTcD98%~hd(%98t516Ywx>B-@6guAe0-E zs8N7YE|1kB`}V$u(R22+{c_TcrgimLP$Sjwa8Et4>isPdYc1x~%{F=EZd}A<@j(3U z;Tu0!V6ek-#@Na0IyYT2hJw+`%snIW0ozopnuyq{CnVZn>5|$L8K=Zw7^OM`rsr0k z>`brc^@>tBQohy8(r#6#*`A36wha!Nv%Bc3aJ&&!Ave3?Sx7Ph;EKyIdIO2%0hWvt< zr%z}STCZaW9k3VJibHnhU7J6)%cjZPd;Pb|u!lkpR+JLYu}6w`T9bsC7nxnmKZG7r zHe*^b-i?F)#%t>NzuE@Y|G^Ej$TJ~}LZGu)xaJE5DX9;yeUp3$Ay-VIL68| zB%P;a&!4ECgu>=pYJ{&v<1(F=l|kBJG~%6|Y*3K3$Q|u&Odq#w?sBrz2;2*>@l;i! zh;OxHm3=zWwk05zyBJatn%A{j)`3uWqO51tH)r~97fI&{ge|dvvl*&+DiXYY`MZtm zx5tGpjdS60Iwh8#=MfmdfVu9|H@)L7!8bGyI0U6H;p76M?7~_6#9I?69|6ld2NSa8 ziu6~(##X9Lpb=11o!RW(C3!cFdTTswGe(wvr2K$}-0BK+3L-qr7S#I9j77t7dNXYw zH;DZQ{(h#`aW)z=u3bii48_Pni8*AW#eibphBIj5UAPzFrwCA|aPdeE0~9qpkUH2) z;}JAcHhu zF@5$L#tnB zQ?z>Z&Hj2t_<9BS^{kJ*bv-bzhL-)r%-8oE-;Dfb9v#blQ&?v@xZALG8nFd_VB~&( zJhjUw$e#J7reh~7@DsA)63)J*e}D73tqZ&g((32;^L_6Ej`aur8Ab<7t~r54xwMf5 zm%>K^UrtQPhbc8|(Dys0@Pb?kqR+fsVngIwY7h@YYC<_jvO9neBl<(hV*~q0?*~AK zJ~@f`jpipB`cSO^60;;!EDrnW&xSqE9El5rv4uHIKrmRo_&G%PU^)H8xp9>Bb~GeZ zY)#BMSeLp>gRV8m<{+9pVWv=s_=z@>&r21*l)l%UG~^;Txb7deqH*)-0b8&L#$aYM zG)d`CA|}BUB`i;J%%F|oW_Jp8Aub?f;rX&mkRv>##(8rZnXn0YEdKNDqP@yUn37x| za)i@R#`CyJ#08d_7*qvRUMqf8Tsqnl3&cYSD>{)4PjdY3cM()Cadjf-!-8t8dw~U1 z4lE$yS{IbV{=E*_Eg~`g;+PumR5O81RVv-*vhMF)Dt6Ws>W(y4yd3jjKE})BSc=_ayOrnSVn{U>#N`B#_!eP@>Pcbt zAdeLw$pL}N^hk^*EFyjr?*j8NzH+&;8WVTs449OSG%;S?l!*tF$x96dlE5BNgxN4I zTk%#3-IiOGt6BvnA!l_1*72a~bn`-{52kEDR;lFnc+P_{amA1SYK!PA14!j%CZmOu znPDq$NT`o^T;0k$Mvb~0TmKq$B+3)*2EGubvzL4k8T;%(t38qONsc4ldN`mhs5^py z(ED<9Uz^_xTYf}drmXW|J3Uu;M7XF!g1sgsd}4ZwG>__tc&+KhaC|gflG8j16lR!l zT-)uQ&y`4h0gaxYLZB*l-5 zX*rlL>grAf?kT}-PmDXcohZ3793M5JCs8krjIU-@=V_ZsBS|)JogG$%3&X}qDv$i+ zM*Pqyadfcwq^SfqgjOiM!i^xgq}$HE^=rQd0{NbZp*Qekwk!Fg*ysaWue;IoG$1lM z7X3-%{&?&=$Lf#fCx8E)<yZc+O4v#hgjd&q(GS=2v+&N{*Sr;X88ZSV+F|Ht>LvXK-oktw#gISx!4u~;O* z1BCg9`dXcI%3rwmY=iZ<{-MqaOtFQNf3j;fTIUv@lh|h0}A2sX)Bo zElU^bJL_TdkEpL=4-?VV9ThxRa)HD>W z&su3p77J0?yVW4L04|C29ryl>LUCZ8Fn=!au|s)8@Fu#ET~uRo_Or(;%s0j>>FkzYQ`3Q%p zVIuh$V<`wAXVsyx5wyAjt9E+CoBX;_5R zwc7I}i?b`dHGqQ&G(IwmLGJ$E8(G=qBj~p=GybsL^DDPTOr3s$vx^ttn>QzXqK8!{ z2w^Y|{SA_m07TOhHr`=Z!+@E-+EJ0>ScZ+=ZS!~vq>Z6MD#T%JqIy|~IpBp1NHcR} zX5Cg4LralEv3(boQS?^?^{6#ZZ|=T^4bpMhQ0h1@=H6GP+H(cZl-#5LTt0 zz`wIv1@O>25U#hVhZ<3jg&ETlF|}LZ~-a?@@yy}AE>&E*5>9{4iio}RH8({XL{}nR(3U_pz7voQ^_t?xTOEA zv!rXUS{az!Iz?cegHalPW z>b#c79(wL*5(^BPR1BNv3C#d$JkB1nblNN(C8EX3E4*>a6?zYxg&>vb6S8*br~( z;3hAw7f(-aw#|?t^I-wF$%kS;6uyrfhV!V(wD>`bnujo~pQ@ygNiz&}+FsC0Kwjbk zq6krWO_?Y~mIhfcBDKun_dMU%YuW6Mo(mOy*$KSa%~tT+a~^+gp6)jsEDKl&K0*_T za|%@wT!e}GJIn=&bOVkt?>~jw#C24))4@@>f>_otnZmU@ma)tZbsTFHZhH6=I&Q$* znDnJ|WyUlM^^UU^VKT%++(cQ2i+qp!y+xPeum8PJsJT0CWTr>mR3D3=r{f(fI;c#_ zqxaVsknIJ7?%svV>Qacs>`fVB57!9si6{<`3_D+`l?_@im4=PwzXGLDnx11 z0vkcncUlPpdG^cojtnR<^UFhvEeqV9tk6Q_mKXMo)x%ykLA15{p;Da9DxtC)7|*%+ zP%q|Z0kXy-4Q9$(D3MqJE$uS^j#3m!Gs^jr*KZ?OQ&)^aJ%G`#Qnu{Iu?1cIo{!F( zm@m|aY1W%REvJDKjmms5uINJ;>DwIB0`;Sr0L)?iG*uP-W68b2z~La-s#834&WXmd6!X&Ci@?-EI7+}l%O35;hB_UOIRDJhmFXBVHc{-|`U0dW_ zs3@gbt7j(~$s_ZUfS0-a%6u{%>4sJ%?Tsw(C7lw8!9}Ql?kXUp2F{-!?0Tb2{{|yL zC1oaY$%1C<)Y0XZ^^VtJT(@)s*+O|fzpoSQ-={Kuay3|>Wo#C;W)`~Kry8i}4j?({ z0%EIPyTLEmZ&Fs{tB)~m_%1hg`$ltCoz+fl_8v=BF6#eFqiVncm%+YDHj4r zy_hD~O)|jst}fiO^aByxauWchr7j!qvnNd@@$9?-liWs#hY4V>aR*1mUchPalcN|S zZ$45kfSiEac#12{`r=j}_cLong8v$}#LugC;B1n!OA?O7>^}(w zWVM+-H5MZX&-76)0vh?VeNR7lsyhKDV=!}j#q!&ExXvpY*0JGo$)w}5yWy=wG_0N9 z!}S`h2zXrAZrTuPcr=-71;)Fy%+AQPuO-nI?%@yu8jC?59781+VH$;hd zGi>?M4J+|-8v+Io0_{)!@pzS+v?_KZSd20BgJus# zc`sg3>a3zd{;L}sgdJtuMqb<<09W9q5z-iEW2L_NVuz>42a`*#)jvVsHT5s!qY`XL z+$OYie_5xQQEr2{Bmm>i-OT{e67d=d3V$NG@Ykg~2pku#0B9L3g?J+9s^WMncl)?3 z4Y>=>GD^ALo0v?r^NMCCTw=bTB^Ca?ntP%G2N<4gpu4})t7H^g8wfTp6T2i_M2jR= z)@${5tsm{9iw5yIo6#wc@Mkpco$c93rt!souyBTj(ExJ;8e$93ZiLAzpcqi&rKU` zP&fX;lr?~1ue9)wBao6S9}Sr4t;9E@ z8U}|o5~z^1LX~h-)QA$gzyzzfwoW`D-608)lzh9y1!{v7q6>kF`>0;dYt^MQXQ*V= ziGA*N-gFB^aJhNEv=O6FB28N6&n$$It9p|fT3AdSP@iJ0JMg%{%2`zENCm}yVJB> z5^$*2KYXm2A=-p&-N;hNQYu9mQAl=4DKle~jKR!Mc11{KyP_M>{b#)?k&;{#DN&Xz z>DtQDMP-XplK(e{apz3j?%Zz8^UV3p%yZ7X@9+IB=bP_)&KcXvG6ChV`Gv!2ah1)z z-38jQtt+%S94kZ*_PW}w_#=z7!ocdOmx!;$(#KIXDz#4LN)17Qlrp}JFLPUkc3K{> zDmrS}dGc!MovNF$7i}_$g(;dA0xF+!ISTQkAG?-^+)8_XZ~lYn;^D$i$E z^D5cTxN=JlyjQNCD4t#Xv$~JQw%`QS%)%?WjaxJFYM10Mds#p9$g?OY!olADtYfY7aO0a}PHSMDB5XUtgQ*r;s?@-{zO0F5+P( zdwK1UU_q%D!9h%gwBt|PCXbf-#+bO?KP)fB=i5lB8G4hdTpJ9Gop4cwF-13w9NdlY zW6!V4G`?wS`pjj|YkcTNblxFLz3kS&(cL9SEW)iH5%c5MTJ#Jz-WozZTl*P3P_A!~ z7GJX3=AQN|pP<;s^%W>P6`PMmM3d@b)!p|{xPp1FTbQ%yUNQrHgH@SF_v%Y%CZndgy1zw{I?S}@JnS7Fy zuU_#+A>&#Tbm(l=T28Ii_XhuTb^fr^pSv!rY=RV%_xSo@S?dw2>(`Bc*%qGlTI1oH zJ*}tG-P)aPtJC#XvyHj6m!C7#_Lw-8f!C3&8)S1y`t{_MzOCes!UG51zCSxI7}mB{ zu^^^DS1sm+VQI@F0clAsTT1n&NU_O94tYOqepNg#)KkIo%8|!zy~j*X;WU+1GJoBh z8lqLew|!v4O3YZ9OZ|XV*7D%m363hcgH`VqUp%Gw?6Aq;qg!W-_8o0cvwPrMi^|-P z(EaOZt=@@%30~>6w=KEX+nP63gzP_~qdBy0(!E98DtKQ!$@)Z`&46&SKvL>zm7W#_ zP2F-EU0=;^C@@q?V))%==XZ~ALA^Sm9>>V9Rr#Ls$A=Y$Z`e^>8uO;1RQuymYl@O+ zl)J1BhQ0ruf?j-d)Vho#+P@82pdb7kCKSVC{ix)rgm4e9*h!(&wpr4OJ~G=!yyW8o zd^9%kZ?XOTVftVg+L(M&&e=cw!2{xGf*{GbZ-q9gC|Gj8u=%=mUXB(EdPDO3Ete-p z3O4oGk}+y>0wdv7!M`_)7+y0{E9j@(y{RyaPcFAJR5Ba7XJNWHxrFbxn?|YDx%u}D z{H`WCslH2Hlf%9_t+(@B)n2mddPH}xEY zHREW(O*edhrkzuJQtoGW8;8c8bR&8@FU(n11$r(2yaR?^Eu`dqRb_2bjz6O#7Fa~f z8e7|;EcQAavpFaqSGje+(jo^fr%O#7s`|eO<}PllIDU9LWtGsNnOJ24JC}U-k)p}Z z+tKgl`-JuG(m23_P1&E{g2}kwSzVD@QnuWd^X?{cv_voeUGK8bp%l$REx$4Qxawou z43;i!_(&Vd7hM-Cc6#onC!zM_s?H-L476m(d}Qc-XXSwo+YU5Gj-|tvwh``o7!gj( zF>|LRj9m&TsfKs;=-r_+;<)k)f8I7bja_!lrV)z?lWgy<>j;01mdY)1*tNIdc%H{L zg`yfy&pQ88PW?4?3ljaq$AT}Sv$~$S^))011=NMlGgJ?hNsib@*~S(iIV{t2dWDg& z-(pFny0>|i%^ybJ$|w>hsdha&E6bi9*Y7YMd>fb-_wnRUX_^NQj|b{^3DkUWPI=9p zbB9|dr@xeJkCG9|k*(_$JFooaiixTDInJCqNsYUwdTTR1aCi7`3#z?;5#OlOF-ED4 zi%x&dPMa*q>EDYzAU#|w&@i!ub8EQTa8K2f)&Trf%A+$VzYsId=aF@xL3N@W17mI@ z9DExWL>}5Kx9WD|v4_v@S2XH3>)G0^u@lu4KiHCOLP{(7MWVr$%P2ct9ES?#t<)E6 z4^$Ab2`~)9<^|jD927o1u}W`l2N&Yv{Vx&d4v01^D3qIw>gy`lO!DGC(R8+{$ zQ%l#^1v$8#_^FdSs*5{_zrRrYhHLjS#Q7$|Pj1G(=7L;|3V8awp|;GfjWP3X zjR)8!T`0X=V$CO+WD}qnOdRjpc5)t+q}&xVa->INJSQ^$JcfUVLO!!<3;hcBJp zYpQOo8VUK7L}vI1LB`uS+lx6|)?VW{*J1E5hjfl-6SY8llg)-4C~nwZywF})sX0Hz zhMTA86L*5KFdu5o_|M*z$A4)WbUWB-;3iR#+~j*l|MI7r4-uV@yZucJIXIVqzcYuR z%so0r@Qdk<0I(Lu<~rJnMg%I>9!tfpq3_HCIiJxsl0`kpj|4m21W%DKcZQEuat6m5 zg=?crlo#l}->9pke5KW4H(nR5cP-_)>ivc64|An;RPxqWDou6{dA`Lz(QJuQ+~>R1 zTA5HB9c@cli9njb%dkR z6%yJ>sMyq2Hhc@lmuSF;5f(Mok8?hZQ(WY=QV(~o(rRO8MDtnTUF z5|cJ)fp^=$69q|wE$tBiZy^Xz!IEJ&(9m-DBQ|g^4`^IZ?ChR;wswl}$e_(%miE;W z9B6ny+NBQD-vJvw+Hvq>0W_&i0IwJ?e6Y0Of;i9xVz%x_c_B7V+J5kcnQZWt1RW`M z2;M~$LH07!H)2U77b+IMtb%sU#BB7l>f>Shbju8O-g~GZ4$vU-(LyXuBLyA-;5m;2 zNgqq5IyzwSRLWdXYX*LWq3D(wDmyMTn=lW8Vx%B&NeClU1Nf9tDLmE{i*qD`3q}ZY zquC`-p-o$6v~XNoRJJGt{ayuuL|{atg1l!$qb2@aKKaK-!6zv-Szl(u!=$08rkp0!>pFlw5L70{yaI932IF2MLfehj_w{lsi zbQp_n8L>#9>N$DF^W_vFC~}Mq5=3BStwmyyT=$08NakRP9i5r4igdj*9fppvfi9{w4 zr^@M&y=Bhf?E zgNP+j+;KBe^iWl#5}aKDEyA2Ry2S|Q<3DYg`B(=jQ&s_?kAU1!LhvEE&cR3bD3wHT zr;=Src-ODuuh~e1@#&TsKdfYR)+I{_no#70G!gh+)H(1C2qcoH6_tX+TLC?+NDeb3 z6lau~OO6O@PnZtf(&$KVOq~m84Lgf0e|5wPG=@e_NNu`dvw?m$d90&?WjZtxa9>Bw z-q#s{mFExIqyVJDppFd?z&b0~5FLq3n9d7W2M?MKw7l>jIq0}JySh^eyJ&^CgMg)) zQC*EFc~+nJ3EdI zYL_trflcQv!L_VVCWwG1A_B4M-<7qIBZb8PxLmY@13KjO5GrNKM=Rp5)M)aS0+aKr%E7}JrTJVGd?c;#< z9tiF22;Yw~>xtj)V+l)7x6IPZ;WJBHf%G9jdLlx4AIBf(2P?`ei3jfsn>FhvUH@yw z-_-O6$~9o=>6Tggj}v3^H0i(0dI|R*=m;y?J9!U_%%1iC^Z9<1S@q!t^MhG%O^c%fUmKaZu=UE&}*f z3UsPaX4Yxd?Qf>XicV`~+-gFBPDQn}nFq!hsggRDh|tCcEQ%DNeFzqbZka`rs_q?H z2}Ckn$p&pjBvVfNw{c@dq1W>dQ=@@G2fk3q^aHCbSWTnJ1T|P8x@A^qYzNwww)}D$ z%*r4YGUQ_an|Y%ze*J^!A-S=lkmcn=#VX)T4AxH|1w;;&NzB1w*VGgui9ns1KcFGb zwoFm|YBQ_>-O@B*{Pm&1sr+;+n8PdwBQQk-`qmYHkM8P1{yMy*ye|w-x6JTp4WB?; zFs1tdO!dnk;45X2@a6=(JK2%yNp>d^C|`B^KpzgqrCVlP$`Zbop`8$9y^^w(Iwu_<008)X3GmmdCnFSnxsVP;w4;s literal 0 HcmV?d00001 diff --git a/vid-app-common/src/main/resources/service-MsoExampleService-csar.zip b/vid-app-common/src/test/resources/csars/service-MsoExampleService-csar.zip similarity index 100% rename from vid-app-common/src/main/resources/service-MsoExampleService-csar.zip rename to vid-app-common/src/test/resources/csars/service-MsoExampleService-csar.zip diff --git a/vid-app-common/src/main/resources/service-ServicecontainerContainsPprobe.zip b/vid-app-common/src/test/resources/csars/service-ServicecontainerContainsPprobe.zip similarity index 76% rename from vid-app-common/src/main/resources/service-ServicecontainerContainsPprobe.zip rename to vid-app-common/src/test/resources/csars/service-ServicecontainerContainsPprobe.zip index fc74ba06062c8aa8be037d88b48015f9bc89747b..86b784b2ccd62e0d5631956b8e2bb9f9618ab92f 100644 GIT binary patch delta 4928 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 delta 5856 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 diff --git a/vid-app-common/src/main/resources/service-Servicecontainermultiplepprobes-csar.zip b/vid-app-common/src/test/resources/csars/service-Servicecontainermultiplepprobes-csar.zip similarity index 76% rename from vid-app-common/src/main/resources/service-Servicecontainermultiplepprobes-csar.zip rename to vid-app-common/src/test/resources/csars/service-Servicecontainermultiplepprobes-csar.zip index e0a5331018997eeb392d0b3736ad3fa581f6c156..7882b641d4b4a5a7355b6edc231661d54c2c3067 100644 GIT binary patch delta 4818 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 Sgc?8%U?Tzm8vTDY$NvCMo>6W9 diff --git a/vid-app-common/src/test/resources/csars/service-VdorotheaSrv-csar.zip b/vid-app-common/src/test/resources/csars/service-VdorotheaSrv-csar.zip new file mode 100644 index 0000000000000000000000000000000000000000..5c5ee0fd6035021fca3f8037d77b3ba52cc7c902 GIT binary patch literal 67068 zcmZ6xLzE^=6RrD}ZQHhOyQ`|pwr$(CZQHhO+paG2e&^iLe+IEujxr~)c0}&|{E-0x zMFjvLApuH;KC*SWd7Nwj06_G=g8HwFoD3Z4ZA_dEU|bzm;T{lNU6-Hb=%kiirlzG< z;AH5iXQ$_ylo*#;_Mt;*?4{(Url)9uCQ(U})d490z@PuQ+plMAJOLB{z=j0?u>Q{* zCZ-m)7S0xSwoVKNj?NaQ21d?K^d2_WJ*skcI9#wjXKIMI21bNA*01S&9eV0UT4qRH zRG!SoSeqn&N#w}nwm0vrymP-Xt$3Hc&i^WLg7gF0Ds$4QE)b zR3Zd|P6BN=AZ}>C6~E-q4jHjzlP>bY=euIDSCU*3I{P6DKx|qJ4(G_)5}HdE*=iOh zQ)RvIu98h5l?aE!h=R97!R)|((eqlze2Wh^P~J-OxJO?uA07MlFsKXYviEc{ud(R& zruDitY4!NP4xLYP*l>Y8ewHobG&%Sx(EX)bfMknaj(IC`%+?E0`n~FkTDxGNZE;>F zSqlGhi`H@I@ETYJhZV-*^`|wmX3$ymX3ziIaO~|CjDG#MqPKRZ`sC~C#G+MwT9@kV zBf?ON!Ejdf{tTR_yJYi&wM6JKk6_2FctH(d8L2Z9v|W2CrIyFYIU8m~S^oVpyYJD>)UMqzJoF0UISV zEc=rY$!F}8!<$(BUG)#IXw^pgSb0^u&!-cZ>)#B)4{;sL_$^v6&nU4-)%o|EEh@5+ z68_ybNqAOj=>UmIZhv9ZR5415A$M5s*iL|)O|W63QWg^q22VLf{g|$hu2yEPwC8A} zQe!aH6Om(5KW;E5y=n6Peo`%3Mv7wkkh~1q@k=yxvj<5upp%dbb!C5e?*gFum<>l# z_$$UXBnitXF|jtO7H9yS8Fb}6ae&1AQx?aD{S1?w&2lpJ_IEhw3c5Hd))n%lJ|Kqdercd6oC? zN@B~=5z!9II89-HNJfUp7k%_yIO*yXvJ7jZyQy~kIhr+R4?lnVoBY? zaGvxjBr1o9XVtb=9KB)`hGM*uWeAND3-G?j_a0ypNo33{ z3U>-skW=sfgUUkp7Rh}gJy^F3;cf>;A5}4>=Su=7lOi;oN|+KrE2cD{obC|d&j3UY z-X1JC60t7}4hdtMo1GyXAwk`XLA|`pm}p9xH{YhA1E1dEF41^!?u{EgmEwE zIAFFEsx&nnU`#aOr8f3hw`?H zAG7%_b>|BkgyanVZELrP^K`K#VgA}Tbl2nC1}51{%<`6K9+fBPcqIW_vosnG2VhA7 zkw$@ii-u@sz%ro~4qwJ?DZUX5KCjoP{>Je$1LmW$S=@%9hR8hBZ9+>A%w0l-u}$mKBpXjoq<5pjf~#y- zoZO%cASw+wjc{-!4>o7Ublc3A0&u4=r^hqv3;R39PKK05cQ=rWh6QELO~`1DY{j(2 z6i7xYsv=$o&bQInx)toyR@Mo7w8D}^Flh@9PsJ)r?IM*kE_RN0%re?LwI z-q8>4#HK?zMmLo$R*!*jz7|KpR91EXOJ^uD*f+F~QJ{MWF<>W4bm^R};j6~?W%TYQNmP@a z2{tUHHtlG@_Iay1m8KUl^f_iP~hRqvR( zY8f4#k1XeS-}(LEA=M4C(#vTchI(&@0xos~TExPu-x7Vp5pe-@U?0Y>n}~3<#(`fN zL}6QgVPgR%krRxRG8bMoM%+#d z22Cwsi6RgBR-@RQVvp*{_GTAuSte}St-*}SEIF3}0zjTBPULvwhRC+<>UtZ%v z96{L7fVtyd&-!0q;ONbg+K5y0(FXYAaQJm&u@~!B&cc)3+40Y}!D}s57;cShD9cx; zk8Lpnbr}8zTH#M~aC6{0?Y#|@xa3`LlnszB3^81M^?uYj@KR0X$jhKNp^7 z^|##EBSXsari|Y~<9ttpK_j;@+I$PN?^Ivbkmm{~$8pjO>F^3Z5qm`sS0Y_|^2+!V zOTT;dr-6^Klv_^1(3&Qzs_; zakPP)c$zl(@rt{9*UTZ_k!j@{f05vGv&_QG{gvg835;+Cb~lMoRw|Vd zFo4o{%1?6LHC32=@85nv|HuWWEq?3Xi8e$@$O3ra03+^}qiQal=MU7gYQihHXv)j4 zd25neI{%u<>gwvkLR+65bpJP+Mwi5qhmJu|t4bgbFj_cU>o=1UHhhVT9%EeF@)9Ny z94~3}FIBjc#6;lP9(%mixk#i(h$|dlL<==YxkbgPt&X$I}eSMZ#QxJU&M!x z@Z|1WlKbaE{PFHRqLLd)nk?2&H?v4@Uw&B6gwSSndPyXhjqpw(l%MV>2!Id%;D-W3 zJHFC_R-VxVnbDYjWqjw{2KtL%Y&~Si2k3po^>)*Zf@B>+gJDO-hq0PKAH(vO-lQIwD;eE33P8`@oxMGue6VT96E1D6COTMG^s#a{&*xz+?;~9Pf zegc9~lJ|*vM?xMU8dsVmORA!E2pt<$KQ0vd^E=l zS*8oFV^-uM`a`(ww0}3P4ey=gp?J{-B^z&%6vbX14<|zdo$q5J?K6eChB!P_i-k+C z<}ooj73!DB7`0Q`dKprE{V6!kt}#egWD&ckJ-L|Zh{N#OzxBi0=ia1l*#W8-I3@*R z_LA~&35o4p76v3vGLz`k_~Fv=<>>S8K&j_oAwD6>0}i`=jhJ+U?#t~(CcSu#DA;RA z4OmEU9E8zdWz_&_I06ZK6_ilWUK-}LjKG9(l({pqAs!Tw8X6Xy;ctI$*%o8t2v`@= zd78qe;H|qA$Lsfe$zlrZO?Jg3Y%oJe04ujxNX8U}=)Z>k>rme;2~&~o6kJs)yDfbY zRg_Z0py@Ef)1<;hD<+WC5(ms_RblN=hEr`QT>bD0bbB#I0mE}-M;Mk5@T4Lthl3fq zA@ea5mQcxPJ5kRPa|GG=P~*8H)*}9J_Gw0Yjif|54Z$G!y6R9Mj5KZ;a-sMx8_B^g zLZms=6mfgt(=lATD^+7H6Cvz36iBEh34)M&wvMk8!-xwes9BUpVnjwgPhKQDo&>sV zyd^NpR-#W98?kJibCZ^`{$N*oEgKxu&PE{QGIntGzTz^VztK>& z=TFfjY&3JeZhSZ+uK`o(oPPo4#rEsT5> ziMF_m>6U-=?!spS|A+Cl^Z6J?K-lgPXL@diRJvv8J9Cdf=%x3=kJ$Tb#?MX$l_hHW zvq3nsG0?!A=D#~%Hme=!qmpy6{4MgGNl0<&>VmTQhb+-}oQa-@fGG9r;06%F3P1VX z$~OAfPNjXcLS0(=I*6lk%-Mt0gEi5?b$auI+}hw%YBKd;4ITXU0gW9K8Q&XhmrT`H!Y;BP~5xsbol$)En1r&nwIlN(SK0or--w}e4Tc<^~ zj}kKW%NkVZTmZqmluYfG2BD^|*Q34DI#tO~ z-nZJwYoGH>tLLe{_Ze(j3PoB7C zEkPkIcJp=hM}%WUpRl=UX~pt=nOTeNX`%hcJ9)?seUmrMRg10Y=#E2_`&5sXDH2up zlk|hu#LJ>&JbU`Z!sNZvZj5PBjJveZ&op?0 zH~V41x!J6lNEk}bqCX1P+Di0HLu!$A@wpt8?em}LQ!SMfx`*jn)DXxOL3SCv)Se102C*ey3aqpWe68#%w zvhq=sB2tKCu$b~PIs>-U@b>990V{v15b@RUnmaM2Tw!{ZG7p9uj#+*m5BI0gV**gkJTCRT)3&W#Q5cI2Ip{P@gsIA8QEm!>(-g>*WD)kRcV|1eI3IlC~qmp z6V4?y4j`hD_buwWYg_u_d+=t(>BKOI_Kie7VXo&1E|%nrAEK$E*~{Gl<#SA9+5YlL z=t4_cLTr|1pGVtK2Cj(y^Q_S{TL(3eeycs?!=-ApFV8!&VuBD4xLQXM_bI%fyu`Ef zKvl8P8{9Pur6f155z%K`kx_ z$sUYclaP)d^Gy_fvU3QB-LEh|8RRW+X0aO3?Aw{#zIp=4x%J2| z{yMjAh+ha@FQR{78m`$^3Q&(wls7g|*IY>1G{D{RYU0JBr7AR;mx)KosVTCJFrT^b zD|lwW(E3H2aoTa`@Fnmx z2y}`6i$0nSH!?GBb=l}(@ro;})vHrUeYItG3N#HBZ>Vb!f+ECCZsJG&7Q6H3LnM#~P~$Q72#jtRA12zMylosp31{A0Je=roLQ3 zq!zlpg?aE#Y^1skn(R!h7`**3v|qe3W*)CBCsN6eQ62U|n34v#=U6Ph?@pUsr=}>} zW;eN7OQ8v>ONDD*B6+*9;j1N;9O5%QT77uQ^gqavdH)F`_PXvon9{4bDr*tx)SOf= z^Slb3)M3FXISg!c>XR;Gcfop77RYh=>W%fOU6Tj5%D_I5u23pkC!c}8gC^L!H~a17 z4P{9wB|9InKGHzTa6S?CZx|u&TRQ^(=j;1NLY1x!7gjU{@H6E?(=0pkFX|&NYj%qp zX;nc8*~^-kZ+7#*?<7c-5s(&7YoMuK(z6i!#l>!5RKwKIya79^lKL(FSYbq zcB8N27l++A162wNf(Dj1>!MIr&ykOGR`S|3@LP>_!azXMz2YXT$XIMKy74Rd#}U(_ zsRT<<2?egmMOdDHX;v~{iEVv?dY&mQezR4Y#w~36XbtW&-hM7^mfczA{S>@he0KhK zI_ULUqZ@{K2pC{fv%OuZ%R7^l#K3j@lZ|LWUcn1qJ=c85XA_wiGCKJWxNRCC2o5w4 zIG#U{!jAT-Vv=m~YS7TWpSSm*!c{U2yIOTZ?a=nYnoeF0#^m?&Ut3u}#4p)EpAQ^@ zd<;Zc-SRXcZI$Tdn5Jfg^z(uR$3vQ0R8*j(J3t#R+D09G!FNG+8Ppif?xwz&8WBy3 zGC!|3H1F>I%<17Xhuk8#E!$H2Qv!;vb=dLcyQeYE*PX*4w6J@Jn|J)WwbsaR&XqPy z^p*kMS>)$t7e-*Zd&tSGr2O*Un};iUcS7d*gvEnUIOpp_76jV*$?~NzzqcKAO-jU! zK&9|fqKI$5u>Kuo&hJA%Za>9|5{UDxNF9ksnopYT;njM(R)| zf{RDevdx3Ru~NBOb`FSZ1$88e@G#zu+><);MPWsYeS75Ch50iw4;~F2#VtU$y_^?$ z1F!92HnwQ9?!veFx2k3IvrI;TF{K(mdXCzv(DlX+*XaAE)zNyR*i>8svvnN@JyqYm zzBO)bh}+GgW^Or$|2vF~Zmikwbc~(a6cIw8_lEJ0{?YXq#Mie>yH&fEnf(i!0lyQ| zdu0#`1tj0;vY+}J(qbJl(mBriLC^Y|=+|^*IBzMlW22{PE7bmU)qr$CJZVF| zXzDoCaWdiq z>Cy--0X=>R+xj(bco{1MM{_U&P&yB~ERFQ`@Y1RyEt59!fou&)dGx8$z+R!(J=)aE zrJ$iZ3F{uQ@^4>$KF;^yKnoe*8dannho*Gr53=D-2R6~A$Ckgv9BKcs?S)M1+uf%5 z(opi&Y)amlCiSLRF;Wb7T-)!o>1{cxO>bnmBXQzqksoo5WBVD_e)1>btL z)os<7*FF_!oH*8~@y2rw}eXG~EK zY9K^Mx0u5L?`~a`>EVPhJN2cbO-$A1wmYeQ^jfgoPgt@6icFiIzlbs5yzS50b?4-# zz{?9ua^uJ&zwdDK+QN|w4Px5f7XCGLX3K`P6Mu4n>si2fGve&zhA37~!0M)U)irqgc7Ml?EJQ$ixP&PiD z#z~7{9qU+T4lk)vN6-n^ie)nBL<*7CD`l8FUsAv8G{cC8VMvrKm_=XxYjVj!w#Ypk zB&F^=QNxsr0p#eMky3&%Ndao)$a4F-Pd7CX3?K9dS~h&*09}lrMq3fHnktaJf^V~9 zyin>VhVPx$`oClZkz3<4;rbZG#!)so+o*K{m3)SaTihfy9huEhj02xm@$DGzTO@E} zZ4^U1sSLKv>-xT-Zvc%N*EIo6sfAlvBM{`OWI9z)Y&-=^i55CqIF=6Fq=Za+bt!G+4uCn`mgYPB(_@i6E0Er8Ir#h!g|jEr{9g2@*o$Oa@zHdY67}O}-&@!4 zJT|_Zm=dCmHHCOq1eq>ngYlOr0c0J>+myRj!A=bzN59-hiTp; ztW4xA64Fgv48%u_zVN2I{03F2j7P7ywD|&^g*}%Mf_|QV5{=wai6N@ezvl2N2ztv&m$Y;1ryYzWZri4lcJ~+V3B_o_V(!TAj?0jO&q^HWk>Jp&{MR+D~p`;Ec#17pB&)Ea+}|`Ue~y&6IytIyqJ?mz+UJ z@sC#3wj&(-q>@yh)Gs@>pAy2C2Gq?2xSCg;3Ca&~7Cfs?TLt1# zk4s$H`ztT}96ecu@RvfHf^>hBjgM(Xq1RghO9*8f4JtyH6doTA z^g?YjpM-7$c}CxDFZ6)NPNG--Y99;tP`3TN7@pA<7c45%H{$YGXsL@u*6ngeC8zF8 zvE{->&sqi&QfPzTr?>-@&Dd(u9h(EnvK*hj8>iy9aV&AAqlo=SeW~5Xd{6n= zn2VQ$>{crQ&-v7Gi$*+{x4cXlmQVw!+f;GFRFw5)B2#y*F0B*=3}B56Ci?hh@y1SX zSY}eKsH4h_zdb(NL(1J-BNzM|#`QY`JM29QFB9x3ml(qrEMHQKpJe&h(y;?-XAr-J ziJ^RkOtf?&-e&pDNd^0Vl%+HsGb&ZkgiZA3aUwwAeMAi2GKH?ugexkDRC#;fQKe%u z8sIcfz*3FPlTR3ye(OUk(7+YaUn?vAZGE|tmptRHHsMgBR+ZabVquBvQO9t-!k0iS z**~p9CNzMFv!#@K=@=z9VE*mJYzAx=8D{4KLBnn)9W9J#K-x7?u&GDzh)0o!vXQCO z^x-?LAqL9(f0_>Gs7*`Aoba{BL(O1PvE_Q2j@49smLUONIX@ z4z{&3{{I`}#%IU&NV4(NM?lOFyh{gcz4CVOT6cS28ooCGcd=k54tpW+do;4SFu0^#nL=cyjfu(7di7=aj> z1zM*)dRiwA`Qv)tMN~VFbHMVZqxJ63A=OGvSIs9unqsAqh|E+~l;8(z(o`SV|@VLe`7` z;IYB~K4dRkOYTQ#HZ-wv4Epir_Y& z@@@6~0pbTY80P=Bmo{}ZMrfr$_^}8};AzVVpO}N6-dcXnm#OS^{0=7v@%Bg5AK#hJU_%I6p{N<~K@|N;aKZFf zkB46fwzoO)A+4Sy(3iygL`l%2*rOi#5It=jEC1TftwWDwJK{3$e`4n!26X%qF)GA@p1j~V1N!TY-x z+jEZcPKCzEh!;XQL@6>$1q5gi3aKG%&ZkMgFOHa^U6G3ow?K4XwpA*DMcb$oq9&qs zv}_oMhtX+ElwAaSHpAnlR2H9m?rT*QFCkc)hg?_}JZhBN5FwPv>->Q&XD8o>-E<)Z zWI+QrZhGUbH?eFD$uVpT{j;${>NjoHcFEKQj@wY2=06|@9y$`0@}7_;65?Oi{t6^c zk-Qnqs{xt+9pKCz|@zhd3a?bNS1sDp)fai<98v>Z&6}6NhPrG-_6I1Q~;@IM*wi9 z@VmxKsWQxV_rG&T1R}OR;5mnP^eqK`aOP(nSip9D0Q@*0+VUo5GQ9Os+#ez}Z80E$ z9=*M0QiYald@}I26hT!FDs$)&lER!8e}&72x@VnPDfO#7VyhAHD-PV=jLq5<)+c9H=)5qMjBVyjr_xQR`sEv zA-?un$Gj*iUx()eKcIptAoPS>8{s2WC0kNf7Hg zG8@BH=*e~Ps4)~B5;r(A&Ozwk9oRBsCu+Gz z^9s(@A9#`O`{uoYdCB;hDrrGd!`va(%X8*H$qh1C0hAx&?dl?VL|&L!2`+OfQU2k& zMsm_NQzx)Cs&u%UIm3-Ze4e&GBg=mb^&MWy)eFOJG~3T{0bSF#%*M=QEtjdxDG>ir z>1vk-1HvM}l)`tv&F0n`D*{=mZI^(0y8$ONSqi(N+HulU7aLr#SutcBHq*1^y3}&V z4>-}>F)*{!79i_C1%t^SJF-!Uw@MuZCnyJtR|O%DJ95`z%~$D@d!zD-(O8hPHKf=e zuV-q&qX_?&WDM)c%Y*vvUr)~jZ2?TV2BvnYvtg0pq=;+YyfGMx?uV|<_?GL|b57{M zj#R?QfctAQ#2nH$hqBkZHAikihSjbVEnd*@HaD(Ka4>outQyWH)?Pn#RJLb19@&lj z)_r-zYlK2zLK+!NP?jJi1MUY5HTvp8E-idzQ*KT8q(SgdeeModeOaQay^n@ESoCN& zc4#Qg#igcr)*0L>jT%G5x|PJyK6aJsVnSFG;wC9z7HTF#$sB4N^{((47j)QapI%-> z#<*_ClN;5Ww8y(bvS@^VZ+5V->b{jby{ABEgp&^X98|*|(gZB>erN@_ZmTWgY9X8S zS1^{wrXcis@c1!`zeF8TrE`XC)^I1qFc3hs$N}1-b<9O8tuDo4wweHYWHay`Lx^qax#K zug^f@6xm@G{m(H4U>V3eFdmvh7X=VvxOKiB)I6-}kAd8tG15ep|;$9pMk^m5| zSqE_E&#{-n_z>fSISNgN$&ZhQxzh5w1kKE4{!tE1M`4w2aK0jCQ++uqd2w)b_;qLN zobUZS`M9-q-%;h>O>O5*FuRrRpcJzIfH+37APP(+l`i2EVRXE9XNn$1L#W_=J_ir3 zMU2)aTF)Ddt2|j+bV3ED=;L5idti49rl7;sHQd^gs+b|w<1hpXYd4jIFT+7GHVw?V726Tfp$r_j9Y$x1 zjJ0m(E}X$vj#-flIlca`RfsCs!rGGMbPRRJzStO5V$9n3U29O|w7e#l^2^qyMi4$E zS{9|youi%6eG8b2Vi*sw9H-sy^jP-$vZOF)Q@-h6g^roi|2K*3qmryTws_4{UUkcP z23#j&MNgZwCRp!Q*rvPopkgQhc8%K4^k(7tb<*26Z&VTUjdHuu!~C*pXZwCWrKdmJ z+D+BpyKYf!^u)nscA1*<*M*h58;AF6*eOfndZGGzg$sAy8MBx|&t9UCD^qj2b-I7(4Hr@nq`6oyTjfzK-d7~Mu-T6>g1^B%-8?(hMA6vZ~{HCMJ9UP3viYFKfuoV%}rLcWN zx|oqf<#OY4qW5c)C#eA|RBE{j#K+PJHc9R*qy0|3QfoO5l`9*{UzTtK92)qC34Sof z(@-IZlh{(gx~ikZRQ&mc;%~4Cttbe4jBB$`U3HqCP!*-E55Mw!b;|d3?ID_A$qkFg zNUT1OZ|f7h>XI{z<`+M~twpZeLr+2B8i?<^`sYj$hTmtyLk`=hjl_|ygI4m`u{UTg z4T9#uaP-0~T0~1it|QE;0e@dBcWGDITO}mAp*SI6;izS`$GTzbyCs{^-7G>tKs7X- zgt?dT59UKw=iRwJ6QMq}kGCGWMk{d_V#j6wx7;)_CJ(A0VLfJ$Kavt<;1tVaT;FdP z?gwhv&)D8?QvbO{I@$|;HiN+@BRVHNM2a3mD1v@>&FXrK=4q=Dn$K2pNa_7T%+0o0 zX4^UzjPlIUAjc3=!n-XgN|`b+W(>;O;)@m3>UuhAtex5w z_-rORrP;M*HJCW`*ZkRndzyR0I{2FY)|w`V$p97>Tl-IG8v_}V+1?{E`6AFK7@W^m zlWxG@dxdP#wUK)2SAG07QPpf?5S%vH3-dK1Xsjd^sH6?nl}kCSe}d6UAx&zNGEM0^ zFD`;>^_>>xUO|oC8JU;WEhbXjPC@fL~rz@-sTTDH3 zv@K#hZDW#bB@O#u&pjZY{x14dVOmb_T>;HTnfcbu959+rOT=aEaoN_MOQXogWqyjx zWN}zILDz5zH+vtmY1OBF9>9ePf`mcL7)ut7&EX5o+$VYI+1A@aR=gl?!U?~hJR?-M zwBlpMl5aW%|KZ;L)61CvVK^*;kXeVr3P;SKgXAR6wBv)Q54>a&JN#pYD zA16|?Y*s9yqTSKTUtA>;isAGmqv4h2|A?zsKWzf7!1o)x3~XB0Q_; z!7Ok^yZ&$`8t@Ab1{TOi6pmGgQli#mV|a~e@U(4y8H*#NH(Dk^>cpr~2(btPxX6l$ zw(N8YR*zh)SL@CsDkUzoW4LQIOC(kN#k?shzOWmMDQCF8|5tsFujZxAreCcc5sRq5 zghFXt z#eqXOb2*DdT;{52H#y2wXm-~}u_<}evYHyPQ6w_0(`+0xv^>>G+ za#Yr9O$wo~2WJmnxZ@C)$gq%d*$U4+1+%bnxIA|UtyWW_he8bPvj4T}X*~1mc|7x{ zixgrqlBDg=dGpwc&;DiH@5xwOWVN(IETUQpS!BhZ@xafnpUnYsdCy_*o$z<&0>z8; z2`h(8)mOyLtWxn^pGr{)$TBjGKlzfP^`mKPn`n0S^N)qht<`CTnEyR_#klv5|}QvAgNgV|NpRUucMC$aqR-f+)*k}7=uPnb{g?0`vJB5g~x z=RH==myOSs?OSuF%Z3_!p3g}|o{hXtZakve(vqUyqPKH5hz5qVv%NiLy0rj)h<;qv z+r)KiUb`ugTNTTQm_o)}9&sgK4IzPuh^c5n160l3g|A1Q-^=Wk+ns$gaF8KltP z9s&f9bG?`~lCxW1pFBVcMUR62<@N5X#~*Rrr}Yo??5~)nSg*bxLdZ@gu3dg+$P>%| z`X=M!;qm*?J#+3O?Yw3GzFqN2jBfcy$1`kj`R+i+6N`*nIGCaVR;-{KA z&g{>U9=+5ndrY-|3bBQJVo0Ya>ETd^V|s!-X!2`vj>~26@mD;y|NN zmzccq1A1jcbS=}XRl?w=BJ8PmTlvqbDi+baiiu z0w5tC&ek9Cb+L&<=*^uA`FqwJ(uuK&Q9ngur_wi{$xaKD&sU+;|AfXX#~VakvArd| zshH+dSvSn-XwEtw!Fvu|ZT&7q03i`wEaS?CtYmFyON%M&b-BPQeT2ES=s!=z+K~Vh zn4!rlwvZL}5b|l-5!mmR{xJTGTB8<$@pOxv0kIDQFQ)PPEB?R=%rUVjH!;TSGj%4t z>s~EWVbS1f=Dww-1W}Abc654t=V-XGq>KJi<^u;OeDs>gye2R1M;k@*s)CxD7+f>2 z9%=0*+L`rly@84+z6)xk2o13&B%v{?Q7g{Y^L2#;n0h?epCgnO@Ry2{#PtC#9j^iO z5qfm17C_Fk{yzu7yrPA5eJ&nL4@q~N=pe?A0z$m)DvC1_#|PTwtp4LSCG{gfa;~fm zIc)VLSW{?jO$tsZ&|%X6uu!7y->%9PA3u+PK-(G$lc=hjME+yVDp8Oow6L8&4f~Z` zMRQ{_8cFgD6?ky>rKXTmFAqoiip%&NNc@**vsc@$=ensfNN&y`np*OSh{RMxP*mND zwkF5d8I~di+b{a4rKqQ)n*PYuHSx1mg!h{!+be(QAngXgxjcC}j>P^dE5~_pl}<{f zwHVS;U9&e=Ju){=&=Bg1i-Jb)<7%0}7mh|73bT_*Ek&oEU{!5OK3WOB@WuNeB=$la z72nNvjuP=l4tU$LsJ*csDD+KQ1lrMhu?MxxQJYCO0M8{JZ>)_+GY66;tZur}$Q4*R zC-zXPLfx6@WsVob0FCi58zxG_LO+`uW{I&f+qg{Io z@1S!xYf-{Ly z=sgZ90nd%!1K~A05@_)6tg(ar1hSk=Hm^PCmn4~(w>C51sy6N^-!MdJi+VKyxYb{nBuE3Gif@9a9k|q({JUjz_4Fu{~u%T7-dTFC+o&`uZ5x%gZCjPL zZQHh;S!uJP3H;@V5<imv`lNlR#Xt-;d0`r_zP7Un1m6p!T_x@H0y-g+=J z=!(kyDjuv1a}=CeY|Zk?AvTR0b96%>H7`4EGHi0F$X@n7v>ZuAO zjdENv**i3VpxBh~A)IR=aQ+t=LdpzZRZ`aTwm#aN(3DrE16Qze+ptq!5j@$v3oStd z8s&=vEjeIB5oG90INmEUP=32HPw2UN44<{4gU{{iNjP*olDYDr}$TSQN z5;4>vEo3*JvNeYlOT(y(=NmrJTnH^0x?`5@`+=4_n2Q5&okIX@?DPYJkX!v?FZ6X? z)4&kN?DSvyad&U8c46Im{??=VtCLnSsj<-GfxHvMgWPhJAXnX1LhFnEATJk4`!>MZ z!~^i;pJn*of@nG&G#@Z&C@-LswDE_c_t|NyQ`Wap9#ehlno6fMYB~~%ZO#BTu$}?z z*eSQdv51wQ_fO0I$6Ued$S(KM9L4J%f5kx!=Xqow+fkv$uQj~~Np$Cc-I zViVl@DHrQFfAwVOF9{i{B5!Ij*)g96&o_s>jtg+;D z@>n+${4zGTDDd;fu0fDx-4gMa^lbW6`+ZzL0`^rq@3uj_B`gz+^vKw+R34Ypo zxSimHHGUL-oSUt?L4GVY8`ZvQD0fxr*3CCpFuuxUbD*rO;WLDpmDcf#0*0^mW1~qJ5#>{bd$WE7f7Go`()Tno zzxK>m*VntyNcy*IegJW4f7vbe(=6U*S99-St`g7scUc;tS>PnhFDE2$wco#Q6ya-!GkZDf;&h{(Yx{cXb#*;vQHY2XScU@#7s?88m^AS2 z0#uO0@X>+)$gaxT)D~r^n54`j`3Vuv=*Wv`1OXn2fux4eEu%Src%FGw#C&MxzRr6A zYWK8h;_^HD6O-yBz%JQAP1Kr)SYPP7JSNf@jksFFn%O|&wNZf);NH2eVyRrDt{Jh)Ru(fipTtKh%Lj16|wb(He$FEZdd=10# zy6ETSqa#?})b249jJ_!1nV3Ve_&2w7$F~j#Q+GdtSvxwryIw{AI)~~t&6o`B z1iL##&xn|lvM7VftCL7SlxV_P`Dcd5>Wf_`SWco3E_n;Ojb0(#V*C2GE%dZuZ~Mx5 zhtQWQvTWX%!~HhF@XE81&W@(=mgz!T?UU!MC1D7!`%Wx*90jAr9D{@r2ho?eVl0Pr z)0E%>88NXLb0e5sSa!W6mSZT!8Ld!zjiwl0%xaMeL#9L6|6#hAdkz5{cxP@yuKx?_cQ{@l$u~~CH)xPA2{`<^l zYN$1qE(>J&x0OZ2DYWL>wHq6C&BH+pSX*F zxeYp5^xbQi;IVQ}6Ckv;$cw_8H;dD1b}#YC)a|*B=m}5`i+@F8${_DWG%$^aN^h$* zqo;c$g_(7_udE*LabAAP;Z-@v&kV2KZv9jv_vfRE;@UMxzTiC7c?Zw+2n5bx}8f5dRdbi&RF}t zR4+Uk{0`JrMFi!8EX(qKDK3=j0D=@Hm(Uc;=xk@g^XM$8lx-riBQ#1Lst|Rj6+P50 z*L58VyIBxhJ>#{bL)nRDInhao)8kHH8DdZx6~lp2FLq!!x=Qch{3G1ry|#kA(gU-1 z{T?k}7>;?=P#F}fXgGcUN$8Bry=l7hXlw-X?fRdR;*Mh&k25C--``)NoOkFEF67g;x~ zcij~-nbNnG^NMf2?IHL$g!Z%vV**Yix$lSZb-f%y*Y&ju#?R1yb3<&{JG2kW7A4;$ zJGJlduPk}VtH{W>q->Hy8P#@9T+%7G$~QbFMJ2LWCJj{52`_6?_8P4!#wuO*2mgRQ zMYoQuQRr?kirmQReT3O_ol+3{S=r)p!|dCXbKo?FzijT;bAJJzQC9#6O`m+W(Yq8U zBewM@bX`ex`BNt0$*lS3Sor`wn-bwoGj=^=?pmvlOIbx?p;}0CTrU6``Qw@dR=W{J zO&!a`jIpanm?KLTYf1 zK+E_yc=-1Uq`Q@n7Fi+Ufo5Ko zk2S{oAT~PJT$ud?Sm-W*YqhFKQ)7Dgr5TWj!{XO!kSv)k?xGY6>`9yI0ArQr+mENC zF#ys0hi*X`$TdVB8{WlFd0gU4xFmu}k|0THuLZGrYt4*Xcv9mFNk+zC-gIdCR^Fml zjMg!ln7EACT?8)>Gw)uY(tO|HmYGKHUD6-#8^V^yktP<)%oZ6eiON5>z;wGT|48%P zfgGQc!3cRNBr<9yGcK^TH}LhE3V&$qA09@?*w)I9RaDue=YZh<*07~v?Y=g9pVQ3O z(eCV#Q~@`?b=Q&1;i|gT{<2#8_{2HvNs*Ol0vOR*@k}7fJ?y(+lK&8xy58;OLt3Kr zcyjkRn}dJYrW~~%6J!-^f8QKcQ(ncoSIQ!1*Y>oj@UL=NVY~L7%#|bHV_+(YSRz$@ z{27OfnF>5TLy}0GwQ5R*g3HbNowV~^=JQde_=#0^W~ya?x)3h3zQG4m)M@@qUj|OS zOAoW4!{X}{>d>(oY&z}@nqxbw2)jZ3Fa{*mfnk1gEcboj>WC~RPcE%8H^_E~x7%3r zSgWeCP5xnPjbY&5T*QR@Mn0aEh?T<)Lf4=Rpdo@Nt*5&^DDy7?+pxzZ(%Q=N;I2VO zh_UXs{F!gkh!Q_hKJ_D30fxCQZ5u)-8KW6DlY9|b#zp8jhMolU&x92y$5f@e==(tn zYt{P!b-m!+VlIx!ukaOEU1h2!fpi134QcM5K&t^M{8vLO1Zia+fqJKcN?HpgN581s zGd7H=mFXR1!v=)i`iKT(TCA$Q)&eN4Sf^w%>u2frv#Aj6SyV^CZV$!2Q%;3}!@p~>tFD}16{(jx@Lpi5It1|{H zknYJvfyYduGS_>XDdJWH-ZQDI@hnuQp%VpKIB+RE#Ih@Uj~{d;MNro%RJa&%KVgI5 zd=PK2lVN3IDO3eBcYsTxJH;}#0J~kT$F)}0e>XUx(CSpJyL>suyoerxiE~iO>EsM*Mf}LsU9hEAdmusS%#TK zdm?Mw(&E$d$FhufSYnH-dVu>Uy%Zju4x1kh@7WZw=-SYMJ-$)&Ju6favUh)rUe&A4 z7k4kOh=uWAU{38$8<-g7XuH3=q#fZEsS4N}$G<`JTGe9BpE{lkO}tm+>~g_y)T?ut zu_H6~!c6w!LK>D5H{_HJA3SIAp^sfWJ5|Z%+t6+V`n|Jgg8L%IO2_Hzc)8w6YgSV&|#3cALB9lUlNoDE2C4tCnS) z>vz=gTk-b}`z8`~OgWZ;&WkM*K`)46Fo0`nPFoHN1Y;N91kM^;5#~Bj@QK+PTK(t~-xJ+SrAj%e$a)ug){c!G_>=wyy7kIh^4$K#uKgpo zfQD@9Hx4Z=vvvin>1EWCvVnii8s6&=TgGm3S9HZ7bNyJoilW0M6jmK|(DRWdXxC4G zXW(TIFsg%yN~W1ZF0iz0^A&er&#e9iR!Jc?GONF_L{qDkyXscM7GH63o$fVHiN<}T9ob($|7=y9#Q_%DDv|~tG zD!HVlQzxQiD2kEpr$$CMTZE0UWeBe_Bl_Etphw&ei_&L~#vz!$Y`3LDzC_X38dN{C zm<%nitq&lIZYXdhfAL&vaD>qCqF~)O-UwWbLLH8@6Fp4gRpYy)8GK0IjaYn4-hG|0 z_c3YfVb<2et^xk>_TR2*;a1c_&S?hmeM~rR*dX*HLIOu8s2%8F|Jozq! zZ0GLvi9ju(6%g+0wLWnZS!wqN)iFwK~;zb)2kl!S+*qdRa6Z| z9vsvz>KlGXpx@q~hDZVTYZ(CMv%FQtRv-(XFOM`kPX7aC0~p^x^rSxgG*Y9`9&O-n ze|8XRq)z16Dakj+pH4VyU$TZpJ8FiF-6~3Qm z-d)R46(Qv0nq6qNX!_YO0Z!t9t|@T;0?s zYj4pr#*3(l%z)ibn(J;Ga3@TjiD@HP=J{#&OeJe!>rp{Hx8URFao^dU?2Oyu&d3)y zkj<}l>ff3m{?9R^t0t_t=QT8t*;%Wg4)j}R1LA}BX9F@pTDQrz@{JS%4JBjFG-qxe z^cQ;)p9!8;3TWZDL8re!P<{;q?5t_)D7|c0X~Aor9aH;`IJuM7XUfD$VW_SB zV`{bk*3?7S7(+m(HKF~*NDXGa7B;dAF|9sv2tj-q7c3qN{3VPQwXKt!r6zz*uMQ5- zBO8DJK^8jtJS~6dR~ryV=n*ir&%PYYOxlRW;*Z|?cu~D%9g|#Sc+tS4WY=s7&37HB z`w}sEfBK;w03i*XHEiD*W4^@aMN#O)+zGALo=J|pM1Kluu!>j^(^wIz$tA85WlZiP zG8toeMCGVf=doVtq6(AXRy`Kv@5ySk&Im+QR7nCBaks`%Que=X+c`8<%PvVqNnzCQE28bez@_2VIoS z$7HHz&2zI}0|0;Q{)QHMp!!iFXrw{ zX>ek~udh(uyKc`cSh~(Y;WUncH0N0S{z-pGO=Z@x93cBP7k_sRD^Ht9Ih=N(aSGXD zoUjCgV(1X_=9W;pV{0fh#0dtqHDIE(TY&E?F-_UiH%D16h-M?|l!@jr?KYtVXY^$D zSk09>^t)-5#)T6lRQ#f|3cIkxp^hZ`?P-RhM*ey*k=8c}g#EfGiCgdiO`IMza?INn z^=2USCinxK;&W?B3r9$a`utXZ17M{!F7#2?>yi8G&D~3+IXT|Bs!=oS!(d7elDxntHX}4lvRcZKgFy3?71IIVeo-^ce99Y!~m*KRSV2gwg%_60^ zwfsirsbqAS!P~Qbq&{_Y^VxDiqbZ&zZb2Tu7fZ|8{!gQ{t+q?U#%=#k$6djZ{!UK=&5=r^W5t z4Qbc)do(-yz94$6rlTwyLaw|2z)yfZ)u%!S`IM-?{`NzrIzOnKBkGcU(PPT9$PV_b z4hLwvh^z!3!FlO6T#4S-a2w$HX|5s#dwaKRQITgUMvi>Y>2$sZPab`Fx_c>x3}z^+ zXF2PhyOUB3buI+ZzGxBCb~K zD$Lq|?n#?-5Xu>_@P@Vyo|=1#^7TZSUQyR6EDXc&{F(-pP37(`>@GT}94cLn@i z>G1!Skh)`gC^*t}U++#a2+lE?ZMP}^`Kc{M7r5q)dS?LSFwR7gbv2|pWp~7Gc5hzg z7T9Pdaq5VnILGHaZd-k#Lh%h((=>~BqFFSXDv09IX#Dx85pV>)i7M(oN`N%tsRcGZ zQKW$--1)5sWb;&lvZN zK|s0(H44t-T-*uM#^x%k1@+@+I*Y)w1yEKA7r#K|Fb?-Mgl^^!=zT?lGt!x^Y6w5P zV*B_*B;~qDDExJJ6YS>+#_(gX(D%$GvUw47kF3n*@n1Km<@L%$!E@M@9wEWZ+{{&$ zJlYKX0w@tjZ8$Rb@ru<6kkeS6b}Ww7)zQO8jF6aV2hh+$)M%!ubvncvn)3vPO3!6@ zATU;J36oF{Vw#03&cl?alutdG9#Q9S@8$~H!rZ3>XNp(?W6t>l13iytg?7=p6J1So zv~xODeX8{>f@D)I)0&49Y3UuhoLY^XX6HL)ye|t`IzJZ_cHko1^+m}nHAaLOGh~B6 zqJ6C{*z26>DF*{`;%y_g2fC+WNIg(>94S(zo0@93_ef%KCmO6TgQw=MOrUl;0=)7p znnz=HXlBMC%X@kK1G#B`nb{U_|KJ!4AoYeimZ3J=%E=KH z;+C>4!#Dn>{FeIwBTzpk%mpWTKKA4$U@-$4Jw?cV21>(i|)Jwg#9zcH(uRp!Bxu5X&P!K zaod7Q=2Ta*N(1EaLT6C(tX(MkZ3)PB+ET8aJA2l|#PN)-f;q~E#(ovf5S}S{TvQtY zT$|iBOLUFHR9vRe)vBWk8}KkL>z5p!xorpb-NXY~hc;m_8t2H|r^`Ly8e1#0Yx`Qr zNbkz4Yo4LdHM9(X>sO?ZxK%j3rI({et0|=F8%F)ctt-&V>0;e-RW%4MkdB*&MS>I~VE0&9%kz>{RFsn&$iZ>~PE2*~>jp*J@Hd(tI&9c^jYh+!^~dpp%b>Vb#^qcuy$p3 zwQzKHF|f8ZadxwFw4!r1v9bT&txWz!ey{SqO)>sMet*3T&?lA5roXAyipcLbZN+DE76wEL@Wsc*vH+s@X_3<;>AG3g$ zC?HcRjZ^+maC%atncaX1oJDAiH~qD)Sz!uWa&CUMcR&`gzyMcp?SWE_EQe}f(F}iK z5uHwPt^~guwtO)dQR`>Pt|y8hAt;ie1v^mzY@EKpE zdlfhGLlMZ^SH{o zS{zu#q9-KS*%GF^e>2pU^F=An&w%dma%RWhu3&jfdgaXz#4hJ)VCyc}~qmd%7{O~nJ(8PD5Bt_d}@MW>&;tj(LO?DCb! zcFI$e$#A?LF5I69op-8dTURdckkERAdAL`l8cwQRSxtX4re5AN~^Z~DG>wCm_qLuw5t zp-Fbyb;v^gm7jQLdIA4Wi!W|N#@_t4`1o&`2%i57i?=qgb#gKMuMX4yu=%ZT!H0j_ zd<#IISR;XLym~bxzfToSXQi@#%$Y4??yOYL8#=~2R*Z$?cqtd-l$kVVYNNG=993pCx#AU@>$(DT39A6%V#00yZ%)^j<*Hg)BDI33xPUI_3Iv-4Cd3{MGf2RFn zoFh1~yO|;{l1jtgId?H#Hd#fG%)u@+Z5_R#txpccS2@O45~!XvY{*8RfXJJB=%Y$H ziN7pM8EF?&naCRfnU9qU5Ftu@ufTcA85ZlmIg~RJ=V%lru!$g)bPc1eir2i4;}+Zl zxaLS*0w&PA2Jz87POY0?Y24)B#vZ?_Z-6aF@9f3Jfi99@;m^8++Eqdvms%6J zsUem9EShc&pt5C8Va*J=!x2#k;k*qwMgi@@mxn3TJQyd^&pSzLMfPtJ(Vsx>U6slo zRu$8kya=tCE=4k-yyGL~_G4P0{7Uxn^M3=5$1YOi9-jy1C{t3KZx<2eyBAQi{xoJ!E=n3 z7paQm@&QelSaxm%8P8w49=aB}p(#6h8$qNW&U)iiJhd#F{8k5pjLsxt{Qu*`f@E@A zNd66(Ji`J3(f|K_HKOj$wk9slj&`<2_W$vnRI5tIZm|8MCUCvj1WDy+A)7E?z2#y-)*hH(D?4VUWY||8hVLy~L^jw7;iIFLw z_I!vHPPO)wPO;q$3eB2|(&JY5dnDDi({SQgq6SoxcsFtin6|NW9;z)R3+bEDE{05K zU@7=Q?~&TrGSySny-OmQZD~*&nYW|&FOe4AT_`=yw9>mgIqsj25fF)s1yhgIRg(03 z6=AEG2LMXHSQ7iROt|gRmpNe1hydUZg7feVv5RJZ9SuJGfGFq~`vsUN3eMv3ni#qJ ziO|hHt9}aE=(@5ahK?D^Ime_8K*&b}*liYO>psZida82TR}&$g5I>4--?z=gvJ0)x zdjooXQPk}|f^>?rj8Nxz(MNJTQwKUyeP%ciGoz$#EnJ^m>q+2|patl<+;kO_I_MBC zOmQpLB(wBive!yeZ1VHOpKO3WEVySGwn1DR5`Xbj^488efW|=&*ISRvL1P?!&NsXU zK4=?)VDFHrL=ct|Ul(SM#!SE{YJqT98VF9tDm3;N!jeIozM2j@58$_^! zB@F*1ql$OU4`#Td1^y^*wKmzFZtxLA^PI3pJJ@xoqlyG3__najwjSAs+Xu>9cdu9( zJ=4u;ke8Gc9Jwowy^!SnSoitfu%R-Ab#bD~|H8b_lB^lLTO207wo*pz@N7>?yd>ld z*t0@H%q;6Hk7e@76(>~KKlfPW04ADUU+!x8D(!A}7qg9&CP@!OhrsSsUo*1M%(*A|+X@HuSvLm3;1D&&U2_3#q#5$8wgQel6Sjq!PPps|$aOn?{}9a3>O(zR zRCD(n>24jr(D$xef}>pcZ8&QoFCvzG6?*tKgE;x}@lG^250$fwW%WOE znMUr*wZnpaM1DJ(=I??1Emxu}uOuu;C;P4F^bfl`!@n;7CGe!83=IS-(21w>&v0>v z1p@wdQ$Rrfnq*^S5eA5mf}gSiUMduYl2ZS>1^qje0fPG1UAC$f+abTn@5OOJfLQ;>T^vpR9lWa=+d0}f zo0}N?mq(`iuVCh%xcy&`R(nqDPdd|%B4@JS|HOnnd6CJ;{tD}RqJl_qeX&hWXVbtjv+ z%JY$&=^uh0_fH(~J(Nx9{Dm_g+wUtmGPU5Ncke4?C6|}f*lp)X>EffJh>O-2>yVUW~wL|1Kcv36UmGrqAI3393aCz3W+Om&AL6zv!iy+I^e z3#B@G=1+K;`*I#Zy0AxH5G=+7f8zW+Ex*xVzz>QTU=O~#o$_Lq>*b%&7;#1BbX-No z!<7Xtd9;%RFLrrrJbMTeKLE%#n#J-WW=Jz78uRIl8caz<2&8djM_QP|4X>VW&vt>d z7(_M(s`*G@vs!UG!>igpUpF70wemmrZ`OBm-X9!XjSgOH)Yur1iG7=ueSw;uEjXQ9 zudUHzU&L+;fEj88h#KUcK#wk!giheo&uf^`4j&Cy))!&AoH@cXCcRKQop8cJXkjo$ zoRIi%Xv1Zlh}$Kl&`ZX{j-eQ#_w-cGuo8{xX0bw0rvkP>jB-)9;m&2HjH}i+A zrW-^LqRGnf_u5~a2%$gjuuwFqlcX=I9zv5Yn5sV>E|_Undki%SlLlWvBAyR!%n(0K z*q{pqb(#pPsP{27+b!U(*nNZbTbywZmMYKnF9-}xX=E)#eZZ|k$H~#&OF&L|n9Ap{ zFxO_ck&ehF#v>mhy+9k=Lsh9L4Z_Go>@cFK8ajWlo{j`_O&mG5!TY?g{JDmP{e!d3 zmXplpAbW|A(L!{I`%ZFaH;|z=oB_Pxiq@r`-(5mab!%SbK8MX1qUwBI^`g=R{#uG0 zDp`9#m%uj@P6N3z8)U*R9Bp@51GK?;5j1bgQ=8tMVgo=yymiYT_+163&cc$DzK`W} zA|ie-mbA|_2TQa7C{SMN(SrfC31X~nrF}JJ?9#XLH4cF z=!l!EjLn6BbHSt@q5b7507pdGQh{DN-BZLGMeZqz?J$Qv_f>PEg{L-+=)?Vzu`?$e2{}hTSx99f@=2{;!2b>QjQgEDm&BiYaM)Im{SQG6 zFVB&v6pFdZC4n8^lMdjrmg*|>yu*by-i2!0R99Q+Ha5sm7yWg@7QDz%)9anBGyRZ( zZG}upIe+q0K6j8P@3wN(BIC*tS(JAZZFG|Q)>X#0C?)cOBuit$64OoZAnp{oGXpIF_Am&raqrP(m zsk(4K0>*x_Uy!Ma&&}1XuCYClsR?|=q^sAaHgk=mT$oIGasC9;0(YmENfbe@UnwY* zda5)P`tzZ~*h8Re!!` zlYXKzo(7%QS^LcHfE_u?2rVY`lp#;ujD)(A0^&s*k(!}=p~w}zdS>>d0PYTY+|%`d zv4Y5YZZdjvSY52&I11mArRExeF_^YXLeAtMbEmYoj4<;ofhKQE*)ub*HC>}A&g5VH z>5$qHN_!>O@82abwjm06ytn^nc!kh`fNy~3eJq=!-sL?_2b01_VaPapA#YONTQS9{ ztx7d-Jc)O@+WvUBu2S~GnM z=PO=aScYOa0x8+qiHNKgLAa;#V0_YTRdq7RId*!q^Dm|I-?BYrC0W_MKr=`UM#2~X z;L&DCiCwWOIn>Gtnri&NqN!*oFejD#K!1TaMg=#nsVUypEbQy-x^o-RZp%$--3cn-y6-`>)BWEk0|?5x;_Xj9PVu~Rm#{6 z@FRjIBS@E-!X|5TrVliO=5xK?LeqVUH$TIct2$u^E2{)opbw&5nh)U1dI8J>BGO=) zcpOj&yigwP5%@;%yglCZMc^D`h2v1i7BD^woCn?UCU&?DYd>OUoE9<@5AVaB8Z4b0 zUyKw4#zA_~cUwt(7`41NqWqgehr>$|efN1t61DWgw{I@1j^Vc&9+y!dbd!8S`Le98jrl??rH>_kIPf zio}qJv+k6QZRzy}$$;@<2tp&@KVH!Ds&2V1ayp^y zN&C?RqD({L4R5Gh{db~}ss`x;Cd?S&$|HzXSO=&=lvU8GxYUs}w-CX$tR3R84Kb2c z;eXILQr1A}(BS+UQ9~b{FEZ1S^q^i)l~R?6??^1HQN;*`aa<@TJoBFwJvl?vA;#ka zeM#?CUej7n)^8iq{fWpKh3Bhd)^k+GdXJJx)-Wdx*FA(Zw7%x%Hjgzns#C-?&(S*_ zHL?aIfI}KB-%t$~XitGDq^dVoaU9}GV81kW^oy8=z&H#N`%H52JFHLG#cYqz_E9mr zL>EO?QB~Gp1+y+`pvF{09qUI5{zqxh;T)8_m-FaWU05V0+Uv1rX&zJf0Y9um;?wr{!NP8YLYih)1 zmMkKy+qE1Me&b=22(OW+++nCt%TM5I)PODmCnx|1jElEGktv*Y1Be~>zD`i&iKfCc zjGj-t>|Dc1>@VrPW9{jve(tI~i;&sqX&%QZ^5z;x&8QIAwEydrUSO&h?PFzKJMjgjn;p?1gc1 zJVo(7b-jGR%khafp=fXOVF@*?F`Oa>H6l*))dFVtsC|&>(BdQX#+`vI9om{4frVzq zDg_}k3L0P6I4fI6mIvi+lvEzA-80?$Ca;c49}^K~FmNEQIzt2POpaIFeur~8 zoIJY(`Ck33cZMLAoq#0Dy{jIlk%qvoYJRa|u%S3WZ6nrT3#2+q89%dvfL<*ISa}x) zhiOa)CyYowQ>e6GF?ck;o(Q=-WT;%l$q8i z5$Ft$YDl}LM#Qx}Eh~1kf%3PJ_HF&9wj1C>q&Tm`E@n?*>S*plnly_siL#AW=L^HlTw-edgd{$FIkhIwukoWxdmhmg zN-5}c40q&O+y6i))1O{u*a=)&pyKxY>k(9wae2eSJOUR=Y)v2!PenmoCAj<{RugM? zpbrWYXP^mh7es^Wo6EX1%aCyong~4**=>2}w4wGY3m%zvN}$t zHU=0E7M`r9c(dK^%{lGT0`uP^f}~$#W#s$pY?40B6eNpbXzO!p$yEezxw{pTmPMi=fV0H7_wtqY?0OVjGgy#dcy%8cFTWB`%oMxf&GDQYveo zpjKe3&QU5uXPp(#v)Q1E*6fvn`qXKfSDszM@sir8Kz1!Z!BPAcWtckn8UT^!* zrD`i!uYgh8(7B2)HP>A7FTolF)9~Emm`~OTDyu3OH5ZRx3baQ;0_AKrFJX?klK9KV2`aJ6k}vsa_bWyu~@6MXk-$k9^Zjgaxi*_u!rVQ0W5b#6Vt$4 zmKg_?%j&+I5-aNx-fc?IfhU8|g|mjr*zqOlA368I)Zr)mf?O!2-^5L;K$qi;NO~~@ zLZ5mBb4F)OmLu3-z+cRe-WWXDOH3X%c{^I_LtxTLqS{V zRgn_I<>`4P`H>g31*Rwza_Xv$*QzhXn zN$%!V-Pj%eUlv^Fk1GMB6I?r&Cls+oUb>FF(>#aco8R@z+X0})J-o=X;R7iHMf?vk zVPKCq_f*`L8dLZ5D&kM_Z}vo)gD4r?DeCb9P)w3&$X5)wg0ixh zsxpuE8@{jtvYG976oy%Eq@t*3f7KVnnp~pv<(d8BHs^el>s@v?+q+k;Tl#4dlsQ!H zx6xQQ*i}k!XV{YZjLRc;G(G-jI=jUM?l-?b&@-#Ji}M|)%-?e)gZ^jWYH*MdaoK$u(I>-+x@`b$%!UF?M3jdhkzwJRxZ?FX<%7#wJs~8b zQKZfYfeaMNyDGtSnvitH4wNJ4;Fg0iP#r6>LLqX9!X*LdcUPPVt2se$L;g9a*r80Y z+QexAbHb&jxKVIPQ9W|F+<59LVfVNQWOiOct~_F`SsmY>5^6jon#2u{93)&zeon>M z*=v+AIuEWO4-qF(mxOylPlz^Yk(Y#F^9veIOw>w_`I2gwIom6R%;>I~aI-}$VKbv; zllu}E@M49wuTLyt(PCR$tQ=tqm?D0|b7kBv80Y$nqOs=pVIxTD+107rsB%jdIagfK zE@+FfqFUGEDHxu;jlnQBg&UyqKN!}O_O52%`#qQ(AQ$7Uw(Y0hFY0f*XS)&(5qrHX zTr#`RI+NNLy{=;^_(kP57iH_qi*a(!56hm#H3t!4TCNEu9E}zL%CSpUDK>611=G|k zmaRTgKV9MYo{sSjUd?U)c6xNQ9=8(Ed8biHw`IjLY5-KzxYk>i{&sf~Pu7M!d4IiF zRAxV7_bb^2I$8M_8dTcI;Nz$-SWd^N1U<7Is+SY%)0*TF2PkJx5$2oAyGiy#GzlfJ z0oV(gYCiv~cp2~HR39(^P0 zBOBL*ixSJkM5%^5DQKjh%8buIkH(KH-^WHh5Xl`$#~8E9255%0 z;cGczaJUPF1BhR{!u*BG9$^e{ea;PW9gDP=3lWv8Lxi0!RRm#7@I4^z^g9hh$?w!G(zKTe@M%g_0kqZ^|-2NM~T&#vI@FK$S$&V zT1(Gb-wqPtShS<>UG2=*>+9%-miu19Q22*Y#@woRJRhOK$p`myWuVe6((nxX1mFhi z`C1;U`n~*%p-WoM_2YF0s&m4Qqc30B&>cIGjB6O7oiZPHm_1^jQf|@fGaU?!^7lpa zW5?62@Ik`P{;57{+Sls?O`IND>G%{)QP4GYet;6%45Gg8qyB?8)DAg1wMjnfZ$8>> z?&mNYejvK$P?lUwVIve{Jj&S5de)YQ0<3o=@zTe#cgdSqEdO_|ACqS29a(t04s#|I_!zXzH>z{PHqcn+c0hSbq<;-P%I!+oR zIeG{95m3yHCp5xnLJm2|($h$6={IuwxI%RNJ6mzNiv?Xe=63h7hD>t$#Iv3vj07|6 z4MR+x_?-}?p6pOHOlHi&gKW%YjAocOA%j3z^7sFu?wz7+3%fMUux;D6ZQHhO+qP|- zux;Ds3EOdkr{n(+v=7T7Z*_3ZhfG&oGgqdGdVP{^ErIL3ISdCoZ9KSWynP6Fxv z+f?FLW7TpIT;XbjvvIQEeoPo;-yx@%Cx!DUY{JPvQ&w2~+L4bEaP1*{{Wi32cQN2Z z&5b?f%m)0WIY~O-Gq%x1B7YJ(q9Mj*Qu`0a=5rojym zf#fmWB#L<61Pj&+Y6B*DX$Q4?^?(Q25EVb`qvA+FXz}8zt+E^6Gh%BZ9`7h6tO3o6 zYkuSte%oYD5KWy96!|OHh?YpH-w1@}*e*akou6M&L!4 zMjL@@1a_R%bQ@8#|B6cZW@1L=`u84pZ&!g1Iu){#<-972Bs734^L;%?f7L?m)F2hz zEuh*(wO^l8_1J2KP8XFR`}y#*T$$BPc4hkp2Kc(AkD^0QABm%xqC6i> zt|A*!l8OeT0YD72?%fu1i*35q%p<;>qu$UAOc6>S(8KL7$XEYWrV6OtzNL_9_bT=p zD-Xf$2exsi(Gsi`+UPyMud2`A)V%nA$c<%GiNFg7{N-yq4P&lWryd!{FlZQRt#>kM z@NTqj}w z?Ch?(MOds0znj$*^Rn5BT=jIYjcaY$Ud1VQR-Jonn!)Z~UM18T0dIgUEU2~2v|QWi z`nKUYOSxZPU*|0%yW5Z)|Ulh!4s$Rq9E6b@og!?|y6`ktrJ@zo9vJb1| zERKLFLEH_1q-24vUg2J8-R`-5Uf+E0ojzitD>vTnHi4i;~OJRZSNnc=EfK{QizzR66?v5_zPh3+dgNfq^(=>CP zqH{{J9$)fs7mNF<*`AyZDZEJegPE>kaMz?qUaVFaVK|Q^!lj~RYJ^cIu?G1pR4*b; zO~r9$Apv0}Ez4I1x`;2OQibb!zoh$2uU$Am;Rk`S@ViX7U&aI@Ppe_mKj0cqg#xq% z19t-B>e-y(fgzo;JnpY%%Y4}q9+3(5?)fIQNHG-oO+;D>KhKi^U=^PEH8VO5!+uNw zWAVsdCNE$tV=UGBznGiWasTd`elcs-_?637hXqqlc_A@F6cNL`@b-IL^s}<%3mg0r zpR_wA&rl|taRe{fKmU_M9>HFV@8IY--AP3Jz)z{qqJ(#&+VB)7PDs>rq^Jc2EEw1o zBhgiE8>D1;E+X(63r)03S9Uz4E{VKBMV@(~vc$y!#h&~c)j^7eMr_M!%QZlfyJ{AN zgSPT#CsG@oH#BDtJ%>qVQqcU36Zv)BJ_V4S&m%hqEx>_8H@_bj``zz6K~Z#s%F_up z4s3~R_DK^0duuv{6@wpy2lzSZCui6v>>L@!1%@)z^vXK`_bT>w{WocK>E(?FA}Y^D zF{HUxeX-EQrTOGoyJYYFys$^PwoS;e+(`*lgZllg(oPo>ljQ5#-NEZ;)}s?VOkP=s zL;hN3YzeAWn=*}%6DRR;r@Sv^nLojYI_po0jl)qBes0oLl!4kjM!`31X;||6Vn&hj zJA$Gym(eMJf_asg`Q|)U*ovBO06j^Gs$Gaa#IzE*!a+{Nwag$|d=p znx~=HGs;K(2PPB97jJ|Bdy{vVvwujzu-G=K5&^O5uQiULGF7vN99n#zz8!zi!XMCq*nmp3feOs0&Ov_Y47DD5^v~vFalBI>* zi6LOTP8m5>%Oq6xz~i-m1Bxu~hDHMj8Is^sTqXvOO~=6}ypD0Km-_50UH{`d%-9DY zBjp}iY8&X}A`IrZuq|lTfSF=zoSF!=zylcHQ4f(UGvX!nB@ni}_V>|iGomtqGU!mi z81mBA`w)iwNK%q4S6<`DJfQ<+#f1od;@FlC!B=U|xLBPpEBbd(^gd-_=!$9Vm$maw znPLt!!kuSeldQQmqQLXMBSn&th$ylGjzM=lGrGV4i@25-@pIHdZe(~-_s=6sx1Y28uQg-V@*v5x|GX9?_|-xlB#r!Y z?^}%CKbK9$Ps07&=Y#Vv-y%c#FQ4f~XPd~5*OBcnB0Ang9z=hB)+zh{tkXZp`fedV z{O83#2j$a0r~by|MVx@=!6yJ7>(fx3V_!s3@Bw^D^gTX+f8LXVLQ{+e7Ym+Mt_$zT zPpHg=_nI?4Gy?H2s0HrqYF3-*DGP)~Z#dFq2i?@ z=#90S6WR7GB-|L`Zm2MMCkIq?^X{ITi8E=C=0P(F@6M7*>{VHt*uliqA7EfR+h%X| zj1gx_p^Q8dvKQdbP}R*M`~HUt5M)h_Ls>p#}gNsFGWUym}-5GB7Xt zGHVjgEA+ye-m>o*m?LzpDM%akFT_-tF|J09MZPn41I4e@QM)I^{wx-{>gdmB=Qiy$ zX=LU(_uYbkl^w(TVp|KlBB(tZ7AcFeg;?vXu0n`$_qN4Q;PdYpaVdyg-A(h`p9)hb zt7T+bopr0@-dtT?9eTX|IN>x2Z8q4pNXDSTU8@7ON&cx!umXJgVg)R9An3}E#~!e6 zwi`A0@w?Eq#SQ}KKto~v$dEld?jCD_V)3BT7z?XIl85j+Ff*r&zy~*N520N!K5=sM zSuSBAmyOU3Gw=~GzgK}XFcLPvw#5frWt(mZoN?k_Brqb}94rE|mV8d4tivn_<9C+h zqh-*-ERCKp(h}uR#&9!~W#Lw*%2Z?nd;FZ0XBDCmVLo7tEZj%ZHO1j~vt-TW7-(St zgWD$??Ns50@@3g_6eW`Bx~Ow4#8UpOc`nm=|M;gQpD62^sfvtykY$7l5)qobNfG30 z6OPe16h0S1#!kn2B;xWgNp-V zELHSIT8?6@)_aiHtay~TgIClD=zKQ$Xq`nF*JOjm>}Ij=Xm339YRIuP_7Tzv#}-C9 z&8zQ>Lxffch)2D=Y*34Y@Qc$0o$c|mXN>JeU)>Dw%6{H zr9GpA43AMW+tFZ28nsG=njcf%<(<#n!9+#W)ZQQorb5X*ql$n~+ZQ*?x>Q9Nl*V}s zZj4IHPV^x;P8W%u+3nzuksZOk^Wd%_sz1>9mhwPPO7seNI={pX=u&80qO@>sVvaMl zC{1?qw3>a#;$q+4K5!z{AiB zEaS{|q!aG9=sb^`fG6`NL^{ROc8yfyW?i9LJ<59T4EHNqvsxp#^$tv;qoBcbVKCB3 zeYf^`Dke8@3qbKJj2{{7q-E3kQujpkE#W9#U5jzC!v~;S`@7`Ds3XnA?MJ7|W{-Dv zlY6z6c37p(GNz`Y#ow+cnz0qN=~dY5PrVYy9wajz7GccP?C9MhOB+2?dWD(i6pfxD zw?GpxwhjYGby9i^geRf=N|@RD9vuQ3qBPvM>Utm#&H`AGr#OiI9QlZ2pg?~X+50y- z_HtCh1W!gTa38;d*Vs&GjOEH&9P(PGk5MzR;`(_nFH(c~##FzmXTrk@da8f=HGvS4Y2#YyO0POQ2A=H*T zrTYiMOEaZdjwK*+%@?c;isErluL+?Q5j+wHM?(^8uJF_rs=os`6nk=*~iv+}>nafT-G{>+OYgt`BPvda@$f0w|u z6%7W#%pw%+hARI(K_-w0Bnf%fcdM9|T>+RB>#=v*i>WJMf#SM(QIQKfBf@uAjON%H zbOSCt1M0POmHky#4gp29j7`{_+izWee|`N{h_)h!s&QQ{bF7<}Dw=0*+whU-+NE>6 zj(1btcvL|R1I~j2GA@z2|5Q~!U8TE#djo))_6nnYR*5El+#PKW6j_TuDzV5VD%gm0 z?81y`j@W~D$kQJkJ-CEXz&hNc^>Fy-PjsaRrqbeDEW-KGXDOQeaERFI;Ck;A{}uwT zfys`tL$Nql(s5Rc0Pei+qW%N|2wnY-J%46jhy5ed3$5d)Ti3xg7rt=M#4wMNRy9H{ z8;*bO{USEo(xmbhH9=%_JcB?r?4Coc&ocUQa^TytIq$Fa)P{cY+fi0mRWxr0vETlr z_M0&!m|6a@-2O>+`@H4MlUrs-%Y{Dtj5N@HA6D0bqTtyQt+;OA->a|il{DA`KZW!D zz9s$spnv=~Te*MDW-p4cse$}73&+9(0I2?#e}RAh?Unz-NRXVVvx}(-qp_Qr@&8kg z?f;@jxkdfo#=GxUr^F%xMd5onUD0S0$ON-Z;G=^IDidW@h+0TWm;d_VlS-xOa5rq% z%A;`N+wVG+3MtDh&o5 zq*vygT#Gf*I^mQJLif>*0U0vqNh?OBP9C_>Fm1;dr8zAaY*jdsaC1crT3c5&sB|I6 zOD9uzoHlM*iwMDVgWFwkF_Ky)l~Eu|&#I^?DVZ~Q%Ehw!2@8eMH#qG=ohPRO+k6bG zQkU{>$OwogKc>uT^-*f7Do-+7N4+tUdy}ExKU#-|KBSh9s#q3UxzjL_iA+#m+oIw) zsXiK7zsD##QtI^-~ZS(teYu2C6OHeJYb}AFI2d0BkUD(* zFjtrc;R_$}r`QI($O;Lo2TX6st74{Gd6nd?XZANIWy7JSn1@~=OF4(OD8B%mStK}` z=F!2DmcjKYxdwIpK7QOO8ZIg0SG8Vd(Kh}9Z)*A6#kBFpf&Rsy&-Hr3m7 zSdbQ8b4o(6vp0@aMDytvX=c#x!Ua*+{#J#;KShZYde(Tk_d1;XBTuwP!V^!e`Syq+ z%_l;q0)fv1@phb9(B8vk4H-%>Z$_O|Y8tJm5G_C=1j%}KT3$it^3rGwdM=h}rzwYH zeH*7E;k_8(6yXruZcc?A=$FCUF!eZwWJP=zBhMG(i91f@>?#q4rZ^F&sgYyOi>I=@ z6txRc?O}bonZH%Ja(`w+ZWivS1xtByNB*A5{9>+1wx8Kt>`QG_Dab0io?<7GfkdVS&A6@<#0&I)ruxi_z25o^ zN%tUM>7DGuXtHJ*`b(U<{)d0EF>+$(G8v=a9jolTE|j0U-H-UngEQG$0HW9@K8V;~ z(*)DQ{v-w}vcxb9{lM+9jXd(WR(IGJ7|{0)smOePo4P677d8~i`-O6`WozgK_M zAt*5c0HpuVg`|JqocJ^wN#&x0L9~*| z{g64;DU?WvqG{?7_rHjOl4X29-2B@_l(}4a#E7TQScY%5;~62(fwt~Vkm$$?`5|@p zt0H$S4npCwe@n7N)?bFRk+qr|qlqT|_KM?n^&$ANwMwh#{P;Y6Tncw*=a?cUtAQn+ zOfns39ubkDXksEmjn3JkD(eSjQMnV!blyIB2jNdJ6SdOr?}Js0kXDgGBP3Fs(Yd{c zso4#N_yYD&zqLOACylCcZqP02(-;L=;}Y=g^Ffv(g;1@h%b1oH+=wz&q)Ur%l6>rW zrl&C!2@115^|F6N*2v;Xu^bQhDgHqTB|wv=tFPk-S?v*{Jc9hO4!2nXVRO}K-XR9+ zS-(vzZ94krVY2^j2b`sq!z7@YE8-Ovn460Q zTv_2EPz0$>JFV*T|8-Jv5a^T6c`O3$cVZPBHjo&WeNw82AswHbQxQDa1Q8{TC%j%l zglQU4;@K)@nMnZ`TCSarw#)~)LLTl7)Y=#oNJWUDT0sB=g-gK-r-V%*m)m{{I~5?1 zWt2+7Tf;K!RjF=BgM&*sPx>_IAvgg78P0>!T(u9K^ASI~+M9N9XBoRm{Qi;9F%{32 zl0LT3LlF0V$hIs9MY^xU${q_gvostGTT3PT)PiCldu>BT1@~>i%n_he@9yo?(E0%6 z1s-Z<;_BK-ZLj30YIVK3HW2?RwmAPIDpX@7dMO3S2tk#UQZRIrHUny>E&Ua!mKRVE zU`isR0kWf;@@q>L@~D_8*QTD&X>y)U1>3DaK+vwYfJ49yZZi1gWr_;b1Z+yBehJmj zZlL%;*mglI7eH9YRIr#tqFv<_>Ij`U}y}9NE;;C66@fpzH z1r6t3%=ldKt~l5EF_r=-w2;0dQ(Pd-tALpUXcGo%3o^&pJFB#9E^3cb!c56W$X$P znkUDrru957<~jWkTz_^PJ?^v}_jE5Q?zlwmLB#@D+5mw4I5}X*AOHks3v~&2-T*%i z6i($^p)jGHd!k&7VH@o;Xzg@JL{>+sRtsSObxwHM(sS#Jo*+*0B{4HB$3Tc$lF9t0 zm(~LIpqj`Cq+BmpFUz*+=jyHyMV5pow{or>zL#A-2Da7wg}XoV6rSnzC@kY~R_-a? zo?b%sc~2VOFA%cqYC<0Sx15dT;uP-Y(^+K*4qKx9_*ofisgwalt$+&aZEFCHE&|}r z1WPmMVd=+u)Vs;6t;@(vZdmsD%uE)E2vL$muc5cuUS|emFu+-@HL#TP{RIn5c94NT+UV&d6 zJ-GmgFC}nbSMNw`Jt?54Hz_ricvdlKjP)i^3ir5&i?~I~@$$jsPX}`%>-;*(0D>2R~^sQLc~ z?SC)4%T82fDdlM@Psej^Fn2`c>r>IB)bX&ENkOZ287DFlO6ghJSMMiOC#9pEf34y& zqZMT{Ybbl|*bjy_S3SvIs7`2+reQ{xQibd^dU^hR`@SEV3F7rP5@QCL%R_hnF!hXw)(PJi>>K%%8^{P9#o=l8FK?RUeN!H$!R$^XS zUqrxRH~xTq>~^BZRzkRs;}FfWH_<7^VRNk`5>q_i9`=ce>0=M2!8wd}i(?dcwkI|m zrwS{vM#AC&+a2<(km*|5D1GCZ`Q@x+Hq;XL(Ea1u=hzzI7o<0h087_6JyhD#zq}yd zs%9{T+{s|z=<*A=&1zfleRZp?u+7rYa5zf(wN#Crw$S~an_+f?qh0%2IHBSD@z8Qz>^KKpY)yBPIF@(O(a z@$*c`f_i>tik7B+q>qqUocg&7l3Qx0_|P1Wl%KiR?9lU{Zbm#ic*V@hvz>^gB;RcL zabNl$xZnGu*OP{(0hL6%VQ+@8uwP0_a<|9GN~M$#Q>|=O4Jg;eZ`6v^X$KzkyPlN_^Ca4}O(pO3fK*E7-)k?F)1V~m~*oiIMFoxzHU!fFn)?fE1Hvc z@V60X^7a|P^VfrINi&JcP^XDhN>U^0lrf<_!f{m8KX~6%BrweS_J{Y0HM00pG>89% z_X$eW*wxqZgfRDrQ|?gy!TU`pY_d8rKfK@cPu`Cx|5x5mr6GO!AG}XF$*9`1XoF64 z>>_U3wOUy{7f&C>a-%ke#@48|FI6Zw7>xLgN8*bM;Z5vlhfX52Pk&f*y{66YVdfBjF~KO-mXb0?z^)1QSw zAbaqbLzsVbHWqMYg_pz$u3qW5xaC)OUcM9Pr55C549aicEiiOQIW8+=fi^yuq>A99 z;E6A6j{q4gW0{~7CP99~GBvH@M9H($&rJ#>5_7}vN8L_SSQ8?`Hu(HF34J(fX$JSBJ%Ce>$$lBcaQE&KMFmr$? z{m~wP=x`GO>zz9K=l%79un|c9i zt10~!pq3X@7h7Z7pW1UUwiYOds>0UnqZP4d2j{eTu9=*7qZXRmM#8E^}g zW8@7>9Ta1^ivb`k11u0|>+pw=ab(Ux#hL`8;~7 zb28p_4G^ULic)8y<^s!2L4n$dFKs4&Q*>4ticyi7IW(u8I(;Q;dX~*7kKbO?RSb?; z`C+J7?6K)7dJsLI|EKznyJyHa5J2TBD9sXZ!LAXu^T1i?fak0(Tmx(jS{hrX3TjoB_3DEOC`1U%-kSnSHj!uWEMzLr6Kmoe7E36&Ctr1AnS7iIzdmCL2{&f??S6D1*O3 zwUa{0bRo?J=`p~qENFwT&3YCUCXDkU#hyIZ?x>K)ZK45KHWdff5gWBe<;!|IicD4c z6gjaD3ijYyR)wpOQyCFZO&jz2QiD2^ZbHKvN!7WX`79s7Q6^?FM@igg4F-KN&= zmLP$4_&L65Fn60WGkmf=WxrV7KYCHh522nCW;LfdObsJq49tMRUC0!|KuMf(Jflj? zw>Fe=JH}O1inBh!h;5*B zv>jKnWKlHEJeoi1YUmasPH?6JoKktv*;tVA2E#jd1t*st@~@mnF!rYn^yO0=r5d39 zy=OfWo--UdDOrq!v6@e`l(7TcXp$I6nBcH$Hd-<35`5K%ts9Ggee$;9D*8|xp@r0i z7Pf5Je(0)n&$SQ{9bsraWluGoXQ8@`WuaZ21=V&XIczCof<-UDP0K(eIx^V{H(G=X z!hH#qFDk>uR8qU<`KQF4q2m`JH9p~Of-q0PFSvLPA~arTWZYC683~ro-${dg^7Fo! zlxE=|r$C#4^EpKC%psiQW%0`jyVKoa)`u8ym}afogz*KbZbuGoeCPM2O;a@F(WAJC z)7>GIZG7HDrg-8A5C_bPC#NN%8P~96F$L75!3r5;0>IF~<%EaEZp0XH23XiC7&BG_ z!Pp3igSWoa=dQi1Y9R-1Gc@lo@k+mf`U193a<5Q!+c|_BjzpAKTmL8|fhK5326n)Y z-d8#@^6WvuwI-pSR*s5v9aP6oEL?EJMm#17TF4Iu0wZD1H44NG;Um=jl|5IJW5Gr;|;=U4?N&uPLTf#Dls z6~xXs2(IlbP`x=C3nTaT%)1`?x;{NSd(3;!r1zwwN$ka z7z1o~sB)v6iMWhYDxpt*>kZwGHN(EvYNL{$^IP|Mt3IV1NIhDVH->ziwJ)199nwyd z!d#wm&8jY+yYz8|>r1cA6O>GG=Y_I2;CYcxX*dQ2X#0x3d&cErtbV$gQ-fL(6C*cncDqgtu6B*zTy+KyrT*abo_`g} zA(Z%l$kQF4#~&wO_k21&^>iBet*pJ>Y!k~GS;zQ2kk3!vV#)P;5>fm(n#ca!EYS~| zJIzLczQmUtbz|NmW}#mHiP_{~ot(==oN$xp+UzmgAkcT^aOS>LSnpDxm!#92j zPv_j;We=27frY*I?B7l);7utUd=_O5DW1{#sh7*1U-q;X8lLsCV!;o|E6`CQLh=eP8~^}=82|v^e`_oLuU>3da3-9#+n;Oe z_DL0;49Z_c*<)$u+9%UglYR-)(IkLq$4CYpET)}Yo&xF!0&Qy>w^i#{A=!^?0r0qp z2mxD?wc51I+luDsakaP2Dh*uacv4|>-+=)vZ(o$(4zHSNKm$iBKti) z-*zQ6XWZN85xEg)lgi5#r<$7uLG^}SewsFqj`bRs04cES$6!NRHRNZ zl>El<;B2IbW1bK1TkymHnTR~__7jE!1M?feeRL_qaIs2WJ^{HgLIn<-95ub)Ksj7* zjMT>f{5?GZrN{+Q^mHp^A`+~$6=}8r|A>Iv*8kN$t;^sXXbyt#L_*1BQSOl>#02sK(D^4W)hUhCE#Sr# z2Y9f*3T?O5C8onL_)w-*9b(KG6o=MFrqWkpaZ|)Ud}{#pNf&U+#vK-}skj}KG1Vag zViS+C(|YF*Q)J{UBUH*;hWd`^p;%mHh8N?L{HX;65z-Bbo4BJP2`Jv$P2{DDE-Njv zJPt1uBThR3M^M!FWQoHSI|qhI*=wHn7@(U3gRGEz1C8o$lGiELODUqr*eMLSUXo9KI`y4YS?sE|H4O>z@(8NbJakH`ELUF>4 z$f*>V7q<|@-bOfO8L0(0=M1GZLTTh3qGHI`nsJ_q0I~i4q8SwjjQFMcc>wc>U{uV4 zo-7-(%phqX1opdLc{GkA;nCA6v5;^nL;xX94Fpb(ZGV<10F05W%87(IoyH?H5qHF8 z);zwH9v`y|%)5~nxzCFHXjs5FkDm>qf_& z?M(@3lqtJe*JXHyj53$^)64m99vs+}5>G5*+eL_-QuBF)niGL<5Q-GvEeIQsF~)MV zug}CFZmgT`g8BhTV6zU$E8E)NP|9RcjwKigPhC$ChR`^58l-@QP{aoqoj4ia;=mIF z`>1)Fk-PzoD^zImC%;NVWh}sNe;e?1P#r_|OS$Tx4RjNplmOEcxkv`{If={>?g%); zdyR$!WTOr#12eKk2~IM}VkbgryjG6j50OL)m`EWS4e0@)Djc$=ifR)@bw~l|)@bL; zZi%PIDpUADGdro_z5?~FSltohXksaRG>d+vsPfX<>d=8mr^^XJJXme45q3H#iA-~r zBektWxok&%;M6Qv_lirhSiD@Q$2`%Fb|eWN7lghvVFeQMaRhbgSWAT|>I=#gdT2ob z^CAk6%*yIh_K`yR)-^1si;j02Mu9_k^Ws#wu#;7*(8{2!^pCCm`qhz2K~-~j>-45wx*Di3H25+wE6YD={;f*wdUW^cGpR(Wu3NIl9q>!TfEXlEv>$oq0u6j+i{ zuk)QtH-;4HN-YewwZ)i{T$7L^+%Jod#%Y`SdRho_4{nY*k&bO9S28;+hvP0(38@Bz zNDgT!{+?UPsYW~svRvQno>uc?gL9+{rR^zwK2?334Aj?t(&tC94lffvuZ0eu+1A0# z9uZ?rUrll|rBU@|-K$*nu@oZh+N$@w)#1#Ik6w>)I}w702+ooTxKtpu zE=3(+!sm0*I_T(A@ya~)abl3`>@5MOgoBStN5{=-TG+XFDe$wPk4^b8GBv z-LEi;knE34t|e}&zYp%0{F%`%V#RHwm~oejh`%CaawM-e7Et}u5_~zr`+P&4fR=_B zj3UFy`TlZ8#eY5yb|}Z9ES-%pJB&fV8g4)zPw#H~E3achZuLUgPO_17Cd(csxH`NI z*DhZ}zT#7`<94uL-*MN=U)#SB*Ax0&*dvC>d*N}56zqL35iGEZINfQ45|uOeLxk}@ z%X6YN;v1OslE0?xQk>{s4GL!++9uOkgE4#_vvc;%4M*yZo)0~z4@W$)gWjQw4-Ome zeWka}hn3>$QgyHIYQ$5>N6CIVL>Sn}Zkn=DFor5A0%RvC;4)Jt7-Z@{8)H?yaP+6D z(k}@gsx;q(9J;ofmO*%VtAnktDTF#leW6q20v}Baeas0OeeN36#RnumD#B~3!DbGmj&o*@NEd91g`~N2!nFM6?SJxiL~c18rlVft~qLC zrA0rg$eFW9Ed=A8s7e|`$)Umi`Xk1sdtb_V7aFo4LMft?k~33n>MBtkx{_JeHJEqL z7NXi_T`OlPQ@ZbN@&ggBTBFu`l@CeiSwiK`3D=VvcN8cfrwkTaz_DUT- zXI#kdyP7g7*oF<$*~H@8D@d1%JITM~he(&${hUvl4Cos%lw3kMY zuX%yf>hcTv#qZIjcj67zjVKGM>6N86sja&@_seDE6eDsmw`71Rc3Z3w=&+G|WP4N5 z6E^XVy)cvs-n+a+#8NgV8Azz8>84NtNZBSI<={$P(QOR&Cf^}mbbsOW`M9a}-v1=j z{&f5y54w?U>NW)is|$|n8586CsyQe1Hosh<#ujAM$9w%ex~FsZjM~+9me$oCkH)oY zdrqC(r~kw%f2fRL)G(6GqLl7eaAB>xM=??Jb|qKA=56|qg+2QVzV-=T;q$1HZ1YaV zBGB zhq(&sStc7zb5V0-TOuZlQxjF4jh^A!lIlB74yJQC(BY2=Hw6{BS}rzlmffn~Vo_co zAnuV}QmR0-+uClJwbYAPKnL6Dbwu!){!sbB&glnTM#ch^GRFK{`)MuFP%x*L8()}6 z;!g!n9Kp};?mBcZ*-r3ZEakHxy6IYo92`n;N(q9c0#vfHTwB4-f7+zd9UaupsX#Y5 zHn5`D0yScu-a@KU?1)J(mB(A8)>S4ZLZ)oKZqevoJDMQUv))S%NjbnLC|QG=tSVUR<=AT+oD5)KPMRlQ53jYw3QcQNlvVvAJhiFQGAq!Dx!b~ z*@Cy2E9jpm;R7o&-QFrDDW$`)=>HQe*{Csk{sAictt9 z#nL%1uG)~BhJjC8d0GyoLCCXl`4U+2A_+DYnlf(A#+Mr11q5*>x%oBABJTw*cHtJo z_5eug63Uhb(^63iP$OEeXO-GdS1Cz?k84wk9GVnQMV+5JlbT;H)y><#fPfrLpfJ9yKWv?p5Z>cL8l=D^~o%Ww7>1bmUuh>&jt@HEl~Q7tQ}z=?bsUCD=Q+%!hSI4`qNrw)S2O7v$kK%tukWtvy!)hE>( zh0$EXL2N+k5@O^>o2phcfue_1Mks*swiq6el9AAkPF>08{EhUCQU<;97+^%czBj6! zDT@$nV_kI_L29(+kYj-q4iNqgf{-D-F4rso4M3Ax|9;?6;?xkhWyO}>nue5V7&k~l z&O;|_6zea^h|NG$q>%suwMond+1YTk-)qrh38NQm(%?9P!h46*No9no5*r_&IDKAT zd00u=4TAxXbkpt`RGe|7v@x4If!Ers6gbk-waKc(q)Jbv%o+a70`rM|7BzsLVOOrJ z5Ws^Bz}S31*2D~nmxJFnqTyYCNMu6KLGB3VM3)0aWk{xe_I2!Cj^N`618hV#PGn{X ztrUVpB*0y{Ds0fjRirdQd%;5}?FMpob$s%njZn46gDhn2?xfTn&MP%rI3BBaaBwk}2|h8+75uEOSlEP6Kz6_`+ykm)GvBd|LzVu2P@Vo<2Z z5L=3u+PrD#+Gwr<*A^$0c4B&-2_%w6lYx{Kpd=rKUs%@mUVF${=5tYx84-e7F$wMQ zg7E~^;X*xPEiJ$#(?xv@ZS4el1)-QC@TTX5UBI|O$K5ZqmYdvJGm2@u>N`0R7; zeaTqaT%6CS~W#;$-r~ z+&@a|{iXfi!ILZ7FZv3dW>}=V&O~h*kZLKXQ4JR1l)w1VXPgO~3HUs^zaCr_$zcc4 z5^P__7IUWx`|^yOD?on>BCkfNqm<#T8%htgL-&FL6Zx3nA0HaQ_Wln?GD%9wAC6>i zJWJ>ZePF&g!nSOOZh4eik?Jq5SMRK9vdY-&79vQ`|<@*7=ajVBiljpk2F&3J{l z@R~UeGCb*RyT#8JDXx@J|IGD()np$=i)Lu? VYtg@2Y$5Ym9F?y>)c8k5J3X_Gw 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 literal 0 HcmV?d00001 diff --git a/vid-app-common/src/test/resources/csars/service-vf-csar.zip b/vid-app-common/src/test/resources/csars/service-vf-csar.zip new file mode 100644 index 0000000000000000000000000000000000000000..05d4fd3b4c5c28fb6380211ea6e9e82ecd57abbf GIT binary patch literal 46618 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

f#JV}^!uF;kH5T0kEID%;M9mS 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 XJ`^Yb`5Dg>0OCNQ_AJlO@%euM-ORoH literal 0 HcmV?d00001 diff --git a/vid-app-common/src/test/resources/csars/service-vl-csar.zip b/vid-app-common/src/test/resources/csars/service-vl-csar.zip new file mode 100644 index 0000000000000000000000000000000000000000..220e02fd50ff73e7e707ff4fe79be086469e8a69 GIT binary patch literal 33677 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

DGNVs0bogZS%#;svsL|U%_8?beq`NIO6 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 F{{b*+e2)MC literal 0 HcmV?d00001 diff --git a/vid-app-common/src/test/resources/csars/service-vnf-grouping-csar.zip b/vid-app-common/src/test/resources/csars/service-vnf-grouping-csar.zip new file mode 100644 index 0000000000000000000000000000000000000000..7f93dc83a97f15b22475bfaa2d10f77ce1fb38f4 GIT binary patch literal 71009 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 T(7gaa7W|BY?#c$c0>J+Oi6*54 literal 0 HcmV?d00001 diff --git a/vid-app-common/src/main/resources/vLoadBalancerMS-with-policy.TOSCA.zip b/vid-app-common/src/test/resources/csars/vLoadBalancerMS-with-policy.TOSCA.zip similarity index 100% rename from vid-app-common/src/main/resources/vLoadBalancerMS-with-policy.TOSCA.zip rename to vid-app-common/src/test/resources/csars/vLoadBalancerMS-with-policy.TOSCA.zip diff --git a/vid-app-common/src/test/resources/fabric-configuration.json b/vid-app-common/src/test/resources/fabric-configuration.json index ff17ca049..cb4407386 100644 --- a/vid-app-common/src/test/resources/fabric-configuration.json +++ b/vid-app-common/src/test/resources/fabric-configuration.json @@ -2,13 +2,13 @@ "service": { "uuid": "12344bb4-a416-4b4e-997e-0059973630b9", "invariantUuid": "12343f9e-3244-4d8f-a8e0-0e5d7a29eda9", - "name": "ADIOD vMX vPE_BV Service 488", + "name": "PASQUALE vMX vPE_BV Service 488", "version": "1.0", "toscaModelURL": null, "category": "Network L1-3", "serviceType": "", "serviceRole": "", - "description": "ADIOD vMX vPE based on Juniper 17.2 release. Updated with updated VF for v8.0 of VLM", + "description": "PASQUALE vMX vPE based on Juniper 17.2 release. Updated with updated VF for v8.0 of VLM", "serviceEcompNaming": "true", "instantiationType": "ClientConfig", "inputs": { @@ -21,7 +21,7 @@ "networks": { }, - "collectionResource": {}, + "collectionResources": {}, "configurations": { }, @@ -48,5 +48,8 @@ "pnfs": { }, - "vnfGroups": {} + "vnfGroups": {}, + "vrfs": { + + } } \ No newline at end of file diff --git a/vid-app-common/src/test/resources/fabric-real-sriov-configuration.json b/vid-app-common/src/test/resources/fabric-real-sriov-configuration.json index d6efc2854..1b20c31fb 100644 --- a/vid-app-common/src/test/resources/fabric-real-sriov-configuration.json +++ b/vid-app-common/src/test/resources/fabric-real-sriov-configuration.json @@ -21,7 +21,7 @@ "networks": { }, - "collectionResource": {}, + "collectionResources": {}, "configurations": { }, diff --git a/vid-app-common/src/test/resources/getTopology/network.json b/vid-app-common/src/test/resources/getTopology/network.json new file mode 100644 index 000000000..ba9cf5ca6 --- /dev/null +++ b/vid-app-common/src/test/resources/getTopology/network.json @@ -0,0 +1,79 @@ +{ + "network-id": "94c86b39-bbbf-4027-8120-ff37c6d2493a", + "network-name": "AUK51a_oam_calea_net_1", + "network-type": "SR-IOV-PROVIDER2-1", + "network-role": "oam_calea_net_1", + "network-technology": "STANDARD-SR-IOV", + "is-bound-to-vpn": false, + "resource-version": "1540925016770", + "orchestration-status": "Assigned", + "model-invariant-id": "b9a9b549-0ee4-49fc-b4f2-5edc6701da68", + "model-version-id": "77010093-df36-4dcb-8428-c3d02bf3f88d", + "model-customization-id": "e5f33853-f84c-4cdd-99f2-93846957aa18", + "physical-network-name": "sriovnet1", + "is-provider-network": true, + "is-shared-network": true, + "is-external-network": false, + "selflink": "restconf/config/GENERIC-RESOURCE-API:services/service/4b7cc8d1-f8ec-4461-ac43-5805e4ca3126/service-data/networks/network/94c86b39-bbbf-4027-8120-ff37c6d2493a/network-data/network-topology/", + "relationship-list": { + "relationship": [{ + "related-to": "service-instance", + "relationship-label": "org.onap.relationships.inventory.ComposedOf", + "related-link": "/aai/v14/business/customers/customer/a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb/service-subscriptions/service-subscription/Emanuel/service-instances/service-instance/4b7cc8d1-f8ec-4461-ac43-5805e4ca3126", + "relationship-data": [{ + "relationship-key": "customer.global-customer-id", + "relationship-value": "a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb" + }, { + "relationship-key": "service-subscription.service-type", + "relationship-value": "Emanuel" + }, { + "relationship-key": "service-instance.service-instance-id", + "relationship-value": "4b7cc8d1-f8ec-4461-ac43-5805e4ca3126" + } + ], + "related-to-property": [{ + "property-key": "service-instance.service-instance-name", + "property-value": "AUK51a_oam_calea_net_service" + } + ] + }, { + "related-to": "tenant", + "relationship-label": "org.onap.relationships.inventory.Uses", + "related-link": "/aai/v14/cloud-infrastructure/cloud-regions/cloud-region/att-nc/auk51a/tenants/tenant/b530fc990b6d4334bd45518bebca6a51", + "relationship-data": [{ + "relationship-key": "cloud-region.cloud-owner", + "relationship-value": "att-nc" + }, { + "relationship-key": "cloud-region.cloud-region-id", + "relationship-value": "auk51a" + }, { + "relationship-key": "tenant.tenant-id", + "relationship-value": "b530fc990b6d4334bd45518bebca6a51" + } + ], + "related-to-property": [{ + "property-key": "tenant.tenant-name", + "property-value": "ecomp_ispt" + } + ] + }, { + "related-to": "cloud-region", + "relationship-label": "org.onap.relationships.inventory.Uses", + "related-link": "/aai/v14/cloud-infrastructure/cloud-regions/cloud-region/att-nc/auk51a", + "relationship-data": [{ + "relationship-key": "cloud-region.cloud-owner", + "relationship-value": "att-nc" + }, { + "relationship-key": "cloud-region.cloud-region-id", + "relationship-value": "auk51a" + } + ], + "related-to-property": [{ + "property-key": "cloud-region.owner-defined-type", + "property-value": "lcp" + } + ] + } + ] + } +} diff --git a/vid-app-common/src/test/resources/getTopology/serviceWithCR/CR.json b/vid-app-common/src/test/resources/getTopology/serviceWithCR/CR.json new file mode 100644 index 000000000..26d598c6c --- /dev/null +++ b/vid-app-common/src/test/resources/getTopology/serviceWithCR/CR.json @@ -0,0 +1,62 @@ +{ + "collection-id": "84a351ae-3601-45e2-98df-878d6c816abc", + "model-invariant-id": "081ceb56-eb71-4566-a72d-3e7cbee5cdf1", + "model-version-id": "ce8c98bc-4691-44fb-8ff0-7a47487c11c4", + "collection-name": "NcmVlanSvcYm161f_77_vTSBC Customer Landing Network Collection", + "collection-type": "L3-NETWORK", + "collection-role": "SUB_INTERFACE", + "collection-function": "vTSBC_function", + "orchestration-status": "Active", + "collection-customization-id": "bac6ffe5-c851-495f-a64a-28751400ff03", + "relationship-list": { + "relationship": [ + { + "related-to": "service-instance", + "relationship-label": "org.onap.relationships.inventory.ComposedOf", + "related-link": "/aai/v14/business/customers/customer/a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb/service-subscriptions/service-subscription/Emanuel/service-instances/service-instance/a565e6ad-75d1-4493-98f1-33234b5c17e2", + "relationship-data": [ + { + "relationship-key": "customer.global-customer-id", + "relationship-value": "a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb" + }, + { + "relationship-key": "service-subscription.service-type", + "relationship-value": "Emanuel" + }, + { + "relationship-key": "service-instance.service-instance-id", + "relationship-value": "a565e6ad-75d1-4493-98f1-33234b5c17e2" + } + ], + "related-to-property": [ + { + "property-key": "service-instance.service-instance-name", + "property-value": "NcmVlanSvcYm161f_77" + } + ] + }, + { + "related-to": "instance-group", + "relationship-label": "org.onap.inventory.BelongsTo", + "related-link": "/aai/v14/network/instance-groups/instance-group/6b3536cf-3a12-457f-abb5-fa2203e0d923", + "relationship-data": [ + { + "relationship-key": "instance-group.id", + "relationship-value": "6b3536cf-3a12-457f-abb5-fa2203e0d923" + } + ], + "related-to-property": [ + { + "property-key": "instance-group.description", + "property-value": "vTSBC Customer Landing Network Collection Desc" + }, + { + "property-key": "instance-group.instance-group-name", + "property-value": "NcmVlanSvcYm161f_77_vTSBC Customer Landing Network Collection" + } + ] + } + ] + }, + "resource-version": "1539158498209" +} diff --git a/vid-app-common/src/test/resources/getTopology/serviceWithCR/getTopologyWithCR.json b/vid-app-common/src/test/resources/getTopology/serviceWithCR/getTopologyWithCR.json new file mode 100644 index 000000000..f038427c5 --- /dev/null +++ b/vid-app-common/src/test/resources/getTopology/serviceWithCR/getTopologyWithCR.json @@ -0,0 +1,95 @@ +{ + "action": "None", + "instanceName": "NcmVlanSvcYm161f_77", + "instanceId": "a565e6ad-75d1-4493-98f1-33234b5c17e2", + "orchStatus": "Assigned", + "productFamilyId": null, + "lcpCloudRegionId": null, + "tenantId": null, + "cloudOwner": null, + "modelInfo": { + "modelInvariantId": "f6342be5-d66b-4d03-a1aa-c82c3094c4ea", + "modelVersionId": "6e0bec91-09f3-43aa-9cf3-e617cd0146be", + "modelName": "NCM_VLAN_SVC_ym161f", + "modelType": "service", + "modelVersion": "8.0" + }, + "globalSubscriberId": "a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb", + "subscriptionServiceType": "Emanuel", + "owningEntityId": null, + "owningEntityName": null, + "tenantName": null, + "aicZoneId": null, + "aicZoneName": null, + "projectName": null, + "rollbackOnFailure": null, + "isALaCarte": false, + "vnfs": {}, + "networks": {}, + "vrfs": {}, + "vnfGroups": {}, + "collectionResources": { + "84a351ae-3601-45e2-98df-878d6c816abc": { + "action": "None", + "instanceName": "NcmVlanSvcYm161f_77_vTSBC Customer Landing Network Collection", + "instanceId": "84a351ae-3601-45e2-98df-878d6c816abc", + "orchStatus": "Active", + "productFamilyId": null, + "lcpCloudRegionId": null, + "tenantId": null, + "cloudOwner": null, + "modelInfo": { + "modelInvariantId": "081ceb56-eb71-4566-a72d-3e7cbee5cdf1", + "modelVersionId": "ce8c98bc-4691-44fb-8ff0-7a47487c11c4", + "modelName": "NCM_VLAN_ym161f", + "modelType": "collection", + "modelVersion": "5.0" + }, + "instanceType": null, + "provStatus": null, + "inMaint": false, + "uuid": "ce8c98bc-4691-44fb-8ff0-7a47487c11c4", + "originalName": "NCM_VLAN_ym161f 0", + "legacyRegion": null, + "lineOfBusiness": null, + "platformName": null, + "trackById": "84a351ae-3601-45e2-98df-878d6c816abc", + "ncfs": { + "6b3536cf-3a12-457f-abb5-fa2203e0d923": { + "action": "None", + "instanceName": "NcmVlanSvcYm161f_77_vTSBC Customer Landing Network Collection", + "instanceId": "6b3536cf-3a12-457f-abb5-fa2203e0d923", + "orchStatus": null, + "productFamilyId": null, + "lcpCloudRegionId": null, + "tenantId": null, + "cloudOwner": null, + "modelInfo": { + "modelInvariantId": "868b109c-9481-4a18-891b-af974db7705a", + "modelVersionId": "dd182d7d-6949-4b90-b3cc-5befe400742e", + "modelName": "ncm_vlan_ym161f..NetworkCollection..0", + "modelType": "instanceGroup", + "modelVersion": "1" + }, + "instanceType": "L3-NETWORK", + "provStatus": null, + "inMaint": false, + "uuid": "dd182d7d-6949-4b90-b3cc-5befe400742e", + "originalName": "ncm_vlan_ym161f..NetworkCollection..0", + "legacyRegion": null, + "lineOfBusiness": null, + "platformName": null, + "trackById": "6b3536cf-3a12-457f-abb5-fa2203e0d923", + "instanceGroupRole": "SUB_INTERFACE", + "instanceGroupFunction": "vTSBC Customer Landing Network Collection", + "numberOfNetworks": 1 + } + } + } + }, + "validationCounter": 0, + "existingVNFCounterMap": {}, + "existingNetworksCounterMap": {}, + "existingVnfGroupCounterMap": {}, + "existingVRFCounterMap": {} +} diff --git a/vid-app-common/src/test/resources/getTopology/serviceWithCR/instanceGroup-NCF.json b/vid-app-common/src/test/resources/getTopology/serviceWithCR/instanceGroup-NCF.json new file mode 100644 index 000000000..8c4d3f26c --- /dev/null +++ b/vid-app-common/src/test/resources/getTopology/serviceWithCR/instanceGroup-NCF.json @@ -0,0 +1,43 @@ +{ + "id": "6b3536cf-3a12-457f-abb5-fa2203e0d923", + "instance-group-role": "SUB_INTERFACE", + "model-invariant-id": "868b109c-9481-4a18-891b-af974db7705a", + "model-version-id": "dd182d7d-6949-4b90-b3cc-5befe400742e", + "description": "vTSBC Customer Landing Network Collection Desc", + "instance-group-type": "L3-NETWORK", + "resource-version": "1539158492730", + "instance-group-name": "NcmVlanSvcYm161f_77_vTSBC Customer Landing Network Collection", + "instance-group-function": "vTSBC Customer Landing Network Collection", + "relationship-list": { + "relationship": [ + { + "related-to-property": [ + { + "property-value": "APPC-24595-T-IST-02AShared_cps_internal_net_1", + "property-key": "l3-network.network-name" + } + ], + "relationship-data": [ + { + "relationship-value": "1fea0624-dac2-4997-904d-34ca1bc12fa9", + "relationship-key": "l3-network.network-id" + } + ], + "related-link": "/aai/v14/network/l3-networks/l3-network/1fea0624-dac2-4997-904d-34ca1bc12fa9", + "relationship-label": "org.onap.relationships.inventory.ComposedOf", + "related-to": "l3-network" + }, + { + "related-to": "collection", + "relationship-label": "org.onap.inventory.BelongsTo", + "related-link": "/aai/v14/network/collections/collection/84a351ae-3601-45e2-98df-878d6c816abc", + "relationship-data": [ + { + "relationship-key": "collection.collection-id", + "relationship-value": "84a351ae-3601-45e2-98df-878d6c816abc" + } + ] + } + ] + } +} \ No newline at end of file diff --git a/vid-app-common/src/test/resources/getTopology/serviceWithCR/service-design-and-creation.json b/vid-app-common/src/test/resources/getTopology/serviceWithCR/service-design-and-creation.json new file mode 100644 index 000000000..d7bafebfe --- /dev/null +++ b/vid-app-common/src/test/resources/getTopology/serviceWithCR/service-design-and-creation.json @@ -0,0 +1,1057 @@ +{ + "model": [ + { + "model-invariant-id": "f6342be5-d66b-4d03-a1aa-c82c3094c4ea", + "model-type": "service", + "resource-version": "1534274421300", + "model-vers": { + "model-ver": [ + { + "model-version-id": "a92f899d-a3ec-465b-baed-1663b0a5aee1", + "model-name": "NCM_VLAN_SVC_ym161f", + "model-version": "3.0", + "distribution-status": "DISTRIBUTION_COMPLETE_OK", + "model-description": "Network Collection service for vLAN tagging", + "resource-version": "1534788756086", + "model-elements": { + "model-element": [ + { + "model-element-uuid": "901e2641-c66c-4178-a6e8-cbe2877b0a2a", + "new-data-del-flag": "T", + "cardinality": "unbounded", + "resource-version": "1534463243387", + "relationship-list": { + "relationship": [ + { + "related-to": "model-ver", + "relationship-label": "org.onap.relationships.inventory.IsA", + "related-link": "/aai/v14/service-design-and-creation/models/model/82194af1-3c2c-485a-8f44-420e22a9eaa4/model-vers/model-ver/46b92144-923a-4d20-b85a-3cbd847668a9", + "relationship-data": [ + { + "relationship-key": "model.model-invariant-id", + "relationship-value": "82194af1-3c2c-485a-8f44-420e22a9eaa4" + }, + { + "relationship-key": "model-ver.model-version-id", + "relationship-value": "46b92144-923a-4d20-b85a-3cbd847668a9" + } + ], + "related-to-property": [ + { + "property-key": "model-ver.model-name", + "property-value": "service-instance" + } + ] + } + ] + } + } + ] + } + }, + { + "model-version-id": "d2fda667-e92e-4cfa-9620-5da5de01a319", + "model-name": "NCM_VLAN_SVC_ym161f", + "model-version": "1.0", + "distribution-status": "DISTRIBUTION_COMPLETE_OK", + "model-description": "Network Collection service for vLAN tagging", + "resource-version": "1534444087221", + "model-elements": { + "model-element": [ + { + "model-element-uuid": "d291ed5e-4f50-4f57-956d-ce0e67a059e5", + "new-data-del-flag": "T", + "cardinality": "unbounded", + "resource-version": "1534274421311", + "relationship-list": { + "relationship": [ + { + "related-to": "model-ver", + "relationship-label": "org.onap.relationships.inventory.IsA", + "related-link": "/aai/v14/service-design-and-creation/models/model/82194af1-3c2c-485a-8f44-420e22a9eaa4/model-vers/model-ver/46b92144-923a-4d20-b85a-3cbd847668a9", + "relationship-data": [ + { + "relationship-key": "model.model-invariant-id", + "relationship-value": "82194af1-3c2c-485a-8f44-420e22a9eaa4" + }, + { + "relationship-key": "model-ver.model-version-id", + "relationship-value": "46b92144-923a-4d20-b85a-3cbd847668a9" + } + ], + "related-to-property": [ + { + "property-key": "model-ver.model-name", + "property-value": "service-instance" + } + ] + } + ] + } + } + ] + } + }, + { + "model-version-id": "d4a447e5-9791-47b9-b365-1abb19b4b626", + "model-name": "NCM_VLAN_SVC_ym161f", + "model-version": "4.0", + "model-description": "Network Collection service for vLAN tagging", + "resource-version": "1534863624237", + "model-elements": { + "model-element": [ + { + "model-element-uuid": "0ef29f1f-836a-4fab-986c-5f1b96310a3d", + "new-data-del-flag": "T", + "cardinality": "unbounded", + "resource-version": "1534863624242", + "relationship-list": { + "relationship": [ + { + "related-to": "model-ver", + "relationship-label": "org.onap.relationships.inventory.IsA", + "related-link": "/aai/v14/service-design-and-creation/models/model/82194af1-3c2c-485a-8f44-420e22a9eaa4/model-vers/model-ver/46b92144-923a-4d20-b85a-3cbd847668a9", + "relationship-data": [ + { + "relationship-key": "model.model-invariant-id", + "relationship-value": "82194af1-3c2c-485a-8f44-420e22a9eaa4" + }, + { + "relationship-key": "model-ver.model-version-id", + "relationship-value": "46b92144-923a-4d20-b85a-3cbd847668a9" + } + ], + "related-to-property": [ + { + "property-key": "model-ver.model-name", + "property-value": "service-instance" + } + ] + } + ] + } + } + ] + } + }, + { + "model-version-id": "0e97a118-b1b6-40d5-bbad-98cdd51b1c48", + "model-name": "NCM_VLAN_SVC_ym161f", + "model-version": "11.0", + "distribution-status": "DISTRIBUTION_COMPLETE_OK", + "model-description": "Network Collection service for vLAN tagging", + "resource-version": "1550783120267", + "model-elements": { + "model-element": [ + { + "model-element-uuid": "0ea8ac21-64b8-4489-9d62-12e625d66995", + "new-data-del-flag": "T", + "cardinality": "unbounded", + "resource-version": "1543961990189", + "relationship-list": { + "relationship": [ + { + "related-to": "model-ver", + "relationship-label": "org.onap.relationships.inventory.IsA", + "related-link": "/aai/v14/service-design-and-creation/models/model/82194af1-3c2c-485a-8f44-420e22a9eaa4/model-vers/model-ver/46b92144-923a-4d20-b85a-3cbd847668a9", + "relationship-data": [ + { + "relationship-key": "model.model-invariant-id", + "relationship-value": "82194af1-3c2c-485a-8f44-420e22a9eaa4" + }, + { + "relationship-key": "model-ver.model-version-id", + "relationship-value": "46b92144-923a-4d20-b85a-3cbd847668a9" + } + ], + "related-to-property": [ + { + "property-key": "model-ver.model-name", + "property-value": "service-instance" + } + ] + } + ] + } + } + ] + } + }, + { + "model-version-id": "46093d8f-6dfa-4332-9c00-7e822c681b59", + "model-name": "NCM_VLAN_SVC_ym161f", + "model-version": "7.0", + "distribution-status": "DISTRIBUTION_COMPLETE_OK", + "model-description": "Network Collection service for vLAN tagging", + "resource-version": "1534885144462", + "model-elements": { + "model-element": [ + { + "model-element-uuid": "d74a5dff-ef7f-4e32-9c13-d82fb2c617c9", + "new-data-del-flag": "T", + "cardinality": "unbounded", + "resource-version": "1534885014144", + "relationship-list": { + "relationship": [ + { + "related-to": "model-ver", + "relationship-label": "org.onap.relationships.inventory.IsA", + "related-link": "/aai/v14/service-design-and-creation/models/model/82194af1-3c2c-485a-8f44-420e22a9eaa4/model-vers/model-ver/46b92144-923a-4d20-b85a-3cbd847668a9", + "relationship-data": [ + { + "relationship-key": "model.model-invariant-id", + "relationship-value": "82194af1-3c2c-485a-8f44-420e22a9eaa4" + }, + { + "relationship-key": "model-ver.model-version-id", + "relationship-value": "46b92144-923a-4d20-b85a-3cbd847668a9" + } + ], + "related-to-property": [ + { + "property-key": "model-ver.model-name", + "property-value": "service-instance" + } + ] + } + ] + } + } + ] + } + }, + { + "model-version-id": "12930bcc-5276-42bb-8ed6-1e43d7acae2c", + "model-name": "NCM_VLAN_SVC_ym161f", + "model-version": "10.0", + "distribution-status": "DISTRIBUTION_COMPLETE_OK", + "model-description": "Network Collection service for vLAN tagging", + "resource-version": "1539613511543", + "model-elements": { + "model-element": [ + { + "model-element-uuid": "4d57798e-81b7-490e-bee8-48bd382a1349", + "new-data-del-flag": "T", + "cardinality": "unbounded", + "resource-version": "1539613450903", + "relationship-list": { + "relationship": [ + { + "related-to": "model-ver", + "relationship-label": "org.onap.relationships.inventory.IsA", + "related-link": "/aai/v14/service-design-and-creation/models/model/82194af1-3c2c-485a-8f44-420e22a9eaa4/model-vers/model-ver/46b92144-923a-4d20-b85a-3cbd847668a9", + "relationship-data": [ + { + "relationship-key": "model.model-invariant-id", + "relationship-value": "82194af1-3c2c-485a-8f44-420e22a9eaa4" + }, + { + "relationship-key": "model-ver.model-version-id", + "relationship-value": "46b92144-923a-4d20-b85a-3cbd847668a9" + } + ], + "related-to-property": [ + { + "property-key": "model-ver.model-name", + "property-value": "service-instance" + } + ] + } + ] + } + } + ] + } + }, + { + "model-version-id": "f8783bb2-6135-4c35-8320-64fa7deae76b", + "model-name": "NCM_VLAN_SVC_ym161f", + "model-version": "2.0", + "distribution-status": "DISTRIBUTION_COMPLETE_OK", + "model-description": "Network Collection service for vLAN tagging", + "resource-version": "1534450229751", + "model-elements": { + "model-element": [ + { + "model-element-uuid": "c666f1dd-99ff-442a-9ba2-1ee2dabb9e25", + "new-data-del-flag": "T", + "cardinality": "unbounded", + "resource-version": "1534450167963", + "relationship-list": { + "relationship": [ + { + "related-to": "model-ver", + "relationship-label": "org.onap.relationships.inventory.IsA", + "related-link": "/aai/v14/service-design-and-creation/models/model/82194af1-3c2c-485a-8f44-420e22a9eaa4/model-vers/model-ver/46b92144-923a-4d20-b85a-3cbd847668a9", + "relationship-data": [ + { + "relationship-key": "model.model-invariant-id", + "relationship-value": "82194af1-3c2c-485a-8f44-420e22a9eaa4" + }, + { + "relationship-key": "model-ver.model-version-id", + "relationship-value": "46b92144-923a-4d20-b85a-3cbd847668a9" + } + ], + "related-to-property": [ + { + "property-key": "model-ver.model-name", + "property-value": "service-instance" + } + ] + } + ] + } + } + ] + } + }, + { + "model-version-id": "0148e4c5-629b-4fef-9728-1e13fd630679", + "model-name": "NCM_VLAN_SVC_ym161f", + "model-version": "9.0", + "distribution-status": "DISTRIBUTION_COMPLETE_OK", + "model-description": "Network Collection service for vLAN tagging", + "resource-version": "1537901614540", + "model-elements": { + "model-element": [ + { + "model-element-uuid": "6ae6fd91-2086-470d-8c36-9d668c41fd32", + "new-data-del-flag": "T", + "cardinality": "unbounded", + "resource-version": "1537882880185", + "relationship-list": { + "relationship": [ + { + "related-to": "model-ver", + "relationship-label": "org.onap.relationships.inventory.IsA", + "related-link": "/aai/v14/service-design-and-creation/models/model/82194af1-3c2c-485a-8f44-420e22a9eaa4/model-vers/model-ver/46b92144-923a-4d20-b85a-3cbd847668a9", + "relationship-data": [ + { + "relationship-key": "model.model-invariant-id", + "relationship-value": "82194af1-3c2c-485a-8f44-420e22a9eaa4" + }, + { + "relationship-key": "model-ver.model-version-id", + "relationship-value": "46b92144-923a-4d20-b85a-3cbd847668a9" + } + ], + "related-to-property": [ + { + "property-key": "model-ver.model-name", + "property-value": "service-instance" + } + ] + } + ] + } + } + ] + } + }, + { + "model-version-id": "1ceab842-7ded-49f1-a129-dce2ecef8c71", + "model-name": "NCM_VLAN_SVC_ym161f", + "model-version": "6.0", + "distribution-status": "DISTRIBUTION_COMPLETE_OK", + "model-description": "Network Collection service for vLAN tagging", + "resource-version": "1534883213652", + "model-elements": { + "model-element": [ + { + "model-element-uuid": "5ca853fc-2984-45c7-b2e7-8514a56785ba", + "new-data-del-flag": "T", + "cardinality": "unbounded", + "resource-version": "1534883154090", + "relationship-list": { + "relationship": [ + { + "related-to": "model-ver", + "relationship-label": "org.onap.relationships.inventory.IsA", + "related-link": "/aai/v14/service-design-and-creation/models/model/82194af1-3c2c-485a-8f44-420e22a9eaa4/model-vers/model-ver/46b92144-923a-4d20-b85a-3cbd847668a9", + "relationship-data": [ + { + "relationship-key": "model.model-invariant-id", + "relationship-value": "82194af1-3c2c-485a-8f44-420e22a9eaa4" + }, + { + "relationship-key": "model-ver.model-version-id", + "relationship-value": "46b92144-923a-4d20-b85a-3cbd847668a9" + } + ], + "related-to-property": [ + { + "property-key": "model-ver.model-name", + "property-value": "service-instance" + } + ] + } + ] + } + } + ] + } + }, + { + "model-version-id": "fd21f6b5-02f6-4ac0-9515-e1f01112da95", + "model-name": "NCM_VLAN_SVC_ym161f", + "model-version": "5.0", + "distribution-status": "DISTRIBUTION_COMPLETE_OK", + "model-description": "Network Collection service for vLAN tagging", + "resource-version": "1534872246413", + "model-elements": { + "model-element": [ + { + "model-element-uuid": "0812b47d-7ef1-4a65-b6fb-9f3ff3bc3eee", + "new-data-del-flag": "T", + "cardinality": "unbounded", + "resource-version": "1534872174141", + "relationship-list": { + "relationship": [ + { + "related-to": "model-ver", + "relationship-label": "org.onap.relationships.inventory.IsA", + "related-link": "/aai/v14/service-design-and-creation/models/model/82194af1-3c2c-485a-8f44-420e22a9eaa4/model-vers/model-ver/46b92144-923a-4d20-b85a-3cbd847668a9", + "relationship-data": [ + { + "relationship-key": "model.model-invariant-id", + "relationship-value": "82194af1-3c2c-485a-8f44-420e22a9eaa4" + }, + { + "relationship-key": "model-ver.model-version-id", + "relationship-value": "46b92144-923a-4d20-b85a-3cbd847668a9" + } + ], + "related-to-property": [ + { + "property-key": "model-ver.model-name", + "property-value": "service-instance" + } + ] + } + ] + } + } + ] + } + }, + { + "model-version-id": "6e0bec91-09f3-43aa-9cf3-e617cd0146be", + "model-name": "NCM_VLAN_SVC_ym161f", + "model-version": "8.0", + "distribution-status": "DISTRIBUTION_COMPLETE_OK", + "model-description": "Network Collection service for vLAN tagging", + "resource-version": "1536098608209", + "model-elements": { + "model-element": [ + { + "model-element-uuid": "a0247d2e-3843-4753-be2f-4c252c99390e", + "new-data-del-flag": "T", + "cardinality": "unbounded", + "resource-version": "1536098548388", + "relationship-list": { + "relationship": [ + { + "related-to": "model-ver", + "relationship-label": "org.onap.relationships.inventory.IsA", + "related-link": "/aai/v14/service-design-and-creation/models/model/82194af1-3c2c-485a-8f44-420e22a9eaa4/model-vers/model-ver/46b92144-923a-4d20-b85a-3cbd847668a9", + "relationship-data": [ + { + "relationship-key": "model.model-invariant-id", + "relationship-value": "82194af1-3c2c-485a-8f44-420e22a9eaa4" + }, + { + "relationship-key": "model-ver.model-version-id", + "relationship-value": "46b92144-923a-4d20-b85a-3cbd847668a9" + } + ], + "related-to-property": [ + { + "property-key": "model-ver.model-name", + "property-value": "service-instance" + } + ] + } + ] + } + } + ] + } + } + ] + } + }, + { + "model-invariant-id": "868b109c-9481-4a18-891b-af974db7705a", + "model-type": "resource", + "resource-version": "1534795610752", + "model-vers": { + "model-ver": [ + { + "model-version-id": "dd182d7d-6949-4b90-b3cc-5befe400742e", + "model-name": "ncm_vlan_ym161f..NetworkCollection..0", + "model-version": "1", + "distribution-status": "DISTRIBUTION_COMPLETE_OK", + "resource-version": "1534795610763" + }, + { + "model-version-id": "e5fc56b7-e14c-45e5-b127-978c36a921c0", + "model-name": "ncm_vlan_ym161f..NetworkCollection..0", + "model-version": "1", + "resource-version": "1543961989136", + "model-elements": { + "model-element": [ + { + "model-element-uuid": "9001ff96-1142-49c6-af5b-df4e2b23a305", + "new-data-del-flag": "T", + "cardinality": "unbounded", + "resource-version": "1543961989136", + "relationship-list": { + "relationship": [ + { + "related-to": "model-ver", + "relationship-label": "org.onap.relationships.inventory.IsA", + "related-link": "/aai/v14/service-design-and-creation/models/model/3bf1e610-45f7-4ad6-b833-ca4c5ee6a3fd/model-vers/model-ver/8e6ee9dc-9017-444a-83b3-219edb018128", + "relationship-data": [ + { + "relationship-key": "model.model-invariant-id", + "relationship-value": "3bf1e610-45f7-4ad6-b833-ca4c5ee6a3fd" + }, + { + "relationship-key": "model-ver.model-version-id", + "relationship-value": "8e6ee9dc-9017-444a-83b3-219edb018128" + } + ], + "related-to-property": [ + { + "property-key": "model-ver.model-name", + "property-value": "instance-group" + } + ] + } + ] + } + } + ] + }, + "relationship-list": { + "relationship": [ + { + "related-to": "model-element", + "relationship-label": "org.onap.relationships.inventory.IsA", + "related-link": "/aai/v14/service-design-and-creation/models/model/081ceb56-eb71-4566-a72d-3e7cbee5cdf1/model-vers/model-ver/a580855f-8d1b-40d5-a75b-50709fbd17d3/model-elements/model-element/06014449-69d3-4aef-a96b-0a5130ba9483/model-elements/model-element/a050dc96-2c35-45c7-ba23-9279215d501e", + "relationship-data": [ + { + "relationship-key": "model.model-invariant-id", + "relationship-value": "081ceb56-eb71-4566-a72d-3e7cbee5cdf1" + }, + { + "relationship-key": "model-ver.model-version-id", + "relationship-value": "a580855f-8d1b-40d5-a75b-50709fbd17d3" + }, + { + "relationship-key": "model-element.model-element-uuid", + "relationship-value": "06014449-69d3-4aef-a96b-0a5130ba9483" + }, + { + "relationship-key": "model-element.model-element-uuid", + "relationship-value": "a050dc96-2c35-45c7-ba23-9279215d501e" + } + ] + } + ] + } + } + ] + } + }, + { + "model-invariant-id": "081ceb56-eb71-4566-a72d-3e7cbee5cdf1", + "model-type": "resource", + "resource-version": "1534788713816", + "model-vers": { + "model-ver": [ + { + "model-version-id": "747d2a17-5771-4fd6-879d-c2e9e4c5cd4f", + "model-name": "NCM_VLAN_ym161f", + "model-version": "2.0", + "model-description": "Network Collection Service VF for VLAN TAgging", + "resource-version": "1534863623891", + "model-elements": { + "model-element": [ + { + "model-element-uuid": "0dd28c63-cadf-48b2-afb0-a7bf7184ef5a", + "new-data-del-flag": "T", + "cardinality": "unbounded", + "resource-version": "1534863623895", + "relationship-list": { + "relationship": [ + { + "related-to": "model-ver", + "relationship-label": "org.onap.relationships.inventory.IsA", + "related-link": "/aai/v14/service-design-and-creation/models/model/425b2158-e51d-4509-9945-dad4556474a3/model-vers/model-ver/2a160989-b202-47dd-874b-4a0f275998f7", + "relationship-data": [ + { + "relationship-key": "model.model-invariant-id", + "relationship-value": "425b2158-e51d-4509-9945-dad4556474a3" + }, + { + "relationship-key": "model-ver.model-version-id", + "relationship-value": "2a160989-b202-47dd-874b-4a0f275998f7" + } + ], + "related-to-property": [ + { + "property-key": "model-ver.model-name", + "property-value": "cloud-region" + } + ] + } + ] + } + } + ] + }, + "relationship-list": { + "relationship": [ + { + "related-to": "model-element", + "relationship-label": "org.onap.relationships.inventory.IsA", + "related-link": "/aai/v14/service-design-and-creation/models/model/f6342be5-d66b-4d03-a1aa-c82c3094c4ea/model-vers/model-ver/d4a447e5-9791-47b9-b365-1abb19b4b626/model-elements/model-element/0ef29f1f-836a-4fab-986c-5f1b96310a3d/model-elements/model-element/700f890b-05c9-471a-b859-956655d28f47", + "relationship-data": [ + { + "relationship-key": "model.model-invariant-id", + "relationship-value": "f6342be5-d66b-4d03-a1aa-c82c3094c4ea" + }, + { + "relationship-key": "model-ver.model-version-id", + "relationship-value": "d4a447e5-9791-47b9-b365-1abb19b4b626" + }, + { + "relationship-key": "model-element.model-element-uuid", + "relationship-value": "0ef29f1f-836a-4fab-986c-5f1b96310a3d" + }, + { + "relationship-key": "model-element.model-element-uuid", + "relationship-value": "700f890b-05c9-471a-b859-956655d28f47" + } + ] + } + ] + } + }, + { + "model-version-id": "a580855f-8d1b-40d5-a75b-50709fbd17d3", + "model-name": "NCM_VLAN_ym161f", + "model-version": "6.0", + "model-description": "Network Collection Service VF for VLAN TAgging", + "resource-version": "1543961989670", + "model-elements": { + "model-element": [ + { + "model-element-uuid": "06014449-69d3-4aef-a96b-0a5130ba9483", + "new-data-del-flag": "T", + "cardinality": "unbounded", + "resource-version": "1543961989670", + "relationship-list": { + "relationship": [ + { + "related-to": "model-ver", + "relationship-label": "org.onap.relationships.inventory.IsA", + "related-link": "/aai/v14/service-design-and-creation/models/model/8bac3599-9a1c-4b7f-80e5-c1838f744c23/model-vers/model-ver/3f908abc-3a15-40d0-b674-2a639e52884d", + "relationship-data": [ + { + "relationship-key": "model.model-invariant-id", + "relationship-value": "8bac3599-9a1c-4b7f-80e5-c1838f744c23" + }, + { + "relationship-key": "model-ver.model-version-id", + "relationship-value": "3f908abc-3a15-40d0-b674-2a639e52884d" + } + ], + "related-to-property": [ + { + "property-key": "model-ver.model-name", + "property-value": "collection" + } + ] + } + ] + } + } + ] + }, + "relationship-list": { + "relationship": [ + { + "related-to": "model-element", + "relationship-label": "org.onap.relationships.inventory.IsA", + "related-link": "/aai/v14/service-design-and-creation/models/model/f6342be5-d66b-4d03-a1aa-c82c3094c4ea/model-vers/model-ver/0e97a118-b1b6-40d5-bbad-98cdd51b1c48/model-elements/model-element/0ea8ac21-64b8-4489-9d62-12e625d66995/model-elements/model-element/d614653c-5f19-4668-ad98-cfbe012308e1", + "relationship-data": [ + { + "relationship-key": "model.model-invariant-id", + "relationship-value": "f6342be5-d66b-4d03-a1aa-c82c3094c4ea" + }, + { + "relationship-key": "model-ver.model-version-id", + "relationship-value": "0e97a118-b1b6-40d5-bbad-98cdd51b1c48" + }, + { + "relationship-key": "model-element.model-element-uuid", + "relationship-value": "0ea8ac21-64b8-4489-9d62-12e625d66995" + }, + { + "relationship-key": "model-element.model-element-uuid", + "relationship-value": "d614653c-5f19-4668-ad98-cfbe012308e1" + } + ] + } + ] + } + }, + { + "model-version-id": "b84e2233-37bf-4c8d-b613-eb8a8820b725", + "model-name": "NCM_VLAN_ym161f", + "model-version": "4.0", + "model-description": "Network Collection Service VF for VLAN TAgging", + "resource-version": "1534883153714", + "model-elements": { + "model-element": [ + { + "model-element-uuid": "f7c3f5bb-777a-4d9f-9401-a652f5006152", + "new-data-del-flag": "T", + "cardinality": "unbounded", + "resource-version": "1534883153720", + "relationship-list": { + "relationship": [ + { + "related-to": "model-ver", + "relationship-label": "org.onap.relationships.inventory.IsA", + "related-link": "/aai/v14/service-design-and-creation/models/model/425b2158-e51d-4509-9945-dad4556474a3/model-vers/model-ver/2a160989-b202-47dd-874b-4a0f275998f7", + "relationship-data": [ + { + "relationship-key": "model.model-invariant-id", + "relationship-value": "425b2158-e51d-4509-9945-dad4556474a3" + }, + { + "relationship-key": "model-ver.model-version-id", + "relationship-value": "2a160989-b202-47dd-874b-4a0f275998f7" + } + ], + "related-to-property": [ + { + "property-key": "model-ver.model-name", + "property-value": "cloud-region" + } + ] + } + ] + } + } + ] + }, + "relationship-list": { + "relationship": [ + { + "related-to": "model-element", + "relationship-label": "org.onap.relationships.inventory.IsA", + "related-link": "/aai/v14/service-design-and-creation/models/model/f6342be5-d66b-4d03-a1aa-c82c3094c4ea/model-vers/model-ver/1ceab842-7ded-49f1-a129-dce2ecef8c71/model-elements/model-element/5ca853fc-2984-45c7-b2e7-8514a56785ba/model-elements/model-element/030553aa-8d82-4b03-a3dc-bc210daadd5e", + "relationship-data": [ + { + "relationship-key": "model.model-invariant-id", + "relationship-value": "f6342be5-d66b-4d03-a1aa-c82c3094c4ea" + }, + { + "relationship-key": "model-ver.model-version-id", + "relationship-value": "1ceab842-7ded-49f1-a129-dce2ecef8c71" + }, + { + "relationship-key": "model-element.model-element-uuid", + "relationship-value": "5ca853fc-2984-45c7-b2e7-8514a56785ba" + }, + { + "relationship-key": "model-element.model-element-uuid", + "relationship-value": "030553aa-8d82-4b03-a3dc-bc210daadd5e" + } + ] + } + ] + } + }, + { + "model-version-id": "5ededaad-905c-4356-b30d-471b0ae2a12a", + "model-name": "NCM_VLAN_ym161f", + "model-version": "3.0", + "model-description": "Network Collection Service VF for VLAN TAgging", + "resource-version": "1534872173817", + "model-elements": { + "model-element": [ + { + "model-element-uuid": "31f558c6-d73a-43e4-aab0-c863ccd6b110", + "new-data-del-flag": "T", + "cardinality": "unbounded", + "resource-version": "1534872173821", + "relationship-list": { + "relationship": [ + { + "related-to": "model-ver", + "relationship-label": "org.onap.relationships.inventory.IsA", + "related-link": "/aai/v14/service-design-and-creation/models/model/425b2158-e51d-4509-9945-dad4556474a3/model-vers/model-ver/2a160989-b202-47dd-874b-4a0f275998f7", + "relationship-data": [ + { + "relationship-key": "model.model-invariant-id", + "relationship-value": "425b2158-e51d-4509-9945-dad4556474a3" + }, + { + "relationship-key": "model-ver.model-version-id", + "relationship-value": "2a160989-b202-47dd-874b-4a0f275998f7" + } + ], + "related-to-property": [ + { + "property-key": "model-ver.model-name", + "property-value": "cloud-region" + } + ] + } + ] + } + } + ] + }, + "relationship-list": { + "relationship": [ + { + "related-to": "model-element", + "relationship-label": "org.onap.relationships.inventory.IsA", + "related-link": "/aai/v14/service-design-and-creation/models/model/f6342be5-d66b-4d03-a1aa-c82c3094c4ea/model-vers/model-ver/fd21f6b5-02f6-4ac0-9515-e1f01112da95/model-elements/model-element/0812b47d-7ef1-4a65-b6fb-9f3ff3bc3eee/model-elements/model-element/110a5ba4-997b-45f0-8e53-d64d6b342be1", + "relationship-data": [ + { + "relationship-key": "model.model-invariant-id", + "relationship-value": "f6342be5-d66b-4d03-a1aa-c82c3094c4ea" + }, + { + "relationship-key": "model-ver.model-version-id", + "relationship-value": "fd21f6b5-02f6-4ac0-9515-e1f01112da95" + }, + { + "relationship-key": "model-element.model-element-uuid", + "relationship-value": "0812b47d-7ef1-4a65-b6fb-9f3ff3bc3eee" + }, + { + "relationship-key": "model-element.model-element-uuid", + "relationship-value": "110a5ba4-997b-45f0-8e53-d64d6b342be1" + } + ] + } + ] + } + }, + { + "model-version-id": "67b91dcd-4fa5-4111-80c9-60d524740667", + "model-name": "NCM_VLAN_ym161f", + "model-version": "1.0", + "model-description": "Network Collection Service VF for VLAN TAgging", + "resource-version": "1534788713822", + "model-elements": { + "model-element": [ + { + "model-element-uuid": "6fdf228e-89ce-4cf6-9bd7-399aa1b690b3", + "new-data-del-flag": "T", + "cardinality": "unbounded", + "resource-version": "1534788713833", + "relationship-list": { + "relationship": [ + { + "related-to": "model-ver", + "relationship-label": "org.onap.relationships.inventory.IsA", + "related-link": "/aai/v14/service-design-and-creation/models/model/425b2158-e51d-4509-9945-dad4556474a3/model-vers/model-ver/2a160989-b202-47dd-874b-4a0f275998f7", + "relationship-data": [ + { + "relationship-key": "model.model-invariant-id", + "relationship-value": "425b2158-e51d-4509-9945-dad4556474a3" + }, + { + "relationship-key": "model-ver.model-version-id", + "relationship-value": "2a160989-b202-47dd-874b-4a0f275998f7" + } + ], + "related-to-property": [ + { + "property-key": "model-ver.model-name", + "property-value": "cloud-region" + } + ] + } + ] + } + } + ] + } + }, + { + "model-version-id": "ce8c98bc-4691-44fb-8ff0-7a47487c11c4", + "model-name": "NCM_VLAN_ym161f", + "model-version": "5.0", + "model-description": "Network Collection Service VF for VLAN TAgging", + "resource-version": "1534885013739", + "model-elements": { + "model-element": [ + { + "model-element-uuid": "4bd10473-a9de-4399-abe7-c9b24e48e0ee", + "new-data-del-flag": "T", + "cardinality": "unbounded", + "resource-version": "1534885013745", + "relationship-list": { + "relationship": [ + { + "related-to": "model-ver", + "relationship-label": "org.onap.relationships.inventory.IsA", + "related-link": "/aai/v14/service-design-and-creation/models/model/425b2158-e51d-4509-9945-dad4556474a3/model-vers/model-ver/2a160989-b202-47dd-874b-4a0f275998f7", + "relationship-data": [ + { + "relationship-key": "model.model-invariant-id", + "relationship-value": "425b2158-e51d-4509-9945-dad4556474a3" + }, + { + "relationship-key": "model-ver.model-version-id", + "relationship-value": "2a160989-b202-47dd-874b-4a0f275998f7" + } + ], + "related-to-property": [ + { + "property-key": "model-ver.model-name", + "property-value": "cloud-region" + } + ] + } + ] + } + } + ] + }, + "relationship-list": { + "relationship": [ + { + "related-to": "model-element", + "relationship-label": "org.onap.relationships.inventory.IsA", + "related-link": "/aai/v14/service-design-and-creation/models/model/f6342be5-d66b-4d03-a1aa-c82c3094c4ea/model-vers/model-ver/12930bcc-5276-42bb-8ed6-1e43d7acae2c/model-elements/model-element/4d57798e-81b7-490e-bee8-48bd382a1349/model-elements/model-element/93eafb42-11b5-471d-8f8a-333408114a9a", + "relationship-data": [ + { + "relationship-key": "model.model-invariant-id", + "relationship-value": "f6342be5-d66b-4d03-a1aa-c82c3094c4ea" + }, + { + "relationship-key": "model-ver.model-version-id", + "relationship-value": "12930bcc-5276-42bb-8ed6-1e43d7acae2c" + }, + { + "relationship-key": "model-element.model-element-uuid", + "relationship-value": "4d57798e-81b7-490e-bee8-48bd382a1349" + }, + { + "relationship-key": "model-element.model-element-uuid", + "relationship-value": "93eafb42-11b5-471d-8f8a-333408114a9a" + } + ] + }, + { + "related-to": "model-element", + "relationship-label": "org.onap.relationships.inventory.IsA", + "related-link": "/aai/v14/service-design-and-creation/models/model/f6342be5-d66b-4d03-a1aa-c82c3094c4ea/model-vers/model-ver/6e0bec91-09f3-43aa-9cf3-e617cd0146be/model-elements/model-element/a0247d2e-3843-4753-be2f-4c252c99390e/model-elements/model-element/cb986adf-5ca8-48a5-ac9b-b222d6d2e280", + "relationship-data": [ + { + "relationship-key": "model.model-invariant-id", + "relationship-value": "f6342be5-d66b-4d03-a1aa-c82c3094c4ea" + }, + { + "relationship-key": "model-ver.model-version-id", + "relationship-value": "6e0bec91-09f3-43aa-9cf3-e617cd0146be" + }, + { + "relationship-key": "model-element.model-element-uuid", + "relationship-value": "a0247d2e-3843-4753-be2f-4c252c99390e" + }, + { + "relationship-key": "model-element.model-element-uuid", + "relationship-value": "cb986adf-5ca8-48a5-ac9b-b222d6d2e280" + } + ] + }, + { + "related-to": "model-element", + "relationship-label": "org.onap.relationships.inventory.IsA", + "related-link": "/aai/v14/service-design-and-creation/models/model/f6342be5-d66b-4d03-a1aa-c82c3094c4ea/model-vers/model-ver/0148e4c5-629b-4fef-9728-1e13fd630679/model-elements/model-element/6ae6fd91-2086-470d-8c36-9d668c41fd32/model-elements/model-element/a520808b-b8bc-4969-9eba-c85e2797f3dd", + "relationship-data": [ + { + "relationship-key": "model.model-invariant-id", + "relationship-value": "f6342be5-d66b-4d03-a1aa-c82c3094c4ea" + }, + { + "relationship-key": "model-ver.model-version-id", + "relationship-value": "0148e4c5-629b-4fef-9728-1e13fd630679" + }, + { + "relationship-key": "model-element.model-element-uuid", + "relationship-value": "6ae6fd91-2086-470d-8c36-9d668c41fd32" + }, + { + "relationship-key": "model-element.model-element-uuid", + "relationship-value": "a520808b-b8bc-4969-9eba-c85e2797f3dd" + } + ] + }, + { + "related-to": "model-element", + "relationship-label": "org.onap.relationships.inventory.IsA", + "related-link": "/aai/v14/service-design-and-creation/models/model/ca26a7e6-064d-4e90-a5b9-32ffe819f826/model-vers/model-ver/e9a290ca-41f0-4117-a1b5-8b7cd5595ff7/model-elements/model-element/ff3fdeb9-24e9-406f-8761-1334c9ea29d1/model-elements/model-element/bc6ddc86-f948-4f47-a4e6-bededd8d5780", + "relationship-data": [ + { + "relationship-key": "model.model-invariant-id", + "relationship-value": "ca26a7e6-064d-4e90-a5b9-32ffe819f826" + }, + { + "relationship-key": "model-ver.model-version-id", + "relationship-value": "e9a290ca-41f0-4117-a1b5-8b7cd5595ff7" + }, + { + "relationship-key": "model-element.model-element-uuid", + "relationship-value": "ff3fdeb9-24e9-406f-8761-1334c9ea29d1" + }, + { + "relationship-key": "model-element.model-element-uuid", + "relationship-value": "bc6ddc86-f948-4f47-a4e6-bededd8d5780" + } + ] + }, + { + "related-to": "model-element", + "relationship-label": "org.onap.relationships.inventory.IsA", + "related-link": "/aai/v14/service-design-and-creation/models/model/f6342be5-d66b-4d03-a1aa-c82c3094c4ea/model-vers/model-ver/46093d8f-6dfa-4332-9c00-7e822c681b59/model-elements/model-element/d74a5dff-ef7f-4e32-9c13-d82fb2c617c9/model-elements/model-element/f7bd32b4-bbbf-4788-9137-9dfa299e6111", + "relationship-data": [ + { + "relationship-key": "model.model-invariant-id", + "relationship-value": "f6342be5-d66b-4d03-a1aa-c82c3094c4ea" + }, + { + "relationship-key": "model-ver.model-version-id", + "relationship-value": "46093d8f-6dfa-4332-9c00-7e822c681b59" + }, + { + "relationship-key": "model-element.model-element-uuid", + "relationship-value": "d74a5dff-ef7f-4e32-9c13-d82fb2c617c9" + }, + { + "relationship-key": "model-element.model-element-uuid", + "relationship-value": "f7bd32b4-bbbf-4788-9137-9dfa299e6111" + } + ] + } + ] + } + } + ] + } + } + ] +} diff --git a/vid-app-common/src/test/resources/getTopology/serviceWithCR/serviceWithCR.json b/vid-app-common/src/test/resources/getTopology/serviceWithCR/serviceWithCR.json new file mode 100644 index 000000000..7b9672966 --- /dev/null +++ b/vid-app-common/src/test/resources/getTopology/serviceWithCR/serviceWithCR.json @@ -0,0 +1,38 @@ +{ + "service-instance-id": "a565e6ad-75d1-4493-98f1-33234b5c17e2", + "service-instance-name": "NcmVlanSvcYm161f_77", + "service-type": "INFRASTRUCTURE", + "environment-context": "General_Revenue-Bearing", + "workload-context": "Production", + "model-invariant-id": "f6342be5-d66b-4d03-a1aa-c82c3094c4ea", + "model-version-id": "6e0bec91-09f3-43aa-9cf3-e617cd0146be", + "resource-version": "1539158502875", + "selflink": "restconf/config/GENERIC-RESOURCE-API:services/service/a565e6ad-75d1-4493-98f1-33234b5c17e2/service-data/service-topology/", + "orchestration-status": "Assigned", + "relationship-list": { + "relationship": [ + { + "related-to": "collection", + "relationship-label": "org.onap.relationships.inventory.ComposedOf", + "related-link": "/aai/v14/network/collections/collection/84a351ae-3601-45e2-98df-878d6c816abc", + "relationship-data": [ + { + "relationship-key": "collection.collection-id", + "relationship-value": "84a351ae-3601-45e2-98df-878d6c816abc" + } + ] + }, + { + "related-to": "owning-entity", + "relationship-label": "org.onap.relationships.inventory.BelongsTo", + "related-link": "/aai/v14/business/owning-entities/owning-entity/e4257a94-21cc-40c5-adc9-e6f4ff868e31", + "relationship-data": [ + { + "relationship-key": "owning-entity.owning-entity-id", + "relationship-value": "e4257a94-21cc-40c5-adc9-e6f4ff868e31" + } + ] + } + ] + } +} \ No newline at end of file diff --git a/vid-app-common/src/test/resources/getTopology/serviceWithCR/serviceWithCRModel.json b/vid-app-common/src/test/resources/getTopology/serviceWithCR/serviceWithCRModel.json new file mode 100644 index 000000000..6cca1cdc0 --- /dev/null +++ b/vid-app-common/src/test/resources/getTopology/serviceWithCR/serviceWithCRModel.json @@ -0,0 +1,72 @@ +{ + "service": { + "uuid": "6e0bec91-09f3-43aa-9cf3-e617cd0146be", + "invariantUuid": "f6342be5-d66b-4d03-a1aa-c82c3094c4ea", + "name": "NCM_VLAN_SVC_ym161f", + "version": "8.0", + "toscaModelURL": null, + "category": "Network L4+", + "serviceType": "INFRASTRUCTURE", + "serviceRole": "", + "description": "Network Collection service for vLAN tagging", + "serviceEcompNaming": "true", + "instantiationType": "Macro", + "inputs": {}, + "vidNotions": { + "instantiationType": "Macro", + "instantiationUI": "serviceWithCollectionResource", + "modelCategory": "other", + "viewEditUI": "serviceWithCollectionResource" + } + }, + "vnfs": {}, + "networks": {}, + "collectionResources": { + "NCM_VLAN_ym161f 0": { + "uuid": "ce8c98bc-4691-44fb-8ff0-7a47487c11c4", + "invariantUuid": "081ceb56-eb71-4566-a72d-3e7cbee5cdf1", + "description": "Network Collection Service VF for VLAN TAgging", + "name": "NCM_VLAN_ym161f", + "version": "5.0", + "customizationUuid": "bac6ffe5-c851-495f-a64a-28751400ff03", + "inputs": {}, + "commands": {}, + "properties": { + "ncm_vlan_ym161f..Fixed..0_quantity": "3", + "cr_function": "vTSBC_function", + "ncm_vlan_ym161f..NetworkCollection..0_network_collection_description": "vTSBC Customer Landing Network Collection Desc", + "cr_role": "SUB_INTERFACE", + "cr_type": "L3-NETWORK", + "ecomp_generated_naming": "false", + "ncm_vlan_ym161f..NetworkCollection..0_network_collection_function": "vTSBC Customer Landing Network Collection" + }, + "type": "CR", + "category": "Generic", + "subcategory": "Infrastructure", + "resourceVendor": "ATT", + "resourceVendorRelease": "201810", + "resourceVendorModelNumber": "294455b", + "customizationUUID": "bac6ffe5-c851-495f-a64a-28751400ff03", + "networksCollection": { + "ncm_vlan_ym161f..NetworkCollection..0": { + "uuid": "dd182d7d-6949-4b90-b3cc-5befe400742e", + "invariantUuid": "868b109c-9481-4a18-891b-af974db7705a", + "name": "ncm_vlan_ym161f..NetworkCollection..0", + "version": "1", + "networkCollectionProperties": { + "networkCollectionFunction": "vTSBC Customer Landing Network Collection", + "networkCollectionDescription": "vTSBC Customer Landing Network Collection Desc" + } + } + } + } + }, + "configurations": {}, + "fabricConfigurations": {}, + "serviceProxies": {}, + "vfModules": {}, + "volumeGroups": {}, + "pnfs": {}, + "vnfGroups": {}, + "vrfs": {} +} diff --git a/vid-app-common/src/test/resources/getTopology/vfModule.json b/vid-app-common/src/test/resources/getTopology/vfModule.json new file mode 100644 index 000000000..3fd9c089e --- /dev/null +++ b/vid-app-common/src/test/resources/getTopology/vfModule.json @@ -0,0 +1,66 @@ +{ + "vf-module": [{ + "vf-module-id": "2cb6d41e-2bef-4cb2-80ce-c7815bcdcf4e", + "vf-module-name": "dyh3brarf8000v_base", + "heat-stack-id": "dyh3brarf8000v_base/5a826d59-cafa-49fd-9860-dfc6eb7515ae", + "orchestration-status": "Active", + "is-base-vf-module": true, + "automated-assignment": false, + "resource-version": "1546547784901", + "model-invariant-id": "3ecca473-b0c0-46ae-b0b7-bd2969d8b79f", + "model-version-id": "5c35b764-e266-4498-af87-a88c4ba92dc4", + "model-customization-id": "06b4ece0-f6f8-4003-b445-653418292101", + "selflink": "restconf/config/GENERIC-RESOURCE-API:services/service/aea56040-8caf-41b3-a85b-97c44001499e/service-data/vnfs/vnf/9a7a4dc1-8e5f-43fe-a360-7734c5f51382/vnf-data/vf-modules/vf-module/2cb6d41e-2bef-4cb2-80ce-c7815bcdcf4e/vf-module-data/vf-module-topology/", + "relationship-list": { + "relationship": [{ + "related-to": "l3-network", + "relationship-label": "org.onap.relationships.inventory.DependsOn", + "related-link": "/aai/v14/network/l3-networks/l3-network/974345f8-75d5-4ae2-be72-600930bcbe6b", + "relationship-data": [{ + "relationship-key": "l3-network.network-id", + "relationship-value": "974345f8-75d5-4ae2-be72-600930bcbe6b" + } + ], + "related-to-property": [{ + "property-key": "l3-network.network-name", + "property-value": "APP-C-24595-T-IST-05B_oam_protected_net_1" + } + ] + }, { + "related-to": "vnfc", + "relationship-label": "org.onap.relationships.inventory.Uses", + "related-link": "/aai/v14/network/vnfcs/vnfc/dyh3brarf8000vm001", + "relationship-data": [{ + "relationship-key": "vnfc.vnfc-name", + "relationship-value": "dyh3brarf8000vm001" + } + ] + }, { + "related-to": "vserver", + "relationship-label": "org.onap.relationships.inventory.Uses", + "related-link": "/aai/v14/cloud-infrastructure/cloud-regions/cloud-region/irma-aic/dyh3b/tenants/tenant/c8035f5ee95d4c62bbc8074c044122b9/vservers/vserver/3e3985e1-2369-4191-9721-7858a478ab6d", + "relationship-data": [{ + "relationship-key": "cloud-region.cloud-owner", + "relationship-value": "irma-aic" + }, { + "relationship-key": "cloud-region.cloud-region-id", + "relationship-value": "dyh3b" + }, { + "relationship-key": "tenant.tenant-id", + "relationship-value": "c8035f5ee95d4c62bbc8074c044122b9" + }, { + "relationship-key": "vserver.vserver-id", + "relationship-value": "3e3985e1-2369-4191-9721-7858a478ab6d" + } + ], + "related-to-property": [{ + "property-key": "vserver.vserver-name", + "property-value": "dyh3brarf8000vm001" + } + ] + } + ] + } + } + ] +} diff --git a/vid-app-common/src/test/resources/getTopology/vnf.json b/vid-app-common/src/test/resources/getTopology/vnf.json new file mode 100644 index 000000000..7b640dac1 --- /dev/null +++ b/vid-app-common/src/test/resources/getTopology/vnf.json @@ -0,0 +1,160 @@ +{ + "vnf-id": "9a7a4dc1-8e5f-43fe-a360-7734c5f51382", + "vnf-name": "dyh3brarf8000v", + "vnf-type": "vRAR_1902_ap7134/vRAR_1902_ap7134 0", + "prov-status": "PREPROV", + "equipment-role": "vRAR", + "orchestration-status": "Active", + "in-maint": true, + "is-closed-loop-disabled": false, + "resource-version": "1547155053461", + "model-invariant-id": "b711997f-36b3-4a9b-8b37-71a0fc2ebd6d", + "model-version-id": "7f23e4f7-e44c-44df-b066-4cedc6950bfe", + "model-customization-id": "401350be-0f56-481c-86d8-f32d573fec26", + "nf-type": "REPORT", + "nf-function": "REVENUE-ASSURANCE", + "nf-role": "vRAR", + "nf-naming-code": "rarf", + "selflink": "restconf/config/GENERIC-RESOURCE-API:services/service/aea56040-8caf-41b3-a85b-97c44001499e/service-data/vnfs/vnf/9a7a4dc1-8e5f-43fe-a360-7734c5f51382/vnf-data/vnf-topology/", + "relationship-list": { + "relationship": [{ + "related-to": "service-instance", + "relationship-label": "org.onap.relationships.inventory.ComposedOf", + "related-link": "/aai/v14/business/customers/customer/e433710f-9217-458d-a79d-1c7aff376d89/service-subscriptions/service-subscription/TYLER%20SILVIA/service-instances/service-instance/aea56040-8caf-41b3-a85b-97c44001499e", + "relationship-data": [{ + "relationship-key": "customer.global-customer-id", + "relationship-value": "e433710f-9217-458d-a79d-1c7aff376d89" + }, { + "relationship-key": "service-subscription.service-type", + "relationship-value": "TYLER SILVIA" + }, { + "relationship-key": "service-instance.service-instance-id", + "relationship-value": "aea56040-8caf-41b3-a85b-97c44001499e" + } + ], + "related-to-property": [{ + "property-key": "service-instance.service-instance-name", + "property-value": "vRAR_1902_un577h" + } + ] + }, { + "related-to": "vnfc", + "relationship-label": "org.onap.relationships.inventory.BelongsTo", + "related-link": "/aai/v14/network/vnfcs/vnfc/dyh3brarf8000vm001", + "relationship-data": [{ + "relationship-key": "vnfc.vnfc-name", + "relationship-value": "dyh3brarf8000vm001" + } + ] + }, { + "related-to": "platform", + "relationship-label": "org.onap.relationships.inventory.Uses", + "related-link": "/aai/v14/business/platforms/platform/FIRSTNET-DEDICATED", + "relationship-data": [{ + "relationship-key": "platform.platform-name", + "relationship-value": "FIRSTNET-DEDICATED" + } + ] + }, { + "related-to": "line-of-business", + "relationship-label": "org.onap.relationships.inventory.Uses", + "related-link": "/aai/v14/business/lines-of-business/line-of-business/FIRSTNET", + "relationship-data": [{ + "relationship-key": "line-of-business.line-of-business-name", + "relationship-value": "LINDSEY" + } + ] + }, { + "related-to": "tenant", + "relationship-label": "org.onap.relationships.inventory.BelongsTo", + "related-link": "/aai/v14/cloud-infrastructure/cloud-regions/cloud-region/irma-aic/dyh3b/tenants/tenant/c8035f5ee95d4c62bbc8074c044122b9", + "relationship-data": [{ + "relationship-key": "cloud-region.cloud-owner", + "relationship-value": "irma-aic" + }, { + "relationship-key": "cloud-region.cloud-region-id", + "relationship-value": "dyh3b" + }, { + "relationship-key": "tenant.tenant-id", + "relationship-value": "c8035f5ee95d4c62bbc8074c044122b9" + } + ], + "related-to-property": [{ + "property-key": "tenant.tenant-name", + "property-value": "APP-C-24595-T-IST-05B" + } + ] + }, { + "related-to": "vserver", + "relationship-label": "tosca.relationships.HostedOn", + "related-link": "/aai/v14/cloud-infrastructure/cloud-regions/cloud-region/irma-aic/dyh3b/tenants/tenant/c8035f5ee95d4c62bbc8074c044122b9/vservers/vserver/3e3985e1-2369-4191-9721-7858a478ab6d", + "relationship-data": [{ + "relationship-key": "cloud-region.cloud-owner", + "relationship-value": "irma-aic" + }, { + "relationship-key": "cloud-region.cloud-region-id", + "relationship-value": "dyh3b" + }, { + "relationship-key": "tenant.tenant-id", + "relationship-value": "c8035f5ee95d4c62bbc8074c044122b9" + }, { + "relationship-key": "vserver.vserver-id", + "relationship-value": "3e3985e1-2369-4191-9721-7858a478ab6d" + } + ], + "related-to-property": [{ + "property-key": "vserver.vserver-name", + "property-value": "dyh3brarf8000vm001" + } + ] + }, { + "related-to": "availability-zone", + "relationship-label": "org.onap.relationships.inventory.Uses", + "related-link": "/aai/v14/cloud-infrastructure/cloud-regions/cloud-region/irma-aic/dyh3b/availability-zones/availability-zone/dyh3b-kvm-az02", + "relationship-data": [{ + "relationship-key": "cloud-region.cloud-owner", + "relationship-value": "irma-aic" + }, { + "relationship-key": "cloud-region.cloud-region-id", + "relationship-value": "dyh3b" + }, { + "relationship-key": "availability-zone.availability-zone-name", + "relationship-value": "dyh3b-kvm-az02" + } + ] + }, { + "related-to": "availability-zone", + "relationship-label": "org.onap.relationships.inventory.Uses", + "related-link": "/aai/v14/cloud-infrastructure/cloud-regions/cloud-region/irma-aic/dyh3b/availability-zones/availability-zone/dyh3b-kvm-az01", + "relationship-data": [{ + "relationship-key": "cloud-region.cloud-owner", + "relationship-value": "irma-aic" + }, { + "relationship-key": "cloud-region.cloud-region-id", + "relationship-value": "dyh3b" + }, { + "relationship-key": "availability-zone.availability-zone-name", + "relationship-value": "dyh3b-kvm-az01" + } + ] + }, { + "related-to": "cloud-region", + "relationship-label": "org.onap.relationships.inventory.LocatedIn", + "related-link": "/aai/v14/cloud-infrastructure/cloud-regions/cloud-region/irma-aic/dyh3b", + "relationship-data": [{ + "relationship-key": "cloud-region.cloud-owner", + "relationship-value": "irma-aic" + }, { + "relationship-key": "cloud-region.cloud-region-id", + "relationship-value": "dyh3b" + } + ], + "related-to-property": [{ + "property-key": "cloud-region.owner-defined-type", + "property-value": "lcp" + } + ] + } + ] + } +} diff --git a/vid-app-common/src/test/resources/orchestrationRequestsByServiceInstanceId.json b/vid-app-common/src/test/resources/orchestrationRequestsByServiceInstanceId.json index 34f18f7fb..d20fc6700 100644 --- a/vid-app-common/src/test/resources/orchestrationRequestsByServiceInstanceId.json +++ b/vid-app-common/src/test/resources/orchestrationRequestsByServiceInstanceId.json @@ -93,7 +93,7 @@ ], "cloudConfiguration": { "tenantId": "460f35aeb53542dc9f77105066483e83", - "cloudOwner": "att-aic", + "cloudOwner": "irma-aic" , "lcpCloudRegionId": "rdm5b" }, "requestParameters": {}, @@ -177,7 +177,7 @@ ], "cloudConfiguration": { "tenantId": "460f35aeb53542dc9f77105066483e83", - "cloudOwner": "att-aic", + "cloudOwner": "irma-aic" , "lcpCloudRegionId": "rdm5b" }, "requestParameters": { diff --git a/vid-app-common/src/test/resources/payload_jsons/VnfGroupCreate1Delete1None1Request.json b/vid-app-common/src/test/resources/payload_jsons/VnfGroupCreate1Delete1None1Request.json new file mode 100644 index 000000000..bc645452f --- /dev/null +++ b/vid-app-common/src/test/resources/payload_jsons/VnfGroupCreate1Delete1None1Request.json @@ -0,0 +1,123 @@ +{ + "action": "None", + "isDirty": true, + "trackById":"aabbcc", + "vnfs": {}, + "instanceParams": [], + "validationCounter": 0, + "existingNames": { + "service_instance_name": "", + "vnf_group3_instance_name": "" + }, + "existingVNFCounterMap": {}, + "existingVnfGroupCounterMap": { + "daeb6568-cef8-417f-9075-ed259ce59f48": 3 + }, + "existingNetworksCounterMap": {}, + "networks": {}, + "vnfGroups": { + "groupingservicefortest..ResourceInstanceGroup..0:001": { + "originalName": "groupingservicefortest..ResourceInstanceGroup..0", + "trackById": "groupingservicefortest..ResourceInstanceGroup..0:001", + "instanceName": "VNF_GROUP1_INSTANCE_NAME", + "lcpCloudRegionId": null, + "legacyRegion": null, + "lineOfBusiness": null, + "action": "None_Delete", + "instanceId": "VNF_GROUP1_INSTANCE_ID", + "instanceType": "VNF_GROUP1_INSTANCE_TYPE", + "orchStatus": null, + "platformName": null, + "productFamilyId": null, + "provStatus": null, + "tenantId": null, + "inMaint": false, + "modelInfo": { + "modelType": "instanceGroup", + "modelCustomizationName": "groupingservicefortest..ResourceInstanceGroup..0", + "modelInvariantId": "4bb2e27e-ddab-4790-9c6d-1f731bc14a45", + "modelVersionId": "daeb6568-cef8-417f-9075-ed259ce59f48" + }, + "uuid": "daeb6568-cef8-417f-9075-ed259ce59f48", + "instanceGroupRole": "VNF_GROUP1_INSTANCE_ROLE", + "instanceGroupFunction": "vTSBC Customer Landing Network Collection", + "vnfs":{} + }, + "groupingservicefortest..ResourceInstanceGroup..0:002": { + "originalName": "groupingservicefortest..ResourceInstanceGroup..0", + "trackById": "groupingservicefortest..ResourceInstanceGroup..0:002", + "instanceName": "VNF_GROUP2_INSTANCE_NAME", + "lcpCloudRegionId": null, + "legacyRegion": null, + "lineOfBusiness": null, + "action": "None", + "instanceId": "VNF_GROUP2_INSTANCE_ID", + "instanceType": "VNF_GROUP2_INSTANCE_TYPE", + "orchStatus": null, + "platformName": null, + "productFamilyId": null, + "provStatus": null, + "inMaint": false, + "modelInfo": { + "modelType": "instanceGroup", + "modelCustomizationName": "groupingservicefortest..ResourceInstanceGroup..0", + "modelInvariantId": "4bb2e27e-ddab-4790-9c6d-1f731bc14a45", + "modelVersionId": "daeb6568-cef8-417f-9075-ed259ce59f48" + }, + "uuid": "daeb6568-cef8-417f-9075-ed259ce59f48", + "tenantId": null, + "instanceGroupRole": "VNF_GROUP2_INSTANCE_ROLE", + "instanceGroupFunction": "vTSBC Customer Landing Network Collection", + "vnfs": {} + }, + "groupingservicefortest..ResourceInstanceGroup..0": { + "action": "Create", + "inMaint": false, + "rollbackOnFailure": "true", + "originalName": "groupingservicefortest..ResourceInstanceGroup..0", + "isMissingData": false, + "trackById": "ag5aav86u4j", + "vnfGroupStoreKey": "groupingservicefortest..ResourceInstanceGroup..0", + "uuid": "daeb6568-cef8-417f-9075-ed259ce59f48", + "instanceName": "VNF_GROUP3_INSTANCE_NAME", + "modelInfo": { + "modelInvariantId": "4bb2e27e-ddab-4790-9c6d-1f731bc14a45", + "modelVersionId": "daeb6568-cef8-417f-9075-ed259ce59f48", + "modelName": "groupingservicefortest..ResourceInstanceGroup..0", + "modelVersion": "1", + "modelCustomizationName": "groupingservicefortest..ResourceInstanceGroup..0", + "uuid": "daeb6568-cef8-417f-9075-ed259ce59f48" + }, + "instanceParams": [{} + ], + "vnfs":{} + } + }, + "bulkSize": 1, + "instanceName": "SERVICE_INSTANCE_NAME", + + "instanceId": "service-instance-id", + "orchStatus": "GARBAGE DATA", + "globalSubscriberId": "global-customer-id", + "subscriptionServiceType": "service-instance-type", + "owningEntityId": null, + "owningEntityName": null, + "productFamilyId": null, + "lcpCloudRegionId": null, + "tenantId": null, + "tenantName": null, + "aicZoneId": null, + "aicZoneName": null, + "projectName": null, + "rollbackOnFailure": false, + "isALaCarte": true, + "modelInfo": { + "modelInvariantId": "7ee41ce4-4827-44b0-a48e-2707a59905d2", + "modelVersionId": "4117a0b6-e234-467d-b5b9-fe2f68c8b0fc", + "modelName": "Grouping Service for Test", + "modelType": "service", + "modelVersion": "1.0" + }, + + "testApi": "VNF_API" +} diff --git a/vid-app-common/src/test/resources/payload_jsons/VnfGroupCreate3Delete1None1Request.json b/vid-app-common/src/test/resources/payload_jsons/VnfGroupCreate3Delete1None1Request.json new file mode 100644 index 000000000..1906bc89f --- /dev/null +++ b/vid-app-common/src/test/resources/payload_jsons/VnfGroupCreate3Delete1None1Request.json @@ -0,0 +1,171 @@ +{ + "action": "None", + "isDirty": true, + "trackById":"aabbcc", + "vnfs": {}, + "instanceParams": [], + "validationCounter": 0, + "existingNames": { + "service_instance_name": "", + "vnf_group3_instance_name": "" + }, + "existingVNFCounterMap": {}, + "existingVnfGroupCounterMap": { + "daeb6568-cef8-417f-9075-ed259ce59f48": 3 + }, + "existingNetworksCounterMap": {}, + "networks": {}, + "vnfGroups": { + "groupingservicefortest..ResourceInstanceGroup..0:001": { + "originalName": "groupingservicefortest..ResourceInstanceGroup..0", + "trackById": "groupingservicefortest..ResourceInstanceGroup..0:001", + "instanceName": "VNF_GROUP1_INSTANCE_NAME", + "lcpCloudRegionId": null, + "legacyRegion": null, + "lineOfBusiness": null, + "action": "None_Delete", + "instanceId": "VNF_GROUP1_INSTANCE_ID", + "instanceType": "VNF_GROUP1_INSTANCE_TYPE", + "orchStatus": null, + "platformName": null, + "productFamilyId": null, + "provStatus": null, + "tenantId": null, + "inMaint": false, + "modelInfo": { + "modelType": "instanceGroup", + "modelCustomizationName": "groupingservicefortest..ResourceInstanceGroup..0", + "modelInvariantId": "4bb2e27e-ddab-4790-9c6d-1f731bc14a45", + "modelVersionId": "daeb6568-cef8-417f-9075-ed259ce59f48" + }, + "uuid": "daeb6568-cef8-417f-9075-ed259ce59f48", + "instanceGroupRole": "VNF_GROUP1_INSTANCE_ROLE", + "instanceGroupFunction": "vTSBC Customer Landing Network Collection", + "vnfs":{} + }, + "groupingservicefortest..ResourceInstanceGroup..0:002": { + "originalName": "groupingservicefortest..ResourceInstanceGroup..0", + "trackById": "groupingservicefortest..ResourceInstanceGroup..0:002", + "instanceName": "VNF_GROUP2_INSTANCE_NAME", + "lcpCloudRegionId": null, + "legacyRegion": null, + "lineOfBusiness": null, + "action": "None", + "instanceId": "VNF_GROUP2_INSTANCE_ID", + "instanceType": "VNF_GROUP2_INSTANCE_TYPE", + "orchStatus": null, + "platformName": null, + "productFamilyId": null, + "provStatus": null, + "inMaint": false, + "modelInfo": { + "modelType": "instanceGroup", + "modelCustomizationName": "groupingservicefortest..ResourceInstanceGroup..0", + "modelInvariantId": "4bb2e27e-ddab-4790-9c6d-1f731bc14a45", + "modelVersionId": "daeb6568-cef8-417f-9075-ed259ce59f48" + }, + "uuid": "daeb6568-cef8-417f-9075-ed259ce59f48", + "tenantId": null, + "instanceGroupRole": "VNF_GROUP2_INSTANCE_ROLE", + "instanceGroupFunction": "vTSBC Customer Landing Network Collection", + "vnfs": {} + }, + "groupingservicefortest..ResourceInstanceGroup..0": { + "action": "Create", + "inMaint": false, + "rollbackOnFailure": "true", + "originalName": "groupingservicefortest..ResourceInstanceGroup..0", + "isMissingData": false, + "trackById": "ag5aav86u4j", + "vnfGroupStoreKey": "groupingservicefortest..ResourceInstanceGroup..0", + "uuid": "daeb6568-cef8-417f-9075-ed259ce59f48", + "instanceName": "VNF_GROUP3_INSTANCE_NAME", + "modelInfo": { + "modelInvariantId": "4bb2e27e-ddab-4790-9c6d-1f731bc14a45", + "modelVersionId": "daeb6568-cef8-417f-9075-ed259ce59f48", + "modelName": "groupingservicefortest..ResourceInstanceGroup..0", + "modelVersion": "1", + "modelCustomizationName": "groupingservicefortest..ResourceInstanceGroup..0", + "uuid": "daeb6568-cef8-417f-9075-ed259ce59f48" + }, + "instanceParams": [{} + ], + "vnfs":{} + }, + "groupingservicefortest..ResourceInstanceGroup..0:003": { + "action": "Create", + "isFailed": true, + "statusMessage": "failed!", + "inMaint": false, + "rollbackOnFailure": "true", + "originalName": "groupingservicefortest..ResourceInstanceGroup..0", + "isMissingData": false, + "trackById": "asedrftjko", + "vnfGroupStoreKey": "groupingservicefortest..ResourceInstanceGroup..0", + "uuid": "daeb6568-cef8-417f-9075-ed259ce59f48", + "instanceName": "VNF_GROUP4_INSTANCE_NAME", + "modelInfo": { + "modelInvariantId": "4bb2e27e-ddab-4790-9c6d-1f731bc14a45", + "modelVersionId": "daeb6568-cef8-417f-9075-ed259ce59f48", + "modelName": "groupingservicefortest..ResourceInstanceGroup..0", + "modelVersion": "1", + "modelCustomizationName": "groupingservicefortest..ResourceInstanceGroup..0", + "uuid": "daeb6568-cef8-417f-9075-ed259ce59f48" + }, + "instanceParams": [{} + ], + "vnfs":{} + }, + "groupingservicefortest..ResourceInstanceGroup..0:004": { + "action": "Create", + "isFailed": false, + "statusMessage": null, + "inMaint": false, + "rollbackOnFailure": "true", + "originalName": "groupingservicefortest..ResourceInstanceGroup..0", + "isMissingData": false, + "trackById": "rgedfdged4", + "vnfGroupStoreKey": "groupingservicefortest..ResourceInstanceGroup..0", + "uuid": "daeb6568-cef8-417f-9075-ed259ce59f48", + "instanceName": "VNF_GROUP5_INSTANCE_NAME", + "modelInfo": { + "modelInvariantId": "4bb2e27e-ddab-4790-9c6d-1f731bc14a45", + "modelVersionId": "daeb6568-cef8-417f-9075-ed259ce59f48", + "modelName": "groupingservicefortest..ResourceInstanceGroup..0", + "modelVersion": "1", + "modelCustomizationName": "groupingservicefortest..ResourceInstanceGroup..0", + "uuid": "daeb6568-cef8-417f-9075-ed259ce59f48" + }, + "instanceParams": [{} + ], + "vnfs":{} + } + }, + "bulkSize": 1, + "instanceName": "SERVICE_INSTANCE_NAME", + + "instanceId": "service-instance-id", + "orchStatus": "GARBAGE DATA", + "globalSubscriberId": "global-customer-id", + "subscriptionServiceType": "service-instance-type", + "owningEntityId": null, + "owningEntityName": null, + "productFamilyId": null, + "lcpCloudRegionId": null, + "tenantId": null, + "tenantName": null, + "aicZoneId": null, + "aicZoneName": null, + "projectName": null, + "rollbackOnFailure": false, + "isALaCarte": true, + "modelInfo": { + "modelInvariantId": "7ee41ce4-4827-44b0-a48e-2707a59905d2", + "modelVersionId": "4117a0b6-e234-467d-b5b9-fe2f68c8b0fc", + "modelName": "Grouping Service for Test", + "modelType": "service", + "modelVersion": "1.0" + }, + + "testApi": "VNF_API" +} diff --git a/vid-app-common/src/test/resources/payload_jsons/VnfGroupCreate3Delete1None1RequestResolvedForRetry.json b/vid-app-common/src/test/resources/payload_jsons/VnfGroupCreate3Delete1None1RequestResolvedForRetry.json new file mode 100644 index 000000000..6196cd797 --- /dev/null +++ b/vid-app-common/src/test/resources/payload_jsons/VnfGroupCreate3Delete1None1RequestResolvedForRetry.json @@ -0,0 +1,176 @@ +{ + "action": "None", + "isDirty": true, + "trackById":"aabbcc", + "vnfs": {}, + "instanceParams": [], + "validationCounter": 0, + "existingNames": { + "service_instance_name": "", + "vnf_group3_instance_name": "" + }, + "existingVNFCounterMap": {}, + "existingVnfGroupCounterMap": { + "daeb6568-cef8-417f-9075-ed259ce59f48": 3 + }, + "existingNetworksCounterMap": {}, + "networks": {}, + "vnfGroups": { + "groupingservicefortest..ResourceInstanceGroup..0:001": { + "originalName": "groupingservicefortest..ResourceInstanceGroup..0", + "trackById": "groupingservicefortest..ResourceInstanceGroup..0:001", + "instanceName": "VNF_GROUP1_INSTANCE_NAME", + "lcpCloudRegionId": null, + "legacyRegion": null, + "lineOfBusiness": null, + "action": "None", + "statusMessage": "Vnf has been created successfully.", + "instanceId": "VNF_GROUP1_INSTANCE_ID", + "instanceType": "VNF_GROUP1_INSTANCE_TYPE", + "orchStatus": null, + "platformName": null, + "productFamilyId": null, + "provStatus": null, + "tenantId": null, + "inMaint": false, + "modelInfo": { + "modelType": "instanceGroup", + "modelCustomizationName": "groupingservicefortest..ResourceInstanceGroup..0", + "modelInvariantId": "4bb2e27e-ddab-4790-9c6d-1f731bc14a45", + "modelVersionId": "daeb6568-cef8-417f-9075-ed259ce59f48" + }, + "uuid": "daeb6568-cef8-417f-9075-ed259ce59f48", + "instanceGroupRole": "VNF_GROUP1_INSTANCE_ROLE", + "instanceGroupFunction": "vTSBC Customer Landing Network Collection", + "vnfs":{} + }, + "groupingservicefortest..ResourceInstanceGroup..0:002": { + "originalName": "groupingservicefortest..ResourceInstanceGroup..0", + "trackById": "groupingservicefortest..ResourceInstanceGroup..0:002", + "instanceName": "VNF_GROUP2_INSTANCE_NAME", + "lcpCloudRegionId": null, + "legacyRegion": null, + "lineOfBusiness": null, + "action": "None", + "instanceId": "VNF_GROUP2_INSTANCE_ID", + "instanceType": "VNF_GROUP2_INSTANCE_TYPE", + "orchStatus": null, + "platformName": null, + "productFamilyId": null, + "provStatus": null, + "inMaint": false, + "modelInfo": { + "modelType": "instanceGroup", + "modelCustomizationName": "groupingservicefortest..ResourceInstanceGroup..0", + "modelInvariantId": "4bb2e27e-ddab-4790-9c6d-1f731bc14a45", + "modelVersionId": "daeb6568-cef8-417f-9075-ed259ce59f48" + }, + "uuid": "daeb6568-cef8-417f-9075-ed259ce59f48", + "tenantId": null, + "instanceGroupRole": "VNF_GROUP2_INSTANCE_ROLE", + "instanceGroupFunction": "vTSBC Customer Landing Network Collection", + "vnfs": {} + }, + "groupingservicefortest..ResourceInstanceGroup..0": { + "action": "Create", + "inMaint": false, + "rollbackOnFailure": "true", + "originalName": "groupingservicefortest..ResourceInstanceGroup..0", + "isMissingData": false, + "trackById": "ag5aav86u4j", + "vnfGroupStoreKey": "groupingservicefortest..ResourceInstanceGroup..0", + "uuid": "daeb6568-cef8-417f-9075-ed259ce59f48", + "instanceName": "VNF_GROUP3_INSTANCE_NAME", + "isFailed": true, + "statusMessage": "Vnf has been created successfully.", + "modelInfo": { + "modelInvariantId": "4bb2e27e-ddab-4790-9c6d-1f731bc14a45", + "modelVersionId": "daeb6568-cef8-417f-9075-ed259ce59f48", + "modelName": "groupingservicefortest..ResourceInstanceGroup..0", + "modelVersion": "1", + "modelCustomizationName": "groupingservicefortest..ResourceInstanceGroup..0", + "uuid": "daeb6568-cef8-417f-9075-ed259ce59f48" + }, + "instanceParams": [{} + ], + "vnfs":{} + }, + "groupingservicefortest..ResourceInstanceGroup..0:003": { + "action": "None", + "isFailed": false, + "instanceId": "VNF_GROUP1_INSTANCE_ID_3", + "statusMessage": "Vnf has been created successfully.", + "inMaint": false, + "rollbackOnFailure": "true", + "originalName": "groupingservicefortest..ResourceInstanceGroup..0", + "isMissingData": false, + "trackById": "asedrftjko", + "vnfGroupStoreKey": "groupingservicefortest..ResourceInstanceGroup..0", + "uuid": "daeb6568-cef8-417f-9075-ed259ce59f48", + "instanceName": "VNF_GROUP4_INSTANCE_NAME", + "modelInfo": { + "modelInvariantId": "4bb2e27e-ddab-4790-9c6d-1f731bc14a45", + "modelVersionId": "daeb6568-cef8-417f-9075-ed259ce59f48", + "modelName": "groupingservicefortest..ResourceInstanceGroup..0", + "modelVersion": "1", + "modelCustomizationName": "groupingservicefortest..ResourceInstanceGroup..0", + "uuid": "daeb6568-cef8-417f-9075-ed259ce59f48" + }, + "instanceParams": [{} + ], + "vnfs":{} + }, + "groupingservicefortest..ResourceInstanceGroup..0:004": { + "action": "None", + "isFailed": false, + "statusMessage": "Vnf has been created successfully.", + "instanceId": "VNF_GROUP1_INSTANCE_ID_4", + "inMaint": false, + "rollbackOnFailure": "true", + "originalName": "groupingservicefortest..ResourceInstanceGroup..0", + "isMissingData": false, + "trackById": "rgedfdged4", + "vnfGroupStoreKey": "groupingservicefortest..ResourceInstanceGroup..0", + "uuid": "daeb6568-cef8-417f-9075-ed259ce59f48", + "instanceName": "VNF_GROUP5_INSTANCE_NAME", + "modelInfo": { + "modelInvariantId": "4bb2e27e-ddab-4790-9c6d-1f731bc14a45", + "modelVersionId": "daeb6568-cef8-417f-9075-ed259ce59f48", + "modelName": "groupingservicefortest..ResourceInstanceGroup..0", + "modelVersion": "1", + "modelCustomizationName": "groupingservicefortest..ResourceInstanceGroup..0", + "uuid": "daeb6568-cef8-417f-9075-ed259ce59f48" + }, + "instanceParams": [{} + ], + "vnfs":{} + } + }, + "bulkSize": 1, + "instanceName": "SERVICE_INSTANCE_NAME", + + "instanceId": "service-instance-id", + "orchStatus": "GARBAGE DATA", + "globalSubscriberId": "global-customer-id", + "subscriptionServiceType": "service-instance-type", + "owningEntityId": null, + "owningEntityName": null, + "productFamilyId": null, + "lcpCloudRegionId": null, + "tenantId": null, + "tenantName": null, + "aicZoneId": null, + "aicZoneName": null, + "projectName": null, + "rollbackOnFailure": false, + "isALaCarte": true, + "modelInfo": { + "modelInvariantId": "7ee41ce4-4827-44b0-a48e-2707a59905d2", + "modelVersionId": "4117a0b6-e234-467d-b5b9-fe2f68c8b0fc", + "modelName": "Grouping Service for Test", + "modelType": "service", + "modelVersion": "1.0" + }, + + "testApi": "VNF_API" +} diff --git a/vid-app-common/src/test/resources/payload_jsons/bulk_alacarte_service_request.json b/vid-app-common/src/test/resources/payload_jsons/bulk_alacarte_service_request.json index 955685268..4e3fc1021 100644 --- a/vid-app-common/src/test/resources/payload_jsons/bulk_alacarte_service_request.json +++ b/vid-app-common/src/test/resources/payload_jsons/bulk_alacarte_service_request.json @@ -9,7 +9,7 @@ }, "owningEntity": { "owningEntityId": "038d99af-0427-42c2-9d15-971b99b9b489", - "owningEntityName": "PACKET CORE" + "owningEntityName": "JULIO ERICKSON" }, "project": { "projectName": "{some project name}" diff --git a/vid-app-common/src/test/resources/payload_jsons/bulk_alacarte_service_request_naming_false.json b/vid-app-common/src/test/resources/payload_jsons/bulk_alacarte_service_request_naming_false.json index be697ed88..5b1fdc1bd 100644 --- a/vid-app-common/src/test/resources/payload_jsons/bulk_alacarte_service_request_naming_false.json +++ b/vid-app-common/src/test/resources/payload_jsons/bulk_alacarte_service_request_naming_false.json @@ -9,7 +9,7 @@ }, "owningEntity": { "owningEntityId": "038d99af-0427-42c2-9d15-971b99b9b489", - "owningEntityName": "PACKET CORE" + "owningEntityName": "JULIO ERICKSON" }, "subscriberInfo": { "globalSubscriberId": "{some subscriber id}" diff --git a/vid-app-common/src/test/resources/payload_jsons/bulk_macro_service_request.json b/vid-app-common/src/test/resources/payload_jsons/bulk_macro_service_request.json index 917900c22..c0315d015 100644 --- a/vid-app-common/src/test/resources/payload_jsons/bulk_macro_service_request.json +++ b/vid-app-common/src/test/resources/payload_jsons/bulk_macro_service_request.json @@ -9,7 +9,7 @@ }, "owningEntity": { "owningEntityId": "038d99af-0427-42c2-9d15-971b99b9b489", - "owningEntityName": "PACKET CORE" + "owningEntityName": "JULIO ERICKSON" }, "project": { "projectName": "{some project name}" @@ -51,7 +51,7 @@ }, "cloudConfiguration": { "lcpCloudRegionId": "mdt1", - "cloudOwner": "att-aic", + "cloudOwner": "irma-aic", "tenantId": "88a6ca3ee0394ade9403f075db23167e" }, "platform": { diff --git a/vid-app-common/src/test/resources/payload_jsons/bulk_service_request_ecomp_naming.json b/vid-app-common/src/test/resources/payload_jsons/bulk_service_request_ecomp_naming.json index 55765a86b..dd343f46e 100644 --- a/vid-app-common/src/test/resources/payload_jsons/bulk_service_request_ecomp_naming.json +++ b/vid-app-common/src/test/resources/payload_jsons/bulk_service_request_ecomp_naming.json @@ -9,7 +9,7 @@ }, "owningEntity": { "owningEntityId": "038d99af-0427-42c2-9d15-971b99b9b489", - "owningEntityName": "PACKET CORE" + "owningEntityName": "JULIO ERICKSON" }, "project": { "projectName": "{some project name}" @@ -48,7 +48,7 @@ }, "cloudConfiguration": { "lcpCloudRegionId": "mdt1", - "cloudOwner": "att-aic", + "cloudOwner": "irma-aic", "tenantId": "88a6ca3ee0394ade9403f075db23167e" }, "platform": { diff --git a/vid-app-common/src/test/resources/payload_jsons/bulk_service_request_no_vfmodule_ecomp_naming.json b/vid-app-common/src/test/resources/payload_jsons/bulk_service_request_no_vfmodule_ecomp_naming.json index fdc81511c..0ef15d790 100644 --- a/vid-app-common/src/test/resources/payload_jsons/bulk_service_request_no_vfmodule_ecomp_naming.json +++ b/vid-app-common/src/test/resources/payload_jsons/bulk_service_request_no_vfmodule_ecomp_naming.json @@ -9,7 +9,7 @@ }, "owningEntity": { "owningEntityId": "038d99af-0427-42c2-9d15-971b99b9b489", - "owningEntityName": "PACKET CORE" + "owningEntityName": "JULIO ERICKSON" }, "project": { "projectName": "{some project name}" @@ -48,7 +48,7 @@ }, "cloudConfiguration": { "lcpCloudRegionId": "mdt1", - "cloudOwner": "att-aic", + "cloudOwner": "irma-aic", "tenantId": "88a6ca3ee0394ade9403f075db23167e" }, "platform": { diff --git a/vid-app-common/src/test/resources/payload_jsons/bulk_service_request_unique_names.json b/vid-app-common/src/test/resources/payload_jsons/bulk_service_request_unique_names.json index 643c1043a..c4f40a9c0 100644 --- a/vid-app-common/src/test/resources/payload_jsons/bulk_service_request_unique_names.json +++ b/vid-app-common/src/test/resources/payload_jsons/bulk_service_request_unique_names.json @@ -9,7 +9,7 @@ }, "owningEntity": { "owningEntityId": "038d99af-0427-42c2-9d15-971b99b9b489", - "owningEntityName": "PACKET CORE" + "owningEntityName": "JULIO ERICKSON" }, "project": { "projectName": "{some project name}" @@ -50,7 +50,7 @@ }, "cloudConfiguration": { "lcpCloudRegionId": "mdt1", - "cloudOwner": "att-aic", + "cloudOwner": "irma-aic", "tenantId": "88a6ca3ee0394ade9403f075db23167e" }, "platform": { diff --git a/vid-app-common/src/test/resources/payload_jsons/bulk_vnf_request.json b/vid-app-common/src/test/resources/payload_jsons/bulk_vnf_request.json index d7b6d8629..5aa0211d1 100644 --- a/vid-app-common/src/test/resources/payload_jsons/bulk_vnf_request.json +++ b/vid-app-common/src/test/resources/payload_jsons/bulk_vnf_request.json @@ -12,7 +12,7 @@ "cloudConfiguration": { "lcpCloudRegionId": "mdt1", "tenantId": "88a6ca3ee0394ade9403f075db23167e", - "cloudOwner" : "att-aic" + "cloudOwner" : "irma-aic" }, "requestInfo": { "instanceName": "vmxnjr001_001", diff --git a/vid-app-common/src/test/resources/payload_jsons/bulk_vnf_request_without_instance_name.json b/vid-app-common/src/test/resources/payload_jsons/bulk_vnf_request_without_instance_name.json index 9921de59b..7322d8589 100644 --- a/vid-app-common/src/test/resources/payload_jsons/bulk_vnf_request_without_instance_name.json +++ b/vid-app-common/src/test/resources/payload_jsons/bulk_vnf_request_without_instance_name.json @@ -12,7 +12,7 @@ "cloudConfiguration": { "lcpCloudRegionId": "mdt1", "tenantId": "88a6ca3ee0394ade9403f075db23167e", - "cloudOwner": "att-aic" + "cloudOwner": "irma-aic" }, "requestInfo": { "productFamilyId": "a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb", diff --git a/vid-app-common/src/test/resources/payload_jsons/instance_group_instantiation_request.json b/vid-app-common/src/test/resources/payload_jsons/instance_group_instantiation_request.json index 7072d3213..70e8f04ff 100644 --- a/vid-app-common/src/test/resources/payload_jsons/instance_group_instantiation_request.json +++ b/vid-app-common/src/test/resources/payload_jsons/instance_group_instantiation_request.json @@ -10,7 +10,7 @@ "modelCustomizationId": "ab153b6e-c364-44c0-bef6-1f2982117f04" }, "requestInfo": { - "instanceName": "VNF_GROUP_NAME_001", + "instanceName": "VNF_GROUP_NAME", "source": "VID", "suppressRollback": true, "requestorId": "az2018" @@ -30,7 +30,8 @@ } ], "requestParameters": { - "userParams": [] + "userParams": [], + "testApi" : "VNF_API" } } } \ No newline at end of file diff --git a/vid-app-common/src/test/resources/payload_jsons/mso_request_create_configuration.json b/vid-app-common/src/test/resources/payload_jsons/mso_request_create_configuration.json index e0942bae2..c4849f047 100644 --- a/vid-app-common/src/test/resources/payload_jsons/mso_request_create_configuration.json +++ b/vid-app-common/src/test/resources/payload_jsons/mso_request_create_configuration.json @@ -39,7 +39,7 @@ "modelType": "vnf", "modelInvariantId": "a7eac2b3-8444-40ee-92e3-b3359b32445c", "modelVersionId": "2a2ea15f-07c6-4b89-bfca-e8aba39a34d6", - "modelName": "vmmeService2", + "modelName": "vflorenceService2", "modelVersion": "1.0", "modelCustomizationId": "060be63d-5f9c-4fd0-8ef7-830d5e8eca17" } diff --git a/vid-app-common/src/test/resources/payload_jsons/mso_service_instantiation.json b/vid-app-common/src/test/resources/payload_jsons/mso_service_instantiation.json index 537b8d60c..926c435dc 100644 --- a/vid-app-common/src/test/resources/payload_jsons/mso_service_instantiation.json +++ b/vid-app-common/src/test/resources/payload_jsons/mso_service_instantiation.json @@ -13,7 +13,7 @@ }, "owningEntity": { "owningEntityId": "038d99af-0427-42c2-9d15-971b99b9b489", - "owningEntityName": "PACKET CORE" + "owningEntityName": "JULIO ERICKSON" }, "project": { "projectName": "TODO" @@ -49,7 +49,7 @@ "modelVersion":"10.0" }, "owningEntityId":"038d99af-0427-42c2-9d15-971b99b9b489", - "owningEntityName":"PACKET CORE", + "owningEntityName":"JULIO ERICKSON", "projectName":"{some project name}", "globalSubscriberId":"{some subscriber id}", "productFamilyId":"a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb", diff --git a/vid-app-common/src/test/resources/payload_jsons/networkDelete1Create1Request.json b/vid-app-common/src/test/resources/payload_jsons/networkDelete1Create1Request.json new file mode 100644 index 000000000..cc35dcac7 --- /dev/null +++ b/vid-app-common/src/test/resources/payload_jsons/networkDelete1Create1Request.json @@ -0,0 +1,117 @@ +{ + "action":"None", + "isDirty":true, + "vnfs":{ + + }, + "instanceParams":[ + { + "2017488_pasqualevpe0_ASN":"AV_vPE" + } + ], + "validationCounter":0, + "existingNames":{ + "123":"", + "instancename":"", + "yoav":"" + }, + "existingVNFCounterMap":{ + + }, + "existingVnfGroupCounterMap":{ + + }, + "existingNetworksCounterMap":{ + "94fdd893-4a36-4d70-b16a-ec29c54c184f":1 + }, + "networks":{ + "ExtVL 0":{ + "rollbackOnFailure":"false", + "productFamilyId":"36b4733a-53f4-4cc8-8ff0-9172e5fc4b8e", + "lcpCloudRegionId":"hvf6", + "tenantId":"229bcdc6eaeb4ca59d55221141d01f8e", + "lineOfBusiness":"zzz1", + "platformName":"platform", + "originalName":"ExtVL 0", + "modelInfo":{ + "modelInvariantId":"379f816b-a7aa-422f-be30-17114ff50b7c", + "modelVersionId":"ddc3f20c-08b5-40fd-af72-c6d14636b986", + "modelName":"ExtVL", + "modelVersion":"37.0", + "modelType":"network", + "modelCustomizationId":"94fdd893-4a36-4d70-b16a-ec29c54c184f", + "modelCustomizationName":"ExtVL 0" + }, + "instanceName":"ExtVL 0", + "instanceId":"NETWORK_INSTANCE_ID", + "action":"None_Delete" + }, + "ExtVL 0_1":{ + "action":"Create", + "inMaint":false, + "rollbackOnFailure":"true", + "originalName":"ExtVL 0", + "isMissingData":false, + "trackById":"r21vcx0szoc", + "networkStoreKey":"ExtVL 0_1", + "instanceName":"ExtVL", + "productFamilyId":"a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb", + "lcpCloudRegionId":"hvf6", + "tenantId":"229bcdc6eaeb4ca59d55221141d01f8e", + "platformName":"xxx1", + "lineOfBusiness":"zzz1", + "instanceParams":[ + { + + } + ], + "modelInfo":{ + "modelInvariantId":"379f816b-a7aa-422f-be30-17114ff50b7c", + "modelVersionId":"ddc3f20c-08b5-40fd-af72-c6d14636b986", + "modelName":"ExtVL", + "modelVersion":"37.0", + "modelCustomizationId":"94fdd893-4a36-4d70-b16a-ec29c54c184f", + "modelCustomizationName":"ExtVL 0", + "uuid":"ddc3f20c-08b5-40fd-af72-c6d14636b986", + "modelUniqueId":"94fdd893-4a36-4d70-b16a-ec29c54c184f" + }, + "uuid":"ddc3f20c-08b5-40fd-af72-c6d14636b986" + } + }, + "vnfGroups":{ + + }, + "bulkSize":1, + "instanceName":"InstanceName", + "globalSubscriberId":"e433710f-9217-458d-a79d-1c7aff376d89", + "subscriptionServiceType":"TYLER SILVIA", + "owningEntityId":"d61e6f2d-12fa-4cc2-91df-7c244011d6fc", + "productFamilyId":"17cc1042-527b-11e6-beb8-9e71128cae77", + "lcpCloudRegionId":"AAIAIC25", + "tenantId":"092eb9e8e4b7412e8787dd091bc58e86", + "aicZoneId":"JAG1", + "projectName":"WATKINS", + "rollbackOnFailure":true, + "aicZoneName":"YUDFJULP-JAG1", + "owningEntityName":"WayneHolland", + "testApi":"GR_API", + "tenantName":"USP-SIP-IC-24335-T-01", + "modelInfo":{ + "modelInvariantId":"e49fbd11-e60c-4a8e-b4bf-30fbe8f4fcc0", + "modelVersionId":"6b528779-44a3-4472-bdff-9cd15ec93450", + "modelName":"action-data", + "modelVersion":"1.0", + "uuid":"6b528779-44a3-4472-bdff-9cd15ec93450" + }, + "isALaCarte":true, + "name":"action-data", + "version":"1.0", + "description":"", + "category":"", + "uuid":"6b528779-44a3-4472-bdff-9cd15ec93450", + "invariantUuid":"e49fbd11-e60c-4a8e-b4bf-30fbe8f4fcc0", + "serviceType":"", + "serviceRole":"", + "isMultiStepDesign":false, + "instanceId":"f8791436-8d55-4fde-b4d5-72dd2cf13cfb" +} \ No newline at end of file diff --git a/vid-app-common/src/test/resources/payload_jsons/network_instantiation_request.json b/vid-app-common/src/test/resources/payload_jsons/network_instantiation_request.json index 5a722ac4c..241ee07a9 100644 --- a/vid-app-common/src/test/resources/payload_jsons/network_instantiation_request.json +++ b/vid-app-common/src/test/resources/payload_jsons/network_instantiation_request.json @@ -12,10 +12,10 @@ "cloudConfiguration": { "lcpCloudRegionId": "mdt1", "tenantId": "88a6ca3ee0394ade9403f075db23167e", - "cloudOwner" : "att-aic" + "cloudOwner" : "irma-aic" }, "requestInfo": { - "instanceName": "vmxnjr001_001", + "instanceName": "vmxnjr001", "productFamilyId": "a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb", "source": "VID", "suppressRollback": true, @@ -42,7 +42,8 @@ } ], "requestParameters": { - "userParams": [] + "userParams": [], + "testApi" : "VNF_API" } } } \ No newline at end of file diff --git a/vid-app-common/src/test/resources/payload_jsons/network_instantiation_request_without_instance_name.json b/vid-app-common/src/test/resources/payload_jsons/network_instantiation_request_without_instance_name.json index db55736c4..8b69e0beb 100644 --- a/vid-app-common/src/test/resources/payload_jsons/network_instantiation_request_without_instance_name.json +++ b/vid-app-common/src/test/resources/payload_jsons/network_instantiation_request_without_instance_name.json @@ -12,7 +12,7 @@ "cloudConfiguration": { "lcpCloudRegionId": "mdt1", "tenantId": "88a6ca3ee0394ade9403f075db23167e", - "cloudOwner" : "att-aic" + "cloudOwner" : "irma-aic" }, "requestInfo": { "productFamilyId": "a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb", @@ -41,7 +41,8 @@ } ], "requestParameters": { - "userParams": [] + "userParams": [], + "testApi" : "VNF_API" } } } \ No newline at end of file diff --git a/vid-app-common/src/test/resources/payload_jsons/pre_1806_macro_service_instantiation_request.json b/vid-app-common/src/test/resources/payload_jsons/pre_1806_macro_service_instantiation_request.json new file mode 100644 index 000000000..992323023 --- /dev/null +++ b/vid-app-common/src/test/resources/payload_jsons/pre_1806_macro_service_instantiation_request.json @@ -0,0 +1,47 @@ +{ + "requestDetails": { + "modelInfo": { + "modelType": "service", + "modelInvariantId": "ff3514e3-5a33-55df-13ab-12abad84e7ff", + "modelVersionId": "fe6985cd-ea33-3346-ac12-ab121484a3fe", + "modelName": "sriov", + "modelVersion": "1.0" + }, + "cloudConfiguration": { + "cloudOwner": "irma-aic", + "lcpCloudRegionId": "mdt1", + "tenantId": "88a6ca3ee0394ade9403f075db23167e" + }, + "owningEntity": { + "owningEntityId": "038d99af-0427-42c2-9d15-971b99b9b489", + "owningEntityName": "JULIO ERICKSON" + }, + "project": { + "projectName": "some_project_name" + }, + "subscriberInfo": { + "globalSubscriberId": "some_subscriber_id", + "subscriberName": "some_subscriber_name" + }, + "requestInfo": { + "productFamilyId": "a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb", + "source": "VID", + "suppressRollback": true, + "requestorId": "az2016" + }, + "requestParameters": { + "subscriptionServiceType": "MOG", + "aLaCarte": false, + "userParams": [ + { + "name": "someUserParam", + "value": "someValue" + }, + { + "name": "anotherUserParam", + "value": "anotherValue" + } + ] + } + } +} \ No newline at end of file diff --git a/vid-app-common/src/test/resources/payload_jsons/pre_1806_macro_without_cloudConfiguration.json b/vid-app-common/src/test/resources/payload_jsons/pre_1806_macro_without_cloudConfiguration.json new file mode 100644 index 000000000..472ccc90e --- /dev/null +++ b/vid-app-common/src/test/resources/payload_jsons/pre_1806_macro_without_cloudConfiguration.json @@ -0,0 +1,42 @@ +{ + "requestDetails": { + "modelInfo": { + "modelType": "service", + "modelInvariantId": "ff3514e3-5a33-55df-13ab-12abad84e7ff", + "modelVersionId": "fe6985cd-ea33-3346-ac12-ab121484a3fe", + "modelName": "sriov", + "modelVersion": "1.0" + }, + "owningEntity": { + "owningEntityId": "038d99af-0427-42c2-9d15-971b99b9b489", + "owningEntityName": "JULIO ERICKSON" + }, + "project": { + "projectName": "some_project_name" + }, + "subscriberInfo": { + "globalSubscriberId": "some_subscriber_id", + "subscriberName": "some_subscriber_name" + }, + "requestInfo": { + "productFamilyId": "a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb", + "source": "VID", + "suppressRollback": true, + "requestorId": "az2016" + }, + "requestParameters": { + "subscriptionServiceType": "MOG", + "aLaCarte": false, + "userParams": [ + { + "name": "someUserParam", + "value": "someValue" + }, + { + "name": "anotherUserParam", + "value": "anotherValue" + } + ] + } + } +} \ No newline at end of file diff --git a/vid-app-common/src/test/resources/payload_jsons/resume/feRequestResumeMacroService.json b/vid-app-common/src/test/resources/payload_jsons/resume/feRequestResumeMacroService.json new file mode 100644 index 000000000..c2c84dc9c --- /dev/null +++ b/vid-app-common/src/test/resources/payload_jsons/resume/feRequestResumeMacroService.json @@ -0,0 +1,107 @@ +{ + "isDirty": false, + "instanceParams": [], + "existingNames": { + "ncmvlansvcym161f_77": "" + }, + "vidNotions": { + "instantiationType": "Macro", + "instantiationUI": "serviceWithCollectionResource", + "modelCategory": "other", + "viewEditUI": "serviceWithCollectionResource" + }, + "bulkSize": 1, + "action": "Resume", + "instanceName": "NcmVlanSvcYm161f_77", + "instanceId": "a565e6ad-75d1-4493-98f1-33234b5c17e2", + "orchStatus": "Assigned", + "productFamilyId": null, + "lcpCloudRegionId": null, + "tenantId": null, + "cloudOwner": null, + "modelInfo": { + "modelInvariantId": "f6342be5-d66b-4d03-a1aa-c82c3094c4ea", + "modelVersionId": "6e0bec91-09f3-43aa-9cf3-e617cd0146be", + "modelName": "NCM_VLAN_SVC_ym161f", + "modelType": "service", + "modelVersion": "8.0" + }, + "globalSubscriberId": "a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb", + "subscriptionServiceType": "Emanuel", + "owningEntityId": null, + "owningEntityName": null, + "tenantName": null, + "aicZoneId": null, + "aicZoneName": null, + "projectName": null, + "rollbackOnFailure": false, + "isALaCarte": false, + "vnfs": {}, + "vrfs": {}, + "networks": {}, + "vnfGroups": {}, + "validationCounter": 0, + "existingVNFCounterMap": {}, + "existingVRFCounterMap": {}, + "existingNetworksCounterMap": {}, + "existingVnfGroupCounterMap": {}, + "collectionResources": { + "84a351ae-3601-45e2-98df-878d6c816abc": { + "action": "None", + "instanceName": "NcmVlanSvcYm161f_77_vTSBC Customer Landing Network Collection", + "instanceId": "84a351ae-3601-45e2-98df-878d6c816abc", + "orchStatus": "Active", + "productFamilyId": null, + "lcpCloudRegionId": null, + "tenantId": null, + "cloudOwner": null, + "modelInfo": { + "modelInvariantId": "081ceb56-eb71-4566-a72d-3e7cbee5cdf1", + "modelVersionId": "ce8c98bc-4691-44fb-8ff0-7a47487c11c4", + "modelName": "NCM_VLAN_ym161f", + "modelType": "collection", + "modelVersion": "5.0" + }, + "instanceType": null, + "provStatus": null, + "inMaint": false, + "uuid": "ce8c98bc-4691-44fb-8ff0-7a47487c11c4", + "originalName": "NCM_VLAN_ym161f 0", + "legacyRegion": null, + "lineOfBusiness": null, + "platformName": null, + "trackById": "84a351ae-3601-45e2-98df-878d6c816abc", + "ncfs": { + "6b3536cf-3a12-457f-abb5-fa2203e0d923": { + "action": "None", + "instanceName": "NcmVlanSvcYm161f_77_vTSBC Customer Landing Network Collection", + "instanceId": "6b3536cf-3a12-457f-abb5-fa2203e0d923", + "orchStatus": null, + "productFamilyId": null, + "lcpCloudRegionId": null, + "tenantId": null, + "cloudOwner": null, + "modelInfo": { + "modelInvariantId": "868b109c-9481-4a18-891b-af974db7705a", + "modelVersionId": "dd182d7d-6949-4b90-b3cc-5befe400742e", + "modelName": "ncm_vlan_ym161f..NetworkCollection..0", + "modelType": "instanceGroup", + "modelVersion": "1" + }, + "instanceType": "L3-NETWORK", + "provStatus": null, + "inMaint": false, + "uuid": "dd182d7d-6949-4b90-b3cc-5befe400742e", + "originalName": "ncm_vlan_ym161f..NetworkCollection..0", + "legacyRegion": null, + "lineOfBusiness": null, + "platformName": null, + "trackById": "6b3536cf-3a12-457f-abb5-fa2203e0d923", + "instanceGroupRole": "SUB_INTERFACE", + "instanceGroupFunction": "vTSBC Customer Landing Network Collection", + "numberOfNetworks": 1 + } + } + } + } +} diff --git a/vid-app-common/src/test/resources/payload_jsons/resume/msoResponseGetRequestsOfServiceInstance.json b/vid-app-common/src/test/resources/payload_jsons/resume/msoResponseGetRequestsOfServiceInstance.json new file mode 100644 index 000000000..cb49dd8da --- /dev/null +++ b/vid-app-common/src/test/resources/payload_jsons/resume/msoResponseGetRequestsOfServiceInstance.json @@ -0,0 +1,62 @@ +{ + "requestList": [ + { + "request": { + "requestId": "894089b8-f7f4-418d-81da-34186fd32670", + "startTime": "Wed, 10 Oct 2018 08:01:21 GMT", + "finishTime": "Wed, 10 Oct 2018 08:01:43 GMT", + "requestScope": "service", + "requestType": "createInstance", + "requestDetails": { + "modelInfo": { + "modelInvariantId": "f6342be5-d66b-4d03-a1aa-c82c3094c4ea", + "modelType": "service", + "modelName": "NCM_VLAN_SVC_ym161f", + "modelVersion": "8.0", + "modelVersionId": "6e0bec91-09f3-43aa-9cf3-e617cd0146be", + "modelUuid": "6e0bec91-09f3-43aa-9cf3-e617cd0146be", + "modelInvariantUuid": "f6342be5-d66b-4d03-a1aa-c82c3094c4ea" + }, + "requestInfo": { + "productFamilyId": "db171b8f-115c-4992-a2e3-ee04cae357e0", + "source": "VID", + "suppressRollback": false, + "requestorId": "cs0554" + }, + "subscriberInfo": { + "globalSubscriberId": "a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb" + }, + "cloudConfiguration": { + "tenantId": "d3b49834f7164cbe831bfbfa35ef649b", + "cloudOwner": "irma-aic", + "lcpCloudRegionId": "Two" + }, + "requestParameters": { + "subscriptionServiceType": "Emanuel", + "userParams": [ + { + "name": "aic_zone", + "value": "TTL58" + } + ], + "aLaCarte": false + }, + "owningEntity": { + "owningEntityId": "e4257a94-21cc-40c5-adc9-e6f4ff868e31", + "owningEntityName": "EMANUEL-CORE" + } + }, + "instanceReferences": { + "serviceInstanceId": "a565e6ad-75d1-4493-98f1-33234b5c17e2", + "requestorId": "cs0554" + }, + "requestStatus": { + "requestState": "FAILED", + "statusMessage": "STATUS: Macro-Service-createInstance request was executed correctly.", + "percentProgress": 100, + "timestamp": "Wed, 10 Oct 2018 08:01:43 GMT" + } + } + } + ] +} diff --git a/vid-app-common/src/test/resources/payload_jsons/vfModuleDelete1Create1None1Request.json b/vid-app-common/src/test/resources/payload_jsons/vfModuleDelete1Create1None1Request.json new file mode 100644 index 000000000..642c2aac9 --- /dev/null +++ b/vid-app-common/src/test/resources/payload_jsons/vfModuleDelete1Create1None1Request.json @@ -0,0 +1,139 @@ +{ + "action": "None", + "isDirty": true, + "vnfs": { + "2017-488_PASQUALE-vPE 0": { + "vfModules": { + "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0": { + "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0uvfot": { + "instanceName": "VFinstancenameZERO", + "instanceId": "VF_MODULE_INSTANCE_ID", + "action": "Create", + "lcpCloudRegionId": "AAIAIC25", + "tenantId": "092eb9e8e4b7412e8787dd091bc58e86", + "modelInfo": { + "modelInvariantId": "b34833bb-6aa9-4ad6-a831-70b06367a091", + "modelVersionId": "f8360508-3f17-4414-a2ed-6bc71161e8db", + "modelName": "2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0", + "modelVersion": "5", + "modelCustomizationId": "a55961b2-2065-4ab0-a5b7-2fcee1c227e3", + "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0", + "uuid": "f8360508-3f17-4414-a2ed-6bc71161e8db" + }, + "uuid": "f8360508-3f17-4414-a2ed-6bc71161e8db", + "provStatus": "Prov Status", + "orchStatus": "Active", + "inMaint": true + } + }, + "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vRE_BV..module-1": { + "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vRE_BV..module-1fshmc": { + "instanceName": "VFinstancename", + "instanceId": "VF_MODULE_INSTANCE_ID", + "action": "None_Delete", + "volumeGroupName": "VFinstancename_vol_abc", + "orchStatus": "Create", + "provStatus": "Prov Status", + "inMaint": false, + "lcpCloudRegionId": "AAIAIC25", + "tenantId": "092eb9e8e4b7412e8787dd091bc58e86", + "modelInfo": { + "modelInvariantId": "7253ff5c-97f0-4b8b-937c-77aeb4d79aa1", + "modelVersionId": "25284168-24bb-4698-8cb4-3f509146eca5", + "modelName": "2017488PasqualeVpe..PASQUALE_vRE_BV..module-1", + "modelVersion": "6", + "modelCustomizationId": "f7e7c365-60cf-49a9-9ebf-a1aa11b9d401", + "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_vRE_BV..module-1", + "uuid": "25284168-24bb-4698-8cb4-3f509146eca5" + }, + "uuid": "25284168-24bb-4698-8cb4-3f509146eca5" + } + }, + "2017588_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vRE_BV..module-2": { + "2017588_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vRE_BV..module-2frgth": { + "instanceName": "VFinstancename", + "instanceId": "VF_MODULE_INSTANCE_ID1", + "action": "None", + "volumeGroupName": "VFinstancename_vol_abc", + "orchStatus": "Create", + "provStatus": "Prov Status", + "inMaint": false, + "lcpCloudRegionId": "AAIAIC25", + "tenantId": "092eb9e8e4b7412e8787dd091bc58e86", + "modelInfo": { + "modelInvariantId": "7253ff5c-97f0-4b8b-937c-77aeb4d79aa1", + "modelVersionId": "25284168-24bb-4698-8cb4-3f509146eca5", + "modelName": "2017488PasqualeVpe..PASQUALE_vRE_BV..module-1", + "modelVersion": "6", + "modelCustomizationId": "f7e7c365-60cf-49a9-9ebf-a1aa11b9d401", + "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_vRE_BV..module-1", + "uuid": "25284168-24bb-4698-8cb4-3f509146eca5" + }, + "uuid": "25284168-24bb-4698-8cb4-3f509146eca5" + } + } + }, + "uuid": "69e09f68-8b63-4cc9-b9ff-860960b5db09", + "productFamilyId": "e433710f-9217-458d-a79d-1c7aff376d89", + "lcpCloudRegionId": "AAIAIC25", + "tenantId": "092eb9e8e4b7412e8787dd091bc58e86", + "lineOfBusiness": "ONAP", + "platformName": "platform", + "modelInfo": { + "modelInvariantId": "72e465fe-71b1-4e7b-b5ed-9496118ff7a8", + "modelVersionId": "69e09f68-8b63-4cc9-b9ff-860960b5db09", + "modelName": "2017-488_PASQUALE-vPE", + "modelVersion": "5.0", + "modelCustomizationId": "1da7b585-5e61-4993-b95e-8e6606c81e45", + "modelCustomizationName": "2017-488_PASQUALE-vPE 0", + "uuid": "69e09f68-8b63-4cc9-b9ff-860960b5db09" + }, + "orchStatus": "Created", + "inMaint": false, + "instanceId": "VNF_INSTANCE_ID", + "instanceName": "2017488_PASQUALEvPEVNFinstancename", + "action": "None", + "legacyRegion": "some legacy region" + } + }, + "instanceParams": [], + "validationCounter": 0, + "existingNames": { + "mcankinstancename": "" + }, + "existingVNFCounterMap": { + "afacccf6-397d-45d6-b5ae-94c39734b168": 1, + "69e09f68-8b63-4cc9-b9ff-860960b5db09": 3, + "b3c76f73-eeb5-4fb6-9d31-72a889f1811c": 1 + }, + "existingVnfGroupCounterMap": {}, + "existingNetworksCounterMap": {}, + "networks": {}, + "vnfGroups": {}, + "bulkSize": 1, + "instanceId": "f8791436-8d55-4fde-b4d5-72dd2cf13cfb", + "instanceName": "mCaNkinstancename", + "globalSubscriberId": "e433710f-9217-458d-a79d-1c7aff376d89", + "subscriptionServiceType": "TYLER SILVIA", + "owningEntityId": "d61e6f2d-12fa-4cc2-91df-7c244011d6fc", + "productFamilyId": "e433710f-9217-458d-a79d-1c7aff376d89", + "lcpCloudRegionId": "hvf6", + "tenantId": "bae71557c5bb4d5aac6743a4e5f1d054", + "aicZoneId": "NFT1", + "projectName": "WATKINS", + "rollbackOnFailure": true, + "aicZoneName": "NFTJSSSS-NFT1", + "owningEntityName": "WayneHolland", + "tenantName": "AIN Web Tool-15-D-testalexandria", + "modelInfo": { + "modelInvariantId": "e49fbd11-e60c-4a8e-b4bf-30fbe8f4fcc0", + "modelVersionId": "6b528779-44a3-4472-bdff-9cd15ec93450", + "modelName": "action-data", + "modelVersion": "1.0", + "uuid": "6b528779-44a3-4472-bdff-9cd15ec93450" + }, + "isALaCarte": true, + "orchStatus": "Active", + "modelInavariantId": "6b528779-44a3-4472-bdff-9cd15ec93450", + "testApi": "VNF_API" +} \ No newline at end of file diff --git a/vid-app-common/src/test/resources/payload_jsons/vfmodule/replace_vfmodule.json b/vid-app-common/src/test/resources/payload_jsons/vfmodule/replace_vfmodule.json new file mode 100644 index 000000000..c3ab694aa --- /dev/null +++ b/vid-app-common/src/test/resources/payload_jsons/vfmodule/replace_vfmodule.json @@ -0,0 +1,52 @@ +{ + "requestDetails": { + "requestInfo": { + "source": "VID", + "requestorId": "az2016", + "instanceName": "replace_module", + "suppressRollback": false + }, + "relatedInstanceList": [{ + "relatedInstance": { + "instanceId": "e9993045-cc96-4f3f-bf9a-71b2a400a956", + "modelInfo": { + "modelVersionId": "bad955c3-29b2-4a27-932e-28e942cc6480", + "modelVersion": "1", + "modelName": "Vf zolson5bpxmc02092017-Service", + "modelInvariantId": "b16a9398-ffa3-4041-b78c-2956b8ad9c7b", + "modelType": "service" + } + } + }, { + "relatedInstance": { + "instanceId": "5c9c2896-1fe6-4055-b7ec-d0a01e5f9bf5", + "modelInfo": { + "modelName": "Vf zolson5bpxmc02092017-VF", + "modelVersion": "1", + "modelInvariantId": "23122c9b-dd7f-483f-bf0a-e069303db2f7", + "modelType": "vnf", + "modelCustomizationName": "Vf zolson5bpxmc02092017-VF 0", + "modelVersionId": "d326f424-2312-4dd6-b7fe-364fadbd1ef5", + "modelCustomizationId": "96c23a4a-6887-4b2c-9cce-1e4ea35eaade" + } + } + }], + "requestParameters": { + "userParams": [], + "testApi": "GR_API" + }, + "modelInfo": { + "modelName": "VfZrdm5bpxmc02092017Vf..CORNELIUS_base..module-0", + "modelVersion": "1", + "modelInvariantId": "f7a867f2-596b-4f4a-a128-421e825a6190", + "modelType": "vfModule", + "modelVersionId": "eb5de6fb-9ecf-4009-b922-fae3a9ae7d46", + "modelCustomizationId": "074c64d0-7e13-4bcc-8bdb-ea922331102d" + }, + "cloudConfiguration": { + "cloudOwner": "irma-aic", + "tenantId": "0422ffb57ba042c0800a29dc85ca70f8", + "lcpCloudRegionId": "regionOne" + } + } +} \ No newline at end of file diff --git a/vid-app-common/src/test/resources/payload_jsons/vfmodule/replace_vfmodule_fe_input.json b/vid-app-common/src/test/resources/payload_jsons/vfmodule/replace_vfmodule_fe_input.json new file mode 100644 index 000000000..92ccfe541 --- /dev/null +++ b/vid-app-common/src/test/resources/payload_jsons/vfmodule/replace_vfmodule_fe_input.json @@ -0,0 +1,92 @@ +{ + "action": "None", + "isDirty": true, + "vnfs": { + "Vf zolson5bpxmc02092017-VF 0": { + "vfModules": { + "VfZrdm5bpxmc02092017Vf..CORNELIUS_base..module-0": { + "VfZrdm5bpxmc02092017Vf..CORNELIUS_base..module-0-?": { + "instanceName": "replace_module", + "instanceId": "5d49c3b1-fc90-4762-8c98-e800170baa55", + "action": "Replace", + "orchStatus": "Create", + "provStatus": "Prov Status", + "inMaint": false, + "rollbackOnFailure": true, + "lcpCloudRegionId": "regionOne", + "tenantId": "0422ffb57ba042c0800a29dc85ca70f8", + "modelInfo": { + "modelInvariantId": "f7a867f2-596b-4f4a-a128-421e825a6190", + "modelVersionId": "eb5de6fb-9ecf-4009-b922-fae3a9ae7d46", + "modelName": "VfZrdm5bpxmc02092017Vf..CORNELIUS_base..module-0", + "modelVersion": "1", + "modelCustomizationId": "074c64d0-7e13-4bcc-8bdb-ea922331102d", + "uuid": "eb5de6fb-9ecf-4009-b922-fae3a9ae7d46" + }, + "uuid": "eb5de6fb-9ecf-4009-b922-fae3a9ae7d46" + } + } + }, + "uuid": "d326f424-2312-4dd6-b7fe-364fadbd1ef5", + "productFamilyId": "bad955c3-29b2-4a27-932e-28e942cc6480", + "lcpCloudRegionId": "regionOne", + "tenantId": "0422ffb57ba042c0800a29dc85ca70f8", + "lineOfBusiness": "ONAP", + "platformName": "platform", + "modelInfo": { + "modelInvariantId": "23122c9b-dd7f-483f-bf0a-e069303db2f7", + "modelVersionId": "d326f424-2312-4dd6-b7fe-364fadbd1ef5", + "modelName": "Vf zolson5bpxmc02092017-VF", + "modelVersion": "1", + "modelCustomizationId": "96c23a4a-6887-4b2c-9cce-1e4ea35eaade", + "modelCustomizationName": "Vf zolson5bpxmc02092017-VF 0", + "uuid": "d326f424-2312-4dd6-b7fe-364fadbd1ef5" + }, + "orchStatus": "Created", + "inMaint": false, + "rollbackOnFailure": true, + "instanceId": "5c9c2896-1fe6-4055-b7ec-d0a01e5f9bf5", + "instanceName": "vnf_of_replace_module", + "action": "None", + "legacyRegion": "some legacy region" + } + }, + "instanceParams": [], + "validationCounter": 0, + "existingNames": { + "mcankinstancename": "" + }, + "existingVNFCounterMap": { + "d326f424-2312-4dd6-b7fe-364fadbd1ef5": 1 + }, + "existingVnfGroupCounterMap": {}, + "existingNetworksCounterMap": {}, + "networks": {}, + "vnfGroups": {}, + "bulkSize": 1, + "instanceId": "e9993045-cc96-4f3f-bf9a-71b2a400a956", + "instanceName": "service_of_replace_module", + "globalSubscriberId": "e433710f-9217-458d-a79d-1c7aff376d89", + "subscriptionServiceType": "TYLER SILVIA", + "owningEntityId": "d61e6f2d-12fa-4cc2-91df-7c244011d6fc", + "productFamilyId": "bad955c3-29b2-4a27-932e-28e942cc6480", + "lcpCloudRegionId": "regionOne", + "tenantId": "0422ffb57ba042c0800a29dc85ca70f8", + "aicZoneId": "NFT1", + "projectName": "WATKINS", + "rollbackOnFailure": true, + "aicZoneName": "NFTJSSSS-NFT1", + "owningEntityName": "WayneHolland", + "tenantName": "tenant_name", + "modelInfo": { + "modelInvariantId": "b16a9398-ffa3-4041-b78c-2956b8ad9c7b", + "modelVersionId": "bad955c3-29b2-4a27-932e-28e942cc6480", + "modelName": "Vf zolson5bpxmc02092017-Service", + "modelVersion": "1", + "uuid": "bad955c3-29b2-4a27-932e-28e942cc6480" + }, + "isALaCarte": true, + "orchStatus": "Active", + "modelInavariantId": "b16a9398-ffa3-4041-b78c-2956b8ad9c7b", + "testApi": "GR_API" +} \ No newline at end of file diff --git a/vid-app-common/src/test/resources/payload_jsons/vfmodule_instantiation_request.json b/vid-app-common/src/test/resources/payload_jsons/vfmodule_instantiation_request.json index 92f837faf..1bce76097 100644 --- a/vid-app-common/src/test/resources/payload_jsons/vfmodule_instantiation_request.json +++ b/vid-app-common/src/test/resources/payload_jsons/vfmodule_instantiation_request.json @@ -12,7 +12,7 @@ "cloudConfiguration": { "lcpCloudRegionId": "mdt1", "tenantId": "88a6ca3ee0394ade9403f075db23167e", - "cloudOwner" : "att-aic" + "cloudOwner" : "irma-aic" }, "requestInfo": { "instanceName": "vmxnjr001_AVPN_base_vRE_BV_expansion", @@ -63,7 +63,8 @@ "vre_a_volume_size_0" : "100", "vmx_int_net_len" : "24", "availability_zone_0": "mtpocdv-kvm-az01" - }] + }], + "testApi" : "VNF_API" } } } diff --git a/vid-app-common/src/test/resources/payload_jsons/vfmodule_instantiation_request_without_instance_name.json b/vid-app-common/src/test/resources/payload_jsons/vfmodule_instantiation_request_without_instance_name.json index 82df5b90a..1c0d2b981 100644 --- a/vid-app-common/src/test/resources/payload_jsons/vfmodule_instantiation_request_without_instance_name.json +++ b/vid-app-common/src/test/resources/payload_jsons/vfmodule_instantiation_request_without_instance_name.json @@ -12,7 +12,7 @@ "cloudConfiguration": { "lcpCloudRegionId": "mdt1", "tenantId": "88a6ca3ee0394ade9403f075db23167e", - "cloudOwner" : "att-aic" + "cloudOwner" : "irma-aic" }, "requestInfo": { "source": "VID", @@ -53,7 +53,8 @@ "vre_a_volume_size_0" : "100", "vmx_int_net_len" : "24", "availability_zone_0": "mtpocdv-kvm-az01" - }] + }], + "testApi" : "VNF_API" } } } \ No newline at end of file diff --git a/vid-app-common/src/test/resources/payload_jsons/vfmodule_instantiation_request_without_volume_group.json b/vid-app-common/src/test/resources/payload_jsons/vfmodule_instantiation_request_without_volume_group.json index cfa4c2652..3581a475a 100644 --- a/vid-app-common/src/test/resources/payload_jsons/vfmodule_instantiation_request_without_volume_group.json +++ b/vid-app-common/src/test/resources/payload_jsons/vfmodule_instantiation_request_without_volume_group.json @@ -12,7 +12,7 @@ "cloudConfiguration": { "lcpCloudRegionId": "mdt1", "tenantId": "88a6ca3ee0394ade9403f075db23167e", - "cloudOwner" : "att-aic" + "cloudOwner" : "irma-aic" }, "requestInfo": { "instanceName": "vmxnjr001_AVPN_base_vRE_BV_expansion", @@ -54,7 +54,8 @@ "vre_a_volume_size_0" : "100", "vmx_int_net_len" : "24", "availability_zone_0": "mtpocdv-kvm-az01" - }] + }], + "testApi" : "VNF_API" } } } \ No newline at end of file diff --git a/vid-app-common/src/test/resources/payload_jsons/vnf/bulk_vnf_request.json b/vid-app-common/src/test/resources/payload_jsons/vnf/bulk_vnf_request.json new file mode 100644 index 000000000..1ae0406a7 --- /dev/null +++ b/vid-app-common/src/test/resources/payload_jsons/vnf/bulk_vnf_request.json @@ -0,0 +1,49 @@ + { + "requestDetails": { + "modelInfo": { + "modelType": "vnf", + "modelInvariantId": "11111111-f63c-463e-ba94-286933b895f9", + "modelVersionId": "7f40c192-f63c-463e-ba94-286933b895f8", + "modelName": "2016-73_MOW-AVPN-vPE-BV-L", + "modelVersion": "10.0", + "modelCustomizationName": "2016-73_MOW-AVPN-vPE-BV-L 0", + "modelCustomizationId": "ab153b6e-c364-44c0-bef6-1f2982117f04" + }, + "cloudConfiguration": { + "lcpCloudRegionId": "mdt1", + "tenantId": "88a6ca3ee0394ade9403f075db23167e", + "cloudOwner" : "irma-aic" + }, + "requestInfo": { + "instanceName": "vmxnjr001", + "productFamilyId": "a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb", + "source": "VID", + "suppressRollback": true, + "requestorId": "pa0916" + }, + "platform": { + "platformName": "platformName" + }, + "lineOfBusiness": { + "lineOfBusinessName": "lineOfBusinessName" + }, + "relatedInstanceList": [ + { + "relatedInstance": { + "instanceId": "aa3514e3-5a33-55df-13ab-12abad84e7aa", + "modelInfo": { + "modelType": "service", + "modelInvariantId": "ff3514e3-5a33-55df-13ab-12abad84e7ff", + "modelVersionId": "fe6985cd-ea33-3346-ac12-ab121484a3fe", + "modelName": "sriov", + "modelVersion": "1.0" + } + } + } + ], + "requestParameters": { + "userParams": [], + "testApi" : "VNF_API" + } + } + } \ No newline at end of file diff --git a/vid-app-common/src/test/resources/payload_jsons/vnf/bulk_vnf_request_without_cloud_owner.json b/vid-app-common/src/test/resources/payload_jsons/vnf/bulk_vnf_request_without_cloud_owner.json new file mode 100644 index 000000000..191696490 --- /dev/null +++ b/vid-app-common/src/test/resources/payload_jsons/vnf/bulk_vnf_request_without_cloud_owner.json @@ -0,0 +1,48 @@ + { + "requestDetails": { + "modelInfo": { + "modelType": "vnf", + "modelInvariantId": "11111111-f63c-463e-ba94-286933b895f9", + "modelVersionId": "7f40c192-f63c-463e-ba94-286933b895f8", + "modelName": "2016-73_MOW-AVPN-vPE-BV-L", + "modelVersion": "10.0", + "modelCustomizationName": "2016-73_MOW-AVPN-vPE-BV-L 0", + "modelCustomizationId": "ab153b6e-c364-44c0-bef6-1f2982117f04" + }, + "cloudConfiguration": { + "lcpCloudRegionId": "mdt1", + "tenantId": "88a6ca3ee0394ade9403f075db23167e" + }, + "requestInfo": { + "instanceName": "vmxnjr001", + "productFamilyId": "a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb", + "source": "VID", + "suppressRollback": true, + "requestorId": "pa0916" + }, + "platform": { + "platformName": "platformName" + }, + "lineOfBusiness": { + "lineOfBusinessName": "lineOfBusinessName" + }, + "relatedInstanceList": [ + { + "relatedInstance": { + "instanceId": "aa3514e3-5a33-55df-13ab-12abad84e7aa", + "modelInfo": { + "modelType": "service", + "modelInvariantId": "ff3514e3-5a33-55df-13ab-12abad84e7ff", + "modelVersionId": "fe6985cd-ea33-3346-ac12-ab121484a3fe", + "modelName": "sriov", + "modelVersion": "1.0" + } + } + } + ], + "requestParameters": { + "userParams": [], + "testApi" : "VNF_API" + } + } + } \ No newline at end of file diff --git a/vid-app-common/src/test/resources/payload_jsons/vnf/bulk_vnf_request_without_instance_name.json b/vid-app-common/src/test/resources/payload_jsons/vnf/bulk_vnf_request_without_instance_name.json new file mode 100644 index 000000000..3b59e6d29 --- /dev/null +++ b/vid-app-common/src/test/resources/payload_jsons/vnf/bulk_vnf_request_without_instance_name.json @@ -0,0 +1,48 @@ +{ + "requestDetails": { + "modelInfo": { + "modelType": "vnf", + "modelInvariantId": "11111111-f63c-463e-ba94-286933b895f9", + "modelVersionId": "7f40c192-f63c-463e-ba94-286933b895f8", + "modelName": "2016-73_MOW-AVPN-vPE-BV-L", + "modelVersion": "10.0", + "modelCustomizationName": "2016-73_MOW-AVPN-vPE-BV-L 0", + "modelCustomizationId": "ab153b6e-c364-44c0-bef6-1f2982117f04" + }, + "cloudConfiguration": { + "lcpCloudRegionId": "mdt1", + "tenantId": "88a6ca3ee0394ade9403f075db23167e", + "cloudOwner": "irma-aic" + }, + "requestInfo": { + "productFamilyId": "a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb", + "source": "VID", + "suppressRollback": true, + "requestorId": "pa0916" + }, + "platform": { + "platformName": "platformName" + }, + "lineOfBusiness": { + "lineOfBusinessName": "lineOfBusinessName" + }, + "relatedInstanceList": [ + { + "relatedInstance": { + "instanceId": "aa3514e3-5a33-55df-13ab-12abad84e7aa", + "modelInfo": { + "modelType": "service", + "modelInvariantId": "ff3514e3-5a33-55df-13ab-12abad84e7ff", + "modelVersionId": "fe6985cd-ea33-3346-ac12-ab121484a3fe", + "modelName": "sriov", + "modelVersion": "1.0" + } + } + } + ], + "requestParameters": { + "userParams": [], + "testApi" : "VNF_API" + } + } +} \ No newline at end of file diff --git a/vid-app-common/src/test/resources/payload_jsons/vnf/vnf_without_lob_expected.json b/vid-app-common/src/test/resources/payload_jsons/vnf/vnf_without_lob_expected.json new file mode 100644 index 000000000..11c5dcb63 --- /dev/null +++ b/vid-app-common/src/test/resources/payload_jsons/vnf/vnf_without_lob_expected.json @@ -0,0 +1,46 @@ +{ + "requestDetails": { + "modelInfo": { + "modelCustomizationName": "xbi test VID noFC HEAT 0", + "modelCustomizationId": "e9745411-1f7d-47e3-9857-47363cb9ff92", + "modelInvariantId": "77d3a011-affb-4166-89b2-c4be7bc4ff23", + "modelVersionId": "9bb0edd9-3631-455b-bdfd-979b2ab53d07", + "modelName": "xbi test VID noFC HEAT", + "modelType": "vnf", + "modelVersion": "1.0" + }, + "cloudConfiguration": { + "lcpCloudRegionId": "olson52b", + "tenantId": "bbf14e449c954feea272e926a8c2b244", + "cloudOwner" : "irma-aic" + }, + "requestInfo": { + "instanceName": "zolson52bfrwl01", + "productFamilyId": "a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb", + "source": "VID", + "suppressRollback": false, + "requestorId": "pa0916" + }, + "platform": { + "platformName": "NETWORK-CLOUD" + }, + "relatedInstanceList": [ + { + "relatedInstance": { + "instanceId": "aa3514e3-5a33-55df-13ab-12abad84e7aa", + "modelInfo": { + "modelType": "service", + "modelInvariantId": "ff3514e3-5a33-55df-13ab-12abad84e7ff", + "modelVersionId": "fe6985cd-ea33-3346-ac12-ab121484a3fe", + "modelName": "sriov", + "modelVersion": "1.0" + } + } + } + ], + "requestParameters": { + "userParams": [], + "testApi": "VNF_API" + } + } +} diff --git a/vid-app-common/src/test/resources/payload_jsons/vnf/vnf_without_lob_user_input.json b/vid-app-common/src/test/resources/payload_jsons/vnf/vnf_without_lob_user_input.json new file mode 100644 index 000000000..60be0d13e --- /dev/null +++ b/vid-app-common/src/test/resources/payload_jsons/vnf/vnf_without_lob_user_input.json @@ -0,0 +1,24 @@ +{ + "modelInfo": { + "modelCustomizationName": "xbi test VID noFC HEAT 0", + "modelCustomizationId": "e9745411-1f7d-47e3-9857-47363cb9ff92", + "modelInvariantId": "77d3a011-affb-4166-89b2-c4be7bc4ff23", + "modelVersionId": "9bb0edd9-3631-455b-bdfd-979b2ab53d07", + "modelName": "xbi test VID noFC HEAT", + "modelType": "vnf", + "modelVersion": "1.0" + }, + "productFamilyId": "a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb", + "instanceName": "zolson52bfrwl01", + "action": "Create", + "platformName": "NETWORK-CLOUD", + "lcpCloudRegionId": "olson52b", + "tenantId": "bbf14e449c954feea272e926a8c2b244", + "instanceParams": [{}], + "rollbackOnFailure": true, + "instanceId": null, + "vfModules": {}, + "trackById": "449206d5-54a6-441f-b5c2-beacb2f2e1cc", + "isFailed": false, + "lineOfBusiness": null +} \ No newline at end of file diff --git a/vid-app-common/src/test/resources/payload_jsons/vnfDelete1Create1Request.json b/vid-app-common/src/test/resources/payload_jsons/vnfDelete1Create1Request.json new file mode 100644 index 000000000..5cf7973be --- /dev/null +++ b/vid-app-common/src/test/resources/payload_jsons/vnfDelete1Create1Request.json @@ -0,0 +1,240 @@ +{ + "action": "None", + "isDirty": true, + "vnfs": { + "2017-388_PASQUALE-vPE 0": { + "vfModules": {}, + "uuid": "afacccf6-397d-45d6-b5ae-94c39734b168", + "productFamilyId": "e433710f-9217-458d-a79d-1c7aff376d89", + "lcpCloudRegionId": "AAIAIC25", + "tenantId": "092eb9e8e4b7412e8787dd091bc58e86", + "lineOfBusiness": "ONAP", + "platformName": "platform", + "modelInfo": { + "modelInvariantId": "72e465fe-71b1-4e7b-b5ed-9496118ff7a8", + "modelVersionId": "afacccf6-397d-45d6-b5ae-94c39734b168", + "modelName": "2017-388_PASQUALE-vPE", + "modelVersion": "4.0", + "modelCustomizationId": "b3c76f73-eeb5-4fb6-9d31-72a889f1811c", + "modelCustomizationName": "2017-388_PASQUALE-vPE 0", + "uuid": "afacccf6-397d-45d6-b5ae-94c39734b168" + }, + "instanceName": "2017388_PASQUALEvPEmCaNkinstanceName", + "action": "None", + "legacyRegion": "some legacy region" + }, + "2017-488_PASQUALE-vPE 0": { + "vfModules": {}, + "uuid": "69e09f68-8b63-4cc9-b9ff-860960b5db09", + "productFamilyId": "e433710f-9217-458d-a79d-1c7aff376d89", + "lcpCloudRegionId": "AAIAIC25", + "tenantId": "092eb9e8e4b7412e8787dd091bc58e86", + "lineOfBusiness": "ONAP", + "platformName": "platform", + "modelInfo": { + "modelInvariantId": "72e465fe-71b1-4e7b-b5ed-9496118ff7a8", + "modelVersionId": "69e09f68-8b63-4cc9-b9ff-860960b5db09", + "modelName": "2017-488_PASQUALE-vPE", + "modelVersion": "5.0", + "modelCustomizationId": "1da7b585-5e61-4993-b95e-8e6606c81e45", + "modelCustomizationName": "2017-488_PASQUALE-vPE 0", + "uuid": "69e09f68-8b63-4cc9-b9ff-860960b5db09" + }, + "orchStatus": "Created", + "inMaint": false, + "instanceId": "VNF_INSTANCE_ID", + "instanceName": "2017488_PASQUALEvPEVNFinstancename", + "action": "None_Delete", + "legacyRegion": "some legacy region" + }, + "2017-488_PASQUALE-vPE 0:0001": { + "vfModules": { + "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0": { + "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0uvfot": { + "instanceName": "VFinstancenameZERO_001", + "action": "None", + "provStatus": "Prov Status", + "inMaint": true, + "modelInfo": { + "modelInvariantId": "b34833bb-6aa9-4ad6-a831-70b06367a091", + "modelVersionId": "f8360508-3f17-4414-a2ed-6bc71161e8db", + "modelName": "2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0", + "modelVersion": "5", + "modelCustomizationId": "a55961b2-2065-4ab0-a5b7-2fcee1c227e3", + "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0", + "uuid": "f8360508-3f17-4414-a2ed-6bc71161e8db" + }, + "uuid": "f8360508-3f17-4414-a2ed-6bc71161e8db" + } + }, + "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vRE_BV..module-1": { + "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vRE_BV..module-1fshmc": { + "instanceName": "VFinstancename_001", + "action": "None", + "volumeGroupName": "VFinstancename_vol_abc_001", + "modelInfo": { + "modelInvariantId": "7253ff5c-97f0-4b8b-937c-77aeb4d79aa1", + "modelVersionId": "25284168-24bb-4698-8cb4-3f509146eca5", + "modelName": "2017488PasqualeVpe..PASQUALE_vRE_BV..module-1", + "modelVersion": "6", + "modelCustomizationId": "f7e7c365-60cf-49a9-9ebf-a1aa11b9d401", + "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_vRE_BV..module-1", + "uuid": "25284168-24bb-4698-8cb4-3f509146eca5" + }, + "uuid": "25284168-24bb-4698-8cb4-3f509146eca5" + } + } + }, + "uuid": "69e09f68-8b63-4cc9-b9ff-860960b5db09", + "productFamilyId": "e433710f-9217-458d-a79d-1c7aff376d89", + "lcpCloudRegionId": "AAIAIC25", + "tenantId": "092eb9e8e4b7412e8787dd091bc58e86", + "lineOfBusiness": "ONAP", + "platformName": "platform", + "modelInfo": { + "modelInvariantId": "72e465fe-71b1-4e7b-b5ed-9496118ff7a8", + "modelVersionId": "69e09f68-8b63-4cc9-b9ff-860960b5db09", + "modelName": "2017-488_PASQUALE-vPE", + "modelVersion": "5.0", + "modelCustomizationId": "1da7b585-5e61-4993-b95e-8e6606c81e45", + "modelCustomizationName": "2017-488_PASQUALE-vPE 0", + "uuid": "69e09f68-8b63-4cc9-b9ff-860960b5db09" + }, + "instanceName": "2017488_PASQUALEvPEVNFinstancename_001", + "action": "None", + "legacyRegion": "some legacy region" + }, + "2017-488_PASQUALE-vPE 0:0002": { + "vfModules": { + "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0": { + "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0uvfot": { + "instanceName": "VFinstancenameZERO_002", + "action": "None", + "modelInfo": { + "modelInvariantId": "b34833bb-6aa9-4ad6-a831-70b06367a091", + "modelVersionId": "f8360508-3f17-4414-a2ed-6bc71161e8db", + "modelName": "2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0", + "modelVersion": "5", + "modelCustomizationId": "a55961b2-2065-4ab0-a5b7-2fcee1c227e3", + "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0", + "uuid": "f8360508-3f17-4414-a2ed-6bc71161e8db" + }, + "uuid": "f8360508-3f17-4414-a2ed-6bc71161e8db" + } + }, + "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vRE_BV..module-1": { + "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vRE_BV..module-1fshmc": { + "instanceName": "VFinstancename_002", + "action": "None", + "volumeGroupName": "VFinstancename_vol_abc_002", + "modelInfo": { + "modelInvariantId": "7253ff5c-97f0-4b8b-937c-77aeb4d79aa1", + "modelVersionId": "25284168-24bb-4698-8cb4-3f509146eca5", + "modelName": "2017488PasqualeVpe..PASQUALE_vRE_BV..module-1", + "modelVersion": "6", + "modelCustomizationId": "f7e7c365-60cf-49a9-9ebf-a1aa11b9d401", + "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_vRE_BV..module-1", + "uuid": "25284168-24bb-4698-8cb4-3f509146eca5" + }, + "uuid": "25284168-24bb-4698-8cb4-3f509146eca5" + } + } + }, + "uuid": "69e09f68-8b63-4cc9-b9ff-860960b5db09", + "productFamilyId": "e433710f-9217-458d-a79d-1c7aff376d89", + "lcpCloudRegionId": "AAIAIC25", + "tenantId": "092eb9e8e4b7412e8787dd091bc58e86", + "lineOfBusiness": "ONAP", + "platformName": "platform", + "modelInfo": { + "modelInvariantId": "72e465fe-71b1-4e7b-b5ed-9496118ff7a8", + "modelVersionId": "69e09f68-8b63-4cc9-b9ff-860960b5db09", + "modelName": "2017-488_PASQUALE-vPE", + "modelVersion": "5.0", + "modelCustomizationId": "1da7b585-5e61-4993-b95e-8e6606c81e45", + "modelCustomizationName": "2017-488_PASQUALE-vPE 0", + "uuid": "69e09f68-8b63-4cc9-b9ff-860960b5db09" + }, + "instanceName": "2017488_PASQUALEvPEVNFinstancename_002", + "action": "None", + "legacyRegion": "some legacy region" + }, + "2017-388_PASQUALE-vPE 0_1": { + "action": "Create", + "inMaint": false, + "rollbackOnFailure": "true", + "originalName": "2017-388_PASQUALE-vPE 0", + "isMissingData": false, + "trackById": "wk10c4hh1oj", + "vfModules": {}, + "vnfStoreKey": "2017-388_PASQUALE-vPE 0_1", + "instanceName": "2017388_PASQUALEvPEmCaNkinstanceName", + "productFamilyId": "a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb", + "lcpCloudRegionId": "hvf6", + "tenantId": "229bcdc6eaeb4ca59d55221141d01f8e", + "platformName": "xxx1", + "lineOfBusiness": "zzz1", + "instanceParams": [ + { + "vnf_config_template_version": "17.2", + "bandwidth_units": "Gbps", + "bandwidth": "10", + "AIC_CLLI": "ATLMY8GA", + "ASN": "AV_vPE", + "vnf_instance_name": "mtnj309me6" + } + ], + "modelInfo": { + "modelInvariantId": "72e465fe-71b1-4e7b-b5ed-9496118ff7a8", + "modelVersionId": "afacccf6-397d-45d6-b5ae-94c39734b168", + "modelName": "2017-388_PASQUALE-vPE", + "modelVersion": "4.0", + "modelCustomizationId": "b3c76f73-eeb5-4fb6-9d31-72a889f1811c", + "modelCustomizationName": "2017-388_PASQUALE-vPE 0", + "uuid": "afacccf6-397d-45d6-b5ae-94c39734b168", + "modelUniqueId": "b3c76f73-eeb5-4fb6-9d31-72a889f1811c" + }, + "uuid": "afacccf6-397d-45d6-b5ae-94c39734b168" + } + }, + "instanceParams": [], + "validationCounter": 0, + "existingNames": { + "mcankinstancename": "" + }, + "existingVNFCounterMap": { + "afacccf6-397d-45d6-b5ae-94c39734b168": 1, + "69e09f68-8b63-4cc9-b9ff-860960b5db09": 3, + "b3c76f73-eeb5-4fb6-9d31-72a889f1811c": 1 + }, + "existingVnfGroupCounterMap": {}, + "existingNetworksCounterMap": {}, + "networks": {}, + "vnfGroups": {}, + "bulkSize": 1, + "instanceId": "f8791436-8d55-4fde-b4d5-72dd2cf13cfb", + "instanceName": "mCaNkinstancename", + "globalSubscriberId": "e433710f-9217-458d-a79d-1c7aff376d89", + "subscriptionServiceType": "TYLER SILVIA", + "owningEntityId": "d61e6f2d-12fa-4cc2-91df-7c244011d6fc", + "productFamilyId": "e433710f-9217-458d-a79d-1c7aff376d89", + "lcpCloudRegionId": "hvf6", + "tenantId": "bae71557c5bb4d5aac6743a4e5f1d054", + "aicZoneId": "NFT1", + "projectName": "WATKINS", + "rollbackOnFailure": true, + "aicZoneName": "NFTJSSSS-NFT1", + "owningEntityName": "WayneHolland", + "tenantName": "AIN Web Tool-15-D-testalexandria", + "modelInfo": { + "modelInvariantId": "e49fbd11-e60c-4a8e-b4bf-30fbe8f4fcc0", + "modelVersionId": "6b528779-44a3-4472-bdff-9cd15ec93450", + "modelName": "action-data", + "modelVersion": "1.0", + "uuid": "6b528779-44a3-4472-bdff-9cd15ec93450" + }, + "isALaCarte": true, + "orchStatus": "Active", + "modelInavariantId": "6b528779-44a3-4472-bdff-9cd15ec93450", + "testApi": "VNF_API" +} \ No newline at end of file diff --git a/vid-app-common/src/test/resources/payload_jsons/volumegroup_instantiation_request.json b/vid-app-common/src/test/resources/payload_jsons/volumegroup_instantiation_request.json index 02d2d1e14..8d64ebefb 100644 --- a/vid-app-common/src/test/resources/payload_jsons/volumegroup_instantiation_request.json +++ b/vid-app-common/src/test/resources/payload_jsons/volumegroup_instantiation_request.json @@ -12,7 +12,7 @@ "cloudConfiguration": { "lcpCloudRegionId": "mdt1", "tenantId": "88a6ca3ee0394ade9403f075db23167e", - "cloudOwner" : "att-aic" + "cloudOwner" : "irma-aic" }, "requestInfo": { "instanceName": "myVgName", @@ -50,7 +50,8 @@ ], "requestParameters" : { "userParams" : [ ], - "usePreload" : true + "usePreload" : true, + "testApi" : "VNF_API" } } } diff --git a/vid-app-common/src/test/resources/payload_jsons/vrfEntry/service_with_vrf_entry_fe_input.json b/vid-app-common/src/test/resources/payload_jsons/vrfEntry/service_with_vrf_entry_fe_input.json new file mode 100644 index 000000000..4f20cf19c --- /dev/null +++ b/vid-app-common/src/test/resources/payload_jsons/vrfEntry/service_with_vrf_entry_fe_input.json @@ -0,0 +1,81 @@ +{ + "action": "Create", + "isDirty": false, + "vnfs": {}, + "vrfs": { + "vrf-1": { + "networks": { + "Network-1": { + "instanceName": "myBestNetwork", + "instanceId": "884b373f-41c0-4a96-9785-7f075cb4ae9d", + "modelInfo": { + "modelType": "network" + } + } + }, + "vpns": { + "vpn-1": { + "instanceName": "justFakeVPN", + "instanceId": "7e971d5c-6ddf-4f02-be8a-95dcbc7daf83", + "modelInfo": { + "modelType": "vpnBinding" + } + } + } + } + }, + "instanceParams": [ + {} + ], + "validationCounter": 0, + "existingNames": { + "dfd": "" + }, + "existingVNFCounterMap": {}, + "existingVRFCounterMap": {}, + "existingVnfGroupCounterMap": {}, + "existingNetworksCounterMap": {}, + "optionalGroupMembersMap": {}, + "networks": {}, + "vnfGroups": {}, + "bulkSize": 1, + "instanceName": "dfd", + "productFamilyId": "ddf9cc0f-6331-4d35-bed0-a37f2d5e9cb3", + "globalSubscriberId": "e433710f-9217-458d-a79d-1c7aff376d89", + "subscriberName": "SILVIA ROBBINS", + "subscriptionServiceType": "TYLER SILVIA", + "owningEntityId": "d61e6f2d-12fa-4cc2-91df-7c244011d6fc", + "lcpCloudRegionId": "lcpCloudRegionId", + "tenantName": "tenantName", + "tenantId": "4b273bc5-0ae6-4088-aa5d-5a862d84cab2", + "projectName": "WATKINS", + "rollbackOnFailure": "true", + "aicZoneName": null, + "owningEntityName": "WayneHolland", + "testApi": "VNF_API", + "modelInfo": { + "modelInvariantId": "dfc2c44c-2429-44ca-ae26-1e6dc1f207fb", + "modelVersionId": "f028b2e2-7080-4b13-91b2-94944d4c42d8", + "modelName": "infraVPN", + "modelVersion": "1.0", + "uuid": "f028b2e2-7080-4b13-91b2-94944d4c42d8", + "modelUniqueId": "f028b2e2-7080-4b13-91b2-94944d4c42d8" + }, + "isALaCarte": true, + "name": "infraVPN", + "version": "1.0", + "description": "ddd", + "category": "Network Service", + "uuid": "f028b2e2-7080-4b13-91b2-94944d4c42d8", + "invariantUuid": "dfc2c44c-2429-44ca-ae26-1e6dc1f207fb", + "serviceType": "BONDING", + "serviceRole": "INFRASTRUCTURE-VPN", + "vidNotions": { + "instantiationType": "Macro", + "instantiationUI": "infrastructureVpn", + "modelCategory": "INFRASTRUCTURE_VPN", + "viewEditUI": "legacy" + }, + "isEcompGeneratedNaming": true, + "isMultiStepDesign": false +} \ No newline at end of file diff --git a/vid-app-common/src/test/resources/payload_jsons/vrfEntry/service_with_vrf_instantiation_request.json b/vid-app-common/src/test/resources/payload_jsons/vrfEntry/service_with_vrf_instantiation_request.json new file mode 100644 index 000000000..2e64554a3 --- /dev/null +++ b/vid-app-common/src/test/resources/payload_jsons/vrfEntry/service_with_vrf_instantiation_request.json @@ -0,0 +1,59 @@ +{ + "requestDetails": { + "modelInfo": { + "modelInvariantId": "dfc2c44c-2429-44ca-ae26-1e6dc1f207fb", + "modelVersionId": "f028b2e2-7080-4b13-91b2-94944d4c42d8", + "modelName": "infraVPN", + "modelVersion": "1.0", + "modelType": "service" + }, + "cloudConfiguration": { + "cloudOwner": "irma-aic", + "lcpCloudRegionId": "lcpCloudRegionId", + "tenantId": "4b273bc5-0ae6-4088-aa5d-5a862d84cab2" + }, + "owningEntity": { + "owningEntityId": "d61e6f2d-12fa-4cc2-91df-7c244011d6fc", + "owningEntityName": "WayneHolland" + }, + "project": { + "projectName": "WATKINS" + }, + "subscriberInfo": { + "globalSubscriberId": "e433710f-9217-458d-a79d-1c7aff376d89", + "subscriberName": "SILVIA ROBBINS" + }, + "requestInfo": { + "instanceName": "dfd", + "productFamilyId": "ddf9cc0f-6331-4d35-bed0-a37f2d5e9cb3", + "source": "VID", + "suppressRollback": false, + "requestorId": "az2016" + }, + "requestParameters": { + "subscriptionServiceType": "TYLER SILVIA", + "aLaCarte": false, + "userParams": [] + }, + "relatedInstanceList": [ + { + "relatedInstance": { + "instanceId": "7e971d5c-6ddf-4f02-be8a-95dcbc7daf83", + "instanceName": "justFakeVPN", + "modelInfo": { + "modelType": "vpnBinding" + } + } + }, + { + "relatedInstance": { + "instanceId": "884b373f-41c0-4a96-9785-7f075cb4ae9d", + "instanceName": "myBestNetwork", + "modelInfo": { + "modelType": "network" + } + } + } + ] + } +} \ No newline at end of file diff --git a/vid-app-common/src/test/resources/policy-configuration-by-policy-false.JSON b/vid-app-common/src/test/resources/policy-configuration-by-policy-false.JSON index 4508599bc..6e073260e 100644 --- a/vid-app-common/src/test/resources/policy-configuration-by-policy-false.JSON +++ b/vid-app-common/src/test/resources/policy-configuration-by-policy-false.JSON @@ -34,8 +34,8 @@ "type": "Configuration", "modelCustomizationName": "Port Mirroring Configuration By Policy 1", "sourceNodes": [ - "vmmeservice2_proxy 2", - "vmmeservice2_proxy 3" + "vflorenceservice2_proxy 2", + "vflorenceservice2_proxy 3" ], "collectorNodes": [ "pprobeservice_proxy 5" @@ -61,9 +61,9 @@ "type": "Configuration", "modelCustomizationName": "Port Mirroring Configuration By Policy 0", "sourceNodes": [ - "vmmeservice2_proxy 2", - "vmmeservice_proxy 1", - "vmmeservice_proxy 0" + "vflorenceservice2_proxy 2", + "vflorenceservice_proxy 1", + "vflorenceservice_proxy 0" ], "collectorNodes": [ ], @@ -71,11 +71,11 @@ } }, "serviceProxies": { - "vmmeservice_proxy 0": { + "vflorenceservice_proxy 0": { "uuid": "a32fee17-5b59-4c34-ba6f-6dd2f1c61fee", "invariantUuid": "2933b574-d28d-45ea-bf22-4df2907e4a10", - "description": "A Proxy for Service vmmeService", - "name": "vmmeService Service Proxy", + "description": "A Proxy for Service vflorenceService", + "name": "vflorenceService Service Proxy", "version": "1.0", "customizationUuid": "d7cfe338-eeda-4217-ba13-f24b0811fb17", "inputs": {}, @@ -84,13 +84,13 @@ "type": "Service Proxy", "sourceModelUuid": "c3e6c9bd-b24d-458e-aa99-e0cadf70c5e5", "sourceModelInvariant": "dd8a805d-3946-4f11-9831-e26cd6aec9a3", - "sourceModelName": "vmmeService" + "sourceModelName": "vflorenceService" }, - "vmmeservice_proxy 1": { + "vflorenceservice_proxy 1": { "uuid": "a32fee17-5b59-4c34-ba6f-6dd2f1c61fee", "invariantUuid": "2933b574-d28d-45ea-bf22-4df2907e4a10", - "description": "A Proxy for Service vmmeService", - "name": "vmmeService Service Proxy", + "description": "A Proxy for Service vflorenceService", + "name": "vflorenceService Service Proxy", "version": "1.0", "customizationUuid": "7a69f133-564c-4eb6-b93e-0a8281967efb", "inputs": {}, @@ -99,13 +99,13 @@ "type": "Service Proxy", "sourceModelUuid": "c3e6c9bd-b24d-458e-aa99-e0cadf70c5e5", "sourceModelInvariant": "dd8a805d-3946-4f11-9831-e26cd6aec9a3", - "sourceModelName": "vmmeService" + "sourceModelName": "vflorenceService" }, - "vmmeservice2_proxy 3": { + "vflorenceservice2_proxy 3": { "uuid": "a32fee17-5b59-4c34-ba6f-6dd2f1c61fee", "invariantUuid": "2933b574-d28d-45ea-bf22-4df2907e4a10", - "description": "A Proxy for Service vmmeService2", - "name": "vmmeService2 Service Proxy", + "description": "A Proxy for Service vflorenceService2", + "name": "vflorenceService2 Service Proxy", "version": "1.0", "customizationUuid": "9d81c21f-e29c-44f6-b5f6-caa974ee078a", "inputs": {}, @@ -114,7 +114,7 @@ "type": "Service Proxy", "sourceModelUuid": "2a2ea15f-07c6-4b89-bfca-e8aba39a34d6", "sourceModelInvariant": "a7eac2b3-8444-40ee-92e3-b3359b32445c", - "sourceModelName": "vmmeService2" + "sourceModelName": "vflorenceService2" }, "pprobeservice_proxy 4": { "uuid": "a32fee17-5b59-4c34-ba6f-6dd2f1c61fee", @@ -146,11 +146,11 @@ "sourceModelInvariant": "83b458fd-5dd3-419b-a9e3-7335814a0911", "sourceModelName": "pProbeService" }, - "vmmeservice2_proxy 2": { + "vflorenceservice2_proxy 2": { "uuid": "a32fee17-5b59-4c34-ba6f-6dd2f1c61fee", "invariantUuid": "2933b574-d28d-45ea-bf22-4df2907e4a10", - "description": "A Proxy for Service vmmeService2", - "name": "vmmeService2 Service Proxy", + "description": "A Proxy for Service vflorenceService2", + "name": "vflorenceService2 Service Proxy", "version": "1.0", "customizationUuid": "060be63d-5f9c-4fd0-8ef7-830d5e8eca17", "inputs": {}, @@ -159,7 +159,7 @@ "type": "Service Proxy", "sourceModelUuid": "2a2ea15f-07c6-4b89-bfca-e8aba39a34d6", "sourceModelInvariant": "a7eac2b3-8444-40ee-92e3-b3359b32445c", - "sourceModelName": "vmmeService2" + "sourceModelName": "vflorenceService2" } }, "vfModules": {}, diff --git a/vid-app-common/src/test/resources/policy-configuration-csar.JSON b/vid-app-common/src/test/resources/policy-configuration-csar.JSON index 41f5f5cbf..d2614cb18 100644 --- a/vid-app-common/src/test/resources/policy-configuration-csar.JSON +++ b/vid-app-common/src/test/resources/policy-configuration-csar.JSON @@ -34,9 +34,9 @@ "type": "Configuration", "modelCustomizationName": "Port Mirroring Configuration By Policy 1", "sourceNodes": [ - "vmmeservice2_proxy 2", - "vmmeservice2_proxy 3", - "vmmeservice_proxy 1" + "vflorenceservice2_proxy 2", + "vflorenceservice2_proxy 3", + "vflorenceservice_proxy 1" ], "collectorNodes": [ "pprobeservice_proxy 5" @@ -62,9 +62,9 @@ "type": "Configuration", "modelCustomizationName": "Port Mirroring Configuration By Policy 0", "sourceNodes": [ - "vmmeservice2_proxy 2", - "vmmeservice_proxy 1", - "vmmeservice_proxy 0" + "vflorenceservice2_proxy 2", + "vflorenceservice_proxy 1", + "vflorenceservice_proxy 0" ], "collectorNodes": [ "pprobeservice_proxy 4" @@ -73,11 +73,11 @@ } }, "serviceProxies": { - "vmmeservice_proxy 0": { + "vflorenceservice_proxy 0": { "uuid": "a32fee17-5b59-4c34-ba6f-6dd2f1c61fee", "invariantUuid": "2933b574-d28d-45ea-bf22-4df2907e4a10", - "description": "A Proxy for Service vmmeService", - "name": "vmmeService Service Proxy", + "description": "A Proxy for Service vflorenceService", + "name": "vflorenceService Service Proxy", "version": "1.0", "customizationUuid": "d7cfe338-eeda-4217-ba13-f24b0811fb17", "inputs": {}, @@ -88,13 +88,13 @@ "type": "Service Proxy", "sourceModelUuid": "c3e6c9bd-b24d-458e-aa99-e0cadf70c5e5", "sourceModelInvariant": "dd8a805d-3946-4f11-9831-e26cd6aec9a3", - "sourceModelName": "vmmeService" + "sourceModelName": "vflorenceService" }, - "vmmeservice_proxy 1": { + "vflorenceservice_proxy 1": { "uuid": "a32fee17-5b59-4c34-ba6f-6dd2f1c61fee", "invariantUuid": "2933b574-d28d-45ea-bf22-4df2907e4a10", - "description": "A Proxy for Service vmmeService", - "name": "vmmeService Service Proxy", + "description": "A Proxy for Service vflorenceService", + "name": "vflorenceService Service Proxy", "version": "1.0", "customizationUuid": "7a69f133-564c-4eb6-b93e-0a8281967efb", "inputs": {}, @@ -105,13 +105,13 @@ "type": "Service Proxy", "sourceModelUuid": "c3e6c9bd-b24d-458e-aa99-e0cadf70c5e5", "sourceModelInvariant": "dd8a805d-3946-4f11-9831-e26cd6aec9a3", - "sourceModelName": "vmmeService" + "sourceModelName": "vflorenceService" }, - "vmmeservice2_proxy 3": { + "vflorenceservice2_proxy 3": { "uuid": "a32fee17-5b59-4c34-ba6f-6dd2f1c61fee", "invariantUuid": "2933b574-d28d-45ea-bf22-4df2907e4a10", - "description": "A Proxy for Service vmmeService2", - "name": "vmmeService2 Service Proxy", + "description": "A Proxy for Service vflorenceService2", + "name": "vflorenceService2 Service Proxy", "version": "1.0", "customizationUuid": "9d81c21f-e29c-44f6-b5f6-caa974ee078a", "inputs": {}, @@ -122,7 +122,7 @@ "type": "Service Proxy", "sourceModelUuid": "2a2ea15f-07c6-4b89-bfca-e8aba39a34d6", "sourceModelInvariant": "a7eac2b3-8444-40ee-92e3-b3359b32445c", - "sourceModelName": "vmmeService2" + "sourceModelName": "vflorenceService2" }, "pprobeservice_proxy 4": { "uuid": "a32fee17-5b59-4c34-ba6f-6dd2f1c61fee", @@ -158,11 +158,11 @@ "sourceModelInvariant": "83b458fd-5dd3-419b-a9e3-7335814a0911", "sourceModelName": "pProbeService" }, - "vmmeservice2_proxy 2": { + "vflorenceservice2_proxy 2": { "uuid": "a32fee17-5b59-4c34-ba6f-6dd2f1c61fee", "invariantUuid": "2933b574-d28d-45ea-bf22-4df2907e4a10", - "description": "A Proxy for Service vmmeService2", - "name": "vmmeService2 Service Proxy", + "description": "A Proxy for Service vflorenceService2", + "name": "vflorenceService2 Service Proxy", "version": "1.0", "customizationUuid": "060be63d-5f9c-4fd0-8ef7-830d5e8eca17", "inputs": {}, @@ -173,11 +173,14 @@ "type": "Service Proxy", "sourceModelUuid": "2a2ea15f-07c6-4b89-bfca-e8aba39a34d6", "sourceModelInvariant": "a7eac2b3-8444-40ee-92e3-b3359b32445c", - "sourceModelName": "vmmeService2" + "sourceModelName": "vflorenceService2" } }, "vfModules": {}, "volumeGroups": {}, "pnfs": {}, - "vnfGroups": {} + "vnfGroups": {}, + "vrfs": { + + } } \ No newline at end of file diff --git a/vid-app-common/src/test/resources/responses/aai/getCloudRegionAndTenantByVnfId.json b/vid-app-common/src/test/resources/responses/aai/getCloudRegionAndTenantByVnfId.json index 690be607b..bc3ab0a18 100644 --- a/vid-app-common/src/test/resources/responses/aai/getCloudRegionAndTenantByVnfId.json +++ b/vid-app-common/src/test/resources/responses/aai/getCloudRegionAndTenantByVnfId.json @@ -34,7 +34,7 @@ { "id": "264798392", "node-type": "vserver", - "url": "/aai/v14/cloud-infrastructure/cloud-regions/cloud-region/att-aic/mtn23b/tenants/tenant/3e9a20a3e89e45f884e09df0cc2d2d2a/vservers/vserver/088c2bf0-80e2-4bdf-93ae-b2469fbeba84", + "url": "/aai/v14/cloud-infrastructure/cloud-regions/cloud-region/irma-aic/mtn23b/tenants/tenant/3e9a20a3e89e45f884e09df0cc2d2d2a/vservers/vserver/088c2bf0-80e2-4bdf-93ae-b2469fbeba84", "properties": { "vserver-id": "088c2bf0-80e2-4bdf-93ae-b2469fbeba84", "vserver-name": "zrdm3mogx01oam001", @@ -49,7 +49,7 @@ "id": "211808464", "relationship-label": "tosca.relationships.AttachesTo", "node-type": "volume", - "url": "/aai/v14/cloud-infrastructure/cloud-regions/cloud-region/att-aic/mtn23b/tenants/tenant/3e9a20a3e89e45f884e09df0cc2d2d2a/vservers/vserver/088c2bf0-80e2-4bdf-93ae-b2469fbeba84/volumes/volume/28e1246e-2aeb-4a59-bb51-f20fb8e93c42" + "url": "/aai/v14/cloud-infrastructure/cloud-regions/cloud-region/irma-aic/mtn23b/tenants/tenant/3e9a20a3e89e45f884e09df0cc2d2d2a/vservers/vserver/088c2bf0-80e2-4bdf-93ae-b2469fbeba84/volumes/volume/28e1246e-2aeb-4a59-bb51-f20fb8e93c42" } ] }, @@ -75,7 +75,7 @@ { "id": "8757432", "node-type": "tenant", - "url": "/aai/v14/cloud-infrastructure/cloud-regions/cloud-region/att-aic/mtn23b/tenants/tenant/3e9a20a3e89e45f884e09df0cc2d2d2a", + "url": "/aai/v14/cloud-infrastructure/cloud-regions/cloud-region/irma-aic/mtn23b/tenants/tenant/3e9a20a3e89e45f884e09df0cc2d2d2a", "properties": { "tenant-id": "3e9a20a3e89e45f884e09df0cc2d2d2a", "tenant-name": "APPC-24595-T-IST-02C", @@ -93,9 +93,9 @@ { "id": "302227536", "node-type": "cloud-region", - "url": "/aai/v14/cloud-infrastructure/cloud-regions/cloud-region/att-aic/mtn23b", + "url": "/aai/v14/cloud-infrastructure/cloud-regions/cloud-region/irma-aic/mtn23b", "properties": { - "cloud-owner": "att-aic", + "cloud-owner": "irma-aic" , "cloud-region-id": "mtn23b", "cloud-type": "openstack", "owner-defined-type": "lcp", @@ -111,7 +111,7 @@ "id": "2744328", "relationship-label": "org.onap.relationships.inventory.BelongsTo", "node-type": "tenant", - "url": "/aai/v14/cloud-infrastructure/cloud-regions/cloud-region/att-aic/mtn23b/tenants/tenant/5452d6bd0cb34e99a3553d349456c642" + "url": "/aai/v14/cloud-infrastructure/cloud-regions/cloud-region/irma-aic/mtn23b/tenants/tenant/5452d6bd0cb34e99a3553d349456c642" } ] } diff --git a/vid-app-common/src/test/resources/responses/mso/multipleOrchestrationRequestsServiceInstance.json b/vid-app-common/src/test/resources/responses/mso/multipleOrchestrationRequestsServiceInstance.json new file mode 100644 index 000000000..9708522a2 --- /dev/null +++ b/vid-app-common/src/test/resources/responses/mso/multipleOrchestrationRequestsServiceInstance.json @@ -0,0 +1,300 @@ +{ + "requestList": [ + { + "request": { + "requestId": "2543cd7c-ed76-4e94-83be-0cf0cc55bf23", + "startTime": "Mon, 04 Mar 2019 20:47:45 GMT", + "finishTime": "Mon, 04 Mar 2019 20:48:46 GMT", + "requestScope": "vnf", + "requestType": "createInstance", + "requestDetails": { + "modelInfo": { + "modelCustomizationName": "OAM_FRWL_5G_NC 0", + "modelInvariantId": "d5f2cc03-fad3-4a5a-bf36-6328771b3915", + "modelType": "vnf", + "modelName": "OAM_FRWL_5G_NC", + "modelVersion": "7.0", + "modelCustomizationUuid": "006ad5a0-b8c4-43f3-aa93-0fa379ea613d", + "modelVersionId": "f248be17-b66d-4ea0-bb24-51de6f62c240", + "modelCustomizationId": "006ad5a0-b8c4-43f3-aa93-0fa379ea613d", + "modelUuid": "f248be17-b66d-4ea0-bb24-51de6f62c240", + "modelInvariantUuid": "d5f2cc03-fad3-4a5a-bf36-6328771b3915", + "modelInstanceName": "OAM_FRWL_5G_NC 0" + }, + "requestInfo": { + "productFamilyId": "a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb", + "source": "VID", + "instanceName": "zauk51bfrwl07", + "suppressRollback": false, + "requestorId": "pj8646" + }, + "relatedInstanceList": [ + { + "relatedInstance": { + "instanceId": "d40c8a82-cc04-45e5-a0f6-0c9394c8f8d2", + "modelInfo": { + "modelInvariantId": "77ac5b6f-e31a-4477-b2c9-8a49ea58aee2", + "modelType": "service", + "modelName": "OAM_FRWL_5G_NC_SVC", + "modelVersion": "6.0", + "modelVersionId": "75a90831-a34f-4b81-8245-4f8b110f93fa", + "modelUuid": "75a90831-a34f-4b81-8245-4f8b110f93fa", + "modelInvariantUuid": "77ac5b6f-e31a-4477-b2c9-8a49ea58aee2" + } + } + } + ], + "cloudConfiguration": { + "tenantId": "e2a6af59d1cb43b2874e943bbbf8470a", + "cloudOwner": "att-nc", + "lcpCloudRegionId": "auk51b" + }, + "requestParameters": { + "testApi": "GR_API" + }, + "platform": { + "platformName": "NETWORK-CLOUD" + }, + "lineOfBusiness": { + "lineOfBusinessName": "EMANUEL-CONSUMER" + } + }, + "instanceReferences": { + "serviceInstanceId": "d40c8a82-cc04-45e5-a0f6-0c9394c8f8d2", + "vnfInstanceId": "05bedd02-b933-40f1-ad20-bab3197489a9", + "vnfInstanceName": "zauk51bfrwl07", + "requestorId": "pj8646" + }, + "requestStatus": { + "requestState": "COMPLETE", + "statusMessage": "STATUS: ALaCarte-Vnf-createInstance request was executed correctly. FLOW STATUS: Successfully completed all Building Blocks", + "percentProgress": 100, + "timestamp": "Mon, 04 Mar 2019 20:48:46 GMT" + } + } + }, + { + "request": { + "requestId": "fab854bf-e53c-415e-b3cc-b6fcce8414b2", + "startTime": "Mon, 04 Mar 2019 20:47:15 GMT", + "finishTime": "Mon, 04 Mar 2019 20:47:38 GMT", + "requestScope": "service", + "requestType": "createInstance", + "requestDetails": { + "modelInfo": { + "modelInvariantId": "77ac5b6f-e31a-4477-b2c9-8a49ea58aee2", + "modelType": "service", + "modelName": "OAM_FRWL_5G_NC_SVC", + "modelVersion": "6.0", + "modelVersionId": "75a90831-a34f-4b81-8245-4f8b110f93fa", + "modelUuid": "75a90831-a34f-4b81-8245-4f8b110f93fa", + "modelInvariantUuid": "77ac5b6f-e31a-4477-b2c9-8a49ea58aee2" + }, + "requestInfo": { + "source": "VID", + "instanceName": "zauk51bfrwl07_vnf_service", + "suppressRollback": false, + "requestorId": "pj8646" + }, + "subscriberInfo": { + "globalSubscriberId": "a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb" + }, + "requestParameters": { + "subscriptionServiceType": "Emanuel", + "aLaCarte": true, + "testApi": "GR_API" + }, + "project": { + "projectName": "Kennedy" + }, + "owningEntity": { + "owningEntityId": "e4257a94-21cc-40c5-adc9-e6f4ff868e31", + "owningEntityName": "EMANUEL-CORE" + } + }, + "instanceReferences": { + "serviceInstanceId": "d40c8a82-cc04-45e5-a0f6-0c9394c8f8d2", + "serviceInstanceName": "zauk51bfrwl07_vnf_service", + "requestorId": "pj8646" + }, + "requestStatus": { + "requestState": "COMPLETE", + "statusMessage": "STATUS: ALaCarte-Service-createInstance request was executed correctly. FLOW STATUS: Successfully completed all Building Blocks", + "percentProgress": 100, + "timestamp": "Mon, 04 Mar 2019 20:47:38 GMT" + } + } + }, + { + "request": { + "requestId": "3eb7b323-b486-402e-931a-2ad296e6406b", + "startTime": "Mon, 04 Mar 2019 20:48:52 GMT", + "finishTime": "Mon, 04 Mar 2019 20:50:40 GMT", + "requestScope": "vfModule", + "requestType": "createInstance", + "requestDetails": { + "modelInfo": { + "modelCustomizationName": "OamFrwl5gNc..base_oam..module-0", + "modelInvariantId": "00b03b3e-454f-438c-87ca-5860f98e8dbc", + "modelType": "vfModule", + "modelName": "OamFrwl5gNc..base_oam..module-0", + "modelVersion": "3", + "modelCustomizationUuid": "53aef95c-92b5-48d7-912a-1f89d0eb6355", + "modelVersionId": "3fb037f3-d629-490f-af49-2bbb97a946be", + "modelCustomizationId": "53aef95c-92b5-48d7-912a-1f89d0eb6355", + "modelUuid": "3fb037f3-d629-490f-af49-2bbb97a946be", + "modelInvariantUuid": "00b03b3e-454f-438c-87ca-5860f98e8dbc", + "modelInstanceName": "OamFrwl5gNc..base_oam..module-0" + }, + "requestInfo": { + "source": "VID", + "instanceName": "zauk51bfrwl07_base_1", + "suppressRollback": false, + "requestorId": "pj8646" + }, + "relatedInstanceList": [ + { + "relatedInstance": { + "instanceId": "d40c8a82-cc04-45e5-a0f6-0c9394c8f8d2", + "modelInfo": { + "modelInvariantId": "77ac5b6f-e31a-4477-b2c9-8a49ea58aee2", + "modelType": "service", + "modelName": "OAM_FRWL_5G_NC_SVC", + "modelVersion": "6.0", + "modelVersionId": "75a90831-a34f-4b81-8245-4f8b110f93fa", + "modelUuid": "75a90831-a34f-4b81-8245-4f8b110f93fa", + "modelInvariantUuid": "77ac5b6f-e31a-4477-b2c9-8a49ea58aee2" + } + } + }, + { + "relatedInstance": { + "instanceId": "05bedd02-b933-40f1-ad20-bab3197489a9", + "modelInfo": { + "modelCustomizationName": "OAM_FRWL_5G_NC 0", + "modelInvariantId": "d5f2cc03-fad3-4a5a-bf36-6328771b3915", + "modelType": "vnf", + "modelName": "OAM_FRWL_5G_NC", + "modelVersion": "7.0", + "modelCustomizationUuid": "006ad5a0-b8c4-43f3-aa93-0fa379ea613d", + "modelVersionId": "f248be17-b66d-4ea0-bb24-51de6f62c240", + "modelCustomizationId": "006ad5a0-b8c4-43f3-aa93-0fa379ea613d", + "modelUuid": "f248be17-b66d-4ea0-bb24-51de6f62c240", + "modelInvariantUuid": "d5f2cc03-fad3-4a5a-bf36-6328771b3915", + "modelInstanceName": "OAM_FRWL_5G_NC 0" + } + } + } + ], + "cloudConfiguration": { + "tenantId": "e2a6af59d1cb43b2874e943bbbf8470a", + "cloudOwner": "att-nc", + "lcpCloudRegionId": "auk51b" + }, + "requestParameters": { + "usePreload": false, + "testApi": "GR_API" + } + }, + "instanceReferences": { + "serviceInstanceId": "d40c8a82-cc04-45e5-a0f6-0c9394c8f8d2", + "vnfInstanceId": "05bedd02-b933-40f1-ad20-bab3197489a9", + "vfModuleInstanceId": "9276805f-07ba-43c0-a5f1-f327c1d72606", + "vfModuleInstanceName": "zauk51bfrwl07_base_1", + "requestorId": "pj8646" + }, + "requestStatus": { + "requestState": "COMPLETE", + "statusMessage": "STATUS: ALaCarte-VfModule-createInstance request was executed correctly. FLOW STATUS: Successfully completed all Building Blocks", + "percentProgress": 100, + "timestamp": "Mon, 04 Mar 2019 20:50:40 GMT" + } + } + }, + { + "request": { + "requestId": "74f5a2dc-1e80-4553-8fac-d30675e510be", + "startTime": "Mon, 04 Mar 2019 20:50:47 GMT", + "requestScope": "vfModule", + "requestType": "createInstance", + "requestDetails": { + "modelInfo": { + "modelCustomizationName": "OamFrwl5gNc..module_oam..module-1", + "modelInvariantId": "972a22a1-8cbf-45ce-8ff2-f0f33694695d", + "modelType": "vfModule", + "modelName": "OamFrwl5gNc..module_oam..module-1", + "modelVersion": "3", + "modelCustomizationUuid": "cf88008e-c4b6-48b8-99a9-44d850f3d8db", + "modelVersionId": "cea74dcd-1174-4f65-adff-87a355849275", + "modelCustomizationId": "cf88008e-c4b6-48b8-99a9-44d850f3d8db", + "modelUuid": "cea74dcd-1174-4f65-adff-87a355849275", + "modelInvariantUuid": "972a22a1-8cbf-45ce-8ff2-f0f33694695d", + "modelInstanceName": "OamFrwl5gNc..module_oam..module-1" + }, + "requestInfo": { + "source": "VID", + "instanceName": "zauk51bfrwl07_mod_1", + "suppressRollback": false, + "requestorId": "pj8646" + }, + "relatedInstanceList": [ + { + "relatedInstance": { + "instanceId": "d40c8a82-cc04-45e5-a0f6-0c9394c8f8d2", + "modelInfo": { + "modelInvariantId": "77ac5b6f-e31a-4477-b2c9-8a49ea58aee2", + "modelType": "service", + "modelName": "OAM_FRWL_5G_NC_SVC", + "modelVersion": "6.0", + "modelVersionId": "75a90831-a34f-4b81-8245-4f8b110f93fa", + "modelUuid": "75a90831-a34f-4b81-8245-4f8b110f93fa", + "modelInvariantUuid": "77ac5b6f-e31a-4477-b2c9-8a49ea58aee2" + } + } + }, + { + "relatedInstance": { + "instanceId": "05bedd02-b933-40f1-ad20-bab3197489a9", + "modelInfo": { + "modelCustomizationName": "OAM_FRWL_5G_NC 0", + "modelInvariantId": "d5f2cc03-fad3-4a5a-bf36-6328771b3915", + "modelType": "vnf", + "modelName": "OAM_FRWL_5G_NC", + "modelVersion": "7.0", + "modelCustomizationUuid": "006ad5a0-b8c4-43f3-aa93-0fa379ea613d", + "modelVersionId": "f248be17-b66d-4ea0-bb24-51de6f62c240", + "modelCustomizationId": "006ad5a0-b8c4-43f3-aa93-0fa379ea613d", + "modelUuid": "f248be17-b66d-4ea0-bb24-51de6f62c240", + "modelInvariantUuid": "d5f2cc03-fad3-4a5a-bf36-6328771b3915", + "modelInstanceName": "OAM_FRWL_5G_NC 0" + } + } + } + ], + "cloudConfiguration": { + "tenantId": "e2a6af59d1cb43b2874e943bbbf8470a", + "cloudOwner": "att-nc", + "lcpCloudRegionId": "auk51b" + }, + "requestParameters": { + "usePreload": true, + "testApi": "GR_API" + } + }, + "instanceReferences": { + "serviceInstanceId": "d40c8a82-cc04-45e5-a0f6-0c9394c8f8d2", + "vnfInstanceId": "05bedd02-b933-40f1-ad20-bab3197489a9", + "vfModuleInstanceId": "73a01fe6-d9f9-4022-82f4-082c6d8cf520", + "vfModuleInstanceName": "zauk51bfrwl07_mod_1", + "requestorId": "pj8646" + }, + "requestStatus": { + "requestState": "FAILED", + "statusMessage": "STATUS: Error from SDNC: No active l3-network found in AAI with network_name GRP-27529-T-IST-07A_N_oam_protected_net_1 FLOW STATUS: All Rollback flows have completed successfully ROLLBACK STATUS: Rollback has been completed successfully.", + "percentProgress": 100, + "timestamp": "Mon, 04 Mar 2019 20:51:14 GMT" + } + } + } + ] +} diff --git a/vid-app-common/src/test/resources/responses/mso/orchestrationRequestsVnf.json b/vid-app-common/src/test/resources/responses/mso/orchestrationRequestsVnf.json index f83310427..e31f0e05e 100644 --- a/vid-app-common/src/test/resources/responses/mso/orchestrationRequestsVnf.json +++ b/vid-app-common/src/test/resources/responses/mso/orchestrationRequestsVnf.json @@ -42,7 +42,7 @@ ], "cloudConfiguration": { "tenantId": "19dfa99ba1cc4948bb868eba9e0de7ab", - "cloudOwner": "att-aic", + "cloudOwner": "irma-aic" , "lcpCloudRegionId": "test1" }, "requestParameters": { diff --git a/vid-app-common/src/main/resources/sdcservices.json b/vid-app-common/src/test/resources/sdcservices.json similarity index 67% rename from vid-app-common/src/main/resources/sdcservices.json rename to vid-app-common/src/test/resources/sdcservices.json index 12142aa9b..1ba13c9ae 100644 --- a/vid-app-common/src/main/resources/sdcservices.json +++ b/vid-app-common/src/test/resources/sdcservices.json @@ -3,10 +3,10 @@ { "uuid": "6bce7302-70bd-4057-b48e-8d5b99e686ca", "invariantUUID": "9aa04749-c02c-432d-a90c-18caa361c833", - "name": "vDBE_srv", + "name": "vDOROTHEA_srv", "version": "1.0", - "toscaModelURL": "./service-VdbeSrv-csar.zip", - "category": "Mobility", + "toscaModelURL": "./csars/service-VdorotheaSrv-csar.zip", + "category": "Emanuel", "lifecycleState": "CERTIFIED", "lastUpdaterUserId": "rg276b", "lastUpdaterFullName": null, @@ -17,10 +17,10 @@ { "uuid": "76f27dfe-33e5-472f-8e0b-acf524adc4f0", "invariantUUID": "c3618e16-bb5b-433a-a6e0-565ca79d8b65", - "name": "4-27_vMME_Service", + "name": "4-27_vFLORENCE_Service", "version": "1.0", - "toscaModelURL": "./service-MsoExampleService-csar.zip", - "category": "Mobility", + "toscaModelURL": "./csars/service-MsoExampleService-csar.zip", + "category": "Emanuel", "lifecycleState": "CERTIFIED", "lastUpdaterUserId": "rg276b", "lastUpdaterFullName": null, @@ -31,10 +31,10 @@ { "uuid": "f4d84bb4-a416-4b4e-997e-0059973630b9", "invariantUUID": "598e3f9e-3244-4d8f-a8e0-0e5d7a29eda9", - "name": "ADIOD vMX vPE_BV Service 488", + "name": "PASQUALE vMX vPE_BV Service 488", "version": "1.0", - "toscaModelURL": "./service-vf-with-annotations.zip", - "category": "Mobility", + "toscaModelURL": "./csars/service-vf-with-annotations.zip", + "category": "Emanuel", "lifecycleState": "CERTIFIED", "lastUpdaterUserId": "rg276b", "lastUpdaterFullName": null, @@ -45,10 +45,10 @@ { "uuid": "48a52540-8772-4368-9cdb-1f124ea5c931", "invariantUUID": "f430728a-4530-42be-a577-1206b9484cef", - "name": "4-27_vMME_Service", + "name": "4-27_vFLORENCE_Service", "version": "1.0", - "toscaModelURL": "./service-vf-csar.zip", - "category": "Mobility", + "toscaModelURL": "./csars/service-vf-csar.zip", + "category": "Emanuel", "lifecycleState": "CERTIFIED", "lastUpdaterUserId": "rg276b", "lastUpdaterFullName": null, @@ -59,10 +59,10 @@ { "uuid": "cb49608f-5a24-4789-b0f7-2595473cb997", "invariantUUID": "0311f998-9268-4fd6-bbba-afff15087b72", - "name": "4-27_vMME_Service", + "name": "4-27_vFLORENCE_Service", "version": "1.0", - "toscaModelURL": "./service-vl-csar.zip", - "category": "Mobility", + "toscaModelURL": "./csars/service-vl-csar.zip", + "category": "Emanuel", "lifecycleState": "CERTIFIED", "lastUpdaterUserId": "rg276b", "lastUpdaterFullName": null, @@ -75,7 +75,7 @@ "invariantUUID": "5461e83e-0b2a-465d-ab45-9d731894afd9", "name": "vLoadBalancerMS", "version": "1.0", - "toscaModelURL": "./vLoadBalancerMS-with-policy.TOSCA.zip", + "toscaModelURL": "./csars/vLoadBalancerMS-with-policy.TOSCA.zip", "category": "Network L4+", "lifecycleState": "CERTIFIED", "lastUpdaterUserId": "demo", @@ -87,10 +87,10 @@ { "uuid": "90fe6842-aa76-4b68-8329-5c86ff564407", "invariantUUID": "0311f998-9268-4fd6-bbba-afff15087b72", - "name": "4-27_vMME_Service", + "name": "4-27_vFLORENCE_Service", "version": "1.0", - "toscaModelURL": "./1712_ADIOD.zip", - "category": "Mobility", + "toscaModelURL": "./csars/1712_PASQUALE.zip", + "category": "Emanuel", "lifecycleState": "CERTIFIED", "lastUpdaterUserId": "rg276b", "lastUpdaterFullName": null, @@ -101,10 +101,10 @@ { "uuid": "73e1322a-8a9a-49dc-9558-b0c5c5770e4a", "invariantUUID": "f430728a-4530-42be-a577-1206b9484cef", - "name": "4-27_vMME_Service", + "name": "4-27_vFLORENCE_Service", "version": "1.0", - "toscaModelURL": "./pnf.zip", - "category": "Mobility", + "toscaModelURL": "./csars/pnf.zip", + "category": "Emanuel", "lifecycleState": "CERTIFIED", "lastUpdaterUserId": "rg276b", "lastUpdaterFullName": null, @@ -117,8 +117,8 @@ "invariantUUID": "709d1be4-9a3f-4a29-8c4d-a20465e808a3", "name": "Demo Service", "version": "1.0", - "toscaModelURL": "./service-DemoService1-csar.csar", - "category": "Mobility", + "toscaModelURL": "./csars/service-DemoService1-csar.csar", + "category": "Emanuel", "lifecycleState": "CERTIFIED", "lastUpdaterUserId": "rg276b", "lastUpdaterFullName": null, @@ -129,10 +129,10 @@ { "uuid": "32671332-a7ee-4df6-9609-db50ce5eaee7", "invariantUUID": "598e3f9e-3244-4d8f-a8e0-0e5d7a29eda9", - "name": "ADIOD vMX vPE_BV Service 488", + "name": "PASQUALE vMX vPE_BV Service 488", "version": "1.0", - "toscaModelURL": "./adiod.zip", - "category": "Mobility", + "toscaModelURL": "./csars/pasquale.zip", + "category": "Emanuel", "lifecycleState": "CERTIFIED", "lastUpdaterUserId": "rg276b", "lastUpdaterFullName": null, @@ -145,8 +145,8 @@ "invariantUUID": "3d89efc0-19ca-4df7-9818-028e1fc6f708", "name": "AMP PH SVC", "version": "1.0", - "toscaModelURL": "./service-AmpPhSvc-csar.zip", - "category": "Mobility", + "toscaModelURL": "./csars/service-AmpPhSvc-csar.zip", + "category": "Emanuel", "lifecycleState": "CERTIFIED", "lastUpdaterUserId": "rg276b", "lastUpdaterFullName": null, @@ -159,8 +159,8 @@ "invariantUUID": "e49fbd11-e60c-4a8e-b4bf-30fbe8f4fcc0", "name": "action-data", "version": "1.0", - "toscaModelURL": "./2f80c596.zip", - "category": "Mobility", + "toscaModelURL": "./csars/2f80c596.zip", + "category": "Emanuel", "lifecycleState": "CERTIFIED", "lastUpdaterUserId": "rg276b", "lastUpdaterFullName": null, @@ -173,8 +173,8 @@ "invariantUUID": "b7d923c9-6175-41f1-91ba-4565c4953408", "name": "Multiple pProbes", "version": "1.0", - "toscaModelURL": "./service-Servicecontainermultiplepprobes-csar.zip", - "category": "Mobility", + "toscaModelURL": "./csars/service-Servicecontainermultiplepprobes-csar.zip", + "category": "Emanuel", "lifecycleState": "CERTIFIED", "lastUpdaterUserId": "rg276b", "lastUpdaterFullName": null, @@ -187,7 +187,7 @@ "invariantUUID": "b7d923c9-6175-41f1-91ba-4565c4955555", "name": "ServiceContainerMultiplepProbes2", "version": "2.0", - "toscaModelURL": "./service-ServicecontainerContainsPprobe.zip", + "toscaModelURL": "./csars/service-ServicecontainerContainsPprobe.zip", "category": "Network L1-3", "lifecycleState": "CERTIFIED", "lastUpdaterUserId": "rg276b", @@ -201,8 +201,8 @@ "invariantUUID": "598e3f9e-3244-4d8f-a8e0-0e5d7a29eda9", "name": "Fabric Configuration", "version": "1.0", - "toscaModelURL": "./service-fabric-configuration.zip", - "category": "Mobility", + "toscaModelURL": "./csars/service-fabric-configuration.zip", + "category": "Emanuel", "lifecycleState": "CERTIFIED", "lastUpdaterUserId": "rg276b", "lastUpdaterFullName": null, @@ -215,7 +215,7 @@ "invariantUUID": "93518289-3049-450f-a22d-86108c250265", "name": "jenny vTSBC vlan SVC", "version": "1.0", - "toscaModelURL": "./service-JennyVtsbcVlanSvc-csar.zip", + "toscaModelURL": "./csars/service-JennyVtsbcVlanSvc-csar.zip", "category": "Network L1-3", "lifecycleState": "CERTIFIED", "lastUpdaterUserId": "rg276b", @@ -224,12 +224,40 @@ "artifacts": null, "resources": null }, + { + "uuid": "2a53419b-3f85-4ad5-a9c9-d79905500a27", + "invariantUUID": "16972715-9d79-4fb0-9463-0253d45e1d48", + "name": "MNS VNN1B exn svc", + "version": "1.0", + "toscaModelURL": "./csars/service-MnsVnn1bExnSvc-csar.csar", + "category": "Emanuel", + "lifecycleState": "CERTIFIED", + "lastUpdaterUserId": "rg276b", + "lastUpdaterFullName": null, + "distributionStatus": "DISTRIBUTED", + "artifacts": null, + "resources": null + }, + { + "uuid": "e32a5014-357f-4be4-b3f9-fecb0010811e", + "invariantUUID": "4e099102-fccb-4ee3-b51b-ebb51259dc50", + "name": "MNS VNN1B dmz svc", + "version": "1.0", + "toscaModelURL": "./csars/service-MnsVnn1bDmzSvc-csar.csar", + "category": "Emanuel", + "lifecycleState": "CERTIFIED", + "lastUpdaterUserId": "rg276b", + "lastUpdaterFullName": null, + "distributionStatus": "DISTRIBUTED", + "artifacts": null, + "resources": null + }, { "uuid": "4117a0b6-e234-467d-b5b9-fe2f68c8b0fc", "invariantUUID": "7ee41ce4-4827-44b0-a48e-2707a59905d2", "name": "Grouping Service for Test", "version": "1.0", - "toscaModelURL": "./service-vnf-grouping-csar.zip", + "toscaModelURL": "./csars/service-vnf-grouping-csar.zip", "category": "Network L4+", "lifecycleState": "CERTIFIED", "lastUpdaterUserId": "rg276b", @@ -237,6 +265,20 @@ "distributionStatus": "DISTRIBUTED", "artifacts": null, "resources": null + }, + { + "uuid": "f028b2e2-7080-4b13-91b2-94944d4c42d8", + "invariantUUID": "dfc2c44c-2429-44ca-ae26-1e6dc1f207fb", + "name": "infraVPN", + "version": "1.0", + "toscaModelURL": "./csars/service-Infravpn-csar.zip", + "category": "Network Service", + "lifecycleState": "CERTIFIED", + "lastUpdaterUserId": "rg276b", + "lastUpdaterFullName": null, + "distributionStatus": "DISTRIBUTED", + "artifacts": null, + "resources": null } ] } \ No newline at end of file diff --git a/vid-app-common/src/test/resources/vLoadBalancerMS-with-policy.TOSCA.json b/vid-app-common/src/test/resources/vLoadBalancerMS-with-policy.TOSCA.json index 8e29ff1d9..d066c2aba 100644 --- a/vid-app-common/src/test/resources/vLoadBalancerMS-with-policy.TOSCA.json +++ b/vid-app-common/src/test/resources/vLoadBalancerMS-with-policy.TOSCA.json @@ -167,7 +167,7 @@ } }, "networks": {}, - "collectionResource": {}, + "collectionResources": {}, "configurations": {}, "fabricConfigurations": {}, "serviceProxies": {}, diff --git a/vid-app-common/src/test/resources/vf-csar.JSON b/vid-app-common/src/test/resources/vf-csar.JSON index c1b71b34f..591f06803 100644 --- a/vid-app-common/src/test/resources/vf-csar.JSON +++ b/vid-app-common/src/test/resources/vf-csar.JSON @@ -3,7 +3,7 @@ }, "service": { - "category": "Mobility", + "category": "Emanuel", "description": "Bla bla", "serviceRole": null, "serviceType": null, @@ -96,10 +96,10 @@ "properties": { "availability_zone_max_count": "get_input:greatdefect0_availability_zone_max_count", "itc_flavor_name": "nv.c8r24d160", - "itc_image_name": "NIMBUS_IXLA-ITC_8.20_EA_KVM_210117.qcow2", + "itc_image_name": "KENNEDY_IXLA-ITC_8.20_EA_KVM_210117.qcow2", "itc_name_0": "get_input:greatdefect0_itc_name_0", "itm_flavor_name": "nv.c2r4d50", - "itm_image_name": "NIMBUS_IXLA-ITM_8.20.EA_KVM.qcow2", + "itm_image_name": "KENNEDY_IXLA-ITM_8.20.EA_KVM.qcow2", "vf_module_id": "get_input:greatdefect0_vf_module_id", "ecomp_generated_naming": "false" }, @@ -178,5 +178,8 @@ "pnfs": { }, - "vnfGroups": {} + "vnfGroups": {}, + "vrfs": { + + } } \ No newline at end of file diff --git a/vid-app-common/src/test/resources/vf-with-annotation-csar.json b/vid-app-common/src/test/resources/vf-with-annotation-csar.json index db68313f1..17cb65251 100644 --- a/vid-app-common/src/test/resources/vf-with-annotation-csar.json +++ b/vid-app-common/src/test/resources/vf-with-annotation-csar.json @@ -2,17 +2,17 @@ "service": { "uuid": "f4d84bb4-a416-4b4e-997e-0059973630b9", "invariantUuid": "598e3f9e-3244-4d8f-a8e0-0e5d7a29eda9", - "name": "ADIOD vMX vPE_BV Service 488", + "name": "PASQUALE vMX vPE_BV Service 488", "version": "1.0", "toscaModelURL": null, "category": "Network L1-3", "serviceType": "", "serviceRole": "", - "description": "ADIOD vMX vPE based on Juniper 17.2 release. Updated with updated VF for v8.0 of VLM", + "description": "PASQUALE vMX vPE based on Juniper 17.2 release. Updated with updated VF for v8.0 of VLM", "serviceEcompNaming": "true", "instantiationType": "Macro", "inputs": { - "2017488_adiodvpe0_ASN": { + "2017488_pasqualevpe0_ASN": { "type": "string", "description": "AV/PE", "entry_schema": null, @@ -26,11 +26,11 @@ } }, "vnfs": { - "2017-488_ADIOD-vPE 0": { + "2017-488_PASQUALE-vPE 0": { "uuid": "ea81d6f7-0861-44a7-b7d5-d173b562c350", "invariantUuid": "5be7e99e-8eb2-4d97-be63-8081ff3cd10e", - "description": "Name ADIOD vPE Description The provider edge function for the ADIOD service supported by the Junipers VMX product Category Router Vendor Juniper Vendor Release Code 17.2 Owners Mary Fragale. Updated 9-25 to use v8.0 of the Juniper Valid 2 VLM", - "name": "2017-488_ADIOD-vPE", + "description": "Name PASQUALE vPE Description The provider edge function for the PASQUALE service supported by the Junipers VMX product Category Router Vendor Juniper Vendor Release Code 17.2 Owners Mary Fragale. Updated 9-25 to use v8.0 of the Juniper Valid 2 VLM", + "name": "2017-488_PASQUALE-vPE", "version": "9.0", "customizationUuid": "41516cc6-5098-4b40-a619-f8d5f55fc4d8", "inputs": { @@ -41,21 +41,21 @@ }, "properties": { "vmxvre_retype": "RE-VMX", - "vnf_config_template_version": "get_input:2017488_adiodvpe0_vnf_config_template_version", + "vnf_config_template_version": "get_input:2017488_pasqualevpe0_vnf_config_template_version", "sriov44_net_id": "48d399b3-11ee-48a8-94d2-f0ea94d6be8d", "int_ctl_net_id": "2f323477-6936-4d01-ac53-d849430281d9", "vmxvpfe_sriov41_0_port_mac": "00:11:22:EF:AC:DF", "int_ctl_net_name": "VMX-INTXI", - "vmx_int_ctl_prefix": "128.0.0.0", + "vmx_int_ctl_prefix": "10.0.0.10", "sriov43_net_id": "da349ca1-6de9-4548-be88-2d88e99bfef5", "sriov42_net_id": "760669ba-013d-4d9b-b0e7-4151fe2e6279", "sriov41_net_id": "25ad52d5-c165-40f8-b3b0-ddfc2373280a", "nf_type": "ROUTER", - "vmxvpfe_int_ctl_ip_1": "128.0.0.16", + "vmxvpfe_int_ctl_ip_1": "10.0.0.10", "is_AVPN_service": "false", "vmx_RSG_name": "vREXI-affinity", "vmx_int_ctl_forwarding": "l2", - "vmxvre_oam_ip_0": "10.40.123.5", + "vmxvre_oam_ip_0": "10.0.0.10", "vmxvpfe_sriov44_0_port_mac": "00:11:22:EF:AC:DF", "vmxvpfe_sriov41_0_port_vlanstrip": "false", "vmxvpfe_sriov42_0_port_vlanfilter": "4001", @@ -83,10 +83,10 @@ "vmxvpfe_sriov42_0_port_unknownmulticastallow": "true", "vmxvpfe_sriov44_0_port_vlanstrip": "false", "vf_module_id": "123", - "nf_function": "ADIOD vPE", + "nf_function": "PASQUALE vPE", "vmxvpfe_sriov43_0_port_unknownmulticastallow": "true", - "vmxvre_int_ctl_ip_0": "128.0.0.1", - "AIC_CLLI": "get_input:2017488_adiodvpe0_AIC_CLLI", + "vmxvre_int_ctl_ip_0": "10.0.0.10", + "AIC_CLLI": "get_input:2017488_pasqualevpe0_AIC_CLLI", "vnf_name": "mtnj309me6vre", "vmxvpfe_sriov41_0_port_unknownunicastallow": "true", "vmxvre_volume_type_1": "HITACHI", @@ -94,24 +94,24 @@ "vmxvre_volume_type_0": "HITACHI", "vmxvpfe_volume_type_0": "HITACHI", "vmxvpfe_sriov43_0_port_broadcastallow": "true", - "bandwidth_units": "get_input:2017488_adiodvpe0_bandwidth_units", + "bandwidth_units": "get_input:2017488_pasqualevpe0_bandwidth_units", "vnf_id": "123", "vmxvre_oam_prefix": "24", - "availability_zone_0": "get_input:2017488_adiodvpe0_availability_zone_0", - "ASN": "get_input:2017488_adiodvpe0_ASN", + "availability_zone_0": "get_input:2017488_pasqualevpe0_availability_zone_0", + "ASN": "get_input:2017488_pasqualevpe0_ASN", "vmxvre_chassis_i2cid": "161", "vmxvpfe_name_0": "vPFEXI", - "bandwidth": "get_input:2017488_adiodvpe0_bandwidth", + "bandwidth": "get_input:2017488_pasqualevpe0_bandwidth", "availability_zone_max_count": "1", "vmxvre_volume_size_0": "45.0", "vmxvre_volume_size_1": "50.0", "vmxvpfe_sriov42_0_port_broadcastallow": "true", - "vmxvre_oam_gateway": "10.40.123.1", + "vmxvre_oam_gateway": "10.0.0.10", "vmxvre_volume_name_1": "vREXI_FAVolume", "vmxvre_ore_present": "0", "vmxvre_volume_name_0": "vREXI_FBVolume", "vmxvre_type": "0", - "vnf_instance_name": "get_input:2017488_adiodvpe0_vnf_instance_name", + "vnf_instance_name": "get_input:2017488_pasqualevpe0_vnf_instance_name", "vmxvpfe_sriov41_0_port_unknownmulticastallow": "true", "oam_net_id": "b95eeb1d-d55d-4827-abb4-8ebb94941429", "vmx_int_ctl_len": "24", @@ -126,32 +126,32 @@ "ecomp_generated_naming": "true" }, "type": "VF", - "modelCustomizationName": "2017-488_ADIOD-vPE 0", + "modelCustomizationName": "2017-488_PASQUALE-vPE 0", "vfModules": { - "2017488_adiodvpe0..2017488AdiodVpe..ADIOD_vRE_BV..module-1": { + "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vRE_BV..module-1": { "uuid": "a5d8df05-11cb-4351-96e0-b6d4168ea4df", "invariantUuid": "7253ff5c-97f0-4b8b-937c-77aeb4d79aa1", "customizationUuid": "f3d97417-0c8d-424e-8ff7-b2eb4fbcecc3", "description": null, - "name": "2017488AdiodVpe..ADIOD_vRE_BV..module-1", + "name": "2017488PasqualeVpe..PASQUALE_vRE_BV..module-1", "version": "8", - "modelCustomizationName": "2017488AdiodVpe..ADIOD_vRE_BV..module-1", + "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_vRE_BV..module-1", "properties": { "minCountInstances": 0, "maxCountInstances": null, "initialCount": 0, - "vfModuleLabel": "ADIOD_vRE_BV", + "vfModuleLabel": "PASQUALE_vRE_BV", "baseModule" : false }, "inputs": { "bandwidth_units": { - "fromInputName": "2017488_adiodvpe0_bandwidth_units", + "fromInputName": "2017488_pasqualevpe0_bandwidth_units", "type": "string", "description": "Units of bandwidth", "entry_schema": null, "inputProperties": { "sourceType": "HEAT", - "vfModuleLabel": "ADIOD_vRE_BV", + "vfModuleLabel": "PASQUALE_vRE_BV", "paramName": "bandwidth_units" }, "constraints": null, @@ -159,13 +159,13 @@ "default": "Gbps" }, "bandwidth": { - "fromInputName": "2017488_adiodvpe0_bandwidth", + "fromInputName": "2017488_pasqualevpe0_bandwidth", "type": "string", "description": "Requested VPE bandwidth", "entry_schema": null, "inputProperties": { "sourceType": "HEAT", - "vfModuleLabel": "ADIOD_vRE_BV", + "vfModuleLabel": "PASQUALE_vRE_BV", "paramName": "bandwidth" }, "constraints": null, @@ -173,13 +173,13 @@ "default": "10" }, "vnf_instance_name": { - "fromInputName": "2017488_adiodvpe0_vnf_instance_name", + "fromInputName": "2017488_pasqualevpe0_vnf_instance_name", "type": "string", "description": "The hostname assigned to the vpe.", "entry_schema": null, "inputProperties": { "sourceType": "HEAT", - "vfModuleLabel": "ADIOD_vRE_BV", + "vfModuleLabel": "PASQUALE_vRE_BV", "paramName": "vnf_instance_name" }, "constraints": null, @@ -187,13 +187,13 @@ "default": "mtnj309me6" }, "vnf_config_template_version": { - "fromInputName": "2017488_adiodvpe0_vnf_config_template_version", + "fromInputName": "2017488_pasqualevpe0_vnf_config_template_version", "type": "string", "description": "VPE Software Version", "entry_schema": null, "inputProperties": { "sourceType": "HEAT", - "vfModuleLabel": "ADIOD_vRE_BV", + "vfModuleLabel": "PASQUALE_vRE_BV", "paramName": "vnf_config_template_version" }, "constraints": null, @@ -201,13 +201,13 @@ "default": "17.2" }, "AIC_CLLI": { - "fromInputName": "2017488_adiodvpe0_AIC_CLLI", + "fromInputName": "2017488_pasqualevpe0_AIC_CLLI", "type": "string", "description": "AIC Site CLLI", "entry_schema": null, "inputProperties": { "sourceType": "HEAT", - "vfModuleLabel": "ADIOD_vRE_BV", + "vfModuleLabel": "PASQUALE_vRE_BV", "paramName": "AIC_CLLI" }, "constraints": null, @@ -217,19 +217,19 @@ }, "volumeGroupAllowed": true }, - "2017488_adiodvpe0..2017488AdiodVpe..ADIOD_base_vPE_BV..module-0": { + "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0": { "uuid": "040e591e-5d30-4e0d-850f-7266e5a8e013", "invariantUuid": "b34833bb-6aa9-4ad6-a831-70b06367a091", "customizationUuid": "5c5f91f9-5e31-4120-b892-5536587ec258", "description": null, - "name": "2017488AdiodVpe..ADIOD_base_vPE_BV..module-0", + "name": "2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0", "version": "6", - "modelCustomizationName": "2017488AdiodVpe..ADIOD_base_vPE_BV..module-0", + "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0", "properties": { "minCountInstances": 1, "maxCountInstances": 1, "initialCount": 1, - "vfModuleLabel": "ADIOD_base_vPE_BV", + "vfModuleLabel": "PASQUALE_base_vPE_BV", "baseModule" : true }, "inputs": { @@ -237,30 +237,30 @@ }, "volumeGroupAllowed": false }, - "2017488_adiodvpe0..2017488AdiodVpe..ADIOD_vPFE_BV..module-2": { + "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2": { "uuid": "b3e8b26e-cff0-49fc-a4e6-f3e16c8440fe", "invariantUuid": "eff8cc59-53a1-4101-aed7-8cf24ecf8339", "customizationUuid": "6e410843-257c-46d9-ba8a-8d94e1362452", "description": null, - "name": "2017488AdiodVpe..ADIOD_vPFE_BV..module-2", + "name": "2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2", "version": "8", - "modelCustomizationName": "2017488AdiodVpe..ADIOD_vPFE_BV..module-2", + "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2", "properties": { "minCountInstances": 0, "maxCountInstances": null, "initialCount": 0, - "vfModuleLabel": "ADIOD_vPFE_BV", + "vfModuleLabel": "PASQUALE_vPFE_BV", "baseModule" : false }, "inputs": { "availability_zone_0": { - "fromInputName": "2017488_adiodvpe0_availability_zone_0", + "fromInputName": "2017488_pasqualevpe0_availability_zone_0", "type": "string", "description": "The Availability Zone to launch the instance.", "entry_schema": null, "inputProperties": { "sourceType": "HEAT", - "vfModuleLabel": "ADIOD_vPFE_BV", + "vfModuleLabel": "PASQUALE_vPFE_BV", "paramName": "availability_zone_0" }, "constraints": null, @@ -272,29 +272,29 @@ } }, "volumeGroups": { - "2017488_adiodvpe0..2017488AdiodVpe..ADIOD_vRE_BV..module-1": { + "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vRE_BV..module-1": { "uuid": "a5d8df05-11cb-4351-96e0-b6d4168ea4df", "invariantUuid": "7253ff5c-97f0-4b8b-937c-77aeb4d79aa1", "customizationUuid": "f3d97417-0c8d-424e-8ff7-b2eb4fbcecc3", "description": null, - "name": "2017488AdiodVpe..ADIOD_vRE_BV..module-1", + "name": "2017488PasqualeVpe..PASQUALE_vRE_BV..module-1", "version": "8", - "modelCustomizationName": "2017488AdiodVpe..ADIOD_vRE_BV..module-1", + "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_vRE_BV..module-1", "properties": { "minCountInstances": 0, "maxCountInstances": null, "initialCount": 0, - "vfModuleLabel": "ADIOD_vRE_BV" + "vfModuleLabel": "PASQUALE_vRE_BV" }, "inputs": { "bandwidth_units": { - "fromInputName": "2017488_adiodvpe0_bandwidth_units", + "fromInputName": "2017488_pasqualevpe0_bandwidth_units", "type": "string", "description": "Units of bandwidth", "entry_schema": null, "inputProperties": { "sourceType": "HEAT", - "vfModuleLabel": "ADIOD_vRE_BV", + "vfModuleLabel": "PASQUALE_vRE_BV", "paramName": "bandwidth_units" }, "constraints": null, @@ -302,13 +302,13 @@ "default": "Gbps" }, "bandwidth": { - "fromInputName": "2017488_adiodvpe0_bandwidth", + "fromInputName": "2017488_pasqualevpe0_bandwidth", "type": "string", "description": "Requested VPE bandwidth", "entry_schema": null, "inputProperties": { "sourceType": "HEAT", - "vfModuleLabel": "ADIOD_vRE_BV", + "vfModuleLabel": "PASQUALE_vRE_BV", "paramName": "bandwidth" }, "constraints": null, @@ -316,13 +316,13 @@ "default": "10" }, "vnf_instance_name": { - "fromInputName": "2017488_adiodvpe0_vnf_instance_name", + "fromInputName": "2017488_pasqualevpe0_vnf_instance_name", "type": "string", "description": "The hostname assigned to the vpe.", "entry_schema": null, "inputProperties": { "sourceType": "HEAT", - "vfModuleLabel": "ADIOD_vRE_BV", + "vfModuleLabel": "PASQUALE_vRE_BV", "paramName": "vnf_instance_name" }, "constraints": null, @@ -330,13 +330,13 @@ "default": "mtnj309me6" }, "vnf_config_template_version": { - "fromInputName": "2017488_adiodvpe0_vnf_config_template_version", + "fromInputName": "2017488_pasqualevpe0_vnf_config_template_version", "type": "string", "description": "VPE Software Version", "entry_schema": null, "inputProperties": { "sourceType": "HEAT", - "vfModuleLabel": "ADIOD_vRE_BV", + "vfModuleLabel": "PASQUALE_vRE_BV", "paramName": "vnf_config_template_version" }, "constraints": null, @@ -344,13 +344,13 @@ "default": "17.2" }, "AIC_CLLI": { - "fromInputName": "2017488_adiodvpe0_AIC_CLLI", + "fromInputName": "2017488_pasqualevpe0_AIC_CLLI", "type": "string", "description": "AIC Site CLLI", "entry_schema": null, "inputProperties": { "sourceType": "HEAT", - "vfModuleLabel": "ADIOD_vRE_BV", + "vfModuleLabel": "PASQUALE_vRE_BV", "paramName": "AIC_CLLI" }, "constraints": null, @@ -359,29 +359,29 @@ } } }, - "2017488_adiodvpe0..2017488AdiodVpe..ADIOD_vPFE_BV..module-2": { + "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2": { "uuid": "b3e8b26e-cff0-49fc-a4e6-f3e16c8440fe", "invariantUuid": "eff8cc59-53a1-4101-aed7-8cf24ecf8339", "customizationUuid": "6e410843-257c-46d9-ba8a-8d94e1362452", "description": null, - "name": "2017488AdiodVpe..ADIOD_vPFE_BV..module-2", + "name": "2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2", "version": "8", - "modelCustomizationName": "2017488AdiodVpe..ADIOD_vPFE_BV..module-2", + "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2", "properties": { "minCountInstances": 0, "maxCountInstances": null, "initialCount": 0, - "vfModuleLabel": "ADIOD_vPFE_BV" + "vfModuleLabel": "PASQUALE_vPFE_BV" }, "inputs": { "availability_zone_0": { - "fromInputName": "2017488_adiodvpe0_availability_zone_0", + "fromInputName": "2017488_pasqualevpe0_availability_zone_0", "type": "string", "description": "The Availability Zone to launch the instance.", "entry_schema": null, "inputProperties": { "sourceType": "HEAT", - "vfModuleLabel": "ADIOD_vPFE_BV", + "vfModuleLabel": "PASQUALE_vPFE_BV", "paramName": "availability_zone_0" }, "constraints": null, @@ -396,7 +396,7 @@ "networks": { }, - "collectionResource": { + "collectionResources": { }, "configurations": { @@ -406,30 +406,30 @@ }, "vfModules": { - "2017488_adiodvpe0..2017488AdiodVpe..ADIOD_vRE_BV..module-1": { + "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vRE_BV..module-1": { "uuid": "a5d8df05-11cb-4351-96e0-b6d4168ea4df", "invariantUuid": "7253ff5c-97f0-4b8b-937c-77aeb4d79aa1", "customizationUuid": "f3d97417-0c8d-424e-8ff7-b2eb4fbcecc3", "description": null, - "name": "2017488AdiodVpe..ADIOD_vRE_BV..module-1", + "name": "2017488PasqualeVpe..PASQUALE_vRE_BV..module-1", "version": "8", - "modelCustomizationName": "2017488AdiodVpe..ADIOD_vRE_BV..module-1", + "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_vRE_BV..module-1", "properties": { "minCountInstances": 0, "maxCountInstances": null, "initialCount": 0, - "vfModuleLabel": "ADIOD_vRE_BV", + "vfModuleLabel": "PASQUALE_vRE_BV", "baseModule" : false }, "inputs": { "bandwidth_units": { - "fromInputName": "2017488_adiodvpe0_bandwidth_units", + "fromInputName": "2017488_pasqualevpe0_bandwidth_units", "type": "string", "description": "Units of bandwidth", "entry_schema": null, "inputProperties": { "sourceType": "HEAT", - "vfModuleLabel": "ADIOD_vRE_BV", + "vfModuleLabel": "PASQUALE_vRE_BV", "paramName": "bandwidth_units" }, "constraints": null, @@ -437,13 +437,13 @@ "default": "Gbps" }, "bandwidth": { - "fromInputName": "2017488_adiodvpe0_bandwidth", + "fromInputName": "2017488_pasqualevpe0_bandwidth", "type": "string", "description": "Requested VPE bandwidth", "entry_schema": null, "inputProperties": { "sourceType": "HEAT", - "vfModuleLabel": "ADIOD_vRE_BV", + "vfModuleLabel": "PASQUALE_vRE_BV", "paramName": "bandwidth" }, "constraints": null, @@ -451,13 +451,13 @@ "default": "10" }, "vnf_instance_name": { - "fromInputName": "2017488_adiodvpe0_vnf_instance_name", + "fromInputName": "2017488_pasqualevpe0_vnf_instance_name", "type": "string", "description": "The hostname assigned to the vpe.", "entry_schema": null, "inputProperties": { "sourceType": "HEAT", - "vfModuleLabel": "ADIOD_vRE_BV", + "vfModuleLabel": "PASQUALE_vRE_BV", "paramName": "vnf_instance_name" }, "constraints": null, @@ -465,13 +465,13 @@ "default": "mtnj309me6" }, "vnf_config_template_version": { - "fromInputName": "2017488_adiodvpe0_vnf_config_template_version", + "fromInputName": "2017488_pasqualevpe0_vnf_config_template_version", "type": "string", "description": "VPE Software Version", "entry_schema": null, "inputProperties": { "sourceType": "HEAT", - "vfModuleLabel": "ADIOD_vRE_BV", + "vfModuleLabel": "PASQUALE_vRE_BV", "paramName": "vnf_config_template_version" }, "constraints": null, @@ -479,13 +479,13 @@ "default": "17.2" }, "AIC_CLLI": { - "fromInputName": "2017488_adiodvpe0_AIC_CLLI", + "fromInputName": "2017488_pasqualevpe0_AIC_CLLI", "type": "string", "description": "AIC Site CLLI", "entry_schema": null, "inputProperties": { "sourceType": "HEAT", - "vfModuleLabel": "ADIOD_vRE_BV", + "vfModuleLabel": "PASQUALE_vRE_BV", "paramName": "AIC_CLLI" }, "constraints": null, @@ -495,19 +495,19 @@ }, "volumeGroupAllowed": true }, - "2017488_adiodvpe0..2017488AdiodVpe..ADIOD_base_vPE_BV..module-0": { + "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0": { "uuid": "040e591e-5d30-4e0d-850f-7266e5a8e013", "invariantUuid": "b34833bb-6aa9-4ad6-a831-70b06367a091", "customizationUuid": "5c5f91f9-5e31-4120-b892-5536587ec258", "description": null, - "name": "2017488AdiodVpe..ADIOD_base_vPE_BV..module-0", + "name": "2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0", "version": "6", - "modelCustomizationName": "2017488AdiodVpe..ADIOD_base_vPE_BV..module-0", + "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0", "properties": { "minCountInstances": 1, "maxCountInstances": 1, "initialCount": 1, - "vfModuleLabel": "ADIOD_base_vPE_BV", + "vfModuleLabel": "PASQUALE_base_vPE_BV", "baseModule" : true }, "inputs": { @@ -515,30 +515,30 @@ }, "volumeGroupAllowed": false }, - "2017488_adiodvpe0..2017488AdiodVpe..ADIOD_vPFE_BV..module-2": { + "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2": { "uuid": "b3e8b26e-cff0-49fc-a4e6-f3e16c8440fe", "invariantUuid": "eff8cc59-53a1-4101-aed7-8cf24ecf8339", "customizationUuid": "6e410843-257c-46d9-ba8a-8d94e1362452", "description": null, - "name": "2017488AdiodVpe..ADIOD_vPFE_BV..module-2", + "name": "2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2", "version": "8", - "modelCustomizationName": "2017488AdiodVpe..ADIOD_vPFE_BV..module-2", + "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2", "properties": { "minCountInstances": 0, "maxCountInstances": null, "initialCount": 0, - "vfModuleLabel": "ADIOD_vPFE_BV", + "vfModuleLabel": "PASQUALE_vPFE_BV", "baseModule" : false }, "inputs": { "availability_zone_0": { - "fromInputName": "2017488_adiodvpe0_availability_zone_0", + "fromInputName": "2017488_pasqualevpe0_availability_zone_0", "type": "string", "description": "The Availability Zone to launch the instance.", "entry_schema": null, "inputProperties": { "sourceType": "HEAT", - "vfModuleLabel": "ADIOD_vPFE_BV", + "vfModuleLabel": "PASQUALE_vPFE_BV", "paramName": "availability_zone_0" }, "constraints": null, @@ -550,30 +550,30 @@ } }, "volumeGroups": { - "2017488_adiodvpe0..2017488AdiodVpe..ADIOD_vRE_BV..module-1": { + "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vRE_BV..module-1": { "uuid": "a5d8df05-11cb-4351-96e0-b6d4168ea4df", "invariantUuid": "7253ff5c-97f0-4b8b-937c-77aeb4d79aa1", "customizationUuid": "f3d97417-0c8d-424e-8ff7-b2eb4fbcecc3", "description": null, - "name": "2017488AdiodVpe..ADIOD_vRE_BV..module-1", + "name": "2017488PasqualeVpe..PASQUALE_vRE_BV..module-1", "version": "8", - "modelCustomizationName": "2017488AdiodVpe..ADIOD_vRE_BV..module-1", + "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_vRE_BV..module-1", "properties": { "minCountInstances": 0, "maxCountInstances": null, "initialCount": 0, - "vfModuleLabel": "ADIOD_vRE_BV", + "vfModuleLabel": "PASQUALE_vRE_BV", "baseModule" : false }, "inputs": { "bandwidth_units": { - "fromInputName": "2017488_adiodvpe0_bandwidth_units", + "fromInputName": "2017488_pasqualevpe0_bandwidth_units", "type": "string", "description": "Units of bandwidth", "entry_schema": null, "inputProperties": { "sourceType": "HEAT", - "vfModuleLabel": "ADIOD_vRE_BV", + "vfModuleLabel": "PASQUALE_vRE_BV", "paramName": "bandwidth_units" }, "constraints": null, @@ -581,13 +581,13 @@ "default": "Gbps" }, "bandwidth": { - "fromInputName": "2017488_adiodvpe0_bandwidth", + "fromInputName": "2017488_pasqualevpe0_bandwidth", "type": "string", "description": "Requested VPE bandwidth", "entry_schema": null, "inputProperties": { "sourceType": "HEAT", - "vfModuleLabel": "ADIOD_vRE_BV", + "vfModuleLabel": "PASQUALE_vRE_BV", "paramName": "bandwidth" }, "constraints": null, @@ -595,13 +595,13 @@ "default": "10" }, "vnf_instance_name": { - "fromInputName": "2017488_adiodvpe0_vnf_instance_name", + "fromInputName": "2017488_pasqualevpe0_vnf_instance_name", "type": "string", "description": "The hostname assigned to the vpe.", "entry_schema": null, "inputProperties": { "sourceType": "HEAT", - "vfModuleLabel": "ADIOD_vRE_BV", + "vfModuleLabel": "PASQUALE_vRE_BV", "paramName": "vnf_instance_name" }, "constraints": null, @@ -609,13 +609,13 @@ "default": "mtnj309me6" }, "vnf_config_template_version": { - "fromInputName": "2017488_adiodvpe0_vnf_config_template_version", + "fromInputName": "2017488_pasqualevpe0_vnf_config_template_version", "type": "string", "description": "VPE Software Version", "entry_schema": null, "inputProperties": { "sourceType": "HEAT", - "vfModuleLabel": "ADIOD_vRE_BV", + "vfModuleLabel": "PASQUALE_vRE_BV", "paramName": "vnf_config_template_version" }, "constraints": null, @@ -623,13 +623,13 @@ "default": "17.2" }, "AIC_CLLI": { - "fromInputName": "2017488_adiodvpe0_AIC_CLLI", + "fromInputName": "2017488_pasqualevpe0_AIC_CLLI", "type": "string", "description": "AIC Site CLLI", "entry_schema": null, "inputProperties": { "sourceType": "HEAT", - "vfModuleLabel": "ADIOD_vRE_BV", + "vfModuleLabel": "PASQUALE_vRE_BV", "paramName": "AIC_CLLI" }, "constraints": null, @@ -638,30 +638,30 @@ } } }, - "2017488_adiodvpe0..2017488AdiodVpe..ADIOD_vPFE_BV..module-2": { + "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2": { "uuid": "b3e8b26e-cff0-49fc-a4e6-f3e16c8440fe", "invariantUuid": "eff8cc59-53a1-4101-aed7-8cf24ecf8339", "customizationUuid": "6e410843-257c-46d9-ba8a-8d94e1362452", "description": null, - "name": "2017488AdiodVpe..ADIOD_vPFE_BV..module-2", + "name": "2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2", "version": "8", - "modelCustomizationName": "2017488AdiodVpe..ADIOD_vPFE_BV..module-2", + "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2", "properties": { "minCountInstances": 0, "maxCountInstances": null, "initialCount": 0, - "vfModuleLabel": "ADIOD_vPFE_BV", + "vfModuleLabel": "PASQUALE_vPFE_BV", "baseModule" : false }, "inputs": { "availability_zone_0": { - "fromInputName": "2017488_adiodvpe0_availability_zone_0", + "fromInputName": "2017488_pasqualevpe0_availability_zone_0", "type": "string", "description": "The Availability Zone to launch the instance.", "entry_schema": null, "inputProperties": { "sourceType": "HEAT", - "vfModuleLabel": "ADIOD_vPFE_BV", + "vfModuleLabel": "PASQUALE_vPFE_BV", "paramName": "availability_zone_0" }, "constraints": null, @@ -674,5 +674,8 @@ "pnfs": { }, - "vnfGroups": {} + "vnfGroups": {}, + "vrfs": { + + } } \ No newline at end of file diff --git a/vid-app-common/src/test/resources/vf-with-vfcInstanceGroups.json b/vid-app-common/src/test/resources/vf-with-vfcInstanceGroups.json index 3b7e2e854..34e2d45b8 100644 --- a/vid-app-common/src/test/resources/vf-with-vfcInstanceGroups.json +++ b/vid-app-common/src/test/resources/vf-with-vfcInstanceGroups.json @@ -2,13 +2,13 @@ "service": { "uuid": "6bce7302-70bd-4057-b48e-8d5b99e686ca", "invariantUuid": "9aa04749-c02c-432d-a90c-18caa361c833", - "name": "vDBE_srv", + "name": "vDOROTHEA_srv", "version": "1.0", "toscaModelURL": null, "category": "Network L4+", "serviceType": "", "serviceRole": "", - "description": "vDBE_srv", + "description": "vDOROTHEA_srv", "serviceEcompNaming": "true", "instantiationType": "A-La-Carte", "inputs": { @@ -16,11 +16,11 @@ } }, "vnfs": { - "vDBE 0": { + "vDOROTHEA 0": { "uuid": "61535073-2e50-4141-9000-f66fea69b433", "invariantUuid": "fcdf49ce-6f0b-4ca2-b676-a484e650e734", - "description": "vDBE", - "name": "vDBE", + "description": "vDOROTHEA", + "name": "vDOROTHEA", "version": "0.2", "customizationUuid": "882e5dcb-ba9f-4766-8cde-e326638107db", "inputs": { @@ -40,16 +40,16 @@ "untr_network_collection_function": "untraaa" }, "type": "VF", - "modelCustomizationName": "vDBE 0", + "modelCustomizationName": "vDOROTHEA 0", "vfModules": { - "vdbe0..Vdbe..main..module-0": { + "vdorothea0..Vdorothea..main..module-0": { "uuid": "25a4d009-2f5a-44b4-b02a-62c584c15912", "invariantUuid": "614afb1a-3e7e-44e9-90ab-424d0070c781", "customizationUuid": "3443b341-7b0b-498c-a84a-a7ee736cba7e", "description": null, - "name": "Vdbe..main..module-0", + "name": "Vdorothea..main..module-0", "version": "1", - "modelCustomizationName": "Vdbe..main..module-0", + "modelCustomizationName": "Vdorothea..main..module-0", "properties": { "minCountInstances": 1, "maxCountInstances": 1, @@ -97,7 +97,7 @@ "networks": { }, - "collectionResource": { + "collectionResources": { }, "configurations": { @@ -107,14 +107,14 @@ }, "vfModules": { - "vdbe0..Vdbe..main..module-0": { + "vdorothea0..Vdorothea..main..module-0": { "uuid": "25a4d009-2f5a-44b4-b02a-62c584c15912", "invariantUuid": "614afb1a-3e7e-44e9-90ab-424d0070c781", "customizationUuid": "3443b341-7b0b-498c-a84a-a7ee736cba7e", "description": null, - "name": "Vdbe..main..module-0", + "name": "Vdorothea..main..module-0", "version": "1", - "modelCustomizationName": "Vdbe..main..module-0", + "modelCustomizationName": "Vdorothea..main..module-0", "properties": { "minCountInstances": 1, "maxCountInstances": 1, @@ -134,5 +134,8 @@ "pnfs": { }, - "vnfGroups": {} + "vnfGroups": {}, + "vrfs": { + + } } \ No newline at end of file diff --git a/vid-app-common/src/test/resources/vl-csar.JSON b/vid-app-common/src/test/resources/vl-csar.JSON index 3de6ee460..cdf2125d4 100644 --- a/vid-app-common/src/test/resources/vl-csar.JSON +++ b/vid-app-common/src/test/resources/vl-csar.JSON @@ -75,7 +75,7 @@ "modelCustomizationName": "ExtVL 0" } }, - "collectionResource": { + "collectionResources": { }, "configurations": { @@ -93,5 +93,8 @@ "pnfs": { }, - "vnfGroups": {} + "vnfGroups": {}, + "vrfs": { + + } } \ No newline at end of file diff --git a/vid-app-common/src/test/resources/vnf-grouping-csar.json b/vid-app-common/src/test/resources/vnf-grouping-csar.json index 4c6f1d9c5..ebf2204bd 100644 --- a/vid-app-common/src/test/resources/vnf-grouping-csar.json +++ b/vid-app-common/src/test/resources/vnf-grouping-csar.json @@ -18,18 +18,18 @@ }, "networks": { }, - "collectionResource": { + "collectionResources": { }, "configurations": { }, "fabricConfigurations": { }, "serviceProxies": { - "vdbe_svc_vprs_proxy 0": { + "vdorothea_svc_vprs_proxy 0": { "uuid": "65fadfa8-a0d9-443f-95ad-836cd044e26c", "invariantUuid": "f4baae0c-b3a5-4ca1-a777-afbffe7010bc", - "description": "A Proxy for Service vDBE_Svc_vPRS", - "name": "vDBE_Svc_vPRS Service Proxy", + "description": "A Proxy for Service vDOROTHEA_Svc_vPRS", + "name": "vDOROTHEA_Svc_vPRS Service Proxy", "version": "1.0", "customizationUuid": "bdb63d23-e132-4ce7-af2c-a493b4cafac9", "inputs": { @@ -42,7 +42,7 @@ "type": "Service Proxy", "sourceModelUuid": "da7827a2-366d-4be6-8c68-a69153c61274", "sourceModelInvariant": "24632e6b-584b-4f45-80d4-fefd75fd9f14", - "sourceModelName": "vDBE_Svc_vPRS" + "sourceModelName": "vDOROTHEA_Svc_vPRS" }, "tsbc0001vm001_svc_proxy 0": { "uuid": "65fadfa8-a0d9-443f-95ad-836cd044e26c", @@ -87,11 +87,11 @@ "ecomp_generated_naming": "true" }, "members": { - "vdbe_svc_vprs_proxy 0": { + "vdorothea_svc_vprs_proxy 0": { "uuid": "65fadfa8-a0d9-443f-95ad-836cd044e26c", "invariantUuid": "f4baae0c-b3a5-4ca1-a777-afbffe7010bc", - "description": "A Proxy for Service vDBE_Svc_vPRS", - "name": "vDBE_Svc_vPRS Service Proxy", + "description": "A Proxy for Service vDOROTHEA_Svc_vPRS", + "name": "vDOROTHEA_Svc_vPRS Service Proxy", "version": "1.0", "customizationUuid": "bdb63d23-e132-4ce7-af2c-a493b4cafac9", "inputs": {}, @@ -102,7 +102,7 @@ "type": "Service Proxy", "sourceModelUuid": "da7827a2-366d-4be6-8c68-a69153c61274", "sourceModelInvariant": "24632e6b-584b-4f45-80d4-fefd75fd9f14", - "sourceModelName": "vDBE_Svc_vPRS" + "sourceModelName": "vDOROTHEA_Svc_vPRS" } } }, @@ -119,7 +119,8 @@ "function": "SIGNALING", "description": "DDD1", "type": "LOAD-GROUP", - "ecomp_generated_naming": "true" + "ecomp_generated_naming": "true", + "quantity": 3 }, "members": { "tsbc0001vm001_svc_proxy 0": { @@ -141,5 +142,8 @@ } } } + }, + "vrfs": { + } } \ No newline at end of file -- 2.16.6