From 75aacbbe1acf78fa53378f07f0a8c7769449a17e Mon Sep 17 00:00:00 2001 From: Michael Lando Date: Mon, 17 Jul 2017 21:12:03 +0300 Subject: [PATCH] [SDC] rebase 1710 code Change-Id: I532ed68979fee7840ea8a5395e7e965b155fb9f9 Signed-off-by: Michael Lando --- .gitignore | 1 + .../ci/tests/api/ComponentInstanceBaseTest.java | 50 +- .../java/org/openecomp/sdc/ci/tests/api/Urls.java | 46 +- .../sdc/ci/tests/datatypes/ResourceReqDetails.java | 2 + .../sdc/ci/tests/datatypes/ServiceReqDetails.java | 7 + .../execute/artifacts/DownloadComponentArt.java | 6 +- .../tests/execute/category/CatalogDataApiTest.java | 99 +- .../ci/tests/execute/devCI/CRUDExternalAPI.java | 22 +- .../sdc/ci/tests/execute/devCI/HealthCheckAPI.java | 68 + .../general/BasicHttpAuthenticationTest.java | 4 +- .../ci/tests/execute/imports/CsarUtilsTest.java | 83 +- .../ci/tests/execute/imports/ExportToscaTest.java | 2 +- .../tests/execute/resource/GetLeftPaletteTest.java | 193 + .../service/ServiceComponentInstanceCRUDTest.java | 75 +- .../sdc/ci/tests/utils/DistributionUtils.java | 6 +- .../sdc/ci/tests/utils/general/ElementFactory.java | 8 +- .../sdc/ci/tests/utils/rest/AssetRestUtils.java | 10 +- .../sdc/ci/tests/utils/rest/CatalogRestUtils.java | 12 +- .../sdc/ci/tests/utils/rest/CommonRestUtils.java | 23 + .../sdc/ci/tests/utils/rest/ResourceRestUtils.java | 14 + asdctool/pom.xml | 20 + .../impl/migration/v1604/ServiceMigration.java | 5 +- .../v1707/Migration1707ArtifactUuidFix.java | 4 +- .../impl/migration/v1707/Migration1707Config.java | 5 + .../v1707/Migration1707MissingInfoFix.java | 220 ++ .../v1707/jsonmodel/ComponentMigration.java | 4 +- .../jsonmodel/NodeTemplateMissingDataResolver.java | 129 +- .../openecomp/sdc/asdctool/main/MigrationMenu.java | 63 +- .../migration/config/MigrationSpringConfig.java | 59 + .../sdc/asdctool/migration/core/DBVersion.java | 95 + .../migration/core/MigrationException.java | 13 + .../asdctool/migration/core/SdcMigrationTool.java | 62 + .../core/execution/MigrationExecutionResult.java | 70 + .../core/execution/MigrationExecutor.java | 15 + .../core/execution/MigrationExecutorImpl.java | 47 + .../asdctool/migration/core/task/Migration.java | 14 + .../migration/core/task/MigrationResult.java | 31 + .../sdc/asdctool/migration/main/MigrationMenu.java | 100 + .../migration/resolver/MigrationResolver.java | 16 + .../resolver/SpringBeansMigrationResolver.java | 45 + .../asdctool/migration/service/SdcRepoService.java | 34 + .../migration/tasks/mig1710/ExampleMigration.java | 27 + .../src/main/resources/config/configuration.yaml | 1 + asdctool/src/main/resources/config/logback.xml | 15 +- .../main/resources/scripts/postMigration1707Fix.sh | 35 + .../src/main/resources/scripts/sdc-migration.sh | 36 + .../asdctool/migration/DummyMigrationFactory.java | 72 + .../sdc/asdctool/migration/core/DBVersionTest.java | 57 + .../migration/core/SdcMigrationToolTest.java | 101 + .../core/execution/MigrationExecutorImplTest.java | 47 + .../resolver/SpringBeansMigrationResolverTest.java | 84 + .../asdctool/migration/scanner/ClassScanner.java | 81 + .../migration/service/SdcRepoServiceTest.java | 55 + .../migration/task/MigrationTasksTest.java | 56 + .../be/components/impl/ArtifactsBusinessLogic.java | 125 +- .../sdc/be/components/impl/BaseBusinessLogic.java | 12 +- .../be/components/impl/CassandraHealthCheck.java | 189 + .../be/components/impl/ComponentBusinessLogic.java | 50 +- .../impl/ComponentInstanceBusinessLogic.java | 58 +- .../be/components/impl/ElementBusinessLogic.java | 56 +- .../sdc/be/components/impl/GroupBusinessLogic.java | 31 +- .../components/impl/HealthCheckBusinessLogic.java | 361 +- .../sdc/be/components/impl/ImportUtils.java | 2 + .../be/components/impl/InputsBusinessLogic.java | 98 +- .../ProductComponentInstanceBusinessLogic.java | 4 - .../be/components/impl/ResourceBusinessLogic.java | 1733 +++++---- .../be/components/impl/ResourceImportManager.java | 16 +- .../be/components/impl/ServiceBusinessLogic.java | 140 +- .../ServiceComponentInstanceBusinessLogic.java | 4 - .../impl/VFComponentInstanceBusinessLogic.java | 12 +- .../lifecycle/CertificationRequestTransition.java | 9 +- .../lifecycle/LifecycleBusinessLogic.java | 55 +- .../be/externalapi/servlet/AssetsDataServlet.java | 14 +- .../externalapi/servlet/CrudExternalServlet.java | 4 +- .../sdc/be/servlets/ComponentServlet.java | 2 +- .../openecomp/sdc/be/servlets/ElementServlet.java | 44 +- .../openecomp/sdc/be/servlets/GroupServlet.java | 2 +- .../java/org/openecomp/sdc/be/tosca/CsarUtils.java | 60 +- .../openecomp/sdc/be/tosca/PropertyConvertor.java | 71 +- .../openecomp/sdc/be/tosca/ToscaExportHandler.java | 10 +- .../sdc/be/tosca/model/ToscaMetadata.java | 27 + .../common/transaction/mngr/RollbackManager.java | 13 +- catalog-be/src/main/resources/config/SDC.zip | Bin 30057 -> 29275 bytes .../src/main/resources/config/configuration.yaml | 23 +- .../main/resources/config/error-configuration.yaml | 518 +-- .../import/tosca/data-types/dataTypes.yml | 53 + .../import/tosca/data-types/dataTypes.zip | Bin 5277 -> 5408 bytes .../src/main/resources/import/tosca/heat-types.zip | Bin 72549 -> 0 bytes .../tosca/heat-types/Generic_PNF/Generic_PNF.json | 21 + .../tosca/heat-types/Generic_PNF/Generic_PNF.yml | 11 + .../tosca/heat-types/Generic_PNF/Generic_PNF.zip | Bin 0 -> 320 bytes .../import/tosca/heat-types/extCp/extCp.yml | 20 +- .../import/tosca/heat-types/extCp/extCp.zip | Bin 790 -> 780 bytes .../heat-types/multiFlavorVFC/multiFlavorVFC.json | 21 + .../heat-types/multiFlavorVFC/multiFlavorVFC.yml | 10 + .../heat-types/multiFlavorVFC/multiFlavorVFC.zip | Bin 0 -> 714 bytes .../vnfConfiguration/vnfConfiguration.json | 21 + .../vnfConfiguration/vnfConfiguration.yml | 10 + .../vnfConfiguration/vnfConfiguration.zip | Bin 0 -> 759 bytes .../scripts/import/tosca/importHeatTypes.py | 7 +- .../scripts/import/tosca/upgradeHeatTypes1707.py | 5 +- catalog-be/src/main/webapp/WEB-INF/web.xml | 1 - .../components/HealthCheckBusinessLogicTest.java | 18 +- .../be/components/ResourceImportManagerTest.java | 8 +- .../components/impl/ResourceBusinessLogicTest.java | 69 +- .../be/components/lifecycle/LifecycleTestBase.java | 5 +- .../resources/config/catalog-be/configuration.yaml | 228 +- .../config/catalog-be/error-configuration.yaml | 535 +-- .../org/openecomp/sdc/be/dao/api/ActionStatus.java | 9 +- .../be/dao/cassandra/MigrationTasksAccessor.java | 17 + .../sdc/be/dao/cassandra/MigrationTasksDao.java | 73 + .../sdc/be/dao/cassandra/schema/Table.java | 23 +- .../tables/MigrationTasksTableDescription.java | 81 + .../openecomp/sdc/be/dao/jsongraph/TitanDao.java | 15 +- .../sdc/be/dao/jsongraph/types/EdgeLabelEnum.java | 4 + .../sdc/be/resources/data/MigrationTaskEntry.java | 92 + .../data/auditing/AuditingTypesConstants.java | 41 +- .../sdc/fe/servlets/HealthCheckService.java | 3 +- catalog-model/pom.xml | 14 +- .../java/org/openecomp/sdc/be/model/Component.java | 10 + .../sdc/be/model/ComponentInstanceInput.java | 2 +- .../sdc/be/model/ComponentInstanceProperty.java | 3 +- .../openecomp/sdc/be/model/GroupDefinition.java | 8 + .../sdc/be/model/IPropertyInputCommon.java | 14 + .../org/openecomp/sdc/be/model/ImportCsarInfo.java | 73 + .../org/openecomp/sdc/be/model/NodeTypeInfo.java | 55 + .../be/model/RequirementAndRelationshipPair.java | 2 +- .../java/org/openecomp/sdc/be/model/Resource.java | 12 +- .../java/org/openecomp/sdc/be/model/Service.java | 18 +- .../sdc/be/model/UploadComponentInstanceInfo.java | 18 + .../jsontitan/operations/ArtifactsOperations.java | 71 +- .../model/jsontitan/operations/BaseOperation.java | 29 +- .../jsontitan/operations/GroupsOperation.java | 2 +- .../operations/NodeTemplateOperation.java | 186 +- .../operations/TopologyTemplateOperation.java | 7 +- .../operations/ToscaElementLifecycleOperation.java | 83 +- .../operations/ToscaElementOperation.java | 96 +- .../jsontitan/operations/ToscaOperationFacade.java | 4097 ++++++++++---------- .../be/model/jsontitan/utils/ModelConverter.java | 46 +- .../be/model/operations/api/IServiceOperation.java | 7 +- .../model/operations/impl/AbstractOperation.java | 9 +- .../impl/ComponentInstanceOperation.java | 7 + .../model/operations/impl/ComponentOperation.java | 1 + .../model/operations/impl/GroupTypeOperation.java | 1 - .../model/operations/impl/PolicyTypeOperation.java | 1 - .../tosca/converters/ToscaMapValueConverter.java | 3 + .../tosca/validators/HeatStringValidator.java | 4 +- .../be/model/tosca/validators/KeyValidator.java | 4 +- .../be/model/tosca/validators/StringValidator.java | 4 +- .../sdc/be/ui/model/UiResourceMetadata.java | 10 + .../sdc/be/ui/model/UiServiceMetadata.java | 20 + .../operations/ArtifactsOperationsTest.java | 85 + .../operations/ToscaElementOperationTest.java | 344 ++ .../operations/ToscaElementOperationTestImpl.java | 74 + .../be/model/jsontitan/utils/GraphTestUtils.java | 114 + catalog-ui/configurations/MenuReadMe.txt | 2 - catalog-ui/configurations/dev.js | 14 +- catalog-ui/configurations/menu.js | 196 +- catalog-ui/configurations/mock.json | 14 - catalog-ui/configurations/prod.js | 13 +- catalog-ui/pom.xml | 9 +- catalog-ui/src/app/app.ts | 25 +- .../style/component-instances-nodes-style.ts | 7 +- .../graphs-v2/palette/palette.directive.ts | 66 +- .../type-map/type-map-directive.html | 2 +- .../property-types/type-map/type-map-directive.ts | 5 + .../structure-tree/structure-tree-directive.html | 2 +- .../app/directives/utils/sdc-tags/sdc-tags.less | 4 +- catalog-ui/src/app/models.ts | 4 +- catalog-ui/src/app/models/app-config.ts | 12 - catalog-ui/src/app/models/categories.ts | 1 - catalog-ui/src/app/models/component-metadata.ts | 6 + catalog-ui/src/app/models/components/component.ts | 7 +- .../src/app/models/components/displayComponent.ts | 3 - catalog-ui/src/app/models/components/product.ts | 125 - catalog-ui/src/app/models/components/resource.ts | 5 +- catalog-ui/src/app/models/components/service.ts | 6 + .../componentsInstances/componentInstance.ts | 4 +- .../models/componentsInstances/productInstance.ts | 33 - catalog-ui/src/app/models/modal.ts | 16 + .../app/models/properties-inputs/input-fe-model.ts | 2 +- .../models/properties-inputs/property-fe-model.ts | 10 +- catalog-ui/src/app/models/user.ts | 10 +- catalog-ui/src/app/modules/service-module.ts | 2 - catalog-ui/src/app/modules/view-model-module.ts | 6 +- catalog-ui/src/app/ng2/app.component.ts | 4 +- .../confirmation-delete-input.component.html | 3 - .../confirmation-delete-input.component.ts | 58 - .../inputs-table/inputs-table.component.html | 1 - .../inputs-table/inputs-table.component.ts | 10 +- .../app/ng2/components/modal/modal.component.html | 16 +- .../app/ng2/components/modal/modal.component.ts | 14 +- .../src/app/ng2/components/modal/modal.module.ts | 19 + .../dynamic-property.component.html | 6 +- .../dynamic-property.component.less | 9 +- .../dynamic-property/dynamic-property.component.ts | 43 +- .../properties-assignment.module.ts | 10 +- .../properties-assignment.page.component.less | 3 +- .../properties-assignment.page.component.ts | 8 +- .../properties-assignment/properties.utils.ts | 5 +- .../component-services/component.service.ts | 2 - .../app/ng2/services/http.interceptor.service.ts | 24 +- catalog-ui/src/app/ng2/services/modal.service.ts | 73 + catalog-ui/src/app/services.ts | 1 - .../src/app/services/available-icons-service.ts | 17 - .../src/app/services/components/product-service.ts | 55 - .../utils/composition-left-palette-service.ts | 45 +- catalog-ui/src/app/services/data-types-service.ts | 3 +- catalog-ui/src/app/services/entity-service.ts | 17 +- catalog-ui/src/app/utils/component-factory.ts | 20 +- .../src/app/utils/component-instance-factory.ts | 10 +- catalog-ui/src/app/utils/constants.ts | 8 +- catalog-ui/src/app/utils/modals-handler.ts | 18 + .../app/view-models/catalog/catalog-view-model.ts | 8 +- .../src/app/view-models/catalog/catalog.less | 22 - .../view-models/dashboard/dashboard-view-model.ts | 7 + .../app/view-models/dashboard/dashboard-view.html | 14 +- .../src/app/view-models/dashboard/dashboard.less | 7 - .../src/app/view-models/dcae-app/dcae-app.less | 22 - .../property-form-view-model.ts | 13 + .../property-form-view.html | 2 +- .../modals/icons-modal/icons-modal-view.html | 18 + .../modals/icons-modal/icons-modal-view.less | 33 + .../icons-modal/icons-modal-view.ts} | 88 +- .../view-models/onboard-vendor/onboard-vendor.less | 22 - .../workspace/tabs/activity-log/activity-log.less | 5 +- .../workspace/tabs/attributes/attributes.less | 2 +- .../tabs/composition/composition-view-model.ts | 9 +- .../tabs/composition/composition-view.html | 3 +- .../composition/tabs/artifacts/artifacts-view.html | 2 +- .../composition/tabs/details/details-view-model.ts | 2 +- .../composition/tabs/details/details-view.html | 21 + .../tabs/composition/tabs/details/details.less | 3 + .../deployment-artifacts/deployment-artifacts.less | 2 +- .../workspace/tabs/general/general-view-model.ts | 49 +- .../workspace/tabs/general/general-view.html | 552 +-- .../workspace/tabs/general/general.less | 80 +- .../workspace/tabs/icons/icons-view.html | 26 - .../view-models/workspace/tabs/icons/icons.less | 65 - .../information-artifacts.less | 2 +- .../view-models/workspace/tabs/inputs/inputs.less | 2 +- .../product-hierarchy-view-model.ts | 129 - .../product-hierarchy/product-hierarchy-view.html | 40 - .../tabs/product-hierarchy/product-hierarchy.less | 130 - .../workspace/tabs/properties/properties.less | 2 +- .../tabs/tosca-artifacts/tosca-artifacts.less | 5 +- .../view-models/workspace/workspace-view-model.ts | 46 +- .../app/view-models/workspace/workspace-view.html | 17 +- .../src/app/view-models/workspace/workspace.less | 60 +- catalog-ui/src/assets/languages/en_US.json | 5 - catalog-ui/src/assets/styles/app.less | 4 +- .../images/resource-icons/vnfconfiguration.png | Bin 0 -> 2835 bytes .../assets/styles/images/sprites/sprite-global.png | Bin 90334 -> 93182 bytes .../styles/images/sprites/sprite-product-icons.png | Bin 132122 -> 0 bytes .../images/sprites/sprite-resource-icons.png | Bin 474238 -> 476775 bytes catalog-ui/src/assets/styles/mixins.less | 4 + catalog-ui/src/assets/styles/modal.less | 7 +- .../src/assets/styles/sprite-product-icons.less | 71 - .../src/assets/styles/sprite-resource-icons.less | 1 + catalog-ui/src/assets/styles/sprite.less | 2 + catalog-ui/src/assets/styles/variables-old.less | 2 +- catalog-ui/src/assets/styles/variables.less | 1 + .../org/openecomp/sdc/be/config/Configuration.java | 19 + .../org/openecomp/sdc/common/api/Constants.java | 1 + .../openecomp/sdc/common/api/HealthCheckInfo.java | 38 +- .../sdc/common/config/EcompErrorCode.java | 4 +- .../openecomp/sdc/common/util/GeneralUtility.java | 10 + .../openecomp/sdc/common/util/ValidationUtils.java | 30 +- .../openecomp/sdc/common/test/CommonUtilsTest.java | 6 +- .../ComponentMetadataDataDefinition.java | 19 +- .../components/ResourceMetadataDataDefinition.java | 21 +- .../components/ServiceMetadataDataDefinition.java | 38 +- .../be/datatypes/elements/ListDataDefinition.java | 8 +- .../be/datatypes/elements/MapDataDefinition.java | 12 + .../elements/RelationshipInstDataDefinition.java | 16 +- .../elements/RequirementDataDefinition.java | 6 +- .../be/datatypes/enums/JsonPresentationFields.java | 3 + .../sdc/be/datatypes/enums/OriginTypeEnum.java | 4 +- .../sdc/be/datatypes/enums/ResourceTypeEnum.java | 12 +- .../be/datatypes/tosca/ToscaDataDefinition.java | 4 + pom.xml | 2 +- .../templates/default/BE-configuration.yaml.erb | 4 +- .../templates/default/configuration.yaml.erb | 5 +- .../templates/default/BE-configuration.yaml.erb | 23 +- .../java/org/openecomp/sdc/ci/tests/api/Urls.java | 14 +- .../attribute/ComponentInstanceAttributeTest.java | 4 +- .../sdc/ci/tests/execute/devCI/AndreyTest.java | 31 +- .../general/BasicHttpAuthenticationTest.java | 2 +- .../execute/imports/ImportToscaResourceTest.java | 4 +- .../ci/tests/sanity/MultipleResourceUpdate.java | 2 +- .../ci/tests/tosca/datatypes/ToscaDefinition.java | 2 +- .../tosca/datatypes/ToscaParameterConstants.java | 9 + .../sdc/ci/tests/utils/CsarParserUtils.java | 34 +- .../sdc/ci/tests/utils/ToscaParserUtils.java | 122 +- .../tests/utils/general/AtomicOperationUtils.java | 14 +- .../sdc/ci/tests/utils/rest/CatalogRestUtils.java | 3 +- .../ci/tests/utils/rest/LifecycleRestUtils.java | 15 +- .../sdc/ci/tests/utils/rest/ResponseParser.java | 1 + .../sdc/ci/tests/utils/rest/ServiceRestUtils.java | 2 + .../utils/validation/CsarValidationUtils.java | 33 - .../sdc/externalApis/CRUDExternalAPI.java | 392 +- .../openecomp/sdc/externalApis/GetCSARofVF.java | 68 +- .../sdc/externalApis/VFCMTExternalAPI.java | 12 +- .../src/main/resources/ci/conf/attsdc.yaml | 2 +- .../src/test/resources/CI/error-configuration.yaml | 6 + .../tests/US/MIBsArtifactsOnResourceInstance.java | 4 - .../sdc/ci/tests/datatypes/DataTestIdEnum.java | 22 +- .../sdc/ci/tests/execute/sanity/Onboard.java | 41 + .../ci/tests/execute/sanity/OnboardViaApis.java | 32 + .../sdc/ci/tests/execute/sanity/Service.java | 12 - .../openecomp/sdc/ci/tests/execute/sanity/Vf.java | 4 - .../sdc/ci/tests/utilities/OnboardingUtils.java | 29 +- 312 files changed, 10637 insertions(+), 6411 deletions(-) create mode 100644 asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/execute/devCI/HealthCheckAPI.java create mode 100644 asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/execute/resource/GetLeftPaletteTest.java create mode 100644 asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/utils/rest/CommonRestUtils.java create mode 100644 asdctool/src/main/java/org/openecomp/sdc/asdctool/impl/migration/v1707/Migration1707MissingInfoFix.java create mode 100644 asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/config/MigrationSpringConfig.java create mode 100644 asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/core/DBVersion.java create mode 100644 asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/core/MigrationException.java create mode 100644 asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/core/SdcMigrationTool.java create mode 100644 asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/core/execution/MigrationExecutionResult.java create mode 100644 asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/core/execution/MigrationExecutor.java create mode 100644 asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/core/execution/MigrationExecutorImpl.java create mode 100644 asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/core/task/Migration.java create mode 100644 asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/core/task/MigrationResult.java create mode 100644 asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/main/MigrationMenu.java create mode 100644 asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/resolver/MigrationResolver.java create mode 100644 asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/resolver/SpringBeansMigrationResolver.java create mode 100644 asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/service/SdcRepoService.java create mode 100644 asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/tasks/mig1710/ExampleMigration.java create mode 100644 asdctool/src/main/resources/scripts/postMigration1707Fix.sh create mode 100644 asdctool/src/main/resources/scripts/sdc-migration.sh create mode 100644 asdctool/src/test/java/org/openecomp/sdc/asdctool/migration/DummyMigrationFactory.java create mode 100644 asdctool/src/test/java/org/openecomp/sdc/asdctool/migration/core/DBVersionTest.java create mode 100644 asdctool/src/test/java/org/openecomp/sdc/asdctool/migration/core/SdcMigrationToolTest.java create mode 100644 asdctool/src/test/java/org/openecomp/sdc/asdctool/migration/core/execution/MigrationExecutorImplTest.java create mode 100644 asdctool/src/test/java/org/openecomp/sdc/asdctool/migration/resolver/SpringBeansMigrationResolverTest.java create mode 100644 asdctool/src/test/java/org/openecomp/sdc/asdctool/migration/scanner/ClassScanner.java create mode 100644 asdctool/src/test/java/org/openecomp/sdc/asdctool/migration/service/SdcRepoServiceTest.java create mode 100644 asdctool/src/test/java/org/openecomp/sdc/asdctool/migration/task/MigrationTasksTest.java create mode 100644 catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/CassandraHealthCheck.java delete mode 100644 catalog-be/src/main/resources/import/tosca/heat-types.zip create mode 100644 catalog-be/src/main/resources/import/tosca/heat-types/Generic_PNF/Generic_PNF.json create mode 100644 catalog-be/src/main/resources/import/tosca/heat-types/Generic_PNF/Generic_PNF.yml create mode 100644 catalog-be/src/main/resources/import/tosca/heat-types/Generic_PNF/Generic_PNF.zip create mode 100644 catalog-be/src/main/resources/import/tosca/heat-types/multiFlavorVFC/multiFlavorVFC.json create mode 100644 catalog-be/src/main/resources/import/tosca/heat-types/multiFlavorVFC/multiFlavorVFC.yml create mode 100644 catalog-be/src/main/resources/import/tosca/heat-types/multiFlavorVFC/multiFlavorVFC.zip create mode 100644 catalog-be/src/main/resources/import/tosca/heat-types/vnfConfiguration/vnfConfiguration.json create mode 100644 catalog-be/src/main/resources/import/tosca/heat-types/vnfConfiguration/vnfConfiguration.yml create mode 100644 catalog-be/src/main/resources/import/tosca/heat-types/vnfConfiguration/vnfConfiguration.zip create mode 100644 catalog-dao/src/main/java/org/openecomp/sdc/be/dao/cassandra/MigrationTasksAccessor.java create mode 100644 catalog-dao/src/main/java/org/openecomp/sdc/be/dao/cassandra/MigrationTasksDao.java create mode 100644 catalog-dao/src/main/java/org/openecomp/sdc/be/dao/cassandra/schema/tables/MigrationTasksTableDescription.java create mode 100644 catalog-dao/src/main/java/org/openecomp/sdc/be/resources/data/MigrationTaskEntry.java create mode 100644 catalog-model/src/main/java/org/openecomp/sdc/be/model/IPropertyInputCommon.java create mode 100644 catalog-model/src/main/java/org/openecomp/sdc/be/model/ImportCsarInfo.java create mode 100644 catalog-model/src/main/java/org/openecomp/sdc/be/model/NodeTypeInfo.java create mode 100644 catalog-model/src/test/java/org/openecomp/sdc/be/model/jsontitan/operations/ArtifactsOperationsTest.java create mode 100644 catalog-model/src/test/java/org/openecomp/sdc/be/model/jsontitan/operations/ToscaElementOperationTest.java create mode 100644 catalog-model/src/test/java/org/openecomp/sdc/be/model/jsontitan/operations/ToscaElementOperationTestImpl.java create mode 100644 catalog-model/src/test/java/org/openecomp/sdc/be/model/jsontitan/utils/GraphTestUtils.java delete mode 100644 catalog-ui/src/app/models/components/product.ts delete mode 100644 catalog-ui/src/app/models/componentsInstances/productInstance.ts create mode 100644 catalog-ui/src/app/models/modal.ts delete mode 100644 catalog-ui/src/app/ng2/components/inputs-table/confirmation-delete-input/confirmation-delete-input.component.html delete mode 100644 catalog-ui/src/app/ng2/components/inputs-table/confirmation-delete-input/confirmation-delete-input.component.ts create mode 100644 catalog-ui/src/app/ng2/components/modal/modal.module.ts create mode 100644 catalog-ui/src/app/ng2/services/modal.service.ts delete mode 100644 catalog-ui/src/app/services/components/product-service.ts create mode 100644 catalog-ui/src/app/view-models/modals/icons-modal/icons-modal-view.html create mode 100644 catalog-ui/src/app/view-models/modals/icons-modal/icons-modal-view.less rename catalog-ui/src/app/view-models/{workspace/tabs/icons/icons-view-model.ts => modals/icons-modal/icons-modal-view.ts} (61%) delete mode 100644 catalog-ui/src/app/view-models/workspace/tabs/icons/icons-view.html delete mode 100644 catalog-ui/src/app/view-models/workspace/tabs/icons/icons.less delete mode 100644 catalog-ui/src/app/view-models/workspace/tabs/product-hierarchy/product-hierarchy-view-model.ts delete mode 100644 catalog-ui/src/app/view-models/workspace/tabs/product-hierarchy/product-hierarchy-view.html delete mode 100644 catalog-ui/src/app/view-models/workspace/tabs/product-hierarchy/product-hierarchy.less create mode 100644 catalog-ui/src/assets/styles/images/resource-icons/vnfconfiguration.png delete mode 100644 catalog-ui/src/assets/styles/images/sprites/sprite-product-icons.png delete mode 100644 catalog-ui/src/assets/styles/sprite-product-icons.less create mode 100644 test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/tosca/datatypes/ToscaParameterConstants.java diff --git a/.gitignore b/.gitignore index e9f00350d3..3ad4296d58 100644 --- a/.gitignore +++ b/.gitignore @@ -145,6 +145,7 @@ openecomp-ui/node/* sdc-os-chef/sdc-cassandra/chef-repo/cookbooks/cassandra-actions/files/default/SDC-*.zip sdc-os-chef/sdc-cassandra/chef-repo/cookbooks/cassandra-actions/files/default/sdctool.tar sdc-os-chef/.idea/* +node/* # chef .delivery diff --git a/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/api/ComponentInstanceBaseTest.java b/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/api/ComponentInstanceBaseTest.java index 9428a9b695..60c226136d 100644 --- a/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/api/ComponentInstanceBaseTest.java +++ b/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/api/ComponentInstanceBaseTest.java @@ -91,6 +91,7 @@ public class ComponentInstanceBaseTest extends ComponentBaseTest { protected ResourceReqDetails resourceDetailsVFC_02; protected ResourceReqDetails resourceDetailsVF_01; protected ResourceReqDetails resourceDetailsVF_02; + protected ResourceReqDetails resourceDetailsPNF_01; protected ResourceReqDetails resourceDetailsCP_01; protected ResourceReqDetails resourceDetailsCP_02; protected ResourceReqDetails resourceDetailsVL_01; @@ -119,6 +120,7 @@ public class ComponentInstanceBaseTest extends ComponentBaseTest { resourceDetailsVFC_02 = ElementFactory.getDefaultResourceByType("ciVFC200", NormativeTypesEnum.COMPUTE, ResourceCategoryEnum.GENERIC_INFRASTRUCTURE, sdncDesignerDetails.getUserId(), ResourceTypeEnum.VFC.toString()); resourceDetailsVF_01 = ElementFactory.getDefaultResourceByType("ciVF100", NormativeTypesEnum.ROOT, ResourceCategoryEnum.GENERIC_INFRASTRUCTURE, sdncDesignerDetails.getUserId(), ResourceTypeEnum.VF.toString()); resourceDetailsVF_02 = ElementFactory.getDefaultResourceByType("ciVF200", NormativeTypesEnum.ROOT, ResourceCategoryEnum.GENERIC_INFRASTRUCTURE, sdncDesignerDetails.getUserId(), ResourceTypeEnum.VF.toString()); + resourceDetailsPNF_01 = ElementFactory.getDefaultResourceByType("ciPNF100", NormativeTypesEnum.ROOT, ResourceCategoryEnum.GENERIC_INFRASTRUCTURE, sdncDesignerDetails.getUserId(), ResourceTypeEnum.PNF.toString()); resourceDetailsCP_01 = ElementFactory.getDefaultResourceByType("ciCP100", NormativeTypesEnum.PORT, ResourceCategoryEnum.GENERIC_NETWORK_ELEMENTS, sdncDesignerDetails.getUserId(), ResourceTypeEnum.CP.toString()); resourceDetailsCP_02 = ElementFactory.getDefaultResourceByType("ciCP200", NormativeTypesEnum.PORT, ResourceCategoryEnum.GENERIC_DATABASE, sdncDesignerDetails.getUserId(), ResourceTypeEnum.CP.toString()); resourceDetailsVL_01 = ElementFactory.getDefaultResourceByType("ciVL100", NormativeTypesEnum.NETWORK, ResourceCategoryEnum.GENERIC_NETWORK_ELEMENTS, sdncDesignerDetails.getUserId(), ResourceTypeEnum.VL.toString()); @@ -338,9 +340,9 @@ public class ComponentInstanceBaseTest extends ComponentBaseTest { Function>, List> capabilityDefinitionMapper = e -> new ArrayList<>(e.getValue().stream().map(item -> new CapabilityDefinition(item)).collect(Collectors.toList())); Map> capCopy = resourceCapabilities.entrySet().stream().collect(Collectors.toMap(e -> e.getKey(), capabilityDefinitionMapper)); - setupContainerExpectedReqCap(uniqueId, name, resourceRequirements, resourceCapabilities); + setupContainerExpectedReqCap(uniqueId, name, originComponentId, resourceRequirements, resourceCapabilities); if (component.getComponentType().equals(ComponentTypeEnum.RESOURCE) && ((Resource) component).getResourceType() != ResourceTypeEnum.VF) { - setupConstInstExpectedReqCap(uniqueId, name, reqCopy, capCopy); + setupConstInstExpectedReqCap(uniqueId, name, originComponentId, reqCopy, capCopy); } // adding entry for expected componentInstance @@ -348,12 +350,15 @@ public class ComponentInstanceBaseTest extends ComponentBaseTest { expectedContInstReqCap.put(uniqueId, compInstReqCapPair); } - private void setupContainerExpectedReqCap(String uniqueId, String name, Map> componentRequirements, Map> componentCapabilities) { + private void setupContainerExpectedReqCap(String uniqueId, String name, String componentId, Map> componentRequirements, Map> componentCapabilities) { for (Entry> resReq : componentRequirements.entrySet()) { List reqListToAdd = resReq.getValue(); for (RequirementDefinition requirementDefinition : reqListToAdd) { requirementDefinition.setOwnerId(uniqueId); requirementDefinition.setOwnerName(name); + requirementDefinition.addToPath(uniqueId); + requirementDefinition.setSource(componentId); + requirementDefinition.setLeftOccurrences(requirementDefinition.getMaxOccurrences()); } List expectedReqList = expectedContainerRequirements.get(resReq.getKey()); if (expectedReqList == null) { @@ -369,6 +374,9 @@ public class ComponentInstanceBaseTest extends ComponentBaseTest { for (CapabilityDefinition capDefinition : capListToAdd) { capDefinition.setOwnerId(uniqueId); capDefinition.setOwnerName(name); + capDefinition.addToPath(uniqueId); + capDefinition.setSource(componentId); + capDefinition.setLeftOccurrences(capDefinition.getMaxOccurrences()); } List expectedCapList = expectedContainerCapabilities.get(resCap.getKey()); if (expectedCapList == null) { @@ -380,12 +388,15 @@ public class ComponentInstanceBaseTest extends ComponentBaseTest { } } - private void setupConstInstExpectedReqCap(String uniqueId, String name, Map> componentRequirements, Map> componentCapabilities) { + private void setupConstInstExpectedReqCap(String uniqueId, String name, String componentId, Map> componentRequirements, Map> componentCapabilities) { for (Entry> resReq : componentRequirements.entrySet()) { List reqListToAdd = resReq.getValue(); for (RequirementDefinition requirementDefinition : reqListToAdd) { requirementDefinition.setOwnerId(uniqueId); requirementDefinition.setOwnerName(name); + requirementDefinition.addToPath(uniqueId); + requirementDefinition.setSource(componentId); + requirementDefinition.setLeftOccurrences(requirementDefinition.getMaxOccurrences()); } } @@ -394,6 +405,8 @@ public class ComponentInstanceBaseTest extends ComponentBaseTest { for (CapabilityDefinition capDefinition : capListToAdd) { capDefinition.setOwnerId(uniqueId); capDefinition.setOwnerName(name); + capDefinition.addToPath(uniqueId); + capDefinition.setSource(componentId); } } } @@ -570,6 +583,31 @@ public class ComponentInstanceBaseTest extends ComponentBaseTest { return component; } + protected Component getComponentAndValidateRIsOnly(ComponentReqDetails componentDetails, int numberOfRIs, int numberOfRelations) throws IOException, Exception { + + RestResponse getResponse = null; + Component component = null; + if (componentDetails instanceof ResourceReqDetails) { + getResponse = ResourceRestUtils.getResource(sdncAdminDetails, componentDetails.getUniqueId()); + component = ResponseParser.parseToObjectUsingMapper(getResponse.getResponse(), Resource.class); + } else if (componentDetails instanceof ServiceReqDetails) { + getResponse = ServiceRestUtils.getService((ServiceReqDetails) componentDetails, sdncAdminDetails); + component = ResponseParser.parseToObjectUsingMapper(getResponse.getResponse(), Service.class); + } else if (componentDetails instanceof ProductReqDetails) { + getResponse = ProductRestUtils.getProduct(componentDetails.getUniqueId(), sdncAdminDetails.getUserId()); + component = ResponseParser.parseToObjectUsingMapper(getResponse.getResponse(), Product.class); + } else { + Assert.fail("Unsupported type of componentDetails - " + componentDetails.getClass().getSimpleName()); + } + ResourceRestUtils.checkSuccess(getResponse); + int numberOfActualRIs = component.getComponentInstances() != null ? component.getComponentInstances().size() : 0; + int numberOfActualRelations = component.getComponentInstancesRelations() != null ? component.getComponentInstancesRelations().size() : 0; + assertEquals("Check number of RIs meet the expected number", numberOfRIs, numberOfActualRIs); + assertEquals("Check number of RI relations meet the expected number", numberOfRelations, numberOfActualRelations); + + return component; + } + protected void getComponentAndValidateRIsAfterChangeLifecycleState(String oldComponentUniqueIdToReplace, ComponentReqDetails componentDetails, int numOfRIs, int numOfRelations) throws IOException, Exception { updateExpectedReqCapAfterChangeLifecycleState(oldComponentUniqueIdToReplace, componentDetails.getUniqueId()); getComponentAndValidateRIs(componentDetails, numOfRIs, numOfRelations); @@ -612,6 +650,10 @@ public class ComponentInstanceBaseTest extends ComponentBaseTest { ResourceRestUtils.checkCreateResponse(createVfResponse); } + protected void createPNF(ResourceReqDetails resourceDetails) throws Exception { + createVF(resourceDetails, sdncDesignerDetails); + } + protected void createService(ServiceReqDetails serviceDetails) throws Exception { createService(serviceDetails, sdncDesignerDetails); } diff --git a/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/api/Urls.java b/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/api/Urls.java index 0e1c0e4da1..3e4411b06e 100644 --- a/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/api/Urls.java +++ b/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/api/Urls.java @@ -45,6 +45,8 @@ public interface Urls { final String GET_SERVICE_lATEST_VERSION = "http://%s:%s/sdc2/rest/v1/catalog/services/latestversion/notabstract"; + final String GET_RESOURCE_METADATA_lATEST_VERSION = "http://%s:%s/sdc2/rest/v1/catalog/resources/latestversion/notabstract/metadata"; + // Get resource artifact list: // http://172.20.43.124:8080/sdc2/rest/v1/catalog/resources/alien.nodes.Apache/2.0.0-SNAPSHOT/artifacts final String GET_RESOURCE_ARTIFACTS_LIST = "http://%s:%s/sdc2/rest/v1/catalog/resources/%s/%s/artifacts"; @@ -186,35 +188,35 @@ public interface Urls { // ***********************************External API's // (AssetData)**************************************** - final String DELETE_EXTRNAL_API_DELETE_ARTIFACT_OF_ASSET = "http://%s:%s/asdc/v1/catalog/%s/%s/artifacts/%s"; - final String DELETE_EXTRNAL_API_DELETE_ARTIFACT_OF_COMPONENTINSTANCE_ON_ASSET = "http://%s:%s/asdc/v1/catalog/%s/%s/resourceInstances/%s/artifacts/%s"; + final String DELETE_EXTRNAL_API_DELETE_ARTIFACT_OF_ASSET = "http://%s:%s/sdc/v1/catalog/%s/%s/artifacts/%s"; + final String DELETE_EXTRNAL_API_DELETE_ARTIFACT_OF_COMPONENTINSTANCE_ON_ASSET = "http://%s:%s/sdc/v1/catalog/%s/%s/resourceInstances/%s/artifacts/%s"; - final String POST_EXTERNAL_API_UPDATE_ARTIFACT_OF_ASSET = "http://%s:%s/asdc/v1/catalog/%s/%s/artifacts/%s"; - final String POST_EXTERNAL_API_UPDATE_ARTIFACT_OF_COMPONENTINSTANCE_ON_ASSET = "http://%s:%s/asdc/v1/catalog/%s/%s/resourceInstances/%s/artifacts/%s"; + final String POST_EXTERNAL_API_UPDATE_ARTIFACT_OF_ASSET = "http://%s:%s/sdc/v1/catalog/%s/%s/artifacts/%s"; + final String POST_EXTERNAL_API_UPDATE_ARTIFACT_OF_COMPONENTINSTANCE_ON_ASSET = "http://%s:%s/sdc/v1/catalog/%s/%s/resourceInstances/%s/artifacts/%s"; - final String POST_EXTERNAL_API_UPLOAD_ARTIFACT_OF_ASSET = "http://%s:%s/asdc/v1/catalog/%s/%s/artifacts"; - final String POST_EXTERNAL_API_UPLOAD_ARTIFACT_OF_COMPONENTINSTANCE_ON_ASSET = "http://%s:%s/asdc/v1/catalog/%s/%s/resourceInstances/%s/artifacts"; + final String POST_EXTERNAL_API_UPLOAD_ARTIFACT_OF_ASSET = "http://%s:%s/sdc/v1/catalog/%s/%s/artifacts"; + final String POST_EXTERNAL_API_UPLOAD_ARTIFACT_OF_COMPONENTINSTANCE_ON_ASSET = "http://%s:%s/sdc/v1/catalog/%s/%s/resourceInstances/%s/artifacts"; - final String GET_DOWNLOAD_RESOURCE_ARTIFACT_OF_ASSET = "http://%s:%s/asdc/v1/catalog/resources/%s/artifacts/%s"; - final String GET_DOWNLOAD_SERVICE_ARTIFACT_OF_ASSET = "http://%s:%s/asdc/v1/catalog/services/%s/artifacts/%s"; + final String GET_DOWNLOAD_RESOURCE_ARTIFACT_OF_ASSET = "http://%s:%s/sdc/v1/catalog/resources/%s/artifacts/%s"; + final String GET_DOWNLOAD_SERVICE_ARTIFACT_OF_ASSET = "http://%s:%s/sdc/v1/catalog/services/%s/artifacts/%s"; - final String GET_DOWNLOAD_RESOURCE_ARTIFACT_OF_COMPONENT_INSTANCE = "http://%s:%s/asdc/v1/catalog/resources/%s/resourceInstances/%s/artifacts/%s"; - final String GET_DOWNLOAD_SERVICE_ARTIFACT_OF_COMPONENT_INSTANCE = "http://%s:%s/asdc/v1/catalog/services/%s/resourceInstances/%s/artifacts/%s"; + final String GET_DOWNLOAD_RESOURCE_ARTIFACT_OF_COMPONENT_INSTANCE = "http://%s:%s/sdc/v1/catalog/resources/%s/resourceInstances/%s/artifacts/%s"; + final String GET_DOWNLOAD_SERVICE_ARTIFACT_OF_COMPONENT_INSTANCE = "http://%s:%s/sdc/v1/catalog/services/%s/resourceInstances/%s/artifacts/%s"; - final String GET_ASSET_LIST = "http://%s:%s/asdc/v1/catalog/%s"; - final String GET_FILTERED_ASSET_LIST = "http://%s:%s/asdc/v1/catalog/%s?%s"; - final String GET_TOSCA_MODEL = "http://%s:%s/asdc/v1/catalog/%s/%s/toscaModel"; - // https://{serverRoot}/asdc/v1/catalog/{assetType}/{uuid}/metadata, where + final String GET_ASSET_LIST = "http://%s:%s/sdc/v1/catalog/%s"; + final String GET_FILTERED_ASSET_LIST = "http://%s:%s/sdc/v1/catalog/%s?%s"; + final String GET_TOSCA_MODEL = "http://%s:%s/sdc/v1/catalog/%s/%s/toscaModel"; + // https://{serverRoot}/sdc/v1/catalog/{assetType}/{uuid}/metadata, where // assetType in {resources, services} - final String GET_ASSET_METADATA = "http://%s:%s/asdc/v1/catalog/%s/%s/metadata"; + final String GET_ASSET_METADATA = "http://%s:%s/sdc/v1/catalog/%s/%s/metadata"; final String POST_AUTHORIZATION = "http://%s:%s/sdc2/rest/v1/consumers"; - final String GET_DOWNLOAD_SERVICE_RI_ARTIFACT = "http://%s:%s/asdc/v1/catalog/services/%s/resourceInstances/%s/artifacts/%s"; - final String GET_DOWNLOAD_SERVICE_ARTIFACT = "http://%s:%s/asdc/v1/catalog/services/%s/artifacts/%s"; + final String GET_DOWNLOAD_SERVICE_RI_ARTIFACT = "http://%s:%s/sdc/v1/catalog/services/%s/resourceInstances/%s/artifacts/%s"; + final String GET_DOWNLOAD_SERVICE_ARTIFACT = "http://%s:%s/sdc/v1/catalog/services/%s/artifacts/%s"; - final String POST_EXTERNAL_API_CREATE_RESOURCE = "http://%s:%s/asdc/v1/catalog/resources"; + final String POST_EXTERNAL_API_CREATE_RESOURCE = "http://%s:%s/sdc/v1/catalog/resources"; - final String CHANGE_RESOURCE_LIFECYCLE_STATE_EXTERNAL_API = "http://%s:%s/asdc/v1/catalog/resources/%s/lifecycleState/%s"; - final String CHANGE_SERVICE_LIFECYCLE_STATE_EXTERNAL_API = "http://%s:%s/asdc/v1/catalog/services/%s/lifecycleState/%s"; + final String CHANGE_RESOURCE_LIFECYCLE_STATE_EXTERNAL_API = "http://%s:%s/sdc/v1/catalog/resources/%s/lifecycleState/%s"; + final String CHANGE_SERVICE_LIFECYCLE_STATE_EXTERNAL_API = "http://%s:%s/sdc/v1/catalog/services/%s/lifecycleState/%s"; // ***************************************************************************************************** @@ -238,8 +240,8 @@ public interface Urls { final String DISTRIB_DOWNLOAD_SERVICE_ARTIFACT = "/sdc2/rest/v1/catalog/services/%s/%s/artifacts/%s"; // "/sdc2/v1/services//<0.1>/resources/{resourceName}/{resourceVersion}/artifacts/_aaa.hh" final String DISTRIB_DOWNLOAD_RESOURCE_ARTIFACT = "/sdc2/rest/v1/catalog/services/%s/%s/resources/%s/%s/artifacts/%s"; - final String DISTRIB_DOWNLOAD_SERVICE_ARTIFACT_RELATIVE_URL = "/asdc/v1/catalog/services/%s/%s/artifacts/%s"; - final String DISTRIB_DOWNLOAD_RESOURCE_ARTIFACT_RELATIVE_URL = "/asdc/v1/catalog/services/%s/%s/resources/%s/%s/artifacts/%s"; + final String DISTRIB_DOWNLOAD_SERVICE_ARTIFACT_RELATIVE_URL = "/sdc/v1/catalog/services/%s/%s/artifacts/%s"; + final String DISTRIB_DOWNLOAD_RESOURCE_ARTIFACT_RELATIVE_URL = "/sdc/v1/catalog/services/%s/%s/resources/%s/%s/artifacts/%s"; final String DOWNLOAD_SERVICE_ARTIFACT_FULL_URL = "http://%s:%s%s"; final String DOWNLOAD_RESOURCE_ARTIFACT_FULL_URL = "http://%s:%s%s"; // ********************************************************************************** diff --git a/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/datatypes/ResourceReqDetails.java b/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/datatypes/ResourceReqDetails.java index 8456e5b35b..d8bd80115e 100644 --- a/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/datatypes/ResourceReqDetails.java +++ b/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/datatypes/ResourceReqDetails.java @@ -29,6 +29,7 @@ public class ResourceReqDetails extends ComponentReqDetails { List derivedFrom; String vendorName; String vendorRelease; + String resourceVendorModelNumber; // Unsettable/unupdatable fields @@ -55,6 +56,7 @@ public class ResourceReqDetails extends ComponentReqDetails { this.derivedFrom = resource.getDerivedFrom(); this.vendorName = resource.getVendorName(); this.vendorRelease = resource.getVendorRelease(); + this.resourceVendorModelNumber = resource.getResourceVendorModelNumber(); this.contactId = resource.getContactId(); this.icon = resource.getIcon(); this.toscaResourceName = resource.getToscaResourceName(); diff --git a/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/datatypes/ServiceReqDetails.java b/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/datatypes/ServiceReqDetails.java index e33183ca94..022caecf41 100644 --- a/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/datatypes/ServiceReqDetails.java +++ b/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/datatypes/ServiceReqDetails.java @@ -26,6 +26,9 @@ import org.openecomp.sdc.be.model.Service; import org.openecomp.sdc.be.model.category.CategoryDefinition; public class ServiceReqDetails extends ComponentReqDetails { + + String serviceType; + String serviceRole; public ServiceReqDetails(String serviceName, String category, ArrayList tags, String description, String contactId, String icon) { @@ -35,6 +38,8 @@ public class ServiceReqDetails extends ComponentReqDetails { this.description = description; this.contactId = contactId; this.icon = icon; + this.serviceType = ""; + this.serviceRole = ""; projectCode = "12345"; CategoryDefinition categoryDefinition = new CategoryDefinition(); categoryDefinition.setName(category); @@ -56,6 +61,8 @@ public class ServiceReqDetails extends ComponentReqDetails { this.uniqueId = service.getUniqueId(); this.UUID = service.getUUID(); this.version = service.getVersion(); + this.serviceType = service.getServiceType(); + this.serviceRole = service.getServiceRole(); } diff --git a/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/execute/artifacts/DownloadComponentArt.java b/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/execute/artifacts/DownloadComponentArt.java index 5ec4a86977..e4c89bee94 100644 --- a/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/execute/artifacts/DownloadComponentArt.java +++ b/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/execute/artifacts/DownloadComponentArt.java @@ -178,7 +178,7 @@ public class DownloadComponentArt extends ComponentBaseTest { expectedResourceAuditJavaObject.setDesc("OK"); expectedResourceAuditJavaObject.setCONSUMER_ID("ci"); - String resource_url = String.format("/asdc/v1/catalog/resources/%s/artifacts/%s", resourceUUID, artifactUUID); + String resource_url = String.format("/sdc/v1/catalog/resources/%s/artifacts/%s", resourceUUID, artifactUUID); expectedResourceAuditJavaObject.setRESOURCE_URL(resource_url); AuditValidationUtils.validateAuditDownloadExternalAPI(expectedResourceAuditJavaObject, auditAction, null, false); @@ -250,7 +250,7 @@ public class DownloadComponentArt extends ComponentBaseTest { expectedResourceAuditJavaObject.setDesc("OK"); expectedResourceAuditJavaObject.setCONSUMER_ID("ci"); - String resource_url = String.format("/asdc/v1/catalog/services/%s/artifacts/%s", resourceUUID, artifactUUID); + String resource_url = String.format("/sdc/v1/catalog/services/%s/artifacts/%s", resourceUUID, artifactUUID); expectedResourceAuditJavaObject.setRESOURCE_URL(resource_url); AuditValidationUtils.validateAuditDownloadExternalAPI(expectedResourceAuditJavaObject, auditAction, null, false); @@ -313,7 +313,7 @@ public class DownloadComponentArt extends ComponentBaseTest { expectedResourceAuditJavaObject.setDesc("OK"); expectedResourceAuditJavaObject.setCONSUMER_ID("ci"); - String resource_url = String.format("/asdc/v1/catalog/services/%s/resourceInstances/%s/artifacts/%s", resourceUUID, componentNormalizedName, artifactUUID); + String resource_url = String.format("/sdc/v1/catalog/services/%s/resourceInstances/%s/artifacts/%s", resourceUUID, componentNormalizedName, artifactUUID); expectedResourceAuditJavaObject.setRESOURCE_URL(resource_url); AuditValidationUtils.validateAuditDownloadExternalAPI(expectedResourceAuditJavaObject, auditAction, null, false); diff --git a/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/execute/category/CatalogDataApiTest.java b/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/execute/category/CatalogDataApiTest.java index 86641eb2c7..44b781f065 100644 --- a/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/execute/category/CatalogDataApiTest.java +++ b/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/execute/category/CatalogDataApiTest.java @@ -20,26 +20,21 @@ package org.openecomp.sdc.ci.tests.execute.category; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; +import java.util.*; -import org.apache.log4j.lf5.util.ResourceUtils; import org.json.simple.JSONArray; import org.json.simple.JSONObject; import org.json.simple.JSONValue; import org.junit.Rule; import org.junit.rules.TestName; +import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum; import org.openecomp.sdc.be.model.User; import org.openecomp.sdc.ci.tests.api.ComponentBaseTest; import org.openecomp.sdc.ci.tests.api.Urls; import org.openecomp.sdc.ci.tests.config.Config; import org.openecomp.sdc.ci.tests.datatypes.ResourceReqDetails; import org.openecomp.sdc.ci.tests.datatypes.ServiceReqDetails; -import org.openecomp.sdc.ci.tests.datatypes.enums.LifeCycleStatesEnum; -import org.openecomp.sdc.ci.tests.datatypes.enums.ResourceCategoryEnum; -import org.openecomp.sdc.ci.tests.datatypes.enums.ServiceCategoriesEnum; -import org.openecomp.sdc.ci.tests.datatypes.enums.UserRoleEnum; +import org.openecomp.sdc.ci.tests.datatypes.enums.*; import org.openecomp.sdc.ci.tests.datatypes.http.HttpHeaderEnum; import org.openecomp.sdc.ci.tests.datatypes.http.HttpRequest; import org.openecomp.sdc.ci.tests.datatypes.http.RestResponse; @@ -49,9 +44,8 @@ import org.openecomp.sdc.ci.tests.utils.rest.CatalogRestUtils; import org.openecomp.sdc.ci.tests.utils.rest.LifecycleRestUtils; import org.openecomp.sdc.ci.tests.utils.rest.ResourceRestUtils; import org.openecomp.sdc.ci.tests.utils.rest.ResponseParser; -import org.openecomp.sdc.ci.tests.utils.rest.ServiceRestUtils; import org.testng.AssertJUnit; -import org.testng.annotations.AfterMethod; +import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; @@ -62,6 +56,7 @@ public class CatalogDataApiTest extends ComponentBaseTest { protected Config config = Config.instance(); protected String contentTypeHeaderData = "application/json"; protected String acceptHeaderDate = "application/json"; + protected boolean isInitialized = false; @Rule public static TestName name = new TestName(); @@ -79,28 +74,36 @@ public class CatalogDataApiTest extends ComponentBaseTest { @BeforeMethod public void setUp() throws Exception { + if (isInitialized) + return; user = ElementFactory.getDefaultUser(UserRoleEnum.ADMIN); resourceDetails1 = buildResourceDetails(user, "TestResource1"); + resourceDetails1.setResourceType(ResourceTypeEnum.VFCMT.name()); resourceDetails2 = buildResourceDetails(user, "TestResource2"); svcDetails1 = buildServiceDetails("TestService1"); + // VFCMT res1 = createResource(user, resourceDetails1); AssertJUnit.assertEquals("create resorce failed", 201, res1.getErrorCode().intValue()); resourceDetails1.setUniqueId(ResponseParser.getUniqueIdFromResponse(res1)); + resourceDetails2.setVersion(ResponseParser.getVersionFromResponse(res1)); + // VFC res2 = createResource(user, resourceDetails2); AssertJUnit.assertEquals("create resorce failed", 201, res2.getErrorCode().intValue()); resourceDetails2.setUniqueId(ResponseParser.getUniqueIdFromResponse(res2)); resourceDetails2.setVersion(ResponseParser.getVersionFromResponse(res2)); + // SERVICE svc1 = createService(user, svcDetails1); AssertJUnit.assertEquals("create resorce failed", 201, svc1.getErrorCode().intValue()); svcDetails1.setUniqueId(ResponseParser.convertServiceResponseToJavaObject(svc1.getResponse()).getUniqueId()); svcDetails1.setVersion(ResponseParser.convertServiceResponseToJavaObject(svc1.getResponse()).getVersion()); + isInitialized = true; } - @AfterMethod + @AfterClass public void tearDown() throws Exception { deleteResource(resourceDetails1.getUniqueId(), user.getUserId()); deleteResource(resourceDetails2.getUniqueId(), user.getUserId()); @@ -131,6 +134,66 @@ public class CatalogDataApiTest extends ComponentBaseTest { } + @Test + public void getCatalogDataNoVFCMT() throws Exception { + + List excludeTyps = Arrays.asList(OriginTypeEnum.VFCMT.name()); + RestResponse res = CatalogRestUtils.getCatalog(user.getUserId(), excludeTyps); + String json = res.getResponse(); + JSONObject jsonResp = (JSONObject) JSONValue.parse(json); + JSONArray resources = (JSONArray) jsonResp.get("resources"); + JSONArray services = (JSONArray) jsonResp.get("services"); + + // Verify all the expected resources received except of resource1 which is VFCMT + AssertJUnit.assertFalse("check resource1 is in response", + isComponentInArray(resourceDetails1.getUniqueId(), resources)); + AssertJUnit.assertTrue("check resource2 is in response", + isComponentInArray(resourceDetails2.getUniqueId(), resources)); + AssertJUnit.assertTrue("check service1 is in response", + isComponentInArray(svcDetails1.getUniqueId(), services)); + + } + + @Test + public void getCatalogDataNoVFCandVFCMT() throws Exception { + + List excludeTyps = Arrays.asList(OriginTypeEnum.VFCMT.name(), OriginTypeEnum.VFC.name()); + RestResponse res = CatalogRestUtils.getCatalog(user.getUserId(), excludeTyps); + String json = res.getResponse(); + JSONObject jsonResp = (JSONObject) JSONValue.parse(json); + JSONArray resources = (JSONArray) jsonResp.get("resources"); + JSONArray services = (JSONArray) jsonResp.get("services"); + + // Verify all the expected resources received except of VFCMT & VFC + AssertJUnit.assertFalse("check resource1 is in response", + isComponentInArray(resourceDetails1.getUniqueId(), resources)); + AssertJUnit.assertFalse("check resource2 is in response", + isComponentInArray(resourceDetails2.getUniqueId(), resources)); + AssertJUnit.assertTrue("check service1 is in response", + isComponentInArray(svcDetails1.getUniqueId(), services)); + + } + + @Test + public void getCatalogDataNoServiceAndVFC() throws Exception { + + List excludeTyps = Arrays.asList(OriginTypeEnum.SERVICE.name(), OriginTypeEnum.VFC.name()); + RestResponse res = CatalogRestUtils.getCatalog(user.getUserId(), excludeTyps); + String json = res.getResponse(); + JSONObject jsonResp = (JSONObject) JSONValue.parse(json); + JSONArray resources = (JSONArray) jsonResp.get("resources"); + JSONArray services = (JSONArray) jsonResp.get("services"); + + // Verify all the expected resources received except of VFC & SERVICE + AssertJUnit.assertTrue("check resource1 is in response", + isComponentInArray(resourceDetails1.getUniqueId(), resources)); + AssertJUnit.assertFalse("check resource2 is in response", + isComponentInArray(resourceDetails2.getUniqueId(), resources)); + AssertJUnit.assertFalse("check service1 is in response", + isComponentInArray(svcDetails1.getUniqueId(), services)); + + } + protected void deleteResource(String resourceUniqueId, String httpCspUserId) throws Exception { RestResponse deleteResourceResponse = ResourceRestUtils.deleteResource(resourceUniqueId, httpCspUserId); @@ -171,6 +234,7 @@ public class CatalogDataApiTest extends ComponentBaseTest { protected RestResponse createService(User user, ServiceReqDetails svcDetails) throws Exception { + deleteService(svcDetails1.getUniqueId(), user); Config config = Utils.getConfig(); Map headersMap = getHeadersMap(user); @@ -189,7 +253,7 @@ public class CatalogDataApiTest extends ComponentBaseTest { Map headersMap = new HashMap(); headersMap.put(HttpHeaderEnum.CONTENT_TYPE.getValue(), contentTypeHeaderData); headersMap.put(HttpHeaderEnum.ACCEPT.getValue(), acceptHeaderDate); - headersMap.put(HttpHeaderEnum.USER_ID.getValue(), user.getUserId()); + headersMap.put("USER_ID", user.getUserId()); return headersMap; } @@ -210,15 +274,8 @@ public class CatalogDataApiTest extends ComponentBaseTest { } public RestResponse deleteService(String serviceId, User user) throws Exception { - HttpRequest httpRequest = new HttpRequest(); - String url = String.format(Urls.DELETE_SERVICE, config.getCatalogBeHost(), config.getCatalogBePort(), - serviceId); - - Map headersMap = getHeadersMap(user); - RestResponse res = httpRequest.httpSendDelete(url, headersMap); - // System.out.println("Delete service was finished with response: - // "+res.getErrorCode()); - return res; + RestResponse deleteServiceResponse = ResourceRestUtils.deleteResource(serviceId, user.getUserId()); + return deleteServiceResponse; } public class NewObject { diff --git a/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/execute/devCI/CRUDExternalAPI.java b/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/execute/devCI/CRUDExternalAPI.java index 7e8d5cf8cc..4a4e5a4529 100644 --- a/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/execute/devCI/CRUDExternalAPI.java +++ b/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/execute/devCI/CRUDExternalAPI.java @@ -435,7 +435,7 @@ public class CRUDExternalAPI extends ComponentBaseTest { AssetTypeEnum assetTypeEnum = AssetTypeEnum.valueOf((resourceDetails.getComponentType().getValue() + "s").toUpperCase()); ExpectedExternalAudit expectedExternalAudit = ElementFactory.getDefaultExternalArtifactAuditSuccess(assetTypeEnum, action, responseArtifact, resourceDetails); expectedExternalAudit.setRESOURCE_NAME(componentInstance.getNormalizedName()); - expectedExternalAudit.setRESOURCE_URL("/asdc/v1/catalog/" + assetTypeEnum.getValue() + "/" + resourceDetails.getUUID() + "/resourceInstances/" + componentInstance.getNormalizedName() + "/artifacts"); + expectedExternalAudit.setRESOURCE_URL("/sdc/v1/catalog/" + assetTypeEnum.getValue() + "/" + resourceDetails.getUUID() + "/resourceInstances/" + componentInstance.getNormalizedName() + "/artifacts"); AuditValidationUtils.validateExternalAudit(expectedExternalAudit, AuditingActionEnum.ARTIFACT_UPLOAD_BY_API.getName(), body); return restResponse; @@ -584,13 +584,13 @@ public class CRUDExternalAPI extends ComponentBaseTest { // // if(componentTypeEnum == ComponentTypeEnum.RESOURCE_INSTANCE) { // expectedResourceAuditJavaObject.setResourceName(resourceDetails.getComponentInstances().get(0).getName()); -// String resource_url = String.format("/asdc/v1/catalog/services/%s/resourceInstances/%s/artifacts/%s", resourceDetails.getUUID(), resourceDetails.getComponentInstances().get(0).getNormalizedName(), artifactDefinition.getArtifactUUID()); +// String resource_url = String.format("/sdc/v1/catalog/services/%s/resourceInstances/%s/artifacts/%s", resourceDetails.getUUID(), resourceDetails.getComponentInstances().get(0).getNormalizedName(), artifactDefinition.getArtifactUUID()); // expectedResourceAuditJavaObject.setRESOURCE_URL(resource_url); // // AuditValidationUtils.validateAuditDownloadExternalAPI(expectedResourceAuditJavaObject, auditAction, null, false); // } else { // expectedResourceAuditJavaObject.setResourceName(resourceDetails.getName()); -// String resource_url = String.format("/asdc/v1/catalog/services/%s/artifacts/%s", resourceDetails.getUUID(), artifactDefinition.getArtifactUUID()); +// String resource_url = String.format("/sdc/v1/catalog/services/%s/artifacts/%s", resourceDetails.getUUID(), artifactDefinition.getArtifactUUID()); // expectedResourceAuditJavaObject.setRESOURCE_URL(resource_url); // } // @@ -1092,7 +1092,7 @@ public class CRUDExternalAPI extends ComponentBaseTest { body.put(AuditingFieldsKeysEnum.AUDIT_STATUS, responseCode.toString()); if(componentResourceInstanceDetails != null) { body.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_NAME, resourceDetails.getComponentInstances().get(0).getNormalizedName()); - expectedExternalAudit.setRESOURCE_URL("/asdc/v1/catalog/" + assetTypeEnum.getValue() + "/" + resourceDetails.getUUID() + "/resourceInstances/" + resourceDetails.getComponentInstances().get(0).getNormalizedName() + "/artifacts"); + expectedExternalAudit.setRESOURCE_URL("/sdc/v1/catalog/" + assetTypeEnum.getValue() + "/" + resourceDetails.getUUID() + "/resourceInstances/" + resourceDetails.getComponentInstances().get(0).getNormalizedName() + "/artifacts"); expectedExternalAudit.setRESOURCE_NAME(resourceDetails.getComponentInstances().get(0).getNormalizedName()); } else { expectedExternalAudit.setRESOURCE_NAME(resourceDetails.getName()); @@ -1148,7 +1148,7 @@ public class CRUDExternalAPI extends ComponentBaseTest { body.put(AuditingFieldsKeysEnum.AUDIT_STATUS, responseCode.toString()); if(componentResourceInstanceDetails != null) { body.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_NAME, resourceDetails.getComponentInstances().get(0).getNormalizedName()); - expectedExternalAudit.setRESOURCE_URL("/asdc/v1/catalog/" + assetTypeEnum.getValue() + "/" + resourceDetails.getUUID() + "/resourceInstances/" + resourceDetails.getComponentInstances().get(0).getNormalizedName() + "/artifacts"); + expectedExternalAudit.setRESOURCE_URL("/sdc/v1/catalog/" + assetTypeEnum.getValue() + "/" + resourceDetails.getUUID() + "/resourceInstances/" + resourceDetails.getComponentInstances().get(0).getNormalizedName() + "/artifacts"); expectedExternalAudit.setRESOURCE_NAME(resourceDetails.getComponentInstances().get(0).getNormalizedName()); } else { body.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_NAME, resourceDetails.getName()); @@ -2354,7 +2354,7 @@ public class CRUDExternalAPI extends ComponentBaseTest { body.put(AuditingFieldsKeysEnum.AUDIT_STATUS, responseCode.toString()); if(componentInstance != null) { body.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_NAME, resourceDetails.getComponentInstances().get(0).getNormalizedName()); - expectedExternalAudit.setRESOURCE_URL("/asdc/v1/catalog/" + assetTypeEnum.getValue() + "/" + resourceDetails.getUUID() + "/resourceInstances/" + resourceDetails.getComponentInstances().get(0).getNormalizedName() + "/artifacts/" + artifactUUID); + expectedExternalAudit.setRESOURCE_URL("/sdc/v1/catalog/" + assetTypeEnum.getValue() + "/" + resourceDetails.getUUID() + "/resourceInstances/" + resourceDetails.getComponentInstances().get(0).getNormalizedName() + "/artifacts/" + artifactUUID); expectedExternalAudit.setRESOURCE_NAME(resourceDetails.getComponentInstances().get(0).getNormalizedName()); } else { expectedExternalAudit.setRESOURCE_URL(expectedExternalAudit.getRESOURCE_URL() + "/" + artifactUUID); @@ -2511,7 +2511,7 @@ public class CRUDExternalAPI extends ComponentBaseTest { ExpectedExternalAudit expectedExternalAudit = ElementFactory.getDefaultExternalArtifactAuditSuccess(assetTypeEnum, action, responseArtifact, resourceDetails); // expectedExternalAudit.setRESOURCE_URL(expectedExternalAudit.getRESOURCE_URL()+ "/" + artifactUUID); expectedExternalAudit.setRESOURCE_NAME(componentInstance.getNormalizedName()); - expectedExternalAudit.setRESOURCE_URL("/asdc/v1/catalog/" + assetTypeEnum.getValue() + "/" + resourceDetails.getUUID() + "/resourceInstances/" + componentInstance.getNormalizedName() + "/artifacts/" + artifactUUID); + expectedExternalAudit.setRESOURCE_URL("/sdc/v1/catalog/" + assetTypeEnum.getValue() + "/" + resourceDetails.getUUID() + "/resourceInstances/" + componentInstance.getNormalizedName() + "/artifacts/" + artifactUUID); AuditValidationUtils.validateExternalAudit(expectedExternalAudit, AuditingActionEnum.ARTIFACT_UPDATE_BY_API.getName(), body); return restResponse; @@ -3151,7 +3151,7 @@ public class CRUDExternalAPI extends ComponentBaseTest { body.put(AuditingFieldsKeysEnum.AUDIT_STATUS, responseCode.toString()); if(componentInstance != null) { body.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_NAME, resourceDetails.getComponentInstances().get(0).getNormalizedName()); - expectedExternalAudit.setRESOURCE_URL("/asdc/v1/catalog/" + assetTypeEnum.getValue() + "/" + resourceDetails.getUUID() + "/resourceInstances/" + resourceDetails.getComponentInstances().get(0).getNormalizedName() + "/artifacts/" + artifactUUID); + expectedExternalAudit.setRESOURCE_URL("/sdc/v1/catalog/" + assetTypeEnum.getValue() + "/" + resourceDetails.getUUID() + "/resourceInstances/" + resourceDetails.getComponentInstances().get(0).getNormalizedName() + "/artifacts/" + artifactUUID); expectedExternalAudit.setRESOURCE_NAME(resourceDetails.getComponentInstances().get(0).getNormalizedName()); } else { expectedExternalAudit.setRESOURCE_URL(expectedExternalAudit.getRESOURCE_URL() + "/" + artifactUUID); @@ -3248,7 +3248,7 @@ public class CRUDExternalAPI extends ComponentBaseTest { ExpectedExternalAudit expectedExternalAudit = ElementFactory.getDefaultExternalArtifactAuditSuccess(assetTypeEnum, action, responseArtifact, resourceDetails); // expectedExternalAudit.setRESOURCE_URL(expectedExternalAudit.getRESOURCE_URL()+ "/" + artifactUUID); expectedExternalAudit.setRESOURCE_NAME(componentInstance.getNormalizedName()); - expectedExternalAudit.setRESOURCE_URL("/asdc/v1/catalog/" + assetTypeEnum.getValue() + "/" + resourceDetails.getUUID() + "/resourceInstances/" + componentInstance.getNormalizedName() + "/artifacts/" + artifactUUID); + expectedExternalAudit.setRESOURCE_URL("/sdc/v1/catalog/" + assetTypeEnum.getValue() + "/" + resourceDetails.getUUID() + "/resourceInstances/" + componentInstance.getNormalizedName() + "/artifacts/" + artifactUUID); AuditValidationUtils.validateExternalAudit(expectedExternalAudit, AuditingActionEnum.ARTIFACT_DELETE_BY_API.getName(), body); return restResponse; @@ -3314,13 +3314,13 @@ public class CRUDExternalAPI extends ComponentBaseTest { // // if(componentTypeEnum == ComponentTypeEnum.RESOURCE_INSTANCE) { // expectedResourceAuditJavaObject.setResourceName(resourceDetails.getComponentInstances().get(0).getName()); -// String resource_url = String.format("/asdc/v1/catalog/services/%s/resourceInstances/%s/artifacts/%s", resourceDetails.getUUID(), resourceDetails.getComponentInstances().get(0).getNormalizedName(), artifactDefinition.getArtifactUUID()); +// String resource_url = String.format("/sdc/v1/catalog/services/%s/resourceInstances/%s/artifacts/%s", resourceDetails.getUUID(), resourceDetails.getComponentInstances().get(0).getNormalizedName(), artifactDefinition.getArtifactUUID()); // expectedResourceAuditJavaObject.setRESOURCE_URL(resource_url); // // AuditValidationUtils.validateAuditDownloadExternalAPI(expectedResourceAuditJavaObject, auditAction, null, false); // } else { // expectedResourceAuditJavaObject.setResourceName(resourceDetails.getName()); -// String resource_url = String.format("/asdc/v1/catalog/services/%s/artifacts/%s", resourceDetails.getUUID(), artifactDefinition.getArtifactUUID()); +// String resource_url = String.format("/sdc/v1/catalog/services/%s/artifacts/%s", resourceDetails.getUUID(), artifactDefinition.getArtifactUUID()); // expectedResourceAuditJavaObject.setRESOURCE_URL(resource_url); // } // diff --git a/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/execute/devCI/HealthCheckAPI.java b/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/execute/devCI/HealthCheckAPI.java new file mode 100644 index 0000000000..cb36619f80 --- /dev/null +++ b/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/execute/devCI/HealthCheckAPI.java @@ -0,0 +1,68 @@ +package org.openecomp.sdc.ci.tests.execute.devCI; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import org.junit.Rule; +import org.junit.rules.TestName; +import org.openecomp.sdc.ci.tests.api.ComponentBaseTest; +import org.openecomp.sdc.ci.tests.datatypes.http.RestResponse; +import org.openecomp.sdc.ci.tests.utils.rest.BaseRestUtils; +import org.openecomp.sdc.ci.tests.utils.rest.CommonRestUtils; +import org.openecomp.sdc.common.api.HealthCheckInfo; +import org.openecomp.sdc.common.api.HealthCheckInfo.HealthCheckComponent; +import org.openecomp.sdc.common.api.HealthCheckInfo.HealthCheckStatus; +import org.openecomp.sdc.common.api.HealthCheckWrapper; +import org.testng.annotations.Test; + +import com.google.gson.Gson; + +public class HealthCheckAPI extends ComponentBaseTest { + + @Rule + public static TestName name = new TestName(); + + private static final int STATUS_CODE_GET_SUCCESS = 200; + + public HealthCheckAPI() { + super(name, HealthCheckAPI.class.getName()); + } + + @Test + public void checkAmdocsHealthCheckAPI() throws Exception { + RestResponse healthCheckInfoResponse = CommonRestUtils.getHealthCheck(); + BaseRestUtils.checkSuccess(healthCheckInfoResponse); + + Gson gson = new Gson(); + HealthCheckWrapper healthCheckInfo = gson.fromJson(healthCheckInfoResponse.getResponse(), HealthCheckWrapper.class); + assertNotNull("Health check not contains components info", healthCheckInfo.getComponentsInfo()); + HealthCheckInfo amdocsHC = healthCheckInfo.getComponentsInfo().stream().filter(x -> x.getHealthCheckComponent() == HealthCheckInfo.HealthCheckComponent.ON_BOARDING).findFirst().orElse(null); + assertNotNull("Amdocs health check not exists in Health Check info", amdocsHC); + assertEquals("Amdocs health check is down", HealthCheckInfo.HealthCheckStatus.UP, amdocsHC.getHealthCheckStatus()); + assertNotNull("Amdocs additionalInfo not exists in health check", amdocsHC.getComponentsInfo()); + Map amdocsHCComponents = amdocsHC.getComponentsInfo().stream().collect(Collectors.toMap(HealthCheckInfo::getHealthCheckComponent, HealthCheckInfo::getHealthCheckStatus)); + assertNotNull(amdocsHCComponents); + assertTrue("Amdocs health check ZU component is down or not exists", amdocsHCComponents.get(HealthCheckComponent.ZU) != null && amdocsHCComponents.get(HealthCheckComponent.ZU).equals(HealthCheckStatus.UP)); + assertTrue("Amdocs health check BE component is down or not exists", amdocsHCComponents.get(HealthCheckComponent.BE) != null && amdocsHCComponents.get(HealthCheckComponent.BE).equals(HealthCheckStatus.UP)); + assertTrue("Amdocs health check CAS component is down or not exists", amdocsHCComponents.get(HealthCheckComponent.CAS) != null && amdocsHCComponents.get(HealthCheckComponent.CAS).equals(HealthCheckStatus.UP)); + } + + @Test + public void checkCassandraHealthCheck() throws Exception { + RestResponse healthCheckInfoResponse = CommonRestUtils.getHealthCheck(); + BaseRestUtils.checkSuccess(healthCheckInfoResponse); + + Gson gson = new Gson(); + HealthCheckWrapper healthCheckInfo = gson.fromJson(healthCheckInfoResponse.getResponse(), HealthCheckWrapper.class); + assertNotNull("Health check not contains components info", healthCheckInfo.getComponentsInfo()); + HealthCheckInfo cassandraHC = healthCheckInfo.getComponentsInfo().stream().filter(x -> x.getHealthCheckComponent() == HealthCheckInfo.HealthCheckComponent.CASSANDRA).findFirst().orElse(null); + assertNotNull("Cassandra health check not exists in Health Check info", cassandraHC); + assertEquals("Cassandra health check is down", HealthCheckInfo.HealthCheckStatus.UP, cassandraHC.getHealthCheckStatus()); + } + +} \ No newline at end of file diff --git a/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/execute/general/BasicHttpAuthenticationTest.java b/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/execute/general/BasicHttpAuthenticationTest.java index bc114e22c5..c52ee470cf 100644 --- a/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/execute/general/BasicHttpAuthenticationTest.java +++ b/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/execute/general/BasicHttpAuthenticationTest.java @@ -163,13 +163,13 @@ public class BasicHttpAuthenticationTest extends ComponentBaseTest { ValidationUtils.convertToSystemName(serviceDetails.getName()), serviceDetails.getVersion(), ValidationUtils.convertToSystemName(resourceDetails.getName()), resourceDetails.getVersion(), ValidationUtils.normalizeFileName(deploymentArtifact.getArtifactName())); - expectedDownloadResourceUrl = expectedDownloadResourceUrl.substring("/asdc/".length(), + expectedDownloadResourceUrl = expectedDownloadResourceUrl.substring("/sdc/".length(), expectedDownloadResourceUrl.length()); expectedDownloadServiceUrl = String.format(Urls.DISTRIB_DOWNLOAD_SERVICE_ARTIFACT_RELATIVE_URL, ValidationUtils.convertToSystemName(serviceDetails.getName()), serviceDetails.getVersion(), ValidationUtils.normalizeFileName(deploymentArtifact.getArtifactName())); - expectedDownloadServiceUrl = expectedDownloadServiceUrl.substring("/asdc/".length(), + expectedDownloadServiceUrl = expectedDownloadServiceUrl.substring("/sdc/".length(), expectedDownloadServiceUrl.length()); sdncAdminUserDetails = ElementFactory.getDefaultUser(UserRoleEnum.ADMIN); diff --git a/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/execute/imports/CsarUtilsTest.java b/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/execute/imports/CsarUtilsTest.java index 16d3fcb092..a58ec18840 100644 --- a/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/execute/imports/CsarUtilsTest.java +++ b/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/execute/imports/CsarUtilsTest.java @@ -43,6 +43,8 @@ import org.openecomp.sdc.be.model.Resource; import org.openecomp.sdc.be.model.Service; import org.openecomp.sdc.be.model.User; import org.openecomp.sdc.ci.tests.api.ComponentBaseTest; +import org.openecomp.sdc.ci.tests.datatypes.ResourceReqDetails; +import org.openecomp.sdc.ci.tests.datatypes.ServiceReqDetails; import org.openecomp.sdc.ci.tests.datatypes.enums.ArtifactTypeEnum; import org.openecomp.sdc.ci.tests.datatypes.enums.LifeCycleStatesEnum; import org.openecomp.sdc.ci.tests.datatypes.enums.UserRoleEnum; @@ -51,7 +53,9 @@ import org.openecomp.sdc.ci.tests.utils.general.AtomicOperationUtils; import org.openecomp.sdc.ci.tests.utils.general.ElementFactory; import org.openecomp.sdc.ci.tests.utils.rest.ArtifactRestUtils; import org.openecomp.sdc.ci.tests.utils.rest.BaseRestUtils; +import org.openecomp.sdc.ci.tests.utils.rest.ResourceRestUtils; import org.openecomp.sdc.ci.tests.utils.rest.ResponseParser; +import org.openecomp.sdc.ci.tests.utils.rest.ServiceRestUtils; import org.openecomp.sdc.common.util.YamlToObjectConverter; import org.testng.annotations.Test; import org.yaml.snakeyaml.Yaml; @@ -94,13 +98,18 @@ public class CsarUtilsTest extends ComponentBaseTest { public void createResourceCsarBasicTest() throws Exception { Resource resourceVF = AtomicOperationUtils.createResourceByType(ResourceTypeEnum.VF, UserRoleEnum.DESIGNER, true).left().value(); + User sdncModifierDetails = ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER); + resourceVF = (Resource) AtomicOperationUtils .changeComponentState(resourceVF, UserRoleEnum.DESIGNER, LifeCycleStatesEnum.CERTIFY, true).getLeft(); - User sdncModifierDetails = ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER); byte[] downloadCSAR = downloadCSAR(sdncModifierDetails, resourceVF); csarBasicValidation(resourceVF, downloadCSAR); + + validateVFCsar(resourceVF, downloadCSAR, 1, 0, 0, 0, 0, 0, 0); + + } @Test(enabled = true) @@ -138,6 +147,7 @@ public class CsarUtilsTest extends ComponentBaseTest { Resource resourceVF1 = AtomicOperationUtils.createResourceByType(ResourceTypeEnum.VF, UserRoleEnum.DESIGNER, true).left().value(); + AtomicOperationUtils.uploadArtifactByType(ArtifactTypeEnum.YANG_XML, resourceVF1, UserRoleEnum.DESIGNER, true, true); AtomicOperationUtils.uploadArtifactByType(ArtifactTypeEnum.HEAT_ARTIFACT, resourceVF1, UserRoleEnum.DESIGNER, true, true); @@ -157,7 +167,7 @@ public class CsarUtilsTest extends ComponentBaseTest { public void createResourceCsarInclInformationalArtTest() throws Exception { Resource resourceVF1 = AtomicOperationUtils.createResourceByType(ResourceTypeEnum.VF, UserRoleEnum.DESIGNER, true).left().value(); - + AtomicOperationUtils.uploadArtifactByType(ArtifactTypeEnum.YANG_XML, resourceVF1, UserRoleEnum.DESIGNER, false, true); AtomicOperationUtils.uploadArtifactByType(ArtifactTypeEnum.HEAT, resourceVF1, UserRoleEnum.DESIGNER, false, true); @@ -173,6 +183,59 @@ public class CsarUtilsTest extends ComponentBaseTest { validateVFCsar(resourceVF1, downloadCSAR, 1, 0, 0, 0, 1, 1, 0); } + @Test(enabled = true) + public void createServiceCsarNotMandatoryMetadataFieldsTest() throws Exception { + + Service service = AtomicOperationUtils.createDefaultService(UserRoleEnum.DESIGNER, true).left().value(); + User sdncModifierDetails = ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER); + + service.setServiceType("serviceTypeTest"); + service.setServiceRole("serviceRoleTest"); + ServiceRestUtils.updateService(new ServiceReqDetails(service), sdncModifierDetails); + + Resource resourceVF1 = AtomicOperationUtils.createResourceByType(ResourceTypeEnum.VF, UserRoleEnum.DESIGNER, true).left().value(); + Resource resourceVF2 = AtomicOperationUtils.createResourceByType(ResourceTypeEnum.VF, UserRoleEnum.DESIGNER, true).left().value(); + + resourceVF1 = (Resource) AtomicOperationUtils + .changeComponentState(resourceVF1, UserRoleEnum.DESIGNER, LifeCycleStatesEnum.CERTIFY, true).getLeft(); + + resourceVF2 = (Resource) AtomicOperationUtils + .changeComponentState(resourceVF2, UserRoleEnum.DESIGNER, LifeCycleStatesEnum.CERTIFY, true).getLeft(); + + AtomicOperationUtils.addComponentInstanceToComponentContainer(resourceVF1, service, UserRoleEnum.DESIGNER, true); + AtomicOperationUtils.addComponentInstanceToComponentContainer(resourceVF2, service, UserRoleEnum.DESIGNER, true); + + service = (Service) AtomicOperationUtils.changeComponentState(service, UserRoleEnum.DESIGNER, LifeCycleStatesEnum.CERTIFY, true).getLeft(); + + byte[] downloadCSAR = downloadCSAR(sdncModifierDetails, service); + + csarBasicValidation(service, downloadCSAR); + + validateServiceCsar(resourceVF1, resourceVF2, service, downloadCSAR, 3, 3, 0, 0); + } + + @Test(enabled = true) + public void createResourceCsarNotMandatoryMetadataFieldsTest() throws Exception { + + Resource resourceVF = AtomicOperationUtils.createResourceByType(ResourceTypeEnum.VF, UserRoleEnum.DESIGNER, true).left().value(); + User sdncModifierDetails = ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER); + + resourceVF.setResourceVendorModelNumber("modelNumberTest"); + ResourceRestUtils.updateResourceMetadata(new ResourceReqDetails(resourceVF), sdncModifierDetails, resourceVF.getUniqueId()); + + resourceVF = (Resource) AtomicOperationUtils + .changeComponentState(resourceVF, UserRoleEnum.DESIGNER, LifeCycleStatesEnum.CERTIFY, true).getLeft(); + + byte[] downloadCSAR = downloadCSAR(sdncModifierDetails, resourceVF); + + csarBasicValidation(resourceVF, downloadCSAR); + + validateVFCsar(resourceVF, downloadCSAR, 1, 0, 0, 0, 0, 0, 0); + + + } + + private void csarBasicValidation(Component mainComponent, byte[] downloadCSAR) { try (ByteArrayInputStream ins = new ByteArrayInputStream(downloadCSAR); ZipInputStream zip = new ZipInputStream(ins);) { @@ -234,11 +297,12 @@ public class CsarUtilsTest extends ComponentBaseTest { while ((len = zip.read(buffer)) > 0) { sb.append(new String(buffer, 0, len)); } - assertTrue(nextEntry.getName().equals("csar.meta")); - + assertTrue(nextEntry.getName().equals("csar.meta")); readNextEntry(sb, len, buffer, zip); nextEntry = zip.getNextEntry(); assertTrue(nextEntry.getName().equals("TOSCA-Metadata/TOSCA.meta")); + readNextEntry(sb, len, buffer, zip); + YamlToObjectConverter yamlToObjectConverter = new YamlToObjectConverter(); @@ -483,15 +547,24 @@ public class CsarUtilsTest extends ComponentBaseTest { String UUID = (String) metadata.get("UUID"); assertNotNull(UUID); - assertEquals("Validate component invariantUUID", component.getUUID(), UUID); + assertEquals("Validate component UUID", component.getUUID(), UUID); String type = (String) metadata.get("type"); assertNotNull(type); if (component.getComponentType().equals(ComponentTypeEnum.SERVICE)) { assertEquals("Validate component type", component.getComponentType().getValue(), type); + String serviceType = (String) metadata.get("serviceType"); + assertNotNull(serviceType); + assertEquals("Validate service type", ((Service )component).getServiceType(), serviceType); + String serviceRole = (String) metadata.get("serviceRole"); + assertNotNull(serviceRole); + assertEquals("Validate service role", ((Service )component).getServiceRole(), serviceRole); } else { assertEquals("Validate component type", ((Resource) component).getResourceType(), ResourceTypeEnum.valueOf(type)); + String resourceVendorModelNumber = (String) metadata.get("resourceVendorModelNumber"); + assertNotNull(resourceVendorModelNumber); + assertEquals("Validate resource vendor model number", ((Resource )component).getResourceVendorModelNumber(), resourceVendorModelNumber); } } diff --git a/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/execute/imports/ExportToscaTest.java b/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/execute/imports/ExportToscaTest.java index 6bf0786a4b..5f0cbaf1c7 100644 --- a/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/execute/imports/ExportToscaTest.java +++ b/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/execute/imports/ExportToscaTest.java @@ -156,7 +156,7 @@ public class ExportToscaTest extends ComponentBaseTest { assertNotNull(vfModulesInRes); assertNotNull(groups); - assertEquals("Validate count of vf module instanses", vfModulesInRes.size(), groups.size()); + assertEquals("Validate count of vf module instances", vfModulesInRes.size(), groups.size()); vfModulesInRes.forEach(modInRes -> { validateVfModuleVsInstance(normalizedName, groups, modInRes); diff --git a/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/execute/resource/GetLeftPaletteTest.java b/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/execute/resource/GetLeftPaletteTest.java new file mode 100644 index 0000000000..4ad008633a --- /dev/null +++ b/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/execute/resource/GetLeftPaletteTest.java @@ -0,0 +1,193 @@ +package org.openecomp.sdc.ci.tests.execute.resource; + +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; +import org.json.simple.JSONValue; +import org.junit.rules.TestName; +import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum; +import org.openecomp.sdc.be.model.User; +import org.openecomp.sdc.ci.tests.api.ComponentBaseTest; +import org.openecomp.sdc.ci.tests.datatypes.ResourceReqDetails; +import org.openecomp.sdc.ci.tests.datatypes.enums.LifeCycleStatesEnum; +import org.openecomp.sdc.ci.tests.datatypes.enums.ResourceCategoryEnum; +import org.openecomp.sdc.ci.tests.datatypes.enums.UserRoleEnum; +import org.openecomp.sdc.ci.tests.datatypes.http.RestResponse; +import org.openecomp.sdc.ci.tests.utils.general.ElementFactory; +import org.openecomp.sdc.ci.tests.utils.rest.LifecycleRestUtils; +import org.openecomp.sdc.ci.tests.utils.rest.ResourceRestUtils; +import org.openecomp.sdc.ci.tests.utils.rest.ResponseParser; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testng.AssertJUnit; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.AfterClass; +import org.testng.annotations.Test; + +import java.io.IOException; +import java.util.Arrays; + +import static org.testng.AssertJUnit.assertTrue; + +/** + * Created by chaya on 6/15/2017. + */ +public class GetLeftPaletteTest extends ComponentBaseTest { + + private static Logger logger = LoggerFactory.getLogger(GetLeftPaletteTest.class.getName()); + protected User designerDetails = ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER); + protected ResourceReqDetails vlResourceDetails; + protected ResourceReqDetails cpResourceDetails; + protected ResourceReqDetails vfcResourceDetails; + protected ResourceReqDetails vfcmtResourceDetails; + protected ResourceReqDetails vfResourceDetails; + + + public static TestName name = new TestName(); + + public GetLeftPaletteTest() { + super(name, GetLeftPaletteTest.class.getName()); + } + + @BeforeClass + public void setUp() throws Exception { + // create VL + vlResourceDetails = createResource(vlResourceDetails, "vlRes", ResourceTypeEnum.VL); + checkInResource(vlResourceDetails); + + // create CP + cpResourceDetails = createResource(cpResourceDetails, "cpRes", ResourceTypeEnum.CP); + checkInResource(cpResourceDetails); + + // create VFC + vfcResourceDetails = createResource(vfcResourceDetails, "vfcRes", ResourceTypeEnum.VFC); + checkInResource(vfcResourceDetails); + + // create VFCMT + vfcmtResourceDetails = createResource(vfcmtResourceDetails, "vfcmtRes", ResourceTypeEnum.VFCMT); + checkInResource(vfcmtResourceDetails); + + // create VF + vfResourceDetails = createResource(vfResourceDetails, "vfRes", ResourceTypeEnum.VF); + checkInResource(vfResourceDetails); + } + + + + @Test + public void testGetLeftPaletteForPNF() throws IOException { + + RestResponse getResourceLatestVersionResponse = ResourceRestUtils.getResourceLatestVersionListMetadata(designerDetails, "PNF"); + assertTrue("response code is not 200, returned :" + getResourceLatestVersionResponse.getErrorCode(), + getResourceLatestVersionResponse.getErrorCode() == 200); + + String json = getResourceLatestVersionResponse.getResponse(); + JSONArray jsonResp = (JSONArray) JSONValue.parse(json); + + AssertJUnit.assertTrue("check vlResource is in response", + isComponentInArray(vlResourceDetails.getUniqueId(), jsonResp)); + + AssertJUnit.assertTrue("check cpResource is in response", + isComponentInArray(cpResourceDetails.getUniqueId(), jsonResp)); + + AssertJUnit.assertFalse("check vfcResource is not in response", + isComponentInArray(vfcResourceDetails.getUniqueId(), jsonResp)); + + AssertJUnit.assertFalse("check vfResource is not in response", + isComponentInArray(vfResourceDetails.getUniqueId(), jsonResp)); + + AssertJUnit.assertFalse("check vfcmtResource is not in response", + isComponentInArray(vfcmtResourceDetails.getUniqueId(), jsonResp)); + + } + + @Test + public void testGetLeftPaletteForVF() throws IOException { + + RestResponse getResourceLatestVersionResponse = ResourceRestUtils.getResourceLatestVersionListMetadata(designerDetails, "VF"); + assertTrue("response code is not 200, returned :" + getResourceLatestVersionResponse.getErrorCode(), + getResourceLatestVersionResponse.getErrorCode() == 200); + + String json = getResourceLatestVersionResponse.getResponse(); + JSONArray jsonResp = (JSONArray) JSONValue.parse(json); + + AssertJUnit.assertTrue("check vlResource is in response", + isComponentInArray(vlResourceDetails.getUniqueId(), jsonResp)); + + AssertJUnit.assertTrue("check cpResource is in response", + isComponentInArray(cpResourceDetails.getUniqueId(), jsonResp)); + + AssertJUnit.assertTrue("check vfcResource is not in response", + isComponentInArray(vfcResourceDetails.getUniqueId(), jsonResp)); + + AssertJUnit.assertFalse("check vfResource is not in response", + isComponentInArray(vfResourceDetails.getUniqueId(), jsonResp)); + + AssertJUnit.assertFalse("check vfcmtResource is not in response", + isComponentInArray(vfcmtResourceDetails.getUniqueId(), jsonResp)); + + } + + @Test + public void testGetLeftPaletteForService() throws IOException { + + RestResponse getResourceLatestVersionResponse = ResourceRestUtils.getResourceLatestVersionListMetadata(designerDetails, "SERVICE"); + assertTrue("response code is not 200, returned :" + getResourceLatestVersionResponse.getErrorCode(), + getResourceLatestVersionResponse.getErrorCode() == 200); + + String json = getResourceLatestVersionResponse.getResponse(); + JSONArray jsonResp = (JSONArray) JSONValue.parse(json); + + AssertJUnit.assertTrue("check vlResource is in response", + isComponentInArray(vlResourceDetails.getUniqueId(), jsonResp)); + + AssertJUnit.assertTrue("check cpResource is in response", + isComponentInArray(cpResourceDetails.getUniqueId(), jsonResp)); + + AssertJUnit.assertFalse("check vfcResource is not in response", + isComponentInArray(vfcResourceDetails.getUniqueId(), jsonResp)); + + AssertJUnit.assertTrue("check vfResource is not in response", + isComponentInArray(vfResourceDetails.getUniqueId(), jsonResp)); + + AssertJUnit.assertFalse("check vfcmtResource is not in response", + isComponentInArray(vfcmtResourceDetails.getUniqueId(), jsonResp)); + + } + + private ResourceReqDetails createResource(ResourceReqDetails resDetails, String name, ResourceTypeEnum resType) throws Exception { + resDetails = new ResourceReqDetails(name, "desc",Arrays.asList(name), "Generic", Arrays.asList("tosca.nodes.Root"), "c", "1", "111", "myIcon", resType.name()); + resDetails.addCategoryChain(ResourceCategoryEnum.GENERIC_NETWORK_ELEMENTS.getCategory(), + ResourceCategoryEnum.GENERIC_NETWORK_ELEMENTS.getSubCategory()); + RestResponse response = ResourceRestUtils.createResource(resDetails, designerDetails); + assertTrue("response code is not 200, returned :" + response.getErrorCode(), + response.getErrorCode() == 201); + resDetails.setUniqueId(ResponseParser.getUniqueIdFromResponse(response)); + return resDetails; + } + + private void checkInResource(ResourceReqDetails resDetails) throws IOException { + RestResponse checkInResponse = LifecycleRestUtils.changeResourceState(resDetails, designerDetails, "0.1", + LifeCycleStatesEnum.CHECKIN); + AssertJUnit.assertEquals("check in operation failed", 200, checkInResponse.getErrorCode().intValue()); + + } + + protected boolean isComponentInArray(String id, JSONArray component) { + for (int i = 0; i < component.size(); i++) { + JSONObject jobject = (JSONObject) component.get(i); + if (jobject.get("uniqueId").toString().equals(id.toLowerCase())) { + return true; + } + } + return false; + } + + @AfterClass + public void tearDown() throws IOException { + ResourceRestUtils.deleteResource(vlResourceDetails.getUniqueId(), designerDetails.getUserId()); + ResourceRestUtils.deleteResource(cpResourceDetails.getUniqueId(), designerDetails.getUserId()); + ResourceRestUtils.deleteResource(vfcResourceDetails.getUniqueId(), designerDetails.getUserId()); + ResourceRestUtils.deleteResource(vfcmtResourceDetails.getUniqueId(), designerDetails.getUserId()); + ResourceRestUtils.deleteResource(vfResourceDetails.getUniqueId(), designerDetails.getUserId()); + } +} diff --git a/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/execute/service/ServiceComponentInstanceCRUDTest.java b/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/execute/service/ServiceComponentInstanceCRUDTest.java index 149febf05c..2939a8a09e 100644 --- a/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/execute/service/ServiceComponentInstanceCRUDTest.java +++ b/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/execute/service/ServiceComponentInstanceCRUDTest.java @@ -34,13 +34,7 @@ import org.json.JSONArray; import org.junit.rules.TestName; import org.openecomp.sdc.be.dao.api.ActionStatus; import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; -import org.openecomp.sdc.be.model.CapReqDef; -import org.openecomp.sdc.be.model.CapabilityDefinition; -import org.openecomp.sdc.be.model.Component; -import org.openecomp.sdc.be.model.ComponentInstance; -import org.openecomp.sdc.be.model.RequirementCapabilityRelDef; -import org.openecomp.sdc.be.model.RequirementDefinition; -import org.openecomp.sdc.be.model.User; +import org.openecomp.sdc.be.model.*; import org.openecomp.sdc.ci.tests.api.ComponentInstanceBaseTest; import org.openecomp.sdc.ci.tests.api.Urls; import org.openecomp.sdc.ci.tests.datatypes.ArtifactReqDetails; @@ -93,10 +87,13 @@ public class ServiceComponentInstanceCRUDTest extends ComponentInstanceBaseTest createAtomicResource(resourceDetailsVFC_01); createAtomicResource(resourceDetailsVFC_02); createAtomicResource(resourceDetailsCP_01); + LifecycleRestUtils.changeResourceState(resourceDetailsCP_01, sdncAdminDetails, "0.1", + LifeCycleStatesEnum.CHECKIN); createAtomicResource(resourceDetailsVL_01); createAtomicResource(resourceDetailsVL_02); createVF(resourceDetailsVF_01); createVF(resourceDetailsVF_02); + createPNF(resourceDetailsPNF_01); createService(serviceDetails_01); certifyResource(resourceDetailsVFC_01); certifyResource(resourceDetailsVFC_02); @@ -173,6 +170,10 @@ public class ServiceComponentInstanceCRUDTest extends ComponentInstanceBaseTest return createVFInstance(containerDetails, compInstOriginDetails, modifier); } + private RestResponse createCheckedinPNFInstance(ServiceReqDetails containerDetails, ResourceReqDetails compInstOriginDetails, User modifier) throws Exception { + return createCheckedinVFInstance(containerDetails, compInstOriginDetails, modifier); + } + private RestResponse createCheckedinAtomicInstanceForService(ServiceReqDetails containerDetails, ResourceReqDetails compInstOriginDetails, User modifier) throws Exception { changeResourceLifecycleState(compInstOriginDetails, compInstOriginDetails.getCreatorUserId(), LifeCycleStatesEnum.CHECKIN); return createAtomicInstanceForService(containerDetails, compInstOriginDetails, modifier); @@ -204,6 +205,16 @@ public class ServiceComponentInstanceCRUDTest extends ComponentInstanceBaseTest getComponentAndValidateRIs(serviceDetails_01, 2, 0); } + @Test + public void createPNFInstanceSuccessfullyTest() throws Exception { + RestResponse createPNFInstResp = createCheckedinPNFInstance(serviceDetails_01, resourceDetailsPNF_01, sdncDesignerDetails); + ResourceRestUtils.checkCreateResponse(createPNFInstResp); + getComponentAndValidateRIs(serviceDetails_01, 1, 0); +// createVFInstResp = createCheckedinVFInstance(serviceDetails_01, resourceDetailsVF_02, sdncDesignerDetails); +// ResourceRestUtils.checkCreateResponse(createVFInstResp); +// getComponentAndValidateRIs(serviceDetails_01, 2, 0); + } + @Test public void createVFAndAtomicInstanceTest() throws Exception { RestResponse createVFInstResp = createCheckedinVFInstance(serviceDetails_01, resourceDetailsVF_01, sdncDesignerDetails); @@ -217,6 +228,56 @@ public class ServiceComponentInstanceCRUDTest extends ComponentInstanceBaseTest getComponentAndValidateRIs(serviceDetails_01, 4, 0); } + @Test + public void createPNFAndAtomicInstanceTest() throws Exception { + RestResponse createPNFInstResp = createCheckedinPNFInstance(serviceDetails_01, resourceDetailsPNF_01, sdncDesignerDetails); + ResourceRestUtils.checkCreateResponse(createPNFInstResp); + RestResponse createVLInstResp = createCheckedinAtomicInstanceForService(serviceDetails_01, resourceDetailsVL_01, sdncDesignerDetails); + ResourceRestUtils.checkCreateResponse(createVLInstResp); + getComponentAndValidateRIs(serviceDetails_01, 2, 0); + + + } + + private String createCpInstance() throws Exception { + // Create CP instance + RestResponse createAtomicResourceInstance = createAtomicInstanceForVF(resourceDetailsPNF_01, + resourceDetailsCP_01, sdncDesignerDetails); + ResourceRestUtils.checkCreateResponse(createAtomicResourceInstance); + getComponentAndValidateRIs(resourceDetailsPNF_01, 1, 0); + return ResponseParser.getUniqueIdFromResponse(createAtomicResourceInstance); + } + + @Test + public void createPNFAndAtomicInstanceAssociatedTest() throws Exception { + reqOwnerId = createCpInstance(); + RestResponse createPNFInstResp = createCheckedinPNFInstance(serviceDetails_01, resourceDetailsPNF_01, sdncDesignerDetails); + ResourceRestUtils.checkCreateResponse(createPNFInstResp); + String fromCompInstId = ResponseParser.getUniqueIdFromResponse(createPNFInstResp); + RestResponse createVLInstResp = createCheckedinAtomicInstanceForService(serviceDetails_01, resourceDetailsVL_01, sdncDesignerDetails); + ResourceRestUtils.checkCreateResponse(createVLInstResp); + capOwnerId = ResponseParser.getUniqueIdFromResponse(createVLInstResp); + String toCompInstId = ResponseParser.getUniqueIdFromResponse(createVLInstResp); + + String capType = "tosca.capabilities.network.Linkable"; + String reqName = "link"; + + RestResponse getResourceResponse = ComponentRestUtils.getComponentRequirmentsCapabilities(sdncDesignerDetails, serviceDetails_01); + ResourceRestUtils.checkSuccess(getResourceResponse); + CapReqDef capReqDef = ResponseParser.parseToObjectUsingMapper(getResourceResponse.getResponse(), CapReqDef.class); + List capList = capReqDef.getCapabilities().get(capType); + List reqList = capReqDef.getRequirements().get(capType); + + RequirementCapabilityRelDef requirementDef = getReqCapRelation(fromCompInstId, toCompInstId, capType, reqName, capList, reqList); + + associateComponentInstancesForService(requirementDef, serviceDetails_01, sdncDesignerDetails); + getResourceResponse = ComponentRestUtils.getComponentRequirmentsCapabilities(sdncDesignerDetails, serviceDetails_01); + capReqDef = ResponseParser.parseToObjectUsingMapper(getResourceResponse.getResponse(), CapReqDef.class); + List list = capReqDef.getRequirements().get(capType); +// AssertJUnit.assertEquals("Check requirement", null, list); + getComponentAndValidateRIsOnly(serviceDetails_01, 2, 1); + } + @Test public void deleteAtomicInstanceTest() throws Exception { RestResponse createVFInstResp = createCheckedinVFInstance(serviceDetails_01, resourceDetailsVF_01, sdncDesignerDetails); diff --git a/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/utils/DistributionUtils.java b/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/utils/DistributionUtils.java index 85b01e6d2b..6bfa1b8e94 100644 --- a/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/utils/DistributionUtils.java +++ b/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/utils/DistributionUtils.java @@ -63,7 +63,7 @@ import org.openecomp.sdc.ci.tests.utils.rest.ServiceRestUtils; // public class DistributionUtils { - final static String serviceDistributionSuffix = "/asdc/v1/catalog/services/"; + final static String serviceDistributionSuffix = "/sdc/v1/catalog/services/"; public static ServiceDistributionStatus getLatestServiceDistributionObject(Service service) throws IOException, ParseException { ServiceDistributionStatus serviceDistributionStatus = null; @@ -124,13 +124,13 @@ import org.openecomp.sdc.ci.tests.utils.rest.ServiceRestUtils; } private static String buildServiceDeploymentUrl(Service service, String artifactName, String artifactUUID) { -// format "/asdc/v1/catalog/services/" + service.getSystemName() + "/" + service.getVersion() + "/artifacts/AAI-" + service.getName() + "-service-1.xml" +// format "/sdc/v1/catalog/services/" + service.getSystemName() + "/" + service.getVersion() + "/artifacts/AAI-" + service.getName() + "-service-1.xml" return serviceDistributionSuffix + service.getSystemName() + "/" + service.getVersion() + "/artifacts/" + artifactName; } public static String buildResourceInstanceDeploymentUrl(Service service, String artifactName, String artifactUUID){ -// /asdc/v1/catalog/services/Servicefordistribution/1.0 /resourceInstances/nestedfrommarina2 /artifacts/FEAdd_On_Module_vProbeLauncher.yaml +// /sdc/v1/catalog/services/Servicefordistribution/1.0 /resourceInstances/nestedfrommarina2 /artifacts/FEAdd_On_Module_vProbeLauncher.yaml String resourceInstanceNormalizedName = getResourceInstanceNormalizeName(service, artifactName, artifactUUID ); return serviceDistributionSuffix + service.getSystemName() + "/" + service.getVersion() + "/resourceInstances/" + resourceInstanceNormalizedName +"/artifacts/" + artifactName; } diff --git a/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/utils/general/ElementFactory.java b/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/utils/general/ElementFactory.java index c06cb570f8..1578b6eba0 100644 --- a/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/utils/general/ElementFactory.java +++ b/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/utils/general/ElementFactory.java @@ -689,7 +689,7 @@ public class ElementFactory { ExpectedExternalAudit expectedExternalAudit = new ExpectedExternalAudit(); expectedExternalAudit.setACTION(action.getName()); expectedExternalAudit.setCONSUMER_ID("ci"); - expectedExternalAudit.setRESOURCE_URL("/asdc/v1/catalog/" + assetType.getValue() + (query == null ? "" : query)); + expectedExternalAudit.setRESOURCE_URL("/sdc/v1/catalog/" + assetType.getValue() + (query == null ? "" : query)); expectedExternalAudit.setSTATUS("200"); expectedExternalAudit.setDESC("OK"); return expectedExternalAudit; @@ -752,7 +752,7 @@ public class ElementFactory { expectedResourceAuditJavaObject.setResourceName(resourceName); expectedResourceAuditJavaObject.setResourceType("Resource"); expectedResourceAuditJavaObject.setCONSUMER_ID("ci"); - expectedResourceAuditJavaObject.setRESOURCE_URL("/asdc/v1/catalog/resources"); + expectedResourceAuditJavaObject.setRESOURCE_URL("/sdc/v1/catalog/resources"); expectedResourceAuditJavaObject.setMODIFIER(""); expectedResourceAuditJavaObject.setPrevVersion(""); expectedResourceAuditJavaObject.setCurrVersion("0.1"); @@ -769,7 +769,7 @@ public class ElementFactory { public static ExpectedExternalAudit getDefaultExternalArtifactAuditSuccess(AssetTypeEnum assetType, AuditingActionEnum action, ArtifactDefinition artifactDefinition, String componentUUID, String resourceInstanceName) { ExpectedExternalAudit expectedExternalArtifactAudit = getDefaultExternalArtifactAuditSuccess(assetType, action, artifactDefinition, componentUUID); - expectedExternalArtifactAudit.setRESOURCE_URL("/asdc/v1/catalog/" + assetType.getValue() + "/" + componentUUID + "/resourceInstances/" + resourceInstanceName + "/artifacts"); + expectedExternalArtifactAudit.setRESOURCE_URL("/sdc/v1/catalog/" + assetType.getValue() + "/" + componentUUID + "/resourceInstances/" + resourceInstanceName + "/artifacts"); return expectedExternalArtifactAudit; } @@ -794,7 +794,7 @@ public class ElementFactory { String resourceInstanceName) { ExpectedExternalAudit expectedExternalArtifactAudit = getDefaultExternalArtifactAuditFailure(assetType, action, artifactDefinition, componentUUID, errorInfo, variables); - expectedExternalArtifactAudit.setRESOURCE_URL("/asdc/v1/catalog/" + assetType.getValue() + "/" + componentUUID + "/resourceInstances/" + resourceInstanceName + "/artifacts"); + expectedExternalArtifactAudit.setRESOURCE_URL("/sdc/v1/catalog/" + assetType.getValue() + "/" + componentUUID + "/resourceInstances/" + resourceInstanceName + "/artifacts"); return expectedExternalArtifactAudit; } diff --git a/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/utils/rest/AssetRestUtils.java b/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/utils/rest/AssetRestUtils.java index 7272e345ae..5565780dd5 100644 --- a/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/utils/rest/AssetRestUtils.java +++ b/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/utils/rest/AssetRestUtils.java @@ -76,10 +76,10 @@ public class AssetRestUtils extends BaseRestUtils { static final String contentTypeHeaderData = "application/json"; static final String acceptHeaderDate = "application/json"; static final String basicAuthentication = "Basic Y2k6MTIzNDU2"; - // /asdc/v1/catalog/{services/resources}/{componentUUID}/artifacts/{artifactUUID} - static final String COMPONENT_ARTIFACT_URL = "/asdc/v1/catalog/%s/%s/artifacts/%s"; - // /asdc/v1/catalog/{services/resources}/{componentUUID}/resourceInstances/{resourceInstanceName}/artifacts/{artifactUUID} - static final String RESOURCE_INSTANCE_ARTIFACT_URL = "/asdc/v1/catalog/%s/%s/resourceInstances/%s/artifacts/%s"; + // /sdc/v1/catalog/{services/resources}/{componentUUID}/artifacts/{artifactUUID} + static final String COMPONENT_ARTIFACT_URL = "/sdc/v1/catalog/%s/%s/artifacts/%s"; + // /sdc/v1/catalog/{services/resources}/{componentUUID}/resourceInstances/{resourceInstanceName}/artifacts/{artifactUUID} + static final String RESOURCE_INSTANCE_ARTIFACT_URL = "/sdc/v1/catalog/%s/%s/resourceInstances/%s/artifacts/%s"; public static HttpResponse getComponentToscaModel(AssetTypeEnum assetType, String uuid) throws IOException { Config config = Utils.getConfig(); @@ -338,7 +338,7 @@ public class AssetRestUtils extends BaseRestUtils { // assertNotNull("Expected artifact asset resourceInvariantUUID // is null", // resourceInstanceAssetStructure.getResourceInvariantUUID()); - // String expectedArtifactUrl = "/asdc/v1/catalog/" + + // String expectedArtifactUrl = "/sdc/v1/catalog/" + // assetType.getValue() + "/" + componentUuid + "/artifacts/" + // componentDeploymentArtifactValue.getArtifactUUID(); String expectedArtifactUrl = ""; diff --git a/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/utils/rest/CatalogRestUtils.java b/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/utils/rest/CatalogRestUtils.java index a265639804..522a91f7d3 100644 --- a/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/utils/rest/CatalogRestUtils.java +++ b/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/utils/rest/CatalogRestUtils.java @@ -21,8 +21,7 @@ package org.openecomp.sdc.ci.tests.utils.rest; import java.io.IOException; -import java.util.HashMap; -import java.util.Map; +import java.util.*; import org.openecomp.sdc.ci.tests.api.Urls; import org.openecomp.sdc.ci.tests.config.Config; @@ -52,6 +51,15 @@ public class CatalogRestUtils extends BaseRestUtils { return sendGet(url, userId); } + public static RestResponse getCatalog(String userId, List excludeList) throws IOException { + Config config = Utils.getConfig(); + String url = String.format(Urls.GET_CATALOG_DATA, config.getCatalogBeHost(), config.getCatalogBePort()); + StringBuilder sb = new StringBuilder(); + sb.append(url).append("?"); + Optional.ofNullable(excludeList).orElse(Collections.emptyList()).forEach(type -> sb.append("excludeTypes="+type+"&")); + return sendGet(sb.toString(), userId); + } + public static RestResponse getAllCategoriesTowardsCatalogBe() throws IOException { Config config = Utils.getConfig(); diff --git a/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/utils/rest/CommonRestUtils.java b/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/utils/rest/CommonRestUtils.java new file mode 100644 index 0000000000..bc807df7fa --- /dev/null +++ b/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/utils/rest/CommonRestUtils.java @@ -0,0 +1,23 @@ +package org.openecomp.sdc.ci.tests.utils.rest; + +import org.openecomp.sdc.ci.tests.api.Urls; +import org.openecomp.sdc.ci.tests.config.Config; +import org.openecomp.sdc.ci.tests.utils.Utils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.openecomp.sdc.ci.tests.datatypes.http.RestResponse; + +public class CommonRestUtils extends BaseRestUtils { + + private static Logger logger = LoggerFactory.getLogger(CommonRestUtils.class.getName()); + + public static RestResponse getHealthCheck() throws Exception { + + Config config = Utils.getConfig(); + String url = String.format(Urls.GET_HEALTH_CHECK_VIA_PROXY, config.getCatalogFeHost(), config.getCatalogFePort()); + + return sendGet(url, null); + + } +} diff --git a/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/utils/rest/ResourceRestUtils.java b/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/utils/rest/ResourceRestUtils.java index 90371662a7..b17deb3756 100644 --- a/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/utils/rest/ResourceRestUtils.java +++ b/asdc-tests/src/main/java/org/openecomp/sdc/ci/tests/utils/rest/ResourceRestUtils.java @@ -254,6 +254,20 @@ public class ResourceRestUtils extends BaseRestUtils { return sendGet(url, sdncModifierDetails.getUserId()); } + public static RestResponse getResourceLatestVersionListMetadata(User sdncModifierDetails, String internalComponentType) throws IOException { + + Config config = Utils.getConfig(); + StringBuilder sb = new StringBuilder(); + String url = String.format(Urls.GET_RESOURCE_METADATA_lATEST_VERSION, config.getCatalogBeHost(), + config.getCatalogBePort()); + sb.append(url); + if (internalComponentType != null && !internalComponentType.isEmpty()) { + sb.append("?internalComponentType="+internalComponentType); + } + return sendGet(sb.toString(), sdncModifierDetails.getUserId()); + + } + public static RestResponse getResourceByNameAndVersion(String userId, String resourceName, String resourceVersion) throws IOException { diff --git a/asdctool/pom.xml b/asdctool/pom.xml index da1b9160fd..40eebbab5f 100644 --- a/asdctool/pom.xml +++ b/asdctool/pom.xml @@ -75,6 +75,12 @@ compile + + commons-cli + commons-cli + 1.4 + + org.eclipse.jetty jetty-servlet @@ -417,6 +423,20 @@ ${junit.version} test + + + org.testng + testng + ${testng.version} + test + + + + org.mockito + mockito-all + ${mockito.version} + test + diff --git a/asdctool/src/main/java/org/openecomp/sdc/asdctool/impl/migration/v1604/ServiceMigration.java b/asdctool/src/main/java/org/openecomp/sdc/asdctool/impl/migration/v1604/ServiceMigration.java index ee5171d8ab..0ef435e1c3 100644 --- a/asdctool/src/main/java/org/openecomp/sdc/asdctool/impl/migration/v1604/ServiceMigration.java +++ b/asdctool/src/main/java/org/openecomp/sdc/asdctool/impl/migration/v1604/ServiceMigration.java @@ -706,7 +706,7 @@ public class ServiceMigration { Either, TitanOperationStatus> reqInst = titanGenericDao.getParentNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.RelationshipInst), rel.getUniqueId(), GraphEdgeLabels.RELATIONSHIP_INST, NodeTypeEnum.ResourceInstance, ComponentInstanceData.class); if (reqInst.isRight()) { - log.debug("updateRelations : failed to fetch capabilty component instance for relation {}, error {}", rel.getUniqueId(), reqInst.right().value()); + log.debug("updateRelations : failed to fetch capability component instance for relation {}, error {}", rel.getUniqueId(), reqInst.right().value()); return false; } ComponentInstanceData requirementInstanceData = reqInst.left().value().getLeft(); @@ -917,6 +917,9 @@ public class ServiceMigration { case CP: originType = OriginTypeEnum.CP; break; + case CVFC: + originType = OriginTypeEnum.CVFC; + break; default: log.debug("updateComponentInstanceType failed, no supported resource type {} for origin resource with id {}", resourceType, originId); return false; diff --git a/asdctool/src/main/java/org/openecomp/sdc/asdctool/impl/migration/v1707/Migration1707ArtifactUuidFix.java b/asdctool/src/main/java/org/openecomp/sdc/asdctool/impl/migration/v1707/Migration1707ArtifactUuidFix.java index c14301ae5e..b3f138241e 100644 --- a/asdctool/src/main/java/org/openecomp/sdc/asdctool/impl/migration/v1707/Migration1707ArtifactUuidFix.java +++ b/asdctool/src/main/java/org/openecomp/sdc/asdctool/impl/migration/v1707/Migration1707ArtifactUuidFix.java @@ -103,10 +103,10 @@ public class Migration1707ArtifactUuidFix { if (runMode.equals("fix") || runMode.equals("fix_only_services")) { log.info("Mode {}. Start fix", runMode); if (fix(vfLst, serviceList) == false) { - log.info("Mode {}. Fix finished withh failure", runMode); + log.info("Mode {}. Fix finished with failure", runMode); return false; } - log.info("Mode {}. Fix finished withh success", runMode); + log.info("Mode {}. Fix finished with success", runMode); } return true; diff --git a/asdctool/src/main/java/org/openecomp/sdc/asdctool/impl/migration/v1707/Migration1707Config.java b/asdctool/src/main/java/org/openecomp/sdc/asdctool/impl/migration/v1707/Migration1707Config.java index 21a6ae1416..36919d7520 100644 --- a/asdctool/src/main/java/org/openecomp/sdc/asdctool/impl/migration/v1707/Migration1707Config.java +++ b/asdctool/src/main/java/org/openecomp/sdc/asdctool/impl/migration/v1707/Migration1707Config.java @@ -271,4 +271,9 @@ public class Migration1707Config { return new NodeTemplateMissingDataResolver<>(); } + @Bean(name = "migration1707MissingInfoFix") + public Migration1707MissingInfoFix migration1707MissingInfoFix() { + return new Migration1707MissingInfoFix(); + } + } diff --git a/asdctool/src/main/java/org/openecomp/sdc/asdctool/impl/migration/v1707/Migration1707MissingInfoFix.java b/asdctool/src/main/java/org/openecomp/sdc/asdctool/impl/migration/v1707/Migration1707MissingInfoFix.java new file mode 100644 index 0000000000..ff41f12b8e --- /dev/null +++ b/asdctool/src/main/java/org/openecomp/sdc/asdctool/impl/migration/v1707/Migration1707MissingInfoFix.java @@ -0,0 +1,220 @@ +package org.openecomp.sdc.asdctool.impl.migration.v1707; + +import fj.data.Either; +import org.openecomp.sdc.asdctool.impl.migration.v1707.jsonmodel.NodeTemplateMissingDataResolver; +import org.openecomp.sdc.be.dao.jsongraph.GraphVertex; +import org.openecomp.sdc.be.dao.jsongraph.TitanDao; +import org.openecomp.sdc.be.dao.jsongraph.types.EdgeLabelEnum; +import org.openecomp.sdc.be.dao.jsongraph.types.JsonParseFlagEnum; +import org.openecomp.sdc.be.dao.jsongraph.types.VertexTypeEnum; +import org.openecomp.sdc.be.dao.titan.TitanOperationStatus; +import org.openecomp.sdc.be.datatypes.elements.*; +import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; +import org.openecomp.sdc.be.datatypes.enums.GraphPropertyEnum; +import org.openecomp.sdc.be.datatypes.enums.OriginTypeEnum; +import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum; +import org.openecomp.sdc.be.datatypes.tosca.ToscaDataDefinition; +import org.openecomp.sdc.be.model.*; +import org.openecomp.sdc.be.model.jsontitan.datamodel.ToscaElement; +import org.openecomp.sdc.be.model.jsontitan.enums.JsonConstantKeysEnum; +import org.openecomp.sdc.be.model.jsontitan.operations.ToscaOperationFacade; +import org.openecomp.sdc.be.model.operations.api.IServiceOperation; +import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.annotation.Resource; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +@org.springframework.stereotype.Component("migration1707MissingInfoFix") +public class Migration1707MissingInfoFix { + + private static final Logger LOGGER = LoggerFactory.getLogger(Migration1707MissingInfoFix.class); + + @Resource(name = "service-operation") + private IServiceOperation serviceOperation; + + @Resource(name = "node-template-missing-data-resolver") + private NodeTemplateMissingDataResolver nodeTemplateMissingDataResolver; + + @Resource(name = "tosca-operation-facade") + private ToscaOperationFacade toscaOperations; + + @Resource(name = "titan-dao") + private TitanDao titanDao; + + + public boolean migrate(){ + boolean res = updateVFs(); + if(res) + res = updateServices(); + return res; + } + + private ComponentParametersView getFilter() { + ComponentParametersView filter = new ComponentParametersView(true); + filter.setIgnoreComponentInstances(false); + filter.setIgnoreArtifacts(false); + filter.setIgnoreGroups(false); + filter.setIgnoreComponentInstancesInputs(false); + return filter; + } + + // if new service has VF instances with no groups - try to fetch them from old graph + private boolean oldServiceModelRequired(Component newService) { + Predicate vfInstanceWithNoGroups = p -> OriginTypeEnum.VF == p.getOriginType() && (null == p.getGroupInstances() || p.getGroupInstances().isEmpty()); + return null != newService.getComponentInstances() && newService.getComponentInstances().stream() + .anyMatch(vfInstanceWithNoGroups); + } + + + + private List fetchVertices(Map hasProps){ + Either, TitanOperationStatus> componentsByCriteria = titanDao.getByCriteria(VertexTypeEnum.TOPOLOGY_TEMPLATE, hasProps, JsonParseFlagEnum.ParseAll); + if (componentsByCriteria.isRight()) { + LOGGER.debug("couldn't fetch assets from sdctitan"); + return null; + } + return componentsByCriteria.left().value(); + } + + private boolean updateVFs() { + + boolean res = true; + Map hasProps = new HashMap<>(); + hasProps.put(GraphPropertyEnum.COMPONENT_TYPE, ComponentTypeEnum.RESOURCE.name()); + hasProps.put(GraphPropertyEnum.RESOURCE_TYPE, ResourceTypeEnum.VF.name()); + + List resources = fetchVertices(hasProps); + if(null == resources) + return false; + ComponentParametersView filter = getFilter(); + Map origCompMap = new HashMap<>(); + + for (GraphVertex gv : resources) { + boolean fixed = true; + Either toscaElement = toscaOperations.getToscaElement(gv.getUniqueId(), filter); + if (toscaElement.isRight()) { + LOGGER.debug("Failed to fetch resource {} {}", gv.getUniqueId(), toscaElement.right().value()); + return false; + } + Component resource = toscaElement.left().value(); + Map updateMap = new HashMap<>(); + nodeTemplateMissingDataResolver.updateVFComposition(resource, origCompMap, updateMap); + if(updateMap.get(JsonConstantKeysEnum.COMPOSITION.name())){ + LOGGER.info("applying instance tosca name fix on VF {}", gv.getUniqueId()); + fixed = toscaOperations.updateComponentInstanceMetadataOfTopologyTemplate(resource).isLeft(); + } + if(updateMap.get(EdgeLabelEnum.GROUPS.name())) { + List groups = new ArrayList<>(resource.getGroups()); + LOGGER.info("applying groups vertex fix on VF {}", gv.getUniqueId()); + fixed = fixed && toscaOperations.updateGroupsOnComponent(resource, ComponentTypeEnum.RESOURCE, groups).isLeft(); + } + + res = res && fixed; + titanDao.commit(); + } + return res; + } + + private Map buildInstancesInputsMap(Component component){ + Map instanceInputsMap = new HashMap<>(); + for (Map.Entry> entry : component.getComponentInstancesInputs().entrySet()) { + MapPropertiesDataDefinition inputsMap = new MapPropertiesDataDefinition(); + inputsMap.setMapToscaDataDefinition(entry.getValue().stream().map(e -> new PropertyDataDefinition(e)).collect(Collectors.toMap(e -> e.getName(), e -> e))); + instanceInputsMap.put(entry.getKey(), inputsMap); + } + return instanceInputsMap; + } + + + + private Map buildGroupInstanceMap(Component component) { + Map instGroupsMap = new HashMap<>(); + for (ComponentInstance instance : component.getComponentInstances()) { + if (instance.getGroupInstances() != null) { + MapGroupsDataDefinition groupsMap = new MapGroupsDataDefinition(); + groupsMap.setMapToscaDataDefinition(instance.getGroupInstances().stream().map(e -> new GroupInstanceDataDefinition(e)).collect(Collectors.toMap(e -> e.getName(), e -> e))); + instGroupsMap.put(instance.getUniqueId(), groupsMap); + } + } + return instGroupsMap; + } + + private boolean updateDataVertex(GraphVertex componentVertex, VertexTypeEnum vertexType, EdgeLabelEnum edgeLabel, Map dataMap){ + Either dataVertexEither = titanDao.getChildVertex(componentVertex, edgeLabel, JsonParseFlagEnum.ParseJson); + if (dataVertexEither.isRight()) { + if(TitanOperationStatus.NOT_FOUND != dataVertexEither.right().value()) + return false; + return (nodeTemplateMissingDataResolver.topologyTemplateOperation.assosiateElementToData(componentVertex, vertexType, edgeLabel, dataMap)).isLeft(); + } + GraphVertex dataVertex = dataVertexEither.left().value(); + dataVertex.setJson(dataMap); + return (titanDao.updateVertex(dataVertex)).isLeft(); + + } + + + private boolean updateServices(){ + + boolean res = true; + Map hasProps = new HashMap<>(); + hasProps.put(GraphPropertyEnum.COMPONENT_TYPE, ComponentTypeEnum.SERVICE.name()); + + List componentsByCriteria = fetchVertices(hasProps); + if(null == componentsByCriteria) + return false; + + ComponentParametersView filter = getFilter(); + Map origCompMap = new HashMap<>(); + + Predicate containsGroupInstances = p -> null != p.getGroupInstances() && !p.getGroupInstances().isEmpty(); + + for (GraphVertex gv : componentsByCriteria) { + + boolean fixed = true; + Either toscaElement = toscaOperations.getToscaElement(gv.getUniqueId(), filter); + if (toscaElement.isRight()) { + LOGGER.debug("Failed to fetch service {} {}", gv.getUniqueId(), toscaElement.right().value()); + return false; + } + Component service = toscaElement.left().value(); + Component oldService = null; + + if(oldServiceModelRequired(service)){ + Either oldServiceEither = serviceOperation.getService(gv.getUniqueId(), filter, false); + if (oldServiceEither.isRight()){ + LOGGER.debug("couldn't fetch service {} from old titan", gv.getUniqueId()); + }else { + oldService = oldServiceEither.left().value(); + oldService = oldService.getComponentInstances().stream().anyMatch(containsGroupInstances) ? oldService : null; + } + } + + Map updateMap = new HashMap<>(); + nodeTemplateMissingDataResolver.updateServiceComposition(service, origCompMap, oldService, updateMap); + if(updateMap.get(JsonConstantKeysEnum.COMPOSITION.name())) { + LOGGER.info("applying instance tosca name fix on service {}", gv.getUniqueId()); + fixed = (toscaOperations.updateComponentInstanceMetadataOfTopologyTemplate(service)).isLeft(); + } + if(updateMap.get(EdgeLabelEnum.INST_GROUPS.name())) { + Map groupsMap = buildGroupInstanceMap(service); + LOGGER.info("applying groups instances vertex fix on service {}", gv.getUniqueId()); + fixed = fixed && updateDataVertex(gv, VertexTypeEnum.INST_GROUPS, EdgeLabelEnum.INST_GROUPS, groupsMap); + } + if(updateMap.get(EdgeLabelEnum.INST_INPUTS.name())) { + Map instInputs = buildInstancesInputsMap(service); + LOGGER.info("applying instances inputs vertex fix on service {}", gv.getUniqueId()); + fixed = fixed && updateDataVertex(gv, VertexTypeEnum.INST_INPUTS, EdgeLabelEnum.INST_INPUTS, instInputs); + } + res = res && fixed; + titanDao.commit(); + } + return res; + } +} diff --git a/asdctool/src/main/java/org/openecomp/sdc/asdctool/impl/migration/v1707/jsonmodel/ComponentMigration.java b/asdctool/src/main/java/org/openecomp/sdc/asdctool/impl/migration/v1707/jsonmodel/ComponentMigration.java index d69363be89..7603a5704a 100644 --- a/asdctool/src/main/java/org/openecomp/sdc/asdctool/impl/migration/v1707/jsonmodel/ComponentMigration.java +++ b/asdctool/src/main/java/org/openecomp/sdc/asdctool/impl/migration/v1707/jsonmodel/ComponentMigration.java @@ -109,8 +109,8 @@ public abstract class ComponentMigration extends JsonModel protected void setMissingTemplateInfo(List components) { Map origCompMap = new HashMap<>(); for (T component : components) { - List instances = component.getComponentInstances(); - if(null != instances) { + List instances = component.getComponentInstances(); + if(null != instances) { for (ComponentInstance instance : instances) { nodeTemplateMissingDataResolver.resolveNodeTemplateInfo(instance, origCompMap, component); nodeTemplateMissingDataResolver.fixVFGroupInstances(component, instance); diff --git a/asdctool/src/main/java/org/openecomp/sdc/asdctool/impl/migration/v1707/jsonmodel/NodeTemplateMissingDataResolver.java b/asdctool/src/main/java/org/openecomp/sdc/asdctool/impl/migration/v1707/jsonmodel/NodeTemplateMissingDataResolver.java index 01e36345e1..c83421066c 100644 --- a/asdctool/src/main/java/org/openecomp/sdc/asdctool/impl/migration/v1707/jsonmodel/NodeTemplateMissingDataResolver.java +++ b/asdctool/src/main/java/org/openecomp/sdc/asdctool/impl/migration/v1707/jsonmodel/NodeTemplateMissingDataResolver.java @@ -17,23 +17,18 @@ * limitations under the License. * ============LICENSE_END========================================================= */ - package org.openecomp.sdc.asdctool.impl.migration.v1707.jsonmodel; - - +import fj.data.Either; +import org.openecomp.sdc.be.dao.jsongraph.types.EdgeLabelEnum; import fj.data.Either; import org.openecomp.sdc.be.datatypes.elements.ComponentInstanceDataDefinition; import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition; import org.openecomp.sdc.be.datatypes.enums.OriginTypeEnum; import org.openecomp.sdc.be.datatypes.tosca.ToscaDataDefinition; -import org.openecomp.sdc.be.model.ArtifactDefinition; -import org.openecomp.sdc.be.model.Component; -import org.openecomp.sdc.be.model.ComponentInstance; -import org.openecomp.sdc.be.model.ComponentInstanceInput; -import org.openecomp.sdc.be.model.GroupDefinition; -import org.openecomp.sdc.be.model.GroupInstance; +import org.openecomp.sdc.be.model.*; import org.openecomp.sdc.be.model.jsontitan.datamodel.TopologyTemplate; import org.openecomp.sdc.be.model.jsontitan.datamodel.ToscaElement; +import org.openecomp.sdc.be.model.jsontitan.enums.JsonConstantKeysEnum; import org.openecomp.sdc.be.model.jsontitan.operations.TopologyTemplateOperation; import org.openecomp.sdc.be.model.jsontitan.operations.ToscaElementLifecycleOperation; import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; @@ -45,6 +40,8 @@ import org.slf4j.LoggerFactory; import javax.annotation.Resource; import java.util.ArrayList; import java.util.HashMap; +import java.util.*; +import java.util.stream.Collectors; import java.util.List; import java.util.Map; import java.util.Optional; @@ -59,32 +56,98 @@ public class NodeTemplateMissingDataResolver { private ToscaElementLifecycleOperation lifecycleOperation; @Resource(name = "topology-template-operation") - private TopologyTemplateOperation topologyTemplateOperation; + public TopologyTemplateOperation topologyTemplateOperation; public void resolveNodeTemplateInfo(ComponentInstanceDataDefinition vfInst, Map origCompMap, T component) { lifecycleOperation.resolveToscaComponentName(vfInst, origCompMap); if(OriginTypeEnum.VF == vfInst.getOriginType()) { - Map> componentInstancesInputs = Optional.ofNullable(component.getComponentInstancesInputs()).orElse(new HashMap<>()); - collectVFInstanceInputs(componentInstancesInputs, origCompMap, vfInst); + collectVFInstanceInputs(component, origCompMap, vfInst); + } + } + + + + + public void updateServiceComposition(Component component, Map origCompMap, Component oldModelService, Map updateMap){ + + boolean composition = false; + boolean instInputs = false; + boolean instGroups = false; + List instances = component.getComponentInstances(); + if(null != instances) { + for (ComponentInstance instance : instances) { + composition = composition || lifecycleOperation.resolveToscaComponentName(instance, origCompMap); + if(OriginTypeEnum.VF == instance.getOriginType()) { + instInputs = instInputs || collectVFInstanceInputs(component, origCompMap, instance); + instGroups = instGroups || resolveInstGroupsFromOldTitanGraphAndApplyFix(component, instance, oldModelService); + } + } } + updateMap.put(JsonConstantKeysEnum.COMPOSITION.name(), composition); + updateMap.put(EdgeLabelEnum.INST_INPUTS.name(), instInputs); + updateMap.put(EdgeLabelEnum.INST_GROUPS.name(), instGroups); + } + + + public void updateVFComposition(Component component, Map origCompMap, Map updateMap) { + + boolean composition = false; + boolean groups = fixVFGroups(component); + List instances = component.getComponentInstances(); + if(null != instances) { + for (ComponentInstance instance : instances) { + composition = composition || lifecycleOperation.resolveToscaComponentName(instance, origCompMap); + } + } + updateMap.put(JsonConstantKeysEnum.COMPOSITION.name(), composition); + updateMap.put(EdgeLabelEnum.GROUPS.name(), groups); + } + + + + private boolean resolveInstGroupsFromOldTitanGraphAndApplyFix(Component component, ComponentInstance instance, Component oldService){ + + boolean res = false; + //info already exists, apply fix if needed + if(null != instance.getGroupInstances() && !instance.getGroupInstances().isEmpty()) { + res = fixVFGroupInstances(component, instance); + //get group instances from old model + }else if(null != oldService){ + ComponentInstance origInstance = oldService.getComponentInstances().stream() + .filter(p -> instance.getUniqueId().equals(p.getUniqueId())) + .findAny().orElse(null); + if(null != origInstance && null != origInstance.getGroupInstances()) { + fixVFGroupInstances(oldService, origInstance); + instance.setGroupInstances(origInstance.getGroupInstances()); + res = true; + } + } + return res; } - private void collectVFInstanceInputs(Map> instInputs, Map origCompMap, ComponentInstanceDataDefinition vfInst) { + private boolean collectVFInstanceInputs(Component component, Map origCompMap, ComponentInstanceDataDefinition vfInst) { + boolean res = false; String ciUid = vfInst.getUniqueId(); String origCompUid = vfInst.getComponentUid(); + if(null == component.getComponentInstancesInputs()) + component.setComponentInstancesInputs(new HashMap<>()); + Map> componentInstInputs = component.getComponentInstancesInputs(); Either origComp = fetchToscaElement(origCompMap, vfInst, origCompUid); if(origComp.isRight()) - return; + return false; Map origVFInputs = ((TopologyTemplate)origComp.left().value()).getInputs(); if (origVFInputs != null && !origVFInputs.isEmpty()) { + res = true; Map collectedVFInputs = origVFInputs.values().stream() .collect(Collectors.toMap(PropertyDataDefinition::getName, ComponentInstanceInput::new)); - List instInputList = instInputs.get(ciUid); + + List instInputList = componentInstInputs.get(ciUid); Map existingInstInputs = ToscaDataDefinition.listToMapByName(instInputList); collectedVFInputs.putAll(existingInstInputs); List mergedList = new ArrayList<>(collectedVFInputs.values()); - instInputs.put(ciUid, mergedList); + componentInstInputs.put(ciUid, mergedList); } + return res; } private Either fetchToscaElement(Map origCompMap, ComponentInstanceDataDefinition vfInst, String origCompUid) { @@ -201,22 +264,23 @@ public class NodeTemplateMissingDataResolver { return artifactLabel; } - protected boolean fixVFGroups(Component component){ - boolean res = true; - + public boolean fixVFGroups(Component component){ + boolean res = false; + Map deploymentArtifacts = component.getDeploymentArtifacts(); List groups = component.getGroups(); if (groups == null || groups.isEmpty()) { - LOGGER.debug("No groups in component {} id {} ", component.getName(), component.getUniqueId()); + LOGGER.debug("No groups in component {} id {} ", component.getName(), component.getUniqueId()); return res; } for (GroupDefinition group : groups) { if (group.getType().equals(Constants.DEFAULT_GROUP_VF_MODULE) && deploymentArtifacts != null) { if (isProblematicGroup(group, component.getName(), deploymentArtifacts)) { - List groupArtifacts = new ArrayList(group.getArtifacts()); - group.getArtifacts().clear(); - group.getArtifactsUuid().clear(); + res = true; + List groupArtifacts = null == group.getArtifacts()? new ArrayList<>() : new ArrayList<>(group.getArtifacts()); + group.setArtifacts(new ArrayList<>()); + group.setArtifactsUuid(new ArrayList<>()); for (String artifactId : groupArtifacts) { String artifactlabel = findArtifactLabelFromArtifactId(artifactId); LOGGER.debug("fix group: group name {} artifactId for fix {} artifactlabel {} ", group.getName(), artifactId, artifactlabel); @@ -229,19 +293,16 @@ public class NodeTemplateMissingDataResolver { if (correctArtifactUUID != null && !correctArtifactUUID.isEmpty()) { group.getArtifactsUuid().add(correctArtifactUUID); } - } } } } - - } - + } return res; } - protected boolean fixVFGroupInstances(Component component, ComponentInstance instance){ - boolean res = true; + public boolean fixVFGroupInstances(Component component, ComponentInstance instance){ + boolean res = false; Map deploymentArtifacts = instance.getDeploymentArtifacts(); List groupInstances = instance.getGroupInstances(); @@ -252,10 +313,9 @@ public class NodeTemplateMissingDataResolver { for (GroupInstance group : groupInstances) { if (group.getType().equals(Constants.DEFAULT_GROUP_VF_MODULE)) { if (isProblematicGroupInstance(group, instance.getName(), component.getName(), deploymentArtifacts)) { - - LOGGER.debug("Migration1707ArtifactUuidFix fix group: resource id {}, group name {} ", component.getUniqueId(), group.getName()); - List groupArtifacts = Optional.ofNullable(group.getArtifacts()).orElse(new ArrayList<>()); - + res = true; + LOGGER.debug("Migration1707ArtifactUuidFix fix group: resource id {}, group name {} ", component.getUniqueId(), group.getName()); + List groupArtifacts = null == group.getArtifacts()? new ArrayList<>() : new ArrayList<>(group.getArtifacts()); group.setArtifacts(new ArrayList<>()); group.setArtifactsUuid(new ArrayList<>()); group.setGroupInstanceArtifacts(new ArrayList<>()); @@ -285,12 +345,9 @@ public class NodeTemplateMissingDataResolver { } } } - } } } - return res; } - } diff --git a/asdctool/src/main/java/org/openecomp/sdc/asdctool/main/MigrationMenu.java b/asdctool/src/main/java/org/openecomp/sdc/asdctool/main/MigrationMenu.java index dd9fa86084..600ebf848a 100644 --- a/asdctool/src/main/java/org/openecomp/sdc/asdctool/main/MigrationMenu.java +++ b/asdctool/src/main/java/org/openecomp/sdc/asdctool/main/MigrationMenu.java @@ -33,12 +33,7 @@ import org.openecomp.sdc.asdctool.impl.migration.v1607.CsarMigration; import org.openecomp.sdc.asdctool.impl.migration.v1610.TitanFixUtils; import org.openecomp.sdc.asdctool.impl.migration.v1610.ToscaArtifactsAlignment; import org.openecomp.sdc.asdctool.impl.migration.v1702.Migration1702; -import org.openecomp.sdc.asdctool.impl.migration.v1707.Migration1707; -import org.openecomp.sdc.asdctool.impl.migration.v1707.Migration1707ArtifactUuidFix; -import org.openecomp.sdc.asdctool.impl.migration.v1707.Migration1707Config; -import org.openecomp.sdc.asdctool.impl.migration.v1707.DistributionStatusUpdate; -import org.openecomp.sdc.asdctool.impl.migration.v1707.Migration1707VnfFix; -import org.openecomp.sdc.asdctool.impl.migration.v1707.VfModulesPropertiesAdding; +import org.openecomp.sdc.asdctool.impl.migration.v1707.*; import org.openecomp.sdc.be.config.ConfigurationManager; import org.openecomp.sdc.common.api.ConfigurationSource; import org.openecomp.sdc.common.impl.ExternalConfiguration; @@ -53,17 +48,17 @@ public class MigrationMenu { private static final String SERVICE_MIGARTION_BEAN = "serviceMigrationBean"; private static enum MigrationOperationEnum { - MIGRATION_1602_1604("migrate-1602-1604", SERVICE_MIGARTION_BEAN), - ALIGN_DERIVED_FROM_1604("align-derived-from-1604", "derivedFromAlignment"), - MIGRATE_1604_1607("migrate-1604-1607", SERVICE_MIGARTION_BEAN), - ALIGN_VFC_NAMES_1604("align-vfc-names-1604", "vfcNamingAlignmentBean"), - TEST_REMOVE_HEAT_PLACEHOLDERS("testremoveheatplaceholders", SERVICE_MIGARTION_BEAN), - TEST_ADD_GROUP_UUIDS("testaddgroupuuids", SERVICE_MIGARTION_BEAN), - ALIGN_GROUPS("align-groups", "groupsAlignment"), - CLEAN_CSAR("clean-csar", "csarMigration"), - POPULATE_COMPONENT_CACHE("populate-component-cache", "populateComponentCache"), - FIX_PROPERTIES("fix-properties", "titanFixUtils"), - ALIGN_TOSCA_ARTIFACTS("align-tosca-artifacts", "toscaArtifactsAlignment"), + MIGRATION_1602_1604("migrate-1602-1604", SERVICE_MIGARTION_BEAN), + ALIGN_DERIVED_FROM_1604("align-derived-from-1604", "derivedFromAlignment"), + MIGRATE_1604_1607("migrate-1604-1607", SERVICE_MIGARTION_BEAN), + ALIGN_VFC_NAMES_1604("align-vfc-names-1604", "vfcNamingAlignmentBean"), + TEST_REMOVE_HEAT_PLACEHOLDERS("testremoveheatplaceholders", SERVICE_MIGARTION_BEAN), + TEST_ADD_GROUP_UUIDS("testaddgroupuuids", SERVICE_MIGARTION_BEAN), + ALIGN_GROUPS("align-groups", "groupsAlignment"), + CLEAN_CSAR("clean-csar", "csarMigration"), + POPULATE_COMPONENT_CACHE("populate-component-cache", "populateComponentCache"), + FIX_PROPERTIES("fix-properties", "titanFixUtils"), + ALIGN_TOSCA_ARTIFACTS("align-tosca-artifacts", "toscaArtifactsAlignment"), FIX_ICONS("fix-icons", "titanFixUtils"), MIGRATION_1610_1702("migrate-1610-1702", "migration1702"), MIGRATION_1702_1707("migrate-1702-1707", "migration1707"), @@ -71,7 +66,8 @@ public class MigrationMenu { VFMODULES_PROPERTIES_ADDING("vfModules-properties-adding", "vfModulesPropertiesAdding"), MIGRATION_1707_RELATIONS_FIX("fix-relations-after-migration-1707", "migration1707relationsFix"), MIGRATION_1707_VNF_FIX("fix-vnf-after-migration-1707", "migration1707vnfFix"), - MIGRATION_1707_UUID_FIX("fix-UUID-1707", "migration1707UuidFix"); + MIGRATION_1707_UUID_FIX("fix-UUID-1707", "migration1707UuidFix"), + MIGRATION_1707_MISSING_INFO_FIX("fix-missing-info-1707", "migration1707MissingInfoFix"); // UPDATE_DATA_TYPES("update_data_types", "updateDataTypes"); private String value, beanName; @@ -225,7 +221,7 @@ public class MigrationMenu { ToscaArtifactsAlignment toscaArtifactsAlignment = (ToscaArtifactsAlignment) context.getBean(operationEnum.getBeanName()); boolean isSuccessful = toscaArtifactsAlignment.alignToscaArtifacts(); if (isSuccessful) { - log.info("Tosca Artifacts alignment was finished successfull"); + log.info("Tosca Artifacts alignment was finished successfully"); System.exit(0); } else { log.info("Tosca Artifacts alignment has failed"); @@ -233,20 +229,20 @@ public class MigrationMenu { } break; case MIGRATION_1610_1702: - log.info("Start ASDC migration from 1610 to 1702"); + log.info("Start SDC migration from 1610 to 1702"); Migration1702 migration = (Migration1702) context.getBean(operationEnum.getBeanName()); isSuccessful = migration.migrate(appConfigDir); if (isSuccessful) { - log.info("ASDC migration from 1610 to 1702 was finished successful"); + log.info("SDC migration from 1610 to 1702 was finished successful"); System.exit(0); } else{ - log.info("ASDC migration from 1610 to 1702 has failed"); + log.info("SDC migration from 1610 to 1702 has failed"); System.exit(2); } - + break; case MIGRATION_1702_1707://this migration is currently not needed, but will be commented out for production env - log.info("Start ASDC migration from 1702 to 1707"); +// log.info("Start SDC migration from 1702 to 1707"); Migration1707 migration1707 = (Migration1707) context.getBean(operationEnum.getBeanName()); isSuccessful = migration1707.migrate(); if (isSuccessful) { @@ -278,8 +274,8 @@ public class MigrationMenu { } String fixServices = args[3]; String runMode = args[4]; - log.info("Start fixing artifact UUID after 1707 migration with arguments run with configutation [{}] , for [{}] services", runMode, fixServices); - + log.info("Start fixing artifact UUID after 1707 migration with arguments run with configuration [{}] , for [{}] services", runMode, fixServices); + Migration1707ArtifactUuidFix migrationFix = (Migration1707ArtifactUuidFix) context.getBean(operationEnum.getBeanName()); isSuccessful = migrationFix.migrate(fixServices, runMode); if (isSuccessful) { @@ -290,6 +286,20 @@ public class MigrationMenu { } System.exit(0); break; + case MIGRATION_1707_MISSING_INFO_FIX: + + log.info("Start fixing missing group and instance info after 1707 migration"); + + Migration1707MissingInfoFix migration1707Fix = (Migration1707MissingInfoFix) context.getBean(operationEnum.getBeanName()); + isSuccessful = migration1707Fix.migrate(); + if (isSuccessful) { + log.info("Fixing groups and node templates missing info was finished successfully"); + } else{ + log.info("Fixing groups and node templates missing info has failed"); + System.exit(2); + } + System.exit(0); + break; default: usageAndExit(); } @@ -330,5 +340,6 @@ public class MigrationMenu { System.out.println("Usage: fix-relations-after-migration-1707 "); System.out.println("Usage: fix-vnf-after-migration-1707 "); System.out.println("Usage: fix-UUID-1707 "); + System.out.println("Usage: fix-missing-info-1707 "); } } diff --git a/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/config/MigrationSpringConfig.java b/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/config/MigrationSpringConfig.java new file mode 100644 index 0000000000..0457c2136d --- /dev/null +++ b/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/config/MigrationSpringConfig.java @@ -0,0 +1,59 @@ +package org.openecomp.sdc.asdctool.migration.config; + +import org.openecomp.sdc.asdctool.migration.core.SdcMigrationTool; +import org.openecomp.sdc.asdctool.migration.core.task.Migration; +import org.openecomp.sdc.asdctool.migration.resolver.MigrationResolver; +import org.openecomp.sdc.asdctool.migration.resolver.SpringBeansMigrationResolver; +import org.openecomp.sdc.asdctool.migration.service.SdcRepoService; +import org.openecomp.sdc.be.dao.cassandra.CassandraClient; +import org.openecomp.sdc.be.dao.cassandra.MigrationTasksDao; +import org.openecomp.sdc.be.dao.config.DAOSpringConfig; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; + +import java.util.ArrayList; +import java.util.List; + +@Configuration +@Import(DAOSpringConfig.class) +@ComponentScan({"org.openecomp.sdc.asdctool.migration.tasks",//migration tasks + "org.openecomp.sdc.be.model.operations.impl", + "org.openecomp.sdc.be.model.cache", + "org.openecomp.sdc.be.dao.titan", + "org.openecomp.sdc.be.dao.cassandra", + "org.openecomp.sdc.be.model.jsontitan.operations", + "org.openecomp.sdc.be.dao.jsongraph"}) +public class MigrationSpringConfig { + + @Autowired(required=false) + private List migrations = new ArrayList<>(); + + @Bean(name = "sdc-migration-tool") + public SdcMigrationTool sdcMigrationTool(MigrationResolver migrationResolver, SdcRepoService sdcRepoService) { + return new SdcMigrationTool(migrationResolver, sdcRepoService); + } + + @Bean(name = "spring-migrations-resolver") + public SpringBeansMigrationResolver migrationResolver(SdcRepoService sdcRepoService) { + return new SpringBeansMigrationResolver(migrations, sdcRepoService); + } + + @Bean(name = "sdc-repo-service") + public SdcRepoService sdcRepoService(MigrationTasksDao migrationTasksDao) { + return new SdcRepoService(migrationTasksDao); + } + + @Bean(name = "sdc-migration-tasks-cassandra-dao") + public MigrationTasksDao migrationTasksDao() { + return new MigrationTasksDao(); + } + + @Bean(name = "cassandra-client") + public CassandraClient cassandraClient() { + return new CassandraClient(); + } + +} diff --git a/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/core/DBVersion.java b/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/core/DBVersion.java new file mode 100644 index 0000000000..003a27a1e4 --- /dev/null +++ b/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/core/DBVersion.java @@ -0,0 +1,95 @@ +package org.openecomp.sdc.asdctool.migration.core; + +import java.math.BigInteger; + +public class DBVersion implements Comparable{ + + private static final String VERSION_PARTS_SEPARATOR = "\\."; + private static final int MAJOR_PART_IDX = 0; + private static final int MINOR_PART_IDX = 1; + private BigInteger major; + private BigInteger minor; + + /** + * The current db version. should be tested against real db to verify it is compatible to the db version + */ + public static final DBVersion CURRENT_VERSION = new DBVersion(1710, 0); + + private DBVersion(BigInteger major, BigInteger minor) { + this.major = major; + this.minor = minor; + } + + private DBVersion(int major, int minor) { + this.major = BigInteger.valueOf(major); + this.minor = BigInteger.valueOf(minor); + } + + public BigInteger getMajor() { + return major; + } + + public BigInteger getMinor() { + return minor; + } + + public static DBVersion from(BigInteger major, BigInteger minor) { + return new DBVersion(major, minor); + } + + public static DBVersion fromString(String version) { + String[] split = version.split(VERSION_PARTS_SEPARATOR); + if (split.length != 2) { + throw new MigrationException("version must be of pattern: ."); + } + return new DBVersion(getVersionPart(split[MAJOR_PART_IDX]), + getVersionPart(split[MINOR_PART_IDX])); + + } + + private static BigInteger getVersionPart(String versionPart) { + try { + return new BigInteger(versionPart); + } catch (NumberFormatException e) { + throw new MigrationException(String.format("version part %s is non numeric", versionPart)); + } + } + + @Override + public String toString() { + return String.format("%s.%s", major, minor); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + DBVersion dbVersion = (DBVersion) o; + + return major.equals(dbVersion.major) && minor.equals(dbVersion.minor); + } + + @Override + public int hashCode() { + int result = major.hashCode(); + result = 31 * result + minor.hashCode(); + return result; + } + + @Override + public int compareTo(DBVersion o) { + if (o == null) { + return 1; + } + int majorsComparision = this.major.compareTo(o.major); + if (majorsComparision != 0) { + return majorsComparision; + } + int minorsComparision = this.minor.compareTo(o.minor); + if (minorsComparision != 0) { + return minorsComparision; + } + return 0; + } +} diff --git a/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/core/MigrationException.java b/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/core/MigrationException.java new file mode 100644 index 0000000000..e9e805355e --- /dev/null +++ b/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/core/MigrationException.java @@ -0,0 +1,13 @@ +package org.openecomp.sdc.asdctool.migration.core; + +public class MigrationException extends RuntimeException { + + public MigrationException(String message) { + super(message); + } + + public MigrationException(String message, RuntimeException e) { + super(message, e); + } + +} diff --git a/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/core/SdcMigrationTool.java b/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/core/SdcMigrationTool.java new file mode 100644 index 0000000000..e2691dc7f8 --- /dev/null +++ b/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/core/SdcMigrationTool.java @@ -0,0 +1,62 @@ +package org.openecomp.sdc.asdctool.migration.core; + +import org.openecomp.sdc.asdctool.migration.core.execution.MigrationExecutionResult; +import org.openecomp.sdc.asdctool.migration.core.execution.MigrationExecutorImpl; +import org.openecomp.sdc.asdctool.migration.core.task.Migration; +import org.openecomp.sdc.asdctool.migration.core.task.MigrationResult; +import org.openecomp.sdc.asdctool.migration.resolver.MigrationResolver; +import org.openecomp.sdc.asdctool.migration.service.SdcRepoService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; + +public class SdcMigrationTool { + + private static final Logger LOGGER = LoggerFactory.getLogger(SdcMigrationTool.class); + + private MigrationResolver migrationsResolver; + + private SdcRepoService sdcRepoService; + + public SdcMigrationTool(MigrationResolver migrationsResolver, SdcRepoService sdcRepoService) { + this.migrationsResolver = migrationsResolver; + this.sdcRepoService = sdcRepoService; + } + + public SdcMigrationTool() { + } + + public boolean migrate(boolean enforceAll) { + LOGGER.info("starting migration process"); + handleEnforceMigrationFlag(enforceAll); + List migrations = migrationsResolver.resolveMigrations(); + LOGGER.info("there are {} migrations task to execute", migrations.size()); + for (Migration migration : migrations) { + try { + MigrationExecutionResult executionResult = new MigrationExecutorImpl().execute(migration); + if (migrationHasFailed(executionResult)) { + LOGGER.error("migration {} with version {} has failed. error msg: {}", migration.getClass().getName(), migration.getVersion().toString(), executionResult.getMsg()); + return false; + } + sdcRepoService.createMigrationTask(executionResult.toMigrationTaskEntry()); + } catch (RuntimeException e) { + LOGGER.error("migration {} with version {} has failed. error msg: {}", migration.getClass().getName(), migration.getVersion().toString(), e); + return false; + } + } + return true; + } + + private boolean migrationHasFailed(MigrationExecutionResult migrationResult) { + return migrationResult.getMigrationStatus().equals(MigrationResult.MigrationStatus.FAILED); + } + + private void handleEnforceMigrationFlag(boolean enforceAll) { + if (enforceAll) { + LOGGER.info("enforcing migration for current version"); + sdcRepoService.clearTasksForCurrentMajor(); + } + } + +} diff --git a/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/core/execution/MigrationExecutionResult.java b/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/core/execution/MigrationExecutionResult.java new file mode 100644 index 0000000000..4ebec6e440 --- /dev/null +++ b/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/core/execution/MigrationExecutionResult.java @@ -0,0 +1,70 @@ +package org.openecomp.sdc.asdctool.migration.core.execution; + +import org.openecomp.sdc.asdctool.migration.core.DBVersion; +import org.openecomp.sdc.asdctool.migration.core.task.MigrationResult; +import org.openecomp.sdc.be.resources.data.MigrationTaskEntry; + +import java.util.Date; + +public class MigrationExecutionResult { + + private MigrationResult.MigrationStatus migrationStatus; + private String msg; + private double executionTime; + private DBVersion version; + private String taskName; + + public MigrationTaskEntry toMigrationTaskEntry() { + MigrationTaskEntry migrationTaskEntry = new MigrationTaskEntry(); + migrationTaskEntry.setMajorVersion(this.getVersion().getMajor().longValue()); + migrationTaskEntry.setMinorVersion(this.getVersion().getMinor().longValue()); + migrationTaskEntry.setTimestamp(new Date()); + migrationTaskEntry.setTaskName(this.getTaskName()); + migrationTaskEntry.setTaskStatus(this.getMigrationStatus().name()); + migrationTaskEntry.setMessage(this.getMsg()); + migrationTaskEntry.setExecutionTime(this.getExecutionTime()); + return migrationTaskEntry; + } + + + public MigrationResult.MigrationStatus getMigrationStatus() { + return migrationStatus; + } + + void setMigrationStatus(MigrationResult.MigrationStatus migrationStatus) { + this.migrationStatus = migrationStatus; + } + + public String getMsg() { + return msg; + } + + void setMsg(String msg) { + this.msg = msg; + } + + double getExecutionTime() { + return executionTime; + } + + void setExecutionTime(double executionTime) { + this.executionTime = executionTime; + } + + public DBVersion getVersion() { + return version; + } + + public void setVersion(DBVersion version) { + this.version = version; + } + + String getTaskName() { + return taskName; + } + + void setTaskName(String taskName) { + this.taskName = taskName; + } + +} diff --git a/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/core/execution/MigrationExecutor.java b/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/core/execution/MigrationExecutor.java new file mode 100644 index 0000000000..aba5056b48 --- /dev/null +++ b/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/core/execution/MigrationExecutor.java @@ -0,0 +1,15 @@ +package org.openecomp.sdc.asdctool.migration.core.execution; + +import org.openecomp.sdc.asdctool.migration.core.MigrationException; +import org.openecomp.sdc.asdctool.migration.core.task.Migration; + +public interface MigrationExecutor { + + /** + * @param migration the migration to execute + * @return a {@link MigrationExecutionResult} with the relevant data on the current migration execution; + * @throws MigrationException in case there was an unexpected exception during migration + */ + MigrationExecutionResult execute(Migration migration) throws MigrationException; + +} diff --git a/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/core/execution/MigrationExecutorImpl.java b/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/core/execution/MigrationExecutorImpl.java new file mode 100644 index 0000000000..2e4d3ba8b0 --- /dev/null +++ b/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/core/execution/MigrationExecutorImpl.java @@ -0,0 +1,47 @@ +package org.openecomp.sdc.asdctool.migration.core.execution; + +import org.openecomp.sdc.asdctool.migration.core.MigrationException; +import org.openecomp.sdc.asdctool.migration.core.task.Migration; +import org.openecomp.sdc.asdctool.migration.core.task.MigrationResult; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.util.StopWatch; + + +public class MigrationExecutorImpl implements MigrationExecutor { + + private static final Logger LOGGER = LoggerFactory.getLogger(MigrationExecutorImpl.class); + + @Override + public MigrationExecutionResult execute(Migration migration) throws MigrationException { + try { + LOGGER.info("starting migration {}. description: {}. version {}", migration.getClass().getName(), migration.description(), migration.getVersion().toString()); + StopWatch stopWatch = new StopWatch(); + stopWatch.start(); + MigrationResult migrationResult = migration.migrate(); + stopWatch.stop(); + double executionTime = stopWatch.getTotalTimeSeconds(); + return logAndCreateExecutionResult(migration, migrationResult, executionTime); + } catch (RuntimeException e) { + LOGGER.error("migration {} has failed!", migration.description(), e); + throw new MigrationException("migration %s failed!!!", e); + + } + } + + private MigrationExecutionResult logAndCreateExecutionResult(Migration migration, MigrationResult migrationResult, double executionTime) { + LOGGER.info("finished migration {}. with version {}. migration status: {}, migration message: {}, execution time: {}", migration.getClass().getName(), migration.getVersion().toString(), migrationResult.getMigrationStatus().name(), migrationResult.getMsg(), executionTime); + return createMigrationTask(migration, migrationResult, executionTime); + } + + private MigrationExecutionResult createMigrationTask(Migration migration, MigrationResult migrationResult, double totalTimeSeconds) { + MigrationExecutionResult migrationExecutionResult = new MigrationExecutionResult(); + migrationExecutionResult.setExecutionTime(totalTimeSeconds); + migrationExecutionResult.setMigrationStatus(migrationResult.getMigrationStatus()); + migrationExecutionResult.setMsg(migrationResult.getMsg()); + migrationExecutionResult.setTaskName(migration.getClass().getName()); + migrationExecutionResult.setVersion(migration.getVersion()); + return migrationExecutionResult; + } + +} diff --git a/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/core/task/Migration.java b/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/core/task/Migration.java new file mode 100644 index 0000000000..58f201acf5 --- /dev/null +++ b/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/core/task/Migration.java @@ -0,0 +1,14 @@ +package org.openecomp.sdc.asdctool.migration.core.task; + + +import org.openecomp.sdc.asdctool.migration.core.DBVersion; + +public interface Migration { + + String description(); + + DBVersion getVersion(); + + MigrationResult migrate(); + +} diff --git a/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/core/task/MigrationResult.java b/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/core/task/MigrationResult.java new file mode 100644 index 0000000000..8c4c090d94 --- /dev/null +++ b/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/core/task/MigrationResult.java @@ -0,0 +1,31 @@ +package org.openecomp.sdc.asdctool.migration.core.task; + +public class MigrationResult { + + private String msg; + private MigrationStatus migrationStatus; + + public String getMsg() { + return msg; + } + + public void setMsg(String msg) { + this.msg = msg; + } + + public MigrationStatus getMigrationStatus() { + return migrationStatus; + } + + public void setMigrationStatus(MigrationStatus migrationStatus) { + this.migrationStatus = migrationStatus; + } + + public enum MigrationStatus { + COMPLETED, + COMPLETED_WITH_ERRORS, + FAILED + } + + +} diff --git a/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/main/MigrationMenu.java b/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/main/MigrationMenu.java new file mode 100644 index 0000000000..1e8a533624 --- /dev/null +++ b/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/main/MigrationMenu.java @@ -0,0 +1,100 @@ +package org.openecomp.sdc.asdctool.migration.main; + +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.CommandLineParser; +import org.apache.commons.cli.DefaultParser; +import org.apache.commons.cli.HelpFormatter; +import org.apache.commons.cli.Option; +import org.apache.commons.cli.Options; +import org.apache.commons.cli.ParseException; +import org.openecomp.sdc.asdctool.migration.config.MigrationSpringConfig; +import org.openecomp.sdc.asdctool.migration.core.SdcMigrationTool; +import org.openecomp.sdc.be.config.ConfigurationManager; +import org.openecomp.sdc.common.api.ConfigurationSource; +import org.openecomp.sdc.common.impl.ExternalConfiguration; +import org.openecomp.sdc.common.impl.FSConfigurationSource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; + +public class MigrationMenu { + + private final static Logger LOGGER = LoggerFactory.getLogger(MigrationMenu.class); + + public static void main(String[] args) { + CommandLine commandLine = initCmdLineOptions(args); + String appConfigDir = commandLine.getOptionValue("c"); + boolean enforceAll = commandLine.hasOption("e"); + uploadConfiguration(appConfigDir); + AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MigrationSpringConfig.class); + doMigrate(enforceAll, context); + + } + + private static void doMigrate(boolean enforceAll, AnnotationConfigApplicationContext context) { + SdcMigrationTool migrationTool = context.getBean(SdcMigrationTool.class); + boolean migrate = migrationTool.migrate(enforceAll); + if (migrate) { + LOGGER.info("migration completed successfully"); + System.exit(0); + } else { + LOGGER.error("migration failed"); + System.exit(1); + } + } + + private static CommandLine initCmdLineOptions(String[] args) { + Options options = buildCmdLineOptions(); + CommandLineParser parser = new DefaultParser(); + try { + // parse the command line arguments + return parser.parse( options, args ); + } + catch( ParseException exp ) { + // oops, something went wrong + System.err.println( "Parsing failed. Reason: " + exp.getMessage() ); + usageAndExit(options); + } + return null; + } + + private static void usageAndExit(Options options) { + HelpFormatter formatter = new HelpFormatter(); + formatter.printHelp( "yy", options ); + System.exit(1); + } + + private static Options buildCmdLineOptions() { + Option configPath = buildConfigPathOption(); + + Option enforceAll = buildEnforceAllOption(); + + Options options = new Options(); + options.addOption(configPath); + options.addOption(enforceAll); + return options; + } + + private static Option buildEnforceAllOption() { + return Option.builder("e") + .longOpt("enforceAll") + .desc("enforce running all migration steps for current version") + .build(); + } + + private static Option buildConfigPathOption() { + return Option.builder("c") + .longOpt("configFolderPath") + .required() + .hasArg() + .desc("path to sdc configuration folder - required") + .build(); + } + + private static void uploadConfiguration(String appConfigDir) { + ConfigurationSource configurationSource = new FSConfigurationSource(ExternalConfiguration.getChangeListener(), appConfigDir); + ConfigurationManager configurationManager = new ConfigurationManager(configurationSource); + } + + +} diff --git a/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/resolver/MigrationResolver.java b/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/resolver/MigrationResolver.java new file mode 100644 index 0000000000..b272d45ff0 --- /dev/null +++ b/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/resolver/MigrationResolver.java @@ -0,0 +1,16 @@ +package org.openecomp.sdc.asdctool.migration.resolver; + + +import org.openecomp.sdc.asdctool.migration.core.task.Migration; + +import java.util.List; + +public interface MigrationResolver { + + /** + * + * @return a list of {@code T} + */ + List resolveMigrations(); + +} diff --git a/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/resolver/SpringBeansMigrationResolver.java b/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/resolver/SpringBeansMigrationResolver.java new file mode 100644 index 0000000000..4af5d76123 --- /dev/null +++ b/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/resolver/SpringBeansMigrationResolver.java @@ -0,0 +1,45 @@ +package org.openecomp.sdc.asdctool.migration.resolver; + + +import org.openecomp.sdc.asdctool.migration.core.DBVersion; +import org.openecomp.sdc.asdctool.migration.core.task.Migration; +import org.openecomp.sdc.asdctool.migration.service.SdcRepoService; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.stream.Collectors; + +public class SpringBeansMigrationResolver implements MigrationResolver { + + private List migrations = new ArrayList<>(); + + private SdcRepoService sdcRepoService; + + public SpringBeansMigrationResolver(List migrations, SdcRepoService sdcRepoService) { + this.migrations = migrations; + this.sdcRepoService = sdcRepoService; + } + + @Override + public List resolveMigrations() { + migrations.sort(Comparator.comparing(Migration::getVersion)); + return resolveNonExecutedMigrations(); + } + + //package private for testing + void setMigrations(List migrations) { + this.migrations = migrations; + } + + private List resolveNonExecutedMigrations() { + DBVersion latestDBVersion = sdcRepoService.getLatestDBVersion(); + return migrations.stream() + .filter(mig -> isMigrationVersionGreaterThanLatestVersion(latestDBVersion, mig)) + .collect(Collectors.toList()); + } + + private boolean isMigrationVersionGreaterThanLatestVersion(DBVersion latestDBVersion, Migration mig) { + return mig.getVersion().compareTo(latestDBVersion) > 0; + } +} diff --git a/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/service/SdcRepoService.java b/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/service/SdcRepoService.java new file mode 100644 index 0000000000..2888ecb474 --- /dev/null +++ b/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/service/SdcRepoService.java @@ -0,0 +1,34 @@ +package org.openecomp.sdc.asdctool.migration.service; + +import org.openecomp.sdc.asdctool.migration.core.DBVersion; +import org.openecomp.sdc.be.dao.cassandra.MigrationTasksDao; +import org.openecomp.sdc.be.resources.data.MigrationTaskEntry; + +import java.math.BigInteger; + +public class SdcRepoService { + + private MigrationTasksDao migrationTasksDao; + + public SdcRepoService(MigrationTasksDao migrationTasksDao) { + this.migrationTasksDao = migrationTasksDao; + } + + public DBVersion getLatestDBVersion() { + BigInteger currentMajorVersion = DBVersion.CURRENT_VERSION.getMajor(); + BigInteger latestMinorVersion = migrationTasksDao.getLatestMinorVersion(currentMajorVersion); + return latestMinorVersion == null ? DBVersion.from(currentMajorVersion, BigInteger.valueOf(Integer.MIN_VALUE)) : DBVersion.from(currentMajorVersion, latestMinorVersion); + } + + public void clearTasksForCurrentMajor() { + BigInteger currentMajorVersion = DBVersion.CURRENT_VERSION.getMajor(); + migrationTasksDao.deleteAllTasksForVersion(currentMajorVersion); + } + + public void createMigrationTask(MigrationTaskEntry migrationTaskEntry) { + migrationTasksDao.createMigrationTask(migrationTaskEntry); + } + + + +} diff --git a/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/tasks/mig1710/ExampleMigration.java b/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/tasks/mig1710/ExampleMigration.java new file mode 100644 index 0000000000..1302dc26a8 --- /dev/null +++ b/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/tasks/mig1710/ExampleMigration.java @@ -0,0 +1,27 @@ +//package org.openecomp.sdc.asdctool.migration.tasks.mig1710;//package org.openecomp.sdc.migration.tasks.mig1710; +// +//import org.openecomp.sdc.asdctool.migration.core.DBVersion; +//import org.openecomp.sdc.asdctool.migration.core.task.Migration; +//import org.openecomp.sdc.asdctool.migration.core.task.MigrationResult; +//import org.springframework.stereotype.Component; +// +//@Component +//public class ExampleMigration implements Migration { +// +// @Override +// public String description() { +// return "some description"; +// } +// +// @Override +// public DBVersion getVersion() { +// return DBVersion.fromString("1710.0"); +// } +// +// @Override +// public MigrationResult migrate() { +// MigrationResult migrationResult = new MigrationResult(); +// migrationResult.setMigrationStatus(MigrationResult.MigrationStatus.COMPLETED); +// return migrationResult; +// } +//} \ No newline at end of file diff --git a/asdctool/src/main/resources/config/configuration.yaml b/asdctool/src/main/resources/config/configuration.yaml index b998e2cf1f..0421d656be 100644 --- a/asdctool/src/main/resources/config/configuration.yaml +++ b/asdctool/src/main/resources/config/configuration.yaml @@ -507,6 +507,7 @@ cassandraConfig: - { name: sdcaudit, replicationStrategy: SimpleStrategy, replicationInfo: ['1']} - { name: sdcartifact, replicationStrategy: SimpleStrategy, replicationInfo: ['1']} - { name: sdccomponent, replicationStrategy: SimpleStrategy, replicationInfo: ['1']} + - { name: sdcrepository, replicationStrategy: SimpleStrategy, replicationInfo: ['1']} switchoverDetector: diff --git a/asdctool/src/main/resources/config/logback.xml b/asdctool/src/main/resources/config/logback.xml index 0426a32d9e..dadc5254a5 100644 --- a/asdctool/src/main/resources/config/logback.xml +++ b/asdctool/src/main/resources/config/logback.xml @@ -4,7 +4,16 @@ - + + + + + + ${default-log-pattern} + + + + ${HOME}/asdctool/logs/${ECOMP-component-name}/${ECOMP-subcomponent-name}/debug.log @@ -65,4 +74,8 @@ + + + + \ No newline at end of file diff --git a/asdctool/src/main/resources/scripts/postMigration1707Fix.sh b/asdctool/src/main/resources/scripts/postMigration1707Fix.sh new file mode 100644 index 0000000000..56a16db70a --- /dev/null +++ b/asdctool/src/main/resources/scripts/postMigration1707Fix.sh @@ -0,0 +1,35 @@ +#!/bin/bash + +############################## +# Data Migration 1707 +############################## + +CURRENT_DIR=`pwd` +BASEDIR=$(dirname $0) + +if [ ${BASEDIR:0:1} = "/" ] +then + FULL_PATH=$BASEDIR +else + FULL_PATH=$CURRENT_DIR/$BASEDIR +fi + +source ${FULL_PATH}/baseOperation.sh + +mainClass="org.openecomp.sdc.asdctool.main.MigrationMenu" + +command="java $JVM_LOG_FILE -Xmx6000M -cp $JARS $mainClass fix-missing-info-1707 $@" +echo $command + +$command +result=$? + + + +echo "***********************************" +echo "***** $result *********************" +echo "***********************************" + +exit $result + + diff --git a/asdctool/src/main/resources/scripts/sdc-migration.sh b/asdctool/src/main/resources/scripts/sdc-migration.sh new file mode 100644 index 0000000000..1616890217 --- /dev/null +++ b/asdctool/src/main/resources/scripts/sdc-migration.sh @@ -0,0 +1,36 @@ +#!/bin/bash + +############################## +# Data Migration +############################## + +CURRENT_DIR=`pwd` +BASEDIR=$(dirname $0) + +if [ ${BASEDIR:0:1} = "/" ] +then + FULL_PATH=$BASEDIR +else + FULL_PATH=$CURRENT_DIR/$BASEDIR +fi + +source ${FULL_PATH}/baseOperation.sh + +mainClass="org.openecomp.sdc.asdctool.migration.main.MigrationMenu" + +command="java $JVM_LOG_FILE -Xmx6000M -cp $JARS $mainClass $@" +echo $command + +$command +result=$? + + + +echo "***********************************" +echo "***** $result *********************" +echo "***********************************" + +exit $result + + + diff --git a/asdctool/src/test/java/org/openecomp/sdc/asdctool/migration/DummyMigrationFactory.java b/asdctool/src/test/java/org/openecomp/sdc/asdctool/migration/DummyMigrationFactory.java new file mode 100644 index 0000000000..b16951ef02 --- /dev/null +++ b/asdctool/src/test/java/org/openecomp/sdc/asdctool/migration/DummyMigrationFactory.java @@ -0,0 +1,72 @@ +package org.openecomp.sdc.asdctool.migration; + + +import org.openecomp.sdc.asdctool.migration.core.DBVersion; +import org.openecomp.sdc.asdctool.migration.core.task.Migration; +import org.openecomp.sdc.asdctool.migration.core.task.MigrationResult; + +public class DummyMigrationFactory { + + public static Migration SUCCESSFUL_MIGRATION = new Migration() { + @Override + public String description() { + return "success mig"; + } + + @Override + public DBVersion getVersion() { + return DBVersion.fromString("1710.22"); + } + + @Override + public MigrationResult migrate() { + MigrationResult migrationResult = new MigrationResult(); + migrationResult.setMigrationStatus(MigrationResult.MigrationStatus.COMPLETED); + migrationResult.setMsg("myMsg"); + return migrationResult; + } + }; + + public static Migration FAILED_MIGRATION = new Migration() { + @Override + public String description() { + return "failed mig"; + } + + @Override + public DBVersion getVersion() { + return DBVersion.fromString("1710.22"); + } + + @Override + public MigrationResult migrate() { + MigrationResult migrationResult = new MigrationResult(); + migrationResult.setMigrationStatus(MigrationResult.MigrationStatus.FAILED); + migrationResult.setMsg("myMsg"); + return migrationResult; + } + }; + + public static Migration getMigration(String version, MigrationResult.MigrationStatus status) { + return new Migration() { + @Override + public String description() { + return "success mig"; + } + + @Override + public DBVersion getVersion() { + return DBVersion.fromString(version); + } + + @Override + public MigrationResult migrate() { + MigrationResult migrationResult = new MigrationResult(); + migrationResult.setMigrationStatus(status); + migrationResult.setMsg("myMsg"); + return migrationResult; + } + }; + } + +} diff --git a/asdctool/src/test/java/org/openecomp/sdc/asdctool/migration/core/DBVersionTest.java b/asdctool/src/test/java/org/openecomp/sdc/asdctool/migration/core/DBVersionTest.java new file mode 100644 index 0000000000..4e5fd3ab31 --- /dev/null +++ b/asdctool/src/test/java/org/openecomp/sdc/asdctool/migration/core/DBVersionTest.java @@ -0,0 +1,57 @@ +package org.openecomp.sdc.asdctool.migration.core; + +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; + +public class DBVersionTest { + + + @DataProvider(name = "invalidVersionStringsProvider") + private Object[][] invalidVersionStringsProvider() { + return new Object[][] { + {"1.1.1"}, + {"1.a"}, + {"a.1"}, + {"1"} + }; + } + + @Test(dataProvider = "invalidVersionStringsProvider", expectedExceptions = MigrationException.class) + public void testFromString_invalidVersionString(String invalidVersion) { + DBVersion.fromString(invalidVersion); + } + + @DataProvider(name = "validVersionStringsProvider") + private Object[][] validVersionStringsProvider() { + return new Object[][] { + {"1.1", "1.1"}, + {"10100.0001", "10100.1"}, + {"000.1", "0.1"}, + {"01.00001000", "1.1000"}, + }; + } + + @Test(dataProvider = "validVersionStringsProvider") + public void testFromString(String validString, String expectedVersionString) { + assertEquals(expectedVersionString, DBVersion.fromString(validString).toString()); + } + + @DataProvider(name = "versionComparisionProvider") + public static Object[][] versionComparisionProvider() { + return new Object[][] { + {"1.1", "001.00001", 0}, + {"10.1", "0010.00001", 0}, + {"1.1", "001.000010", -1}, + {"1.1", "0010.00001", -1}, + {"10.10", "0010.00001", 1}, + {"1.1", "001.00", 1}, + }; + } + + @Test(dataProvider = "versionComparisionProvider") + public void testVersionCompareTo2(String firstVersion, String otherVersion, int expectedComparisionResult) throws Exception { + assertEquals(DBVersion.fromString(firstVersion).compareTo(DBVersion.fromString(otherVersion)), expectedComparisionResult); + } +} diff --git a/asdctool/src/test/java/org/openecomp/sdc/asdctool/migration/core/SdcMigrationToolTest.java b/asdctool/src/test/java/org/openecomp/sdc/asdctool/migration/core/SdcMigrationToolTest.java new file mode 100644 index 0000000000..b1813227e2 --- /dev/null +++ b/asdctool/src/test/java/org/openecomp/sdc/asdctool/migration/core/SdcMigrationToolTest.java @@ -0,0 +1,101 @@ +package org.openecomp.sdc.asdctool.migration.core; + +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.mockito.internal.verification.Times; +import org.openecomp.sdc.asdctool.migration.core.task.Migration; +import org.openecomp.sdc.asdctool.migration.core.task.MigrationResult; +import org.openecomp.sdc.asdctool.migration.resolver.MigrationResolver; +import org.openecomp.sdc.asdctool.migration.service.SdcRepoService; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import java.util.Arrays; +import java.util.Collections; + +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +public class SdcMigrationToolTest { + + @InjectMocks + private SdcMigrationTool testInstance = spy(SdcMigrationTool.class); + + @Mock + private MigrationResolver migrationResolverMock; + + @Mock + private SdcRepoService sdcRepoServiceMock; + + @BeforeMethod + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + } + + @Test + public void testMigrate_noMigrations() throws Exception { + when(migrationResolverMock.resolveMigrations()).thenReturn(Collections.emptyList()); + testInstance.migrate(false); + verify(sdcRepoServiceMock, new Times(0)).clearTasksForCurrentMajor(); + verify(sdcRepoServiceMock, new Times(0)).createMigrationTask(Mockito.any()); + } + + @Test + public void testMigrate_enforceFlag_removeAllMigrationTasksForCurrentVersion() throws Exception { + when(migrationResolverMock.resolveMigrations()).thenReturn(Collections.emptyList()); + testInstance.migrate(true); + verify(sdcRepoServiceMock, new Times(1)).clearTasksForCurrentMajor(); + } + + @Test + public void testMigrate_stopAfterFirstFailure() throws Exception { + when(migrationResolverMock.resolveMigrations()).thenReturn(Arrays.asList(new SuccessfulMigration(), new FailedMigration(), new SuccessfulMigration())); + testInstance.migrate(false); + verify(sdcRepoServiceMock, new Times(0)).clearTasksForCurrentMajor(); + verify(sdcRepoServiceMock, new Times(1)).createMigrationTask(Mockito.any()); + + } + + private class FailedMigration implements Migration { + + @Override + public String description() { + return null; + } + + @Override + public DBVersion getVersion() { + return DBVersion.fromString("1710.22"); + } + + @Override + public MigrationResult migrate() { + MigrationResult migrationResult = new MigrationResult(); + migrationResult.setMigrationStatus(MigrationResult.MigrationStatus.FAILED); + return migrationResult; + } + } + + private class SuccessfulMigration implements Migration { + + @Override + public String description() { + return null; + } + + @Override + public DBVersion getVersion() { + return DBVersion.fromString("1710.22"); + } + + @Override + public MigrationResult migrate() { + MigrationResult migrationResult = new MigrationResult(); + migrationResult.setMigrationStatus(MigrationResult.MigrationStatus.COMPLETED); + return migrationResult; + } + } +} diff --git a/asdctool/src/test/java/org/openecomp/sdc/asdctool/migration/core/execution/MigrationExecutorImplTest.java b/asdctool/src/test/java/org/openecomp/sdc/asdctool/migration/core/execution/MigrationExecutorImplTest.java new file mode 100644 index 0000000000..763d6c83d2 --- /dev/null +++ b/asdctool/src/test/java/org/openecomp/sdc/asdctool/migration/core/execution/MigrationExecutorImplTest.java @@ -0,0 +1,47 @@ +package org.openecomp.sdc.asdctool.migration.core.execution; + +import org.openecomp.sdc.asdctool.migration.core.DBVersion; +import org.openecomp.sdc.asdctool.migration.core.task.Migration; +import org.openecomp.sdc.asdctool.migration.core.task.MigrationResult; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotNull; + +public class MigrationExecutorImplTest { + + @Test + public void testExecuteMigration() throws Exception { + MigrationExecutionResult execute = new MigrationExecutorImpl().execute(new DummyMigration()); + + } + + private void assertMigrationTaskEntryByMigrationExecutionResult(MigrationExecutionResult executionResult, Migration migration, MigrationResult result) { + assertEquals(executionResult.getMsg(), result.getMsg()); + assertEquals(executionResult.getMigrationStatus().name(), result.getMigrationStatus()); + assertEquals(executionResult.getTaskName(), migration.getClass().getName()); + assertEquals(executionResult.getVersion(), migration.getVersion()); + assertNotNull(executionResult.getExecutionTime()); + } + + private class DummyMigration implements Migration { + + @Override + public String description() { + return null; + } + + @Override + public DBVersion getVersion() { + return DBVersion.fromString("1710.22"); + } + + @Override + public MigrationResult migrate() { + MigrationResult migrationResult = new MigrationResult(); + migrationResult.setMigrationStatus(MigrationResult.MigrationStatus.COMPLETED); + migrationResult.setMsg("myMsg"); + return migrationResult; + } + } +} diff --git a/asdctool/src/test/java/org/openecomp/sdc/asdctool/migration/resolver/SpringBeansMigrationResolverTest.java b/asdctool/src/test/java/org/openecomp/sdc/asdctool/migration/resolver/SpringBeansMigrationResolverTest.java new file mode 100644 index 0000000000..6084608f0e --- /dev/null +++ b/asdctool/src/test/java/org/openecomp/sdc/asdctool/migration/resolver/SpringBeansMigrationResolverTest.java @@ -0,0 +1,84 @@ +package org.openecomp.sdc.asdctool.migration.resolver; + +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.openecomp.sdc.asdctool.migration.core.DBVersion; +import org.openecomp.sdc.asdctool.migration.core.task.Migration; +import org.openecomp.sdc.asdctool.migration.core.task.MigrationResult; +import org.openecomp.sdc.asdctool.migration.service.SdcRepoService; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import static org.mockito.Mockito.when; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; + +public class SpringBeansMigrationResolverTest { + + @InjectMocks + private SpringBeansMigrationResolver testInstance; + + @Mock + private SdcRepoService sdcRepoServiceMock; + + private List migrations = Arrays.asList(createMigration("1710.1"), createMigration("1710.22"), createMigration("1707.12"), createMigration("1710.3")); + + + @BeforeMethod + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + testInstance.setMigrations(migrations); + } + + @Test + public void testResolveMigrations_getMigrationsWithVersionGreaterThanLatest() throws Exception { + when(sdcRepoServiceMock.getLatestDBVersion()).thenReturn(DBVersion.fromString("1710.2")); + List resolvedMigrations = testInstance.resolveMigrations(); + assertEquals(resolvedMigrations.size(), 2); + assertEquals(resolvedMigrations.get(0).getVersion(), DBVersion.fromString("1710.3")); + assertEquals(resolvedMigrations.get(1).getVersion(), DBVersion.fromString("1710.22")); + } + + @Test + public void testResolveMigration_noLatestVersionForCurrentMajorVersion() throws Exception { + when(sdcRepoServiceMock.getLatestDBVersion()).thenReturn(DBVersion.fromString("1710.-1")); + List resolvedMigrations = testInstance.resolveMigrations(); + assertEquals(resolvedMigrations.size(), 3); + assertEquals(resolvedMigrations.get(0).getVersion(), DBVersion.fromString("1710.1")); + assertEquals(resolvedMigrations.get(1).getVersion(), DBVersion.fromString("1710.3")); + assertEquals(resolvedMigrations.get(2).getVersion(), DBVersion.fromString("1710.22")); + } + + @Test + public void testResolveMigrations_emptyMigrationsList() throws Exception { + testInstance.setMigrations(Collections.emptyList()); + when(sdcRepoServiceMock.getLatestDBVersion()).thenReturn(DBVersion.fromString("1710.-1")); + List resolvedMigrations = testInstance.resolveMigrations(); + assertTrue(resolvedMigrations.isEmpty()); + } + + private Migration createMigration(String version) { + return new Migration() { + @Override + public String description() { + return null; + } + + @Override + public DBVersion getVersion() { + return DBVersion.fromString(version); + } + + @Override + public MigrationResult migrate() { + return null; + } + }; + } + +} diff --git a/asdctool/src/test/java/org/openecomp/sdc/asdctool/migration/scanner/ClassScanner.java b/asdctool/src/test/java/org/openecomp/sdc/asdctool/migration/scanner/ClassScanner.java new file mode 100644 index 0000000000..a2bf623b83 --- /dev/null +++ b/asdctool/src/test/java/org/openecomp/sdc/asdctool/migration/scanner/ClassScanner.java @@ -0,0 +1,81 @@ +package org.openecomp.sdc.asdctool.migration.scanner; + +import org.apache.commons.io.FileUtils; +import org.openecomp.sdc.asdctool.migration.core.MigrationException; + +import java.io.File; +import java.lang.reflect.Modifier; +import java.net.URL; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Optional; + +/** + * scan and instantiate classes of given type in the class path + */ +public class ClassScanner { + + + private ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + + public List getAllClassesOfType(String basePackage, Class ofType) { + Collection allClassesInPackage = getAllClassesInPackage(basePackage); + List loadedClasses = new ArrayList<>(); + for (File clazzFile : allClassesInPackage) { + Optional instance = loadAndInstantiateClass(getClassReference(clazzFile), ofType); + instance.ifPresent(loadedClasses::add); + } + return loadedClasses; + } + + private Optional loadAndInstantiateClass(String classReference, Class ofType) { + try { + return instantiateClassOfType(classReference, ofType); + }catch (ClassNotFoundException e) { + //log + throw new MigrationException(String.format("could not find class %s of type %s. cause: %s", classReference, ofType.toGenericString(), e.getMessage())); + } catch (IllegalAccessException e1) { + //log + throw new MigrationException(String.format("could not instantiate class %s of type %s. class is not accessible. cause: %s", classReference, ofType.toGenericString(), e1.getMessage())); + } catch (InstantiationException e2) { + //log + throw new MigrationException(String.format("could not instantiate class %s of type %s. cause: %s", classReference, ofType.toGenericString(), e2.getMessage())); + } + } + + private Optional instantiateClassOfType(String classReference, Class ofType) throws ClassNotFoundException, IllegalAccessException, InstantiationException { + String className = classReference.replaceAll(".class$", "").replaceAll(".class", ""); + Class aClass = classLoader.loadClass(className); + if (ofType.isAssignableFrom(aClass) && isInstantiateAbleClass(aClass)){ + return Optional.of((T) aClass.newInstance()); + } + return Optional.empty(); + } + + private boolean isInstantiateAbleClass(Class clazz) { + return !Modifier.isAbstract(clazz.getModifiers()) && !clazz.isEnum() && !clazz.isAnonymousClass() && !clazz.isInterface(); + } + + private Collection getAllClassesInPackage(String fromPackage) { + String path = fromPackage.replace(".", "/"); + URL resource = classLoader.getResource(path); + if (noMigrationTasks(resource)) { + return Collections.emptyList(); + } + return FileUtils.listFiles(new File(resource.getFile()), new String[]{"class"}, true); + } + + private boolean noMigrationTasks(URL resource) { + return resource == null; + } + + private String getClassReference(File classFile) { + String asPackage = classFile.getPath().replace(File.separator, "."); + String classes = "classes."; + return asPackage.substring(asPackage.indexOf(classes) + classes.length()); + } + + +} diff --git a/asdctool/src/test/java/org/openecomp/sdc/asdctool/migration/service/SdcRepoServiceTest.java b/asdctool/src/test/java/org/openecomp/sdc/asdctool/migration/service/SdcRepoServiceTest.java new file mode 100644 index 0000000000..f8e9abe2c9 --- /dev/null +++ b/asdctool/src/test/java/org/openecomp/sdc/asdctool/migration/service/SdcRepoServiceTest.java @@ -0,0 +1,55 @@ +package org.openecomp.sdc.asdctool.migration.service; + +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.mockito.internal.verification.Times; +import org.openecomp.sdc.asdctool.migration.core.DBVersion; +import org.openecomp.sdc.be.dao.cassandra.MigrationTasksDao; +import org.openecomp.sdc.be.resources.data.MigrationTaskEntry; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import java.math.BigInteger; + +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static org.testng.Assert.assertEquals; + +public class SdcRepoServiceTest { + + @InjectMocks + private SdcRepoService testInstance; + + @Mock + private MigrationTasksDao migrationTasksDaoMock; + + @BeforeMethod + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + } + + @Test + public void testGetLatestVersion_noMinorVersionForCurrentVersion() throws Exception { + when(migrationTasksDaoMock.getLatestMinorVersion(DBVersion.CURRENT_VERSION.getMajor())).thenReturn(null); + DBVersion latestDBVersion = testInstance.getLatestDBVersion(); + assertEquals(latestDBVersion.getMajor(), DBVersion.CURRENT_VERSION.getMajor()); + assertEquals(latestDBVersion.getMinor(), BigInteger.valueOf(Integer.MIN_VALUE)); + } + + @Test + public void testGetLatestVersion() throws Exception { + when(migrationTasksDaoMock.getLatestMinorVersion(DBVersion.CURRENT_VERSION.getMajor())).thenReturn(BigInteger.TEN); + DBVersion latestDBVersion = testInstance.getLatestDBVersion(); + assertEquals(latestDBVersion.getMajor(), DBVersion.CURRENT_VERSION.getMajor()); + assertEquals(latestDBVersion.getMinor(), BigInteger.TEN); + } + + @Test + public void testCreateMigrationTask() throws Exception { + MigrationTaskEntry taskEntry = new MigrationTaskEntry(); + testInstance.createMigrationTask(taskEntry); + verify(migrationTasksDaoMock, new Times(1)).createMigrationTask(taskEntry); + } + +} diff --git a/asdctool/src/test/java/org/openecomp/sdc/asdctool/migration/task/MigrationTasksTest.java b/asdctool/src/test/java/org/openecomp/sdc/asdctool/migration/task/MigrationTasksTest.java new file mode 100644 index 0000000000..037d51ba12 --- /dev/null +++ b/asdctool/src/test/java/org/openecomp/sdc/asdctool/migration/task/MigrationTasksTest.java @@ -0,0 +1,56 @@ +package org.openecomp.sdc.asdctool.migration.task; + +import org.apache.commons.lang.StringUtils; +import org.openecomp.sdc.asdctool.migration.core.DBVersion; +import org.openecomp.sdc.asdctool.migration.core.task.Migration; +import org.openecomp.sdc.asdctool.migration.scanner.ClassScanner; +import org.testng.Assert; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + + +public class MigrationTasksTest { + + public static final String MIGRATIONS_BASE_PACKAGE = "org.openecomp.sdc.asdctool.migration.tasks"; + private List migrations; + + @BeforeMethod + public void setUp() throws Exception { + ClassScanner classScanner = new ClassScanner(); + migrations = classScanner.getAllClassesOfType(MIGRATIONS_BASE_PACKAGE, Migration.class); + } + + @Test + public void testNoTasksWithSameVersion() throws Exception { + Map> migrationsByVersion = migrations.stream().collect(Collectors.groupingBy(Migration::getVersion)); + migrationsByVersion.forEach((version, migrations) -> { + if (migrations.size() > 1) { + System.out.println(String.format("the following migration tasks have the same version %s. versions must be unique", version.toString())); + Assert.fail(String.format("migration tasks %s has same version %s. migration tasks versions must be unique.", getMigrationsNameAsString(migrations), version.toString())); + } + }); + } + + @Test + public void testNoTaskWithVersionGreaterThanCurrentVersion() throws Exception { + Set migrationsWithVersionsGreaterThanCurrent = migrations.stream().filter(mig -> mig.getVersion().compareTo(DBVersion.CURRENT_VERSION) > 0) + .collect(Collectors.toSet()); + + if (!migrationsWithVersionsGreaterThanCurrent.isEmpty()) { + Assert.fail(String.format("migrations tasks %s have version which is greater than DBVersion.CURRENT_VERSION %s. did you forget to update current version?", + getMigrationsNameAsString(migrationsWithVersionsGreaterThanCurrent), + DBVersion.CURRENT_VERSION.toString())); + } + } + + private String getMigrationsNameAsString(Collection migrations) { + return StringUtils.join(migrations.stream().map(mig -> mig.getClass().getName()).collect(Collectors.toList()), ","); + } +} diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ArtifactsBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ArtifactsBusinessLogic.java index cec045d8a3..ebdfe22185 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ArtifactsBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ArtifactsBusinessLogic.java @@ -340,10 +340,14 @@ public class ArtifactsBusinessLogic extends BaseBusinessLogic { private boolean artifactGenerationRequired(org.openecomp.sdc.be.model.Component component, ArtifactDefinition artifactInfo) { boolean needGenerate; needGenerate = artifactInfo.getArtifactGroupType() == ArtifactGroupTypeEnum.TOSCA && (component.getLifecycleState() == LifecycleStateEnum.NOT_CERTIFIED_CHECKIN || component.getLifecycleState() == LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT); - needGenerate = needGenerate || (ComponentTypeEnum.RESOURCE == component.getComponentType() && artifactInfo.getArtifactType().equalsIgnoreCase(ArtifactTypeEnum.HEAT_ENV.getType())); + needGenerate = needGenerate || (ComponentTypeEnum.RESOURCE == component.getComponentType() && (artifactInfo.getArtifactType().equalsIgnoreCase(ArtifactTypeEnum.HEAT_ENV.getType()) || isAbstractVfcEmptyCsar((Resource) component, artifactInfo))); return needGenerate; } + private boolean isAbstractVfcEmptyCsar(Resource resource, ArtifactDefinition artifactInfo) { + return resource.isAbstract() && artifactInfo.getArtifactGroupType() == ArtifactGroupTypeEnum.TOSCA && artifactInfo.getArtifactType().equals(ArtifactTypeEnum.TOSCA_CSAR.getType()) && StringUtils.isEmpty(artifactInfo.getArtifactChecksum()); + } + public Either, ResponseFormat> generateAndSaveToscaArtifact(ArtifactDefinition artifactDefinition, org.openecomp.sdc.be.model.Component component, User user, boolean isInCertificationRequest, boolean shouldLock, boolean inTransaction, boolean fetchTemplatesFromDB) { @@ -798,13 +802,13 @@ public class ArtifactsBusinessLogic extends BaseBusinessLogic { return Either.left(artifactResult.left().value()); } - private Either, ResponseFormat> handleCreate(String parentId, ArtifactDefinition artifactInfo, ArtifactOperationInfo operation, AuditingActionEnum auditingAction, User user, ComponentTypeEnum componentType, + private Either, ResponseFormat> handleCreate(String componentId, ArtifactDefinition artifactInfo, ArtifactOperationInfo operation, AuditingActionEnum auditingAction, User user, ComponentTypeEnum componentType, org.openecomp.sdc.be.model.Component parent, String origMd5, String originData, String interfaceType, String operationName, boolean shouldLock, boolean inTransaction) { String artifactId = null; // step 11 - Either payloadEither = validateInput(parentId, artifactInfo, operation, auditingAction, artifactId, user, componentType, parent, origMd5, originData, interfaceType, operationName, inTransaction); + Either payloadEither = validateInput(componentId, artifactInfo, operation, auditingAction, artifactId, user, componentType, parent, origMd5, originData, interfaceType, operationName, inTransaction); if (payloadEither.isRight()) { return Either.right(payloadEither.right().value()); } @@ -814,14 +818,14 @@ public class ArtifactsBusinessLogic extends BaseBusinessLogic { if (shouldLock) { Either lockComponent = lockComponent(parent, "Upload Artifact - lock "); if (lockComponent.isRight()) { - handleAuditing(auditingAction, parent, parentId, user, null, null, null, lockComponent.right().value(), componentType, null); + handleAuditing(auditingAction, parent, componentId, user, null, null, null, lockComponent.right().value(), componentType, null); return Either.right(lockComponent.right().value()); } } Either, ResponseFormat> resultOp = null; try { - resultOp = createArtifact(parent, parentId, artifactInfo, decodedPayload, user, componentType, auditingAction, interfaceType, operationName); + resultOp = createArtifact(parent, componentId, artifactInfo, decodedPayload, user, componentType, auditingAction, interfaceType, operationName); return resultOp; } finally { if (shouldLock) { @@ -872,28 +876,28 @@ public class ArtifactsBusinessLogic extends BaseBusinessLogic { return lockComponentAndUpdateArtifact(parentId, artifactInfo, auditingAction, artifactId, user, componentType, parent, decodedPayload, interfaceType, operationName, shouldLock, inTransaction); } - private Either validateInput(String parentId, ArtifactDefinition artifactInfo, ArtifactOperationInfo operation, AuditingActionEnum auditingAction, String artifactId, User user, ComponentTypeEnum componentType, + private Either validateInput(String componentId, ArtifactDefinition artifactInfo, ArtifactOperationInfo operation, AuditingActionEnum auditingAction, String artifactId, User user, ComponentTypeEnum componentType, org.openecomp.sdc.be.model.Component parent, String origMd5, String originData, String interfaceType, String operationName, boolean inTransaction) { // Md5 validations Either validateMd5 = validateMd5(origMd5, originData, artifactInfo.getPayloadData(), operation); if (validateMd5.isRight()) { ResponseFormat responseFormat = validateMd5.right().value(); - handleAuditing(auditingAction, parent, parentId, user, null, null, artifactId, responseFormat, componentType, null); + handleAuditing(auditingAction, parent, componentId, user, null, null, artifactId, responseFormat, componentType, null); return Either.right(responseFormat); } // step 11 - Either validateResult = validateInput(parentId, artifactInfo, operation, artifactId, user, interfaceType, operationName, componentType, parent, inTransaction); + Either validateResult = validateInput(componentId, artifactInfo, operation, artifactId, user, interfaceType, operationName, componentType, parent, inTransaction); if (validateResult.isRight()) { ResponseFormat responseFormat = validateResult.right().value(); - handleAuditing(auditingAction, parent, parentId, user, null, null, artifactId, responseFormat, componentType, null); + handleAuditing(auditingAction, parent, componentId, user, null, null, artifactId, responseFormat, componentType, null); return Either.right(validateResult.right().value()); } Either payloadEither = handlePayload(artifactInfo, isArtifactMetadataUpdate(auditingAction)); if (payloadEither.isRight()) { ResponseFormat responseFormat = payloadEither.right().value(); - handleAuditing(auditingAction, parent, parentId, user, null, null, artifactId, responseFormat, componentType, null); + handleAuditing(auditingAction, parent, componentId, user, null, null, artifactId, responseFormat, componentType, null); log.debug("Error during handle payload"); return Either.right(responseFormat); } @@ -903,7 +907,7 @@ public class ArtifactsBusinessLogic extends BaseBusinessLogic { Either validateAndConvertHeatParamers = validateAndConvertHeatParamers(artifactInfo, artifactInfo.getArtifactType()); if (validateAndConvertHeatParamers.isRight()) { ResponseFormat responseFormat = validateAndConvertHeatParamers.right().value(); - handleAuditing(auditingAction, parent, parentId, user, artifactInfo, null, artifactId, responseFormat, componentType, null); + handleAuditing(auditingAction, parent, componentId, user, artifactInfo, null, artifactId, responseFormat, componentType, null); log.debug("Error during handle payload"); return Either.right(responseFormat); } @@ -1025,9 +1029,16 @@ public class ArtifactsBusinessLogic extends BaseBusinessLogic { return Either.left(true); } - private Either validateInput(String parentId, ArtifactDefinition artifactInfo, ArtifactOperationInfo operation, String artifactId, User user, String interfaceName, String operationName, + private Either validateInput(String componentId, ArtifactDefinition artifactInfo, ArtifactOperationInfo operation, String artifactId, User user, String interfaceName, String operationName, ComponentTypeEnum componentType, Component parentComponent, boolean inTransaction) { + Either artifactById = findArtifactOnParentComponent(parentComponent, componentType, componentId, operation, artifactId); + if (artifactById.isRight()) { + return Either.right(artifactById.right().value()); + } + ArtifactDefinition currentArtifactInfo = artifactById.left().value(); + + ignoreUnupdateableFieldsInUpdate(operation, artifactInfo, currentArtifactInfo); Either validateInformationalArtifactRes = validateInformationalArtifact(artifactInfo, parentComponent); if (validateInformationalArtifactRes.isRight()) { return Either.right(validateInformationalArtifactRes.right().value()); @@ -1036,16 +1047,11 @@ public class ArtifactsBusinessLogic extends BaseBusinessLogic { if (validateAndSetArtifactname.isRight()) { return Either.right(validateAndSetArtifactname.right().value()); } - Either artifactById = findArtifactOnParentComponent(parentComponent, componentType, parentId, operation, artifactId); - if (artifactById.isRight()) { - return Either.right(artifactById.right().value()); - } - ArtifactDefinition currentArtifactInfo = artifactById.left().value(); if (operationName != null && interfaceName != null) { operationName = operationName.toLowerCase(); interfaceName = interfaceName.toLowerCase(); } - Either logicalNameStatus = handleArtifactLabel(parentId, operation, artifactId, artifactInfo, interfaceName, operationName, currentArtifactInfo, componentType, inTransaction); + Either logicalNameStatus = handleArtifactLabel(componentId, parentComponent, operation, artifactId, artifactInfo, interfaceName, operationName, currentArtifactInfo, componentType); if (logicalNameStatus.isRight()) { return Either.right(logicalNameStatus.right().value()); } @@ -1058,7 +1064,7 @@ public class ArtifactsBusinessLogic extends BaseBusinessLogic { checkCreateFields(user, artifactInfo, (operationName != null ? ArtifactGroupTypeEnum.LIFE_CYCLE : ArtifactGroupTypeEnum.INFORMATIONAL)); } - composeArtifactId(parentId, artifactId, artifactInfo, interfaceName, operationName); + composeArtifactId(componentId, artifactId, artifactInfo, interfaceName, operationName); if (currentArtifactInfo != null) { artifactInfo.setMandatory(currentArtifactInfo.getMandatory()); } @@ -1077,7 +1083,7 @@ public class ArtifactsBusinessLogic extends BaseBusinessLogic { boolean isCreate = operation.getArtifactOperationEnum() == ArtifactOperationEnum.Create; if (isDeploymentArtifact(artifactInfo)) { - Either deploymentValidationResult = validateDeploymentArtifact(parentComponent, parentId, user.getUserId(), isCreate, artifactInfo, currentArtifactInfo, parentType); + Either deploymentValidationResult = validateDeploymentArtifact(parentComponent, componentId, user.getUserId(), isCreate, artifactInfo, currentArtifactInfo, parentType); if (deploymentValidationResult.isRight()) { return Either.right(deploymentValidationResult.right().value()); } @@ -1135,6 +1141,14 @@ public class ArtifactsBusinessLogic extends BaseBusinessLogic { return Either.left(artifactInfo); } + private void ignoreUnupdateableFieldsInUpdate(ArtifactOperationInfo operation, ArtifactDefinition artifactInfo, ArtifactDefinition currentArtifactInfo) { + if(operation.getArtifactOperationEnum().equals(ArtifactOperationEnum.Update)){ + artifactInfo.setArtifactType(currentArtifactInfo.getArtifactType()); + artifactInfo.setArtifactGroupType(currentArtifactInfo.getArtifactGroupType()); + artifactInfo.setArtifactLabel(currentArtifactInfo.getArtifactLabel()); + } + } + private Either findArtifactOnParentComponent(Component parentComponent, ComponentTypeEnum componentType, String parentId, ArtifactOperationInfo operation, String artifactId) { Either result = null; @@ -1474,13 +1488,13 @@ public class ArtifactsBusinessLogic extends BaseBusinessLogic { private void resetMandatoryArtifactFields(ArtifactDefinition fetchedArtifact) { if (fetchedArtifact != null) { log.debug("Going to reset mandatory artifact {} fields. ", fetchedArtifact.getUniqueId()); - fetchedArtifact.setEsId(""); - fetchedArtifact.setArtifactName(""); - fetchedArtifact.setDescription(""); - fetchedArtifact.setApiUrl(""); - fetchedArtifact.setArtifactChecksum(""); + fetchedArtifact.setEsId(null); + fetchedArtifact.setArtifactName(null); + fetchedArtifact.setDescription(null); + fetchedArtifact.setApiUrl(null); + fetchedArtifact.setArtifactChecksum(null); nodeTemplateOperation.setDefaultArtifactTimeout(fetchedArtifact.getArtifactGroupType(), fetchedArtifact); - fetchedArtifact.setArtifactUUID(""); + fetchedArtifact.setArtifactUUID(null); long time = System.currentTimeMillis(); fetchedArtifact.setPayloadUpdateDate(time); fetchedArtifact.setHeatParameters(null); @@ -1540,10 +1554,10 @@ public class ArtifactsBusinessLogic extends BaseBusinessLogic { return Either.left(currentArtifactInfo); } - private Either handleArtifactLabel(String componentId, ArtifactOperationInfo operation, String artifactId, ArtifactDefinition artifactInfo, String interfaceName, String operationName, - ArtifactDefinition currentArtifactInfo, ComponentTypeEnum componentType, boolean inTransaction) { - String artifactLabel = artifactInfo.getArtifactLabel(); + private Either handleArtifactLabel(String componentId, Component parentComponent, ArtifactOperationInfo operation, String artifactId, ArtifactDefinition artifactInfo, String interfaceName, String operationName, + ArtifactDefinition currentArtifactInfo, ComponentTypeEnum componentType) { + String artifactLabel = artifactInfo.getArtifactLabel(); if (operationName == null && (artifactInfo.getArtifactLabel() == null || artifactInfo.getArtifactLabel().isEmpty())) { BeEcompErrorManager.getInstance().logBeMissingArtifactInformationError("Artifact Update / Upload", "artifactLabel"); log.debug("missing artifact logical name for component {}", componentId); @@ -1584,27 +1598,25 @@ public class ArtifactsBusinessLogic extends BaseBusinessLogic { log.debug("Invalid lenght form Artifact label : {}", artifactLabel); return Either.right(componentsUtils.getResponseFormat(ActionStatus.EXCEEDS_LIMIT, ARTIFACT_LABEL, String.valueOf(ValidationUtils.ARTIFACT_LABEL_LENGTH))); } - if (!validateLabelUniqueness(componentId, artifactLabel, componentType)) { + if (!validateLabelUniqueness(componentId, parentComponent, artifactLabel, componentType)) { log.debug("Non unique Artifact label : {}", artifactLabel); return Either.right(componentsUtils.getResponseFormat(ActionStatus.ARTIFACT_EXIST, artifactLabel)); } } artifactInfo.setArtifactLabel(artifactLabel); - if (currentArtifactInfo != null && !currentArtifactInfo.getArtifactLabel().equals(artifactInfo.getArtifactLabel())) { - log.info("Logical artifact's name cannot be changed {}", artifactId); - return Either.right(componentsUtils.getResponseFormat(ActionStatus.ARTIFACT_LOGICAL_NAME_CANNOT_BE_CHANGED)); - } return Either.left(ActionStatus.OK); } - private boolean validateLabelUniqueness(String parentId, String artifactLabel, ComponentTypeEnum componentType) { + private boolean validateLabelUniqueness(String componentId, Component parentComponent, String artifactLabel, ComponentTypeEnum componentType) { boolean isUnique = true; - if (componentType.equals(ComponentTypeEnum.RESOURCE)) { + Either, StorageOperationStatus> artifacts; + if (componentType.equals(ComponentTypeEnum.RESOURCE_INSTANCE)) { + artifacts = artifactToscaOperation.getAllInstanceArtifacts(parentComponent.getUniqueId(), componentId); } else { + artifacts = artifactToscaOperation.getArtifacts(componentId); } - // Either, StorageOperationStatus> artifacts = artifactOperation.getArtifacts(parentId, parentType, inTransaction); - Either, StorageOperationStatus> artifacts = artifactToscaOperation.getArtifacts(parentId); + if (artifacts.isLeft()) { for (String label : artifacts.left().value().keySet()) { if (label.equals(artifactLabel)) { @@ -1614,7 +1626,7 @@ public class ArtifactsBusinessLogic extends BaseBusinessLogic { } } if (componentType.equals(ComponentTypeEnum.RESOURCE)) { - Either, StorageOperationStatus> allInterfacesOfResource = interfaceLifecycleOperation.getAllInterfacesOfResource(parentId, true, true); + Either, StorageOperationStatus> allInterfacesOfResource = interfaceLifecycleOperation.getAllInterfacesOfResource(componentId, true, true); if (allInterfacesOfResource.isLeft()) { for (InterfaceDefinition interace : allInterfacesOfResource.left().value().values()) { for (Operation operation : interace.getOperationsMap().values()) { @@ -3886,7 +3898,7 @@ public class ArtifactsBusinessLogic extends BaseBusinessLogic { * currently getArtifactById does not retrieve heatParameters Either artifactRes = artifactOperation.getArtifactById(artifactId, false); ArtifactDefinition currArtifact = artifactRes.left().value(); */ String currentHeatId = currHeatArtifact.getUniqueId(); - + String esArtifactId = currHeatArtifact.getEsId(); Either artifactfromES = artifactCassandraDao.getArtifact(esArtifactId); if (artifactfromES.isRight()) { @@ -3899,8 +3911,8 @@ public class ArtifactsBusinessLogic extends BaseBusinessLogic { ESArtifactData esArtifactData = artifactfromES.left().value(); byte[] data = esArtifactData.getDataAsArray(); - - + + ArtifactDefinition updatedHeatArt = currHeatArtifact; List updatedHeatEnvParams = artifactEnvInfo.getListHeatParameters(); @@ -3949,7 +3961,7 @@ public class ArtifactsBusinessLogic extends BaseBusinessLogic { if (!updatedHeatArt.getDuplicated() || esArtifactData.getId() == null) esArtifactData.setId(updatedHeatArt.getEsId()); res = saveArtifacts(esArtifactData, parent.getUniqueId(), false); - + if (res) { log.debug("Artifact saved into ES - {}", updatedHeatArt.getUniqueId()); ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.OK); @@ -3964,7 +3976,7 @@ public class ArtifactsBusinessLogic extends BaseBusinessLogic { resultOp = Either.right(responseFormat); // return resultOp; } - + insideEither = Either.left(updatedHeatArt); } } @@ -3976,13 +3988,17 @@ public class ArtifactsBusinessLogic extends BaseBusinessLogic { updateHeatEnvArtifact = artifactToscaOperation.updateHeatEnvPlaceholder(artifactEnvInfo, componentId, componentType.getNodeType()); } - if ( needToUpdateGroup && updateHeatEnvArtifact.isLeft() ){ + if (needToUpdateGroup && updateHeatEnvArtifact.isLeft()) { ActionStatus result = updateGroupForHeat(currHeatArtifact, updatedHeatArt, artifactEnvInfo, updateHeatEnvArtifact.left().value(), parent, componentType); - if ( result != ActionStatus.OK ){ + if (result != ActionStatus.OK) { ResponseFormat responseFormat = componentsUtils.getResponseFormat(result); return Either.right(responseFormat); } } + + if (updatedHeatEnvParams.isEmpty()) { + return getResponseAndAuditInvalidEmptyHeatEnvFile(auditingAction, parent, parent.getUniqueId(), user, currHeatArtifact, artifactId, componentType); + } resultOp = Either.left(insideEither); ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.OK); handleAuditing(auditingAction, parent, parent.getUniqueId(), user, currHeatArtifact, null, artifactId, responseFormat, componentType, ""); @@ -3990,6 +4006,13 @@ public class ArtifactsBusinessLogic extends BaseBusinessLogic { } + private Either,ResponseFormat> getResponseAndAuditInvalidEmptyHeatEnvFile(AuditingActionEnum auditingAction, Component parent, String uniqueId, User user, ArtifactDefinition currHeatArtifact, String artifactId, ComponentTypeEnum componentType) { + ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_YAML); + handleAuditing(auditingAction, parent, parent.getUniqueId(), user, currHeatArtifact, null, artifactId, responseFormat, componentType, ""); + return Either.right(responseFormat); + } + + private StorageOperationStatus generateCustomizationUUIDOnGroupInstance(ComponentInstance ri, String artifactId, String componentId) { StorageOperationStatus error = StorageOperationStatus.OK; log.debug("Need to re-generate customization UUID for group instance on component instance {}", ri.getUniqueId()); @@ -4092,7 +4115,7 @@ public class ArtifactsBusinessLogic extends BaseBusinessLogic { Component component = getComponentByUuid(componentType, componentUuid, errorWrapper); if (errorWrapper.isEmpty()) { auditAdditionalParam.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_NAME, component.getName()); - downloadedArtifact = downloadArtifact(component.getDeploymentArtifacts(), artifactUUID, errorWrapper, component.getName()); + downloadedArtifact = downloadArtifact(component.getAllArtifacts(), artifactUUID, errorWrapper, component.getName()); } if (errorWrapper.isEmpty()) { result = Either.left(downloadedArtifact); @@ -4733,17 +4756,17 @@ public class ArtifactsBusinessLogic extends BaseBusinessLogic { byte[] downloadedArtifact = null; Either, ResponseFormat> downloadArtifactEither = null; - List deploymentArtifacts = null; + List artifactsList = null; ArtifactDefinition deploymentArtifact = null; if (artifacts != null && !artifacts.isEmpty()) { - deploymentArtifacts = artifacts.values().stream().filter(art -> art.getArtifactUUID() != null && art.getArtifactUUID().equals(artifactUUID)).collect(Collectors.toList()); + artifactsList = artifacts.values().stream().filter(art -> art.getArtifactUUID() != null && art.getArtifactUUID().equals(artifactUUID)).collect(Collectors.toList()); } - if (deploymentArtifacts == null || deploymentArtifacts.isEmpty()) { + if (artifactsList == null || artifactsList.isEmpty()) { log.debug("Deployment artifact with uuid {} was not found for component {}", artifactUUID, componentName); errorWrapper.setInnerElement(componentsUtils.getResponseFormat(ActionStatus.ARTIFACT_NOT_FOUND, artifactUUID)); } if (errorWrapper.isEmpty()) { - deploymentArtifact = deploymentArtifacts.get(0); + deploymentArtifact = artifactsList.get(0); downloadArtifactEither = downloadArtifact(deploymentArtifact); if (downloadArtifactEither.isRight()) { log.debug("Failed to download artifact {}. ", deploymentArtifact.getArtifactName()); diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/BaseBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/BaseBusinessLogic.java index df8460ca96..1d153e0a5d 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/BaseBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/BaseBusinessLogic.java @@ -47,6 +47,7 @@ import org.openecomp.sdc.be.model.ComponentParametersView; import org.openecomp.sdc.be.model.DataTypeDefinition; import org.openecomp.sdc.be.model.GroupProperty; import org.openecomp.sdc.be.model.IComplexDefaultValue; +import org.openecomp.sdc.be.model.IPropertyInputCommon; import org.openecomp.sdc.be.model.LifecycleStateEnum; import org.openecomp.sdc.be.model.User; import org.openecomp.sdc.be.model.cache.ApplicationDataTypeCache; @@ -391,11 +392,10 @@ public abstract class BaseBusinessLogic { } protected Either validatePropertyDefaultValue(IComplexDefaultValue property, Map dataTypes) { - log.debug("validate property"); String type = null; String innerType = null; if (!propertyOperation.isPropertyTypeValid(property)) { - log.info("Invalid type for property"); + log.info("Invalid type for property {} type {}", property.getName(), property.getType()); ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_PROPERTY_TYPE, property.getType(), property.getName()); return Either.right(responseFormat); } @@ -404,13 +404,13 @@ public abstract class BaseBusinessLogic { ImmutablePair propertyInnerTypeValid = propertyOperation.isPropertyInnerTypeValid(property, dataTypes); innerType = propertyInnerTypeValid.getLeft(); if (!propertyInnerTypeValid.getRight().booleanValue()) { - log.info("Invalid inner type for property"); + log.info("Invalid inner type for property {} type {}", property.getName(), property.getType() ); ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_PROPERTY_INNER_TYPE, innerType, property.getName()); return Either.right(responseFormat); } } if (!propertyOperation.isPropertyDefaultValueValid(property, dataTypes)) { - log.info("Invalid default value for property"); + log.info("Invalid default value for property {} type {}", property.getName(), property.getType() ); ResponseFormat responseFormat; if (type.equals(ToscaPropertyType.LIST.getType()) || type.equals(ToscaPropertyType.MAP.getType())) { responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_COMPLEX_DEFAULT_VALUE, property.getName(), type, innerType, property.getDefaultValue()); @@ -568,7 +568,7 @@ public abstract class BaseBusinessLogic { return Arrays.asList(enumValues).contains(enumFound); } - protected Either validatePropValueBeforeCreate(ComponentInstanceProperty property, String value, boolean isValidate, String innerType, Map allDataTypes) { + protected Either validatePropValueBeforeCreate(IPropertyInputCommon property, String value, boolean isValidate, String innerType, Map allDataTypes) { String propertyType = property.getType(); ToscaPropertyType type = ToscaPropertyType.isValidType(propertyType); @@ -603,7 +603,7 @@ public abstract class BaseBusinessLogic { } ImmutablePair pair = validateAndUpdateRules(propertyType, property.getRules(), innerType, allDataTypes, isValidate); - log.debug("After validateAndUpdateRules. pair = {}", pair); + log.trace("After validateAndUpdateRules. pair = {}", pair); if (pair.getRight() != null && pair.getRight() == false) { BeEcompErrorManager.getInstance().logBeInvalidValueError("Add property value", pair.getLeft(), property.getName(), propertyType); return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(TitanOperationStatus.ILLEGAL_ARGUMENT)); diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/CassandraHealthCheck.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/CassandraHealthCheck.java new file mode 100644 index 0000000000..237ec6d5fe --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/CassandraHealthCheck.java @@ -0,0 +1,189 @@ +package org.openecomp.sdc.be.components.impl; + +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Set; + +import javax.annotation.PostConstruct; + +import org.openecomp.sdc.be.config.ConfigurationManager; +import org.openecomp.sdc.be.dao.cassandra.schema.SdcSchemaUtils; +import org.openecomp.sdc.be.dao.cassandra.schema.Table; +import org.openecomp.sdc.common.util.GeneralUtility; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import com.datastax.driver.core.Cluster; +import com.datastax.driver.core.KeyspaceMetadata; +import com.datastax.driver.core.Metadata; +import com.datastax.driver.core.Session; + +@Component("cassandra-health-check") +public class CassandraHealthCheck { + + + private static Logger log = LoggerFactory.getLogger(CassandraHealthCheck.class.getName()); + + private String localDataCenterName = null; + + private Set sdcKeyspaces = new HashSet(); + + private int HC_FormulaNumber; + + @PostConstruct + private void init() { + + //Initialize local data center name - this field must be filled by DevOps + localDataCenterName = ConfigurationManager.getConfigurationManager().getConfiguration().getCassandraConfig().getLocalDataCenter(); + + if (GeneralUtility.isEmptyString(localDataCenterName)) { + log.error("localDataCenter Name in configuration.yaml is missing."); + return; + } + + //Collect all SDC keyspaces + for (Table table : Table.values()) { + sdcKeyspaces.add(table.getTableDescription().getKeyspace()); + } + + String titanCfgFile = ConfigurationManager.getConfigurationManager().getConfiguration().getTitanCfgFile(); + Properties prop = new Properties(); + InputStream titanProp = null; + try { + //load a properties file + titanProp = new FileInputStream(titanCfgFile); + prop.load(titanProp); + //Add titan keyspace + String titanKeyspace = prop.getProperty("storage.cassandra.keyspace"); + if (!GeneralUtility.isEmptyString(titanKeyspace)) { + sdcKeyspaces.add(titanKeyspace); + } + } catch (Exception e) { + log.error("Failed to open titen.properties file , url is : {}", titanCfgFile); + } + + log.info("All sdc keyspaces are : {}", sdcKeyspaces); + + //Calculate the Formula of Health Check + Cluster cluster = null; + try { + + log.info("creating cluster for Cassandra Health Check."); + //Create cluster from nodes in cassandra configuration + cluster = SdcSchemaUtils.createCluster(); + if (cluster == null) { + log.error("Failure create cassandra cluster."); + return; + } + + Metadata metadata = cluster.getMetadata(); + + if (metadata == null) { + log.error("Failure get cassandra metadata."); + return; + } + + log.info("Cluster Metadata: {}", metadata.toString()); + List keyspaces = metadata.getKeyspaces(); + List replactionFactorList = new ArrayList(); + + //Collect the keyspaces Replication Factor of current localDataCenter + for (KeyspaceMetadata keyspace : keyspaces) { + + if (sdcKeyspaces.contains(keyspace.getName())) { + + log.info("keyspace : {} , replication: {}", keyspace.getName(), keyspace.getReplication()); + Map replicationOptions = keyspace.getReplication(); + + //In 1 site with one data center + if (replicationOptions.containsKey("replication_factor")) { + replactionFactorList.add(Integer.parseInt(replicationOptions.get("replication_factor"))); + } + //In multiple sites with some data center + else if (replicationOptions.containsKey(localDataCenterName)) { + replactionFactorList.add(Integer.parseInt(replicationOptions.get(localDataCenterName))); + } + } + } + + if (replactionFactorList.size() == 0) { + log.error("Replication factor NOT found in all keyspaces"); + return; + } + + int maxReplicationFactor = Collections.max(replactionFactorList); + log.info("maxReplication Factor is: {}", maxReplicationFactor); + + int localQuorum = maxReplicationFactor/2 + 1; + log.info("localQuorum is: {}", localQuorum); + + HC_FormulaNumber = maxReplicationFactor - localQuorum; + + log.info("Health Check formula : Replication Factor – Local_Quorum = {}", HC_FormulaNumber); + + + } catch (Exception e) { + log.error("create cassandra cluster failed with exception.", e); + } finally { + if (cluster != null) { + cluster.close(); + } + } + + } + + public boolean getCassandraStatus() { + + if (GeneralUtility.isEmptyString(localDataCenterName)) { + log.error("localDataCenter Name in configuration.yaml is missing."); + return false; + } + + Cluster cluster = null; + Session session = null; + try { + log.info("creating cluster for Cassandra for monitoring."); + cluster = SdcSchemaUtils.createCluster(); + if (cluster == null) { + log.error("Failure create cassandra cluster."); + return false; + } + session = cluster.connect(); + Metadata metadata = cluster.getMetadata(); + + if (metadata == null) { + log.error("Failure get cassandra metadata."); + return false; + } + + log.info("The number of cassandra nodes is:{}", metadata.getAllHosts().size()); + + //Count the number of data center nodes that are down + Long downHostsNumber = metadata.getAllHosts().stream() + .filter(x -> x.getDatacenter().equals(localDataCenterName) && !x.isUp()).count(); + + log.info("The cassandra down nodes number is {}", downHostsNumber.toString()); + return (HC_FormulaNumber >= downHostsNumber); + + } catch (Exception e) { + log.error("create cassandra cluster failed with exception.", e); + return false; + } finally { + if (session != null) { + session.close(); + } + if (cluster != null) { + cluster.close(); + } + } + } +} diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentBusinessLogic.java index 5ee5c88f69..d1be69689e 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentBusinessLogic.java @@ -183,11 +183,7 @@ public abstract class ComponentBusinessLogic extends BaseBusinessLogic { return Either.right(errorResponse); } - description = ValidationUtils.removeNoneUtf8Chars(description); - description = ValidationUtils.normaliseWhitespace(description); - description = ValidationUtils.stripOctets(description); - description = ValidationUtils.removeHtmlTagsOnly(description); - + description = cleanUpText(description); Either validatDescription = validateComponentDescription(description, type); if (validatDescription.isRight()) { ResponseFormat responseFormat = validatDescription.right().value(); @@ -666,19 +662,25 @@ public abstract class ComponentBusinessLogic extends BaseBusinessLogic { } toscaArtifact = generateToscaRes.left().value().left().value(); component.getToscaArtifacts().put(toscaArtifact.getArtifactLabel(), toscaArtifact); - toscaArtifact = component.getToscaArtifacts().values().stream() - .filter(p -> p.getArtifactType().equals(ArtifactTypeEnum.TOSCA_CSAR.getType())) - .findAny().get(); - generateToscaRes = saveToscaArtifactPayload(toscaArtifact, component, user, isInCertificationRequest, shouldLock, inTransaction, true); - } - if (generateToscaRes.isRight()) { - return generateToscaRes; + if(!isAbstractResource(component)){ + toscaArtifact = component.getToscaArtifacts().values().stream() + .filter(p -> p.getArtifactType().equals(ArtifactTypeEnum.TOSCA_CSAR.getType())) + .findAny().get(); + generateToscaRes = saveToscaArtifactPayload(toscaArtifact, component, user, isInCertificationRequest, shouldLock, inTransaction, true); + if (generateToscaRes.isRight()) { + return generateToscaRes; + } + toscaArtifact = generateToscaRes.left().value().left().value(); + component.getToscaArtifacts().put(toscaArtifact.getArtifactLabel(), toscaArtifact); + } } - ArtifactDefinition toscaArtifact = generateToscaRes.left().value().left().value(); - component.getToscaArtifacts().put(toscaArtifact.getArtifactLabel(), toscaArtifact); return generateToscaRes; } + private boolean isAbstractResource(Component component) { + return component.getComponentType() == ComponentTypeEnum.RESOURCE && ((Resource)component).isAbstract(); + } + public Either, ResponseFormat> saveToscaArtifactPayload(ArtifactDefinition artifactDefinition, org.openecomp.sdc.be.model.Component component, User user, boolean isInCertificationRequest, boolean shouldLock, boolean inTransaction, boolean fetchTemplatesFromDB) { return artifactsBusinessLogic.generateAndSaveToscaArtifact(artifactDefinition, component, user, isInCertificationRequest, shouldLock, inTransaction, fetchTemplatesFromDB); @@ -735,11 +737,11 @@ public abstract class ComponentBusinessLogic extends BaseBusinessLogic { } } - public Either validateAndUpdateDescription(User user, Component currentComponent, Component updatedComponent, AuditingActionEnum audatingAction) { + public Either validateAndUpdateDescription(User user, Component currentComponent, Component updatedComponent, AuditingActionEnum auditingAction) { String descriptionUpdated = updatedComponent.getDescription(); String descriptionCurrent = currentComponent.getDescription(); if (descriptionUpdated != null && !descriptionCurrent.equals(descriptionUpdated)) { - Either validateDescriptionResponse = validateDescriptionAndCleanup(user, updatedComponent, audatingAction); + Either validateDescriptionResponse = validateDescriptionAndCleanup(user, updatedComponent, auditingAction); if (validateDescriptionResponse.isRight()) { ResponseFormat errorRespons = validateDescriptionResponse.right().value(); return Either.right(errorRespons); @@ -977,8 +979,12 @@ public abstract class ComponentBusinessLogic extends BaseBusinessLogic { } protected Either fetchAndSetDerivedFromGenericType(T component){ - - String genericTypeToscaName = component.fetchGenericTypeToscaNameFromConfig(); + String genericTypeToscaName = null; + if(component.getComponentType() == ComponentTypeEnum.RESOURCE && ((Resource)component).getResourceType() == ResourceTypeEnum.CVFC){ + genericTypeToscaName = ((Resource)component).getDerivedFrom().get(0); + } else { + genericTypeToscaName = component.fetchGenericTypeToscaNameFromConfig(); + } if(null == genericTypeToscaName) return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR)); Either findLatestGeneric = toscaOperationFacade.getLatestCertifiedNodeTypeByToscaResourceName(genericTypeToscaName); @@ -1237,6 +1243,14 @@ public abstract class ComponentBusinessLogic extends BaseBusinessLogic { } return isMatchingType; } + + protected String cleanUpText(String text){ + text = ValidationUtils.removeNoneUtf8Chars(text); + text = ValidationUtils.normaliseWhitespace(text); + text = ValidationUtils.stripOctets(text); + text = ValidationUtils.removeHtmlTagsOnly(text); + return text; + } } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogic.java index 5da416ec0b..56cd91d754 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogic.java @@ -58,10 +58,12 @@ import org.openecomp.sdc.be.model.ComponentParametersView; import org.openecomp.sdc.be.model.DataTypeDefinition; import org.openecomp.sdc.be.model.GroupDefinition; import org.openecomp.sdc.be.model.GroupInstance; +import org.openecomp.sdc.be.model.InputDefinition; import org.openecomp.sdc.be.model.LifecycleStateEnum; import org.openecomp.sdc.be.model.PropertyDefinition.PropertyNames; import org.openecomp.sdc.be.model.cache.ApplicationDataTypeCache; import org.openecomp.sdc.be.model.RequirementCapabilityRelDef; +import org.openecomp.sdc.be.model.Resource; import org.openecomp.sdc.be.model.User; import org.openecomp.sdc.be.model.jsontitan.operations.ToscaOperationFacade; import org.openecomp.sdc.be.model.operations.api.IComponentInstanceOperation; @@ -72,6 +74,7 @@ import org.openecomp.sdc.be.model.operations.utils.ComponentValidationUtils; import org.openecomp.sdc.be.model.tosca.ToscaPropertyType; import org.openecomp.sdc.be.resources.data.ComponentInstanceData; import org.openecomp.sdc.be.resources.data.PropertyValueData; +import org.openecomp.sdc.be.tosca.ToscaUtils; import org.openecomp.sdc.common.api.ArtifactGroupTypeEnum; import org.openecomp.sdc.common.api.ArtifactTypeEnum; import org.openecomp.sdc.common.api.Constants; @@ -142,9 +145,9 @@ public abstract class ComponentInstanceBusinessLogic extends BaseBusinessLogic { containerComponent = validateComponentExists.left().value(); } - Either validateAllowedToContainCompInstances = validateAllowedToContainCompInstances(containerComponent); - if (validateAllowedToContainCompInstances.isRight()) { - return Either.right(validateAllowedToContainCompInstances.right().value()); + if (ToscaUtils.isAtomicType(containerComponent)) { + log.debug("Cannot attach resource instances to container resource of type {}", containerComponent.assetType()); + return Either.right(componentsUtils.getResponseFormat(ActionStatus.RESOURCE_CANNOT_CONTAIN_RESOURCE_INSTANCES, containerComponent.assetType())); } Either validateCanWorkOnComponent = validateCanWorkOnComponent(containerComponent, userId); @@ -201,9 +204,9 @@ public abstract class ComponentInstanceBusinessLogic extends BaseBusinessLogic { } org.openecomp.sdc.be.model.Component containerComponent = validateComponentExists.left().value(); - Either validateAllowedToContainCompInstances = validateAllowedToContainCompInstances(containerComponent); - if (validateAllowedToContainCompInstances.isRight()) { - return Either.right(validateAllowedToContainCompInstances.right().value()); + if (ToscaUtils.isAtomicType(containerComponent)) { + log.debug("Cannot attach resource instances to container resource of type {}", containerComponent.assetType()); + return Either.right(componentsUtils.getResponseFormat(ActionStatus.RESOURCE_CANNOT_CONTAIN_RESOURCE_INSTANCES, containerComponent.assetType())); } Either validateCanWorkOnComponent = validateCanWorkOnComponent(containerComponent, userId); @@ -620,6 +623,7 @@ public abstract class ComponentInstanceBusinessLogic extends BaseBusinessLogic { Optional componentInstanceOptional = null; Either, StorageOperationStatus> updateRes = null; ComponentInstance oldComponentInstance = null; + boolean isNameChanged = false; if (resultOp == null) { componentInstanceOptional = containerComponent.getComponentInstances().stream().filter(ci -> ci.getUniqueId().equals(componentInstance.getUniqueId())).findFirst(); @@ -631,6 +635,9 @@ public abstract class ComponentInstanceBusinessLogic extends BaseBusinessLogic { if (resultOp == null) { oldComponentInstance = componentInstanceOptional.get(); String newInstanceName = componentInstance.getName(); + if ( oldComponentInstance!=null && oldComponentInstance.getName() != null + && !oldComponentInstance.getName().equals( newInstanceName ) ) + isNameChanged = true; Boolean isUniqueName = validateInstanceNameUniquenessUponUpdate(containerComponent, oldComponentInstance, newInstanceName); if (!isUniqueName) { CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to update the name of the component instance {} to {}. A component instance with the same name already exists. ", oldComponentInstance.getName(), newInstanceName); @@ -643,6 +650,14 @@ public abstract class ComponentInstanceBusinessLogic extends BaseBusinessLogic { CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to update metadata of component instance {} belonging to container component {}. Status is {}. ", componentInstance.getName(), containerComponent.getName(), updateRes.right().value()); resultOp = Either.right(componentsUtils.getResponseFormatForResourceInstance(componentsUtils.convertFromStorageResponseForResourceInstance(updateRes.right().value(), true), "", null)); + }else{ + //region - Update instance Groups + if ( isNameChanged ){ + Either result = toscaOperationFacade.cleanAndAddGroupInstancesToComponentInstance( containerComponent ,oldComponentInstance ,componentInstanceId ); + if ( result.isRight() ) + CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to rename group instances for container {}. error {} ", componentInstanceId ,result.right().value() ); + } + //endregion } } if (resultOp == null) { @@ -662,11 +677,29 @@ public abstract class ComponentInstanceBusinessLogic extends BaseBusinessLogic { } return resultOp; } + /** + * @param oldPrefix- The normalized old vf name + * @param newNormailzedPrefix- The normalized new vf name + * @param qualifiedGroupInstanceName- old Group Instance Name + **/ + //modify group names + private String getNewGroupName( String oldPrefix ,String newNormailzedPrefix , String qualifiedGroupInstanceName){ + if (qualifiedGroupInstanceName == null){ + log.info("CANNOT change group name "); + return null; + } + if (qualifiedGroupInstanceName.startsWith(oldPrefix) || qualifiedGroupInstanceName.startsWith(ValidationUtils.normalizeComponentInstanceName(oldPrefix))) + return qualifiedGroupInstanceName.replaceFirst(oldPrefix, newNormailzedPrefix); + return qualifiedGroupInstanceName; + } private ComponentInstance updateComponentInstanceMetadata(ComponentInstance oldComponentInstance, ComponentInstance newComponentInstance) { oldComponentInstance.setName(newComponentInstance.getName()); oldComponentInstance.setModificationTime(System.currentTimeMillis()); oldComponentInstance.setCustomizationUUID(UUID.randomUUID().toString()); + if ( oldComponentInstance.getGroupInstances() != null ) + oldComponentInstance.getGroupInstances().forEach( group -> + group.setName( getNewGroupName( oldComponentInstance.getNormalizedName() , ValidationUtils.normalizeComponentInstanceName( newComponentInstance.getName() ) , group.getName() ) ) ); return oldComponentInstance; } @@ -748,6 +781,17 @@ public abstract class ComponentInstanceBusinessLogic extends BaseBusinessLogic { resultOp = Either.right(componentsUtils.getResponseFormat(status, componentInstanceId)); } } + if(resultOp.isLeft() && CollectionUtils.isNotEmpty(containerComponent.getInputs())){ + List inputsToDelete = containerComponent.getInputs().stream().filter(i -> i.getInstanceUniqueId() != null && i.getInstanceUniqueId().equals(componentInstanceId)).collect(Collectors.toList()); + if(CollectionUtils.isNotEmpty(inputsToDelete)){ + StorageOperationStatus deleteInputsRes = + toscaOperationFacade.deleteComponentInstanceInputsFromTopologyTemplate(containerComponent, containerComponent.getComponentType(), inputsToDelete); + if(deleteInputsRes != StorageOperationStatus.OK){ + log.debug("Failed to delete inputs of the component instance {} from container component. ", componentInstanceId); + resultOp = Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(deleteInputsRes, containerComponentType), componentInstanceId)); + } + } + } return resultOp; } @@ -1696,8 +1740,6 @@ public abstract class ComponentInstanceBusinessLogic extends BaseBusinessLogic { } } - protected abstract Either validateAllowedToContainCompInstances(org.openecomp.sdc.be.model.Component containerComponent); - protected abstract NodeTypeEnum getNodeTypeOfComponentInstanceOrigin(); protected abstract ComponentTypeEnum getComponentTypeOfComponentInstance(); diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ElementBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ElementBusinessLogic.java index 669b84f229..7214d011e0 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ElementBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ElementBusinessLogic.java @@ -20,19 +20,10 @@ package org.openecomp.sdc.be.components.impl; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; +import com.thinkaurelius.titan.core.TitanGraph; +import fj.data.Either; import java.util.EnumMap; -import java.util.HashMap; -import java.util.HashSet; import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Set; -import java.util.function.Predicate; -import java.util.stream.Collectors; - import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.http.NameValuePair; import org.apache.http.client.utils.URLEncodedUtils; @@ -47,24 +38,10 @@ import org.openecomp.sdc.be.datamodel.api.CategoryTypeEnum; import org.openecomp.sdc.be.datamodel.utils.NodeTypeConvertUtils; import org.openecomp.sdc.be.datatypes.components.ComponentMetadataDataDefinition; import org.openecomp.sdc.be.datatypes.components.ResourceMetadataDataDefinition; -import org.openecomp.sdc.be.datatypes.enums.AssetTypeEnum; -import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; -import org.openecomp.sdc.be.datatypes.enums.FilterKeyEnum; +import org.openecomp.sdc.be.datatypes.enums.*; import org.openecomp.sdc.be.datatypes.enums.GraphPropertyEnum; -import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum; -import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum; import org.openecomp.sdc.be.impl.ComponentsUtils; -import org.openecomp.sdc.be.model.ArtifactType; -import org.openecomp.sdc.be.model.Component; -import org.openecomp.sdc.be.model.DistributionStatusEnum; -import org.openecomp.sdc.be.model.LifecycleStateEnum; -import org.openecomp.sdc.be.model.Product; -import org.openecomp.sdc.be.model.PropertyScope; -import org.openecomp.sdc.be.model.Resource; -import org.openecomp.sdc.be.model.ResourceMetadataDefinition; -import org.openecomp.sdc.be.model.Service; -import org.openecomp.sdc.be.model.Tag; -import org.openecomp.sdc.be.model.User; +import org.openecomp.sdc.be.model.*; import org.openecomp.sdc.be.model.category.CategoryDefinition; import org.openecomp.sdc.be.model.category.GroupingDefinition; import org.openecomp.sdc.be.model.category.SubCategoryDefinition; @@ -87,9 +64,10 @@ import org.openecomp.sdc.exception.ResponseFormat; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.thinkaurelius.titan.core.TitanGraph; - -import fj.data.Either; +import java.nio.charset.StandardCharsets; +import java.util.*; +import java.util.function.Predicate; +import java.util.stream.Collectors; @org.springframework.stereotype.Component("elementsBusinessLogic") public class ElementBusinessLogic extends BaseBusinessLogic { @@ -1003,16 +981,16 @@ public class ElementBusinessLogic extends BaseBusinessLogic { return elementOperation.getDefaultHeatTimeout(); } - public Either>, ResponseFormat> getCatalogComponents(String userId) { + public Either>, ResponseFormat> getCatalogComponents(String userId, List excludeTypes) { Either resp = validateUserExists(userId, "get Catalog Components", false); if (resp.isRight()) { return Either.right(resp.right().value()); } Map> resMap = new HashMap<>(); - Either, StorageOperationStatus> resResources = toscaOperationFacade.getCatalogComponents(ComponentTypeEnum.RESOURCE, true); + Either, StorageOperationStatus> resResources = toscaOperationFacade.getCatalogComponents(ComponentTypeEnum.RESOURCE,excludeTypes, true); if (resResources.isLeft()) { - Either, StorageOperationStatus> resServices = toscaOperationFacade.getCatalogComponents(ComponentTypeEnum.SERVICE, true); + Either, StorageOperationStatus> resServices = toscaOperationFacade.getCatalogComponents(ComponentTypeEnum.SERVICE,excludeTypes, true); if (resServices.isLeft()) { // Either, StorageOperationStatus> resProducts = productOperation.getProductCatalogData(false); // if (resProducts.isLeft()) { @@ -1041,7 +1019,7 @@ public class ElementBusinessLogic extends BaseBusinessLogic { } if (filters == null || filters.isEmpty()) { - Either, StorageOperationStatus> componentsList = toscaOperationFacade.getCatalogComponents(assetTypeEnum, false); + Either, StorageOperationStatus> componentsList = toscaOperationFacade.getCatalogComponents(assetTypeEnum,null, false); if(componentsList.isRight()) { return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(componentsList.right().value()))); } @@ -1134,15 +1112,15 @@ public class ElementBusinessLogic extends BaseBusinessLogic { log.debug("getCatalogComponentsByUuidAndAssetType: Corresponding ComponentTypeEnum not allowed for this API"); return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT)); } - + Either, StorageOperationStatus> componentsListByUuid = toscaOperationFacade.getComponentListByUuid(uuid, additionalPropertiesToMatch); if(componentsListByUuid.isRight()) { - log.debug("getCatalogComponentsByUuidAndAssetType: Service fetching failed"); - ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(componentsListByUuid.right().value(), ComponentTypeEnum.SERVICE); + log.debug("getCatalogComponentsByUuidAndAssetType: " + assetTypeEnum.getValue()+ " fetching failed"); + ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(componentsListByUuid.right().value(), assetTypeEnum); return Either.right(componentsUtils.getResponseFormat(actionStatus, uuid)); } - - log.debug("getCatalogComponentsByUuidAndAssetType: " + assetTypeEnum.getValue() + "Service fetching successful"); + + log.debug("getCatalogComponentsByUuidAndAssetType: " + assetTypeEnum.getValue() + assetTypeEnum.getValue() + "fetching successful"); return Either.left(componentsListByUuid.left().value()); } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/GroupBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/GroupBusinessLogic.java index f298b0f203..a3d590374f 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/GroupBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/GroupBusinessLogic.java @@ -359,7 +359,7 @@ public class GroupBusinessLogic extends BaseBusinessLogic { * @param inTransaction * @return */ - public Either validateAndUpdateGroupMetadata(String componentId, User user, ComponentTypeEnum componentType, GroupDefinition updatedGroup, boolean inTransaction) { + public Either validateAndUpdateGroupMetadata(String componentId, User user, ComponentTypeEnum componentType, GroupDefinition updatedGroup, boolean inTransaction , boolean shouldLock) { Either result = null; try { @@ -396,10 +396,12 @@ public class GroupBusinessLogic extends BaseBusinessLogic { return result; } GroupDefinition currentGroup = currentGroupOpt.get(); - Either lockResult = lockComponent(componentId, component, "Update GroupDefinition Metadata"); - if (lockResult.isRight()) { - result = Either.right(lockResult.right().value()); - return result; + if ( shouldLock ){ + Either lockResult = lockComponent(componentId, component, "Update GroupDefinition Metadata"); + if (lockResult.isRight()) { + result = Either.right(lockResult.right().value()); + return result; + } } // Validate group type is vfModule if (!currentGroup.getType().equals(Constants.DEFAULT_GROUP_VF_MODULE)) { @@ -417,7 +419,8 @@ public class GroupBusinessLogic extends BaseBusinessLogic { } else { titanDao.rollback(); } - graphLockOperation.unlockComponent(componentId, componentType.getNodeType()); + if( shouldLock ) + graphLockOperation.unlockComponent(componentId, componentType.getNodeType()); } } @@ -734,7 +737,7 @@ public class GroupBusinessLogic extends BaseBusinessLogic { String nameUpdated = groupUpdate.getName(); String nameCurrent = currentGroup.getName(); if (!nameCurrent.equals(nameUpdated)) { - Either validatNameResponse = validateGroupName(currentGroup.getName(), groupUpdate.getName()); + Either validatNameResponse = validateGroupName(currentGroup.getName(), groupUpdate.getName() ,true); if (validatNameResponse.isRight()) { ResponseFormat errorRespons = validatNameResponse.right().value(); return Either.right(errorRespons); @@ -752,7 +755,7 @@ public class GroupBusinessLogic extends BaseBusinessLogic { * @param groupUpdateName * @return */ - private Either validateGroupName(String currentGroupName, String groupUpdateName) { + private Either validateGroupName(String currentGroupName, String groupUpdateName , boolean isforceNameModification) { try { // Check if the group name is in old format. if (Pattern.compile(Constants.MODULE_OLD_NAME_PATTERN).matcher(groupUpdateName).matches()) { @@ -771,14 +774,16 @@ public class GroupBusinessLogic extends BaseBusinessLogic { String[] split2 = groupUpdateName.split("\\.\\."); String groupUpdateResourceName = split2[0]; String groupUpdateCounter = split2[2]; + if (!isforceNameModification){ //if not forced ,allow name prefix&suffix validation [no changes] + if (!currentResourceName.equals(groupUpdateResourceName)) { + return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_VF_MODULE_NAME_MODIFICATION, currentResourceName)); + } - if (!currentResourceName.equals(groupUpdateResourceName)) { - return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_VF_MODULE_NAME_MODIFICATION, currentResourceName)); + if (!currentCounter.equals(groupUpdateCounter)) { + return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_VF_MODULE_NAME_MODIFICATION, currentCounter)); + } } - if (!currentCounter.equals(groupUpdateCounter)) { - return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_VF_MODULE_NAME_MODIFICATION, currentCounter)); - } } return Either.left(true); diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/HealthCheckBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/HealthCheckBusinessLogic.java index e535214d70..8a8937740f 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/HealthCheckBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/HealthCheckBusinessLogic.java @@ -20,7 +20,10 @@ package org.openecomp.sdc.be.components.impl; +import java.io.IOException; +import java.lang.reflect.Type; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -34,16 +37,23 @@ import java.util.stream.Collectors; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import javax.annotation.Resource; -import javax.servlet.ServletContext; +import org.apache.http.HttpEntity; +import org.apache.http.HttpStatus; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.util.EntityUtils; import org.openecomp.sdc.be.components.distribution.engine.DistributionEngineClusterHealth; import org.openecomp.sdc.be.components.distribution.engine.UebHealthCheckCall; import org.openecomp.sdc.be.config.BeEcompErrorManager; +import org.openecomp.sdc.be.config.Configuration; +import org.openecomp.sdc.be.config.ConfigurationManager; import org.openecomp.sdc.be.dao.api.IEsHealthCheckDao; import org.openecomp.sdc.be.dao.titan.TitanGenericDao; -import org.openecomp.sdc.be.impl.WebAppContextWrapper; import org.openecomp.sdc.be.switchover.detector.SwitchoverDetector; -import org.openecomp.sdc.common.api.Constants; import org.openecomp.sdc.common.api.HealthCheckInfo; import org.openecomp.sdc.common.api.HealthCheckInfo.HealthCheckComponent; import org.openecomp.sdc.common.api.HealthCheckInfo.HealthCheckStatus; @@ -52,7 +62,9 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import org.springframework.web.context.WebApplicationContext; + +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; @Component("healthCheckBusinessLogic") public class HealthCheckBusinessLogic { @@ -62,6 +74,7 @@ public class HealthCheckBusinessLogic { private static Logger healthLogger = LoggerFactory.getLogger(BE_HEALTH_LOG_CONTEXT); private static final String BE_HEALTH_CHECK_STR = "beHealthCheck"; + private static final String COMPONENT_CHANGED_MESSAGE = "BE Component %s state changed from %s to %s"; @Resource private TitanGenericDao titanGenericDao; @@ -72,15 +85,16 @@ public class HealthCheckBusinessLogic { @Resource private DistributionEngineClusterHealth distributionEngineClusterHealth; + @Resource + private CassandraHealthCheck cassandraHealthCheck; + @Autowired private SwitchoverDetector switchoverDetector; private static Logger log = LoggerFactory.getLogger(HealthCheckBusinessLogic.class.getName()); - private volatile List lastBeHealthCheckInfos = null; + private volatile List prevBeHealthCheckInfos = null; - // private static volatile HealthCheckBusinessLogic instance; - // public HealthCheckBusinessLogic() { } @@ -99,9 +113,9 @@ public class HealthCheckBusinessLogic { @PostConstruct public void init() { - lastBeHealthCheckInfos = getBeHealthCheckInfos(); + prevBeHealthCheckInfos = getBeHealthCheckInfos(); - log.debug("After initializing lastBeHealthCheckInfos: {}", lastBeHealthCheckInfos); + log.debug("After initializing prevBeHealthCheckInfos: {}", prevBeHealthCheckInfos); healthCheckScheduledTask = new HealthCheckScheduledTask(); @@ -111,115 +125,9 @@ public class HealthCheckBusinessLogic { } - // - // public static HealthCheckBusinessLogic getInstance(){ - //// if (instance == null){ - //// instance = init(); - //// } - // return instance; - // } - - // private synchronized static HealthCheckBusinessLogic init() { - // if (instance == null){ - // instance = new HealthCheckBusinessLogic(); - // } - // return instance; - // } - - private List getBeHealthCheckInfos(ServletContext servletContext) { - - List healthCheckInfos = new ArrayList(); - - // BE - getBeHealthCheck(servletContext, healthCheckInfos); - - // ES - getEsHealthCheck(servletContext, healthCheckInfos); - - // Titan - getTitanHealthCheck(servletContext, healthCheckInfos); - - // Distribution Engine - getDistributionEngineCheck(servletContext, healthCheckInfos); - - return healthCheckInfos; - } - - private List getBeHealthCheck(ServletContext servletContext, List healthCheckInfos) { - String appVersion = ExternalConfiguration.getAppVersion(); - String description = "OK"; - healthCheckInfos.add(new HealthCheckInfo(HealthCheckComponent.BE, HealthCheckStatus.UP, appVersion, description)); - return healthCheckInfos; - } - - public List getTitanHealthCheck(ServletContext servletContext, List healthCheckInfos) { - // Titan health check and version - TitanGenericDao titanStatusDao = (TitanGenericDao) getDao(servletContext, TitanGenericDao.class); - String description; - boolean isTitanUp; - - try { - isTitanUp = titanStatusDao.isGraphOpen(); - } catch (Exception e) { - description = "Titan error: " + e.getMessage(); - healthCheckInfos.add(new HealthCheckInfo(HealthCheckComponent.TITAN, HealthCheckStatus.DOWN, null, description)); - return healthCheckInfos; - } - if (isTitanUp) { - description = "OK"; - healthCheckInfos.add(new HealthCheckInfo(HealthCheckComponent.TITAN, HealthCheckStatus.UP, null, description)); - } else { - description = "Titan graph is down"; - healthCheckInfos.add(new HealthCheckInfo(HealthCheckComponent.TITAN, HealthCheckStatus.DOWN, null, description)); - } - return healthCheckInfos; - } - - public List getEsHealthCheck(ServletContext servletContext, List healthCheckInfos) { - - // ES health check and version - IEsHealthCheckDao esStatusDao = (IEsHealthCheckDao) getDao(servletContext, IEsHealthCheckDao.class); - HealthCheckStatus healthCheckStatus; - String description; - - try { - healthCheckStatus = esStatusDao.getClusterHealthStatus(); - } catch (Exception e) { - healthCheckStatus = HealthCheckStatus.DOWN; - description = "ES cluster error: " + e.getMessage(); - healthCheckInfos.add(new HealthCheckInfo(HealthCheckComponent.ES, healthCheckStatus, null, description)); - return healthCheckInfos; - } - if (healthCheckStatus.equals(HealthCheckStatus.DOWN)) { - description = "ES cluster is down"; - } else { - description = "OK"; - } - healthCheckInfos.add(new HealthCheckInfo(HealthCheckComponent.ES, healthCheckStatus, null, description)); - return healthCheckInfos; - } - - public Object getDao(ServletContext servletContext, Class clazz) { - WebAppContextWrapper webApplicationContextWrapper = (WebAppContextWrapper) servletContext.getAttribute(Constants.WEB_APPLICATION_CONTEXT_WRAPPER_ATTR); - - WebApplicationContext webApplicationContext = webApplicationContextWrapper.getWebAppContext(servletContext); - - return webApplicationContext.getBean(clazz); - } - - private void getDistributionEngineCheck(ServletContext servletContext, List healthCheckInfos) { - - DistributionEngineClusterHealth deDao = (DistributionEngineClusterHealth) getDao(servletContext, DistributionEngineClusterHealth.class); - HealthCheckInfo healthCheckInfo = deDao.getHealthCheckInfo(); + public boolean isDistributionEngineUp() { - healthCheckInfos.add(healthCheckInfo); - - } - - public boolean isDistributionEngineUp(ServletContext servletContext) { - - DistributionEngineClusterHealth deDao = (DistributionEngineClusterHealth) getDao(servletContext, DistributionEngineClusterHealth.class); - HealthCheckInfo healthCheckInfo = deDao.getHealthCheckInfo(); + HealthCheckInfo healthCheckInfo = distributionEngineClusterHealth.getHealthCheckInfo(); if (healthCheckInfo.getHealthCheckStatus().equals(HealthCheckStatus.DOWN)) { return false; } @@ -228,7 +136,7 @@ public class HealthCheckBusinessLogic { public List getBeHealthCheckInfosStatus() { - return lastBeHealthCheckInfos; + return prevBeHealthCheckInfos; } @@ -241,8 +149,8 @@ public class HealthCheckBusinessLogic { // BE getBeHealthCheck(healthCheckInfos); - // ES - getEsHealthCheck(healthCheckInfos); + /*// ES + getEsHealthCheck(healthCheckInfos);*/ // Titan getTitanHealthCheck(healthCheckInfos); @@ -250,6 +158,12 @@ public class HealthCheckBusinessLogic { // Distribution Engine getDistributionEngineCheck(healthCheckInfos); + //Cassandra + getCassandraHealthCheck(healthCheckInfos); + + // Amdocs + getAmdocsHealthCheck(healthCheckInfos); + return healthCheckInfos; } @@ -260,7 +174,8 @@ public class HealthCheckBusinessLogic { return healthCheckInfos; } - public List getEsHealthCheck(List healthCheckInfos) { + //Removed from aggregate HC - TDP 293490 +/* private List getEsHealthCheck(List healthCheckInfos) { // ES health check and version HealthCheckStatus healthCheckStatus; @@ -282,7 +197,7 @@ public class HealthCheckBusinessLogic { healthCheckInfos.add(new HealthCheckInfo(HealthCheckComponent.ES, healthCheckStatus, null, description)); return healthCheckInfos; } - +*/ public List getTitanHealthCheck(List healthCheckInfos) { // Titan health check and version String description; @@ -305,6 +220,28 @@ public class HealthCheckBusinessLogic { return healthCheckInfos; } + private List getCassandraHealthCheck(List healthCheckInfos) { + + String description; + boolean isCassandraUp; + + try { + isCassandraUp = cassandraHealthCheck.getCassandraStatus(); + } catch (Exception e) { + isCassandraUp = false; + description = "Cassandra error: " + e.getMessage(); + } + if (isCassandraUp) { + description = "OK"; + healthCheckInfos.add(new HealthCheckInfo(HealthCheckComponent.CASSANDRA, HealthCheckStatus.UP, null, description)); + } else { + description = "Cassandra is down"; + healthCheckInfos.add(new HealthCheckInfo(HealthCheckComponent.CASSANDRA, HealthCheckStatus.DOWN, null, description)); + } + return healthCheckInfos; + + } + private void getDistributionEngineCheck(List healthCheckInfos) { HealthCheckInfo healthCheckInfo = distributionEngineClusterHealth.getHealthCheckInfo(); @@ -313,6 +250,76 @@ public class HealthCheckBusinessLogic { } + private List getAmdocsHealthCheck(List healthCheckInfos) { + HealthCheckStatus healthCheckStatus; + String description; + Map amdocsHC = null; + String version = null; + List componentsInfo = null; + CloseableHttpClient httpClient = getHttpClient(); + String amdocsHealtchCheckUrl = buildHealthCheckUrl(); + HttpGet httpGet = new HttpGet(amdocsHealtchCheckUrl); + CloseableHttpResponse beResponse; + int beStatus; + try { + beResponse = httpClient.execute(httpGet); + beStatus = beResponse.getStatusLine().getStatusCode(); + + HttpEntity entity = beResponse.getEntity(); + String beJsonResponse = EntityUtils.toString(entity); + Gson gson = new Gson(); + amdocsHC = gson.fromJson(beJsonResponse, Map.class); + version = amdocsHC.get("sdcVersion") != null ? amdocsHC.get("sdcVersion").toString() : null; + Object object = amdocsHC.get("componentsInfo"); + Type listType = new TypeToken>(){}.getType(); + componentsInfo = gson.fromJson(object.toString(), listType); + + if (beStatus != HttpStatus.SC_OK) { + healthCheckStatus = HealthCheckStatus.DOWN; + StringBuilder sb = new StringBuilder(); + componentsInfo.forEach(x -> { + if (x.getHealthCheckStatus()==HealthCheckStatus.DOWN){ + sb.append("Component "+x.getHealthCheckComponent().name()+" is Down,"); + } + }); + //Removing the last comma + description = sb.length()>0 + ? sb.substring(0, sb.length()-1) + : "Onboarding is Down, specific reason unknown";//No Amdocs inner component returned DOWN, but the status of Amdocs HC is still DOWN. + } else { + healthCheckStatus = HealthCheckStatus.UP; + description = "OK"; + + + } + + } catch (Exception e) { + healthCheckStatus = HealthCheckStatus.DOWN; + description = "Onboarding unexpected response: " + e.getMessage(); + } finally { + if (httpClient != null) { + try { + httpClient.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + healthCheckInfos.add(new HealthCheckInfo(HealthCheckComponent.ON_BOARDING, healthCheckStatus, version, description, componentsInfo)); + return healthCheckInfos; + } + + private CloseableHttpClient getHttpClient() { + int timeout = 3000; + RequestConfig.Builder requestBuilder = RequestConfig.custom(); + requestBuilder.setConnectTimeout(timeout).setConnectionRequestTimeout(timeout).setSocketTimeout(timeout); + + HttpClientBuilder builder = HttpClientBuilder.create(); + builder.setDefaultRequestConfig(requestBuilder.build()); + return builder.build(); + } + @PreDestroy private void destroy() { @@ -340,101 +347,127 @@ public class HealthCheckBusinessLogic { healthLogger.trace("Executing BE Health Check Task"); - List beHealthCheckInfos = getBeHealthCheckInfos(); - boolean healthStatus = getAggregateBeStatus(beHealthCheckInfos); + List currentBeHealthCheckInfos = getBeHealthCheckInfos(); + boolean healthStatus = getAggregateBeStatus(currentBeHealthCheckInfos); + + boolean prevHealthStatus = getAggregateBeStatus(prevBeHealthCheckInfos); - boolean lastHealthStatus = getAggregateBeStatus(lastBeHealthCheckInfos); + boolean anyStatusChanged = anyStatusChanged(currentBeHealthCheckInfos, prevBeHealthCheckInfos); - if (lastHealthStatus != healthStatus) { + if (prevHealthStatus != healthStatus || anyStatusChanged) { log.trace("BE Health State Changed to {}. Issuing alarm / recovery alarm...", healthStatus); - lastBeHealthCheckInfos = beHealthCheckInfos; + prevBeHealthCheckInfos = currentBeHealthCheckInfos; logAlarm(healthStatus); + } - } else { - // check if we need to update the status's list in case one of - // the statuses was changed - if (true == anyStatusChanged(beHealthCheckInfos, lastBeHealthCheckInfos)) { - lastBeHealthCheckInfos = beHealthCheckInfos; - } + } - } + private boolean getAggregateBeStatus(List beHealthCheckInfos) { + + boolean status = true; + for (HealthCheckInfo healthCheckInfo : beHealthCheckInfos) { + if (healthCheckInfo.getHealthCheckStatus().equals(HealthCheckStatus.DOWN) && healthCheckInfo.getHealthCheckComponent() != HealthCheckComponent.DE) { + status = false; + break; + } + } + return status; } } - private void logAlarm(boolean lastHealthState) { - if (lastHealthState == true) { + private void logAlarm(boolean prevHealthState) { + if (prevHealthState) { BeEcompErrorManager.getInstance().logBeHealthCheckRecovery(BE_HEALTH_CHECK_STR); } else { BeEcompErrorManager.getInstance().logBeHealthCheckError(BE_HEALTH_CHECK_STR); } } - private boolean getAggregateBeStatus(List beHealthCheckInfos) { - - boolean status = true; - - for (HealthCheckInfo healthCheckInfo : beHealthCheckInfos) { - if (healthCheckInfo.getHealthCheckStatus().equals(HealthCheckStatus.DOWN) && healthCheckInfo.getHealthCheckComponent() != HealthCheckComponent.DE) { - status = false; - break; - } - } - return status; + private void logAlarm(String componentChangedMsg) { + BeEcompErrorManager.getInstance().logBeHealthCheckRecovery(componentChangedMsg); } + public String getSiteMode() { return switchoverDetector.getSiteMode(); } - public boolean anyStatusChanged(List beHealthCheckInfos, List lastBeHealthCheckInfos) { + public boolean anyStatusChanged(List beHealthCheckInfos, List prevBeHealthCheckInfos) { boolean result = false; - if (beHealthCheckInfos != null && lastBeHealthCheckInfos != null) { + if (beHealthCheckInfos != null && prevBeHealthCheckInfos != null) { Map currentValues = beHealthCheckInfos.stream().collect(Collectors.toMap(p -> p.getHealthCheckComponent(), p -> p.getHealthCheckStatus())); - Map lastValues = lastBeHealthCheckInfos.stream().collect(Collectors.toMap(p -> p.getHealthCheckComponent(), p -> p.getHealthCheckStatus())); + Map prevValues = prevBeHealthCheckInfos.stream().collect(Collectors.toMap(p -> p.getHealthCheckComponent(), p -> p.getHealthCheckStatus())); - if (currentValues != null && lastValues != null) { + if (currentValues != null && prevValues != null) { int currentSize = currentValues.size(); - int lastSize = lastValues.size(); + int prevSize = prevValues.size(); + + if (currentSize != prevSize) { + + result = true; //extra/missing component + + Map notPresent = null; + if (currentValues.keySet().containsAll(prevValues.keySet())) { + notPresent = new HashMap<>(currentValues); + notPresent.keySet().removeAll(prevValues.keySet()); + } else { + notPresent = new HashMap<>(prevValues); + notPresent.keySet().removeAll(currentValues.keySet()); + } + + for (HealthCheckComponent component : notPresent.keySet()) { + logAlarm(String.format(COMPONENT_CHANGED_MESSAGE, component, prevValues.get(component), currentValues.get(component))); + } + // HealthCheckComponent changedComponent = notPresent.keySet().iterator().next(); - if (currentSize != lastSize) { - result = true; } else { for (Entry entry : currentValues.entrySet()) { HealthCheckComponent key = entry.getKey(); HealthCheckStatus value = entry.getValue(); - if (false == lastValues.containsKey(key)) { - result = true; + if (!prevValues.containsKey(key)) { + result = true; //component missing + logAlarm(String.format(COMPONENT_CHANGED_MESSAGE, key, prevValues.get(key), currentValues.get(key))); break; } - HealthCheckStatus lastHealthCheckStatus = lastValues.get(key); + HealthCheckStatus prevHealthCheckStatus = prevValues.get(key); - if (value != lastHealthCheckStatus) { - result = true; + if (value != prevHealthCheckStatus) { + result = true; //component status changed + logAlarm(String.format(COMPONENT_CHANGED_MESSAGE, key, prevValues.get(key), currentValues.get(key))); break; } } } - } else if (currentValues == null && lastValues == null) { - result = false; - } else { - result = true; } - } else if (beHealthCheckInfos == null && lastBeHealthCheckInfos == null) { + } else if (beHealthCheckInfos == null && prevBeHealthCheckInfos == null) { result = false; } else { + logAlarm(String.format(COMPONENT_CHANGED_MESSAGE, "", prevBeHealthCheckInfos == null ? "null" : "true", prevBeHealthCheckInfos == null ? "true" : "null")); result = true; } return result; } + + private String buildHealthCheckUrl() { + + Configuration.OnboardingConfig onboardingConfig = ConfigurationManager.getConfigurationManager().getConfiguration().getOnboarding(); + + String protocol = onboardingConfig.getProtocol(); + String host = onboardingConfig.getHost(); + Integer port = onboardingConfig.getPort(); + String uri = onboardingConfig.getHealthCheckUri(); + + return protocol + "://" + host + ":" + port + uri; + } } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ImportUtils.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ImportUtils.java index cded9ee706..c85520dbe4 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ImportUtils.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ImportUtils.java @@ -107,6 +107,7 @@ public final class ImportUtils { public static final List TOSCA_DEFINITION_VERSIONS = Arrays.asList(new String[] { "tosca_simple_yaml_1_0_0", "tosca_simple_profile_for_nfv_1_0_0", "tosca_simple_yaml_1_0" }); public static final List TOSCA_YML_CSAR_VALID_SUFFIX = Arrays.asList(new String[] { ".yml", ".yaml", ".csar" }); public static final String UI_JSON_PAYLOAD_NAME = "payloadName"; + public static final String CVFC_DESCRIPTION = "Complex node type that is used as nested type in VF"; } public enum ResultStatusEnum { @@ -133,6 +134,7 @@ public final class ImportUtils { PARAMETERS("parameters"), // Import Validations TOSCA_VERSION("tosca_definitions_version"), TOPOLOGY_TEMPLATE("topology_template"), NODE_TYPES("node_types"), OCCURRENCES("occurrences"), NODE_TEMPLATES("node_templates"), GROUPS("groups"), INPUTS("inputs"), + SUBSTITUTION_MAPPINGS("substitution_mappings"), NODE_TYPE("node_type"), // Attributes ATTRIBUTES("attributes"), LABEL("label"), HIDDEN("hidden"), IMMUTABLE("immutable"), GET_INPUT("get_input"); diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/InputsBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/InputsBusinessLogic.java index d6497b58ea..f85e25e5fb 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/InputsBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/InputsBusinessLogic.java @@ -456,47 +456,7 @@ public class InputsBusinessLogic extends BaseBusinessLogic { } resList = result.left().value(); - /*int index = 0; - for (Entry> entry : newInputsMap.entrySet()) { - - String compInstId = entry.getKey(); - - Optional op = ciList.stream().filter(ci -> ci.getUniqueId().equals(compInstId)).findAny(); - if(!op.isPresent()){ - ActionStatus actionStatus = ActionStatus.INVALID_CONTENT; - log.debug("Failed to find component instance {} under component {}", compInstId, componentId); - result = Either.right(componentsUtils.getResponseFormat(actionStatus)); - return result; - } - ComponentInstance ci = op.get(); - String compInstname = ci.getNormalizedName(); - Either origComponentEither = getOriginComponent(ci, origComponentMap); - if(origComponentEither.isRight()){ - ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(origComponentEither.right().value()); - log.debug("Failed to create inputs value under component {}, error: {}", componentId, actionStatus.name()); - result = Either.right(componentsUtils.getResponseFormat(actionStatus)); - return result; - } - org.openecomp.sdc.be.model.Component origComponent = origComponentEither.left().value(); - - List inputs = entry.getValue(); - - if (inputs != null && !inputs.isEmpty()) { - - for (InputDefinition input : inputs) { - - StorageOperationStatus status = addInputsToComponent(componentId, inputsToCreate, inputsValueToCreateMap, allDataTypes.left().value(), resList, index, compInstId, compInstname, origComponent, input); - if(status != StorageOperationStatus.OK ){ - ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(status); - log.debug("Failed to create inputs value under component {}, error: {}", componentId, actionStatus.name()); - result = Either.right(componentsUtils.getResponseFormat(actionStatus)); - return result; - } - - } - } - - }*/ + } @@ -715,42 +675,38 @@ public class InputsBusinessLogic extends BaseBusinessLogic { Either, ResponseFormat> result = Either.left(resList); List resourceProperties = component.getInputs(); - if(inputs != null && !inputs.isEmpty()){ - Either, ResponseFormat> allDataTypes = getAllDataTypes(applicationDataTypeCache); - if (allDataTypes.isRight()) { - return Either.right(allDataTypes.right().value()); - } + Either, ResponseFormat> allDataTypes = getAllDataTypes(applicationDataTypeCache); + if (allDataTypes.isRight()) { + return Either.right(allDataTypes.right().value()); + } - Map dataTypes = allDataTypes.left().value(); + Map dataTypes = allDataTypes.left().value(); - for (Map.Entry inputDefinition : inputs.entrySet()) { - String inputName = inputDefinition.getKey(); - inputDefinition.getValue().setName(inputName); + for (Map.Entry inputDefinition : inputs.entrySet()) { + String inputName = inputDefinition.getKey(); + inputDefinition.getValue().setName(inputName); - Either preparedInputEither = prepareAndValidateInputBeforeCreate(inputDefinition.getValue(), dataTypes); - if(preparedInputEither.isRight()){ - return Either.right(preparedInputEither.right().value()); - } - - } - if (resourceProperties != null) { - Map generatedInputs = resourceProperties.stream().collect(Collectors.toMap(i -> i.getName(), i -> i)); - Either, String> mergeEither = ToscaDataDefinition.mergeDataMaps(generatedInputs, inputs); - if(mergeEither.isRight()){ - return Either.right(componentsUtils.getResponseFormat(ActionStatus.PROPERTY_ALREADY_EXIST, mergeEither.right().value())); - } - inputs = mergeEither.left().value(); + Either preparedInputEither = prepareAndValidateInputBeforeCreate(inputDefinition.getValue(), dataTypes); + if(preparedInputEither.isRight()){ + return Either.right(preparedInputEither.right().value()); } - Either, StorageOperationStatus> assotiateInputsEither = toscaOperationFacade.createAndAssociateInputs(inputs, component.getUniqueId()); - if(assotiateInputsEither.isRight()){ - log.debug("Failed to create inputs under component {}. Status is {}", component.getUniqueId(), assotiateInputsEither.right().value()); - return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(assotiateInputsEither.right().value()))); + } + if (resourceProperties != null) { + Map generatedInputs = resourceProperties.stream().collect(Collectors.toMap(i -> i.getName(), i -> i)); + Either, String> mergeEither = ToscaDataDefinition.mergeDataMaps(generatedInputs, inputs); + if(mergeEither.isRight()){ + return Either.right(componentsUtils.getResponseFormat(ActionStatus.PROPERTY_ALREADY_EXIST, mergeEither.right().value())); } - result = Either.left(assotiateInputsEither.left().value()); - + inputs = mergeEither.left().value(); } + Either, StorageOperationStatus> assotiateInputsEither = toscaOperationFacade.createAndAssociateInputs(inputs, component.getUniqueId()); + if(assotiateInputsEither.isRight()){ + log.debug("Failed to create inputs under component {}. Status is {}", component.getUniqueId(), assotiateInputsEither.right().value()); + return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(assotiateInputsEither.right().value()))); + } + result = Either.left(assotiateInputsEither.left().value()); return result; } @@ -901,15 +857,13 @@ public class InputsBusinessLogic extends BaseBusinessLogic { } List inputsValue= getComponentInstanceInputsByInputId(component, inputId); - Map> insInputsMatToDelete = new HashMap<>(); - + if(inputsValue != null && !inputsValue.isEmpty()){ for(ComponentInstanceInput inputValue: inputsValue){ String compInstId = inputValue.getComponentInstanceId(); prepareValueBeforeDelete(compInstId, inputForDelete, inputValue, inputValue.getPath()); status = toscaOperationFacade.updateComponentInstanceInput(component, compInstId, inputValue); - List inputList = null; if(status != StorageOperationStatus.OK){ log.debug("Component id: {} update component instance property {} id: {} failed", componentId, inputValue.getUniqueId(), inputId); deleteEither = Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(status), component.getName())); diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ProductComponentInstanceBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ProductComponentInstanceBusinessLogic.java index ab0969358c..7a7148a6a1 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ProductComponentInstanceBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ProductComponentInstanceBusinessLogic.java @@ -30,10 +30,6 @@ import fj.data.Either; @Component("productComponentInstanceBusinessLogic") public class ProductComponentInstanceBusinessLogic extends ComponentInstanceBusinessLogic { - @Override - protected Either validateAllowedToContainCompInstances(org.openecomp.sdc.be.model.Component containerComponent) { - return Either.left(true); - } @Override protected NodeTypeEnum getNodeTypeOfComponentInstanceOrigin() { diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ResourceBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ResourceBusinessLogic.java index cc4a6d9c71..37067e6541 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ResourceBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ResourceBusinessLogic.java @@ -79,6 +79,7 @@ import org.openecomp.sdc.be.model.CapabilityDefinition; import org.openecomp.sdc.be.model.CapabilityTypeDefinition; import org.openecomp.sdc.be.model.Component; import org.openecomp.sdc.be.model.ComponentInstance; +import org.openecomp.sdc.be.model.ComponentInstanceInput; import org.openecomp.sdc.be.model.ComponentInstanceProperty; import org.openecomp.sdc.be.model.ComponentParametersView; import org.openecomp.sdc.be.model.DataTypeDefinition; @@ -86,10 +87,12 @@ import org.openecomp.sdc.be.model.GroupDefinition; import org.openecomp.sdc.be.model.GroupProperty; import org.openecomp.sdc.be.model.GroupTypeDefinition; import org.openecomp.sdc.be.model.HeatParameterDefinition; +import org.openecomp.sdc.be.model.ImportCsarInfo; import org.openecomp.sdc.be.model.InputDefinition; import org.openecomp.sdc.be.model.InterfaceDefinition; import org.openecomp.sdc.be.model.LifeCycleTransitionEnum; import org.openecomp.sdc.be.model.LifecycleStateEnum; +import org.openecomp.sdc.be.model.NodeTypeInfo; import org.openecomp.sdc.be.model.Operation; import org.openecomp.sdc.be.model.ParsedToscaYamlInfo; import org.openecomp.sdc.be.model.PropertyDefinition; @@ -111,13 +114,11 @@ import org.openecomp.sdc.be.model.heat.HeatParameterType; import org.openecomp.sdc.be.model.operations.api.ICacheMangerOperation; import org.openecomp.sdc.be.model.operations.api.ICapabilityTypeOperation; import org.openecomp.sdc.be.model.operations.api.IElementOperation; -import org.openecomp.sdc.be.model.operations.api.IHeatParametersOperation; import org.openecomp.sdc.be.model.operations.api.IInterfaceLifecycleOperation; import org.openecomp.sdc.be.model.operations.api.IPropertyOperation; import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; import org.openecomp.sdc.be.model.operations.impl.CsarOperation; import org.openecomp.sdc.be.model.operations.impl.DaoStatusConverter; -import org.openecomp.sdc.be.model.operations.impl.InputsOperation; import org.openecomp.sdc.be.model.operations.impl.UniqueIdBuilder; import org.openecomp.sdc.be.model.operations.utils.ComponentValidationUtils; import org.openecomp.sdc.be.model.tosca.ToscaPropertyType; @@ -125,6 +126,7 @@ import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum; import org.openecomp.sdc.be.servlets.RepresentationUtils; import org.openecomp.sdc.be.tosca.CsarUtils; import org.openecomp.sdc.be.tosca.CsarUtils.NonMetaArtifactInfo; +import org.openecomp.sdc.be.tosca.ToscaUtils; import org.openecomp.sdc.be.ui.model.UiComponentDataTransfer; import org.openecomp.sdc.be.user.IUserBusinessLogic; import org.openecomp.sdc.be.user.Role; @@ -203,18 +205,6 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { @Autowired private InputsBusinessLogic inputsBusinessLogic; - @javax.annotation.Resource - private InputsOperation inputOperation; - - // @Autowired - // private GroupOperation groupOperation; - - @Autowired - private IHeatParametersOperation heatParametersOperation; - - // @Autowired - // private IArtifactOperation artifactOperation; - @Autowired private CompositionBusinessLogic compositionBusinessLogic; @@ -290,8 +280,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { * the method returns a list of all the resources that are certified, the returned resources are only abstract or only none abstract according to the given param * * @param getAbstract - * @param userId - * TODO + * @param userId TODO * @return */ public Either, ResponseFormat> getAllCertifiedResources(boolean getAbstract, HighestFilterEnum highestFilter, String userId) { @@ -301,16 +290,16 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } Boolean isHighest = null; switch (highestFilter) { - case ALL: - break; - case HIGHEST_ONLY: - isHighest = true; - break; - case NON_HIGHEST_ONLY: - isHighest = false; - break; - default: - break; + case ALL: + break; + case HIGHEST_ONLY: + isHighest = true; + break; + case NON_HIGHEST_ONLY: + isHighest = false; + break; + default: + break; } Either, StorageOperationStatus> getResponse = toscaOperationFacade.getAllCertifiedResources(getAbstract, isHighest); @@ -489,7 +478,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } private Either updateResourceFromCsar(Resource oldRresource, Resource newRresource, User user, AuditingActionEnum updateResource, boolean inTransaction, Either, StorageOperationStatus> csarUIPayload, - String csarUUID) { + String csarUUID) { // check state if (LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT.equals(oldRresource.getLifecycleState())) { @@ -538,19 +527,24 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { Either result = null; String yamlFileName = toscaYamlCsarStatus.left().value().getKey(); + String yamlFileContents = toscaYamlCsarStatus.left().value().getValue(); Either, ResponseFormat> parseNodeTypeInfoYamlEither = null; + ImportCsarInfo importCsarInfo = new ImportCsarInfo(newRresource.getName(), user, csarUUID, csar.left().value()); + try { Either, ResponseFormat> prepareForUpdate = null; Resource preparedResource = null; - Either uploadComponentInstanceInfoMap = parseResourceInfoFromYaml(yamlFileName, newRresource, toscaYamlCsarStatus.left().value().getValue(), user); + Either uploadComponentInstanceInfoMap = parseResourceInfoFromYaml(yamlFileName, newRresource, toscaYamlCsarStatus.left().value().getValue(), user, importCsarInfo.getCreatedNodesToscaResourceNames(), null, null); if (uploadComponentInstanceInfoMap.isRight()) { ResponseFormat responseFormat = uploadComponentInstanceInfoMap.right().value(); componentsUtils.auditResource(responseFormat, user, newRresource, "", "", updateResource, null); result = Either.right(responseFormat); return result; } + Map nodeTypesInfo = extractNodeTypesInfo(csar.left().value(), yamlFileContents); Map instances = uploadComponentInstanceInfoMap.left().value().getInstances(); - Either>>, ResponseFormat> findNodeTypesArtifactsToHandleRes = findNodeTypesArtifactsToHandle(csar.left().value(), csarUUID, yamlFileName, oldRresource, user, true, instances); + Either>>, ResponseFormat> findNodeTypesArtifactsToHandleRes = findNodeTypesArtifactsToHandle(nodeTypesInfo, csar.left().value(), csarUUID, yamlFileName, oldRresource, user, true, + instances); if (findNodeTypesArtifactsToHandleRes.isRight()) { log.debug("failed to find node types for update with artifacts during import csar {}. ", csarUUID); result = Either.right(findNodeTypesArtifactsToHandleRes.right().value()); @@ -567,10 +561,9 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } preparedResource = prepareForUpdate.left().value().left; - String yamlFileContents = toscaYamlCsarStatus.left().value().getValue(); log.trace("YAML topology file found in CSAR, file name: {}, contents: {}", yamlFileName, yamlFileContents); - parseNodeTypeInfoYamlEither = this.handleNodeTypes(yamlFileName, preparedResource, user, yamlFileContents, csar.left().value(), false, nodeTypesArtifactsToHandle, nodeTypesNewCreatedArtifacts); + parseNodeTypeInfoYamlEither = this.handleNodeTypes(yamlFileName, preparedResource, yamlFileContents, false, nodeTypesArtifactsToHandle, nodeTypesNewCreatedArtifacts, nodeTypesInfo, importCsarInfo); if (parseNodeTypeInfoYamlEither.isRight()) { ResponseFormat responseFormat = parseNodeTypeInfoYamlEither.right().value(); componentsUtils.auditResource(responseFormat, user, preparedResource, "", "", updateResource, null); @@ -638,7 +631,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { preparedResource = dataModelResponse.left().value(); } - Either createdCsarArtifactsEither = handleCsarArtifacts(preparedResource, user, csarUUID, csar.left().value(), createdArtifacts, + Either createdCsarArtifactsEither = handleVfCsarArtifacts(preparedResource, importCsarInfo, createdArtifacts, artifactsBusinessLogic.new ArtifactOperationInfo(false, false, ArtifactOperationEnum.Update), false, true); if (createdCsarArtifactsEither.isRight()) { @@ -674,8 +667,8 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } - private Either>>, ResponseFormat> findNodeTypesArtifactsToHandle(Map csar, String csarUUID, String yamlFileName, Resource oldResource, User user, - boolean inTransaction, Map uploadComponentInstanceInfoMap) { + private Either>>, ResponseFormat> findNodeTypesArtifactsToHandle(Map nodeTypesInfo, Map csar, String csarUUID, String yamlFileName, Resource oldResource, User user, + boolean inTransaction, Map uploadComponentInstanceInfoMap) { Map> extractedVfcsArtifacts = CsarUtils.extractVfcsArtifactsFromCsar(csar); Map>> nodeTypesArtifactsToHandle = new HashMap<>(); @@ -683,14 +676,14 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { try { nodeTypesArtifactsToHandleRes = Either.left(nodeTypesArtifactsToHandle); - List>, String>> extractedVfcToscaNames = extractVfcToscaNames(csar, yamlFileName, oldResource.getSystemName(), uploadComponentInstanceInfoMap); - validateNodeTypeIdentifiers(extractedVfcsArtifacts, extractedVfcToscaNames); + Map extractedVfcToscaNames = extractVfcToscaNames(nodeTypesInfo, yamlFileName, oldResource.getSystemName(), uploadComponentInstanceInfoMap); Either>, ResponseFormat> curNodeTypeArtifactsToHandleRes = null; EnumMap> curNodeTypeArtifactsToHandle = null; log.debug("Going to fetch node types for resource with name {} during import csar with UUID {}. ", oldResource.getName(), csarUUID); - for (ImmutablePair>, String> currVfcToscaNameEntry : extractedVfcToscaNames) { + for (Entry currVfcToscaNameEntry : extractedVfcToscaNames.entrySet()) { String currVfcToscaName = currVfcToscaNameEntry.getValue(); + String currNamespace = currVfcToscaNameEntry.getKey(); log.debug("Going to fetch node type with tosca name {}. ", currVfcToscaName); Either curVfcRes = toscaOperationFacade.getLatestByToscaResourceName(currVfcToscaName); @@ -706,10 +699,8 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } if (!MapUtils.isEmpty(extractedVfcsArtifacts)) { List currArtifacts = new ArrayList<>(); - for (String currNamespace : currVfcToscaNameEntry.getKey().getValue()) { - if (extractedVfcsArtifacts.containsKey(currNamespace)) { - handleAndAddExtractedVfcsArtifacts(currArtifacts, extractedVfcsArtifacts.get(currNamespace)); - } + if (extractedVfcsArtifacts.containsKey(currNamespace)) { + handleAndAddExtractedVfcsArtifacts(currArtifacts, extractedVfcsArtifacts.get(currNamespace)); } curNodeTypeArtifactsToHandleRes = findNodeTypeArtifactsToHandle(curNodeType, currArtifacts); if (curNodeTypeArtifactsToHandleRes.isRight()) { @@ -731,7 +722,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } } if (MapUtils.isNotEmpty(curNodeTypeArtifactsToHandle)) { - nodeTypesArtifactsToHandle.put(currVfcToscaNameEntry.getKey().getKey(), curNodeTypeArtifactsToHandle); + nodeTypesArtifactsToHandle.put(currVfcToscaNameEntry.getKey(), curNodeTypeArtifactsToHandle); } } } catch (Exception e) { @@ -742,22 +733,6 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { return nodeTypesArtifactsToHandleRes; } - private void validateNodeTypeIdentifiers(Map> extractedVfcsArtifacts, List>, String>> extractedVfcToscaNames) { - if (extractedVfcsArtifacts != null) { - List validIdentifiers = new ArrayList<>(); - if (extractedVfcToscaNames != null) { - extractedVfcToscaNames.stream().forEach(pair -> { - validIdentifiers.addAll(pair.getKey().getValue()); - validIdentifiers.add(pair.getKey().getKey()); - }); - } - for (String curIdentifier : extractedVfcsArtifacts.keySet()) { - if (validIdentifiers != null && !validIdentifiers.contains(curIdentifier)) - log.warn("Warning - VFC identification {} provided in the Artifacts folder of the CSAR is not valid. ", curIdentifier); - } - } - } - private Either>, ResponseFormat> findNodeTypeArtifactsToHandle(Resource curNodeType, List extractedArtifacts) { Either>, ResponseFormat> nodeTypeArtifactsToHandleRes = null; @@ -870,7 +845,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { * @return */ public Either, ResponseFormat> handleNodeTypeArtifacts(Resource nodeTypeResource, Map> nodeTypeArtifactsToHandle, List vfcsNewCreatedArtifacts, - User user, boolean inTransaction) { + User user, boolean inTransaction) { Either, ResponseFormat> handleNodeTypeArtifactsRequestRes; Either, ResponseFormat> handleNodeTypeArtifactsRes = null; Either changeStateResponse; @@ -912,32 +887,30 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } @SuppressWarnings("unchecked") - private List>, String>> extractVfcToscaNames(Map csar, String yamlFileName, String vfResourceName, Map uploadComponentInstanceInfoMap) { - List>, String>> vfcToscaNames = new ArrayList<>(); - Map nodeTypes; - if (csar != null) { - nodeTypes = new HashMap<>(); - putNodeTypesFromYaml(csar, yamlFileName, nodeTypes); - putNodeTypesFromYaml(csar, Constants.GLOBAL_SUBSTITUTION_TYPES_SERVICE_TEMPLATE, nodeTypes); - putNodeTypesFromYaml(csar, Constants.ABSTRACT_SUBSTITUTE_GLOBAL_TYPES_SERVICE_TEMPLATE, nodeTypes); - Map nestedServiceTemplatesMap = new HashMap<>(); - for(UploadComponentInstanceInfo ci : uploadComponentInstanceInfoMap.values()){ - if(ci.getProperties() != null && ci.getProperties().containsKey("service_template_filter")){ - String tempName = CsarUtils.DEFINITIONS_PATH + ((Map)ci.getProperties().get("service_template_filter").get(0).getValue()).get("substitute_service_template"); - putNodeTypesFromYaml(csar,tempName, nodeTypes); - nestedServiceTemplatesMap.put(ci.getType(), tempName); - } + private Map extractVfcToscaNames(Map nodeTypesInfo, String yamlFileName, String vfResourceName, Map uploadComponentInstanceInfoMap) { + Map vfcToscaNames = new HashMap<>(); + + Map nodes = extractAllNodes(nodeTypesInfo); + if (!nodes.isEmpty()) { + Iterator> nodesNameEntry = nodes.entrySet().iterator(); + while (nodesNameEntry.hasNext()) { + Entry nodeType = nodesNameEntry.next(); + String toscaResourceName = buildNodeToscaResourceName(vfResourceName, nodeType.getKey()); + vfcToscaNames.put(nodeType.getKey(), toscaResourceName); } + } + return vfcToscaNames; + } - if (!nodeTypes.isEmpty()) { - Iterator> nodesNameEntry = nodeTypes.entrySet().iterator(); - while (nodesNameEntry.hasNext()) { - Entry nodeType = nodesNameEntry.next(); - addVfcToscaNameFindSubstitutes(csar, vfResourceName, vfcToscaNames, nodeType.getKey(), nestedServiceTemplatesMap); - } + private Map extractAllNodes(Map nodeTypesInfo) { + Map nodes = new HashMap<>(); + for(NodeTypeInfo nodeTypeInfo: nodeTypesInfo.values()){ + Either, ResultStatusEnum> eitherNodeTypes = ImportUtils.findFirstToscaMapElement(nodeTypeInfo.getMappedToscaTemplate(), ToscaTagNamesEnum.NODE_TYPES); + if (eitherNodeTypes.isLeft()) { + nodes.putAll(eitherNodeTypes.left().value()); } } - return vfcToscaNames; + return nodes; } @SuppressWarnings("unchecked") @@ -954,22 +927,6 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } } - private void addVfcToscaNameFindSubstitutes(Map csar, String vfResourceName, List>, String>> vfcToscaNames, String nodeTypeFullName, Map nestedServiceTemplatesMap) { - - String toscaResourceName = buildNestedVfcToscaResourceName(vfResourceName, nodeTypeFullName); - String nodeTypeTemplateYamlName =null; - if(nestedServiceTemplatesMap.containsKey(nodeTypeFullName)){ - nodeTypeTemplateYamlName = nestedServiceTemplatesMap.get(nodeTypeFullName); - } - List relatedVfcsToscaNameSpaces = new ArrayList<>(); - relatedVfcsToscaNameSpaces.add(buildNestedVfcToscaNamespace(nodeTypeFullName)); - if (nodeTypeTemplateYamlName!=null && csar.containsKey(nodeTypeTemplateYamlName)) { - addSubstituteToscaNamespacesRecursively(csar, nodeTypeTemplateYamlName, relatedVfcsToscaNameSpaces, nestedServiceTemplatesMap); - } - ImmutablePair> toscaNameSpacesHierarchy = new ImmutablePair<>(nodeTypeFullName, relatedVfcsToscaNameSpaces); - vfcToscaNames.add(new ImmutablePair<>(toscaNameSpacesHierarchy, toscaResourceName)); - } - private void addSubstituteToscaNamespacesRecursively(Map csar, String yamlFileName, List toscaNameSpaces, Map nestedServiceTemplatesMap) { Map nodeTypes = new HashMap<>(); @@ -988,12 +945,12 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } toscaNameSpaces.add(toscaNameSpace); - String nodeTypeTemplateYamlName =null; - if(nestedServiceTemplatesMap.containsKey(nodeTypeFullName)){ + String nodeTypeTemplateYamlName = null; + if (nestedServiceTemplatesMap.containsKey(nodeTypeFullName)) { nodeTypeTemplateYamlName = nestedServiceTemplatesMap.get(nodeTypeFullName); } - if (nodeTypeTemplateYamlName!=null && csar.containsKey(nodeTypeTemplateYamlName)) { + if (nodeTypeTemplateYamlName != null && csar.containsKey(nodeTypeTemplateYamlName)) { addSubstituteToscaNamespacesRecursively(csar, nodeTypeTemplateYamlName, toscaNameSpaces, nestedServiceTemplatesMap); } } @@ -1024,7 +981,11 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { String yamlFileName = toscaYamlCsarStatus.left().value().getKey(); String yamlFileContents = toscaYamlCsarStatus.left().value().getValue(); log.trace("YAML topology file found in CSAR, file name: {}, contents: {}", yamlFileName, yamlFileContents); - Either createResourceFromYaml = createResourceFromYaml(resource, user, yamlFileContents, yamlFileName, csar.left().value(), csarUUID); + + Map nodeTypesInfo = extractNodeTypesInfo(csar.left().value(), yamlFileContents); + Map>> nodeTypesArtifactsToCreate = findNodeTypeArtifactsToCreate(csar.left().value(), resource); + ImportCsarInfo importCsarInfo = new ImportCsarInfo(resource.getName(), user, csarUUID, csar.left().value()); + Either createResourceFromYaml = createResourceFromYaml(resource, yamlFileContents, yamlFileName, nodeTypesInfo, importCsarInfo, nodeTypesArtifactsToCreate, true, false, null); if (createResourceFromYaml.isRight()) { log.debug("Couldn't create resource from YAML"); return Either.right(createResourceFromYaml.right().value()); @@ -1035,6 +996,78 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { return Either.left(vfResource); } + @SuppressWarnings("unchecked") + private Map extractNodeTypesInfo(Map csar, String yamlFileContent) { + Map nodeTypesInfo = new HashMap<>(); + List> globalSubstitutes = new ArrayList<>(); + for (Map.Entry entry : csar.entrySet()) { + if (Pattern.compile(CsarUtils.SERVICE_TEMPLATE_PATH_PATTERN).matcher(entry.getKey()).matches()) { + if (!isGlobalSubstitute(entry.getKey())) { + String yamlFileContents = new String(entry.getValue()); + Map mappedToscaTemplate = (Map) new Yaml().load(yamlFileContents); + Either substitutionMappingsEither = ImportUtils.findToscaElement(mappedToscaTemplate, ToscaTagNamesEnum.SUBSTITUTION_MAPPINGS, ToscaElementTypeEnum.MAP); + if (substitutionMappingsEither.isLeft()) { + Map substitutionMappings = (Map) substitutionMappingsEither.left().value(); + if (substitutionMappings.containsKey(ToscaTagNamesEnum.NODE_TYPE.getElementName())) { + NodeTypeInfo nodeTypeInfo = new NodeTypeInfo(); + nodeTypeInfo.setType((String) substitutionMappings.get(ToscaTagNamesEnum.NODE_TYPE.getElementName())); + nodeTypeInfo.setTemplateFileName(entry.getKey()); + nodeTypeInfo.setMappedToscaTemplate(mappedToscaTemplate); + nodeTypesInfo.put(nodeTypeInfo.getType(), nodeTypeInfo); + } + } + } else { + globalSubstitutes.add(entry); + } + } + } + if (CollectionUtils.isNotEmpty(globalSubstitutes)) { + for (Map.Entry entry : globalSubstitutes) { + String yamlFileContents = new String(entry.getValue()); + Map mappedToscaTemplate = (Map) new Yaml().load(yamlFileContents); + Either nodeTypesEither = ImportUtils.findToscaElement(mappedToscaTemplate, ToscaTagNamesEnum.NODE_TYPES, ToscaElementTypeEnum.MAP); + if (nodeTypesEither.isLeft()) { + Map nodeTypes = (Map) nodeTypesEither.left().value(); + for (Entry nodeType : nodeTypes.entrySet()) { + Map nodeTypeMap = (Map) nodeType.getValue(); + if (nodeTypeMap.containsKey(ToscaTagNamesEnum.DERIVED_FROM.getElementName())) { + if (nodeTypesInfo.containsKey(nodeType.getKey())) { + NodeTypeInfo nodeTypeInfo = nodeTypesInfo.get(nodeType.getKey()); + List derivedFrom = new ArrayList<>(); + derivedFrom.add((String) nodeTypeMap.get(ToscaTagNamesEnum.DERIVED_FROM.getElementName())); + nodeTypeInfo.setDerivedFrom(derivedFrom); + } + } + } + } + } + } + markNestedVfc(yamlFileContent, nodeTypesInfo); + return nodeTypesInfo; + } + + private void markNestedVfc(String yamlFileContent, Map nodeTypesInfo) { + Map mappedToscaTemplate = (Map) new Yaml().load(yamlFileContent); + Either nodeTemplatesEither = ImportUtils.findToscaElement(mappedToscaTemplate, ToscaTagNamesEnum.NODE_TEMPLATES, ToscaElementTypeEnum.MAP); + if (nodeTemplatesEither.isLeft()) { + Map nodeTemplates = (Map) nodeTemplatesEither.left().value(); + for (Entry nodeTemplateEntry : nodeTemplates.entrySet()) { + Map nodeTemplate = (Map) nodeTemplateEntry.getValue(); + if (nodeTemplate.containsKey(ToscaTagNamesEnum.TYPE.getElementName())) { + String type = (String) nodeTemplate.get(ToscaTagNamesEnum.TYPE.getElementName()); + if (nodeTypesInfo.containsKey(type)) { + NodeTypeInfo nodeTypeInfo = nodeTypesInfo.get(type); + nodeTypeInfo.setNested(true); + } + } + } + } + } + + private boolean isGlobalSubstitute(String fileName) { + return fileName.equalsIgnoreCase(Constants.GLOBAL_SUBSTITUTION_TYPES_SERVICE_TEMPLATE) || fileName.equalsIgnoreCase(Constants.ABSTRACT_SUBSTITUTE_GLOBAL_TYPES_SERVICE_TEMPLATE); + } + private Either, ResponseFormat> validateAndParseCsar(Resource resource, User user, String csarUUID, Either, StorageOperationStatus> csar) { if (csar.isRight()) { StorageOperationStatus value = csar.right().value(); @@ -1079,8 +1112,8 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { if (validateRes.isRight()) { return Either.right(validateRes.right().value()); } - // VF "derivedFrom" should be null (or ignored) - if (!resource.getResourceType().equals(ResourceTypeEnum.VF)) { + // VF / PNF "derivedFrom" should be null (or ignored) + if (ToscaUtils.isAtomicType(resource)) { Either validateDerivedFromNotEmpty = validateDerivedFromNotEmpty(user, resource, AuditingActionEnum.CREATE_RESOURCE); if (validateDerivedFromNotEmpty.isRight()) { return Either.right(validateDerivedFromNotEmpty.right().value()); @@ -1089,26 +1122,31 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { return validateResourceBeforeCreate(resource, user, AuditingActionEnum.CREATE_RESOURCE, inTransaction); } - - public Either createResourceFromYaml(Resource resource, User user, String topologyTemplateYaml, String yamlName, Map csar, String csarUUID) { +//resource, yamlFileContents, yamlFileName, nodeTypesInfo,importCsarInfo, nodeTypesArtifactsToCreate, true, false, null + private Either createResourceFromYaml(Resource resource, String topologyTemplateYaml, String yamlName, + Map nodeTypesInfo, ImportCsarInfo importCsarInfo, + Map>> nodeTypesArtifactsToCreate, + boolean shouldLock, boolean inTransaction, String nodeTypeName) { List createdArtifacts = new ArrayList(); log.trace("************* createResourceFromYaml before parse yaml "); - Either parseResourceInfoFromYamlEither = parseResourceInfoFromYaml(yamlName, resource, topologyTemplateYaml, user); + Either parseResourceInfoFromYamlEither = parseResourceInfoFromYaml(yamlName, resource, topologyTemplateYaml, importCsarInfo.getModifier(), importCsarInfo.getCreatedNodesToscaResourceNames(), nodeTypesInfo, nodeTypeName); if (parseResourceInfoFromYamlEither.isRight()) { ResponseFormat responseFormat = parseResourceInfoFromYamlEither.right().value(); - componentsUtils.auditResource(responseFormat, user, resource, "", "", AuditingActionEnum.IMPORT_RESOURCE, null); + componentsUtils.auditResource(responseFormat, importCsarInfo.getModifier(), resource, "", "", AuditingActionEnum.IMPORT_RESOURCE, null); return Either.right(responseFormat); } log.trace("************* createResourceFromYaml after parse yaml "); ParsedToscaYamlInfo parsedToscaYamlInfo = parseResourceInfoFromYamlEither.left().value(); log.debug("The parsed tosca yaml info is {}", parsedToscaYamlInfo); log.trace("************* createResourceFromYaml before create "); - Either createdResourceResponse = createResourceAndRIsFromYaml(yamlName, resource, user, parsedToscaYamlInfo, AuditingActionEnum.IMPORT_RESOURCE, false, csarUUID, csar, createdArtifacts, topologyTemplateYaml); + Either createdResourceResponse = createResourceAndRIsFromYaml(yamlName, resource, parsedToscaYamlInfo, + AuditingActionEnum.IMPORT_RESOURCE, false, createdArtifacts, topologyTemplateYaml, + nodeTypesInfo, importCsarInfo, nodeTypesArtifactsToCreate, shouldLock, inTransaction, nodeTypeName); log.trace("************* createResourceFromYaml after create "); if (createdResourceResponse.isRight()) { ResponseFormat responseFormat = createdResourceResponse.right().value(); - componentsUtils.auditResource(responseFormat, user, resource, "", "", AuditingActionEnum.IMPORT_RESOURCE, null); + componentsUtils.auditResource(responseFormat, importCsarInfo.getModifier(), resource, "", "", AuditingActionEnum.IMPORT_RESOURCE, null); return Either.right(responseFormat); } @@ -1116,48 +1154,109 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } - public Either, ResponseFormat> createResourcesFromYamlNodeTypesList(String yamlName, Resource resource, String resourceYml, User user, boolean needLock, - Map>> nodeTypesArtifactsToHandle, List nodeTypesNewCreatedArtifacts) { - - Map mappedToscaTemplate = (Map) new Yaml().load(resourceYml); + @SuppressWarnings("unchecked") + public Either, ResponseFormat> createResourcesFromYamlNodeTypesList(String yamlName, Resource resource, String resourceYml, Map mappedToscaTemplate, boolean needLock, + Map>> nodeTypesArtifactsToHandle, List nodeTypesNewCreatedArtifacts, + Map nodeTypesInfo, ImportCsarInfo importCsarInfo) { Either tosca_version = ImportUtils.findFirstToscaStringElement(mappedToscaTemplate, ToscaTagNamesEnum.TOSCA_VERSION); if (tosca_version.isRight()) { ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_TOSCA_TEMPLATE); return Either.right(responseFormat); } - Either, ResultStatusEnum> eitherNodeTypes = ImportUtils.findFirstToscaMapElement(mappedToscaTemplate, ToscaTagNamesEnum.NODE_TYPES); - Map nodeTypesResources = new HashMap<>(); Either, ResponseFormat> result = Either.left(nodeTypesResources); - Map mapToConvert = new HashMap(); mapToConvert.put(ToscaTagNamesEnum.TOSCA_VERSION.getElementName(), tosca_version.left().value()); - + Resource vfcCreated = null; if (eitherNodeTypes.isLeft()) { - Iterator> nodesNameValue = eitherNodeTypes.left().value().entrySet().iterator(); - while (nodesNameValue.hasNext()) { - Entry nodeType = nodesNameValue.next(); Map> nodeTypeArtifactsToHandle = nodeTypesArtifactsToHandle == null || nodeTypesArtifactsToHandle.isEmpty() ? null : nodeTypesArtifactsToHandle.get(nodeType.getKey()); - log.trace("************* Going to create node {}", nodeType.getKey()); - Either, ResponseFormat> resourceCreated = this.createNodeTypeResourceFromYaml(yamlName, nodeType, user, mapToConvert, resource, needLock, nodeTypeArtifactsToHandle, nodeTypesNewCreatedArtifacts); - log.trace("************* finished to create node {}", nodeType.getKey()); - if (resourceCreated.isRight()) { - return Either.right(resourceCreated.right().value()); - } - Resource vfcCreated = resourceCreated.left().value().getLeft(); - nodeTypesResources.put(nodeType.getKey(), vfcCreated); + if (nodeTypesInfo.containsKey(nodeType.getKey())) { + log.trace("************* Going to handle nested vfc {}", nodeType.getKey()); + Either handleNeatedVfcYaml = handleNestedVfc(resource, nodeTypesArtifactsToHandle, nodeTypesNewCreatedArtifacts, nodeTypesInfo, importCsarInfo, nodeType.getKey(), nodeTypesResources); + log.trace("************* Finished to handle nested vfc {}", nodeType.getKey()); + if (handleNeatedVfcYaml.isRight()) { + return Either.right(handleNeatedVfcYaml.right().value()); + } + vfcCreated = handleNeatedVfcYaml.left().value(); + } else if(importCsarInfo.getCreatedNodesToscaResourceNames()!= null && !importCsarInfo.getCreatedNodesToscaResourceNames().containsKey(nodeType.getKey())){ + log.trace("************* Going to create node {}", nodeType.getKey()); + Either, ResponseFormat> resourceCreated = this.createNodeTypeResourceFromYaml(yamlName, nodeType, importCsarInfo.getModifier(), mapToConvert, resource, needLock, nodeTypeArtifactsToHandle, nodeTypesNewCreatedArtifacts, true); + log.debug("************* Finished to create node {}", nodeType.getKey()); + + if (resourceCreated.isRight()) { + return Either.right(resourceCreated.right().value()); + } + vfcCreated = resourceCreated.left().value().getLeft(); + importCsarInfo.getCreatedNodesToscaResourceNames().put(nodeType.getKey(),vfcCreated.getToscaResourceName()); + } + if (vfcCreated != null) { + nodeTypesResources.put(nodeType.getKey(), vfcCreated); + } mapToConvert.remove(ToscaTagNamesEnum.NODE_TYPES.getElementName()); + } + } + return result; + } + + private Either handleNestedVfc(Resource resource, Map>> nodeTypesArtifactsToHandle, + List nodeTypesNewCreatedArtifacts, Map nodeTypesInfo, ImportCsarInfo importCsarInfo, + String nodeType, Map createdResourcesFromdNodeTypeMap) { + + Either handleNestedVfcRes = Either.left(resource); + String serviceTemplateFileFullName = nodeTypesInfo.get(nodeType).getTemplateFileName(); + String serviceTemplateFileContent = new String(importCsarInfo.getCsar().get(serviceTemplateFileFullName)); + Map nestedVfcJsonMap = nodeTypesInfo.get(nodeType).getMappedToscaTemplate(); + + Either, ResponseFormat> createdResourcesFromdNodeTypeMapEither = createResourcesFromYamlNodeTypesList(serviceTemplateFileFullName, resource, serviceTemplateFileContent, + nestedVfcJsonMap, false, nodeTypesArtifactsToHandle, nodeTypesNewCreatedArtifacts, nodeTypesInfo, importCsarInfo); + log.debug("************* Finished to create all nodes from yaml {}", serviceTemplateFileFullName); + if (createdResourcesFromdNodeTypeMapEither.isRight()) { + log.debug("failed to resources from node types status is {}", createdResourcesFromdNodeTypeMapEither.right().value()); + return Either.right(createdResourcesFromdNodeTypeMapEither.right().value()); + } + createdResourcesFromdNodeTypeMap.putAll(createdResourcesFromdNodeTypeMapEither.left().value()); + if (nestedVfcJsonMap.containsKey(ToscaTagNamesEnum.TOPOLOGY_TEMPLATE.getElementName())) { + Resource complexVfc = new Resource(); + fillComplexVfcMetadata(resource, importCsarInfo, complexVfc, nodeType, nodeTypesInfo, false); + if(!importCsarInfo.getCvfcToCreateQueue().contains(nodeType)){ + importCsarInfo.getCvfcToCreateQueue().add(nodeType); + } else { + log.debug("CFVC LOOP DETECTED, VSP {}, CVFC {}", importCsarInfo.getVfResourceName(), complexVfc.getName()); + return Either.right(componentsUtils.getResponseFormat(ActionStatus.CFVC_LOOP_DETECTED, importCsarInfo.getVfResourceName(), complexVfc.getName())); + } + Either validationRes = validateResourceBeforeCreate(complexVfc, importCsarInfo.getModifier(), AuditingActionEnum.IMPORT_RESOURCE, true); + if(validationRes.isRight()){ + log.debug("Failed to validate complex VFC {}. ", complexVfc.getName()); + return validationRes; + } + Map newNodeTypesInfo = nodeTypesInfo.entrySet().stream().collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue().getUnmarkedCopy())); + markNestedVfc(serviceTemplateFileContent, newNodeTypesInfo); + handleNestedVfcRes = createResourceFromYaml(complexVfc, serviceTemplateFileContent, serviceTemplateFileFullName, + newNodeTypesInfo, importCsarInfo, nodeTypesArtifactsToHandle, false, true, nodeType); + if (handleNestedVfcRes.isRight()) { + log.debug("Couldn't create resource from YAML"); + return Either.right(handleNestedVfcRes.right().value()); } + importCsarInfo.getCreatedNodesToscaResourceNames().put(nodeType, handleNestedVfcRes.left().value().getToscaResourceName()); + LifecycleChangeInfoWithAction lifecycleChangeInfo = new LifecycleChangeInfoWithAction("certification on import", LifecycleChanceActionEnum.CREATE_FROM_CSAR); + log.debug("Going to certify cvfc {}. ", handleNestedVfcRes.left().value().getName()); + Either certRes = propagateStateToCertified(importCsarInfo.getModifier(), handleNestedVfcRes.left().value(), lifecycleChangeInfo, true, false, true); + if (certRes.isRight()) { + log.debug("Couldn't certify resource {}. ", handleNestedVfcRes.left().value()); + return certRes; + } + createdResourcesFromdNodeTypeMap.put(nodeType, certRes.left().value()); + importCsarInfo.getCvfcToCreateQueue().remove(); } - return result; + return handleNestedVfcRes; } private String getNodeTypeActualName(String fullName) { @@ -1168,40 +1267,44 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } private Either, ResponseFormat> createNodeTypeResourceFromYaml(String yamlName, Entry nodeNameValue, User user, Map mapToConvert, Resource resourceVf, boolean needLock, - Map> nodeTypeArtifactsToHandle, List nodeTypesNewCreatedArtifacts) { + Map> nodeTypeArtifactsToHandle, List nodeTypesNewCreatedArtifacts, boolean forceCertificationAllowed) { Either resourceMetaData = fillResourceMetadata(yamlName, resourceVf, nodeNameValue.getKey(), user); if (resourceMetaData.isRight()) { return Either.right(resourceMetaData.right().value()); } + String csarVfName = resourceVf.getSystemName(); + String singleVfcYaml = buildNodeTypeYaml(nodeNameValue, mapToConvert, resourceMetaData.left().value().getResourceType(), csarVfName); + + Either eitherCreator = validateUser(user, "CheckIn Resource", resourceVf, AuditingActionEnum.CHECKIN_RESOURCE, true); + if (eitherCreator.isRight()) { + return Either.right(eitherCreator.right().value()); + } + user = eitherCreator.left().value(); + + return this.createResourceFromNodeType(singleVfcYaml, resourceMetaData.left().value(), user, true, needLock, nodeTypeArtifactsToHandle, nodeTypesNewCreatedArtifacts, forceCertificationAllowed); + } + private String buildNodeTypeYaml(Entry nodeNameValue, Map mapToConvert, String nodeResourceType, String csarVfName) { // We need to create a Yaml from each node_types in order to create // resource from each node type using import normative flow. DumperOptions options = new DumperOptions(); options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK); Yaml yaml = new Yaml(options); - Map singleVfc = new HashMap<>(); + Map node = new HashMap<>(); + node.put(buildNestedToscaResourceName(nodeResourceType, csarVfName, nodeNameValue.getKey()), nodeNameValue.getValue()); + mapToConvert.put(ToscaTagNamesEnum.NODE_TYPES.getElementName(), node); + + return yaml.dumpAsMap(mapToConvert); + } - String actualName = this.getNodeTypeActualName(nodeNameValue.getKey()); + private String buildNestedToscaResourceName(String nodeResourceType, String csarVfName, String originToscaResourceName) { + String actualName = getNodeTypeActualName(originToscaResourceName); if (!actualName.startsWith(Constants.ABSTRACT)) { actualName = "." + Constants.ABSTRACT + actualName; } - - // Setting tosca name - String toscaResourceName = ImportUtils.Constants.USER_DEFINED_RESOURCE_NAMESPACE_PREFIX + resourceMetaData.left().value().getResourceType().toLowerCase() + '.' + resourceVf.getSystemName() + actualName; - singleVfc.put(toscaResourceName, nodeNameValue.getValue()); - mapToConvert.put(ToscaTagNamesEnum.NODE_TYPES.getElementName(), singleVfc); - - String singleVfcYaml = yaml.dumpAsMap(mapToConvert); - - Either eitherCreator = validateUser(user, "CheckIn Resource", resourceVf, AuditingActionEnum.CHECKIN_RESOURCE, true); - if (eitherCreator.isRight()) { - return Either.right(eitherCreator.right().value()); - } - user = eitherCreator.left().value(); - - return this.createResourceFromNodeType(singleVfcYaml, resourceMetaData.left().value(), user, true, needLock, nodeTypeArtifactsToHandle, nodeTypesNewCreatedArtifacts); + return ImportUtils.Constants.USER_DEFINED_RESOURCE_NAMESPACE_PREFIX + nodeResourceType.toLowerCase() + '.' + ValidationUtils.convertToSystemName(csarVfName) + actualName; } public Either validateResourceCreationFromNodeType(Resource resource, User creator) { @@ -1214,11 +1317,11 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } public Either, ResponseFormat> createResourceFromNodeType(String nodeTypeYaml, UploadResourceInfo resourceMetaData, User creator, boolean isInTransaction, boolean needLock, - Map> nodeTypeArtifactsToHandle, List nodeTypesNewCreatedArtifacts) { + Map> nodeTypeArtifactsToHandle, List nodeTypesNewCreatedArtifacts, boolean forceCertificationAllowed) { LifecycleChangeInfoWithAction lifecycleChangeInfo = new LifecycleChangeInfoWithAction("certification on import", LifecycleChanceActionEnum.CREATE_FROM_CSAR); Function> validator = (resource) -> this.validateResourceCreationFromNodeType(resource, creator); - return this.resourceImportManager.importCertifiedResource(nodeTypeYaml, resourceMetaData, creator, validator, lifecycleChangeInfo, isInTransaction, true, needLock, nodeTypeArtifactsToHandle, nodeTypesNewCreatedArtifacts); + return this.resourceImportManager.importCertifiedResource(nodeTypeYaml, resourceMetaData, creator, validator, lifecycleChangeInfo, isInTransaction, true, needLock, nodeTypeArtifactsToHandle, nodeTypesNewCreatedArtifacts, forceCertificationAllowed); } private Either fillResourceMetadata(String yamlName, Resource resourceVf, String nodeTypeName, User user) { @@ -1279,20 +1382,76 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { return Either.left(resourceMetaData); } - private Either createResourceAndRIsFromYaml(String yamlName, Resource resource, User user, ParsedToscaYamlInfo parsedToscaYamlInfo, AuditingActionEnum actionEnum, boolean isNormative, String csarUUID, - Map csar, List createdArtifacts, String topologyTemplateYaml) { + private void fillComplexVfcMetadata(Resource resourceVf, ImportCsarInfo importCsarInfo, Resource cvfc, String nodeTypeName, Map nodeTypesInfo, boolean shouldBeCertified) { + NodeTypeInfo nodeTypeInfo = nodeTypesInfo.get(nodeTypeName); + cvfc.setName(buildCvfcName(importCsarInfo.getVfResourceName(), nodeTypeName)); + cvfc.setNormalizedName(ValidationUtils.normaliseComponentName(cvfc.getName())); + cvfc.setSystemName(ValidationUtils.convertToSystemName(cvfc.getName())); + cvfc.setResourceType(ResourceTypeEnum.CVFC); + cvfc.setAbstract(true); + cvfc.setDerivedFrom(nodeTypeInfo.getDerivedFrom()); + cvfc.setDescription(ImportUtils.Constants.CVFC_DESCRIPTION); + cvfc.setIcon(ImportUtils.Constants.DEFAULT_ICON); + cvfc.setContactId(importCsarInfo.getModifier().getUserId()); + cvfc.setCreatorUserId(importCsarInfo.getModifier().getUserId()); + cvfc.setVendorName(resourceVf.getVendorName()); + cvfc.setVendorRelease(resourceVf.getVendorRelease()); + cvfc.setResourceVendorModelNumber(resourceVf.getResourceVendorModelNumber()); + cvfc.setToscaResourceName(buildNestedToscaResourceName(ResourceTypeEnum.VFC.name(), importCsarInfo.getVfResourceName(), nodeTypeName)); + cvfc.setInvariantUUID(UniqueIdBuilder.buildInvariantUUID()); + + List tags = new ArrayList<>(); + tags.add(cvfc.getName()); + cvfc.setTags(tags); + + CategoryDefinition category = new CategoryDefinition(); + category.setName(ImportUtils.Constants.ABSTRACT_CATEGORY_NAME); + SubCategoryDefinition subCategory = new SubCategoryDefinition(); + subCategory.setName(ImportUtils.Constants.ABSTRACT_SUBCATEGORY); + category.addSubCategory(subCategory); + List categories = new ArrayList<>(); + categories.add(category); + cvfc.setCategories(categories); + + String version; + LifecycleStateEnum state; + + if (shouldBeCertified) { + version = ImportUtils.Constants.FIRST_CERTIFIED_VERSION_VERSION; + state = ImportUtils.Constants.NORMATIVE_TYPE_LIFE_CYCLE; + } else { + version = ImportUtils.Constants.FIRST_NON_CERTIFIED_VERSION; + state = ImportUtils.Constants.NORMATIVE_TYPE_LIFE_CYCLE_NOT_CERTIFIED_CHECKOUT; + } + cvfc.setVersion(version); + cvfc.setLifecycleState(state); + cvfc.setHighestVersion(ImportUtils.Constants.NORMATIVE_TYPE_HIGHEST_VERSION); + } + + private String buildCvfcName(String resourceVfName, String nodeTypeName) { + String nameWithouNamespacePrefix = nodeTypeName.substring(Constants.USER_DEFINED_RESOURCE_NAMESPACE_PREFIX.length()); + String[] findTypes = nameWithouNamespacePrefix.split("\\."); + String resourceType = findTypes[0]; + return resourceVfName + "-" + nameWithouNamespacePrefix.substring(resourceType.length() + 1); + } + + private Either createResourceAndRIsFromYaml(String yamlName, Resource resource, ParsedToscaYamlInfo parsedToscaYamlInfo, AuditingActionEnum actionEnum, boolean isNormative, + List createdArtifacts, String topologyTemplateYaml, Map nodeTypesInfo, + ImportCsarInfo importCsarInfo, Map>> nodeTypesArtifactsToCreate, + boolean shouldLock, boolean inTransaction, String nodeTypeName) { boolean result = true; - boolean inTransaction = true; Map createdVfcs = new HashMap<>(); List nodeTypesNewCreatedArtifacts = new ArrayList<>(); - Either lockResult = lockComponentByName(resource.getSystemName(), resource, "Create Resource"); - if (lockResult.isRight()) { - ResponseFormat responseFormat = lockResult.right().value(); - return Either.right(responseFormat); - } - log.debug("name is locked {} status = {}", resource.getSystemName(), lockResult); + if (shouldLock) { + Either lockResult = lockComponentByName(resource.getSystemName(), resource, "Create Resource"); + if (lockResult.isRight()) { + ResponseFormat responseFormat = lockResult.right().value(); + return Either.right(responseFormat); + } + log.debug("name is locked {} status = {}", resource.getSystemName(), lockResult); + } try { log.trace("************* createResourceFromYaml before full create resource {}", yamlName); Either genericResourceEither = fetchAndSetDerivedFromGenericType(resource); @@ -1300,7 +1459,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { result = false; return genericResourceEither; } - Either createResourcesEither = createResourceTransaction(resource, user, isNormative, inTransaction); + Either createResourcesEither = createResourceTransaction(resource, importCsarInfo.getModifier(), isNormative, inTransaction); log.trace("************* createResourceFromYaml after full create resource {}", yamlName); if (createResourcesEither.isRight()) { result = false; @@ -1313,7 +1472,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { generateInputsFromGenericTypeProperties(resource, genericResourceEither.left().value()); Map inputs = parsedToscaYamlInfo.getInputs(); - Either createInputsOnResource = createInputsOnResource(resource, user, inputs, inTransaction); + Either createInputsOnResource = createInputsOnResource(resource, importCsarInfo.getModifier(), inputs, inTransaction); if (createInputsOnResource.isRight()) { result = false; return createInputsOnResource; @@ -1323,7 +1482,9 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { Map uploadComponentInstanceInfoMap = parsedToscaYamlInfo.getInstances(); log.trace("************* Going to create nodes, RI's and Relations from yaml {}", yamlName); - createResourcesEither = createRIAndRelationsFromYaml(yamlName, resource, user, uploadComponentInstanceInfoMap, actionEnum, topologyTemplateYaml, csar, csarUUID, nodeTypesNewCreatedArtifacts, createdVfcs); + + createResourcesEither = createRIAndRelationsFromYaml(yamlName, resource, uploadComponentInstanceInfoMap, actionEnum, topologyTemplateYaml, + nodeTypesNewCreatedArtifacts, createdVfcs, nodeTypesInfo, importCsarInfo, nodeTypesArtifactsToCreate); log.trace("************* Finished to create nodes, RI and Relation from yaml {}", yamlName); if (createResourcesEither.isRight()) { result = false; @@ -1346,7 +1507,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } else { groups = parsedToscaYamlInfo.getGroups(); } - Either createGroupsOnResource = createGroupsOnResource(resource, user, groups); + Either createGroupsOnResource = createGroupsOnResource(resource, importCsarInfo.getModifier(), groups); if (createGroupsOnResource.isRight()) { result = false; return createGroupsOnResource; @@ -1355,43 +1516,54 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { log.trace("************* Finished to add groups from yaml {}", yamlName); log.trace("************* Going to add artifacts from yaml {}", yamlName); - Either createdCsarArtifactsEither = this.handleCsarArtifacts(resource, user, csarUUID, csar, createdArtifacts, artifactsBusinessLogic.new ArtifactOperationInfo(false, false, ArtifactOperationEnum.Create), false, - inTransaction); - log.trace("************* Finished to add artifacts from yaml {}", yamlName); - if (createdCsarArtifactsEither.isRight()) { - result = false; - return createdCsarArtifactsEither; - } - resource = createdCsarArtifactsEither.left().value(); + if(resource.getResourceType() == ResourceTypeEnum.CVFC){ + if(nodeTypesArtifactsToCreate.containsKey(nodeTypeName) && nodeTypesArtifactsToCreate.get(nodeTypeName) !=null && !nodeTypesArtifactsToCreate.get(nodeTypeName).isEmpty()){ + Either, ResponseFormat> handleNodeTypeArtifactsRes = + handleNodeTypeArtifacts(resource, nodeTypesArtifactsToCreate.get(nodeTypeName), nodeTypesNewCreatedArtifacts, importCsarInfo.getModifier(), true); + if(handleNodeTypeArtifactsRes.isRight()){ + return Either.right(handleNodeTypeArtifactsRes.right().value()); + } + } + } else { + Either createdCsarArtifactsEither = this.handleVfCsarArtifacts(resource, importCsarInfo, createdArtifacts, artifactsBusinessLogic.new ArtifactOperationInfo(false, false, ArtifactOperationEnum.Create), false, + inTransaction); + log.trace("************* Finished to add artifacts from yaml {}", yamlName); + if (createdCsarArtifactsEither.isRight()) { + result = false; + return createdCsarArtifactsEither; + } + resource = createdCsarArtifactsEither.left().value(); + } ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.CREATED); - componentsUtils.auditResource(responseFormat, user, resource, "", "", actionEnum, null); + componentsUtils.auditResource(responseFormat, importCsarInfo.getModifier(), resource, "", "", actionEnum, null); ASDCKpiApi.countCreatedResourcesKPI(); return Either.left(resource); } finally { - if (!result) { - log.warn("operation failed. do rollback"); - titanDao.rollback(); - if (!createdArtifacts.isEmpty() || !nodeTypesNewCreatedArtifacts.isEmpty()) { - createdArtifacts.addAll(nodeTypesNewCreatedArtifacts); - StorageOperationStatus deleteFromEsRes = artifactsBusinessLogic.deleteAllComponentArtifactsIfNotOnGraph(createdArtifacts); - if (!deleteFromEsRes.equals(StorageOperationStatus.OK)) { - ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(deleteFromEsRes); - ResponseFormat responseFormat = componentsUtils.getResponseFormat(actionStatus, resource.getName()); + if (!inTransaction) { + if (!result) { + log.warn("operation failed. do rollback"); + titanDao.rollback(); + if (!createdArtifacts.isEmpty() || !nodeTypesNewCreatedArtifacts.isEmpty()) { + createdArtifacts.addAll(nodeTypesNewCreatedArtifacts); + StorageOperationStatus deleteFromEsRes = artifactsBusinessLogic.deleteAllComponentArtifactsIfNotOnGraph(createdArtifacts); + if (!deleteFromEsRes.equals(StorageOperationStatus.OK)) { + ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(deleteFromEsRes); + ResponseFormat responseFormat = componentsUtils.getResponseFormat(actionStatus, resource.getName()); + } + log.debug("component and all its artifacts were deleted, id = {}", resource.getName()); } - log.debug("component and all its artifacts were deleted, id = {}", resource.getName()); - } - } else { - log.debug("operation success. do commit"); - titanDao.commit(); + } else { + log.debug("operation success. do commit"); + titanDao.commit(); + } + } + if (shouldLock) { + graphLockOperation.unlockComponentByName(resource.getSystemName(), resource.getUniqueId(), NodeTypeEnum.Resource); } - - graphLockOperation.unlockComponentByName(resource.getSystemName(), resource.getUniqueId(), NodeTypeEnum.Resource); - } - } private Either createGroupsOnResource(Resource resource, User user, Map groups) { @@ -1493,11 +1665,12 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } private Either createInputsOnResource(Resource resource, User user, Map inputs, boolean inTransaction) { - if (inputs != null && false == inputs.isEmpty()) { + List resourceProperties = resource.getInputs(); + if ( (inputs != null && false == inputs.isEmpty()) || (resourceProperties != null && false == resourceProperties.isEmpty()) ) { - Either, ResponseFormat> createGroups = inputsBusinessLogic.createInputsInGraph(inputs, resource, user, inTransaction); - if (createGroups.isRight()) { - return Either.right(createGroups.right().value()); + Either, ResponseFormat> createInputs = inputsBusinessLogic.createInputsInGraph(inputs, resource, user, inTransaction); + if (createInputs.isRight()) { + return Either.right(createInputs.right().value()); } } else { return Either.left(resource); @@ -1618,12 +1791,12 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { // Filtered Members Of Current Group containing only members which // are groups List currGroupFilteredMembers = currGroupMembers.stream(). - // Keep Only Elements of type group and not Resource Instances - filter(innerGroupName -> allGroups.containsKey(innerGroupName)). + // Keep Only Elements of type group and not Resource Instances + filter(innerGroupName -> allGroups.containsKey(innerGroupName)). // Add Filtered Elements to main Set - peek(innerGroupName -> allGroupMembers.add(innerGroupName)). + peek(innerGroupName -> allGroupMembers.add(innerGroupName)). // Collect results - collect(Collectors.toList()); + collect(Collectors.toList()); // Recursively call the method for all the filtered group members for (String innerGroupName : currGroupFilteredMembers) { @@ -1649,25 +1822,24 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { if (!stop) { final Set allMembers = allGroups.get(groupName).getMembers().keySet(); Set membersOfTypeGroup = allMembers.stream(). - // Filter In Only Group members - filter(innerGroupName -> allGroups.containsKey(innerGroupName)). + // Filter In Only Group members + filter(innerGroupName -> allGroups.containsKey(innerGroupName)). // Collect - collect(Collectors.toSet()); + collect(Collectors.toSet()); stop = allGroupMembers.containsAll(membersOfTypeGroup); } return stop; } - private Either createRIAndRelationsFromYaml(String yamlName, Resource resource, User user, Map uploadComponentInstanceInfoMap, AuditingActionEnum actionEnum, - String topologyTemplateYaml, Map csar, String csarUUID, List nodeTypesNewCreatedArtifacts, Map createdVfcs) { + private Either createRIAndRelationsFromYaml(String yamlName, Resource resource, Map uploadComponentInstanceInfoMap, AuditingActionEnum actionEnum, + String topologyTemplateYaml, List nodeTypesNewCreatedArtifacts, Map createdVfcs, + Map nodeTypesInfo, ImportCsarInfo importCsarInfo, Map>> nodeTypesArtifactsToCreate) { Either result; Either createResourcesInstancesEither; - Map>> nodeTypesArtifactsToCreate = findNodeTypeArtifactsToCreate(csar, yamlName, resource, uploadComponentInstanceInfoMap); - log.debug("************* Going to create all nodes {}", yamlName); - Either, ResponseFormat> createdResourcesFromdNodeTypeMap = this.handleNodeTypes(yamlName, resource, user, topologyTemplateYaml, csar, false, nodeTypesArtifactsToCreate, nodeTypesNewCreatedArtifacts); + Either, ResponseFormat> createdResourcesFromdNodeTypeMap = this.handleNodeTypes(yamlName, resource, topologyTemplateYaml, false, nodeTypesArtifactsToCreate, nodeTypesNewCreatedArtifacts, nodeTypesInfo, importCsarInfo); log.debug("************* Finished to create all nodes {}", yamlName); if (createdResourcesFromdNodeTypeMap.isRight()) { log.debug("failed to resources from node types status is {}", createdResourcesFromdNodeTypeMap.right().value()); @@ -1677,7 +1849,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { createdVfcs.putAll(createdResourcesFromdNodeTypeMap.left().value()); log.debug("************* Going to create all resource instances {}", yamlName); - createResourcesInstancesEither = createResourceInstances(user, yamlName, resource, uploadComponentInstanceInfoMap, true, false, createdResourcesFromdNodeTypeMap.left().value()); + createResourcesInstancesEither = createResourceInstances(importCsarInfo.getModifier(), yamlName, resource, uploadComponentInstanceInfoMap, true, false, createdResourcesFromdNodeTypeMap.left().value()); log.debug("************* Finished to create all resource instances {}", yamlName); if (createResourcesInstancesEither.isRight()) { @@ -1687,7 +1859,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } resource = createResourcesInstancesEither.left().value(); log.debug("************* Going to create all relations {}", yamlName); - createResourcesInstancesEither = createResourceInstancesRelations(user, yamlName, resource, uploadComponentInstanceInfoMap, true, false); + createResourcesInstancesEither = createResourceInstancesRelations(importCsarInfo.getModifier(), yamlName, resource, uploadComponentInstanceInfoMap, true, false); log.debug("************* Finished to create all relations {}", yamlName); @@ -1700,44 +1872,21 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } log.debug("************* Going to create positions {}", yamlName); - Either, ResponseFormat> eitherSetPosition = compositionBusinessLogic.setPositionsForComponentInstances(resource, user.getUserId()); + Either, ResponseFormat> eitherSetPosition = compositionBusinessLogic.setPositionsForComponentInstances(resource, importCsarInfo.getModifier().getUserId()); log.debug("************* Finished to set positions {}", yamlName); result = eitherSetPosition.isRight() ? Either.right(eitherSetPosition.right().value()) : Either.left(resource); return result; } - private Map>> findNodeTypeArtifactsToCreate(Map csar, String yamlName, Resource resource, Map uploadComponentInstanceInfoMap) { + private Map>> findNodeTypeArtifactsToCreate(Map csar, Resource resource) { Map> extractedVfcsArtifacts = CsarUtils.extractVfcsArtifactsFromCsar(csar); - List>, String>> extractedVfcToscaNames = extractVfcToscaNames(csar, yamlName, resource.getSystemName(), uploadComponentInstanceInfoMap); - validateNodeTypeIdentifiers(extractedVfcsArtifacts, extractedVfcToscaNames); - Map>> nodeTypesArtifactsToHandle = null; - if (!extractedVfcsArtifacts.isEmpty() && !extractedVfcToscaNames.isEmpty()) { - for (ImmutablePair>, String> currToscaNamePair : extractedVfcToscaNames) { - EnumMap> curNodeTypeArtifacts = null; - String currVfcToscaNamespace = currToscaNamePair.getKey().getKey(); - List relatedVfcs = currToscaNamePair.getKey().getValue(); - List currArtifactList = null; - - for (String currSubstitute : relatedVfcs) { - if (extractedVfcsArtifacts.containsKey(currSubstitute)) { - if (MapUtils.isEmpty(curNodeTypeArtifacts)) { - curNodeTypeArtifacts = new EnumMap<>(ArtifactOperationEnum.class); - currArtifactList = new ArrayList<>(); - curNodeTypeArtifacts.put(ArtifactOperationEnum.Create, currArtifactList); - } else { - currArtifactList = curNodeTypeArtifacts.get(ArtifactOperationEnum.Create); - } - handleAndAddExtractedVfcsArtifacts(currArtifactList, extractedVfcsArtifacts.get(currSubstitute)); - } - } - - if (nodeTypesArtifactsToHandle == null) { - nodeTypesArtifactsToHandle = new HashMap<>(); - } - nodeTypesArtifactsToHandle.put(currVfcToscaNamespace, curNodeTypeArtifacts); - } + Map>> nodeTypesArtifactsToHandle = new HashMap<>(); + for (Map.Entry> currArts : extractedVfcsArtifacts.entrySet()) { + EnumMap> artifactsToCreate = new EnumMap<>(ArtifactOperationEnum.class); + artifactsToCreate.put(ArtifactOperationEnum.Create, currArts.getValue()); + nodeTypesArtifactsToHandle.put(currArts.getKey(), artifactsToCreate); } return nodeTypesArtifactsToHandle; } @@ -1754,31 +1903,30 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } - private Either, ResponseFormat> handleNodeTypes(String yamlName, Resource resource, User user, String topologyTemplateYaml, Map csar, boolean needLock, - Map>> nodeTypesArtifactsToHandle, List nodeTypesNewCreatedArtifacts) { + @SuppressWarnings("unchecked") + private Either, ResponseFormat> handleNodeTypes(String yamlName, Resource resource, String topologyTemplateYaml, boolean needLock, + Map>> nodeTypesArtifactsToHandle, List nodeTypesNewCreatedArtifacts, + Map nodeTypesInfo, ImportCsarInfo importCsarInfo) { Map createdResourcesFromdNodeTypeMap = new HashMap<>(); Either, ResponseFormat> result = Either.left(createdResourcesFromdNodeTypeMap); + for (Entry nodeTypeEntry : nodeTypesInfo.entrySet()) { + if (nodeTypeEntry.getValue().isNested()) { - String yamlFileName = Constants.GLOBAL_SUBSTITUTION_TYPES_SERVICE_TEMPLATE; - - if (csar != null && csar.containsKey(yamlFileName)) { - byte[] yamlFileBytes = csar.get(yamlFileName); - String globalTypesYaml = new String(yamlFileBytes, StandardCharsets.UTF_8); - Either, ResponseFormat> createdNodeTypesFromGlobalTypesTemplateEither = this.createResourcesFromYamlNodeTypesList(yamlFileName, resource, globalTypesYaml, user, needLock, nodeTypesArtifactsToHandle, - nodeTypesNewCreatedArtifacts); - if (createdNodeTypesFromGlobalTypesTemplateEither.isRight()) { - ResponseFormat responseFormat = createdNodeTypesFromGlobalTypesTemplateEither.right().value(); - componentsUtils.auditResource(responseFormat, user, resource, "", "", AuditingActionEnum.IMPORT_RESOURCE, null); - return Either.right(responseFormat); + Either createResourceFromYaml = handleNestedVfc(resource, nodeTypesArtifactsToHandle, + nodeTypesNewCreatedArtifacts, nodeTypesInfo, importCsarInfo, nodeTypeEntry.getKey(), createdResourcesFromdNodeTypeMap); + log.trace("************* finished to create node {}", nodeTypeEntry.getKey()); + if (createResourceFromYaml.isRight()) { + return Either.right(createResourceFromYaml.right().value()); + } } - createdResourcesFromdNodeTypeMap.putAll(createdNodeTypesFromGlobalTypesTemplateEither.left().value()); } - - Either, ResponseFormat> createdNodeTypeFromMainTemplateEither = createResourcesFromYamlNodeTypesList(yamlName, resource, topologyTemplateYaml, user, needLock, nodeTypesArtifactsToHandle, nodeTypesNewCreatedArtifacts); + Map mappedToscaTemplate = (Map) new Yaml().load(topologyTemplateYaml); + Either, ResponseFormat> createdNodeTypeFromMainTemplateEither = createResourcesFromYamlNodeTypesList(yamlName, resource, topologyTemplateYaml, mappedToscaTemplate, needLock, nodeTypesArtifactsToHandle, + nodeTypesNewCreatedArtifacts, nodeTypesInfo, importCsarInfo); if (createdNodeTypeFromMainTemplateEither.isRight()) { ResponseFormat responseFormat = createdNodeTypeFromMainTemplateEither.right().value(); - componentsUtils.auditResource(responseFormat, user, resource, "", "", AuditingActionEnum.IMPORT_RESOURCE, null); + componentsUtils.auditResource(responseFormat, importCsarInfo.getModifier(), resource, "", "", AuditingActionEnum.IMPORT_RESOURCE, null); return Either.right(responseFormat); } @@ -1791,10 +1939,10 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { return result; } - private Either handleCsarArtifacts(Resource resource, User user, String csarUUID, Map csar, List createdArtifacts, ArtifactOperationInfo artifactOperation, boolean shouldLock, - boolean inTransaction) { + private Either handleVfCsarArtifacts(Resource resource, ImportCsarInfo importCsarInfo, List createdArtifacts, ArtifactOperationInfo artifactOperation, boolean shouldLock, + boolean inTransaction) { - if (csar != null) { + if (importCsarInfo.getCsar() != null) { String vendorLicenseModelId = null; String vfLicenseModelId = null; @@ -1811,26 +1959,26 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } // Specific Behavior for license artifacts - createOrUpdateSingleNonMetaArtifact(resource, user, csarUUID, csar, CsarUtils.ARTIFACTS_PATH + Constants.VENDOR_LICENSE_MODEL, Constants.VENDOR_LICENSE_MODEL, ArtifactTypeEnum.VENDOR_LICENSE.getType(), ArtifactGroupTypeEnum.DEPLOYMENT, + createOrUpdateSingleNonMetaArtifact(resource, importCsarInfo, CsarUtils.ARTIFACTS_PATH + Constants.VENDOR_LICENSE_MODEL, Constants.VENDOR_LICENSE_MODEL, ArtifactTypeEnum.VENDOR_LICENSE.getType(), ArtifactGroupTypeEnum.DEPLOYMENT, Constants.VENDOR_LICENSE_LABEL, Constants.VENDOR_LICENSE_DISPLAY_NAME, Constants.VENDOR_LICENSE_DESCRIPTION, vendorLicenseModelId, artifactOperation, null, shouldLock, inTransaction); - createOrUpdateSingleNonMetaArtifact(resource, user, csarUUID, csar, CsarUtils.ARTIFACTS_PATH + Constants.VF_LICENSE_MODEL, Constants.VF_LICENSE_MODEL, ArtifactTypeEnum.VF_LICENSE.getType(), ArtifactGroupTypeEnum.DEPLOYMENT, + createOrUpdateSingleNonMetaArtifact(resource, importCsarInfo, CsarUtils.ARTIFACTS_PATH + Constants.VF_LICENSE_MODEL, Constants.VF_LICENSE_MODEL, ArtifactTypeEnum.VF_LICENSE.getType(), ArtifactGroupTypeEnum.DEPLOYMENT, Constants.VF_LICENSE_LABEL, Constants.VF_LICENSE_DISPLAY_NAME, Constants.VF_LICENSE_DESCRIPTION, vfLicenseModelId, artifactOperation, null, shouldLock, inTransaction); - Either eitherCreateResult = createOrUpdateNonMetaArtifacts(csarUUID, csar, resource, user, createdArtifacts, shouldLock, inTransaction, artifactOperation); + Either eitherCreateResult = createOrUpdateNonMetaArtifacts(importCsarInfo, resource, createdArtifacts, shouldLock, inTransaction, artifactOperation); if (eitherCreateResult.isRight()) { return Either.right(eitherCreateResult.right().value()); } - Either, ResponseFormat> artifacsMetaCsarStatus = CsarValidationUtils.getArtifactsMeta(csar, csarUUID, componentsUtils); + Either, ResponseFormat> artifacsMetaCsarStatus = CsarValidationUtils.getArtifactsMeta(importCsarInfo.getCsar(), importCsarInfo.getCsarUUID(), componentsUtils); if (artifacsMetaCsarStatus.isLeft()) { String artifactsFileName = artifacsMetaCsarStatus.left().value().getKey(); String artifactsContents = artifacsMetaCsarStatus.left().value().getValue(); Either createArtifactsFromCsar = Either.left(resource); if (artifactOperation.getArtifactOperationEnum() == ArtifactOperationEnum.Create) - createArtifactsFromCsar = createResourceArtifactsFromCsar(csarUUID, csar, resource, user, artifactsContents, artifactsFileName, createdArtifacts, shouldLock, inTransaction); + createArtifactsFromCsar = createResourceArtifactsFromCsar(importCsarInfo, resource, artifactsContents, artifactsFileName, createdArtifacts, shouldLock, inTransaction); else - createArtifactsFromCsar = updateResourceArtifactsFromCsar(csarUUID, csar, resource, user, artifactsContents, artifactsFileName, createdArtifacts, shouldLock, inTransaction); + createArtifactsFromCsar = updateResourceArtifactsFromCsar(importCsarInfo, resource, artifactsContents, artifactsFileName, createdArtifacts, shouldLock, inTransaction); if (createArtifactsFromCsar.isRight()) { log.debug("Couldn't create artifacts from artifacts.meta"); return Either.right(createArtifactsFromCsar.right().value()); @@ -1849,7 +1997,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { * Either.right(componentsUtils.getResponseFormat(actionStatus)); } } } */ for (String artifactId : artifactsToDelete) { - Either, ResponseFormat> handleDelete = artifactsBusinessLogic.handleDelete(resource.getUniqueId(), artifactId, user, AuditingActionEnum.ARTIFACT_DELETE, ComponentTypeEnum.RESOURCE, + Either, ResponseFormat> handleDelete = artifactsBusinessLogic.handleDelete(resource.getUniqueId(), artifactId, importCsarInfo.getModifier(), AuditingActionEnum.ARTIFACT_DELETE, ComponentTypeEnum.RESOURCE, resource, null, null, shouldLock, inTransaction); if (handleDelete.isRight()) { log.debug("Couldn't delete artifact {}", artifactId); @@ -1870,18 +2018,18 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { return Either.left(resource); } - private Either createOrUpdateSingleNonMetaArtifact(Resource resource, User user, String csarUUID, Map csar, String artifactPath, String artifactFileName, String artifactType, - ArtifactGroupTypeEnum artifactGroupType, String artifactLabel, String artifactDisplayName, String artifactDescription, String artifactId, ArtifactOperationInfo operation, List createdArtifacts, boolean shouldLock, - boolean inTransaction) { + private Either createOrUpdateSingleNonMetaArtifact(Resource resource, ImportCsarInfo importCsarInfo, String artifactPath, String artifactFileName, String artifactType, + ArtifactGroupTypeEnum artifactGroupType, String artifactLabel, String artifactDisplayName, String artifactDescription, String artifactId, ArtifactOperationInfo operation, List createdArtifacts, boolean shouldLock, + boolean inTransaction) { byte[] artifactFileBytes = null; - if (csar.containsKey(artifactPath)) { - artifactFileBytes = csar.get(artifactPath); + if (importCsarInfo.getCsar().containsKey(artifactPath)) { + artifactFileBytes = importCsarInfo.getCsar().get(artifactPath); } Either result = Either.left(true); if (operation.getArtifactOperationEnum() == ArtifactOperationEnum.Update || operation.getArtifactOperationEnum() == ArtifactOperationEnum.Delete) { if (artifactId != null && !artifactId.isEmpty() && artifactFileBytes == null) { - Either, ResponseFormat> handleDelete = artifactsBusinessLogic.handleDelete(resource.getUniqueId(), artifactId, user, AuditingActionEnum.ARTIFACT_DELETE, ComponentTypeEnum.RESOURCE, resource, null, + Either, ResponseFormat> handleDelete = artifactsBusinessLogic.handleDelete(resource.getUniqueId(), artifactId, importCsarInfo.getModifier(), AuditingActionEnum.ARTIFACT_DELETE, ComponentTypeEnum.RESOURCE, resource, null, null, shouldLock, inTransaction); if (handleDelete.isRight()) { result = Either.right(handleDelete.right().value()); @@ -1896,10 +2044,10 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } if (artifactFileBytes != null) { Map vendorLicenseModelJson = buildJsonForUpdateArtifact(artifactId, artifactFileName, artifactType, artifactGroupType, artifactLabel, artifactDisplayName, artifactDescription, artifactFileBytes, null); - Either, ResponseFormat> eitherNonMetaArtifacts = createOrUpdateCsarArtifactFromJson(resource, user, vendorLicenseModelJson, operation, shouldLock, inTransaction); + Either, ResponseFormat> eitherNonMetaArtifacts = createOrUpdateCsarArtifactFromJson(resource, importCsarInfo.getModifier(), vendorLicenseModelJson, operation, shouldLock, inTransaction); addNonMetaCreatedArtifactsToSupportRollback(operation, createdArtifacts, eitherNonMetaArtifacts); if (eitherNonMetaArtifacts.isRight()) { - BeEcompErrorManager.getInstance().logInternalFlowError("UploadLicenseArtifact", "Failed to upload license artifact: " + artifactFileName + "With csar uuid: " + csarUUID, ErrorSeverity.WARNING); + BeEcompErrorManager.getInstance().logInternalFlowError("UploadLicenseArtifact", "Failed to upload license artifact: " + artifactFileName + "With csar uuid: " + importCsarInfo.getCsarUUID(), ErrorSeverity.WARNING); return Either.right(eitherNonMetaArtifacts.right().value()); } } @@ -1930,13 +2078,13 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { return Either.left(uploadArtifactToService.left().value()); } - public Either updateResourceArtifactsFromCsar(String csarUUID, Map csar, Resource resource, User user, String artifactsMetaFile, String artifactsMetaFileName, List createdNewArtifacts, - boolean shouldLock, boolean inTransaction) { + public Either updateResourceArtifactsFromCsar(ImportCsarInfo importCsarInfo, Resource resource, String artifactsMetaFile, String artifactsMetaFileName, List createdNewArtifacts, + boolean shouldLock, boolean inTransaction) { - Either>, ResponseFormat> parseResourceInfoFromYamlEither = parseResourceArtifactsInfoFromFile(resource, artifactsMetaFile, artifactsMetaFileName, user); + Either>, ResponseFormat> parseResourceInfoFromYamlEither = parseResourceArtifactsInfoFromFile(resource, artifactsMetaFile, artifactsMetaFileName, importCsarInfo.getModifier()); if (parseResourceInfoFromYamlEither.isRight()) { ResponseFormat responseFormat = parseResourceInfoFromYamlEither.right().value(); - componentsUtils.auditResource(responseFormat, user, resource, "", "", AuditingActionEnum.IMPORT_RESOURCE, null); + componentsUtils.auditResource(responseFormat, importCsarInfo.getModifier(), resource, "", "", AuditingActionEnum.IMPORT_RESOURCE, null); return Either.right(responseFormat); } @@ -1960,7 +2108,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } } } - return createResourceArtifacts(csarUUID, csar, resource, user, parseResourceInfoFromYamlEither.left().value(), AuditingActionEnum.CREATE_RESOURCE, createdNewArtifacts, shouldLock, inTransaction); + return createResourceArtifacts(importCsarInfo, resource, parseResourceInfoFromYamlEither.left().value(), AuditingActionEnum.CREATE_RESOURCE, createdNewArtifacts, shouldLock, inTransaction); } // find master in group @@ -1996,7 +2144,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { Map mergedgroup = mergeGroupInUpdateFlow(groupArtifact, parsedGroup, artifactsToDelete, groupToDelete, jsonMasterArtifacts, createdDeplymentArtifactsAfterDelete); // Set deletedArtifactsName = new HashSet(); - Either, ResponseFormat> deletedArtifactsEither = deleteArtifactsInUpdateCsarFlow(resource, user, shouldLock, inTransaction, artifactsToDelete, groupToDelete); + Either, ResponseFormat> deletedArtifactsEither = deleteArtifactsInUpdateCsarFlow(resource, importCsarInfo.getModifier(), shouldLock, inTransaction, artifactsToDelete, groupToDelete); if (deletedArtifactsEither.isRight()) { log.debug("Failed to delete artifacts. Status is {} ", deletedArtifactsEither.right().value()); @@ -2023,8 +2171,8 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { ////////////// dissociate, associate or create ////////////// artifacts//////////////////////////// - Either assDissotiateEither = associateAndDissociateArtifactsToGroup(csarUUID, csar, resource, user, createdNewArtifacts, labelCounter, shouldLock, inTransaction, createdDeplymentArtifactsAfterDelete, - mergedgroup, deletedArtifacts); + Either assDissotiateEither = associateAndDissociateArtifactsToGroup(importCsarInfo, resource, createdNewArtifacts, labelCounter, shouldLock, inTransaction, createdDeplymentArtifactsAfterDelete, + mergedgroup, deletedArtifacts); if (assDissotiateEither.isRight()) { log.debug("Failed to delete artifacts. Status is {} ", assDissotiateEither.right().value()); @@ -2042,7 +2190,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } groups = resource.getGroups(); - List groupToUpdate = new ArrayList<>(); + // update vfModule names Set groupForAssociateWithMembers = mergedgroup.keySet(); if (groups != null && !groups.isEmpty()) { @@ -2056,30 +2204,22 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { ; for (GroupDefinition updatedGroupDef : groupForAssociateWithMembers) { - GroupDefinition group = null; - Optional opGr = groups.stream().filter(p -> p.getUniqueId().equals(updatedGroupDef.getUniqueId())).findAny(); - if (opGr.isPresent()) { - group = opGr.get(); - groupToUpdate.add(group); - } - if (group != null) { - Map members = new HashMap(); - Set artifactsGroup = new HashSet(); - artifactsGroup.addAll(group.getArtifacts()); - associateMembersToArtifacts(createdNewArtifacts, createdDeplymentArtifactsAfterDelete, heatGroups, artifactsGroup, members); - if (!members.isEmpty()) { - group.setMembers(members); - } + if (updatedGroupDef.getMembers() != null && !updatedGroupDef.getMembers().isEmpty()) { + updatedGroupDef.getMembers().clear(); } + Map members = new HashMap(); + Set artifactsGroup = new HashSet(); + artifactsGroup.addAll(updatedGroupDef.getArtifacts()); + associateMembersToArtifacts(createdNewArtifacts, createdDeplymentArtifactsAfterDelete, heatGroups, artifactsGroup, members); + if (!members.isEmpty()) { + updatedGroupDef.setMembers(members); + + } + } - /* - * if (!groupToUpdate.isEmpty()) { Either, ResponseFormat> assotiateGroupEither = groupBusinessLogic.associateMembersToGroup(resource.getUniqueId(), user.getUserId(), ComponentTypeEnum.RESOURCE, groupToUpdate, false, - * true); if (assotiateGroupEither.isRight()) { log.debug("Failed to associate artifacts to groups. Status is {} ", assotiateGroupEither.right().value()); return Either.right(assotiateGroupEither.right().value()); - * - * } } - */ + } @@ -2111,7 +2251,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { if (validateGroupNamesRes.isRight()) { return Either.right(validateGroupNamesRes.right().value()); } - Either resStatus = createGroupDeploymentArtifactsFromCsar(csarUUID, csar, resource, user, newArtifactsGroup, createdNewArtifacts, createdDeplymentArtifactsAfterDelete, labelCounter, shouldLock, inTransaction); + Either resStatus = createGroupDeploymentArtifactsFromCsar(importCsarInfo, resource, newArtifactsGroup, createdNewArtifacts, createdDeplymentArtifactsAfterDelete, labelCounter, shouldLock, inTransaction); if (resStatus.isRight()) return resStatus; } @@ -2142,7 +2282,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } private Either, ResponseFormat> deleteArtifactsInUpdateCsarFlow(Resource resource, User user, boolean shouldLock, boolean inTransaction, Set artifactsToDelete, - Map> groupToDelete) { + Map> groupToDelete) { List deletedArtifacts = new ArrayList(); String resourceId = resource.getUniqueId(); if (!artifactsToDelete.isEmpty()) { @@ -2159,9 +2299,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { * deletedArtifacts.add(removeArifactFromGraph.left().value()); */ - } - - else { + } else { Either, ResponseFormat> handleDelete = artifactsBusinessLogic.handleDelete(resourceId, artifact.getUniqueId(), user, AuditingActionEnum.ARTIFACT_DELETE, ComponentTypeEnum.RESOURCE, resource, null, null, shouldLock, inTransaction); if (handleDelete.isRight()) { @@ -2194,8 +2332,8 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { return Either.left(deletedArtifacts); } - private Either associateAndDissociateArtifactsToGroup(String csarUUID, Map csar, Resource resource, User user, List createdNewArtifacts, int labelCounter, boolean shouldLock, - boolean inTransaction, List createdDeplymentArtifactsAfterDelete, Map mergedgroup, List deletedArtifacts) { + private Either associateAndDissociateArtifactsToGroup(ImportCsarInfo importCsarInfo, Resource resource, List createdNewArtifacts, int labelCounter, boolean shouldLock, + boolean inTransaction, List createdDeplymentArtifactsAfterDelete, Map mergedgroup, List deletedArtifacts) { Map> artifactsToAssotiate = new HashMap>(); Map>> artifactsToUpdateMap = new HashMap>>(); Either resEither = Either.left(resource); @@ -2212,7 +2350,6 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { List newArtifactsInGroup = entry.getValue().getListToAssociateArtifactToGroup(); if (newArtifactsInGroup != null && !newArtifactsInGroup.isEmpty()) artifactsToAssotiate.put(entry.getKey(), newArtifactsInGroup); - List> artifactsToUpdate = entry.getValue().getListToUpdateArtifactInGroup(); if (artifactsToUpdate != null && !artifactsToUpdate.isEmpty()) @@ -2224,11 +2361,11 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { for (Entry>> artifactsToUpdateEntry : artifactsToUpdateMap.entrySet()) { List> artifactsToUpdateList = artifactsToUpdateEntry.getValue(); GroupDefinition groupToUpdate = artifactsToUpdateEntry.getKey(); - + for (ImmutablePair artifact : artifactsToUpdateList) { String prevUUID = artifact.getKey().getArtifactUUID(); String prevId = artifact.getKey().getUniqueId(); - Either updateArtifactEither = updateDeploymentArtifactsFromCsar(csarUUID, csar, resource, user, artifact.getKey(), artifact.getValue(), updatedArtifacts, + Either updateArtifactEither = updateDeploymentArtifactsFromCsar(importCsarInfo, resource, artifact.getKey(), artifact.getValue(), updatedArtifacts, artifact.getRight().getRelatedArtifactsInfo(), shouldLock, inTransaction); if (updateArtifactEither.isRight()) { log.debug("failed to update artifacts. status is {}", updateArtifactEither.right().value()); @@ -2236,7 +2373,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { return resEither; } ArtifactDefinition artAfterUpdate = updateArtifactEither.left().value(); - if ( !prevUUID.equals(artAfterUpdate.getArtifactUUID()) || !prevId.equals(artAfterUpdate.getUniqueId()) ){ + if (!prevUUID.equals(artAfterUpdate.getArtifactUUID()) || !prevId.equals(artAfterUpdate.getUniqueId())) { groupToUpdate.getArtifacts().remove(prevId); groupToUpdate.getArtifactsUuid().remove(prevUUID); groupToUpdate.getArtifacts().add(artAfterUpdate.getUniqueId()); @@ -2251,6 +2388,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { for (Entry> associateEntry : artifactsToAssotiate.entrySet()) { List associatedArtifact = associateEntry.getValue(); Set arifactsUids = new HashSet(); + Set arifactsUuids = new HashSet(); for (ArtifactTemplateInfo artifactTemplate : associatedArtifact) { // try // to // find @@ -2261,6 +2399,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { for (ArtifactDefinition createdArtifact : createdDeplymentArtifactsAfterDelete) { if (artifactTemplate.getFileName().equalsIgnoreCase(createdArtifact.getArtifactName())) { arifactsUids.add(createdArtifact.getUniqueId()); + arifactsUuids.add(createdArtifact.getUniqueId()); isCreate = false; String heatEnvId = checkAndGetHeatEnvId(createdArtifact); if (!heatEnvId.isEmpty()) { @@ -2280,6 +2419,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { for (ArtifactDefinition createdNewArtifact : createdNewArtifacts) { if (artifactTemplate.getFileName().equalsIgnoreCase(createdNewArtifact.getArtifactName())) { arifactsUids.add(createdNewArtifact.getUniqueId()); + arifactsUuids.add(createdNewArtifact.getUniqueId()); isCreate = false; String heatEnvId = checkAndGetHeatEnvId(createdNewArtifact); if (!heatEnvId.isEmpty()) { @@ -2291,17 +2431,18 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } if (isCreate) { - Either createArtifactEither = createDeploymentArtifact(csarUUID, csar, resource, user, ARTIFACTS_PATH, artifactTemplate, createdNewArtifacts, labelCounter, shouldLock, inTransaction); + Either createArtifactEither = createDeploymentArtifact(importCsarInfo, resource, ARTIFACTS_PATH, artifactTemplate, createdNewArtifacts, labelCounter, shouldLock, inTransaction); if (createArtifactEither.isRight()) { resEither = Either.right(createArtifactEither.right().value()); return resEither; } ArtifactDefinition createdArtifact = createArtifactEither.left().value(); arifactsUids.add(createdArtifact.getUniqueId()); + arifactsUuids.add(createdArtifact.getUniqueId()); ArtifactTypeEnum artifactType = ArtifactTypeEnum.findType(createdArtifact.getArtifactType()); if (artifactType == ArtifactTypeEnum.HEAT || artifactType == ArtifactTypeEnum.HEAT_NET || artifactType == ArtifactTypeEnum.HEAT_VOL) { Either createHeatEnvPlaceHolder = artifactsBusinessLogic.createHeatEnvPlaceHolder(createdArtifact, ArtifactsBusinessLogic.HEAT_VF_ENV_NAME, resource.getUniqueId(), NodeTypeEnum.Resource, - resource.getName(), user, resource, null); + resource.getName(), importCsarInfo.getModifier(), resource, null); if (createHeatEnvPlaceHolder.isRight()) { return Either.right(createHeatEnvPlaceHolder.right().value()); } @@ -2314,11 +2455,9 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { if (arifactsUids.size() > 0) { List artifactsToAssociate = new ArrayList(); artifactsToAssociate.addAll(arifactsUids); - GroupDefinition assotiateGroup = new GroupDefinition(); - assotiateGroup.setUniqueId(associateEntry.getKey().getUniqueId()); - assotiateGroup.setArtifacts(artifactsToAssociate); - associateArtifactGroup.add(assotiateGroup); - + GroupDefinition assotiateGroup = associateEntry.getKey(); + assotiateGroup.getArtifacts().addAll(arifactsUids); + assotiateGroup.getArtifactsUuid().addAll(arifactsUuids); } } @@ -2354,7 +2493,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } private Map mergeGroupInUpdateFlow(Map>> groupArtifact, Map> parsedGroup, - Set artifactsToDelete, Map> groupToDelete, Set jsonMasterArtifacts, List createdDeplymentArtifacts) { + Set artifactsToDelete, Map> groupToDelete, Set jsonMasterArtifacts, List createdDeplymentArtifacts) { Map mergedgroup = new HashMap(); for (Entry>> groupListEntry : groupArtifact.entrySet()) { Map> createdArtifactMap = groupListEntry.getValue(); @@ -2365,21 +2504,21 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { for (ArtifactDefinition artToDelete : listToDelete) { findArtifactToDelete(parsedGroup, artifactsToDelete, groupListEntry.getKey().getUniqueId(), artToDelete, createdDeplymentArtifacts); } - if(artifactsToDelete != null && !artifactsToDelete.isEmpty()){ + if (artifactsToDelete != null && !artifactsToDelete.isEmpty()) { GroupDefinition group = groupListEntry.getKey(); - for(ArtifactDefinition artifactDefinition: artifactsToDelete){ + for (ArtifactDefinition artifactDefinition : artifactsToDelete) { if (CollectionUtils.isNotEmpty(group.getArtifacts()) && group.getArtifacts().contains(artifactDefinition.getUniqueId())) { group.getArtifacts().remove(artifactDefinition.getUniqueId()); - + } if (CollectionUtils.isNotEmpty(group.getArtifactsUuid()) && group.getArtifactsUuid().contains(artifactDefinition.getArtifactUUID())) { group.getArtifactsUuid().remove(artifactDefinition.getArtifactUUID()); - + } } - + } - + for (ArtifactTemplateInfo jsonMasterArtifact : jsonMasterArtifacts) { if (maserArtifact.getArtifactName().equalsIgnoreCase(jsonMasterArtifact.getFileName())) { MergedArtifactInfo mergedGroup = new MergedArtifactInfo(); @@ -2400,34 +2539,8 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { return mergedgroup; } - private Set findArtifactsNotInGroupToDelete(List groups, List createdDeplymentArtifactsAfterDelete) { - Set artifactNotInGroupSet = new HashSet(); - for (ArtifactDefinition artifact : createdDeplymentArtifactsAfterDelete) { - boolean needToDelete = true; - if (artifact.getArtifactName().equalsIgnoreCase(Constants.VENDOR_LICENSE_MODEL) || artifact.getArtifactName().equalsIgnoreCase(Constants.VF_LICENSE_MODEL)) - continue; - if (groups != null) { - for (GroupDefinition group : groups) { - List groupArtifactIds = group.getArtifacts(); - if (groupArtifactIds == null || groupArtifactIds.isEmpty()) { - continue; - } - for (String groupArtifactid : groupArtifactIds) { - if (groupArtifactid.equalsIgnoreCase(artifact.getUniqueId())) - needToDelete = false; - - } - - } - } - if (needToDelete) - artifactNotInGroupSet.add(artifact.getUniqueId()); - } - return artifactNotInGroupSet; - } - private void findArtifactToDelete(Map> parsedGroup, Set artifactsToDelete, String deleteGroupId, ArtifactDefinition artifact, - List createdDeplymentArtifacts) { + List createdDeplymentArtifacts) { boolean isNeedToDeleteArtifact = true; String artifactType = artifact.getArtifactType(); ArtifactDefinition generatedFromArt = null; @@ -2492,20 +2605,20 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } } - public Either createResourceArtifactsFromCsar(String csarUUID, Map csar, Resource resource, User user, String artifactsMetaFile, String artifactsMetaFileName, List createdArtifacts, - boolean shouldLock, boolean inTransaction) { + public Either createResourceArtifactsFromCsar(ImportCsarInfo importCsarInfo, Resource resource, String artifactsMetaFile, String artifactsMetaFileName, List createdArtifacts, + boolean shouldLock, boolean inTransaction) { log.debug("parseResourceArtifactsInfoFromFile start"); - Either>, ResponseFormat> parseResourceInfoFromYamlEither = parseResourceArtifactsInfoFromFile(resource, artifactsMetaFile, artifactsMetaFileName, user); + Either>, ResponseFormat> parseResourceInfoFromYamlEither = parseResourceArtifactsInfoFromFile(resource, artifactsMetaFile, artifactsMetaFileName, importCsarInfo.getModifier()); if (parseResourceInfoFromYamlEither.isRight()) { ResponseFormat responseFormat = parseResourceInfoFromYamlEither.right().value(); - componentsUtils.auditResource(responseFormat, user, resource, "", "", AuditingActionEnum.IMPORT_RESOURCE, null); + componentsUtils.auditResource(responseFormat, importCsarInfo.getModifier(), resource, "", "", AuditingActionEnum.IMPORT_RESOURCE, null); return Either.right(responseFormat); } log.debug("parseResourceArtifactsInfoFromFile end"); log.debug("createResourceArtifacts start"); - Either respStatus = createResourceArtifacts(csarUUID, csar, resource, user, parseResourceInfoFromYamlEither.left().value(), AuditingActionEnum.CREATE_RESOURCE, createdArtifacts, shouldLock, inTransaction); + Either respStatus = createResourceArtifacts(importCsarInfo, resource, parseResourceInfoFromYamlEither.left().value(), AuditingActionEnum.CREATE_RESOURCE, createdArtifacts, shouldLock, inTransaction); if (respStatus.isRight()) { return respStatus; } @@ -2523,8 +2636,8 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } - private Either createGroupDeploymentArtifactsFromCsar(String csarUUID, Map csar, Resource resource, User user, List artifactsTemplateList, - List createdNewArtifacts, List artifactsFromResource, int labelCounter, boolean shouldLock, boolean inTransaction) { + private Either createGroupDeploymentArtifactsFromCsar(ImportCsarInfo importCsarInfo, Resource resource, List artifactsTemplateList, + List createdNewArtifacts, List artifactsFromResource, int labelCounter, boolean shouldLock, boolean inTransaction) { Either resStatus = Either.left(resource); List createdGroups = resource.getGroups(); List heatGroups = null; @@ -2538,7 +2651,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { Set artifactsGroup = new HashSet(); Set artifactsUUIDGroup = new HashSet(); - resStatus = createDeploymentArtifactsFromCsar(csarUUID, csar, resource, user, artifactsGroup, artifactsUUIDGroup, groupTemplateInfo, createdNewArtifacts, artifactsFromResource, labelCounter, shouldLock, inTransaction); + resStatus = createDeploymentArtifactsFromCsar(importCsarInfo, resource, artifactsGroup, artifactsUUIDGroup, groupTemplateInfo, createdNewArtifacts, artifactsFromResource, labelCounter, shouldLock, inTransaction); if (resStatus.isRight()) return resStatus; @@ -2562,7 +2675,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { prop.setName(Constants.IS_BASE); prop.setValue(Boolean.toString(groupTemplateInfo.isBase())); properties.add(prop); - + List createdArtifacts = new ArrayList<>(); createdArtifacts.addAll(createdNewArtifacts); createdArtifacts.addAll(artifactsFromResource); @@ -2590,15 +2703,15 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } resource = component.left().value(); - Either, ResponseFormat> addGroups = groupBusinessLogic.addGroups(resource, user, ComponentTypeEnum.RESOURCE, needToAdd); + Either, ResponseFormat> addGroups = groupBusinessLogic.addGroups(resource, importCsarInfo.getModifier(), ComponentTypeEnum.RESOURCE, needToAdd); if (addGroups.isRight()) return Either.right(addGroups.right().value()); return resStatus; } - private Either createDeploymentArtifactsFromCsar(String csarUUID, Map csar, Resource resource, User user, Set artifactsGroup, Set artifactsUUIDGroup, - ArtifactTemplateInfo artifactTemplateInfo, List createdArtifacts, List artifactsFromResource, int labelCounter, boolean shoudLock, boolean inTransaction) { + private Either createDeploymentArtifactsFromCsar(ImportCsarInfo importCsarInfo, Resource resource, Set artifactsGroup, Set artifactsUUIDGroup, + ArtifactTemplateInfo artifactTemplateInfo, List createdArtifacts, List artifactsFromResource, int labelCounter, boolean shoudLock, boolean inTransaction) { Either resStatus = Either.left(resource); String artifactFileName = artifactTemplateInfo.getFileName(); String artifactUid = ""; @@ -2646,7 +2759,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { // if not exist need to create if (!alreadyExist) { - Either newArtifactEither = createDeploymentArtifact(csarUUID, csar, resource, user, ARTIFACTS_PATH, artifactTemplateInfo, createdArtifacts, labelCounter, shoudLock, inTransaction); + Either newArtifactEither = createDeploymentArtifact(importCsarInfo, resource, ARTIFACTS_PATH, artifactTemplateInfo, createdArtifacts, labelCounter, shoudLock, inTransaction); if (newArtifactEither.isRight()) { resStatus = Either.right(newArtifactEither.right().value()); return resStatus; @@ -2657,7 +2770,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { ArtifactTypeEnum artifactType = ArtifactTypeEnum.findType(newArtifact.getArtifactType()); if (artifactType == ArtifactTypeEnum.HEAT || artifactType == ArtifactTypeEnum.HEAT_NET || artifactType == ArtifactTypeEnum.HEAT_VOL) { Either createHeatEnvPlaceHolder = artifactsBusinessLogic.createHeatEnvPlaceHolder(newArtifact, ArtifactsBusinessLogic.HEAT_VF_ENV_NAME, resource.getUniqueId(), NodeTypeEnum.Resource, - resource.getName(), user, resource, null); + resource.getName(), importCsarInfo.getModifier(), resource, null); if (createHeatEnvPlaceHolder.isRight()) { return Either.right(createHeatEnvPlaceHolder.right().value()); } @@ -2674,7 +2787,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { List relatedArtifacts = artifactTemplateInfo.getRelatedArtifactsInfo(); if (relatedArtifacts != null) { for (ArtifactTemplateInfo relatedArtifactTemplateInfo : relatedArtifacts) { - resStatus = createDeploymentArtifactsFromCsar(csarUUID, csar, resource, user, artifactsGroup, artifactsUUIDGroup, relatedArtifactTemplateInfo, createdArtifacts, artifactsFromResource, labelCounter, shoudLock, inTransaction); + resStatus = createDeploymentArtifactsFromCsar(importCsarInfo, resource, artifactsGroup, artifactsUUIDGroup, relatedArtifactTemplateInfo, createdArtifacts, artifactsFromResource, labelCounter, shoudLock, inTransaction); if (resStatus.isRight()) return resStatus; } @@ -2682,8 +2795,8 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { return resStatus; } - private Either createResourceArtifacts(String csarUUID, Map csar, Resource resource, User user, Map> artifactsMap, AuditingActionEnum createResource, - List createdArtifacts, boolean shouldLock, boolean inTransaction) { + private Either createResourceArtifacts(ImportCsarInfo importCsarInfo, Resource resource, Map> artifactsMap, AuditingActionEnum createResource, + List createdArtifacts, boolean shouldLock, boolean inTransaction) { Either resStatus = Either.left(resource); @@ -2691,7 +2804,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { for (List groupTemplateList : arifactsCollection) { if (groupTemplateList != null) { - resStatus = createGroupDeploymentArtifactsFromCsar(csarUUID, csar, resource, user, groupTemplateList, createdArtifacts, 0, shouldLock, inTransaction); + resStatus = createGroupDeploymentArtifactsFromCsar(importCsarInfo, resource, groupTemplateList, createdArtifacts, 0, shouldLock, inTransaction); if (resStatus.isRight()) return resStatus; } @@ -2701,8 +2814,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } - private Either createOrUpdateNonMetaArtifacts(String csarUUID, Map csar, Resource resource, User user, List createdArtifacts, boolean shouldLock, boolean inTransaction, - ArtifactOperationInfo artifactOperation) { + private Either createOrUpdateNonMetaArtifacts(ImportCsarInfo importCsarInfo, Resource resource, List createdArtifacts, boolean shouldLock, boolean inTransaction, ArtifactOperationInfo artifactOperation) { Either resStatus = null; Map>> collectedWarningMessages = new HashMap<>(); @@ -2710,7 +2822,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { try { List artifactPathAndNameList = // Stream of file paths contained in csar - csar.entrySet().stream() + importCsarInfo.getCsar().entrySet().stream() // Filter in only VF artifact path location .filter(e -> Pattern.compile(VF_NODE_TYPE_ARTIFACTS_PATH_PATTERN).matcher(e.getKey()).matches()) // Validate and add warnings @@ -2722,13 +2834,19 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { // collect to List .collect(Collectors.toList()); + Either responseFormatEither = validateArtifactNames(artifactPathAndNameList); + if (responseFormatEither.isRight()) { + return Either.right(getComponentsUtils().getResponseFormatByArtifactId(ActionStatus.ARTIFACT_NAME_INVALID, responseFormatEither.right().value())); + } + + EnumMap> vfCsarArtifactsToHandle = null; if (artifactOperation.getArtifactOperationEnum() == ArtifactOperationEnum.Create) { vfCsarArtifactsToHandle = new EnumMap<>(ArtifactOperationEnum.class); vfCsarArtifactsToHandle.put(artifactOperation.getArtifactOperationEnum(), artifactPathAndNameList); } else { - Either>, ResponseFormat> findVfCsarArtifactsToHandleRes = findVfCsarArtifactsToHandle(resource, artifactPathAndNameList, user); + Either>, ResponseFormat> findVfCsarArtifactsToHandleRes = findVfCsarArtifactsToHandle(resource, artifactPathAndNameList, importCsarInfo.getModifier()); if (findVfCsarArtifactsToHandleRes.isRight()) { resStatus = Either.right(findVfCsarArtifactsToHandleRes.right().value()); @@ -2744,15 +2862,15 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { // Stream of artifacts to be created currArtifactOperationPair.getValue().stream() // create each artifact - .map(e -> createOrUpdateSingleNonMetaArtifact(resource, user, csarUUID, csar, e.getPath(), e.getArtifactName(), e.getArtifactType().getType(), e.getArtifactGroupType(), e.getArtifactLabel(), e.getDisplayName(), + .map(e -> createOrUpdateSingleNonMetaArtifact(resource, importCsarInfo, e.getPath(), e.getArtifactName(), e.getArtifactType().getType(), e.getArtifactGroupType(), e.getArtifactLabel(), e.getDisplayName(), CsarUtils.ARTIFACT_CREATED_FROM_CSAR, e.getArtifactUniqueId(), artifactsBusinessLogic.new ArtifactOperationInfo(false, false, currArtifactOperationPair.getKey()), createdArtifacts, shouldLock, inTransaction)) // filter in only error .filter(e -> e.isRight()). // Convert the error from either to ResponseFormat - map(e -> e.right().value()). + map(e -> e.right().value()). // Check if an error occurred - findAny(); + findAny(); // Error found on artifact Creation if (optionalCreateInDBError.isPresent()) { resStatus = Either.right(optionalCreateInDBError.get()); @@ -2772,6 +2890,17 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { return resStatus; } + private Either validateArtifactNames(List artifactPathAndNameList) { + Pattern englishNumbersAndUnderScoresOnly = Pattern.compile(CsarUtils.VALID_ENGLISH_ARTIFACT_NAME); + for (NonMetaArtifactInfo nonMetaArtifactInfo : artifactPathAndNameList) { + if (!englishNumbersAndUnderScoresOnly.matcher(nonMetaArtifactInfo.getDisplayName()).matches()) { + return Either.right(nonMetaArtifactInfo.getArtifactName()); + } + } + return Either.left(true); + } + + private Either>, ResponseFormat> findVfCsarArtifactsToHandle(Resource resource, List artifactPathAndNameList, User user) { List existingArtifacts = new ArrayList<>(); @@ -2816,8 +2945,8 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { return result; } - private Either createGroupDeploymentArtifactsFromCsar(String csarUUID, Map csar, Resource resource, User user, List artifactsTemplateList, List createdArtifacts, - int labelCounter, boolean shouldLock, boolean inTransaction) { + private Either createGroupDeploymentArtifactsFromCsar(ImportCsarInfo importCsarInfo, Resource resource, List artifactsTemplateList, List createdArtifacts, + int labelCounter, boolean shouldLock, boolean inTransaction) { Either resStatus = Either.left(resource); List createdGroups = resource.getGroups(); List heatGroups = null; @@ -2840,7 +2969,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { Set artifactsUUIDGroup = new HashSet(); log.debug("createDeploymentArtifactsFromCsar start"); - resStatus = createDeploymentArtifactFromCsar(csarUUID, ARTIFACTS_PATH, csar, resource, user, artifactsGroup, artifactsUUIDGroup, groupTemplateInfo, createdArtifacts, labelCounter, shouldLock, inTransaction); + resStatus = createDeploymentArtifactFromCsar(importCsarInfo, ARTIFACTS_PATH, resource, artifactsGroup, artifactsUUIDGroup, groupTemplateInfo, createdArtifacts, labelCounter, shouldLock, inTransaction); log.debug("createDeploymentArtifactsFromCsar end"); if (resStatus.isRight()) return resStatus; @@ -2895,7 +3024,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR)); } - Either, ResponseFormat> createGroups = groupBusinessLogic.addGroups(component.left().value(), user, ComponentTypeEnum.RESOURCE, needToCreate); + Either, ResponseFormat> createGroups = groupBusinessLogic.addGroups(component.left().value(), importCsarInfo.getModifier(), ComponentTypeEnum.RESOURCE, needToCreate); if (createGroups.isRight()) { return Either.right(createGroups.right().value()); } @@ -3004,8 +3133,8 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } } - private Either createDeploymentArtifactFromCsar(String csarUUID, String artifactPath, Map csar, Resource resource, User user, Set artifactsGroup, Set artifactsUUIDGroup, - ArtifactTemplateInfo artifactTemplateInfo, List createdArtifacts, int labelCounter, boolean shoudLock, boolean inTransaction) { + private Either createDeploymentArtifactFromCsar(ImportCsarInfo importCsarInfo, String artifactPath, Resource resource, Set artifactsGroup, Set artifactsUUIDGroup, + ArtifactTemplateInfo artifactTemplateInfo, List createdArtifacts, int labelCounter, boolean shoudLock, boolean inTransaction) { Either resStatus = Either.left(resource); String artifactFileName = artifactTemplateInfo.getFileName(); String artifactUid = ""; @@ -3031,7 +3160,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { // if not exist need to create if (!alreadyExist) { - Either newArtifactEither = createDeploymentArtifact(csarUUID, csar, resource, user, artifactPath, artifactTemplateInfo, createdArtifacts, labelCounter, shoudLock, inTransaction); + Either newArtifactEither = createDeploymentArtifact(importCsarInfo, resource, artifactPath, artifactTemplateInfo, createdArtifacts, labelCounter, shoudLock, inTransaction); if (newArtifactEither.isRight()) { resStatus = Either.right(newArtifactEither.right().value()); return resStatus; @@ -3043,7 +3172,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { ArtifactTypeEnum artifactType = ArtifactTypeEnum.findType(newArtifact.getArtifactType()); if (artifactType == ArtifactTypeEnum.HEAT || artifactType == ArtifactTypeEnum.HEAT_NET || artifactType == ArtifactTypeEnum.HEAT_VOL) { Either createHeatEnvPlaceHolder = artifactsBusinessLogic.createHeatEnvPlaceHolder(newArtifact, ArtifactsBusinessLogic.HEAT_VF_ENV_NAME, resource.getUniqueId(), NodeTypeEnum.Resource, - resource.getName(), user, resource, null); + resource.getName(), importCsarInfo.getModifier(), resource, null); if (createHeatEnvPlaceHolder.isRight()) { return Either.right(createHeatEnvPlaceHolder.right().value()); } @@ -3060,7 +3189,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { List relatedArtifacts = artifactTemplateInfo.getRelatedArtifactsInfo(); if (relatedArtifacts != null) { for (ArtifactTemplateInfo relatedArtifactTemplateInfo : relatedArtifacts) { - resStatus = createDeploymentArtifactFromCsar(csarUUID, artifactPath, csar, resource, user, artifactsGroup, artifactsUUIDGroup, relatedArtifactTemplateInfo, createdArtifacts, labelCounter, shoudLock, inTransaction); + resStatus = createDeploymentArtifactFromCsar(importCsarInfo, artifactPath, resource, artifactsGroup, artifactsUUIDGroup, relatedArtifactTemplateInfo, createdArtifacts, labelCounter, shoudLock, inTransaction); if (resStatus.isRight()) return resStatus; } @@ -3077,10 +3206,10 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { return artifactEnvUid; } - private Either createDeploymentArtifact(String csarUUID, Map csar, Resource resource, User user, String artifactPath, ArtifactTemplateInfo artifactTemplateInfo, - List createdArtifacts, int labelCounter, boolean shoudLock, boolean inTransaction) { + private Either createDeploymentArtifact(ImportCsarInfo importCsarInfo, Resource resource, String artifactPath, ArtifactTemplateInfo artifactTemplateInfo, + List createdArtifacts, int labelCounter, boolean shoudLock, boolean inTransaction) { final String artifactFileName = artifactTemplateInfo.getFileName(); - Either, ResponseFormat> artifactContententStatus = CsarValidationUtils.getArtifactsContent(csarUUID, csar, artifactPath + artifactFileName, artifactFileName, componentsUtils); + Either, ResponseFormat> artifactContententStatus = CsarValidationUtils.getArtifactsContent(importCsarInfo.getCsarUUID(), importCsarInfo.getCsar(), artifactPath + artifactFileName, artifactFileName, componentsUtils); if (artifactContententStatus.isRight()) { return Either.right(artifactContententStatus.right().value()); } @@ -3088,7 +3217,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { Map json = buildJsonForArtifact(artifactTemplateInfo, artifactContententStatus.left().value().getValue(), labelCounter); - Either, ResponseFormat> uploadArtifactToService = createOrUpdateCsarArtifactFromJson(resource, user, json, artifactsBusinessLogic.new ArtifactOperationInfo(false, false, ArtifactOperationEnum.Create), + Either, ResponseFormat> uploadArtifactToService = createOrUpdateCsarArtifactFromJson(resource, importCsarInfo.getModifier(), json, artifactsBusinessLogic.new ArtifactOperationInfo(false, false, ArtifactOperationEnum.Create), shoudLock, inTransaction); if (uploadArtifactToService.isRight()) @@ -3097,7 +3226,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { ArtifactDefinition currentInfo = uploadArtifactToService.left().value().left().value(); if (currentInfo.getHeatParameters() != null) { - Either updateEnvEither = updateHeatParamsFromCsar(resource, csarUUID, csar, artifactTemplateInfo, currentInfo, false); + Either updateEnvEither = updateHeatParamsFromCsar(resource, importCsarInfo, artifactTemplateInfo, currentInfo, false); if (updateEnvEither.isRight()) { log.debug("failed to update parameters to artifact {}", artifactFileName); return Either.right(updateEnvEither.right().value()); @@ -3113,30 +3242,8 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } - private Either createInformationalArtifact(String csarUUID, Map csar, Resource resource, User user, ArtifactTemplateInfo artifactTemplateInfo, int labelCounter, boolean shoudLock, - boolean inTransaction) { - final String artifactFileName = artifactTemplateInfo.getFileName(); - String artifactPath = CsarUtils.ARTIFACTS_PATH + CsarUtils.INFORMATIONAL_ARTIFACTS + artifactFileName; - Either, ResponseFormat> artifactContententStatus = CsarValidationUtils.getArtifactsContent(csarUUID, csar, artifactPath, artifactFileName, componentsUtils); - if (artifactContententStatus.isRight()) - return Either.right(artifactContententStatus.right().value()); - - Map json = buildJsonForArtifact(artifactTemplateInfo, artifactContententStatus.left().value().getValue(), labelCounter); - - Either, ResponseFormat> uploadArtifactToService = createOrUpdateCsarArtifactFromJson(resource, user, json, artifactsBusinessLogic.new ArtifactOperationInfo(false, false, ArtifactOperationEnum.Create), - shoudLock, inTransaction); - - if (uploadArtifactToService.isRight()) - return Either.right(uploadArtifactToService.right().value()); - - ArtifactDefinition currentInfo = uploadArtifactToService.left().value().left().value(); - - return Either.left(currentInfo); - - } - - private Either updateDeploymentArtifactsFromCsar(String csarUUID, Map csar, Resource resource, User user, ArtifactDefinition oldArtifact, ArtifactTemplateInfo artifactTemplateInfo, - List updatedArtifacts, List updatedRequiredArtifacts, boolean shouldLock, boolean inTransaction) { + private Either updateDeploymentArtifactsFromCsar(ImportCsarInfo importCsarInfo, Resource resource, ArtifactDefinition oldArtifact, ArtifactTemplateInfo artifactTemplateInfo, + List updatedArtifacts, List updatedRequiredArtifacts, boolean shouldLock, boolean inTransaction) { Either resStatus = null; String artifactFileName = artifactTemplateInfo.getFileName(); @@ -3158,7 +3265,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } - Either, ResponseFormat> artifactContententStatus = CsarValidationUtils.getArtifactsContent(csarUUID, csar, CsarUtils.ARTIFACTS_PATH + artifactFileName, artifactFileName, componentsUtils); + Either, ResponseFormat> artifactContententStatus = CsarValidationUtils.getArtifactsContent(importCsarInfo.getCsarUUID(), importCsarInfo.getCsar(), CsarUtils.ARTIFACTS_PATH + artifactFileName, artifactFileName, componentsUtils); if (artifactContententStatus.isRight()) { resStatus = Either.right(artifactContententStatus.right().value()); return resStatus; @@ -3167,7 +3274,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { Map json = buildJsonForUpdateArtifact(oldArtifact.getUniqueId(), artifactFileName, oldArtifact.getArtifactType(), ArtifactGroupTypeEnum.DEPLOYMENT, oldArtifact.getArtifactLabel(), oldArtifact.getArtifactDisplayName(), oldArtifact.getDescription(), artifactContententStatus.left().value().getRight(), updatedRequiredArtifacts); - Either, ResponseFormat> uploadArtifactToService = createOrUpdateCsarArtifactFromJson(resource, user, json, artifactsBusinessLogic.new ArtifactOperationInfo(false, false, ArtifactOperationEnum.Update), + Either, ResponseFormat> uploadArtifactToService = createOrUpdateCsarArtifactFromJson(resource, importCsarInfo.getModifier(), json, artifactsBusinessLogic.new ArtifactOperationInfo(false, false, ArtifactOperationEnum.Update), shouldLock, inTransaction); if (uploadArtifactToService.isRight()) { @@ -3176,7 +3283,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } ArtifactDefinition currentInfo = uploadArtifactToService.left().value().left().value(); - Either updateEnvEither = updateHeatParamsFromCsar(resource, csarUUID, csar, artifactTemplateInfo, currentInfo, true); + Either updateEnvEither = updateHeatParamsFromCsar(resource, importCsarInfo, artifactTemplateInfo, currentInfo, true); if (updateEnvEither.isRight()) { log.debug("failed to update parameters to artifact {}", artifactFileName); resStatus = Either.right(updateEnvEither.right().value()); @@ -3192,11 +3299,11 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } - private Either updateHeatParamsFromCsar(Resource resource, String csarUUID, Map csar, ArtifactTemplateInfo artifactTemplateInfo, ArtifactDefinition currentInfo, boolean isUpdateEnv) { + private Either updateHeatParamsFromCsar(Resource resource, ImportCsarInfo importCsarInfo, ArtifactTemplateInfo artifactTemplateInfo, ArtifactDefinition currentInfo, boolean isUpdateEnv) { Either resStatus = Either.left(currentInfo); if (artifactTemplateInfo.getEnv() != null && !artifactTemplateInfo.getEnv().isEmpty()) { - Either, ResponseFormat> artifactparamsStatus = CsarValidationUtils.getArtifactsContent(csarUUID, csar, CsarUtils.ARTIFACTS_PATH + artifactTemplateInfo.getEnv(), artifactTemplateInfo.getEnv(), + Either, ResponseFormat> artifactparamsStatus = CsarValidationUtils.getArtifactsContent(importCsarInfo.getCsarUUID(), importCsarInfo.getCsar(), CsarUtils.ARTIFACTS_PATH + artifactTemplateInfo.getEnv(), artifactTemplateInfo.getEnv(), componentsUtils); if (artifactparamsStatus.isRight()) { resStatus = Either.right(artifactparamsStatus.right().value()); @@ -3308,7 +3415,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } private Map buildJsonForUpdateArtifact(String artifactId, String artifactName, String artifactType, ArtifactGroupTypeEnum artifactGroupType, String label, String displayName, String description, byte[] artifactContentent, - List updatedRequiredArtifacts) { + List updatedRequiredArtifacts) { Map json = new HashMap(); if (artifactId != null && !artifactId.isEmpty()) @@ -3446,6 +3553,8 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { Map originCompMap = new HashMap<>(); List relations = new ArrayList<>(); + Map> instInputs = new HashMap<>(); + for (Entry entry : uploadResInstancesMap.entrySet()) { UploadComponentInstanceInfo uploadComponentInstanceInfo = entry.getValue(); ComponentInstance currentCompInstance = null; @@ -3477,20 +3586,54 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } else { originResource = originCompMap.get(currentCompInstance.getComponentUid()); } - if (originResource.getCapabilities() != null && !originResource.getCapabilities().isEmpty()) - instCapabilties.put(currentCompInstance, originResource.getCapabilities()); - if (originResource.getRequirements() != null && !originResource.getRequirements().isEmpty()) - instRequirements.put(currentCompInstance, originResource.getRequirements()); + if (originResource.getCapabilities() != null && !originResource.getCapabilities().isEmpty()) { + Map> originCapabilities ; + if (MapUtils.isNotEmpty(uploadComponentInstanceInfo.getCapabilitiesNamesToUpdate()) && resource.getResourceType() == ResourceTypeEnum.CVFC) { + originCapabilities = new HashMap<>(); + originResource.getCapabilities().entrySet().stream().forEach(e ->{ + List list = e.getValue().stream().map(l -> new CapabilityDefinition(l)).collect(Collectors.toList()); + originCapabilities.put(e.getKey(), list); + }); + for (List capabilities : originCapabilities.values()) { + capabilities.stream().filter(c -> uploadComponentInstanceInfo.getCapabilitiesNamesToUpdate().containsKey(c.getName())).forEach(c -> c.setName(uploadComponentInstanceInfo.getCapabilitiesNamesToUpdate().get(c.getName()))); + } + }else{ + originCapabilities = originResource.getCapabilities(); + } + instCapabilties.put(currentCompInstance, originCapabilities); + } + if (originResource.getRequirements() != null && !originResource.getRequirements().isEmpty()) { + Map> originRequirements; + if (MapUtils.isNotEmpty(uploadComponentInstanceInfo.getRequirementsNamesToUpdate()) && resource.getResourceType() == ResourceTypeEnum.CVFC) { + originRequirements = new HashMap<>(); + originResource.getRequirements().entrySet().stream().forEach(e ->{ + List list = e.getValue().stream().map(l -> new RequirementDefinition(l)).collect(Collectors.toList()); + originRequirements.put(e.getKey(), list); + }); + for (List requirements : originRequirements.values()) { + requirements.stream().filter(r -> uploadComponentInstanceInfo.getRequirementsNamesToUpdate().containsKey(r.getName())).forEach(r -> r.setName(uploadComponentInstanceInfo.getRequirementsNamesToUpdate().get(r.getName()))); + } + }else{ + originRequirements = originResource.getRequirements(); + } + instRequirements.put(currentCompInstance, originRequirements); + } if (originResource.getDeploymentArtifacts() != null && !originResource.getDeploymentArtifacts().isEmpty()) instArtifacts.put(resourceInstanceId, originResource.getDeploymentArtifacts()); if (originResource.getAttributes() != null && !originResource.getAttributes().isEmpty()) instAttributes.put(resourceInstanceId, originResource.getAttributes()); - - ResponseFormat addPropertiesValueToRiRes = addPropertyValuesToRi(uploadComponentInstanceInfo, resource, originResource, currentCompInstance, yamlName, instProperties, allDataTypes.left().value()); - if (addPropertiesValueToRiRes.getStatus() != 200) { - return Either.right(addPropertiesValueToRiRes); + if (originResource.getResourceType() != ResourceTypeEnum.CVFC) { + ResponseFormat addPropertiesValueToRiRes = addPropertyValuesToRi(uploadComponentInstanceInfo, resource, originResource, currentCompInstance, yamlName, instProperties, allDataTypes.left().value()); + if (addPropertiesValueToRiRes.getStatus() != 200) { + return Either.right(addPropertiesValueToRiRes); + } + } else { + // TO DO + ResponseFormat addInputValueToRiRes = addInputsValuesToRi(uploadComponentInstanceInfo, resource, originResource, currentCompInstance, yamlName, instInputs, allDataTypes.left().value()); + if (addInputValueToRiRes.getStatus() != 200) { + return Either.right(addInputValueToRiRes); + } } - } Either>, StorageOperationStatus> addPropToInst = toscaOperationFacade.associateComponentInstancePropertiesToComponent(instProperties, resource.getUniqueId()); @@ -3499,7 +3642,14 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { ResponseFormat responseFormat = componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(addPropToInst.right().value()), yamlName); return Either.right(responseFormat); } - + if (instInputs != null && !instInputs.isEmpty()) { + Either>, StorageOperationStatus> addInputToInst = toscaOperationFacade.associateComponentInstanceInputsToComponent(instInputs, resource.getUniqueId()); + if (addInputToInst.isRight()) { + log.debug("failed to associate inputs value of resource {} status is {}", resource.getUniqueId(), addInputToInst.right().value()); + ResponseFormat responseFormat = componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(addInputToInst.right().value()), yamlName); + return Either.right(responseFormat); + } + } StorageOperationStatus addArtToInst = toscaOperationFacade.associateArtifactToInstances(instArtifacts, resource.getUniqueId(), user); if (addArtToInst != StorageOperationStatus.OK && addArtToInst != StorageOperationStatus.NOT_FOUND) { log.debug("failed to associate artifact of resource {} status is {}", resource.getUniqueId(), addArtToInst); @@ -3590,108 +3740,206 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { UploadComponentInstanceInfo uploadComponentInstanceInfo = nodesInfoValue; - ComponentInstance currentCompInstance = null; + ComponentInstance currentCompInstance = null; + + for (ComponentInstance compInstance : componentInstancesList) { + + if (compInstance.getName().equals(uploadComponentInstanceInfo.getName())) { + currentCompInstance = compInstance; + break; + } + + } + + if (currentCompInstance == null) { + log.debug("component instance with name {} in resource {} ", uploadComponentInstanceInfo.getName(), resource.getUniqueId()); + BeEcompErrorManager.getInstance().logInternalDataError("component instance with name " + uploadComponentInstanceInfo.getName() + " in resource {} ", resource.getUniqueId(), ErrorSeverity.ERROR); + ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.NOT_TOPOLOGY_TOSCA_TEMPLATE, yamlName); + return responseFormat; + } + String resourceInstanceId = currentCompInstance.getUniqueId(); + + Map> regMap = uploadComponentInstanceInfo.getRequirements(); + + if (regMap != null) { + Iterator>> nodesRegValue = regMap.entrySet().iterator(); + + long startAddRelation = System.currentTimeMillis(); + + while (nodesRegValue.hasNext()) { + Entry> nodesRegInfoEntry = nodesRegValue.next(); + + List uploadRegInfoList = nodesRegInfoEntry.getValue(); + for (UploadReqInfo uploadRegInfo : uploadRegInfoList) { + log.debug("Going to create relation {}", uploadRegInfo.getName()); + String regName = uploadRegInfo.getName(); + RequirementCapabilityRelDef regCapRelDef = new RequirementCapabilityRelDef(); + regCapRelDef.setFromNode(resourceInstanceId); + log.debug("try to find available requirement {} ", regName); + Either eitherReqStatus = findAviableRequiremen(regName, yamlName, uploadComponentInstanceInfo, currentCompInstance, uploadRegInfo.getCapabilityName()); + if (eitherReqStatus.isRight()) { + log.debug("failed to find available requirement {} status is {}", regName, eitherReqStatus.right().value()); + return eitherReqStatus.right().value(); + } + + RequirementDefinition validReq = eitherReqStatus.left().value(); + List reqAndRelationshipPairList = regCapRelDef.getRelationships(); + if (reqAndRelationshipPairList == null) + reqAndRelationshipPairList = new ArrayList(); + RequirementAndRelationshipPair reqAndRelationshipPair = new RequirementAndRelationshipPair(); + reqAndRelationshipPair.setRequirement(regName); + reqAndRelationshipPair.setRequirementOwnerId(validReq.getOwnerId()); + reqAndRelationshipPair.setRequirementUid(validReq.getUniqueId()); + RelationshipImpl relationship = new RelationshipImpl(); + relationship.setType(validReq.getCapability()); + reqAndRelationshipPair.setRelationships(relationship); + + ComponentInstance currentCapCompInstance = null; + for (ComponentInstance compInstance : componentInstancesList) { + if (compInstance.getName().equals(uploadRegInfo.getNode())) { + currentCapCompInstance = compInstance; + break; + } + } + + if (currentCapCompInstance == null) { + log.debug("The component instance with name {} not found on resource {} ", uploadRegInfo.getNode(), resource.getUniqueId()); + BeEcompErrorManager.getInstance().logInternalDataError("component instance with name " + uploadRegInfo.getNode() + " in resource {} ", resource.getUniqueId(), ErrorSeverity.ERROR); + ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.NOT_TOPOLOGY_TOSCA_TEMPLATE, yamlName); + return responseFormat; + } + regCapRelDef.setToNode(currentCapCompInstance.getUniqueId()); + log.debug("try to find aviable Capability req name is {} ", validReq.getName()); + CapabilityDefinition aviableCapForRel = findAvailableCapabilityByTypeOrName(validReq, currentCapCompInstance, uploadRegInfo); + if (aviableCapForRel == null) { + log.debug("aviable capability was not found. req name is {} component instance is {}", validReq.getName(), currentCapCompInstance.getUniqueId()); + BeEcompErrorManager.getInstance().logInternalDataError("aviable capability was not found. req name is " + validReq.getName() + " component instance is " + currentCapCompInstance.getUniqueId(), resource.getUniqueId(), + ErrorSeverity.ERROR); + ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.NOT_TOPOLOGY_TOSCA_TEMPLATE, yamlName); + return responseFormat; + } + reqAndRelationshipPair.setCapability(aviableCapForRel.getName()); + reqAndRelationshipPair.setCapabilityUid(aviableCapForRel.getUniqueId()); + reqAndRelationshipPair.setCapabilityOwnerId(aviableCapForRel.getOwnerId()); + reqAndRelationshipPairList.add(reqAndRelationshipPair); + regCapRelDef.setRelationships(reqAndRelationshipPairList); + relations.add(regCapRelDef); + } + } + totalCreateRel += (System.currentTimeMillis() - startAddRelation); + } else if (resource.getResourceType() != ResourceTypeEnum.CVFC) { + ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.OK, yamlName); + return responseFormat; + } + return componentsUtils.getResponseFormat(ActionStatus.OK); + } + + private ResponseFormat addInputsValuesToRi(UploadComponentInstanceInfo uploadComponentInstanceInfo, Resource resource, Resource originResource, ComponentInstance currentCompInstance, String yamlName, + Map> instInputs, Map allDataTypes) { + Map> propMap = uploadComponentInstanceInfo.getProperties(); + if (propMap != null && propMap.size() > 0) { + Map currPropertiesMap = new HashMap(); + + int index = 0; + List listFromMap = originResource.getInputs(); + if (listFromMap == null || listFromMap.isEmpty()) { + log.debug("failed to find properties "); + ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.PROPERTY_NOT_FOUND); + return responseFormat; + } + for (InputDefinition prop : listFromMap) { + String propName = prop.getName(); + if (!currPropertiesMap.containsKey(propName)) { + currPropertiesMap.put(propName, prop); + } + } + List instPropList = new ArrayList<>(); + for (List propertyList : propMap.values()) { + + UploadPropInfo propertyInfo = propertyList.get(0); + String propName = propertyInfo.getName(); + if (!currPropertiesMap.containsKey(propName)) { + log.debug("failed to find property {} ", propName); + ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.PROPERTY_NOT_FOUND, propName); + return responseFormat; + } + InputDefinition curPropertyDef = currPropertiesMap.get(propName); + ComponentInstanceInput property = null; + + String value = null; + List getInputs = null; + boolean isValidate = true; + if (propertyInfo.getValue() != null) { + getInputs = propertyInfo.getGet_input(); + isValidate = getInputs == null || getInputs.isEmpty(); + if (isValidate) { + value = ImportUtils.getPropertyJsonStringValue(propertyInfo.getValue(), curPropertyDef.getType()); + } else + value = ImportUtils.getPropertyJsonStringValue(propertyInfo.getValue(), ToscaTagNamesEnum.GET_INPUT.getElementName()); + } + String innerType = null; + property = new ComponentInstanceInput(curPropertyDef, value, null); - for (ComponentInstance compInstance : componentInstancesList) { + Either validatevalueEiter = validatePropValueBeforeCreate(property, value, isValidate, innerType, allDataTypes); + if (validatevalueEiter.isRight()) { + return componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(validatevalueEiter.right().value())); + } - if (compInstance.getName().equals(uploadComponentInstanceInfo.getName())) { - currentCompInstance = compInstance; - break; - } + // String uniqueId = UniqueIdBuilder.buildResourceInstancePropertyValueUid(currentCompInstance.getComponentUid(), index++); + // property.setUniqueId(uniqueId); + property.setValue(validatevalueEiter.left().value()); - } + if (getInputs != null && !getInputs.isEmpty()) { + List getInputValues = new ArrayList<>(); + for (GetInputValueDataDefinition getInput : getInputs) { + List inputs = resource.getInputs(); + if (inputs == null || inputs.isEmpty()) { + log.debug("Failed to add property {} to resource instance {}. Inputs list is empty ", property, currentCompInstance.getUniqueId()); + return componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT); + } - if (currentCompInstance == null) { - log.debug("component instance with name {} in resource {} ", uploadComponentInstanceInfo.getName(), resource.getUniqueId()); - BeEcompErrorManager.getInstance().logInternalDataError("component instance with name " + uploadComponentInstanceInfo.getName() + " in resource {} ", resource.getUniqueId(), ErrorSeverity.ERROR); - ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.NOT_TOPOLOGY_TOSCA_TEMPLATE, yamlName); - return responseFormat; - } - String resourceInstanceId = currentCompInstance.getUniqueId(); + Optional optional = inputs.stream().filter(p -> p.getName().equals(getInput.getInputName())).findAny(); + if (!optional.isPresent()) { + log.debug("Failed to find input {} ", getInput.getInputName()); + // @@TODO error message + return componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT); + } + InputDefinition input = optional.get(); + getInput.setInputId(input.getUniqueId()); + getInputValues.add(getInput); - log.debug("************* addPropertyValuesToRi start"); - long startAddProperty = System.currentTimeMillis(); - log.debug("************* addPropertyValuesToRi end"); - totalCreatePropVal += (System.currentTimeMillis() - startAddProperty); - Map> regMap = uploadComponentInstanceInfo.getRequirements(); - if (regMap == null) { - ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.OK, yamlName); - return responseFormat; - } - Iterator>> nodesRegValue = regMap.entrySet().iterator(); - - long startAddRelation = System.currentTimeMillis(); - - while (nodesRegValue.hasNext()) { - Entry> nodesRegInfoEntry = nodesRegValue.next(); - - List uploadRegInfoList = nodesRegInfoEntry.getValue(); - for (UploadReqInfo uploadRegInfo : uploadRegInfoList) { - log.debug("Going to create relation {}", uploadRegInfo.getName()); - String regName = uploadRegInfo.getName(); - String nodeCapName = uploadRegInfo.getNode(); - RequirementCapabilityRelDef regCapRelDef = new RequirementCapabilityRelDef(); - regCapRelDef.setFromNode(resourceInstanceId); - log.debug("try to find available requirement {} ", regName); - Either eitherReqStatus = findAviableRequiremen(regName, yamlName, uploadComponentInstanceInfo, currentCompInstance, uploadRegInfo.getCapabilityName()); - if (eitherReqStatus.isRight()) { - log.debug("failed to find available requirement {} status is {}", regName, eitherReqStatus.right().value()); - return eitherReqStatus.right().value(); - } - - RequirementDefinition validReq = eitherReqStatus.left().value(); - List reqAndRelationshipPairList = regCapRelDef.getRelationships(); - if (reqAndRelationshipPairList == null) - reqAndRelationshipPairList = new ArrayList(); - RequirementAndRelationshipPair reqAndRelationshipPair = new RequirementAndRelationshipPair(); - reqAndRelationshipPair.setRequirement(regName); - reqAndRelationshipPair.setRequirementOwnerId(validReq.getOwnerId()); - reqAndRelationshipPair.setRequirementUid(validReq.getUniqueId()); - RelationshipImpl relationship = new RelationshipImpl(); - relationship.setType(validReq.getCapability()); - reqAndRelationshipPair.setRelationships(relationship); - - ComponentInstance currentCapCompInstance = null; - for (ComponentInstance compInstance : componentInstancesList) { - if (compInstance.getName().equals(uploadRegInfo.getNode())) { - currentCapCompInstance = compInstance; - break; + GetInputValueDataDefinition getInputIndex = getInput.getGetInputIndex(); + if (getInputIndex != null) { + optional = inputs.stream().filter(p -> p.getName().equals(getInputIndex.getInputName())).findAny(); + if (!optional.isPresent()) { + log.debug("Failed to find input {} ", getInputIndex.getInputName()); + // @@TODO error message + return componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT); + } + InputDefinition inputIndex = optional.get(); + getInputIndex.setInputId(inputIndex.getUniqueId()); + getInputValues.add(getInputIndex); + } } + property.setGetInputValues(getInputValues); } - - if (currentCapCompInstance == null) { - log.debug("component instance with name {} in resource {} ", uploadRegInfo.getNode(), resource.getUniqueId()); - BeEcompErrorManager.getInstance().logInternalDataError("component instance with name " + uploadRegInfo.getNode() + " in resource {} ", resource.getUniqueId(), ErrorSeverity.ERROR); - ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.NOT_TOPOLOGY_TOSCA_TEMPLATE, yamlName); - return responseFormat; - } - regCapRelDef.setToNode(currentCapCompInstance.getUniqueId()); - log.debug("try to find aviable Capability req name is {} ", validReq.getName()); - CapabilityDefinition aviableCapForRel = findAvailableCapabilityByTypeOrName(validReq, currentCapCompInstance, uploadRegInfo); - if (aviableCapForRel == null) { - log.debug("aviable capability was not found. req name is {} component instance is {}", validReq.getName(), currentCapCompInstance.getUniqueId()); - BeEcompErrorManager.getInstance().logInternalDataError("aviable capability was not found. req name is " + validReq.getName() + " component instance is " + currentCapCompInstance.getUniqueId(), resource.getUniqueId(), - ErrorSeverity.ERROR); - ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.NOT_TOPOLOGY_TOSCA_TEMPLATE, yamlName); - return responseFormat; + instPropList.add(property); + // delete overriden property + currPropertiesMap.remove(property.getName()); + } + // add rest of properties + if (!currPropertiesMap.isEmpty()) { + for (InputDefinition value : currPropertiesMap.values()) { + instPropList.add(new ComponentInstanceInput(value)); } - reqAndRelationshipPair.setCapability(aviableCapForRel.getName()); - reqAndRelationshipPair.setCapabilityUid(aviableCapForRel.getUniqueId()); - reqAndRelationshipPair.setCapabilityOwnerId(aviableCapForRel.getOwnerId()); - reqAndRelationshipPairList.add(reqAndRelationshipPair); - regCapRelDef.setRelationships(reqAndRelationshipPairList); - relations.add(regCapRelDef); - } - + instInputs.put(currentCompInstance.getUniqueId(), instPropList); } - totalCreateRel += (System.currentTimeMillis() - startAddRelation); - return componentsUtils.getResponseFormat(ActionStatus.OK); } private ResponseFormat addPropertyValuesToRi(UploadComponentInstanceInfo uploadComponentInstanceInfo, Resource resource, Resource originResource, ComponentInstance currentCompInstance, String yamlName, - Map> instProperties, Map allDataTypes) { + Map> instProperties, Map allDataTypes) { Map> propMap = uploadComponentInstanceInfo.getProperties(); if (propMap != null && propMap.size() > 0) { @@ -3845,14 +4093,6 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { return cap; } - private RequirementAndRelationshipPair getReqRelPair(CapabilityDefinition cap) { - RequirementAndRelationshipPair relationPair = new RequirementAndRelationshipPair(); - relationPair.setCapabilityUid(cap.getUniqueId()); - relationPair.setCapability(cap.getName()); - relationPair.setCapabilityOwnerId(cap.getOwnerId()); - return relationPair; - } - private CapabilityDefinition findAviableCapability(RequirementDefinition validReq, ComponentInstance currentCapCompInstance) { CapabilityDefinition aviableCapForRel = null; Map> capMap = currentCapCompInstance.getCapabilities(); @@ -3955,9 +4195,15 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } @SuppressWarnings("unchecked") - public Either parseResourceInfoFromYaml(String yamlFileName, Resource resource, String resourceYml, User user) { + public Either parseResourceInfoFromYaml(String yamlFileName, Resource resource, String resourceYml, User user, Map createdNodesToscaResourceNames, Map nodeTypesInfo, String nodeTypeName) { - Map mappedToscaTemplate = (Map) new Yaml().load(resourceYml); + Map mappedToscaTemplate; + if(nodeTypesInfo != null && nodeTypeName != null && nodeTypesInfo.containsKey(nodeTypeName)){ + mappedToscaTemplate = nodeTypesInfo.get(nodeTypeName).getMappedToscaTemplate(); + } + else { + mappedToscaTemplate = (Map) new Yaml().load(resourceYml); + } Either toscaElementEither = ImportUtils.findToscaElement(mappedToscaTemplate, ToscaTagNamesEnum.TOPOLOGY_TEMPLATE, ToscaElementTypeEnum.ALL); if (toscaElementEither.isRight()) { ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.NOT_TOPOLOGY_TOSCA_TEMPLATE); @@ -3970,7 +4216,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { return Either.right(responseFormat); } - Either, ResponseFormat> uploadResInstancesEither = createResourcesInstanceInfoFromYaml(yamlFileName, mappedToscaTemplate, resource); + Either, ResponseFormat> uploadResInstancesEither = createResourcesInstanceInfoFromYaml(yamlFileName, mappedToscaTemplate, resource, createdNodesToscaResourceNames); if (uploadResInstancesEither.isRight()) { ResponseFormat responseFormat = uploadResInstancesEither.right().value(); return Either.right(responseFormat); @@ -3991,7 +4237,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } private Either createResourceInstances(User user, String yamlName, Resource resource, Map uploadResInstancesMap, boolean inTransaction, boolean needLock, - Map nodeTypeNamespaceMap) { + Map nodeTypeNamespaceMap) { Either eitherResource = null; log.debug("createResourceInstances is {} - going to create resource instanse from CSAR", yamlName); @@ -4114,32 +4360,36 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.ILLEGAL_COMPONENT_STATE, refResource.getComponentType().getValue(), refResource.getName(), componentState); return Either.right(responseFormat); } - ResourceTypeEnum resourceTypeEnum = refResource.getResourceType(); - if (resourceTypeEnum == ResourceTypeEnum.VF) { - log.debug("validateResourceInstanceBeforeCreate - ref resource type is ", resourceTypeEnum); + + if (!ToscaUtils.isAtomicType(refResource) && refResource.getResourceType() != ResourceTypeEnum.CVFC) { + log.debug("validateResourceInstanceBeforeCreate - ref resource type is ", refResource.getResourceType()); ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_NODE_TEMPLATE, yamlName, uploadComponentInstanceInfo.getName(), uploadComponentInstanceInfo.getType()); return Either.right(responseFormat); } return Either.left(refResource); } - private Either, ResponseFormat> createResourcesInstanceInfoFromYaml(String yamlFileName, Map toscaJson, Resource resource) { + private Either, ResponseFormat> createResourcesInstanceInfoFromYaml(String yamlFileName, Map toscaJson, Resource resource, Map createdNodesToscaResourceNames) { Map moduleComponentInstances = new HashMap(); + Map substitutionMappings = null; Either, ResponseFormat> result = Either.left(moduleComponentInstances); Either, ResultStatusEnum> eitherNodesTemlates = ImportUtils.findFirstToscaMapElement(toscaJson, ToscaTagNamesEnum.NODE_TEMPLATES); + Either, ResultStatusEnum> eitherSubstitutionMappings = ImportUtils.findFirstToscaMapElement(toscaJson, ToscaTagNamesEnum.SUBSTITUTION_MAPPINGS); + if (eitherSubstitutionMappings.isLeft()) { + substitutionMappings = eitherSubstitutionMappings.left().value(); + } if (eitherNodesTemlates.isLeft()) { Map jsonNodeTemplates = eitherNodesTemlates.left().value(); Iterator> nodesNameValue = jsonNodeTemplates.entrySet().iterator(); while (nodesNameValue.hasNext()) { Entry nodeNameValue = nodesNameValue.next(); - Either eitherNode = createModuleComponentInstanceInfo(nodeNameValue.getValue()); + Either eitherNode = createModuleComponentInstanceInfo(nodeNameValue, substitutionMappings, createdNodesToscaResourceNames); if (eitherNode.isRight()) { log.info("error when creating node template:{}, for resource:{}", nodeNameValue.getKey(), resource.getName()); return Either.right(eitherNode.right().value()); } else { UploadComponentInstanceInfo uploadComponentInstanceInfo = eitherNode.left().value(); - uploadComponentInstanceInfo.setName(nodeNameValue.getKey()); moduleComponentInstances.put(nodeNameValue.getKey(), uploadComponentInstanceInfo); } @@ -4154,20 +4404,25 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { return result; } - private Either createModuleComponentInstanceInfo(Object nodeTemplateJson) { + @SuppressWarnings("unchecked") + private Either createModuleComponentInstanceInfo(Entry nodeTemplateJsonEntry, Map substitutionMappings, Map createdNodesToscaResourceNames) { UploadComponentInstanceInfo nodeTemplateInfo = new UploadComponentInstanceInfo(); Either result = Either.left(nodeTemplateInfo); - + nodeTemplateInfo.setName(nodeTemplateJsonEntry.getKey()); try { - if (nodeTemplateJson instanceof String) { - String nodeTemplateJsonString = (String) nodeTemplateJson; + if (nodeTemplateJsonEntry.getValue() instanceof String) { + String nodeTemplateJsonString = (String) nodeTemplateJsonEntry.getValue(); nodeTemplateInfo.setType(nodeTemplateJsonString); - } else if (nodeTemplateJson instanceof Map) { - Map nodeTemplateJsonMap = (Map) nodeTemplateJson; + } else if (nodeTemplateJsonEntry.getValue() instanceof Map) { + Map nodeTemplateJsonMap = (Map) nodeTemplateJsonEntry.getValue(); // Type if (nodeTemplateJsonMap.containsKey(ToscaTagNamesEnum.TYPE.getElementName())) { - nodeTemplateInfo.setType((String) nodeTemplateJsonMap.get(ToscaTagNamesEnum.TYPE.getElementName())); + String toscaResourceType = (String) nodeTemplateJsonMap.get(ToscaTagNamesEnum.TYPE.getElementName()); + if (createdNodesToscaResourceNames.containsKey(toscaResourceType)) { + toscaResourceType = createdNodesToscaResourceNames.get(toscaResourceType); + } + nodeTemplateInfo.setType(toscaResourceType); } if (nodeTemplateJsonMap.containsKey(ToscaTagNamesEnum.REQUIREMENTS.getElementName())) { @@ -4195,13 +4450,30 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { nodeTemplateInfo.setProperties(regResponse.left().value()); } } + if (substitutionMappings != null) { + if (substitutionMappings.containsKey(ToscaTagNamesEnum.CAPABILITIES.getElementName())) { + Either, ResponseFormat> getCapNamesToUpdateRes = getNamesToUpdate(nodeTemplateInfo, (Map>) substitutionMappings.get(ToscaTagNamesEnum.CAPABILITIES.getElementName())); + if (getCapNamesToUpdateRes.isRight()) + return Either.right(getCapNamesToUpdateRes.right().value()); + if (getCapNamesToUpdateRes.left().value().size() > 0) { + nodeTemplateInfo.setCapabilitiesNamesToUpdate(getCapNamesToUpdateRes.left().value()); + } + } + if (substitutionMappings.containsKey(ToscaTagNamesEnum.REQUIREMENTS.getElementName())) { + Either, ResponseFormat> getReqNamesToUpdateRes = getNamesToUpdate(nodeTemplateInfo, (Map>) substitutionMappings.get(ToscaTagNamesEnum.REQUIREMENTS.getElementName())); + if (getReqNamesToUpdateRes.isRight()) + return Either.right(getReqNamesToUpdateRes.right().value()); + if (getReqNamesToUpdateRes.left().value().size() > 0) { + nodeTemplateInfo.setRequirementsNamesToUpdate(getReqNamesToUpdateRes.left().value()); + } + } + } } else { result = Either.right(componentsUtils.getResponseFormat(ActionStatus.NOT_TOPOLOGY_TOSCA_TEMPLATE)); } } catch (Exception e) { - BeEcompErrorManager.getInstance().processEcompError(EcompErrorName.BeSystemError, "Import Resource - create capability"); BeEcompErrorManager.getInstance().logBeSystemError("Import Resource - create capability"); log.debug("error when creating capability, message:{}", e.getMessage(), e); result = Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_YAML)); @@ -4210,6 +4482,18 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { return result; } + private Either, ResponseFormat> getNamesToUpdate(UploadComponentInstanceInfo nodeTemplateInfo, Map> elements) { + Either, ResponseFormat> response; + try { + Map namesToUpdate = elements.entrySet().stream().filter(e -> e.getValue().get(0).equalsIgnoreCase(nodeTemplateInfo.getName())).collect(Collectors.toMap(e -> e.getValue().get(1), e -> e.getKey())); + response = Either.left(namesToUpdate); + } catch (Exception e) { + log.debug("The exception {} occured upon adding names to update for instance {} . ", e.getMessage(), nodeTemplateInfo.getName()); + response = Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR)); + } + return response; + } + private Either>, ResponseFormat> createPropModuleFromYaml(Map nodeTemplateJsonMap) { Map> moduleProp = new HashMap>(); Either>, ResponseFormat> response = Either.left(moduleProp); @@ -4222,21 +4506,21 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { Object propValue = jsonPropObj.getValue(); if (valueContainsPattern(STR_REPLACE_PATTERN, propValue)) { - log.debug("Ignore property value {}.", propName); + log.trace("Ignore property value {}.", propName); continue; } if (valueContainsPattern(TOKEN_PATTERN, propValue)) { - log.debug("Ignore property value {}.", propName); + log.trace("Ignore property value {}.", propName); continue; } if (valueContainsPattern(GET_PROPERTY_PATTERN, propValue)) { - log.debug("Ignore property value {}.", propName); + log.trace("Ignore property value {}.", propName); continue; } if (valueContainsPattern(CONCAT_PATTERN, propValue)) { - log.debug("Ignore property value {}.", propName); + log.trace("Ignore property value {}.", propName); continue; } @@ -4399,7 +4683,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { log.debug("valueContainsToken value is {}", propValue); boolean result = false; if (propValue != null) { - log.debug("valueContainspattern value is {}", propValue.getClass()); + log.trace("valueContainspattern value is {}", propValue.getClass()); Matcher matcher = pattern.matcher(propValue.toString()); result = matcher.find(); } @@ -4536,29 +4820,28 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { return result; } - public Either propagateStateToCertified(User user, Resource resource, LifecycleChangeInfoWithAction lifecycleChangeInfo, boolean inTransaction, boolean needLock) { + public Either propagateStateToCertified(User user, Resource resource, LifecycleChangeInfoWithAction lifecycleChangeInfo, boolean inTransaction, boolean needLock, boolean forceCertificationAllowed) { + Either result = null; - - // resource updated with checkout. certify the resource - if (resource.getLifecycleState().equals(LifecycleStateEnum.CERTIFIED)) { - Either, ResponseFormat> eitherPopulated = populateToscaArtifacts(resource, user, false, inTransaction, needLock); - result = eitherPopulated.isLeft() ? Either.left(resource) : Either.right(eitherPopulated.right().value()); - return result; - } try { - result = lifecycleBusinessLogic.changeState(resource.getUniqueId(), user, LifeCycleTransitionEnum.CERTIFICATION_REQUEST, lifecycleChangeInfo, inTransaction, needLock); - if (result.isLeft()) { + if(resource.getLifecycleState() != LifecycleStateEnum.CERTIFIED && forceCertificationAllowed){ + result = nodeForceCertification(resource, user, lifecycleChangeInfo, inTransaction, needLock); + if(result.isRight()){ + return result; + } resource = result.left().value(); - result = lifecycleBusinessLogic.changeState(resource.getUniqueId(), user, LifeCycleTransitionEnum.START_CERTIFICATION, lifecycleChangeInfo, inTransaction, needLock); } - if (result.isLeft()) { - resource = result.left().value(); - result = lifecycleBusinessLogic.changeState(resource.getUniqueId(), user, LifeCycleTransitionEnum.CERTIFY, lifecycleChangeInfo, inTransaction, needLock); + if (resource.getLifecycleState() == LifecycleStateEnum.CERTIFIED) { + Either, ResponseFormat> eitherPopulated = populateToscaArtifacts(resource, user, false, inTransaction, needLock); + result = eitherPopulated.isLeft() ? Either.left(resource) : Either.right(eitherPopulated.right().value()); + return result; } - return result; + return nodeFullCertification(resource.getUniqueId(), user, lifecycleChangeInfo, inTransaction, needLock); + } catch (Exception e) { + log.debug("The exception {} has occured upon certification of resource {}. ", e.getMessage(), resource.getName()); + return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR)); } finally { if (result == null || result.isRight()) { - BeEcompErrorManager.getInstance().processEcompError(EcompErrorName.BeSystemError, "Change LifecycleState - Certify"); BeEcompErrorManager.getInstance().logBeSystemError("Change LifecycleState - Certify"); if (inTransaction == false) { log.debug("operation failed. do rollback"); @@ -4571,6 +4854,21 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } } + private Either nodeFullCertification(String uniqueId, User user, LifecycleChangeInfoWithAction lifecycleChangeInfo, boolean inTransaction, boolean needLock) { + Either result = lifecycleBusinessLogic.changeState(uniqueId, user, LifeCycleTransitionEnum.CERTIFICATION_REQUEST, lifecycleChangeInfo, inTransaction, needLock); + if (result.isLeft()) { + result = lifecycleBusinessLogic.changeState(uniqueId, user, LifeCycleTransitionEnum.START_CERTIFICATION, lifecycleChangeInfo, inTransaction, needLock); + } + if (result.isLeft()) { + result = lifecycleBusinessLogic.changeState(uniqueId, user, LifeCycleTransitionEnum.CERTIFY, lifecycleChangeInfo, inTransaction, needLock); + } + return result; + } + + private Either nodeForceCertification(Resource resource, User user, LifecycleChangeInfoWithAction lifecycleChangeInfo, boolean inTransaction, boolean needLock) { + return lifecycleBusinessLogic.forceResourceCertification(resource, user, lifecycleChangeInfo, inTransaction, needLock); + } + /* * /** * @@ -4596,7 +4894,6 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { else { StorageOperationStatus status = latestByName.right().value(); - BeEcompErrorManager.getInstance().processEcompError(EcompErrorName.BeResourceMissingError, "Create / Update resource by import", resource.getName()); BeEcompErrorManager.getInstance().logBeComponentMissingError("Create / Update resource by import", ComponentTypeEnum.RESOURCE.getValue(), resource.getName()); log.debug("resource already exist {}. status={}", resource.getName(), status); ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.RESOURCE_ALREADY_EXISTS); @@ -4614,7 +4911,6 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { // error else { StorageOperationStatus status = latestByName.right().value(); - BeEcompErrorManager.getInstance().processEcompError(EcompErrorName.BeResourceMissingError, "Create / Update resource by import", resource.getName()); log.debug("failed to get latest version of resource {}. status={}", resource.getName(), status); ResponseFormat responseFormat = componentsUtils.getResponseFormatByResource(componentsUtils.convertFromStorageResponse(latestByName.right().value()), resource); componentsUtils.auditResource(responseFormat, user, resource, "", "", AuditingActionEnum.IMPORT_RESOURCE, null); @@ -4726,7 +5022,6 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { return result; } finally { if (result == null || result.isRight()) { - BeEcompErrorManager.getInstance().processEcompError(EcompErrorName.BeSystemError, "Change LifecycleState - Certify"); BeEcompErrorManager.getInstance().logBeSystemError("Change LifecycleState - Certify"); log.debug("operation failed. do rollback"); titanDao.rollback(); @@ -4764,6 +5059,10 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { newResource.setVendorRelease(oldResource.getVendorRelease()); } + if (newResource.getResourceVendorModelNumber() == null) { + newResource.setResourceVendorModelNumber(oldResource.getResourceVendorModelNumber()); + } + if (newResource.getContactId() == null) { newResource.setContactId(oldResource.getContactId()); } @@ -4808,12 +5107,13 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { resource.setCreatorUserId(user.getUserId()); resource.setCreatorFullName(user.getFirstName() + " " + user.getLastName()); resource.setContactId(resource.getContactId().toLowerCase()); - if (resource.getResourceType().equals(ResourceTypeEnum.VF)) { - resource.setToscaResourceName(CommonBeUtils.generateToscaResourceName(ResourceTypeEnum.VF.name(), resource.getSystemName())); + if (!ToscaUtils.isAtomicType(resource) && resource.getResourceType() != ResourceTypeEnum.CVFC) { + resource.setToscaResourceName(CommonBeUtils.generateToscaResourceName(resource.getResourceType().name(), resource.getSystemName())); } // Generate invariant UUID - must be here and not in operation since it // should stay constant during clone + // TODO String invariantUUID = UniqueIdBuilder.buildInvariantUUID(); resource.setInvariantUUID(invariantUUID); @@ -4842,10 +5142,8 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { Either eitherCapTypeFound = interfaceTypeOperation.getInterface(intType); if (eitherCapTypeFound.isRight()) { if (eitherCapTypeFound.right().value() == StorageOperationStatus.NOT_FOUND) { - BeEcompErrorManager.getInstance().processEcompError(EcompErrorName.BeInterfaceMissingError, "Create Resource - validateLifecycleTypesCreate", intType); BeEcompErrorManager.getInstance().logBeGraphObjectMissingError("Create Resource - validateLifecycleTypesCreate", "Interface", intType); log.debug("Lifecycle Type: {} is required by resource: {} but does not exist in the DB", intType, resource.getName()); - BeEcompErrorManager.getInstance().processEcompError(EcompErrorName.BeDaoSystemError, "Create Resource - validateLifecycleTypesCreate"); BeEcompErrorManager.getInstance().logBeDaoSystemError("Create Resource - validateLifecycleTypesCreate"); log.debug("request to data model failed with error: {}", eitherCapTypeFound.right().value().name()); } @@ -4878,7 +5176,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { if (resource.getRequirements() != null && resource.getRequirements().size() > 0) { log.debug("validate capability Types Exist - requirements section"); for (String type : resource.getRequirements().keySet()) { - eitherResult = validateCapabilityTypeExists(user, capabilityTypeOperation, resource, resource.getRequirements().get(type) , actionEnum, eitherResult, type, inTransaction); + eitherResult = validateCapabilityTypeExists(user, capabilityTypeOperation, resource, resource.getRequirements().get(type), actionEnum, eitherResult, type, inTransaction); if (eitherResult.isRight()) { return Either.right(eitherResult.right().value()); } @@ -4888,24 +5186,22 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { return eitherResult; } - //@param typeObject- the object to which the validation is done - private Either validateCapabilityTypeExists(User user, ICapabilityTypeOperation capabilityTypeOperation, Resource resource, List validationObjects , AuditingActionEnum actionEnum, Either eitherResult, String type, - boolean inTransaction) { + // @param typeObject- the object to which the validation is done + private Either validateCapabilityTypeExists(User user, ICapabilityTypeOperation capabilityTypeOperation, Resource resource, List validationObjects, AuditingActionEnum actionEnum, Either eitherResult, String type, + boolean inTransaction) { Either eitherCapTypeFound = capabilityTypeOperation.getCapabilityType(type, inTransaction); if (eitherCapTypeFound.isRight()) { if (eitherCapTypeFound.right().value() == StorageOperationStatus.NOT_FOUND) { - BeEcompErrorManager.getInstance().processEcompError(EcompErrorName.BeCapabilityTypeMissingError, "Create Resource - validateCapabilityTypesCreate", type); BeEcompErrorManager.getInstance().logBeGraphObjectMissingError("Create Resource - validateCapabilityTypesCreate", "Capability Type", type); log.debug("Capability Type: {} is required by resource: {} but does not exist in the DB", type, resource.getName()); BeEcompErrorManager.getInstance().logBeDaoSystemError("Create Resource - validateCapabilityTypesCreate"); } - BeEcompErrorManager.getInstance().processEcompError(EcompErrorName.BeDaoSystemError, "Create Resource - validateCapabilityTypesCreate"); log.debug("Trying to get capability type {} failed with error: {}", type, eitherCapTypeFound.right().value().name()); - ResponseFormat errorResponse =null; - if (type!=null) + ResponseFormat errorResponse = null; + if (type != null) errorResponse = componentsUtils.getResponseFormat(ActionStatus.MISSING_CAPABILITY_TYPE, type); else - errorResponse = componentsUtils.getResponseFormatByElement(ActionStatus.MISSING_CAPABILITY_TYPE, validationObjects ); + errorResponse = componentsUtils.getResponseFormatByElement(ActionStatus.MISSING_CAPABILITY_TYPE, validationObjects); eitherResult = Either.right(errorResponse); componentsUtils.auditResource(errorResponse, user, resource, "", "", actionEnum, null); } @@ -4913,16 +5209,14 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } private Either validateCapabilityTypeExists(User user, ICapabilityTypeOperation capabilityTypeOperation, Resource resource, AuditingActionEnum actionEnum, Either eitherResult, - Entry> typeEntry, boolean inTransaction) { + Entry> typeEntry, boolean inTransaction) { Either eitherCapTypeFound = capabilityTypeOperation.getCapabilityType(typeEntry.getKey(), inTransaction); if (eitherCapTypeFound.isRight()) { if (eitherCapTypeFound.right().value() == StorageOperationStatus.NOT_FOUND) { - BeEcompErrorManager.getInstance().processEcompError(EcompErrorName.BeCapabilityTypeMissingError, "Create Resource - validateCapabilityTypesCreate", typeEntry.getKey()); BeEcompErrorManager.getInstance().logBeGraphObjectMissingError("Create Resource - validateCapabilityTypesCreate", "Capability Type", typeEntry.getKey()); log.debug("Capability Type: {} is required by resource: {} but does not exist in the DB", typeEntry.getKey(), resource.getName()); BeEcompErrorManager.getInstance().logBeDaoSystemError("Create Resource - validateCapabilityTypesCreate"); } - BeEcompErrorManager.getInstance().processEcompError(EcompErrorName.BeDaoSystemError, "Create Resource - validateCapabilityTypesCreate"); log.debug("Trying to get capability type {} failed with error: {}", typeEntry.getKey(), eitherCapTypeFound.right().value().name()); ResponseFormat errorResponse = componentsUtils.getResponseFormat(ActionStatus.MISSING_CAPABILITY_TYPE, typeEntry.getKey()); eitherResult = Either.right(errorResponse); @@ -4985,8 +5279,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { Either respStatus = createResourceTransaction(resource, user, isNormative, inTransaction); if (respStatus.isLeft()) { - ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.CREATED); - componentsUtils.auditResource(responseFormat, user, resource, "", "", actionEnum, additionalParams); + auditCreateResource(user, respStatus.left().value(), actionEnum, additionalParams); ASDCKpiApi.countCreatedResourcesKPI(); } else componentsUtils.auditResource(respStatus.right().value(), user, resource, "", "", actionEnum, additionalParams); @@ -4999,6 +5292,11 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } } + private void auditCreateResource(User user, Resource persistedResource, AuditingActionEnum actionEnum, EnumMap additionalParams) { + ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.CREATED); + componentsUtils.auditResource(responseFormat, user, persistedResource, "", "", actionEnum, additionalParams); + } + private Either createResourceTransaction(Resource resource, User user, boolean isNormative, boolean inTransaction) { // validate resource name uniqueness log.debug("validate resource name"); @@ -5026,7 +5324,8 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { resource.setLifecycleState(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT); resource.setVersion(INITIAL_VERSION); resource.setHighestVersion(true); - resource.setAbstract(false); + if (resource.getResourceType() != null && resource.getResourceType() != ResourceTypeEnum.CVFC) + resource.setAbstract(false); } Either createToscaElement = toscaOperationFacade.createToscaComponent(resource); @@ -5090,6 +5389,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { resource.setDeploymentArtifacts(artifactMap); } + @SuppressWarnings("unchecked") private void setInformationalArtifactsPlaceHolder(Resource resource, User user) { Map artifactMap = resource.getArtifacts(); if (artifactMap == null) { @@ -5097,6 +5397,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } String resourceUniqueId = resource.getUniqueId(); List exludeResourceCategory = ConfigurationManager.getConfigurationManager().getConfiguration().getExcludeResourceCategory(); + List exludeResourceType = ConfigurationManager.getConfigurationManager().getConfiguration().getExcludeResourceType(); Map informationalResourceArtifacts = ConfigurationManager.getConfigurationManager().getConfiguration().getInformationalResourceArtifacts(); List categories = resource.getCategories(); boolean isCreateArtifact = true; @@ -5109,6 +5410,16 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } } + } + if (isCreateArtifact && exludeResourceType != null) { + String resourceType = resource.getResourceType().name(); + for (String type : exludeResourceType) { + if (type.equalsIgnoreCase(resourceType)) { + isCreateArtifact = false; + break; + } + } + } if (informationalResourceArtifacts != null && isCreateArtifact) { @@ -5273,14 +5584,10 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { /** * updateResourceMetadata * - * @param user - * - modifier data (userId) - * @param inTransaction - * TODO - * @param resourceIdToUpdate - * - the resource identifier + * @param user - modifier data (userId) + * @param inTransaction TODO + * @param resourceIdToUpdate - the resource identifier * @param newResource - * * @return Either */ public Either updateResourceMetadata(String resourceIdToUpdate, Resource newResource, Resource currentResource, User user, boolean inTransaction) { @@ -5315,7 +5622,6 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { // lock resource StorageOperationStatus lockResult = graphLockOperation.lockComponent(resourceIdToUpdate, NodeTypeEnum.Resource); if (!lockResult.equals(StorageOperationStatus.OK)) { - BeEcompErrorManager.getInstance().processEcompError(EcompErrorName.BeFailedLockObjectError, "Upload Artifact - lock " + resourceIdToUpdate + ": " + NodeTypeEnum.Resource); BeEcompErrorManager.getInstance().logBeFailedLockObjectError("Upload Artifact - lock ", NodeTypeEnum.Resource.getName(), resourceIdToUpdate); log.debug("Failed to lock resource: {}, error - {}", resourceIdToUpdate, lockResult); ResponseFormat responseFormat = componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(lockResult)); @@ -5331,7 +5637,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { // list // This code is not called from import resources, because of root // VF "derivedFrom" should be null (or ignored) - if (!currentResource.getResourceType().equals(ResourceTypeEnum.VF)) { + if (ToscaUtils.isAtomicType(currentResource)) { Either derivedFromNotEmptyEither = validateDerivedFromNotEmpty(null, newResource, null); if (derivedFromNotEmptyEither.isRight()) { log.debug("for updated resource {}, derived from field is empty", newResource.getName()); @@ -5373,7 +5679,54 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } } + private Either,Boolean> updateComponentGroupName(String replacePattern , String with ,List oldGroup){ + if ( oldGroup==null || with==null || replacePattern==null || with.isEmpty() || replacePattern.isEmpty()){ + if (log.isInfoEnabled()) + log.info("cannot update group name , invalid args -> replacePattern:{} , with:{} , oldGroup:{}" , replacePattern, with, oldGroup == null ? null : " < size : "+oldGroup.size()+" >" ); + return Either.right(false); + } + List list = oldGroup.stream().map( group -> new GroupDefinition(group)).collect(Collectors.toList()); + for ( GroupDefinition group : list) { + if ( group!=null && group.isSamePrefix( replacePattern ) ){ + String prefix = group.getName().substring( 0, replacePattern.length() ); + String newGroupName = group.getName().replaceFirst(prefix , with); + group.setName(newGroupName); + //String newUid = group.getUniqueId().replaceFirst(prefix , with); //removing this will also change the unique id + //group.setUniqueId(newUid); + } + } + return Either.left(list); + } + + private boolean isComponentNameChanged(Resource newResource,Resource oldResource){ + if (newResource!=null && oldResource!=null){ //TODO - must protect all chain against null , use optional + String futureName = newResource.getComponentMetadataDefinition().getMetadataDataDefinition().getName(); + String oldName = oldResource.getComponentMetadataDefinition().getMetadataDataDefinition().getName(); + return !oldName.equals(futureName); + } + return false; + } + private Either updateResourceMetadata(String resourceIdToUpdate, Resource newResource, User user, Resource currentResource, boolean shouldLock, boolean inTransaction) { + //region -> Update groups name for newResource + if ( isComponentNameChanged( currentResource , newResource) ){ + String replacePattern = Optional.ofNullable( //get currentResource name from metadata + Optional.ofNullable( Optional.ofNullable( currentResource ) + .orElse(null).getComponentMetadataDefinition() ) + .orElse(null).getMetadataDataDefinition() ) + .orElse(null).getName(); + String with = Optional.ofNullable( //get newResource name from metadata + Optional.ofNullable( Optional.ofNullable( newResource ) + .orElse(null).getComponentMetadataDefinition() ) + .orElse(null).getMetadataDataDefinition() ) + .orElse(null).getName(); + if ( with != null && replacePattern != null ){ + Either result = updateComponentGroupName( replacePattern , with ,currentResource.getGroups()); + if (result.isLeft()) + newResource.setGroups( (List)result.left().value() ); + } + } + //endregion Either validateResourceFields = validateResourceFieldsBeforeUpdate(currentResource, newResource, inTransaction); if (validateResourceFields.isRight()) { @@ -5395,6 +5748,18 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } log.debug("send resource {} to dao for update", newResource.getUniqueId()); + if (newResource!=null && newResource.getGroups()!=null){ + for ( GroupDefinition group : newResource.getGroups() ){ + if (newResource.getComponentMetadataDefinition()!=null && newResource.getComponentMetadataDefinition().getMetadataDataDefinition()!=null) + groupBusinessLogic.validateAndUpdateGroupMetadata( + newResource.getComponentMetadataDefinition().getMetadataDataDefinition().getUniqueId() , + user, + ComponentTypeEnum.RESOURCE_INSTANCE, + group, + true , + false) ; + } + } Either dataModelResponse = toscaOperationFacade.updateToscaElement(newResource); if (dataModelResponse.isRight()) { @@ -5410,12 +5775,9 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { /** * validateResourceFieldsBeforeCreate * - * @param user - * - modifier data (userId) - * @param dataModel - * - IResourceOperation for resource crud - * @param resource - * - Resource object to validate + * @param user - modifier data (userId) + * @param dataModel - IResourceOperation for resource crud + * @param resource - Resource object to validate * @return Either */ private Either validateResourceFieldsBeforeCreate(User user, Resource resource, AuditingActionEnum actionEnum, boolean inTransaction) { @@ -5449,7 +5811,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { return eitherValidation; } - // validate vendor name & release + // validate vendor name & release & model number log.debug("validate vendor name"); eitherValidation = validateVendorName(user, resource, actionEnum); if (eitherValidation.isRight()) { @@ -5462,6 +5824,12 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { return eitherValidation; } + log.debug("validate resource vendor model number"); + eitherValidation = validateResourceVendorModelNumber(user, resource, actionEnum); + if (eitherValidation.isRight()) { + return eitherValidation; + } + // validate contact info /* * log.debug("validate contact info"); eitherValidation = validateContactIdContactId(user, resource, actionEnum); if (eitherValidation.isRight()) { return eitherValidation; } @@ -5483,7 +5851,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { // validate template (derived from) log.debug("validate derived from"); - if (resource.getResourceType().equals(ResourceTypeEnum.VF)) { + if (!ToscaUtils.isAtomicType(resource) && resource.getResourceType() != ResourceTypeEnum.CVFC) { resource.setDerivedFrom(null); } eitherValidation = validateDerivedFromExist(user, resource, actionEnum); @@ -5519,8 +5887,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { /** * validateResourceFieldsBeforeUpdate * - * @param currentResource - * - Resource object to validate + * @param currentResource - Resource object to validate * @return Either */ private Either validateResourceFieldsBeforeUpdate(Resource currentResource, Resource updateInfoResource, boolean inTransaction) { @@ -5559,6 +5926,13 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { return eitherValidation; } + log.debug("validate resource vendor model number before update"); + eitherValidation = validateResourceVendorModelNumber(currentResource, updateInfoResource); + if (eitherValidation.isRight()) { + return eitherValidation; + } + + log.debug("validate vendor release before update"); eitherValidation = validateVendorReleaseName(null, updateInfoResource, null); if (eitherValidation.isRight()) { @@ -5763,6 +6137,19 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { return Either.left(true); } + private Either validateResourceVendorModelNumber(Resource currentResource, Resource updateInfoResource) { + String updatedResourceVendorModelNumber = updateInfoResource.getResourceVendorModelNumber(); + String currentResourceVendorModelNumber = currentResource.getResourceVendorModelNumber(); + if (!currentResourceVendorModelNumber.equals(updatedResourceVendorModelNumber)) { + Either validateResourceVendorModelNumber = validateResourceVendorModelNumber(null, updateInfoResource, null); + if (validateResourceVendorModelNumber.isRight()) { + ResponseFormat errorResponse = validateResourceVendorModelNumber.right().value(); + return Either.right(errorResponse); + } + } + return Either.left(true); + } + private Either validateCategory(Resource currentResource, Resource updateInfoResource, boolean hasBeenCertified, boolean inTransaction) { Either validateCategoryName = validateCategory(null, updateInfoResource, null, inTransaction); if (validateCategoryName.isRight()) { @@ -5841,9 +6228,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { log.trace("audit before sending response"); componentsUtils.auditResource(responseFormat, user, resource, "", "", actionEnum, null); return Either.right(responseFormat); - } - - else if (!dataModelResponse.left().value()) { + } else if (!dataModelResponse.left().value()) { log.info("resource template with name: {}, does not exists", templateName); ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.PARENT_RESOURCE_NOT_FOUND); componentsUtils.auditResource(responseFormat, user, resource, "", "", actionEnum, null); @@ -5958,7 +6343,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { return Either.right(responseFormat); } if (subcategories.size() > 1) { - log.debug("Must be only one sub ategory for resource"); + log.debug("Must be only one sub category for resource"); ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.RESOURCE_TOO_MUCH_SUBCATEGORIES); return Either.right(responseFormat); } @@ -6071,6 +6456,18 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } + private Either validateResourceVendorModelNumber(User user, Resource resource, AuditingActionEnum actionEnum) { + String resourceVendorModelNumber = resource.getResourceVendorModelNumber(); + Either validateResourceVendorModelNumber = validateResourceVendorModelNumber(resourceVendorModelNumber); + if (validateResourceVendorModelNumber.isRight()) { + ResponseFormat responseFormat = validateResourceVendorModelNumber.right().value(); + componentsUtils.auditResource(responseFormat, user, resource, "", "", actionEnum, null); + } + return validateResourceVendorModelNumber; + + } + + private Either validateVendorName(String vendorName) { if (vendorName != null) { if (!ValidationUtils.validateVendorNameLength(vendorName)) { @@ -6091,6 +6488,26 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } + private Either validateResourceVendorModelNumber(String resourceVendorModelNumber) { + if (resourceVendorModelNumber.equals("")) { + return Either.left(true); + } else { + if (!ValidationUtils.validateResourceVendorModelNumberLength(resourceVendorModelNumber)) { + log.info("resource vendor model number exceeds limit."); + ResponseFormat errorResponse = componentsUtils.getResponseFormat(ActionStatus.RESOURCE_VENDOR_MODEL_NUMBER_EXCEEDS_LIMIT, "" + ValidationUtils.RESOURCE_VENDOR_MODEL_NUMBER_MAX_LENGTH); + return Either.right(errorResponse); + } + // resource vendor model number is currently validated as vendor name + if (!ValidationUtils.validateVendorName(resourceVendorModelNumber)) { + log.info("resource vendor model number is not valid."); + ResponseFormat errorResponse = componentsUtils.getResponseFormat(ActionStatus.INVALID_RESOURCE_VENDOR_MODEL_NUMBER); + return Either.right(errorResponse); + } + return Either.left(true); + } + } + + /* * private Either validateDescriptionAndCleanup(User user, Resource resource, AuditingActionEnum actionEnum) { String description = resource.getDescription(); if (!ValidationUtils.validateStringNotEmpty(description)) { * log.debug("Resource description is empty"); ResponseFormat errorResponse = componentsUtils.getResponseFormat(ActionStatus. COMPONENT_MISSING_DESCRIPTION, ComponentTypeEnum.RESOURCE.getValue()); componentsUtils.auditResource(errorResponse, @@ -6355,7 +6772,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { if (inputs.isRight()) { String message = "Failed when creating inputs: for resource:" + resource.getName(); BeEcompErrorManager.getInstance().logInternalFlowError("ImportResource", message, ErrorSeverity.INFO); - Map resultMap = new HashMap(); + Map resultMap = new HashMap<>(); return Either.left(resultMap); } @@ -6568,7 +6985,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } private Either>, ResponseFormat> organizeVfCsarArtifactsByArtifactOperation(List artifactPathAndNameList, List existingArtifactsToHandle, - Resource resource, User user) { + Resource resource, User user) { EnumMap> nodeTypeArtifactsToHandle = new EnumMap<>(ArtifactOperationEnum.class); Wrapper responseWrapper = new Wrapper<>(); @@ -6648,6 +7065,21 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } return toscaResourceName; } + + private String buildNodeToscaResourceName(String vfResourceName, String nodeTypeFullName) { + String toscaResourceName; + String nameWithouNamespacePrefix = nodeTypeFullName.substring(Constants.USER_DEFINED_RESOURCE_NAMESPACE_PREFIX.length()); + String[] findTypes = nameWithouNamespacePrefix.split("\\."); + String resourceType = findTypes[0]; + String actualName = nameWithouNamespacePrefix.substring(resourceType.length()); + + if (actualName.startsWith(Constants.ABSTRACT)) { + toscaResourceName = Constants.USER_DEFINED_RESOURCE_NAMESPACE_PREFIX + ResourceTypeEnum.VFC.name().toLowerCase() + '.' + vfResourceName + '.' + actualName; + } else { + toscaResourceName = Constants.USER_DEFINED_RESOURCE_NAMESPACE_PREFIX + resourceType.toLowerCase() + '.' + vfResourceName + '.' + Constants.ABSTRACT + actualName; + } + return toscaResourceName; + } public ICacheMangerOperation getCacheManagerOperation() { return cacheManagerOperation; @@ -6659,84 +7091,13 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { ///////////////////////////////////////// DataModel refactoring///////////////////////////////////////////// - /* - * /** - * - * @deprecated Use {@link #createOrUpdateResourceByImport(Resource,User,boolean, boolean,boolean)} instead - */ - /* - * public Either, ResponseFormat> createOrUpdateResourceByImport(Resource resource, User user, AuditingActionEnum auditingEnum, boolean isNormative, boolean needLock) { return - * createOrUpdateResourceByImport(resource, user, isNormative, false, needLock); } - */ - - public Either, ResponseFormat> createOrUpdateNodeTypeByImport(Resource resource, User user, boolean isNormative, boolean isInTransaction, boolean needLock) { - - // check if resource already exist - Either latestByName = toscaOperationFacade.getLatestByName(resource.getName()); - Either, ResponseFormat> result = null; - - // create - if (latestByName.isRight() && latestByName.right().value().equals(StorageOperationStatus.NOT_FOUND)) { - - Either latestByToscaName = toscaOperationFacade.getLatestByToscaResourceName(resource.getToscaResourceName()); - if (latestByToscaName.isRight() && latestByToscaName.right().value().equals(StorageOperationStatus.NOT_FOUND)) - result = createNodeTypeByImport(resource, user, isNormative, isInTransaction); - - else { - StorageOperationStatus status = latestByName.right().value(); - BeEcompErrorManager.getInstance().processEcompError(EcompErrorName.BeResourceMissingError, "Create / Update resource by import", resource.getName()); - BeEcompErrorManager.getInstance().logBeComponentMissingError("Create / Update resource by import", ComponentTypeEnum.RESOURCE.getValue(), resource.getName()); - log.debug("resource already exist {}. status={}", resource.getName(), status); - ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.RESOURCE_ALREADY_EXISTS); - componentsUtils.auditResource(responseFormat, user, resource, "", "", AuditingActionEnum.IMPORT_RESOURCE, null); - result = Either.right(responseFormat); - } - - } - - // update - else if (latestByName.isLeft()) { - // result = updateExistingNodeTypeByImport(resource, latestByName.left().value(), user, isNormative, needLock); - } - - // error - else { - StorageOperationStatus status = latestByName.right().value(); - BeEcompErrorManager.getInstance().processEcompError(EcompErrorName.BeResourceMissingError, "Create / Update resource by import", resource.getName()); - log.debug("failed to get latest version of resource {}. status={}", resource.getName(), status); - ResponseFormat responseFormat = componentsUtils.getResponseFormatByResource(componentsUtils.convertFromStorageResponse(latestByName.right().value()), resource); - componentsUtils.auditResource(responseFormat, user, resource, "", "", AuditingActionEnum.IMPORT_RESOURCE, null); - result = Either.right(responseFormat); - } - return result; - - } - - private Either, ResponseFormat> createNodeTypeByImport(Resource resource, User user, boolean isNormative, boolean isInTransaction) { - log.debug("resource with name {} does not exist. create new resource", resource.getName()); - Either response = validateResourceBeforeCreate(resource, user, AuditingActionEnum.IMPORT_RESOURCE, isInTransaction); - if (response.isRight()) { - return Either.right(response.right().value()); - } - - Either createResponse = createResourceByDao(resource, user, AuditingActionEnum.IMPORT_RESOURCE, isNormative, isInTransaction, null); - if (createResponse.isRight()) { - return Either.right(createResponse.right().value()); - } else { - ImmutablePair resourcePair = new ImmutablePair<>(createResponse.left().value(), ActionStatus.CREATED); - ASDCKpiApi.countImportResourcesKPI(); - return Either.left(resourcePair); - - } - } - public Either getUiComponentDataTransferByComponentId(String resourceId, List dataParamsToReturn) { ComponentParametersView paramsToRetuen = new ComponentParametersView(dataParamsToReturn); Either resourceResultEither = toscaOperationFacade.getToscaElement(resourceId, paramsToRetuen); if (resourceResultEither.isRight()) { - if(resourceResultEither.right().value().equals(StorageOperationStatus.NOT_FOUND)) { + if (resourceResultEither.right().value().equals(StorageOperationStatus.NOT_FOUND)) { log.debug("Failed to found resource with id {} ", resourceId); Either.right(componentsUtils.getResponseFormat(ActionStatus.RESOURCE_NOT_FOUND, resourceId)); } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ResourceImportManager.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ResourceImportManager.java index b157b635b4..d2743aa039 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ResourceImportManager.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ResourceImportManager.java @@ -124,7 +124,7 @@ public class ResourceImportManager { lifecycleChangeInfo.setUserRemarks("certification on import"); Function> validator = (resource) -> resourceBusinessLogic.validatePropertiesDefaultValues(resource); - return importCertifiedResource(resourceYml, resourceMetaData, creator, validator, lifecycleChangeInfo, false, createNewVersion, needLock, null, null); + return importCertifiedResource(resourceYml, resourceMetaData, creator, validator, lifecycleChangeInfo, false, createNewVersion, needLock, null, null, false); } public Either, ResponseFormat> importNormativeResourceFromCsar(String resourceYml, UploadResourceInfo resourceMetaData, User creator, boolean createNewVersion, boolean needLock) { @@ -133,18 +133,18 @@ public class ResourceImportManager { lifecycleChangeInfo.setUserRemarks("certification on import"); Function> validator = (resource) -> resourceBusinessLogic.validatePropertiesDefaultValues(resource); - return importCertifiedResource(resourceYml, resourceMetaData, creator, validator, lifecycleChangeInfo, false, createNewVersion, needLock, null, null); + return importCertifiedResource(resourceYml, resourceMetaData, creator, validator, lifecycleChangeInfo, false, createNewVersion, needLock, null, null, false); } public Either, ResponseFormat> importCertifiedResource(String resourceYml, UploadResourceInfo resourceMetaData, User creator, Function> validationFunction, - LifecycleChangeInfoWithAction lifecycleChangeInfo, boolean isInTransaction, boolean createNewVersion, boolean needLock, Map> nodeTypeArtifactsToHandle, List nodeTypesNewCreatedArtifacts) { + LifecycleChangeInfoWithAction lifecycleChangeInfo, boolean isInTransaction, boolean createNewVersion, boolean needLock, Map> nodeTypeArtifactsToHandle, List nodeTypesNewCreatedArtifacts, boolean forceCertificationAllowed) { Resource resource = new Resource(); ImmutablePair responsePair = new ImmutablePair<>(resource, ActionStatus.CREATED); Either, ResponseFormat> response = Either.left(responsePair); String latestCertifiedResourceId = null; try { - boolean shouldBeCertified = nodeTypeArtifactsToHandle == null || nodeTypeArtifactsToHandle.isEmpty() ? true : false; + boolean shouldBeCertified = nodeTypeArtifactsToHandle == null || nodeTypeArtifactsToHandle.isEmpty(); setConstantMetaData(resource, shouldBeCertified); setMetaDataFromJson(resourceMetaData, resource); @@ -179,7 +179,7 @@ public class ResourceImportManager { } } latestCertifiedResourceId = getLatestCertifiedResourceId(resource); - changeStateResponse = resourceBusinessLogic.propagateStateToCertified(creator, resource, lifecycleChangeInfo, isInTransaction, needLock); + changeStateResponse = resourceBusinessLogic.propagateStateToCertified(creator, resource, lifecycleChangeInfo, isInTransaction, needLock, forceCertificationAllowed); if (changeStateResponse.isRight()) { response = Either.right(changeStateResponse.right().value()); } else { @@ -270,14 +270,14 @@ public class ResourceImportManager { } - private Either populateResourceFromYaml(String resourceYml, Resource resource, boolean inTransaction) { + Either populateResourceFromYaml(String resourceYml, Resource resource, boolean inTransaction) { @SuppressWarnings("unchecked") Either eitherResult = Either.left(true); Map toscaJsonAll = (Map) new Yaml().load(resourceYml); Map toscaJson = toscaJsonAll; // Checks if exist and builds the node_types map - if (toscaJsonAll.containsKey(ToscaTagNamesEnum.NODE_TYPES.getElementName())) { + if (toscaJsonAll.containsKey(ToscaTagNamesEnum.NODE_TYPES.getElementName()) && resource.getResourceType()!=ResourceTypeEnum.CVFC) { toscaJson = new HashMap(); toscaJson.put(ToscaTagNamesEnum.NODE_TYPES.getElementName(), toscaJsonAll.get(ToscaTagNamesEnum.NODE_TYPES.getElementName())); } @@ -721,7 +721,7 @@ public class ResourceImportManager { capabilityDefinition.setProperties(capabilityProperties); } } - } else { + } else if (!(capabilityJson instanceof List)) { result = Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_YAML)); diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceBusinessLogic.java index bc1c6e5910..ae7ae31ed9 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceBusinessLogic.java @@ -447,14 +447,12 @@ public class ServiceBusinessLogic extends ComponentBusinessLogic { return componentsFieldsValidation; } - // validate service name uniqueness log.debug("validate service name uniqueness"); Either serviceNameUniquenessValidation = validateComponentNameUnique(user, service, actionEnum); if (serviceNameUniquenessValidation.isRight()) { return serviceNameUniquenessValidation; } - // validate category log.debug("validate category"); Either categoryValidation = validateServiceCategory(user, service, actionEnum); if (categoryValidation.isRight()) { @@ -462,12 +460,23 @@ public class ServiceBusinessLogic extends ComponentBusinessLogic { } // validate project name (ProjectCode) - mandatory in service - log.debug("validate projectName"); Either projectCodeValidation = validateProjectCode(user, service, actionEnum); if (projectCodeValidation.isRight()) { return projectCodeValidation; } + + log.debug("validate service type"); + Either serviceTypeValidation = validateServiceTypeAndCleanup(user, service, actionEnum); + if (serviceTypeValidation.isRight()) { + return serviceTypeValidation; + } + + log.debug("validate service role"); + Either serviceRoleValidation = validateServiceRoleAndCleanup(user, service, actionEnum); + if (serviceRoleValidation.isRight()) { + return serviceRoleValidation; + } return Either.left(true); @@ -704,6 +713,18 @@ public class ServiceBusinessLogic extends ComponentBusinessLogic { if (!uuidCurrent.equals(uuidUpdated)) { log.info("update srvice: recived request to update uuid to {} the field is not updatable ignoring.", uuidUpdated); } + + response = validateAndUpdateServiceType(user, currentService, serviceUpdate, null); + if (response.isRight()) { + ResponseFormat errorResponse = response.right().value(); + return Either.right(errorResponse); + } + + response = validateAndUpdateServiceRole(user, currentService, serviceUpdate, null); + if (response.isRight()) { + ResponseFormat errorResponse = response.right().value(); + return Either.right(errorResponse); + } String currentInvariantUuid = currentService.getInvariantUUID(); String updatedInvariantUuid = serviceUpdate.getInvariantUUID(); @@ -821,18 +842,18 @@ public class ServiceBusinessLogic extends ComponentBusinessLogic { return Either.left(true); } - private Either validateAndUpdateServiceName(User user, Service currentService, Service serviceUpdate, boolean hasBeenCertified, AuditingActionEnum audatingAction) { + private Either validateAndUpdateServiceName(User user, Service currentService, Service serviceUpdate, boolean hasBeenCertified, AuditingActionEnum auditingAction) { String serviceNameUpdated = serviceUpdate.getName(); String serviceNameCurrent = currentService.getName(); if (!serviceNameCurrent.equals(serviceNameUpdated)) { if (!hasBeenCertified) { - Either validatServiceNameResponse = validateComponentName(user, serviceUpdate, audatingAction); + Either validatServiceNameResponse = validateComponentName(user, serviceUpdate, auditingAction); if (validatServiceNameResponse.isRight()) { ResponseFormat errorRespons = validatServiceNameResponse.right().value(); return Either.right(errorRespons); } - Either serviceNameUniquenessValidation = validateComponentNameUnique(user, serviceUpdate, audatingAction); + Either serviceNameUniquenessValidation = validateComponentNameUnique(user, serviceUpdate, auditingAction); if (serviceNameUniquenessValidation.isRight()) { return serviceNameUniquenessValidation; } @@ -848,6 +869,111 @@ public class ServiceBusinessLogic extends ComponentBusinessLogic { } return Either.left(true); } + + private Either validateAndUpdateServiceType(User user, Service currentService, Service updatedService, AuditingActionEnum auditingAction) { + String updatedServiceType = updatedService.getServiceType(); + String currentServiceType = currentService.getServiceType(); + if (!currentServiceType.equals(updatedServiceType)) { + Either validateServiceType = validateServiceTypeAndCleanup(user, updatedService , auditingAction); + if (validateServiceType.isRight()) { + ResponseFormat errorResponse = validateServiceType.right().value(); + componentsUtils.auditComponentAdmin(errorResponse, user, updatedService, "", "", auditingAction, ComponentTypeEnum.SERVICE); + return Either.right(errorResponse); + } + currentService.setServiceType(updatedServiceType); + } + return Either.left(true); + } + + protected Either validateServiceTypeAndCleanup(User user, Component component, AuditingActionEnum actionEnum) { + String serviceType = ((Service)component).getServiceType(); + if (serviceType != null){ + serviceType = cleanUpText(serviceType); + Either validateServiceType = validateServiceType(serviceType); + if (validateServiceType.isRight()) { + ResponseFormat responseFormat = validateServiceType.right().value(); + componentsUtils.auditComponentAdmin(responseFormat, user, component, "", "", actionEnum, ComponentTypeEnum.SERVICE); + return Either.right(responseFormat); + } + return Either.left(true); + } else { + return Either.left(false); + } + } + + + private Either validateServiceType(String serviceType) { + if (serviceType.equals("")){ + return Either.left(true); + } else { + if (!ValidationUtils.validateServiceTypeLength(serviceType)) { + log.info("service type exceeds limit."); + ResponseFormat errorResponse = componentsUtils.getResponseFormat(ActionStatus.SERVICE_TYPE_EXCEEDS_LIMIT, "" + ValidationUtils.SERVICE_TYPE_MAX_LENGTH); + return Either.right(errorResponse); + } + + if (!ValidationUtils.validateIsEnglish(serviceType)) { + log.info("service type is not valid."); + ResponseFormat errorResponse = componentsUtils.getResponseFormat(ActionStatus.INVALID_SERVICE_TYPE); + return Either.right(errorResponse); + } + return Either.left(true); + } + } + + private Either validateAndUpdateServiceRole(User user, Service currentService, Service updatedService, AuditingActionEnum auditingAction) { + String updatedServiceRole = updatedService.getServiceRole(); + String currentServiceRole = currentService.getServiceRole(); + if (!currentServiceRole.equals(updatedServiceRole)) { + Either validateServiceRole = validateServiceRoleAndCleanup(user, updatedService , auditingAction); + if (validateServiceRole.isRight()) { + ResponseFormat errorResponse = validateServiceRole.right().value(); + componentsUtils.auditComponentAdmin(errorResponse, user, updatedService, "", "", auditingAction, ComponentTypeEnum.SERVICE); + return Either.right(errorResponse); + } + currentService.setServiceRole(updatedServiceRole); + } + return Either.left(true); + } + + protected Either validateServiceRoleAndCleanup(User user, Component component, AuditingActionEnum actionEnum) { + String serviceRole = ((Service)component).getServiceRole(); + if (serviceRole != null){ + serviceRole = cleanUpText(serviceRole); + + Either validateServiceRole = validateServiceRole(serviceRole); + if (validateServiceRole.isRight()) { + ResponseFormat responseFormat = validateServiceRole.right().value(); + componentsUtils.auditComponentAdmin(responseFormat, user, component, "", "", actionEnum, ComponentTypeEnum.SERVICE); + return Either.right(responseFormat); + } + return Either.left(true); + } else { + return Either.left(false); + } + } + + + private Either validateServiceRole(String serviceRole) { + if (serviceRole.equals("")){ + return Either.left(true); + } else { + if (!ValidationUtils.validateServiceRoleLength(serviceRole)) { + log.info("service role exceeds limit."); + ResponseFormat errorResponse = componentsUtils.getResponseFormat(ActionStatus.SERVICE_ROLE_EXCEEDS_LIMIT, "" + ValidationUtils.SERVICE_ROLE_MAX_LENGTH); + return Either.right(errorResponse); + } + + if (!ValidationUtils.validateIsEnglish(serviceRole)) { + log.info("service role is not valid."); + ResponseFormat errorResponse = componentsUtils.getResponseFormat(ActionStatus.INVALID_SERVICE_ROLE); + return Either.right(errorResponse); + } + return Either.left(true); + } + } + + private Either validateAndUpdateCategory(User user, Service currentService, Service serviceUpdate, boolean hasBeenCertified, AuditingActionEnum audatingAction) { List categoryUpdated = serviceUpdate.getCategories(); @@ -1225,7 +1351,7 @@ public class ServiceBusinessLogic extends ComponentBusinessLogic { // DE194021 ServletContext servletContext = request.getSession().getServletContext(); - boolean isDistributionEngineUp = getHealthCheckBL(servletContext).isDistributionEngineUp(request.getSession().getServletContext()); // DE + boolean isDistributionEngineUp = getHealthCheckBL(servletContext).isDistributionEngineUp(); // DE if (!isDistributionEngineUp) { BeEcompErrorManager.getInstance().logBeSystemError("Distribution Engine is DOWN"); log.debug("Distribution Engine is DOWN"); diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceComponentInstanceBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceComponentInstanceBusinessLogic.java index 9586be81ea..11ffcd9329 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceComponentInstanceBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceComponentInstanceBusinessLogic.java @@ -31,10 +31,6 @@ import fj.data.Either; @Component("serviceComponentInstanceBusinessLogic") public class ServiceComponentInstanceBusinessLogic extends ComponentInstanceBusinessLogic { - @Override - protected Either validateAllowedToContainCompInstances(org.openecomp.sdc.be.model.Component containerComponent) { - return Either.left(true); - } @Override protected NodeTypeEnum getNodeTypeOfComponentInstanceOrigin() { diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/VFComponentInstanceBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/VFComponentInstanceBusinessLogic.java index 61a5af5b74..5a93ecf182 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/VFComponentInstanceBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/VFComponentInstanceBusinessLogic.java @@ -25,6 +25,7 @@ import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum; import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum; import org.openecomp.sdc.be.model.Resource; +import org.openecomp.sdc.be.tosca.ToscaUtils; import org.openecomp.sdc.exception.ResponseFormat; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -37,17 +38,6 @@ public class VFComponentInstanceBusinessLogic extends ComponentInstanceBusinessL private static Logger log = LoggerFactory.getLogger(VFComponentInstanceBusinessLogic.class.getName()); - @Override - protected Either validateAllowedToContainCompInstances(org.openecomp.sdc.be.model.Component containerComponent) { - Resource resource = (Resource) containerComponent; - ResourceTypeEnum resourceType = resource.getResourceType(); - if (ResourceTypeEnum.VF != resourceType) { - log.debug("Cannot attach resource instances to container resource of type {}", resourceType); - return Either.right(componentsUtils.getResponseFormat(ActionStatus.RESOURCE_CANNOT_CONTAIN_RESOURCE_INSTANCES, resourceType.getValue())); - } - return Either.left(true); - } - @Override protected NodeTypeEnum getNodeTypeOfComponentInstanceOrigin() { return NodeTypeEnum.Resource; diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/lifecycle/CertificationRequestTransition.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/lifecycle/CertificationRequestTransition.java index 042af54383..b18c4d0985 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/lifecycle/CertificationRequestTransition.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/lifecycle/CertificationRequestTransition.java @@ -55,6 +55,7 @@ import org.openecomp.sdc.be.model.Resource; import org.openecomp.sdc.be.model.Service; import org.openecomp.sdc.be.model.User; import org.openecomp.sdc.be.model.jsontitan.datamodel.ToscaElement; +import org.openecomp.sdc.be.model.jsontitan.datamodel.ToscaElementTypeEnum; import org.openecomp.sdc.be.model.jsontitan.operations.ToscaElementLifecycleOperation; import org.openecomp.sdc.be.model.jsontitan.operations.ToscaOperationFacade; import org.openecomp.sdc.be.model.jsontitan.utils.ModelConverter; @@ -66,6 +67,7 @@ import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum; import org.openecomp.sdc.be.tosca.ToscaError; import org.openecomp.sdc.be.tosca.ToscaExportHandler; import org.openecomp.sdc.be.tosca.ToscaRepresentation; +import org.openecomp.sdc.be.tosca.ToscaUtils; import org.openecomp.sdc.be.user.Role; import org.openecomp.sdc.common.api.ArtifactTypeEnum; import org.openecomp.sdc.common.util.ValidationUtils; @@ -196,7 +198,7 @@ public class CertificationRequestTransition extends LifeCycleTransition { ResponseFormat responseFormat; Either result = null; try{ - if (componentType == ComponentTypeEnum.SERVICE || (componentType == ComponentTypeEnum.RESOURCE && ((Resource) component).getResourceType() == ResourceTypeEnum.VF)) { + if (component.getToscaType().equals(ToscaElementTypeEnum.TopologyTemplate.getValue())) { Either statusCert = validateAllResourceInstanceCertified(component); if (statusCert.isRight()) { @@ -270,7 +272,10 @@ public class CertificationRequestTransition extends LifeCycleTransition { // occurrences in the future Map> reqName2Ids = new HashMap<>(); Map> capName2Ids = new HashMap<>(); - parseRelationsForReqCapVerification(component, reqName2Ids, capName2Ids); +// Either parseRelationsForReqCapVerificationRes = parseRelationsForReqCapVerification(component, reqName2Ids, capName2Ids); +// if(parseRelationsForReqCapVerificationRes.isRight()){ +// return parseRelationsForReqCapVerificationRes; +// } Map> requirementsToFulfillBeforeCert = configurationManager.getConfiguration().getRequirementsToFulfillBeforeCert(); Map> capabilitiesToConsumeBeforeCert = configurationManager.getConfiguration().getCapabilitiesToConsumeBeforeCert(); for (ComponentInstance compInst : componentInstances) { diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/lifecycle/LifecycleBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/lifecycle/LifecycleBusinessLogic.java index 8e89a6bf31..4fe0965ef6 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/lifecycle/LifecycleBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/lifecycle/LifecycleBusinessLogic.java @@ -32,6 +32,7 @@ import org.openecomp.sdc.be.components.impl.ComponentBusinessLogic; import org.openecomp.sdc.be.components.impl.ProductBusinessLogic; import org.openecomp.sdc.be.components.impl.ResourceBusinessLogic; import org.openecomp.sdc.be.components.impl.ServiceBusinessLogic; +import org.openecomp.sdc.be.components.lifecycle.LifecycleChangeInfoWithAction.LifecycleChanceActionEnum; import org.openecomp.sdc.be.config.BeEcompErrorManager; import org.openecomp.sdc.be.dao.api.ActionStatus; import org.openecomp.sdc.be.dao.jsongraph.TitanDao; @@ -46,13 +47,14 @@ import org.openecomp.sdc.be.model.LifecycleStateEnum; import org.openecomp.sdc.be.model.Resource; import org.openecomp.sdc.be.model.Service; import org.openecomp.sdc.be.model.User; +import org.openecomp.sdc.be.model.jsontitan.datamodel.ToscaElement; import org.openecomp.sdc.be.model.jsontitan.operations.ToscaElementLifecycleOperation; import org.openecomp.sdc.be.model.jsontitan.operations.ToscaOperationFacade; +import org.openecomp.sdc.be.model.jsontitan.utils.ModelConverter; import org.openecomp.sdc.be.model.operations.api.ICacheMangerOperation; import org.openecomp.sdc.be.model.operations.api.IGraphLockOperation; import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; import org.openecomp.sdc.be.model.operations.impl.CapabilityOperation; -import org.openecomp.sdc.be.model.operations.impl.ComponentOperation; import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum; import org.openecomp.sdc.be.tosca.ToscaExportHandler; import org.openecomp.sdc.common.api.Constants; @@ -204,9 +206,9 @@ public class LifecycleBusinessLogic { String resourceCurrVersion = component.getVersion(); LifecycleStateEnum resourceCurrState = component.getLifecycleState(); - log.info("lock component {}", componentId); // lock resource if (inTransaction == false && needLock) { + log.info("lock component {}", componentId); Either eitherLockResource = lockComponent(componentType, component); if (eitherLockResource.isRight()) { errorResponse = eitherLockResource.right().value(); @@ -214,8 +216,8 @@ public class LifecycleBusinessLogic { log.error("lock component {} failed", componentId); return Either.right(errorResponse); } + log.info("after lock component {}", componentId); } - log.info("after lock component {}", componentId); try { Either commentValidationResult = validateComment(changeInfo, transitionEnum); if (commentValidationResult.isRight()) { @@ -463,4 +465,51 @@ public class LifecycleBusinessLogic { return Either.left(latestComponent); } + public Either forceResourceCertification(Resource resource, User user, LifecycleChangeInfoWithAction lifecycleChangeInfo, boolean inTransaction, boolean needLock) { + Either result = null; + Either certifyResourceRes = null; + if(lifecycleChangeInfo.getAction() != LifecycleChanceActionEnum.CREATE_FROM_CSAR){ + log.debug("Force certification is not allowed for the action {}. ", lifecycleChangeInfo.getAction().name()); + result = Either.right(componentUtils.getResponseFormat(ActionStatus.NOT_ALLOWED)); + } + // lock resource + if(result == null && !inTransaction && needLock){ + log.info("lock component {}", resource.getUniqueId()); + Either eitherLockResource = lockComponent(resource.getComponentType(), resource); + if (eitherLockResource.isRight()) { + log.error("lock component {} failed", resource.getUniqueId()); + result = Either.right(eitherLockResource.right().value()); + } + log.info("after lock component {}", resource.getUniqueId()); + } + try{ + if(result == null){ + certifyResourceRes = lifecycleOperation.forceCerificationOfToscaElement(resource.getUniqueId(), user.getUserId(), user.getUserId()); + if (certifyResourceRes.isRight()) { + StorageOperationStatus status = certifyResourceRes.right().value(); + log.debug("Failed to perform a force certification of resource {}. The status is {}. ", resource.getName(), status); + result = Either.right(componentUtils.getResponseFormatByResource(componentUtils.convertFromStorageResponse(status), resource)); + } + } + if(result == null){ + result = Either.left(ModelConverter.convertFromToscaElement(certifyResourceRes.left().value())); + } + } finally { + log.info("unlock component {}", resource.getUniqueId()); + if (!inTransaction) { + if(result.isLeft()){ + titanDao.commit(); + } else{ + titanDao.rollback(); + } + if(needLock){ + NodeTypeEnum nodeType = resource.getComponentType().getNodeType(); + log.info("During change state, another component {} has been created/updated", resource.getUniqueId()); + graphLockOperation.unlockComponent(resource.getUniqueId(), nodeType); + } + } + } + return result; + } + } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/externalapi/servlet/AssetsDataServlet.java b/catalog-be/src/main/java/org/openecomp/sdc/be/externalapi/servlet/AssetsDataServlet.java index c3708d4017..f96e226d26 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/externalapi/servlet/AssetsDataServlet.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/externalapi/servlet/AssetsDataServlet.java @@ -126,10 +126,11 @@ public class AssetsDataServlet extends AbstractValidationsServlet { Response response = null; ResponseFormat responseFormat = null; String query = request.getQueryString(); - String requestURI = request.getRequestURI(); + String requestURI = request.getRequestURI().endsWith("/")? + removeDuplicateSlashSeparator(request.getRequestURI()): request.getRequestURI(); String url = request.getMethod() + " " + requestURI; log.debug("Start handle request of {}", url); - + AuditingActionEnum auditingActionEnum = query == null ? AuditingActionEnum.GET_ASSET_LIST : AuditingActionEnum.GET_FILTERED_ASSET_LIST; EnumMap additionalParam = new EnumMap(AuditingFieldsKeysEnum.class); @@ -162,7 +163,7 @@ public class AssetsDataServlet extends AbstractValidationsServlet { } if (resourceType != null) { ResourceTypeEnum resourceTypeEnum = ResourceTypeEnum.getTypeIgnoreCase(resourceType); - if( resourceTypeEnum == null ){ + if (resourceTypeEnum == null) { log.debug("getAssetList: Asset Fetching Failed. Invalid resource type was received"); responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT); getComponentsUtils().auditExternalGetAsset(responseFormat, auditingActionEnum, additionalParam); @@ -370,4 +371,11 @@ public class AssetsDataServlet extends AbstractValidationsServlet { return response; } } + + + private String removeDuplicateSlashSeparator(String requestUri) { + return requestUri.substring(0, requestUri.length()-1); + } + + } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/externalapi/servlet/CrudExternalServlet.java b/catalog-be/src/main/java/org/openecomp/sdc/be/externalapi/servlet/CrudExternalServlet.java index b4240777a8..40a5322afa 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/externalapi/servlet/CrudExternalServlet.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/externalapi/servlet/CrudExternalServlet.java @@ -120,7 +120,7 @@ public class CrudExternalServlet extends AbstractValidationsServlet { @ApiOperation(value = "creates a resource", httpMethod = "POST", notes = "Creates a resource") @ApiResponses(value = { @ApiResponse(code = 200, message = "ECOMP component is authenticated and Asset created", response = Resource.class), - @ApiResponse(code = 400, message = "Missing 'X-ECOMP-InstanceID' HTTP header - POL5001"), + @ApiResponse(code = 400, message = "Missing X-ECOMP-InstanceID HTTP header - POL5001"), @ApiResponse(code = 401, message = "ECOMP component should authenticate itself and to re-send again HTTP request with its Basic Authentication credentials - POL5002"), @ApiResponse(code = 403, message = "ECOMP component is not authorized - POL5003"), @ApiResponse(code = 404, message = "Error: Requested '%1' (uuid) resource was not found - SVC4063"), @@ -269,7 +269,7 @@ public class CrudExternalServlet extends AbstractValidationsServlet { @ApiOperation(value = "Change Resource lifecycle State", httpMethod = "POST") @ApiResponses(value = { @ApiResponse(code = 200, message = "Resource state changed", response = AssetMetadata.class), - @ApiResponse(code = 400, message = "Missing 'X-ECOMP-InstanceID' HTTP header - POL5001"), + @ApiResponse(code = 400, message = "Missing X-ECOMP-InstanceID HTTP header - POL5001"), @ApiResponse(code = 401, message = "ECOMP component should authenticate itself and to re-send again HTTP request with its Basic Authentication credentials - POL5002"), @ApiResponse(code = 403, message = "ECOMP component is not authorized - POL5003"), @ApiResponse(code = 404, message = "Error: Requested '%1' (uuid) resource was not found - SVC4063"), diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ComponentServlet.java b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ComponentServlet.java index 92bc31f123..dff6cddbbb 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ComponentServlet.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ComponentServlet.java @@ -120,7 +120,7 @@ public class ComponentServlet extends BeGenericServlet { @Path("/{componentType}/{componentId}/requirmentsCapabilities") @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) - @ApiOperation(value = "Get Component Requirments And Capabilities", httpMethod = "GET", notes = "Returns Requirments And Capabilities according to componentId", response = Resource.class) + @ApiOperation(value = "Get Component Requirments And Capabilities", httpMethod = "GET", notes = "Returns Requirements And Capabilities according to componentId", response = Resource.class) @ApiResponses(value = { @ApiResponse(code = 200, message = "Component found"), @ApiResponse(code = 403, message = "Restricted operation"), @ApiResponse(code = 404, message = "Component not found") }) public Response getRequirementAndCapabilities(@PathParam("componentType") final String componentType, @PathParam("componentId") final String componentId, @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) { diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ElementServlet.java b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ElementServlet.java index da64dc58fb..4b2ff89ef8 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ElementServlet.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ElementServlet.java @@ -20,26 +20,8 @@ package org.openecomp.sdc.be.servlets; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.inject.Singleton; -import javax.servlet.ServletContext; -import javax.servlet.http.HttpServletRequest; -import javax.ws.rs.Consumes; -import javax.ws.rs.DELETE; -import javax.ws.rs.GET; -import javax.ws.rs.HeaderParam; -import javax.ws.rs.POST; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.Produces; -import javax.ws.rs.core.Context; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; - +import com.jcabi.aspects.Loggable; +import fj.data.Either; import org.openecomp.sdc.be.components.clean.ComponentsCleanBusinessLogic; import org.openecomp.sdc.be.components.impl.ElementBusinessLogic; import org.openecomp.sdc.be.config.BeEcompErrorManager; @@ -47,13 +29,9 @@ import org.openecomp.sdc.be.config.ConfigurationManager; import org.openecomp.sdc.be.dao.api.ActionStatus; import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum; +import org.openecomp.sdc.be.datatypes.enums.OriginTypeEnum; import org.openecomp.sdc.be.info.ArtifactTypesInfo; -import org.openecomp.sdc.be.model.ArtifactType; -import org.openecomp.sdc.be.model.Category; -import org.openecomp.sdc.be.model.Component; -import org.openecomp.sdc.be.model.PropertyScope; -import org.openecomp.sdc.be.model.Tag; -import org.openecomp.sdc.be.model.User; +import org.openecomp.sdc.be.model.*; import org.openecomp.sdc.be.model.category.CategoryDefinition; import org.openecomp.sdc.be.model.category.GroupingDefinition; import org.openecomp.sdc.be.model.category.SubCategoryDefinition; @@ -65,14 +43,20 @@ import org.openecomp.sdc.exception.ResponseFormat; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.jcabi.aspects.Loggable; +import javax.inject.Singleton; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; import io.swagger.annotations.ApiResponse; import io.swagger.annotations.ApiResponses; -import fj.data.Either; +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.*; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import java.util.*; @Path("/v1/") @@ -552,14 +536,14 @@ public class ElementServlet extends BeGenericServlet { @ApiOperation(value = "Retrieve catalog resources and services", httpMethod = "GET", notes = "Retrieve catalog resources and services", response = User.class) @ApiResponses(value = { @ApiResponse(code = 200, message = "Returns resources and services Ok"), @ApiResponse(code = 404, message = "No resources and services were found"), @ApiResponse(code = 404, message = "User not found"), @ApiResponse(code = 500, message = "Internal Server Error") }) - public Response getCatalogComponents(@Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) { + public Response getCatalogComponents(@Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId, @QueryParam("excludeTypes") List excludeTypes) { Response res = null; try { String url = request.getMethod() + " " + request.getRequestURI(); log.debug("Start handle request of {}", url); - Either>, ResponseFormat> catalogData = getElementBL(request.getSession().getServletContext()).getCatalogComponents(userId); + Either>, ResponseFormat> catalogData = getElementBL(request.getSession().getServletContext()).getCatalogComponents(userId, excludeTypes); if (catalogData.isRight()) { log.debug("failed to get catalog data"); diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/GroupServlet.java b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/GroupServlet.java index 04081bac30..f7e7ae2da1 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/GroupServlet.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/GroupServlet.java @@ -153,7 +153,7 @@ public class GroupServlet extends AbstractValidationsServlet { // Update GroupDefinition ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(containerComponentType); Either actionResponse = businessLogic - .validateAndUpdateGroupMetadata(componentId, user, componentTypeEnum, updatedGroup, true); + .validateAndUpdateGroupMetadata(componentId, user, componentTypeEnum, updatedGroup, true ,true); if (actionResponse.isRight()) { log.debug("failed to update GroupDefinition"); diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CsarUtils.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CsarUtils.java index fb87e34de7..b70dae68e8 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CsarUtils.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CsarUtils.java @@ -75,8 +75,10 @@ import org.openecomp.sdc.be.model.operations.impl.LifecycleOperation; import org.openecomp.sdc.be.resources.data.ESArtifactData; import org.openecomp.sdc.be.resources.data.SdcSchemaFilesData; import org.openecomp.sdc.be.tosca.model.ToscaTemplate; +import org.openecomp.sdc.be.utils.CommonBeUtils; import org.openecomp.sdc.common.api.ArtifactGroupTypeEnum; import org.openecomp.sdc.common.api.ArtifactTypeEnum; +import org.openecomp.sdc.common.api.Constants; import org.openecomp.sdc.common.impl.ExternalConfiguration; import org.openecomp.sdc.common.util.GeneralUtility; import org.openecomp.sdc.common.util.ValidationUtils; @@ -146,9 +148,14 @@ public class CsarUtils { "([\\w\\_\\-\\.\\s]+)(/)" + // Artifact Type "([\\w\\_\\-\\.\\s]+)(/)" + - // Artifact File Name - "([\\w\\_\\-\\.\\s]+)"; - public static final String ARTIFACT_CREATED_FROM_CSAR = "Artifact created from csar"; + // Artifact Any File Name + ".+"; + public static final String VALID_ENGLISH_ARTIFACT_NAME = "([\\w\\_\\-\\.\\s]+)"; + public static final String SERVICE_TEMPLATE_PATH_PATTERN = Constants.SERVICE_TEMPLATES_CONTAINING_FOLDER + + // Service Template File Name + "([\\w\\_\\-\\.\\s]+)"; + + public static final String ARTIFACT_CREATED_FROM_CSAR = "Artifact created from csar"; public CsarUtils() { if(SDC_VERSION != null && !SDC_VERSION.isEmpty()){ @@ -281,8 +288,8 @@ public class CsarUtils { dependencies = dependenciesRes.left().value().getDependencies(); } - //UID - Map> innerComponentsCache = new HashMap<>(); + //UID + Map> innerComponentsCache = new HashMap<>(); if (dependencies != null && !dependencies.isEmpty()) { for (Triple d : dependencies) { @@ -295,18 +302,16 @@ public class CsarUtils { return Either.right(responseFormat); } - //fill innerComponentsCache - fileName = d.getLeft(); - innerComponentsCache.put(childComponent.getUniqueId(), - new ImmutableTriple(cassandraId, fileName, childComponent)); - insertInnerComponentsToCache(innerComponentsCache, childComponent); - - byte[] content = entryData.left().value(); - generatorInputs.add(new ImmutablePair(childComponent, content)); - } + //fill innerComponentsCache + fileName = d.getLeft(); + addComponentToCache(innerComponentsCache, cassandraId, fileName, childComponent); + addInnerComponentsToCache(innerComponentsCache, childComponent); - //add inner components to CSAR - + byte[] content = entryData.left().value(); + generatorInputs.add(new ImmutablePair(childComponent, content)); + } + + //add inner components to CSAR for (Entry> innerComponentTripleEntry : innerComponentsCache.entrySet()) { ImmutableTriple innerComponentTriple = innerComponentTripleEntry.getValue(); @@ -418,7 +423,7 @@ public class CsarUtils { } - private void insertInnerComponentsToCache(Map> componentCache, + private void addInnerComponentsToCache(Map> componentCache, Component childComponent) { List instances = childComponent.getComponentInstances(); @@ -438,19 +443,32 @@ public class CsarUtils { ArtifactDefinition childArtifactDefinition = childToscaArtifacts.get(ToscaExportHandler.ASSET_TOSCA_TEMPLATE); if (childArtifactDefinition != null) { //add to cache - componentCache.put(ci.getComponentUid(), - new ImmutableTriple(childArtifactDefinition.getEsId(), - childArtifactDefinition.getArtifactName(), componentRI)); + addComponentToCache(componentCache, childArtifactDefinition.getEsId(), childArtifactDefinition.getArtifactName(), componentRI); } //if not atomic - insert inner components as well if(!ToscaUtils.isAtomicType(componentRI)) { - insertInnerComponentsToCache(componentCache, componentRI); + addInnerComponentsToCache(componentCache, componentRI); } } }); } } + + private void addComponentToCache(Map> componentCache, + String id, String fileName, Component component) { + + ImmutableTriple cachedComponent = componentCache.get(component.getInvariantUUID()); + if (cachedComponent == null || CommonBeUtils.compareAsdcComponentVersions(component.getVersion(), cachedComponent.getRight().getVersion())) { + componentCache.put(component.getInvariantUUID(), + new ImmutableTriple(id, fileName, component)); + + if(cachedComponent != null) { + //overwriting component with newer version + log.warn("Overwriting component invariantID {} of version {} with a newer version {}", id, cachedComponent.getRight().getVersion(), component.getVersion()); + } + } + } private Either writeComponentInterface(Component component, ZipOutputStream zip, String fileName) { try { diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/PropertyConvertor.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/PropertyConvertor.java index 0804ef1ed4..b8414367aa 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/PropertyConvertor.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/PropertyConvertor.java @@ -100,7 +100,7 @@ public class PropertyConvertor { eschema.setDescription(schema.getProperty().getDescription()); prop.setEntry_schema(eschema); } - log.debug("try to convert property {} from type {} with default value {}", property.getName(), property.getType(), property.getDefaultValue()); + log.trace("try to convert property {} from type {} with default value [{}]", property.getName(), property.getType(), property.getDefaultValue()); prop.setDefaultp(convertToToscaObject(property.getType(), property.getName(), property.getDefaultValue(), innerType, dataTypes)); prop.setType(property.getType()); prop.setDescription(property.getDescription()); @@ -112,45 +112,46 @@ public class PropertyConvertor { } public Object convertToToscaObject(String propertyType, String propertyName, String value, String innerType, Map dataTypes) { - log.debug("try to convert propertyType {} , value {}, innerType {}", propertyType, value, innerType); + log.trace("try to convert propertyType {} , value [{}], innerType {}", propertyType, value, innerType); if (value == null) { value = getDataTypeDefaultValue(propertyName, dataTypes.get(propertyType)); if(StringUtils.isEmpty(value)){ return null; } - } - - ToscaMapValueConverter mapConverterInst = ToscaMapValueConverter.getInstance(); - ToscaValueConverter innerConverter = null; - Boolean isScalar = true; - - ToscaPropertyType type = ToscaPropertyType.isValidType(propertyType); - if (type == null) { - log.debug("isn't prederfined type, get from all data types"); - DataTypeDefinition dataTypeDefinition = dataTypes.get(propertyType); - if (innerType == null) { - innerType = propertyType; - } - - if ((type = mapConverterInst.isScalarType(dataTypeDefinition)) != null) { - log.debug("This is scalar type. get suitable converter for type {}", type); - innerConverter = type.getValueConverter(); - } else { - isScalar = false; - } - } else { - ToscaPropertyType typeIfScalar = ToscaPropertyType.getTypeIfScalar(type.getType()); - if (typeIfScalar == null) { - isScalar = false; - } - innerConverter = type.getValueConverter(); - if (ToscaPropertyType.STRING.equals(type) && value.startsWith("/")) { - return innerConverter.convertToToscaValue(value, innerType, dataTypes); - } } - JsonElement jsonElement = null; try { + ToscaMapValueConverter mapConverterInst = ToscaMapValueConverter.getInstance(); + ToscaValueConverter innerConverter = null; + Boolean isScalar = true; + + ToscaPropertyType type = ToscaPropertyType.isValidType(propertyType); + if (type == null) { + log.trace("isn't prederfined type, get from all data types"); + DataTypeDefinition dataTypeDefinition = dataTypes.get(propertyType); + if (innerType == null) { + innerType = propertyType; + } + + if ((type = mapConverterInst.isScalarType(dataTypeDefinition)) != null) { + log.trace("This is scalar type. get suitable converter for type {}", type); + innerConverter = type.getValueConverter(); + } else { + isScalar = false; + } + } else { + ToscaPropertyType typeIfScalar = ToscaPropertyType.getTypeIfScalar(type.getType()); + if (typeIfScalar == null) { + isScalar = false; + } + + innerConverter = type.getValueConverter(); + if (ToscaPropertyType.STRING.equals(type) && value.startsWith("/")) { + return innerConverter.convertToToscaValue(value, innerType, dataTypes); + } + } + JsonElement jsonElement = null; + StringReader reader = new StringReader(value); JsonReader jsonReader = new JsonReader(reader); jsonReader.setLenient(true); @@ -162,11 +163,11 @@ public class PropertyConvertor { } if (jsonElement.isJsonPrimitive() && isScalar) { - log.debug("It's well defined type. convert it"); + log.trace("It's well defined type. convert it"); ToscaValueConverter converter = type.getValueConverter(); return converter.convertToToscaValue(value, innerType, dataTypes); } else { - log.debug("It's data type or inputs in primitive type. convert as map"); + log.trace("It's data type or inputs in primitive type. convert as map"); Object convertedValue; if (innerConverter != null && (ToscaPropertyType.MAP.equals(type) || ToscaPropertyType.LIST.equals(type))) { convertedValue = innerConverter.convertToToscaValue(value, innerType, dataTypes); @@ -185,7 +186,7 @@ public class PropertyConvertor { return convertedValue; } - } catch (JsonSyntaxException e) { + } catch (Exception e) { log.debug("convertToToscaValue failed to parse json value :", e); return null; } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportHandler.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportHandler.java index d6f87967ca..9fdd2d3b0f 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportHandler.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportHandler.java @@ -333,10 +333,13 @@ public class ToscaExportHandler { toscaMetadata.setSubcategory(categoryDefinition.getSubcategories().get(0).getName()); toscaMetadata.setResourceVendor(resource.getVendorName()); toscaMetadata.setResourceVendorRelease(resource.getVendorRelease()); - + toscaMetadata.setResourceVendorModelNumber(resource.getResourceVendorModelNumber()); break; case SERVICE: + Service service = (Service) component; toscaMetadata.setType(component.getComponentType().getValue()); + toscaMetadata.setServiceType(service.getServiceType()); + toscaMetadata.setServiceRole(service.getServiceRole()); if (!isInstance) { // DE268546 toscaMetadata.setServiceEcompNaming(((Service)component).isEcompGeneratedNaming()); @@ -747,8 +750,9 @@ public class ToscaExportHandler { toscaMetadata = new VfModuleToscaMetadata(); Map properties = fillGroupProperties(props.get()); - - properties.put(VF_MODULE_DESC_KEY, description.get()); + if(!properties.containsKey(VF_MODULE_DESC_KEY) || StringUtils.isEmpty((String) properties.get(VF_MODULE_DESC_KEY))){ + properties.put(VF_MODULE_DESC_KEY, description.get()); + } toscaGroup.setProperties(properties); } toscaMetadata.setName(groupName.get()); diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaMetadata.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaMetadata.java index 6573313dbb..604a52083b 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaMetadata.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaMetadata.java @@ -32,6 +32,9 @@ public class ToscaMetadata implements IToscaMetadata { private String subcategory; private String resourceVendor; private String resourceVendorRelease; + private String resourceVendorModelNumber; + private String serviceType; + private String serviceRole; private Boolean serviceEcompNaming; private Boolean ecompGeneratedNaming; private String namingPolicy; @@ -110,6 +113,30 @@ public class ToscaMetadata implements IToscaMetadata { public void setResourceVendorRelease(String resourceVendorRelease) { this.resourceVendorRelease = resourceVendorRelease; } + + public String getResourceVendorModelNumber() { + return resourceVendorModelNumber; + } + + public void setResourceVendorModelNumber(String resourceVendorModelNumber) { + this.resourceVendorModelNumber = resourceVendorModelNumber; + } + + public String getServiceType() { + return serviceType; + } + + public void setServiceType(String serviceType) { + this.serviceType = serviceType; + } + + public String getServiceRole() { + return serviceRole; + } + + public void setServiceRole(String serviceRole) { + this.serviceRole = serviceRole; + } public Boolean isEcompGeneratedNaming() { return ecompGeneratedNaming; diff --git a/catalog-be/src/main/java/org/openecomp/sdc/common/transaction/mngr/RollbackManager.java b/catalog-be/src/main/java/org/openecomp/sdc/common/transaction/mngr/RollbackManager.java index 99e0da0116..7485a8dc43 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/common/transaction/mngr/RollbackManager.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/common/transaction/mngr/RollbackManager.java @@ -20,20 +20,20 @@ package org.openecomp.sdc.common.transaction.mngr; -import org.openecomp.sdc.common.transaction.api.RollbackHandler; -import org.openecomp.sdc.common.transaction.api.TransactionUtils.DBActionCodeEnum; -import org.openecomp.sdc.common.transaction.api.TransactionUtils.DBTypeEnum; -import org.openecomp.sdc.common.util.MethodActivationStatusEnum; - import fj.P; import fj.data.Either; import fj.data.HashMap; import fj.data.List; +import org.openecomp.sdc.common.transaction.api.RollbackHandler; +import org.openecomp.sdc.common.transaction.api.TransactionUtils.DBActionCodeEnum; +import org.openecomp.sdc.common.transaction.api.TransactionUtils.DBTypeEnum; +import org.openecomp.sdc.common.util.MethodActivationStatusEnum; + public class RollbackManager { private final HashMap rollbackHandlersMap; private final Integer transactionId; - private final String userId; + private final String userId; private final String actionType; RollbackManager(Integer transactionId, String userId, String actionType, Iterable rollbackHandlers) { @@ -83,5 +83,4 @@ public class RollbackManager { // by convention left is failure; in SDC right is failure return rollbackHandlersMap.get(dbType).toEither(MethodActivationStatusEnum.NOT_FOUND).swap(); } - } diff --git a/catalog-be/src/main/resources/config/SDC.zip b/catalog-be/src/main/resources/config/SDC.zip index 674f6f86b433619108eaccd6e1ab11fd2b36a156..6df1b13f2b55896612e21c689d926acaa1a1e9b2 100644 GIT binary patch literal 29275 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 Xq5t?({&9#T9No{a?fs9 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%0ActEsrd~; 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 diff --git a/catalog-be/src/main/resources/config/configuration.yaml b/catalog-be/src/main/resources/config/configuration.yaml index c9ebfd2e9f..bbb1969255 100644 --- a/catalog-be/src/main/resources/config/configuration.yaml +++ b/catalog-be/src/main/resources/config/configuration.yaml @@ -23,7 +23,7 @@ beSslPort: 8443 version: 1.0 released: 2012-11-30 -toscaConformanceLevel: 3.0 +toscaConformanceLevel: 4.0 minToscaConformanceLevel: 3.0 titanCfgFile: /home/vagrant/catalog-be/config/catalog-be/titan.properties @@ -41,7 +41,6 @@ esReconnectIntervalInSeconds: 3 uebHealthCheckReconnectIntervalInSeconds: 15 uebHealthCheckReadTimeout: 4 - # Protocols protocols: - http @@ -75,7 +74,7 @@ neo4j: cassandraConfig: cassandraHosts: ['localhost'] - localDataCenter: + localDataCenter: datacenter1 reconnectTimeout : 30000 authenticate: false username: koko @@ -87,6 +86,7 @@ cassandraConfig: - { name: sdcaudit, replicationStrategy: SimpleStrategy, replicationInfo: ['1']} - { name: sdcartifact, replicationStrategy: SimpleStrategy, replicationInfo: ['1']} - { name: sdccomponent, replicationStrategy: SimpleStrategy, replicationInfo: ['1']} + - { name: sdcrepository, replicationStrategy: SimpleStrategy, replicationInfo: ['1']} #Application-specific settings of ES elasticSearch: @@ -147,6 +147,7 @@ resourceTypes: &allResourceTypes - VF - VFCMT - Abstract + - CVFC # validForResourceTypes usage # validForResourceTypes: @@ -195,6 +196,8 @@ toscaArtifacts: #Informational artifacts placeHolder excludeResourceCategory: - Generic +excludeResourceType: + - PNF informationalResourceArtifacts: features: displayName: Features @@ -500,7 +503,15 @@ resourceInformationalArtifacts: validForResourceTypes: *allResourceTypes OTHER: acceptedTypes: - validForResourceTypes: *allResourceTypes + validForResourceTypes: + - VFC + - CVFC + - CP + - VL + - VF + - VFCMT + - Abstract + - PNF SNMP_POLL: acceptedTypes: validForResourceTypes: *allResourceTypes @@ -512,6 +523,7 @@ resourceInformationalArtifacts: validForResourceTypes: - VF - VFC + - CVFC resourceInformationalDeployedArtifacts: @@ -538,6 +550,7 @@ onboarding: host: localhost port: 8080 downloadCsarUri: "/onboarding-api/v1.0/vendor-software-products/packages" + healthCheckUri: "/onboarding-api/v1.0/healthcheck" switchoverDetector: gBeFqdn: AIO-BE.ecomp.idns.cip.com @@ -597,5 +610,7 @@ vfModuleProperties: genericAssetNodeTypes: VFC: org.openecomp.resource.abstract.nodes.VFC + CVFC: org.openecomp.resource.abstract.nodes.VFC VF : org.openecomp.resource.abstract.nodes.VF + PNF: org.openecomp.resource.abstract.nodes.PNF Service: org.openecomp.resource.abstract.nodes.service diff --git a/catalog-be/src/main/resources/config/error-configuration.yaml b/catalog-be/src/main/resources/config/error-configuration.yaml index 4985ab552a..62bd7206ba 100644 --- a/catalog-be/src/main/resources/config/error-configuration.yaml +++ b/catalog-be/src/main/resources/config/error-configuration.yaml @@ -12,103 +12,103 @@ errors: code: 204, message: "No Content" } -#--------POL4050----------------------------- +#--------POL4050----------------------------- NOT_ALLOWED: { code: 405, message: "Error: Method not allowed.", messageId: "POL4050" } -#--------POL5000----------------------------- +#--------POL5000----------------------------- GENERAL_ERROR: { code: 500, message: "Error: Internal Server Error. Please try again later.", messageId: "POL5000" } -#---------POL5001------------------------------ +#---------POL5001------------------------------ MISSING_X_ECOMP_INSTANCE_ID: { code: 400 , message: "Error: Missing 'X-ECOMP-InstanceID' HTTP header.", messageId: "POL5001" } -#---------POL5002------------------------------ +#---------POL5002------------------------------ AUTH_REQUIRED: { code: 401 , message: "Error: Authentication is required to use the API.", messageId: "POL5002" } -#---------POL5003------------------------------ +#---------POL5003------------------------------ AUTH_FAILED: { code: 403 , message: "Error: Not authorized to use the API.", messageId: "POL5003" } -#---------POL5004------------------------------ +#---------POL5004------------------------------ MISSING_USER_ID: { code: 400 , message: "Error: Missing 'USER_ID' HTTP header.", messageId: "POL5004" } -#---------SVC4000----------------------------- +#---------SVC4000----------------------------- INVALID_CONTENT: { code: 400, message: "Error: Invalid content.", messageId: "SVC4000" } -#---------SVC4002----------------------------- +#---------SVC4002----------------------------- MISSING_INFORMATION: { code: 403, message: "Error: Missing information.", messageId: "SVC4002" } -#---------SVC4003------------------------------ -# %1 - Users's ID +#---------SVC4003------------------------------ +# %1 - Users's ID USER_NOT_FOUND: { code: 404, message: "Error: User '%1' was not found.", messageId: "SVC4003" } -#---------SVC4004----------------------------- -# %1 - Users's email address +#---------SVC4004----------------------------- +# %1 - Users's email address INVALID_EMAIL_ADDRESS: { code: 400, message: "Error: Invalid email address '%1'.", messageId: "SVC4004" } -#---------SVC4005------------------------------ +#---------SVC4005------------------------------ # %1 - role INVALID_ROLE: { code: 400, message: "Error: Invalid role '%1'.", messageId: "SVC4005" } -#---------SVC4006------------------------------ -# %1 - Users's USER_ID +#---------SVC4006------------------------------ +# %1 - Users's USER_ID USER_ALREADY_EXIST: { code: 409, message: "Error: User with '%1' ID already exists.", messageId: "SVC4006" } -#---------SVC4007------------------------------ +#---------SVC4007------------------------------ DELETE_USER_ADMIN_CONFLICT: { code: 409, message: "Error: An administrator can only be deleted by another administrator.", messageId: "SVC4007" } -#---------SVC4008----------------------------- -# %1 - Users's userId +#---------SVC4008----------------------------- +# %1 - Users's userId INVALID_USER_ID: { code: 400, message: "Error: Invalid userId '%1'.", messageId: "SVC4008" } -#---------SVC4049------------------------------ +#---------SVC4049------------------------------ # %1 - service/resource COMPONENT_MISSING_CONTACT: { code: 400, message: "Error: Invalid Content. Missing %1 contact.", messageId: "SVC4049" - } -#---------SVC4050----------------------------- + } +#---------SVC4050----------------------------- # %1 - Service/Resource/Additional parameter # %2 - service/resource/label name COMPONENT_NAME_ALREADY_EXIST: { @@ -116,90 +116,90 @@ errors: message: "Error: %1 with name '%2' already exists.", messageId: "SVC4050" } -#---------SVC4051------------------------------ -# %1 - resource/service +#---------SVC4051------------------------------ +# %1 - resource/service COMPONENT_MISSING_CATEGORY: { code: 400, message: "Error: Invalid Content. Missing %1 category.", messageId: "SVC4051" } -#---------SVC4052------------------------------ +#---------SVC4052------------------------------ COMPONENT_MISSING_TAGS: { code: 400, message: "Error: Invalid Content. At least one tag has to be specified.", messageId: "SVC4052" } -#---------SVC4053------------------------------ +#---------SVC4053------------------------------ # %1 - service/resource COMPONENT_MISSING_DESCRIPTION: { code: 400, message: "Error: Invalid Content. Missing %1 description.", messageId: "SVC4053" } -#---------SVC4054------------------------------ +#---------SVC4054------------------------------ # %1 - resource/service COMPONENT_INVALID_CATEGORY: { code: 400, message: "Error: Invalid Content. Invalid %1 category.", messageId: "SVC4054" } -#---------SVC4055------------------------------ +#---------SVC4055------------------------------ MISSING_VENDOR_NAME: { code: 400, message: "Error: Invalid Content. Missing vendor name.", messageId: "SVC4055" } -#---------SVC4056------------------------------ +#---------SVC4056------------------------------ MISSING_VENDOR_RELEASE: { code: 400, message: "Error: Invalid Content. Missing vendor release.", messageId: "SVC4056" } -#---------SVC4057------------------------------ +#---------SVC4057------------------------------ MISSING_DERIVED_FROM_TEMPLATE: { code: 400, message: "Error: Invalid Content. Missing derived from template specification.", messageId: "SVC4057" } -#---------SVC4058------------------------------ +#---------SVC4058------------------------------ # %1 - service/resource COMPONENT_MISSING_ICON: { code: 400, message: "Error: Invalid Content. Missing %1 icon.", messageId: "SVC4058" } -#---------SVC4059------------------------------ +#---------SVC4059------------------------------ # %1 - service/resource COMPONENT_INVALID_ICON: { code: 400, message: "Error: Invalid Content. Invalid %1 icon.", messageId: "SVC4059" } -#---------SVC4060------------------------------ +#---------SVC4060------------------------------ PARENT_RESOURCE_NOT_FOUND: { code: 400, message: "Error: Invalid Content. Derived from resource template was not found.", messageId: "SVC4060" } -#---------SVC4061------------------------------ +#---------SVC4061------------------------------ MULTIPLE_PARENT_RESOURCE_FOUND: { code: 400, message: "Error: Invalid Content. Multiple derived from resource template is not allowed.", messageId: "SVC4061" } -#---------SVC4062------------------------------ +#---------SVC4062------------------------------ # %1 - service/resource MISSING_COMPONENT_NAME: { code: 400, message: "Error: Invalid Content. Missing %1 name.", messageId: "SVC4062" } -#---------SVC4063------------------------------ +#---------SVC4063------------------------------ #%1  -  resource/service name RESOURCE_NOT_FOUND: { code: 404, @@ -207,51 +207,51 @@ errors: messageId: "SVC4063" } -#---------SVC4064------------------------------ +#---------SVC4064------------------------------ # %1 - Service/Resource/Property COMPONENT_INVALID_DESCRIPTION: { code: 400, message: "Error: Invalid Content. %1 description contains non-english characters.", messageId: "SVC4064" } -#---------SVC4065------------------------------ +#---------SVC4065------------------------------ # %1 - Service/Resource/Property -# %2 - max resource/service name length +# %2 - max resource/service name length COMPONENT_DESCRIPTION_EXCEEDS_LIMIT: { code: 400, message: "Error: Invalid Content. %1 description exceeds limit of %2 characters.", messageId: "SVC4065" } -#---------SVC4066------------------------------ -# %1 - max length +#---------SVC4066------------------------------ +# %1 - max length COMPONENT_TAGS_EXCEED_LIMIT: { code: 400, message: "Error: Invalid Content. Tags overall length exceeds limit of %1 characters.", messageId: "SVC4066" } #---------SVC4067------------------------------ -# %1 - max length +# %1 - max length VENDOR_NAME_EXCEEDS_LIMIT: { code: 400, message: "Error: Invalid Content. Vendor name exceeds limit of %1 characters.", messageId: "SVC4067" } #---------SVC4068------------------------------ -# %1 - max length +# %1 - max length VENDOR_RELEASE_EXCEEDS_LIMIT: { code: 400, message: "Error: Invalid Content. Vendor release exceeds limit of %1 characters.", messageId: "SVC4068" } -#---------SVC4069------------------------------ +#---------SVC4069------------------------------ # %1 - Service/Resource/Product COMPONENT_INVALID_CONTACT: { code: 400, message: "Error: Invalid Content. %1 Contact Id should be in format 'mnnnnnn' or 'aannna' or 'aannnn', where m=m ,a=a-zA-Z and n=0-9", messageId: "SVC4069" } -#---------SVC4070------------------------------ +#---------SVC4070------------------------------ # %1 - Service/Resource INVALID_COMPONENT_NAME: { code: 400, @@ -259,27 +259,27 @@ errors: messageId: "SVC4070" } -#---------SVC4071------------------------------ +#---------SVC4071------------------------------ INVALID_VENDOR_NAME: { code: 400, message: 'Error: Invalid Content. Vendor name is not allowed to contain characters like <>:"\/|?* and space characters other than regular space.', messageId: "SVC4071" } -#---------SVC4072------------------------------ +#---------SVC4072------------------------------ INVALID_VENDOR_RELEASE: { code: 400, message: 'Error: Invalid Content. Vendor release is not allowed to contain characters like <>:"\/|?* and space characters other than regular space.', messageId: "SVC4072" } -#---------SVC4073------------------------------ +#---------SVC4073------------------------------ # %1 - Service/Resource -# %2 - max resource/service name +# %2 - max resource/service name COMPONENT_NAME_EXCEEDS_LIMIT: { code: 400, message: "Error: Invalid Content. %1 name exceeds limit of %2 characters.", messageId: "SVC4073" } -#---------SVC4080------------------------------ +#---------SVC4080------------------------------ # %1 - resource/service name # %2 - resource/service # %3 - First name of last modifier @@ -290,7 +290,7 @@ errors: message: "Error: Requested '%1' %2 is locked for modification by %3 %4(%5).", messageId: "SVC4080" } -#---------SVC4081----------------------------- +#---------SVC4081----------------------------- # %1 - resource/service name # %2 - resource/service # %3 - First name of last modifier @@ -302,7 +302,7 @@ errors: messageId: "SVC4081" } -#-----------SVC4082--------------------------- +#-----------SVC4082--------------------------- # %1 - resource/service name # %2 - resource/service # %3 - First name of last modifier @@ -392,7 +392,7 @@ errors: } #-----------SVC4102--------------------------- -# %1 - capability type name +# %1 - capability type name CAPABILITY_TYPE_ALREADY_EXIST: { code: 409, message: "Error: Capability Type with name '%1' already exists.", @@ -405,7 +405,7 @@ errors: messageId: "SVC4114" } #-----------SVC4115--------------------------- -# %1 - capability type name +# %1 - capability type name MISSING_CAPABILITY_TYPE: { code: 400, message: "Error: Invalid Content. Missing Capability Type '%1'.", @@ -483,7 +483,7 @@ errors: message: "Error: Artifact '%1' already exists.", messageId: "SVC4125" } -#---------SVC4126------------------------------ +#---------SVC4126------------------------------ # %1 - resource/service/product/... # %2 - field (tag, vendor name...) INVALID_FIELD_FORMAT: { @@ -518,7 +518,7 @@ errors: #-----------SVC4131--------------------------- # %1-resource/service # %2-srtifact/artifacts -# %3-semicolomn separated list of artifact +# %3-semicolomn separated list of artifact COMPONENT_MISSING_MANDATORY_ARTIFACTS: { code: 403, message: "Error: Missing mandatory informational %1 %2: [%3].", @@ -545,60 +545,60 @@ errors: message: "Error: Invalid Content. Missing interface life-cycle type.", messageId: "SVC4134" } -#---------SVC4135------------------------------ +#---------SVC4135------------------------------ SERVICE_CATEGORY_CANNOT_BE_CHANGED: { code: 400, message: "Error: Service category cannot be changed once the service is certified.", messageId: "SVC4135" } -#---------SVC4136------------------------------ -# %1 - distribution environment name +#---------SVC4136------------------------------ +# %1 - distribution environment name DISTRIBUTION_ENVIRONMENT_NOT_AVAILABLE: { code: 500, message: "Error: Requested distribution environment '%1' is not available.", messageId: "SVC4136" } -#---------SVC4137------------------------------ -# %1 - distribution environment name +#---------SVC4137------------------------------ +# %1 - distribution environment name DISTRIBUTION_ENVIRONMENT_NOT_FOUND: { code: 400, message: "Error: Requested distribution environment '%1' was not found.", messageId: "SVC4137" } -#---------SVC4138------------------------------ +#---------SVC4138------------------------------ DISTRIBUTION_ENVIRONMENT_INVALID: { code: 400, message: "Error: Invalid distribution environment.", messageId: "SVC4138" } -#---------SVC4139------------------------------ +#---------SVC4139------------------------------ # %1 - service name DISTRIBUTION_ARTIFACT_NOT_FOUND: { code: 409, message: "Error: Service '%1' cannot be distributed due to missing deployment artifacts.", messageId: "SVC4139" } -#---------SVC4200------------------------------ +#---------SVC4200------------------------------ # %1 - Service/Resource -# %2 - max icon name length +# %2 - max icon name length COMPONENT_ICON_EXCEEDS_LIMIT: { code: 400, message: "Error: Invalid Content. %1 icon name exceeds limit of %2 characters.", messageId: "SVC4200" } -#---------SVC4300------------------------------ +#---------SVC4300------------------------------ RESTRICTED_ACCESS: { code: 403, message: "Error: Restricted access.", messageId: "SVC4300" } -#---------SVC4301------------------------------ +#---------SVC4301------------------------------ RESTRICTED_OPERATION: { code: 409, message: "Error: Restricted operation.", messageId: "SVC4301" } -#---------SVC4500------------------------------ +#---------SVC4500------------------------------ MISSING_BODY: { code: 400 , message: "Error: Missing request body.", @@ -610,7 +610,7 @@ errors: message: "Error: Invalid Content. Missing mandatory parameter 'apiPublicKey'." , messageId: "SVC4501" } -#---------SVC4502------------------------------ +#---------SVC4502------------------------------ DISTRIBUTION_ENV_DOES_NOT_EXIST: { code: 400 , message: "Error: Invalid Body : Missing mandatory parameter 'distrEnvName'." , @@ -624,7 +624,7 @@ errors: messageId: "SVC4503" } -#---------SVC4504------------------------------ +#---------SVC4504------------------------------ # %1 - Service/Resource # %2 - service/resource version COMPONENT_VERSION_NOT_FOUND: { @@ -634,103 +634,103 @@ errors: } #-----------SVC4505--------------------------- #%1-artifact name - + ARTIFACT_NOT_FOUND: { code: 404, message: "Error: Artifact '%1' was not found.", messageId: "SVC4505" } -#---------SVC4506------------------------------ +#---------SVC4506------------------------------ MISSING_ENV_NAME: { code: 400 , message: "Error: Invalid Content. Missing mandatory parameter 'distrEnvName'.", messageId: "SVC4506" } -#---------SVC4507------------------------------ +#---------SVC4507------------------------------ COMPONENT_INVALID_TAGS_NO_COMP_NAME: { code: 400, message: "Error: Invalid Content. One of the tags should be the component name.", messageId: "SVC4507" } - -#---------SVC4508------------------------------ + +#---------SVC4508------------------------------ SERVICE_NAME_CANNOT_BE_CHANGED: { code: 400, message: "Error: Service name cannot be changed once the service is certified.", messageId: "SVC4508" } -#---------SVC4509------------------------------ +#---------SVC4509------------------------------ SERVICE_ICON_CANNOT_BE_CHANGED: { code: 400, message: "Error: Icon cannot be changed once the service is certified.", messageId: "SVC4509" } -#---------SVC4510------------------------------ +#---------SVC4510------------------------------ # %1 - icon name max length SERVICE_ICON_EXCEEDS_LIMIT: { code: 400, message: "Error: Invalid Content. Icon name exceeds limit of %1 characters.", messageId: "SVC4510" } -#---------SVC4511------------------------------ +#---------SVC4511------------------------------ DISTRIBUTION_REQUESTED_NOT_FOUND: { code: 404, message: "Error: Requested distribution was not found.", messageId: "SVC4511" } -#---------SVC4512------------------------------ +#---------SVC4512------------------------------ # %1 - Distribution ID DISTRIBUTION_REQUESTED_FAILED: { code: 403, message: "Error: Requested distribution '%1' failed.", messageId: "SVC4512" } -#---------SVC4513------------------------------ +#---------SVC4513------------------------------ RESOURCE_CATEGORY_CANNOT_BE_CHANGED: { code: 400, message: "Error: Resource category cannot be changed once the resource is certified.", messageId: "SVC4513" } -#---------SVC4514------------------------------ +#---------SVC4514------------------------------ RESOURCE_NAME_CANNOT_BE_CHANGED: { code: 400, message: "Error: Resource name cannot be changed once the resource is certified.", messageId: "SVC4514" } -#---------SVC4515------------------------------ +#---------SVC4515------------------------------ RESOURCE_ICON_CANNOT_BE_CHANGED: { code: 400, message: "Error: Icon cannot be changed once the resource is certified.", messageId: "SVC4515" } -#---------SVC4516------------------------------ +#---------SVC4516------------------------------ RESOURCE_VENDOR_NAME_CANNOT_BE_CHANGED: { code: 400, message: "Error: Vendor name cannot be changed once the resource is certified.", messageId: "SVC4516" } -#---------SVC4517------------------------------ +#---------SVC4517------------------------------ RESOURCE_DERIVED_FROM_CANNOT_BE_CHANGED: { code: 400, message: "Error: Derived from resource template cannot be changed once the resource is certified.", messageId: "SVC4517" } -#---------SVC4518------------------------------ -# %1 - max length +#---------SVC4518------------------------------ +# %1 - max length COMPONENT_SINGLE_TAG_EXCEED_LIMIT: { code: 400, message: "Error: Invalid Content. Single tag exceeds limit of %1 characters.", messageId: "SVC4518" } -#---------SVC4519------------------------------ +#---------SVC4519------------------------------ INVALID_DEFAULT_VALUE: { code: 400, message: "Error: mismatch in data-type occurred for property %1. data type is %2 and default value found is %3.", messageId: "SVC4519" } -#---------SVC4520------------------------------ -# %1 - service or resource +#---------SVC4520------------------------------ +# %1 - service or resource ADDITIONAL_INFORMATION_MAX_NUMBER_REACHED: { code: 409, message: "Error: Maximal number of additional %1 parameters was reached.", @@ -742,7 +742,7 @@ errors: message: "Error: Invalid Content. The Additional information label and value cannot be empty.", messageId: "SVC4521" } -#---------SVC4522------------------------------ +#---------SVC4522------------------------------ # %1 - label/value # %2 - Maximal length of %1 ADDITIONAL_INFORMATION_EXCEEDS_LIMIT: { @@ -762,32 +762,32 @@ errors: message: "Error: Requested additional information was not found.", messageId: "SVC4524" } -#---------SVC4525------------------------------ +#---------SVC4525------------------------------ ADDITIONAL_INFORMATION_VALUE_NOT_ALLOWED_CHARACTERS: { code: 400, message: 'Error: Invalid Content. Additional information contains non-english characters.', messageId: "SVC4525" } -#---------SVC4526------------------------------ +#---------SVC4526------------------------------ RESOURCE_INSTANCE_NOT_FOUND: { code: 404, message: "Error: Requested '%1' resource instance was not found.", messageId: "SVC4526" } -#---------SVC4527------------------------------ +#---------SVC4527------------------------------ ASDC_VERSION_NOT_FOUND: { code: 500, message: 'Error: ASDC version cannot be displayed.', messageId: "SVC4527" } -#---------SVC4528------------------------------ +#---------SVC4528------------------------------ # %1-artifact url/artifact label/artifact description/VNF Service Indicator MISSING_DATA: { code: 400, message: "Error: Invalid content. Missing %1.", messageId: "SVC4528" } -#---------SVC4529------------------------------ +#---------SVC4529------------------------------ # %1-artifact url/artifact label/artifact description/artifact name # %2 - Maximal length of %1 EXCEEDS_LIMIT: { @@ -795,51 +795,51 @@ errors: message: "Error: Invalid Content. %1 exceeds limit of %2 characters.", messageId: "SVC4529" } -#---------SVC4530------------------------------ +#---------SVC4530------------------------------ ARTIFACT_INVALID_TIMEOUT: { code: 400, message: "Error: Invalid Content. Artifact Timeout should be set to valid positive non-zero number of minutes.", messageId: "SVC4530" } -#---------SVC4531------------------------------ +#---------SVC4531------------------------------ SERVICE_IS_VNF_CANNOT_BE_CHANGED: { code: 400, message: "Error: VNF Indicator cannot be updated for certified service.", messageId: "SVC4531" } - #---------SVC4532------------------------------ + #---------SVC4532------------------------------ RESOURCE_INSTANCE_NOT_FOUND_ON_SERVICE: { code: 404, message: "Error: Requested '%1' resource instance was not found on the service '%2.", messageId: "SVC4532" } - #---------SVC4533------------------------------ - # %1 - "HEAT"/"HEAT_ENV"/"MURANO_PKG"/"YANG_XML" + #---------SVC4533------------------------------ + # %1 - "HEAT"/"HEAT_ENV"/"MURANO_PKG"/"YANG_XML" WRONG_ARTIFACT_FILE_EXTENSION: { code: 400, message: "Error: Invalid file extension for %1 artifact type.", messageId: "SVC4533" } -#---------SVC4534------------------------------ -# %1 - "HEAT"/"HEAT_ENV" +#---------SVC4534------------------------------ +# %1 - "HEAT"/"HEAT_ENV" INVALID_YAML: { code: 400, message: "Error: Uploaded YAML file for %1 artifact is invalid.", messageId: "SVC4534" } -#---------SVC4535------------------------------ -# %1 - "HEAT" +#---------SVC4535------------------------------ +# %1 - "HEAT" INVALID_DEPLOYMENT_ARTIFACT_HEAT: { code: 400, message: "Error: Invalid %1 artifact.", messageId: "SVC4535" } -#---------SVC4536------------------------------ +#---------SVC4536------------------------------ # %1 - "Resource"/"Service" -# %2 - resource/service name -# %3 - "HEAT"/"HEAT_ENV"/"MURANO_PKG" +# %2 - resource/service name +# %3 - "HEAT"/"HEAT_ENV"/"MURANO_PKG" # %4 - "HEAT"/"HEAT_ENV"/"MURANO_PKG DEPLOYMENT_ARTIFACT_OF_TYPE_ALREADY_EXISTS: { code: 400, @@ -847,80 +847,80 @@ errors: messageId: "SVC4536" } -#---------SVC4537------------------------------ +#---------SVC4537------------------------------ MISSING_HEAT: { code: 400, message: "Error: Missing HEAT artifact. HEAT_ENV artifact cannot be uploaded without corresponding HEAT template.", messageId: "SVC4537" } -#---------SVC4538------------------------------ +#---------SVC4538------------------------------ MISMATCH_HEAT_VS_HEAT_ENV: { code: 400, message: "Error: Invalid artifact content. Parameter's set in HEAT_ENV '%1' artifact doesn't match the parameters in HEAT '%2' artifact.", messageId: "SVC4538" } -#---------SVC4539------------------------------ +#---------SVC4539------------------------------ INVALID_RESOURCE_PAYLOAD: { code: 400, message: "Error: Invalid resource payload.", messageId: "SVC4539" } -#---------SVC4540------------------------------ +#---------SVC4540------------------------------ INVALID_TOSCA_FILE_EXTENSION: { code: 400, message: "Error: Invalid file extension for TOSCA template.", messageId: "SVC4540" } -#---------SVC4541------------------------------ +#---------SVC4541------------------------------ INVALID_YAML_FILE: { code: 400, message: "Error: Invalid YAML file.", messageId: "SVC4541" } -#---------SVC4542------------------------------ +#---------SVC4542------------------------------ INVALID_TOSCA_TEMPLATE: { code: 400, message: "Error: Invalid TOSCA template.", messageId: "SVC4542" } -#---------SVC4543------------------------------ +#---------SVC4543------------------------------ NOT_RESOURCE_TOSCA_TEMPLATE: { code: 400, message: "Error: Imported Service TOSCA template.", messageId: "SVC4543" } -#---------SVC4544------------------------------ +#---------SVC4544------------------------------ NOT_SINGLE_RESOURCE: { code: 400, message: "Error: Imported TOSCA template should contain one resource definition.", messageId: "SVC4544" } -#---------SVC4545------------------------------ +#---------SVC4545------------------------------ INVALID_RESOURCE_NAMESPACE: { code: 400, message: "Error: Invalid resource namespace.", messageId: "SVC4545" } -#---------SVC4546------------------------------ +#---------SVC4546------------------------------ RESOURCE_ALREADY_EXISTS: { code: 400, message: "Error: Imported resource already exists in ASDC Catalog.", messageId: "SVC4546" } -#---------SVC4549------------------------------ +#---------SVC4549------------------------------ INVALID_RESOURCE_CHECKSUM: { code: 400, message: "Error: Invalid resource checksum.", messageId: "SVC4549" } -#---------SVC4550------------------------------ +#---------SVC4550------------------------------ #%1  -  Consumer salt INVALID_LENGTH: { code: 400, message: "Error: Invalid %1 length.", messageId: "SVC4550" } - #---------SVC4551------------------------------ + #---------SVC4551------------------------------ #%1  -  ECOMP User name ECOMP_USER_NOT_FOUND: { code: 404, @@ -934,13 +934,13 @@ errors: messageId: "SVC4552" } #---------SVC4553----------------------------- - #%1  -  Consumer name / Consumer password/ Consumer salt + #%1  -  Consumer name / Consumer password/ Consumer salt INVALID_CONTENT_PARAM: { code: 400, message: "Error: %1 is invalid.", messageId: "SVC4553" } - #---------SVC4554------------------------------ + #---------SVC4554------------------------------ # %1 - "Resource"/"Service" COMPONENT_ARTIFACT_NOT_FOUND: { code: 404, @@ -954,7 +954,7 @@ errors: message: "Error: Requested '%1' service is not ready for certification. Service has to have at least one deployment artifact.", messageId: "SVC4554" } -#---------SVC4555------------------------------ +#---------SVC4555------------------------------ #%1 - "Resource"/"Service"/"Product" #%2 - "category" COMPONENT_ELEMENT_INVALID_NAME_LENGTH: { @@ -962,7 +962,7 @@ errors: message: "Error: Invalid %1 %2 name length.", messageId: "SVC4555" } -#---------SVC4556------------------------------ +#---------SVC4556------------------------------ #%1 - "Resource"/"Service"/"Product" #%2 - "category" COMPONENT_ELEMENT_INVALID_NAME_FORMAT: { @@ -970,7 +970,7 @@ errors: message: "Error: Invalid %1 %2 name format.", messageId: "SVC4556" } -#---------SVC4557------------------------------ +#---------SVC4557------------------------------ #%1 - "Resource"/"Service"/"Product" #%2 - "category name" COMPONENT_CATEGORY_ALREADY_EXISTS: { @@ -1001,7 +1001,7 @@ errors: code: 403, message: "Error: Submit for Testing is not permitted as your '%1' includes non-validated '%2' resource. Please use one of available validated resource versions.", messageId: "SVC4560" - } + } #---------SVC4561------------------------------ # %1 - "resource"/"product" # %2 - "category" @@ -1029,108 +1029,108 @@ errors: message: "Error: %1 grouping '%2' already exists under '%3' sub-category.", messageId: "SVC4563" } -#---------SVC4564------------------------------ +#---------SVC4564------------------------------ # %1 - product name PRODUCT_NOT_FOUND: { code: 404, message: "Error: Requested '%1' product was not found.", messageId: "SVC4564" } -#---------SVC4565------------------------------ -# %1 - "HEAT" -# %2 - parameter type ("string" , "boolean" , "number") +#---------SVC4565------------------------------ +# %1 - "HEAT" +# %2 - parameter type ("string" , "boolean" , "number") # %3 - parameter name INVALID_HEAT_PARAMETER_VALUE: { code: 400, message: "Error: Invalid %1 artifact. Invalid %2 value set for '%3' parameter.", messageId: "SVC4565" } -#---------SVC4566------------------------------ -# %1 - "HEAT" -# %2 - parameter type ("string" , "boolean" , "number") +#---------SVC4566------------------------------ +# %1 - "HEAT" +# %2 - parameter type ("string" , "boolean" , "number") INVALID_HEAT_PARAMETER_TYPE: { code: 400, message: "Error: Invalid %1 artifact. Unsupported '%2' parameter type.", messageId: "SVC4566" } -#---------SVC4567------------------------------ -# %1 - "YANG_XML" +#---------SVC4567------------------------------ +# %1 - "YANG_XML" INVALID_XML: { code: 400, message: "Error: Uploaded XML file for %1 artifact is invalid.", messageId: "SVC4567" } -#---------SVC4567------------------------------ -# %1 - "User Name and UserId" +#---------SVC4567------------------------------ +# %1 - "User Name and UserId" # %2 -"checked-out"/"in-certification" CANNOT_DELETE_USER_WITH_ACTIVE_ELEMENTS: { code: 409, message: "Error: User cannot be deleted. User '%1' has %2 projects.", messageId: "SVC4567" } -#---------SVC4568------------------------------ -# %1 - "User Name and UserId" +#---------SVC4568------------------------------ +# %1 - "User Name and UserId" # %2 -"checked-out"/"in-certification" CANNOT_UPDATE_USER_WITH_ACTIVE_ELEMENTS: { code: 409, message: "Error: Role cannot be changed. User '%1' has %2 projects.", messageId: "SVC4568" } -#---------SVC4570------------------------------ +#---------SVC4570------------------------------ UPDATE_USER_ADMIN_CONFLICT: { code: 409, message: "Error: An administrator is not allowed to change his/her role.", messageId: "SVC4570" } -#---------SVC4571------------------------------ +#---------SVC4571------------------------------ SERVICE_CANNOT_CONTAIN_SUBCATEGORY: { code: 400, message: "Error: Sub category cannot be defined for service", messageId: "SVC4571" } -#---------SVC4572------------------------------ +#---------SVC4572------------------------------ # %1 - "Resource"/"Service" COMPONENT_TOO_MUCH_CATEGORIES: { code: 400, message: "Error: %1 must have only 1 category", messageId: "SVC4572" } -#---------SVC4574------------------------------ +#---------SVC4574------------------------------ RESOURCE_TOO_MUCH_SUBCATEGORIES: { code: 400, message: "Error: Resource must have only 1 sub category", messageId: "SVC4574" } -#---------SVC4575------------------------------ +#---------SVC4575------------------------------ COMPONENT_MISSING_SUBCATEGORY: { code: 400, message: "Error: Missing sub category", messageId: "SVC4575" } - #---------SVC4576------------------------------ + #---------SVC4576------------------------------ # %1 - "component type" UNSUPPORTED_ERROR: { code: 400, message: "Error : Requested component type %1 is unsupported.", messageId: "SVC4576" } - #---------SVC4577------------------------------ + #---------SVC4577------------------------------ # %1 - "resource type" RESOURCE_CANNOT_CONTAIN_RESOURCE_INSTANCES: { code: 409, message: "Error : Resource of type %1 cannot contain resource instances.", messageId: "SVC4577" } -#---------SVC4578------------------------------ +#---------SVC4578------------------------------ # %1 - "Resource"/"Service" -# %2 - resource/service name -# %3 - "artifact name" +# %2 - resource/service name +# %3 - "artifact name" DEPLOYMENT_ARTIFACT_NAME_ALREADY_EXISTS: { code: 400, message: "Error: %1 '%2' already has a deployment artifact named '%3'.", messageId: "SVC4578" } -#---------SVC4579------------------------------ +#---------SVC4579------------------------------ # %1 - "Category"/"Sub-Category"/"Group" # %2 - category/sub-category/grouping name. INVALID_GROUP_ASSOCIATION: { @@ -1138,27 +1138,27 @@ errors: message: "Error: Invalid group association. %1 '%2' was not found.", messageId: "SVC4579" } -#---------SVC4580------------------------------ +#---------SVC4580------------------------------ EMPTY_PRODUCT_CONTACTS_LIST: { code: 400, message: "Error: Invalid content. At least one Product Contact has to be specified.", messageId: "SVC4580" } -#---------SVC4581------------------------------ +#---------SVC4581------------------------------ # %1 - UserId INVALID_PRODUCT_CONTACT: { code: 400, message: "Error: Invalid content. User '%1' cannot be set as Product Contact.", messageId: "SVC4581" } -#---------SVC4582------------------------------ +#---------SVC4582------------------------------ # %1 - Product # %2 - "abbreviated"/"full" MISSING_ONE_OF_COMPONENT_NAMES: { code: 400, message: "Error: Invalid content. Missing %1 %2 name.", messageId: "SVC4582" - } + } #---------SVC4583------------------------------ # %1 - "Icon" # %2 - "resource"/"service"/"product" @@ -1168,10 +1168,10 @@ errors: messageId: "SVC4583" } #---------SVC4584------------------------------ -# %1 - service/VF name +# %1 - service/VF name # %2 - "service" /"VF" # %3 - resource instance origin type -# %4 - resource instance name +# %4 - resource instance name # %5 - requirement/capability # %6 - requirement/capability name # %7 - "fulfilled" (for req)/"consumed (for cap)" @@ -1180,57 +1180,57 @@ errors: message: "Error: Requested '%1' %2 is not ready for certification. %3 '%4' has to have %5 '%6' %7.", messageId: "SVC4584" } -#---------SVC4585------------------------------ +#---------SVC4585------------------------------ INVALID_OCCURRENCES: { code: 400, message: "Error: Invalid occurrences format.", messageId: "SVC4585" } -#---------SVC4586------------------------------ -#---------SVC4586------------------------------ +#---------SVC4586------------------------------ +#---------SVC4586------------------------------ INVALID_SERVICE_API_URL: { code: 400, message: 'Error: Invalid Service API URL. Please check whether your URL has a valid domain extension and does not contain the following characters - #?&@%+;,=$<>~^`\[]{}|"*!', messageId: "SVC4586" } -#---------SVC4587------------------------------ -# %1 - Data type name +#---------SVC4587------------------------------ +# %1 - Data type name DATA_TYPE_ALREADY_EXIST: { code: 409, message: 'Error: Data type %1 already exists.', messageId: "SVC4587" } -#---------SVC4588------------------------------ -# %1 - Data type name +#---------SVC4588------------------------------ +# %1 - Data type name DATA_TYPE_NOR_PROPERTIES_NEITHER_DERIVED_FROM: { code: 400, message: 'Error: Invalid Data type %1. Data type must have either a valid derived from declaration or at least one valid property', messageId: "SVC4588" } -#---------SVC4589------------------------------ -# %1 - Data type name +#---------SVC4589------------------------------ +# %1 - Data type name DATA_TYPE_PROPERTIES_CANNOT_BE_EMPTY: { code: 400, message: "Error: Invalid Data type %1. 'properties' parameter cannot be empty if provided.", messageId: "SVC4589" } -#---------SVC4590------------------------------ -# %1 - Property type name +#---------SVC4590------------------------------ +# %1 - Property type name # %2 - Property name INVALID_PROPERTY_TYPE: { code: 400, message: "Error: Invalid Property type %1 in property %2.", messageId: "SVC4590" } -#---------SVC4591------------------------------ +#---------SVC4591------------------------------ # %1 - Property inner type -# %2 - Property name +# %2 - Property name INVALID_PROPERTY_INNER_TYPE: { code: 400, message: "Error: Invalid property inner type %1, in property %2", messageId: "SVC4591" } -#---------SVC4592------------------------------ +#---------SVC4592------------------------------ # %1 - component instance name # %2 - "resource instance"/"service instance" COMPONENT_INSTANCE_NOT_FOUND: { @@ -1238,11 +1238,11 @@ errors: message: "Error: Requested '%1' %2 was not found.", messageId: "SVC4592" } -#---------SVC4593------------------------------ +#---------SVC4593------------------------------ # %1 - component instance name # %2 - "resource instance"/"service instance" # %3 - "resource/"service"/"product" -# %4 - container name +# %4 - container name COMPONENT_INSTANCE_NOT_FOUND_ON_CONTAINER: { code: 404, message: "Error: Requested '%1' %2 was not found on the %3 '%4'.", @@ -1259,20 +1259,20 @@ errors: #---------SVC4595------------------------------ #%1 - requirement / capability #%2 - requirement name -#%3 - parent containing the requirement +#%3 - parent containing the requirement IMPORT_REQ_CAP_NAME_EXISTS_IN_DERIVED: { code: 400, message: "Error: Imported TOSCA template contains %1 '%2' that is already defined by derived template %3.", messageId: "SVC4595" } -#---------SVC4596------------------------------ +#---------SVC4596------------------------------ # %1 - Data type name DATA_TYPE_DERIVED_IS_MISSING: { code: 400, message: "Error: Invalid Content. The ancestor data type %1 cannot be found in the system.", messageId: "SVC4596" } -#---------SVC4597------------------------------ +#---------SVC4597------------------------------ # %1 - Data type name # %2 - Property names DATA_TYPE_PROPERTY_ALREADY_DEFINED_IN_ANCESTOR: { @@ -1280,14 +1280,14 @@ errors: message: "Error: Invalid Content. The data type %1 contains properties named %2 which are already defined in one of its ancestors.", messageId: "SVC4597" } -#---------SVC4598------------------------------ +#---------SVC4598------------------------------ # %1 - Data type name DATA_TYPE_DUPLICATE_PROPERTY: { code: 400, message: "Error: Invalid Content. The data type %1 contains duplicate property.", messageId: "SVC4598" } -#---------SVC4599------------------------------ +#---------SVC4599------------------------------ # %1 - Data type name # %2 - Property names DATA_TYPE_PROEPRTY_CANNOT_HAVE_SAME_TYPE_OF_DATA_TYPE: { @@ -1295,14 +1295,14 @@ errors: message: "Error: Invalid Content. The data type %1 contains properties %2 which their type is this data type.", messageId: "SVC4599" } -#---------SVC4600------------------------------ +#---------SVC4600------------------------------ # %1 - Data type name DATA_TYPE_CANNOT_HAVE_PROPERTIES: { code: 400, message: "Error: Invalid Content. The data type %1 cannot have properties since it is of type scalar", messageId: "SVC4600" } -#---------SVC4601------------------------------ +#---------SVC4601------------------------------ NOT_TOPOLOGY_TOSCA_TEMPLATE: { code: 400, message: "Error: TOSCA yaml file %1 cannot be modeled to VF as it does not contain 'topology_template.", @@ -1317,7 +1317,7 @@ errors: message: "Error: TOSCA yaml file '%1' contains node_template '%2' of type '%3' that does not represent existing VFC/CP/VL", messageId: "SVC4602" } -#---------SVC4603------------------------------ +#---------SVC4603------------------------------ # %1 - component type # %2 - component name # %3 - state @@ -1326,21 +1326,21 @@ errors: message: "Error: Component instance of %1 can not be created because the component '%2' is in an illegal state %3.", messageId: "SVC4603" } -#---------SVC4604------------------------------ +#---------SVC4604------------------------------ # %1 - csar file name CSAR_INVALID: { code: 400, message: "Error: TOSCA CSAR '%1' is invalid. 'TOSCA-Metadata/Tosca.meta' file must be provided.", messageId: "SVC4604" } -#---------SVC4605------------------------------ +#---------SVC4605------------------------------ # %1 - csar file name CSAR_INVALID_FORMAT: { code: 400, message: "Error: TOSCA CSAR '%1' is invalid. Invalid 'TOSCA-Metadata/Tosca.meta' file format.", messageId: "SVC4605" } -#---------SVC4606------------------------------ +#---------SVC4606------------------------------ # %1 - property name # %2 - property type # %3 - property innerType @@ -1350,14 +1350,14 @@ errors: message: "Error: Invalid default value of property %1. Data type is %2 with inner type %3 and default value found is %4.", messageId: "SVC4606" } -#---------SVC4607------------------------------ +#---------SVC4607------------------------------ # %1 - csar file name CSAR_NOT_FOUND: { code: 400, message: "Error: TOSCA CSAR '%1' is not found.", messageId: "SVC4607" } -#---------SVC4608------------------------------ +#---------SVC4608------------------------------ # %1 - artifact name # %2 - component type # %3 - actual component type @@ -1367,14 +1367,14 @@ errors: messageId: "SVC4608" } -#---------SVC4609------------------------------ -# %1 - "INVALID_JSON" +#---------SVC4609------------------------------ +# %1 - "INVALID_JSON" INVALID_JSON: { code: 400, message: "Error: Uploaded JSON file for %1 artifact is invalid.", messageId: "SVC4609" } -#---------SVC4610------------------------------ +#---------SVC4610------------------------------ # %1 - csar file name # %2 - missing file name YAML_NOT_FOUND_IN_CSAR: { @@ -1382,21 +1382,21 @@ errors: message: "Error - TOSCA CSAR %1 is invalid. TOSCA-Metadata/Tosca.meta refers to file %2 that is not provided.", messageId: "SVC4610" } -#---------SVC4611------------------------------ +#---------SVC4611------------------------------ # %1 - group name GROUP_MEMBER_EMPTY: { code: 400, message: "Error: Invalid Content. Group %1 member list was provided but does not have values", messageId: "SVC4611" } -#---------SVC4612------------------------------ -# %1 - group name +#---------SVC4612------------------------------ +# %1 - group name GROUP_TYPE_ALREADY_EXIST: { code: 409, message: 'Error: Group type %1 already exists.', messageId: "SVC4612" } -#---------SVC4613------------------------------ +#---------SVC4613------------------------------ # %1 - group name # %2 - VF name(component name) # %3 - actual component type [VF] @@ -1404,15 +1404,15 @@ errors: code: 409, message: "Error: Group with name '%1' already exists in %2 %3.", messageId: "SVC4613" - } -#---------SVC4614------------------------------ + } +#---------SVC4614------------------------------ # %1 - group type GROUP_TYPE_IS_INVALID: { code: 400, message: "Error: Invalid content. Group type %1 does not exist", messageId: "SVC4614" } -#---------SVC4615------------------------------ +#---------SVC4615------------------------------ # %1 - group name GROUP_MISSING_GROUP_TYPE: { code: 400, @@ -1428,7 +1428,7 @@ errors: code: 400, message: "Error: Member '%1' listed in group '%2' is not part of '%3' %4.", messageId: "SVC4616" - } + } #---------SVC4617------------------------------ # %1 - member name # %2 - group name @@ -1438,7 +1438,7 @@ errors: message: "Error: member %1 listed in group %2 is not part of allowed members of group type %3.", messageId: "SVC4617" } -#---------SVC4618------------------------------ +#---------SVC4618------------------------------ # %1 - missing file name # %2 - csar file name ARTIFACT_NOT_FOUND_IN_CSAR: { @@ -1446,7 +1446,7 @@ errors: message: "Error: artifact %1 is defined in CSAR %2 manifest but is not provided", messageId: "SVC4618" } -#---------SVC4619------------------------------ +#---------SVC4619------------------------------ # %1 - artifact name # %2 - artifact type # %3 - existing artifact type @@ -1455,23 +1455,23 @@ errors: message: "Error: artifact %1 in type %2 already exists in type %3.", messageId: "SVC4619" } -#---------SVC4620------------------------------ +#---------SVC4620------------------------------ FAILED_RETRIVE_ARTIFACTS_TYPES: { code: 400, message: "Error: Failed to retrieve list of suported artifact types.", messageId: "SVC4620" } -#---------SVC4621------------------------------ +#---------SVC4621------------------------------ # %1 - artifact name -# %2 - master +# %2 - master ARTIFACT_ALRADY_EXIST_IN_MASTER_IN_CSAR: { code: 400, message: "Error: artifact %1 already exists in master %2 .", messageId: "SVC4621" } -#---------SVC4622------------------------------ +#---------SVC4622------------------------------ # %1 - artifact name -# %2 - artifact type +# %2 - artifact type # %3 - master name # %4 - master type ARTIFACT_NOT_VALID_IN_MASTER: { @@ -1479,9 +1479,9 @@ errors: message: "Error: artifact %1 in type %2 can not be exists under master %3 in type %4.", messageId: "SVC4622" } -#---------SVC4623------------------------------ +#---------SVC4623------------------------------ # %1 - artifact name -# %2 - artifact type +# %2 - artifact type # %3 - env name # %4 - existing env ARTIFACT_NOT_VALID_ENV: { @@ -1489,7 +1489,7 @@ errors: message: "Error: Artifact %1 in type %2 with env %3 already exists with another env %4", messageId: "SVC4623" } -#---------SVC4624------------------------------ +#---------SVC4624------------------------------ # %1 - groups names # %2 - VF name # %3 - component type [VF ] @@ -1498,14 +1498,14 @@ errors: message: "Error: Invalid Content. The groups '%1' cannot be found under %2 %3.", messageId: "SVC4624" } -#---------SVC4625------------------------------ +#---------SVC4625------------------------------ # %1 - groups name GROUP_ARTIFACT_ALREADY_ASSOCIATED: { code: 400, message: "Error: Invalid Content. Artifact already associated to group '%1'.", messageId: "SVC4625" } -#---------SVC4626------------------------------ +#---------SVC4626------------------------------ # %1 - groups name GROUP_ARTIFACT_ALREADY_DISSOCIATED: { code: 400, @@ -1521,7 +1521,7 @@ errors: message: "Error: property %1 listed in group %2 is not exist in group type %3.", messageId: "SVC4627" } -#---------SVC4628------------------------------ +#---------SVC4628------------------------------ # %1 - csarUUID # %2 - VF name VSP_ALREADY_EXISTS: { @@ -1529,14 +1529,14 @@ errors: message: "Error: The VSP with UUID %1 was already imported for VF %2. Please select another or update the existing VF.", messageId: "SVC4628" } -#---------SVC4629------------------------------ +#---------SVC4629------------------------------ # %1 - VF name MISSING_CSAR_UUID: { code: 400, message: "Error: The Csar UUID or payload name is missing for VF %1.", messageId: "SVC4629" } -#---------SVC4630------------------------------ +#---------SVC4630------------------------------ # %1 - VF name # %2 - new csarUUID # %3 - old csarUUID @@ -1545,8 +1545,8 @@ errors: message: "Error: Resource %1 cannot be updated using CsarUUID %2 since the resource is linked to a different VSP with csarUUID %3.", messageId: "SVC4630" } -#---------SVC4631------------------------------ -# %1 - policy name +#---------SVC4631------------------------------ +# %1 - policy name POLICY_TYPE_ALREADY_EXIST: { code: 409, message: "Error: Policy type %1 already exists.", @@ -1593,7 +1593,7 @@ errors: code: 404, message: "Error: Requested '%1' attribute was not found.", messageId: "SVC4637" - } + } #-----------SVC4638--------------------------- #%1 - attribute name ATTRIBUTE_ALREADY_EXIST: { @@ -1661,7 +1661,7 @@ errors: message: "Error: Invalid Content. VF Module name '%1' contains invalid characters", messageId: "SVC4646" } - + #---------SVC4647------------------------------ # %1 - "modifiedName" INVALID_VF_MODULE_NAME_MODIFICATION: { @@ -1699,23 +1699,23 @@ errors: message: "Error: Once resource is certified, derived_from can be changed only to a sibling", messageId: "SVC4651" } -#---------SVC4652------------------------------ +#---------SVC4652------------------------------ # %1 - resource/service COMPONENT_INVALID_SUBCATEGORY: { code: 400, message: "Error: Invalid Content. Invalid %1 sub category.", messageId: "SVC4652" } -#---------SVC4653------------------------------ -# %1 - group instance uniqueId +#---------SVC4653------------------------------ +# %1 - group instance uniqueId # %2 - service uniqueId GROUP_INSTANCE_NOT_FOUND_ON_COMPONENT_INSTANCE: { code: 404, message: "Error: Requested group instance %1 was not found on component %2.", messageId: "SVC4653" } -#---------SVC4654------------------------------ -# %1 - group property name +#---------SVC4654------------------------------ +# %1 - group property name # %2 - valid min limit value # %3 - valid max limit value INVALID_GROUP_MIN_MAX_INSTANCES_PROPERTY_VALUE: { @@ -1723,8 +1723,8 @@ errors: message: "Error: Value of %1 must be not higher than %2, and not lower than %3.", messageId: "SVC4654" } -#---------SVC4655------------------------------ -# %1 - group property name +#---------SVC4655------------------------------ +# %1 - group property name # %2 - valid min limit value # %3 - valid max limit value INVALID_GROUP_INITIAL_COUNT_PROPERTY_VALUE: { @@ -1732,15 +1732,15 @@ errors: message: "Error: Value of %1 must be between %2 and %3.", messageId: "SVC4655" } -#---------SVC4656------------------------------ -# %1 - group property name +#---------SVC4656------------------------------ +# %1 - group property name # %2 - lower/higher # %3 - valid max/min value INVALID_GROUP_PROPERTY_VALUE_LOWER_HIGHER: { code: 400, message: "Error: Value of %1 must be %2 or equals to %3.", messageId: "SVC4656" - } + } #---------SVC4657------------------------------ # %1 - certificationRequest / startTesting RESOURCE_VFCMT_LIFECYCLE_STATE_NOT_VALID: { @@ -1752,7 +1752,7 @@ errors: # %1 – asset type [service / resource ] # %2 – main asset uuid # %3 – not found asset type [service / resource] -# %4 – not found asset name +# %4 – not found asset name ASSET_NOT_FOUND_DURING_CSAR_CREATION: { code: 400, message: "Error: CSAR packaging failed for %1 %2. %3 %4 was not found", @@ -1761,7 +1761,7 @@ errors: #---------SVC4659------------------------------ # %1 – asset type [service / resource ] # %2 – main asset uuid -# %3 – Artifact name +# %3 – Artifact name # %4 – Artifact uuid ARTIFACT_PAYLOAD_NOT_FOUND_DURING_CSAR_CREATION: { code: 400, @@ -1777,18 +1777,78 @@ errors: messageId: "SVC4660" } #---------SVC4661------------------------------ -# %1 - version -# %2 - conformance level +# %1 - assetType +# %2 - matching generic node type name TOSCA_SCHEMA_FILES_NOT_FOUND: { code: 400, message: "Error: CSAR packaging failed. TOSCA schema files for SDC-Version: %1 and Conformance-Level %2 were not found", messageId: "SVC4661" } -#---------SVC4662------------------------------ +#---------SVC4662------------------------------ # %1 - file name # %2 - parser error TOSCA_PARSE_ERROR: { code: 400, message: "Error: Invalid TOSCA template in file %1. %2", messageId: "SVC4662" + } +#---------SVC4663------------------------------ +# %1 - max length + RESOURCE_VENDOR_MODEL_NUMBER_EXCEEDS_LIMIT: { + code: 400, + message: "Error: Invalid Content. Resource vendor model number exceeds limit of %1 characters.", + messageId: "SVC4663" + } +#---------SVC4664------------------------------ + INVALID_RESOURCE_VENDOR_MODEL_NUMBER: { + code: 400, + message: 'Error: Invalid Content. Resource vendor model number is not allowed to contain characters like <>:"\/|?* and space characters other than regular space.', + messageId: "SVC4664" + } +#---------SVC4665------------------------------ +# %1 - max length + SERVICE_TYPE_EXCEEDS_LIMIT: { + code: 400, + message: "Error: Invalid Content. Service type exceeds limit of %1 characters.", + messageId: "SVC4665" + } +#---------SVC4666------------------------------ + INVALID_SERVICE_TYPE: { + code: 400, + message: 'Error: Invalid Content. Serivce type is not allowed to contain characters like <>:"\/|?* and space characters other than regular space.', + messageId: "SVC4666" + } +#---------SVC4667------------------------------ +# %1 - max length + SERVICE_ROLE_EXCEEDS_LIMIT: { + code: 400, + message: "Error: Invalid Content. Service role exceeds limit of %1 characters.", + messageId: "SVC4667" + } +#---------SVC4668------------------------------ + INVALID_SERVICE_ROLE: { + code: 400, + message: 'Error: Invalid Content. Service role is not allowed to contain characters like <>:"\/|?* and space characters other than regular space.', + messageId: "SVC4668" + } + +#---------SVC4669----------------------------- + INVALID_RESOURCE_TYPE: { + code: 400, + message: "Error: Invalid resource type.", + messageId: "SVC4669" + } +#---------SVC4670------------------------------ + ARTIFACT_NAME_INVALID: { + code: 400, + message: "Error: Artifact name is invalid.", + messageId: "SVC4670" + } +#---------SVC4671------------------------------ +# %1 - VSP name +# %2 - VFC name + CFVC_LOOP_DETECTED: { + code: 400, + message: 'Error: VSP %1 cannot be imported. The VSP contains internal loop in VFC %2', + messageId: "SVC4671" } \ No newline at end of file diff --git a/catalog-be/src/main/resources/import/tosca/data-types/dataTypes.yml b/catalog-be/src/main/resources/import/tosca/data-types/dataTypes.yml index 63d70c699e..da15414d9d 100644 --- a/catalog-be/src/main/resources/import/tosca/data-types/dataTypes.yml +++ b/catalog-be/src/main/resources/import/tosca/data-types/dataTypes.yml @@ -1196,4 +1196,57 @@ org.openecomp.datatypes.Naming: type: string required: false +# NFoD +org.openecomp.datatypes.flavors.ComputeFlavor: + derived_from: tosca.datatypes.Root + properties: + num_cpus: + type: integer + disk_size: + type: scalar-unit.size + mem_size: + type: scalar-unit.size + +org.openecomp.datatypes.flavors.LicenseFlavor: + derived_from: tosca.datatypes.Root + properties: + feature_group_uuid: + type: string + +org.openecomp.datatypes.flavors.VendorInfo: + derived_from: tosca.datatypes.Root + properties: + manufacturer_reference_number: + type: string + vendor_model: + type: string + +org.openecomp.datatypes.flavors.DeploymentFlavor: + derived_from: tosca.datatypes.Root + properties: + sp_part_number: + type: string + vendor_info: + type: org.openecomp.datatypes.flavors.VendorInfo + compute_flavor: + type: org.openecomp.datatypes.flavors.ComputeFlavor + license_flavor: + type: org.openecomp.datatypes.flavors.LicenseFlavor + required: false + + +org.openecomp.datatypes.ImageInfo: + derived_from: tosca.datatypes.Root + properties: + software_version: + type: string + file_name: + type: string + file_hash: + type: string + description: checksum/signature + file_hash_type: + type: string + required: false + default: md5 diff --git a/catalog-be/src/main/resources/import/tosca/data-types/dataTypes.zip b/catalog-be/src/main/resources/import/tosca/data-types/dataTypes.zip index 9c5964df1df4fba94608f7d22ac8c437f874299a..08d4bfc3a5bf8cb1e488d4f283293e8edeb63175 100644 GIT binary patch literal 5408 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 K0IL)L0000QvRr-u literal 5277 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 z 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%0AyxAhrfV@ zGIApw81-`l81+;NXs<#%2w5rsP(jNQkf>9Re}M{R;?qiF)dxmBmEt!l@Jy%?3ehhU zgDPjI69g(agWW|-Z9gp8e|ANU^TA!wBnzW+O(zJ7s8}#*9C&arpy0J%P$09yIR6V2 z1n@ad>v!3Hf~VdEyHZiq#o!6X6+84mGn()kbkyVQG8^@yzXpe5c3upuIJXxV`%b|Q zRC5RJs+uXi#)JhHezkxCi5=zn*Vs_}dOrbUi{*i_rQYvCVFOS8SAHkLF2KHM;Mq^g z0l{x@$b$>{g-oP-*2LK1{{jW(_fHd96m?)dmEVK)#Lc)E95N~GS#Z&azXpfmw{aVc zJv9r)W_kVt%En-RAydDe#a55}YiuZfe;IuTj9v6{4+YagwA~Ycf zjC#ZdMn!zQ4`oy^p^zB{&!V;_`~@l$l{}xosD5|AsJ1sVV4tHByUPvWm;cJq8emW6v+b1k$3M<1PGmRt96n z3_|M(Jn>&!$EpG-%+uT!5F|?fKaHJVNRv?*#^=^7C`ASq(M<^6tb~v(#iA&MZj$~` z-6snYf+#H)7!?E&By|yita6x9QS^@?v5WGeSjET)`a4$|QE8jeMTC&{v1cE9pZ7c8 z+U0J}kLP_j?|07GdEet-Nh!5svfp^-&X0{qZQorv`9`a4p-#tC>>EIu>Ddc;r<@2EX@~gCSx~FK%{Wr3wvu=E zk^3g9W2F=5WiN01888Nw8>&lrFWo`1Yp%W%G_elgi$hRYzrgM~$w&3F6EE+w{V`XC z60H23*#mCvb8yEl%!B>~;qmXmW12a@A-kcj1)!_PKIYPfm%wlYqR2Uy%1~$c*Ktk`h}z>?TiOm6>fm zh;3bbAotap8Y@#l#pL9cUy_=!PEur+Ed*6im6bo%f|^_o>hE%&qB^bQQ-t;xM5Wdo zlxpui0qXEb{+`aytnm^Bw@Hx#`--6m>`1tt5a2u3LubS{WrTAJ5($rw6w%3Ws=lJ{bdf{-JV3w#HRCxRMsRVe6<)qzkL=TE=wSEZg}td(8OvGgop; zWrL3K^L5=46TAyd#Z$=G?>%nBaLu#CjDOHFPysC|iAhk-r$9;7&Q-yJOGWe#dd5YrPI|j&-?le=J#Zbv}%W~^tdzLL-f!}&9&egS2$u%QG z)Y{6x)$hXau^=Q}-)P2h9je4-KAI%uacVZT9L4C5w}KY$Fw?j~RMLh&6`?7+b`E0n a%^}e2(Asa2hCN|Vjdh{1Zrs`tdj0|GA>eQT diff --git a/catalog-be/src/main/resources/import/tosca/heat-types/Generic_PNF/Generic_PNF.json b/catalog-be/src/main/resources/import/tosca/heat-types/Generic_PNF/Generic_PNF.json new file mode 100644 index 0000000000..cfa11dc3c7 --- /dev/null +++ b/catalog-be/src/main/resources/import/tosca/heat-types/Generic_PNF/Generic_PNF.json @@ -0,0 +1,21 @@ +{ + "payloadName": "Generic_PNF.yml", + "contactId": "jh0003", + "name": "Generic_PNF", + "description": "Represents a generic PNF.", + "resourceIconPath": "defaulticon", + "resourceType": "ABSTRACT", + "categories": [ + { + "name": "Generic", + "subcategories": [ + { + "name": "Abstract" + } + ] + } +], + "tags": [ + "Generic_PNF" + ] +} \ No newline at end of file diff --git a/catalog-be/src/main/resources/import/tosca/heat-types/Generic_PNF/Generic_PNF.yml b/catalog-be/src/main/resources/import/tosca/heat-types/Generic_PNF/Generic_PNF.yml new file mode 100644 index 0000000000..db3fc7cd3e --- /dev/null +++ b/catalog-be/src/main/resources/import/tosca/heat-types/Generic_PNF/Generic_PNF.yml @@ -0,0 +1,11 @@ +tosca_definitions_version: tosca_simple_yaml_1_0_0 +node_types: + org.openecomp.resource.abstract.nodes.PNF: + derived_from: tosca.nodes.Root + properties: + nf_function: + type: string + nf_role: + type: string + nf_type: + type: string \ No newline at end of file diff --git a/catalog-be/src/main/resources/import/tosca/heat-types/Generic_PNF/Generic_PNF.zip b/catalog-be/src/main/resources/import/tosca/heat-types/Generic_PNF/Generic_PNF.zip new file mode 100644 index 0000000000000000000000000000000000000000..fc5d7065145d037916c12a21569c6dc35512c62c GIT binary patch literal 320 zcmWIWW@Zs#U|`^2xDj#2>+V6;yg5Lg6e9xzKah4$%}XuHOpXumbJMHL&1vm(F|oT97tbI6 zdt|jt(T$6Z>0Nu5JL@khGMt&MGCjb1RiRephv-eYX`gr9nh<$))r4vKlQNI~57}BD zC?DX>$Yjre%PT5C&wzjen8ffH7gU0gL4tvsSNdAe<4cTjuAf7afV6Y06qq02&B_MS N%?N~vK>8%uC;+H9Zw>$e literal 0 HcmV?d00001 diff --git a/catalog-be/src/main/resources/import/tosca/heat-types/extCp/extCp.yml b/catalog-be/src/main/resources/import/tosca/heat-types/extCp/extCp.yml index e73cafe100..9160a9ba22 100644 --- a/catalog-be/src/main/resources/import/tosca/heat-types/extCp/extCp.yml +++ b/catalog-be/src/main/resources/import/tosca/heat-types/extCp/extCp.yml @@ -37,16 +37,16 @@ node_types: subnetpoolid: type: string requirements: - virtualLink: - capability: tosca.capabilities.network.Linkable - relationship: tosca.relationships.network.LinksTo - virtualBinding: - capability: tosca.capabilities.network.Bindable - relationship: tosca.relationships.network.BindsTo - external_virtualLink: - capability: tosca.capabilities.network.Linkable - relationship: tosca.relationships.network.LinksTo - node: org.openecomp.resource.vl.VL + - virtualLink: + capability: tosca.capabilities.network.Linkable + relationship: tosca.relationships.network.LinksTo + - virtualBinding: + capability: tosca.capabilities.network.Bindable + relationship: tosca.relationships.network.BindsTo + - external_virtualLink: + capability: tosca.capabilities.network.Linkable + relationship: tosca.relationships.network.LinksTo + node: org.openecomp.resource.vl.VL capabilities: internal_connectionPoint: type: tosca.capabilities.Node diff --git a/catalog-be/src/main/resources/import/tosca/heat-types/extCp/extCp.zip b/catalog-be/src/main/resources/import/tosca/heat-types/extCp/extCp.zip index a26c323819f63ac7424e1c0131dfd26dd6b2ab93..5e18a2474a08e2ccf027371b506e0920d1de4674 100644 GIT binary patch delta 753 zcmV@6aWAK2mo4G>q^`1|HO0x000pP000R9003opbVG11d2MXP zRl#oCFbqAfK>tC-Rvfo~?FeHE~(4ak*$s*HRuPvz}01@ehGDbLBfERhu5r|m7tyX(h9RmSoxhXb8JLJZ zDq=N$4&>2)&NopHKN|ET<8i>}xJrONKQvR8UOQ*7?22q3zBi)deA3D;b|RMOsZr(v?cJb+R<)X< zL0a{{*L4I34T~r>HG_`CGn;<>3#@zSF!mH1ZroVNN3@6aWAK2mo=8g-W!ZM=yQ?001rs000R9003opbVG11d2MX1 zRZDK$Fc4igK<>a*(Jm^aU3!-q1sWg;guuwAC_) zc16s_?}0pj+Ihe0;a80w3fAjuX!dt>VgZ&=E5oM5?d6bS4RM~ujkf973(UbE$;WkR z@(DK+>^)j{Ha*23P!n+CK+0+mA0V4&0%-B&W45mZlGJ?kCRMnq12Mn%U=%ALmjnf% zs4}$|6yovWPs{!(vOhlj6)d2w;0(F((%(x^6@t@$sEA?TznxD60rw%lcKoH%vQ<_x zJZ#(8YRf{AN-dkU3bHGuZwB~%erL*r1BQFiL0p}Wg(?c}{19d1+@_3O5yp9!Vri89 zzi5Mj`aKTuD;e|xN|i#7b9l>iZ)7nlf1XFIb{y`t_@u{Yn!KpCEFNszr#xQd9cIhg z`ksJ)`*AL)poKs zP0=8&x?6U=gM+d~q?$H2RKMcsO;ccjRRsSYNJ}$ZCr<1jo@gIy5?$CcC{uY@&y1*22-YuJn2|rpdT{*!EhwX68ZM zQgI{7hFCVBAN_RhJ><^Q&wo%$0Rle&6aWAK2mo=8g-W!ZM=yQ?001tNv;rzF7X*hL t9Inytz+^=jBc? zrs$rm|E2;nK6E`=hspo}7MAeT$O7l$3j4YmOA|k+XiKZ)Ik@<ytpC_pkbyw!_on}fDPo#Cc6Kf((d4`2YBlHO*4{0iJC`^K{@})R%?#);Pryp|F*Rp`#z^ja?gHA?{{i7ulCxx?(3?VTOSm$A}wC`yvZxR z%Ds#MaK9hOy6tsA_QHc_KtJ~b{SFEd48K?A=7a`#_Z?Q?x$AyPwub4-&9vKr{07~5 z6TN-dI1M&=uDVm_G|5YH{fE!LCBnnn%T(lxRy1zD)#|eSIKy!dXRV2Ex-@U;S8v|F z@3hUNwb_cYzxWzbjbbz=KMv`c@JXkSXWtgCU0G7GXN`Ybr^_#k+`#%as9~atj!BgM zoO36FKOBzX_nUY&F3aL`RASGcyiFb4-FzP;-%NX@GR2lfK<2o|y3zytI3EfeY${Y+ zx~hS@tz*5%19O?gTVba@)ZEcu_jW(CijH_s(bTJ}elKk~%=&-B|M;{cUB9oM*}3)S zGNDS}*=Lj8f4$=m@MdI^2ZsT+RG|V48xT+clUTwDlt#Fq(u@oe41P_|q;pQRyL4JnSk&tkQQMA@c>__Fw+14 literal 0 HcmV?d00001 diff --git a/catalog-be/src/main/resources/scripts/import/tosca/importHeatTypes.py b/catalog-be/src/main/resources/scripts/import/tosca/importHeatTypes.py index f65aefacf1..e7eaa8610b 100644 --- a/catalog-be/src/main/resources/scripts/import/tosca/importHeatTypes.py +++ b/catalog-be/src/main/resources/scripts/import/tosca/importHeatTypes.py @@ -37,7 +37,8 @@ def importHeatTypes(beHost, bePort, adminUser, fileDir, updateversion): "eline", "abstractSubstitute", "Generic_VFC", - "Generic_VF", + "Generic_VF", + "Generic_PNF", "Generic_Service", "contrailNetworkRules", "contrailPort", @@ -48,7 +49,9 @@ def importHeatTypes(beHost, bePort, adminUser, fileDir, updateversion): "contrailCompute", "contrailV2VirtualMachineInterface", "subInterface", - "contrailV2VLANSubInterface" + "contrailV2VLANSubInterface", + "multiFlavorVFC", + "vnfConfiguration" ] responseCodes = [200, 201] diff --git a/catalog-be/src/main/resources/scripts/import/tosca/upgradeHeatTypes1707.py b/catalog-be/src/main/resources/scripts/import/tosca/upgradeHeatTypes1707.py index 7c0746fb55..7315ec0635 100644 --- a/catalog-be/src/main/resources/scripts/import/tosca/upgradeHeatTypes1707.py +++ b/catalog-be/src/main/resources/scripts/import/tosca/upgradeHeatTypes1707.py @@ -26,7 +26,8 @@ def upgradeHeatTypes1707(beHost, bePort, adminUser, fileDir, updateversion): "extVl", "extCp", "Generic_VFC", - "Generic_VF", + "Generic_VF", + "Generic_PNF", "Generic_Service", "globalPort", "globalNetwork", @@ -37,6 +38,8 @@ def upgradeHeatTypes1707(beHost, bePort, adminUser, fileDir, updateversion): "contrailVirtualNetwork", "neutronNet", "neutronPort", + "multiFlavorVFC", + "vnfConfiguration" ] responseCodes = [200, 201] diff --git a/catalog-be/src/main/webapp/WEB-INF/web.xml b/catalog-be/src/main/webapp/WEB-INF/web.xml index 9b7a55a4dd..889b1fac60 100644 --- a/catalog-be/src/main/webapp/WEB-INF/web.xml +++ b/catalog-be/src/main/webapp/WEB-INF/web.xml @@ -77,7 +77,6 @@ jerseyDistribution /sdc/* - /asdc/* diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/HealthCheckBusinessLogicTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/HealthCheckBusinessLogicTest.java index 6af338ebcf..68d47590f0 100644 --- a/catalog-be/src/test/java/org/openecomp/sdc/be/components/HealthCheckBusinessLogicTest.java +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/HealthCheckBusinessLogicTest.java @@ -23,19 +23,30 @@ package org.openecomp.sdc.be.components; import java.util.ArrayList; import java.util.List; +import javax.annotation.Resource; + import org.junit.Test; import org.openecomp.sdc.be.components.impl.HealthCheckBusinessLogic; +import org.openecomp.sdc.be.dao.cassandra.schema.SdcSchemaUtils; +import org.openecomp.sdc.be.dao.titan.TitanGenericDao; +import org.openecomp.sdc.be.dao.titan.TitanOperationStatus; +import org.openecomp.sdc.be.dao.utils.UserStatusEnum; +import org.openecomp.sdc.be.resources.data.UserData; import org.openecomp.sdc.common.api.HealthCheckInfo; import org.openecomp.sdc.common.api.HealthCheckInfo.HealthCheckComponent; import org.openecomp.sdc.common.api.HealthCheckInfo.HealthCheckStatus; +import com.datastax.driver.core.Cluster; + +import fj.data.Either; + import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertFalse; public class HealthCheckBusinessLogicTest { HealthCheckBusinessLogic healthCheckBusinessLogic = new HealthCheckBusinessLogic(); - + @Test public void checkStausUpdated() { @@ -51,18 +62,13 @@ public class HealthCheckBusinessLogicTest { HealthCheckInfo checkInfoTitanUp = new HealthCheckInfo(HealthCheckComponent.TITAN, HealthCheckStatus.UP, null, null); HealthCheckInfo checkInfoTitanDown = new HealthCheckInfo(HealthCheckComponent.TITAN, HealthCheckStatus.DOWN, null, null); - HealthCheckInfo checkInfoEsUp = new HealthCheckInfo(HealthCheckComponent.ES, HealthCheckStatus.UP, null, null); - HealthCheckInfo checkInfoEsDown = new HealthCheckInfo(HealthCheckComponent.ES, HealthCheckStatus.DOWN, null, null); - /* * HealthCheckInfo checkInfoUebUp = new HealthCheckInfo(HealthCheckComponent.DE, HealthCheckStatus.UP, null, null); HealthCheckInfo checkInfoUebDown = new HealthCheckInfo(HealthCheckComponent.DE, HealthCheckStatus.DOWN, null, null); */ checkInfosLeft.add(checkInfoTitanUp); - checkInfosLeft.add(checkInfoEsUp); checkInfosRight.add(checkInfoTitanUp); - checkInfosRight.add(checkInfoEsUp); statusChanged = healthCheckBusinessLogic.anyStatusChanged(checkInfosLeft, checkInfosRight); assertFalse("check false", statusChanged); diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/ResourceImportManagerTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/ResourceImportManagerTest.java index 09f2570a35..f0b2865373 100644 --- a/catalog-be/src/test/java/org/openecomp/sdc/be/components/ResourceImportManagerTest.java +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/ResourceImportManagerTest.java @@ -130,7 +130,7 @@ public class ResourceImportManagerTest { testSetDerivedFrom(resource); testSetProperties(resource); - Mockito.verify(resourceBusinessLogic, Mockito.times(1)).propagateStateToCertified(Mockito.eq(user), Mockito.eq(resource), Mockito.any(LifecycleChangeInfoWithAction.class), Mockito.eq(false), Mockito.eq(true)); + Mockito.verify(resourceBusinessLogic, Mockito.times(1)).propagateStateToCertified(Mockito.eq(user), Mockito.eq(resource), Mockito.any(LifecycleChangeInfoWithAction.class), Mockito.eq(false), Mockito.eq(true), Mockito.eq(false)); } @Test @@ -159,7 +159,7 @@ public class ResourceImportManagerTest { Mockito.verify(resourceBusinessLogic, Mockito.times(0)).createOrUpdateResourceByImport(Mockito.any(Resource.class), Mockito.eq(user), Mockito.eq(true), Mockito.eq(false), Mockito.eq(true)); - Mockito.verify(resourceBusinessLogic, Mockito.times(0)).propagateStateToCertified(Mockito.eq(user), Mockito.any(Resource.class), Mockito.any(LifecycleChangeInfoWithAction.class), Mockito.eq(false), Mockito.eq(true)); + Mockito.verify(resourceBusinessLogic, Mockito.times(0)).propagateStateToCertified(Mockito.eq(user), Mockito.any(Resource.class), Mockito.any(LifecycleChangeInfoWithAction.class), Mockito.eq(false), Mockito.eq(true), Mockito.eq(false)); } @@ -181,7 +181,7 @@ public class ResourceImportManagerTest { Resource resource = createResource.left().value().left; testSetCapabilities(resource); - Mockito.verify(resourceBusinessLogic, Mockito.times(1)).propagateStateToCertified(Mockito.eq(user), Mockito.eq(resource), Mockito.any(LifecycleChangeInfoWithAction.class), Mockito.eq(false), Mockito.eq(true)); + Mockito.verify(resourceBusinessLogic, Mockito.times(1)).propagateStateToCertified(Mockito.eq(user), Mockito.eq(resource), Mockito.any(LifecycleChangeInfoWithAction.class), Mockito.eq(false), Mockito.eq(true), Mockito.eq(false)); Mockito.verify(resourceBusinessLogic, Mockito.times(1)).createOrUpdateResourceByImport(resource, user, true, false, true); } @@ -215,7 +215,7 @@ public class ResourceImportManagerTest { } }); - when(resourceBusinessLogic.propagateStateToCertified(Mockito.any(User.class), Mockito.any(Resource.class), Mockito.any(LifecycleChangeInfoWithAction.class), Mockito.eq(false), Mockito.eq(true))) + when(resourceBusinessLogic.propagateStateToCertified(Mockito.any(User.class), Mockito.any(Resource.class), Mockito.any(LifecycleChangeInfoWithAction.class), Mockito.eq(false), Mockito.eq(true), Mockito.eq(false))) .thenAnswer(new Answer>() { public Either answer(InvocationOnMock invocation) throws Throwable { Object[] args = invocation.getArguments(); diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ResourceBusinessLogicTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ResourceBusinessLogicTest.java index f6d2b6bf84..bbfa8bf236 100644 --- a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ResourceBusinessLogicTest.java +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ResourceBusinessLogicTest.java @@ -49,9 +49,7 @@ import org.openecomp.sdc.be.components.lifecycle.LifecycleBusinessLogic; import org.openecomp.sdc.be.components.lifecycle.LifecycleChangeInfoWithAction; import org.openecomp.sdc.be.config.ConfigurationManager; import org.openecomp.sdc.be.dao.api.ActionStatus; -import org.openecomp.sdc.be.dao.jsongraph.GraphVertex; import org.openecomp.sdc.be.dao.jsongraph.TitanDao; -import org.openecomp.sdc.be.dao.titan.TitanGenericDao; import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum; import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum; @@ -67,6 +65,7 @@ import org.openecomp.sdc.be.model.PropertyDefinition; import org.openecomp.sdc.be.model.Resource; import org.openecomp.sdc.be.model.User; import org.openecomp.sdc.be.model.cache.ApplicationDataTypeCache; +import org.openecomp.sdc.be.model.jsontitan.operations.NodeTemplateOperation; import org.openecomp.sdc.be.model.jsontitan.operations.NodeTypeOperation; import org.openecomp.sdc.be.model.jsontitan.operations.TopologyTemplateOperation; import org.openecomp.sdc.be.model.jsontitan.operations.ToscaOperationFacade; @@ -110,6 +109,7 @@ public class ResourceBusinessLogicTest { public static final String RESOURCE_NAME = "My-Resource_Name with space"; private static final String GENERIC_VF_NAME = "org.openecomp.resource.abstract.nodes.VF"; private static final String GENERIC_VFC_NAME = "org.openecomp.resource.abstract.nodes.VFC"; + private static final String GENERIC_PNF_NAME = "org.openecomp.resource.abstract.nodes.PNF"; final ServletContext servletContext = Mockito.mock(ServletContext.class); IAuditingManager iAuditingManager = null; @@ -118,6 +118,7 @@ public class ResourceBusinessLogicTest { UserBusinessLogic mockUserAdmin = Mockito.mock(UserBusinessLogic.class); ToscaOperationFacade toscaOperationFacade = Mockito.mock(ToscaOperationFacade.class); NodeTypeOperation nodeTypeOperation = Mockito.mock(NodeTypeOperation.class); + NodeTemplateOperation nodeTemplateOperation = Mockito.mock(NodeTemplateOperation.class); TopologyTemplateOperation topologyTemplateOperation = Mockito.mock(TopologyTemplateOperation.class); final LifecycleBusinessLogic lifecycleBl = Mockito.mock(LifecycleBusinessLogic.class); final ICapabilityTypeOperation capabilityTypeOperation = Mockito.mock(ICapabilityTypeOperation.class); @@ -135,8 +136,9 @@ public class ResourceBusinessLogicTest { Resource resourceResponse = null; Resource genericVF = null; Resource genericVFC = null; + Resource genericPNF = null; ComponentsUtils componentsUtils = new ComponentsUtils(); - ArtifactsBusinessLogic artifactManager = Mockito.mock(ArtifactsBusinessLogic.class); + ArtifactsBusinessLogic artifactManager = new ArtifactsBusinessLogic(); CsarOperation csarOperation = Mockito.mock(CsarOperation.class); Map emptyDataTypes = new HashMap(); @@ -187,6 +189,7 @@ public class ResourceBusinessLogicTest { Either eitherCount = Either.left(false); when(toscaOperationFacade.validateComponentNameExists(RESOURCE_NAME, ResourceTypeEnum.VFC, ComponentTypeEnum.RESOURCE)).thenReturn(eitherCount); when(toscaOperationFacade.validateComponentNameExists(RESOURCE_NAME, ResourceTypeEnum.VF, ComponentTypeEnum.RESOURCE)).thenReturn(eitherCount); + when(toscaOperationFacade.validateComponentNameExists(RESOURCE_NAME, ResourceTypeEnum.PNF, ComponentTypeEnum.RESOURCE)).thenReturn(eitherCount); Either validateDerivedExists = Either.left(true); when(toscaOperationFacade.validateToscaResourceNameExists("Root")).thenReturn(validateDerivedExists); @@ -195,14 +198,7 @@ public class ResourceBusinessLogicTest { when(toscaOperationFacade.validateToscaResourceNameExists("kuku")).thenReturn(validateDerivedNotExists); when(graphLockOperation.lockComponent(Mockito.anyString(), Mockito.eq(NodeTypeEnum.Resource))).thenReturn(StorageOperationStatus.OK); when(graphLockOperation.lockComponentByName(Mockito.anyString(), Mockito.eq(NodeTypeEnum.Resource))).thenReturn(StorageOperationStatus.OK); - - ArtifactDefinition artifactDef = new ArtifactDefinition(); - artifactDef.setUniqueId("123.123"); - Either returnEither = Either.left(artifactDef); - when(artifactManager.createArtifactPlaceHolderInfo(Mockito.anyString(), Mockito.anyString(), Mockito.anyMap(), Mockito.any(User.class), Mockito.any(ArtifactGroupTypeEnum.class))).thenReturn(artifactDef); - - when(artifactManager.addHeatEnvArtifact(Mockito.any(ArtifactDefinition.class), Mockito.any(ArtifactDefinition.class), Mockito.anyString(), Mockito.any(NodeTypeEnum.class), Mockito.anyString())).thenReturn(returnEither); - + // createResource resourceResponse = createResourceObject(true); Either eitherCreate = Either.left(resourceResponse); @@ -213,6 +209,7 @@ public class ResourceBusinessLogicTest { when(applicationDataTypeCache.getAll()).thenReturn(Either.left(emptyDataTypes)); // BL object + artifactManager.nodeTemplateOperation = nodeTemplateOperation; bl = new ResourceBusinessLogic(); bl.setElementDao(mockElementDao); bl.setUserAdmin(mockUserAdmin); @@ -281,6 +278,7 @@ public class ResourceBusinessLogicTest { resource.setDerivedFrom(template); resource.setVendorName("Motorola"); resource.setVendorRelease("1.0.0"); + resource.setResourceVendorModelNumber(""); resource.setContactId("ya5467"); resource.setIcon("MyIcon"); resource.setCsarUUID("valid_vf.csar"); @@ -364,6 +362,7 @@ public class ResourceBusinessLogicTest { testVendorNameWrongFormatCreate(); testVendorReleaseWrongFormat(); testVendorReleaseExceedsLimitCreate(); + testResourceVendorModelNumberExceedsLimit(); testResourceVendorNameMissing(); testResourceVendorReleaseMissing(); testResourceCategoryExist(); @@ -667,13 +666,23 @@ public class ResourceBusinessLogicTest { private void testVendorNameExceedsLimit() { Resource resourceExccedsVendorNameLimit = createResourceObject(false); - String tooLongVendorName = "h1KSyJh9Eh1KSyJh9Eh1KSyJh9Eh1KSyJh9E"; + String tooLongVendorName = "h1KSyJh9Eh1KSyJh9Eh1KSyJh9Eh1KSyJh9Eh1KSyJh9Eh1KSyJh9Eh1KSyJh9Eh1KSyJh9E"; resourceExccedsVendorNameLimit.setVendorName(tooLongVendorName); Either createResponse = bl.createResource(resourceExccedsVendorNameLimit, AuditingActionEnum.CREATE_RESOURCE, user, null, null); assertTrue(createResponse.isRight()); assertResponse(createResponse, ActionStatus.VENDOR_NAME_EXCEEDS_LIMIT, "" + ValidationUtils.VENDOR_NAME_MAX_LENGTH); } + + private void testResourceVendorModelNumberExceedsLimit() { + Resource resourceExccedsVendorModelNumberLimit = createResourceObject(false); + String tooLongVendorModelNumber = "h1KSyJh9Eh1KSyJh9Eh1KSyJh9Eh1KSyJh9Eh1KSyJh9Eh1KSyJh9Eh1KSyJh9Eh1KSyJh9E"; + resourceExccedsVendorModelNumberLimit.setResourceVendorModelNumber(tooLongVendorModelNumber); + + Either createResponse = bl.createResource(resourceExccedsVendorModelNumberLimit, AuditingActionEnum.CREATE_RESOURCE, user, null, null); + assertTrue(createResponse.isRight()); + assertResponse(createResponse, ActionStatus.RESOURCE_VENDOR_MODEL_NUMBER_EXCEEDS_LIMIT, "" + ValidationUtils.RESOURCE_VENDOR_MODEL_NUMBER_MAX_LENGTH); + } private void testVendorNameWrongFormatCreate() { Resource resource = createResourceObject(false); @@ -1641,7 +1650,7 @@ public class ResourceBusinessLogicTest { @Test - public void testGeneratedInputs() { + public void testVFGeneratedInputs() { Resource resource = createVF(); List inputs = resource.getInputs(); @@ -1654,7 +1663,7 @@ public class ResourceBusinessLogicTest { } @Test - public void testUpdateGenericInputsToLatestOnCheckout() { + public void testVFUpdateGenericInputsToLatestOnCheckout() { //create a VF that is derived from generic version 1.0 Resource resource = createVF(); @@ -1680,7 +1689,7 @@ public class ResourceBusinessLogicTest { @Test - public void testUpdateGenericInputsToLatestOnCheckoutNotPerformed() { + public void testVFUpdateGenericInputsToLatestOnCheckoutNotPerformed() { //create a VF that is derived from generic version 1.0 Resource resource = createVF(); @@ -1713,6 +1722,21 @@ public class ResourceBusinessLogicTest { assertTrue(resource.getInputs().stream().filter(p -> null == p.getOwnerId()).findAny().get().getType().equals("integer")); } + @Test + public void testPNFGeneratedInputsNoGeneratedInformationalArtifacts() { + + Resource resource = createPNF(); + List inputs = resource.getInputs(); + assertTrue(8 == inputs.size()); + for(InputDefinition input : inputs){ + assertNotNull(input.getOwnerId()); + } + assertTrue(resource.getDerivedFromGenericType().equals(genericPNF.getToscaResourceName())); + assertTrue(resource.getDerivedFromGenericVersion().equals(genericPNF.getVersion())); + assertTrue(0 == resource.getArtifacts().size()); + } + + private Resource createVF() { genericVF = setupGenericTypeMock(GENERIC_VF_NAME); @@ -1726,6 +1750,19 @@ public class ResourceBusinessLogicTest { return createResponse.left().value(); } + private Resource createPNF() { + + genericPNF = setupGenericTypeMock(GENERIC_PNF_NAME); + when(toscaOperationFacade.getLatestCertifiedNodeTypeByToscaResourceName(GENERIC_PNF_NAME)).thenReturn(Either.left(genericPNF)); + Resource resource = createResourceObject(true); + resource.setDerivedFrom(null); + resource.setResourceType(ResourceTypeEnum.PNF); + when(toscaOperationFacade.createToscaComponent(resource)).thenReturn(Either.left(resource)); + Either createResponse = bl.createResource(resource, AuditingActionEnum.CREATE_RESOURCE, user, null, null); + assertTrue(createResponse.isLeft()); + return createResponse.left().value(); + } + private Resource setupGenericTypeMock(String toscaName) { @@ -1746,4 +1783,6 @@ public class ResourceBusinessLogicTest { return genericType; } + + } diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/lifecycle/LifecycleTestBase.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/lifecycle/LifecycleTestBase.java index 69b08bd1c1..1488f13015 100644 --- a/catalog-be/src/test/java/org/openecomp/sdc/be/components/lifecycle/LifecycleTestBase.java +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/lifecycle/LifecycleTestBase.java @@ -50,6 +50,7 @@ import org.openecomp.sdc.be.model.Resource; import org.openecomp.sdc.be.model.Service; import org.openecomp.sdc.be.model.User; import org.openecomp.sdc.be.model.jsontitan.datamodel.ToscaElement; +import org.openecomp.sdc.be.model.jsontitan.datamodel.ToscaElementTypeEnum; import org.openecomp.sdc.be.model.jsontitan.operations.ToscaElementLifecycleOperation; import org.openecomp.sdc.be.model.jsontitan.operations.ToscaOperationFacade; import org.openecomp.sdc.be.model.jsontitan.utils.ModelConverter; @@ -168,7 +169,8 @@ public class LifecycleTestBase { resource.setVendorRelease("1.0.0"); resource.setContactId("yavivi"); resource.setIcon("MyIcon.jpg"); - + resource.setToscaType(ToscaElementTypeEnum.NodeType.getValue()); + return resource; } @@ -191,6 +193,7 @@ public class LifecycleTestBase { resource.setVendorRelease("1.0.0"); resource.setContactId("yavivi"); resource.setIcon("MyIcon.jpg"); + resource.setToscaType(ToscaElementTypeEnum.NodeType.getValue()); return resource; } diff --git a/catalog-be/src/test/resources/config/catalog-be/configuration.yaml b/catalog-be/src/test/resources/config/catalog-be/configuration.yaml index cd5c58957d..6a94f7268a 100644 --- a/catalog-be/src/test/resources/config/catalog-be/configuration.yaml +++ b/catalog-be/src/test/resources/config/catalog-be/configuration.yaml @@ -5,8 +5,6 @@ identificationHeaderFields: - HTTP_IV_REMOTE_ADDRESS - HTTP_CSP_WSTYPE - - # catalog backend hostname beFqdn: sdccatalog.att.com @@ -24,33 +22,71 @@ beSslPort: 8443 version: 1.0 released: 2012-11-30 -toscaConformanceLevel: 3.0 +toscaConformanceLevel: 4.0 +minToscaConformanceLevel: 3.0 titanCfgFile: /home/vagrant/catalog-be/config/catalog-be/titan.properties titanInMemoryGraph: true titanLockTimeout: 600 + +# The interval to try and reconnect to titan DB when it is down during ASDC startup: titanReconnectIntervalInSeconds: 3 + +# The read timeout towards Titan DB when health check is invoked: titanHealthCheckReadTimeout: 1 + +# The interval to try and reconnect to Elasticsearch when it is down during ASDC startup: esReconnectIntervalInSeconds: 3 uebHealthCheckReconnectIntervalInSeconds: 15 uebHealthCheckReadTimeout: 4 + # Protocols protocols: - http - https +# Default imports +defaultImports: + - nodes: + file: nodes.yml + - datatypes: + file: data.yml + - capabilities: + file: capabilities.yml + - relationships: + file: relationships.yml + - groups: + file: groups.yml + - policies: + file: policies.yml + # Users users: tom: passwd bob: passwd - + neo4j: host: neo4jhost port: 7474 user: neo4j password: "12345" - + +cassandraConfig: + cassandraHosts: ['localhost'] + localDataCenter: + reconnectTimeout : 30000 + authenticate: false + username: koko + password: bobo + ssl: false + truststorePath : /path/path + truststorePassword : 123123 + keySpaces: + - { name: sdcaudit, replicationStrategy: SimpleStrategy, replicationInfo: ['1']} + - { name: sdcartifact, replicationStrategy: SimpleStrategy, replicationInfo: ['1']} + - { name: sdccomponent, replicationStrategy: SimpleStrategy, replicationInfo: ['1']} + - { name: sdcrepository, replicationStrategy: SimpleStrategy, replicationInfo: ['1']} #Application-specific settings of ES elasticSearch: @@ -68,7 +104,7 @@ elasticSearch: # Legal values for creationPeriod - year, month, day, hour, minute, none (meaning no time-based behaviour). # # If no creationPeriod is configured for indexPrefix, default behavour is creationPeriod: month. - + indicesTimeFrequency: - indexPrefix: auditingevents creationPeriod: month @@ -110,7 +146,8 @@ resourceTypes: &allResourceTypes - VL - VF - VFCMT - + - Abstract + # validForResourceTypes usage # validForResourceTypes: # - VF @@ -128,14 +165,19 @@ deploymentResourceArtifacts: # displayName: "Network HEAT Template" # type: HEAT_NET # validForResourceTypes: *allResourceTypes - + deploymentResourceInstanceArtifacts: heatEnv: displayName: "HEAT ENV" type: HEAT_ENV description: "Auto-generated HEAT Environment deployment artifact" fileExtension: "env" - + VfHeatEnv: + displayName: "VF HEAT ENV" + type: HEAT_ENV + description: "VF Auto-generated HEAT Environment deployment artifact" + fileExtension: "env" + #tosca artifacts placeholders toscaArtifacts: assetToscaTemplate: @@ -149,9 +191,12 @@ toscaArtifacts: type: TOSCA_CSAR description: TOSCA definition package of the asset + #Informational artifacts placeHolder excludeResourceCategory: - Generic +excludeResourceType: + - PNF informationalResourceArtifacts: features: displayName: Features @@ -174,7 +219,7 @@ informationalResourceArtifacts: resourceSecurityTemplate: displayName: Resource Security Template type: OTHER - + excludeServiceCategory: informationalServiceArtifacts: @@ -217,7 +262,7 @@ informationalServiceArtifacts: serviceSecurityTemplate: displayName: Service Security Template type: OTHER - + serviceApiArtifacts: configuration: displayName: Configuration @@ -238,7 +283,6 @@ serviceApiArtifacts: displayName: Testing type: OTHER - additionalInformationMaxNumberOfKeys: 50 systemMonitoring: @@ -261,6 +305,7 @@ serviceDeploymentArtifacts: MODEL_QUERY_SPEC: acceptedTypes: - xml +#AAI Artifacts AAI_SERVICE_MODEL: acceptedTypes: - xml @@ -284,19 +329,19 @@ resourceDeploymentArtifacts: - yaml - yml validForResourceTypes: *allResourceTypes - HEAT_NESTED: + HEAT_NET: acceptedTypes: - yaml - yml validForResourceTypes: *allResourceTypes - HEAT_ARTIFACT: - acceptedTypes: - validForResourceTypes: *allResourceTypes - HEAT_NET: + HEAT_NESTED: acceptedTypes: - yaml - yml validForResourceTypes: *allResourceTypes + HEAT_ARTIFACT: + acceptedTypes: + validForResourceTypes: *allResourceTypes YANG_XML: acceptedTypes: - xml @@ -321,10 +366,55 @@ resourceDeploymentArtifacts: acceptedTypes: - xml validForResourceTypes: *allResourceTypes + LIFECYCLE_OPERATIONS: + acceptedTypes: + - yaml + - yml + validForResourceTypes: + - VF + - VFC + VES_EVENTS: + acceptedTypes: + - yaml + - yml + validForResourceTypes: *allResourceTypes + PERFORMANCE_COUNTER: + acceptedTypes: + - csv + validForResourceTypes: *allResourceTypes APPC_CONFIG: acceptedTypes: validForResourceTypes: - VF + DCAE_TOSCA: + acceptedTypes: + - yml + - yaml + validForResourceTypes: + - VF + - VFCMT + DCAE_JSON: + acceptedTypes: + - json + validForResourceTypes: + - VF + - VFCMT + DCAE_POLICY: + acceptedTypes: + - emf + validForResourceTypes: + - VF + - VFCMT + DCAE_DOC: + acceptedTypes: + validForResourceTypes: + - VF + - VFCMT + DCAE_EVENT: + acceptedTypes: + validForResourceTypes: + - VF + - VFCMT AAI_VF_MODEL: acceptedTypes: - xml @@ -344,7 +434,7 @@ resourceDeploymentArtifacts: SNMP_TRAP: acceptedTypes: validForResourceTypes: *allResourceTypes - + resourceInstanceDeploymentArtifacts: HEAT_ENV: acceptedTypes: @@ -352,6 +442,29 @@ resourceInstanceDeploymentArtifacts: VF_MODULES_METADATA: acceptedTypes: - json + VES_EVENTS: + acceptedTypes: + - yaml + - yml + PERFORMANCE_COUNTER: + acceptedTypes: + - csv + DCAE_INVENTORY_TOSCA: + acceptedTypes: + - yml + - yaml + DCAE_INVENTORY_JSON: + acceptedTypes: + - json + DCAE_INVENTORY_POLICY: + acceptedTypes: + - emf + DCAE_INVENTORY_DOC: + acceptedTypes: + DCAE_INVENTORY_BLUEPRINT: + acceptedTypes: + DCAE_INVENTORY_EVENT: + acceptedTypes: SNMP_POLL: acceptedTypes: validForResourceTypes: *allResourceTypes @@ -389,7 +502,14 @@ resourceInformationalArtifacts: validForResourceTypes: *allResourceTypes OTHER: acceptedTypes: - validForResourceTypes: *allResourceTypes + validForResourceTypes: + - VFC + - CP + - VL + - VF + - VFCMT + - Abstract + - PNF SNMP_POLL: acceptedTypes: validForResourceTypes: *allResourceTypes @@ -404,13 +524,10 @@ resourceInformationalArtifacts: resourceInformationalDeployedArtifacts: - requirementsToFulfillBeforeCert: - CP: - - tosca.capabilities.network.Bindable capabilitiesToConsumeBeforeCert: - + unLoggedUrls: - /sdc2/rest/healthCheck @@ -422,23 +539,20 @@ cleanComponentsConfiguration: artifactsIndex: resources -cassandraConfig: - cassandraHosts: ['localhost'] - localDataCenter: - reconnectTimeout : 30000 - authenticate: false - username: koko - password: bobo - ssl: false - truststorePath : /path/path - truststorePassword : 123123 - keySpaces: - - { name: sdcaudit, replicationStrategy: SimpleStrategy, replicationInfo: ['1']} - - { name: sdcartifact, replicationStrategy: SimpleStrategy, replicationInfo: ['1']} - +heatEnvArtifactHeader: "" +heatEnvArtifactFooter: "" + +onboarding: + protocol: http + host: localhost + port: 8080 + downloadCsarUri: "/onboarding-api/v1.0/vendor-software-products/packages" + healthCheckUri: "/onboarding-api/v1.0/healthcheck" + + switchoverDetector: - gBeFqdn: AIO-BE.ecomp.idns.com - gFeFqdn: AIO-FE.ecomp.idns.com + gBeFqdn: AIO-BE.ecomp.idns.cip.com + gFeFqdn: AIO-FE.ecomp.idns.cip.com beVip: 0.0.0.0 feVip: 0.0.0.0 beResolveAttempts: 3 @@ -454,25 +568,15 @@ switchoverDetector: changePriorityBody: '{"name":"AIO-BE.ecomp.idns.com","uri":"/crt/CipDomain.ECOMP-ASDC-DEVST/config/sites/AIO-BE.ecomp.idns.com","no_ad_redirection":false,"v4groups":{"failover_groups":["/crt/CipDomain.ECOMP-ASDC-DEVST/config/groups/group_mg_be","/crt/CipDomain.ECOMP-ASDC-DEVST/config/groups/group_bs_be"],"failover_policy":["FAILALL"]},"comment":"AIO BE G-fqdn","intended_app_proto":"DNS"}'} feSet: { changePriorityUrl: "http://xxx.com/crt/CipDomain.ECOMP-ASDC-DEVST/config/sites/AIO-FE.ecomp.idns.com?user=root", changePriorityBody: '{"comment":"AIO G-fqdn","name":"AIO-FE.ecomp.idns.com","v4groups":{"failover_groups":["/crt/CipDomain.ECOMP-ASDC-DEVST/config/groups/group_mg_fe","/crt/CipDomain.ECOMP-ASDC-DEVST/config/groups/group_bs_fe"],"failover_policy":["FAILALL"]},"no_ad_redirection":false,"intended_app_proto":"DNS","uri":"/crt/CipDomain.ECOMP-ASDC-DEVST/config/sites/AIO-FE.ecomp.idns.com"}'} - - -heatEnvArtifactHeader: "" -heatEnvArtifactFooter: "" - -onboarding: - protocol: http - host: localhost - port: 8080 - downloadCsarUri: "/onboarding-api/v1.0/vendor-software-products/packages" applicationL1Cache: datatypes: - enabled: true + enabled: false firstRunDelay: 10 pollIntervalInSec: 60 applicationL2Cache: - enabled: false + enabled: true catalogL1Cache: enabled: true resourcesSizeInCache: 300 @@ -482,8 +586,28 @@ applicationL2Cache: syncIntervalInSecondes: 60 waitOnShutDownInMinutes: 30 numberOfCacheWorkers: 4 + +toscaValidators: + stringMaxLength: 2500 + +disableAudit: false + +vfModuleProperties: + min_vf_module_instances: + forBaseModule: 1 + forNonBaseModule: 0 + max_vf_module_instances: + forBaseModule: 1 + forNonBaseModule: + initial_count: + forBaseModule: 1 + forNonBaseModule: 0 + vf_module_type: + forBaseModule: Base + forNonBaseModule: Expansion + genericAssetNodeTypes: VFC: org.openecomp.resource.abstract.nodes.VFC VF : org.openecomp.resource.abstract.nodes.VF + PNF: org.openecomp.resource.abstract.nodes.PNF Service: org.openecomp.resource.abstract.nodes.service - diff --git a/catalog-be/src/test/resources/config/catalog-be/error-configuration.yaml b/catalog-be/src/test/resources/config/catalog-be/error-configuration.yaml index e131929aa7..591a961150 100644 --- a/catalog-be/src/test/resources/config/catalog-be/error-configuration.yaml +++ b/catalog-be/src/test/resources/config/catalog-be/error-configuration.yaml @@ -12,103 +12,103 @@ errors: code: 204, message: "No Content" } -#--------POL4050----------------------------- +#--------POL4050----------------------------- NOT_ALLOWED: { code: 405, message: "Error: Method not allowed.", messageId: "POL4050" } -#--------POL5000----------------------------- +#--------POL5000----------------------------- GENERAL_ERROR: { code: 500, message: "Error: Internal Server Error. Please try again later.", messageId: "POL5000" } -#---------POL5001------------------------------ +#---------POL5001------------------------------ MISSING_X_ECOMP_INSTANCE_ID: { code: 400 , message: "Error: Missing 'X-ECOMP-InstanceID' HTTP header.", messageId: "POL5001" } -#---------POL5002------------------------------ +#---------POL5002------------------------------ AUTH_REQUIRED: { code: 401 , message: "Error: Authentication is required to use the API.", messageId: "POL5002" } -#---------POL5003------------------------------ +#---------POL5003------------------------------ AUTH_FAILED: { code: 403 , message: "Error: Not authorized to use the API.", messageId: "POL5003" } -#---------POL5004------------------------------ +#---------POL5004------------------------------ MISSING_USER_ID: { code: 400 , message: "Error: Missing 'USER_ID' HTTP header.", messageId: "POL5004" } -#---------SVC4000----------------------------- +#---------SVC4000----------------------------- INVALID_CONTENT: { code: 400, message: "Error: Invalid content.", messageId: "SVC4000" } -#---------SVC4002----------------------------- +#---------SVC4002----------------------------- MISSING_INFORMATION: { code: 403, message: "Error: Missing information.", messageId: "SVC4002" } -#---------SVC4003------------------------------ -# %1 - Users's ID +#---------SVC4003------------------------------ +# %1 - Users's ID USER_NOT_FOUND: { code: 404, message: "Error: User '%1' was not found.", messageId: "SVC4003" } -#---------SVC4004----------------------------- -# %1 - Users's email address +#---------SVC4004----------------------------- +# %1 - Users's email address INVALID_EMAIL_ADDRESS: { code: 400, message: "Error: Invalid email address '%1'.", messageId: "SVC4004" } -#---------SVC4005------------------------------ +#---------SVC4005------------------------------ # %1 - role INVALID_ROLE: { code: 400, message: "Error: Invalid role '%1'.", messageId: "SVC4005" } -#---------SVC4006------------------------------ -# %1 - Users's USER_ID +#---------SVC4006------------------------------ +# %1 - Users's USER_ID USER_ALREADY_EXIST: { code: 409, message: "Error: User with '%1' ID already exists.", messageId: "SVC4006" } -#---------SVC4007------------------------------ +#---------SVC4007------------------------------ DELETE_USER_ADMIN_CONFLICT: { code: 409, message: "Error: An administrator can only be deleted by another administrator.", messageId: "SVC4007" } -#---------SVC4008----------------------------- -# %1 - Users's userId +#---------SVC4008----------------------------- +# %1 - Users's userId INVALID_USER_ID: { code: 400, message: "Error: Invalid userId '%1'.", messageId: "SVC4008" } -#---------SVC4049------------------------------ +#---------SVC4049------------------------------ # %1 - service/resource COMPONENT_MISSING_CONTACT: { code: 400, message: "Error: Invalid Content. Missing %1 contact.", messageId: "SVC4049" - } -#---------SVC4050----------------------------- + } +#---------SVC4050----------------------------- # %1 - Service/Resource/Additional parameter # %2 - service/resource/label name COMPONENT_NAME_ALREADY_EXIST: { @@ -116,90 +116,90 @@ errors: message: "Error: %1 with name '%2' already exists.", messageId: "SVC4050" } -#---------SVC4051------------------------------ -# %1 - resource/service +#---------SVC4051------------------------------ +# %1 - resource/service COMPONENT_MISSING_CATEGORY: { code: 400, message: "Error: Invalid Content. Missing %1 category.", messageId: "SVC4051" } -#---------SVC4052------------------------------ +#---------SVC4052------------------------------ COMPONENT_MISSING_TAGS: { code: 400, message: "Error: Invalid Content. At least one tag has to be specified.", messageId: "SVC4052" } -#---------SVC4053------------------------------ +#---------SVC4053------------------------------ # %1 - service/resource COMPONENT_MISSING_DESCRIPTION: { code: 400, message: "Error: Invalid Content. Missing %1 description.", messageId: "SVC4053" } -#---------SVC4054------------------------------ +#---------SVC4054------------------------------ # %1 - resource/service COMPONENT_INVALID_CATEGORY: { code: 400, message: "Error: Invalid Content. Invalid %1 category.", messageId: "SVC4054" } -#---------SVC4055------------------------------ +#---------SVC4055------------------------------ MISSING_VENDOR_NAME: { code: 400, message: "Error: Invalid Content. Missing vendor name.", messageId: "SVC4055" } -#---------SVC4056------------------------------ +#---------SVC4056------------------------------ MISSING_VENDOR_RELEASE: { code: 400, message: "Error: Invalid Content. Missing vendor release.", messageId: "SVC4056" } -#---------SVC4057------------------------------ +#---------SVC4057------------------------------ MISSING_DERIVED_FROM_TEMPLATE: { code: 400, message: "Error: Invalid Content. Missing derived from template specification.", messageId: "SVC4057" } -#---------SVC4058------------------------------ +#---------SVC4058------------------------------ # %1 - service/resource COMPONENT_MISSING_ICON: { code: 400, message: "Error: Invalid Content. Missing %1 icon.", messageId: "SVC4058" } -#---------SVC4059------------------------------ +#---------SVC4059------------------------------ # %1 - service/resource COMPONENT_INVALID_ICON: { code: 400, message: "Error: Invalid Content. Invalid %1 icon.", messageId: "SVC4059" } -#---------SVC4060------------------------------ +#---------SVC4060------------------------------ PARENT_RESOURCE_NOT_FOUND: { code: 400, message: "Error: Invalid Content. Derived from resource template was not found.", messageId: "SVC4060" } -#---------SVC4061------------------------------ +#---------SVC4061------------------------------ MULTIPLE_PARENT_RESOURCE_FOUND: { code: 400, message: "Error: Invalid Content. Multiple derived from resource template is not allowed.", messageId: "SVC4061" } -#---------SVC4062------------------------------ +#---------SVC4062------------------------------ # %1 - service/resource MISSING_COMPONENT_NAME: { code: 400, message: "Error: Invalid Content. Missing %1 name.", messageId: "SVC4062" } -#---------SVC4063------------------------------ +#---------SVC4063------------------------------ #%1  -  resource/service name RESOURCE_NOT_FOUND: { code: 404, @@ -207,51 +207,51 @@ errors: messageId: "SVC4063" } -#---------SVC4064------------------------------ +#---------SVC4064------------------------------ # %1 - Service/Resource/Property COMPONENT_INVALID_DESCRIPTION: { code: 400, message: "Error: Invalid Content. %1 description contains non-english characters.", messageId: "SVC4064" } -#---------SVC4065------------------------------ +#---------SVC4065------------------------------ # %1 - Service/Resource/Property -# %2 - max resource/service name length +# %2 - max resource/service name length COMPONENT_DESCRIPTION_EXCEEDS_LIMIT: { code: 400, message: "Error: Invalid Content. %1 description exceeds limit of %2 characters.", messageId: "SVC4065" } -#---------SVC4066------------------------------ -# %1 - max length +#---------SVC4066------------------------------ +# %1 - max length COMPONENT_TAGS_EXCEED_LIMIT: { code: 400, message: "Error: Invalid Content. Tags overall length exceeds limit of %1 characters.", messageId: "SVC4066" } #---------SVC4067------------------------------ -# %1 - max length +# %1 - max length VENDOR_NAME_EXCEEDS_LIMIT: { code: 400, message: "Error: Invalid Content. Vendor name exceeds limit of %1 characters.", messageId: "SVC4067" } #---------SVC4068------------------------------ -# %1 - max length +# %1 - max length VENDOR_RELEASE_EXCEEDS_LIMIT: { code: 400, message: "Error: Invalid Content. Vendor release exceeds limit of %1 characters.", messageId: "SVC4068" } -#---------SVC4069------------------------------ +#---------SVC4069------------------------------ # %1 - Service/Resource/Product COMPONENT_INVALID_CONTACT: { code: 400, - message: "Error: Invalid Content. %1 Contact id should be in format 'mnnnnnn' or 'aannna' or 'aannnn', where m=m ,a=a-zA-Z and n=0-9", + message: "Error: Invalid Content. %1 Contact Id should be in format 'mnnnnnn' or 'aannna' or 'aannnn', where m=m ,a=a-zA-Z and n=0-9", messageId: "SVC4069" } -#---------SVC4070------------------------------ +#---------SVC4070------------------------------ # %1 - Service/Resource INVALID_COMPONENT_NAME: { code: 400, @@ -259,27 +259,27 @@ errors: messageId: "SVC4070" } -#---------SVC4071------------------------------ +#---------SVC4071------------------------------ INVALID_VENDOR_NAME: { code: 400, message: 'Error: Invalid Content. Vendor name is not allowed to contain characters like <>:"\/|?* and space characters other than regular space.', messageId: "SVC4071" } -#---------SVC4072------------------------------ +#---------SVC4072------------------------------ INVALID_VENDOR_RELEASE: { code: 400, message: 'Error: Invalid Content. Vendor release is not allowed to contain characters like <>:"\/|?* and space characters other than regular space.', messageId: "SVC4072" } -#---------SVC4073------------------------------ +#---------SVC4073------------------------------ # %1 - Service/Resource -# %2 - max resource/service name +# %2 - max resource/service name COMPONENT_NAME_EXCEEDS_LIMIT: { code: 400, message: "Error: Invalid Content. %1 name exceeds limit of %2 characters.", messageId: "SVC4073" } -#---------SVC4080------------------------------ +#---------SVC4080------------------------------ # %1 - resource/service name # %2 - resource/service # %3 - First name of last modifier @@ -290,7 +290,7 @@ errors: message: "Error: Requested '%1' %2 is locked for modification by %3 %4(%5).", messageId: "SVC4080" } -#---------SVC4081----------------------------- +#---------SVC4081----------------------------- # %1 - resource/service name # %2 - resource/service # %3 - First name of last modifier @@ -302,7 +302,7 @@ errors: messageId: "SVC4081" } -#-----------SVC4082--------------------------- +#-----------SVC4082--------------------------- # %1 - resource/service name # %2 - resource/service # %3 - First name of last modifier @@ -392,7 +392,7 @@ errors: } #-----------SVC4102--------------------------- -# %1 - capability type name +# %1 - capability type name CAPABILITY_TYPE_ALREADY_EXIST: { code: 409, message: "Error: Capability Type with name '%1' already exists.", @@ -405,7 +405,7 @@ errors: messageId: "SVC4114" } #-----------SVC4115--------------------------- -# %1 - capability type name +# %1 - capability type name MISSING_CAPABILITY_TYPE: { code: 400, message: "Error: Invalid Content. Missing Capability Type '%1'.", @@ -483,7 +483,7 @@ errors: message: "Error: Artifact '%1' already exists.", messageId: "SVC4125" } -#---------SVC4126------------------------------ +#---------SVC4126------------------------------ # %1 - resource/service/product/... # %2 - field (tag, vendor name...) INVALID_FIELD_FORMAT: { @@ -518,7 +518,7 @@ errors: #-----------SVC4131--------------------------- # %1-resource/service # %2-srtifact/artifacts -# %3-semicolomn separated list of artifact +# %3-semicolomn separated list of artifact COMPONENT_MISSING_MANDATORY_ARTIFACTS: { code: 403, message: "Error: Missing mandatory informational %1 %2: [%3].", @@ -545,60 +545,60 @@ errors: message: "Error: Invalid Content. Missing interface life-cycle type.", messageId: "SVC4134" } -#---------SVC4135------------------------------ +#---------SVC4135------------------------------ SERVICE_CATEGORY_CANNOT_BE_CHANGED: { code: 400, message: "Error: Service category cannot be changed once the service is certified.", messageId: "SVC4135" } -#---------SVC4136------------------------------ -# %1 - distribution environment name +#---------SVC4136------------------------------ +# %1 - distribution environment name DISTRIBUTION_ENVIRONMENT_NOT_AVAILABLE: { code: 500, message: "Error: Requested distribution environment '%1' is not available.", messageId: "SVC4136" } -#---------SVC4137------------------------------ -# %1 - distribution environment name +#---------SVC4137------------------------------ +# %1 - distribution environment name DISTRIBUTION_ENVIRONMENT_NOT_FOUND: { code: 400, message: "Error: Requested distribution environment '%1' was not found.", messageId: "SVC4137" } -#---------SVC4138------------------------------ +#---------SVC4138------------------------------ DISTRIBUTION_ENVIRONMENT_INVALID: { code: 400, message: "Error: Invalid distribution environment.", messageId: "SVC4138" } -#---------SVC4139------------------------------ +#---------SVC4139------------------------------ # %1 - service name DISTRIBUTION_ARTIFACT_NOT_FOUND: { code: 409, message: "Error: Service '%1' cannot be distributed due to missing deployment artifacts.", messageId: "SVC4139" } -#---------SVC4200------------------------------ +#---------SVC4200------------------------------ # %1 - Service/Resource -# %2 - max icon name length +# %2 - max icon name length COMPONENT_ICON_EXCEEDS_LIMIT: { code: 400, message: "Error: Invalid Content. %1 icon name exceeds limit of %2 characters.", messageId: "SVC4200" } -#---------SVC4300------------------------------ +#---------SVC4300------------------------------ RESTRICTED_ACCESS: { code: 403, message: "Error: Restricted access.", messageId: "SVC4300" } -#---------SVC4301------------------------------ +#---------SVC4301------------------------------ RESTRICTED_OPERATION: { code: 409, message: "Error: Restricted operation.", messageId: "SVC4301" } -#---------SVC4500------------------------------ +#---------SVC4500------------------------------ MISSING_BODY: { code: 400 , message: "Error: Missing request body.", @@ -610,7 +610,7 @@ errors: message: "Error: Invalid Content. Missing mandatory parameter 'apiPublicKey'." , messageId: "SVC4501" } -#---------SVC4502------------------------------ +#---------SVC4502------------------------------ DISTRIBUTION_ENV_DOES_NOT_EXIST: { code: 400 , message: "Error: Invalid Body : Missing mandatory parameter 'distrEnvName'." , @@ -624,7 +624,7 @@ errors: messageId: "SVC4503" } -#---------SVC4504------------------------------ +#---------SVC4504------------------------------ # %1 - Service/Resource # %2 - service/resource version COMPONENT_VERSION_NOT_FOUND: { @@ -634,103 +634,103 @@ errors: } #-----------SVC4505--------------------------- #%1-artifact name - + ARTIFACT_NOT_FOUND: { code: 404, message: "Error: Artifact '%1' was not found.", messageId: "SVC4505" } -#---------SVC4506------------------------------ +#---------SVC4506------------------------------ MISSING_ENV_NAME: { code: 400 , message: "Error: Invalid Content. Missing mandatory parameter 'distrEnvName'.", messageId: "SVC4506" } -#---------SVC4507------------------------------ +#---------SVC4507------------------------------ COMPONENT_INVALID_TAGS_NO_COMP_NAME: { code: 400, message: "Error: Invalid Content. One of the tags should be the component name.", messageId: "SVC4507" } - -#---------SVC4508------------------------------ + +#---------SVC4508------------------------------ SERVICE_NAME_CANNOT_BE_CHANGED: { code: 400, message: "Error: Service name cannot be changed once the service is certified.", messageId: "SVC4508" } -#---------SVC4509------------------------------ +#---------SVC4509------------------------------ SERVICE_ICON_CANNOT_BE_CHANGED: { code: 400, message: "Error: Icon cannot be changed once the service is certified.", messageId: "SVC4509" } -#---------SVC4510------------------------------ +#---------SVC4510------------------------------ # %1 - icon name max length SERVICE_ICON_EXCEEDS_LIMIT: { code: 400, message: "Error: Invalid Content. Icon name exceeds limit of %1 characters.", messageId: "SVC4510" } -#---------SVC4511------------------------------ +#---------SVC4511------------------------------ DISTRIBUTION_REQUESTED_NOT_FOUND: { code: 404, message: "Error: Requested distribution was not found.", messageId: "SVC4511" } -#---------SVC4512------------------------------ +#---------SVC4512------------------------------ # %1 - Distribution ID DISTRIBUTION_REQUESTED_FAILED: { code: 403, message: "Error: Requested distribution '%1' failed.", messageId: "SVC4512" } -#---------SVC4513------------------------------ +#---------SVC4513------------------------------ RESOURCE_CATEGORY_CANNOT_BE_CHANGED: { code: 400, message: "Error: Resource category cannot be changed once the resource is certified.", messageId: "SVC4513" } -#---------SVC4514------------------------------ +#---------SVC4514------------------------------ RESOURCE_NAME_CANNOT_BE_CHANGED: { code: 400, message: "Error: Resource name cannot be changed once the resource is certified.", messageId: "SVC4514" } -#---------SVC4515------------------------------ +#---------SVC4515------------------------------ RESOURCE_ICON_CANNOT_BE_CHANGED: { code: 400, message: "Error: Icon cannot be changed once the resource is certified.", messageId: "SVC4515" } -#---------SVC4516------------------------------ +#---------SVC4516------------------------------ RESOURCE_VENDOR_NAME_CANNOT_BE_CHANGED: { code: 400, message: "Error: Vendor name cannot be changed once the resource is certified.", messageId: "SVC4516" } -#---------SVC4517------------------------------ +#---------SVC4517------------------------------ RESOURCE_DERIVED_FROM_CANNOT_BE_CHANGED: { code: 400, message: "Error: Derived from resource template cannot be changed once the resource is certified.", messageId: "SVC4517" } -#---------SVC4518------------------------------ -# %1 - max length +#---------SVC4518------------------------------ +# %1 - max length COMPONENT_SINGLE_TAG_EXCEED_LIMIT: { code: 400, message: "Error: Invalid Content. Single tag exceeds limit of %1 characters.", messageId: "SVC4518" } -#---------SVC4519------------------------------ +#---------SVC4519------------------------------ INVALID_DEFAULT_VALUE: { code: 400, message: "Error: mismatch in data-type occurred for property %1. data type is %2 and default value found is %3.", messageId: "SVC4519" } -#---------SVC4520------------------------------ -# %1 - service or resource +#---------SVC4520------------------------------ +# %1 - service or resource ADDITIONAL_INFORMATION_MAX_NUMBER_REACHED: { code: 409, message: "Error: Maximal number of additional %1 parameters was reached.", @@ -742,7 +742,7 @@ errors: message: "Error: Invalid Content. The Additional information label and value cannot be empty.", messageId: "SVC4521" } -#---------SVC4522------------------------------ +#---------SVC4522------------------------------ # %1 - label/value # %2 - Maximal length of %1 ADDITIONAL_INFORMATION_EXCEEDS_LIMIT: { @@ -762,32 +762,32 @@ errors: message: "Error: Requested additional information was not found.", messageId: "SVC4524" } -#---------SVC4525------------------------------ +#---------SVC4525------------------------------ ADDITIONAL_INFORMATION_VALUE_NOT_ALLOWED_CHARACTERS: { code: 400, message: 'Error: Invalid Content. Additional information contains non-english characters.', messageId: "SVC4525" } -#---------SVC4526------------------------------ +#---------SVC4526------------------------------ RESOURCE_INSTANCE_NOT_FOUND: { code: 404, message: "Error: Requested '%1' resource instance was not found.", messageId: "SVC4526" } -#---------SVC4527------------------------------ +#---------SVC4527------------------------------ ASDC_VERSION_NOT_FOUND: { code: 500, message: 'Error: ASDC version cannot be displayed.', messageId: "SVC4527" } -#---------SVC4528------------------------------ +#---------SVC4528------------------------------ # %1-artifact url/artifact label/artifact description/VNF Service Indicator MISSING_DATA: { code: 400, message: "Error: Invalid content. Missing %1.", messageId: "SVC4528" } -#---------SVC4529------------------------------ +#---------SVC4529------------------------------ # %1-artifact url/artifact label/artifact description/artifact name # %2 - Maximal length of %1 EXCEEDS_LIMIT: { @@ -795,51 +795,51 @@ errors: message: "Error: Invalid Content. %1 exceeds limit of %2 characters.", messageId: "SVC4529" } -#---------SVC4530------------------------------ +#---------SVC4530------------------------------ ARTIFACT_INVALID_TIMEOUT: { code: 400, message: "Error: Invalid Content. Artifact Timeout should be set to valid positive non-zero number of minutes.", messageId: "SVC4530" } -#---------SVC4531------------------------------ +#---------SVC4531------------------------------ SERVICE_IS_VNF_CANNOT_BE_CHANGED: { code: 400, message: "Error: VNF Indicator cannot be updated for certified service.", messageId: "SVC4531" } - #---------SVC4532------------------------------ + #---------SVC4532------------------------------ RESOURCE_INSTANCE_NOT_FOUND_ON_SERVICE: { code: 404, message: "Error: Requested '%1' resource instance was not found on the service '%2.", messageId: "SVC4532" } - #---------SVC4533------------------------------ - # %1 - "HEAT"/"HEAT_ENV"/"MURANO_PKG"/"YANG_XML" + #---------SVC4533------------------------------ + # %1 - "HEAT"/"HEAT_ENV"/"MURANO_PKG"/"YANG_XML" WRONG_ARTIFACT_FILE_EXTENSION: { code: 400, message: "Error: Invalid file extension for %1 artifact type.", messageId: "SVC4533" } -#---------SVC4534------------------------------ -# %1 - "HEAT"/"HEAT_ENV" +#---------SVC4534------------------------------ +# %1 - "HEAT"/"HEAT_ENV" INVALID_YAML: { code: 400, message: "Error: Uploaded YAML file for %1 artifact is invalid.", messageId: "SVC4534" } -#---------SVC4535------------------------------ -# %1 - "HEAT" +#---------SVC4535------------------------------ +# %1 - "HEAT" INVALID_DEPLOYMENT_ARTIFACT_HEAT: { code: 400, message: "Error: Invalid %1 artifact.", messageId: "SVC4535" } -#---------SVC4536------------------------------ +#---------SVC4536------------------------------ # %1 - "Resource"/"Service" -# %2 - resource/service name -# %3 - "HEAT"/"HEAT_ENV"/"MURANO_PKG" +# %2 - resource/service name +# %3 - "HEAT"/"HEAT_ENV"/"MURANO_PKG" # %4 - "HEAT"/"HEAT_ENV"/"MURANO_PKG DEPLOYMENT_ARTIFACT_OF_TYPE_ALREADY_EXISTS: { code: 400, @@ -847,80 +847,80 @@ errors: messageId: "SVC4536" } -#---------SVC4537------------------------------ +#---------SVC4537------------------------------ MISSING_HEAT: { code: 400, message: "Error: Missing HEAT artifact. HEAT_ENV artifact cannot be uploaded without corresponding HEAT template.", messageId: "SVC4537" } -#---------SVC4538------------------------------ +#---------SVC4538------------------------------ MISMATCH_HEAT_VS_HEAT_ENV: { code: 400, message: "Error: Invalid artifact content. Parameter's set in HEAT_ENV '%1' artifact doesn't match the parameters in HEAT '%2' artifact.", messageId: "SVC4538" } -#---------SVC4539------------------------------ +#---------SVC4539------------------------------ INVALID_RESOURCE_PAYLOAD: { code: 400, message: "Error: Invalid resource payload.", messageId: "SVC4539" } -#---------SVC4540------------------------------ +#---------SVC4540------------------------------ INVALID_TOSCA_FILE_EXTENSION: { code: 400, message: "Error: Invalid file extension for TOSCA template.", messageId: "SVC4540" } -#---------SVC4541------------------------------ +#---------SVC4541------------------------------ INVALID_YAML_FILE: { code: 400, message: "Error: Invalid YAML file.", messageId: "SVC4541" } -#---------SVC4542------------------------------ +#---------SVC4542------------------------------ INVALID_TOSCA_TEMPLATE: { code: 400, message: "Error: Invalid TOSCA template.", messageId: "SVC4542" } -#---------SVC4543------------------------------ +#---------SVC4543------------------------------ NOT_RESOURCE_TOSCA_TEMPLATE: { code: 400, message: "Error: Imported Service TOSCA template.", messageId: "SVC4543" } -#---------SVC4544------------------------------ +#---------SVC4544------------------------------ NOT_SINGLE_RESOURCE: { code: 400, message: "Error: Imported TOSCA template should contain one resource definition.", messageId: "SVC4544" } -#---------SVC4545------------------------------ +#---------SVC4545------------------------------ INVALID_RESOURCE_NAMESPACE: { code: 400, message: "Error: Invalid resource namespace.", messageId: "SVC4545" } -#---------SVC4546------------------------------ +#---------SVC4546------------------------------ RESOURCE_ALREADY_EXISTS: { code: 400, message: "Error: Imported resource already exists in ASDC Catalog.", messageId: "SVC4546" } -#---------SVC4549------------------------------ +#---------SVC4549------------------------------ INVALID_RESOURCE_CHECKSUM: { code: 400, message: "Error: Invalid resource checksum.", messageId: "SVC4549" } -#---------SVC4550------------------------------ +#---------SVC4550------------------------------ #%1  -  Consumer salt INVALID_LENGTH: { code: 400, message: "Error: Invalid %1 length.", messageId: "SVC4550" } - #---------SVC4551------------------------------ + #---------SVC4551------------------------------ #%1  -  ECOMP User name ECOMP_USER_NOT_FOUND: { code: 404, @@ -934,13 +934,13 @@ errors: messageId: "SVC4552" } #---------SVC4553----------------------------- - #%1  -  Consumer name / Consumer password/ Consumer salt + #%1  -  Consumer name / Consumer password/ Consumer salt INVALID_CONTENT_PARAM: { code: 400, message: "Error: %1 is invalid.", messageId: "SVC4553" } - #---------SVC4554------------------------------ + #---------SVC4554------------------------------ # %1 - "Resource"/"Service" COMPONENT_ARTIFACT_NOT_FOUND: { code: 404, @@ -954,7 +954,7 @@ errors: message: "Error: Requested '%1' service is not ready for certification. Service has to have at least one deployment artifact.", messageId: "SVC4554" } -#---------SVC4555------------------------------ +#---------SVC4555------------------------------ #%1 - "Resource"/"Service"/"Product" #%2 - "category" COMPONENT_ELEMENT_INVALID_NAME_LENGTH: { @@ -962,7 +962,7 @@ errors: message: "Error: Invalid %1 %2 name length.", messageId: "SVC4555" } -#---------SVC4556------------------------------ +#---------SVC4556------------------------------ #%1 - "Resource"/"Service"/"Product" #%2 - "category" COMPONENT_ELEMENT_INVALID_NAME_FORMAT: { @@ -970,7 +970,7 @@ errors: message: "Error: Invalid %1 %2 name format.", messageId: "SVC4556" } -#---------SVC4557------------------------------ +#---------SVC4557------------------------------ #%1 - "Resource"/"Service"/"Product" #%2 - "category name" COMPONENT_CATEGORY_ALREADY_EXISTS: { @@ -1001,7 +1001,7 @@ errors: code: 403, message: "Error: Submit for Testing is not permitted as your '%1' includes non-validated '%2' resource. Please use one of available validated resource versions.", messageId: "SVC4560" - } + } #---------SVC4561------------------------------ # %1 - "resource"/"product" # %2 - "category" @@ -1029,108 +1029,108 @@ errors: message: "Error: %1 grouping '%2' already exists under '%3' sub-category.", messageId: "SVC4563" } -#---------SVC4564------------------------------ +#---------SVC4564------------------------------ # %1 - product name PRODUCT_NOT_FOUND: { code: 404, message: "Error: Requested '%1' product was not found.", messageId: "SVC4564" } -#---------SVC4565------------------------------ -# %1 - "HEAT" -# %2 - parameter type ("string" , "boolean" , "number") +#---------SVC4565------------------------------ +# %1 - "HEAT" +# %2 - parameter type ("string" , "boolean" , "number") # %3 - parameter name INVALID_HEAT_PARAMETER_VALUE: { code: 400, message: "Error: Invalid %1 artifact. Invalid %2 value set for '%3' parameter.", messageId: "SVC4565" } -#---------SVC4566------------------------------ -# %1 - "HEAT" -# %2 - parameter type ("string" , "boolean" , "number") +#---------SVC4566------------------------------ +# %1 - "HEAT" +# %2 - parameter type ("string" , "boolean" , "number") INVALID_HEAT_PARAMETER_TYPE: { code: 400, message: "Error: Invalid %1 artifact. Unsupported '%2' parameter type.", messageId: "SVC4566" } -#---------SVC4567------------------------------ -# %1 - "YANG_XML" +#---------SVC4567------------------------------ +# %1 - "YANG_XML" INVALID_XML: { code: 400, message: "Error: Uploaded XML file for %1 artifact is invalid.", messageId: "SVC4567" } -#---------SVC4567------------------------------ -# %1 - "User Name and UserId" +#---------SVC4567------------------------------ +# %1 - "User Name and UserId" # %2 -"checked-out"/"in-certification" CANNOT_DELETE_USER_WITH_ACTIVE_ELEMENTS: { code: 409, message: "Error: User cannot be deleted. User '%1' has %2 projects.", messageId: "SVC4567" } -#---------SVC4568------------------------------ -# %1 - "User Name and UserId" +#---------SVC4568------------------------------ +# %1 - "User Name and UserId" # %2 -"checked-out"/"in-certification" CANNOT_UPDATE_USER_WITH_ACTIVE_ELEMENTS: { code: 409, message: "Error: Role cannot be changed. User '%1' has %2 projects.", messageId: "SVC4568" } -#---------SVC4570------------------------------ +#---------SVC4570------------------------------ UPDATE_USER_ADMIN_CONFLICT: { code: 409, message: "Error: An administrator is not allowed to change his/her role.", messageId: "SVC4570" } -#---------SVC4571------------------------------ +#---------SVC4571------------------------------ SERVICE_CANNOT_CONTAIN_SUBCATEGORY: { code: 400, message: "Error: Sub category cannot be defined for service", messageId: "SVC4571" } -#---------SVC4572------------------------------ +#---------SVC4572------------------------------ # %1 - "Resource"/"Service" COMPONENT_TOO_MUCH_CATEGORIES: { code: 400, message: "Error: %1 must have only 1 category", messageId: "SVC4572" } -#---------SVC4574------------------------------ +#---------SVC4574------------------------------ RESOURCE_TOO_MUCH_SUBCATEGORIES: { code: 400, message: "Error: Resource must have only 1 sub category", messageId: "SVC4574" } -#---------SVC4575------------------------------ +#---------SVC4575------------------------------ COMPONENT_MISSING_SUBCATEGORY: { code: 400, message: "Error: Missing sub category", messageId: "SVC4575" } - #---------SVC4576------------------------------ + #---------SVC4576------------------------------ # %1 - "component type" UNSUPPORTED_ERROR: { code: 400, message: "Error : Requested component type %1 is unsupported.", messageId: "SVC4576" } - #---------SVC4577------------------------------ + #---------SVC4577------------------------------ # %1 - "resource type" RESOURCE_CANNOT_CONTAIN_RESOURCE_INSTANCES: { code: 409, message: "Error : Resource of type %1 cannot contain resource instances.", messageId: "SVC4577" } -#---------SVC4578------------------------------ +#---------SVC4578------------------------------ # %1 - "Resource"/"Service" -# %2 - resource/service name -# %3 - "artifact name" +# %2 - resource/service name +# %3 - "artifact name" DEPLOYMENT_ARTIFACT_NAME_ALREADY_EXISTS: { code: 400, message: "Error: %1 '%2' already has a deployment artifact named '%3'.", messageId: "SVC4578" } -#---------SVC4579------------------------------ +#---------SVC4579------------------------------ # %1 - "Category"/"Sub-Category"/"Group" # %2 - category/sub-category/grouping name. INVALID_GROUP_ASSOCIATION: { @@ -1138,27 +1138,27 @@ errors: message: "Error: Invalid group association. %1 '%2' was not found.", messageId: "SVC4579" } -#---------SVC4580------------------------------ +#---------SVC4580------------------------------ EMPTY_PRODUCT_CONTACTS_LIST: { code: 400, message: "Error: Invalid content. At least one Product Contact has to be specified.", messageId: "SVC4580" } -#---------SVC4581------------------------------ -# %1 - userId +#---------SVC4581------------------------------ +# %1 - UserId INVALID_PRODUCT_CONTACT: { code: 400, message: "Error: Invalid content. User '%1' cannot be set as Product Contact.", messageId: "SVC4581" } -#---------SVC4582------------------------------ +#---------SVC4582------------------------------ # %1 - Product # %2 - "abbreviated"/"full" MISSING_ONE_OF_COMPONENT_NAMES: { code: 400, message: "Error: Invalid content. Missing %1 %2 name.", messageId: "SVC4582" - } + } #---------SVC4583------------------------------ # %1 - "Icon" # %2 - "resource"/"service"/"product" @@ -1168,10 +1168,10 @@ errors: messageId: "SVC4583" } #---------SVC4584------------------------------ -# %1 - service/VF name +# %1 - service/VF name # %2 - "service" /"VF" # %3 - resource instance origin type -# %4 - resource instance name +# %4 - resource instance name # %5 - requirement/capability # %6 - requirement/capability name # %7 - "fulfilled" (for req)/"consumed (for cap)" @@ -1180,57 +1180,57 @@ errors: message: "Error: Requested '%1' %2 is not ready for certification. %3 '%4' has to have %5 '%6' %7.", messageId: "SVC4584" } -#---------SVC4585------------------------------ +#---------SVC4585------------------------------ INVALID_OCCURRENCES: { code: 400, message: "Error: Invalid occurrences format.", messageId: "SVC4585" } -#---------SVC4586------------------------------ -#---------SVC4586------------------------------ +#---------SVC4586------------------------------ +#---------SVC4586------------------------------ INVALID_SERVICE_API_URL: { code: 400, message: 'Error: Invalid Service API URL. Please check whether your URL has a valid domain extension and does not contain the following characters - #?&@%+;,=$<>~^`\[]{}|"*!', messageId: "SVC4586" } -#---------SVC4587------------------------------ -# %1 - Data type name +#---------SVC4587------------------------------ +# %1 - Data type name DATA_TYPE_ALREADY_EXIST: { code: 409, message: 'Error: Data type %1 already exists.', messageId: "SVC4587" } -#---------SVC4588------------------------------ -# %1 - Data type name +#---------SVC4588------------------------------ +# %1 - Data type name DATA_TYPE_NOR_PROPERTIES_NEITHER_DERIVED_FROM: { code: 400, message: 'Error: Invalid Data type %1. Data type must have either a valid derived from declaration or at least one valid property', messageId: "SVC4588" } -#---------SVC4589------------------------------ -# %1 - Data type name +#---------SVC4589------------------------------ +# %1 - Data type name DATA_TYPE_PROPERTIES_CANNOT_BE_EMPTY: { code: 400, message: "Error: Invalid Data type %1. 'properties' parameter cannot be empty if provided.", messageId: "SVC4589" } -#---------SVC4590------------------------------ -# %1 - Property type name +#---------SVC4590------------------------------ +# %1 - Property type name # %2 - Property name INVALID_PROPERTY_TYPE: { code: 400, message: "Error: Invalid Property type %1 in property %2.", messageId: "SVC4590" } -#---------SVC4591------------------------------ +#---------SVC4591------------------------------ # %1 - Property inner type -# %2 - Property name +# %2 - Property name INVALID_PROPERTY_INNER_TYPE: { code: 400, message: "Error: Invalid property inner type %1, in property %2", messageId: "SVC4591" } -#---------SVC4592------------------------------ +#---------SVC4592------------------------------ # %1 - component instance name # %2 - "resource instance"/"service instance" COMPONENT_INSTANCE_NOT_FOUND: { @@ -1238,11 +1238,11 @@ errors: message: "Error: Requested '%1' %2 was not found.", messageId: "SVC4592" } -#---------SVC4593------------------------------ +#---------SVC4593------------------------------ # %1 - component instance name # %2 - "resource instance"/"service instance" # %3 - "resource/"service"/"product" -# %4 - container name +# %4 - container name COMPONENT_INSTANCE_NOT_FOUND_ON_CONTAINER: { code: 404, message: "Error: Requested '%1' %2 was not found on the %3 '%4'.", @@ -1259,20 +1259,20 @@ errors: #---------SVC4595------------------------------ #%1 - requirement / capability #%2 - requirement name -#%3 - parent containing the requirement +#%3 - parent containing the requirement IMPORT_REQ_CAP_NAME_EXISTS_IN_DERIVED: { code: 400, message: "Error: Imported TOSCA template contains %1 '%2' that is already defined by derived template %3.", messageId: "SVC4595" } -#---------SVC4596------------------------------ +#---------SVC4596------------------------------ # %1 - Data type name DATA_TYPE_DERIVED_IS_MISSING: { code: 400, message: "Error: Invalid Content. The ancestor data type %1 cannot be found in the system.", messageId: "SVC4596" } -#---------SVC4597------------------------------ +#---------SVC4597------------------------------ # %1 - Data type name # %2 - Property names DATA_TYPE_PROPERTY_ALREADY_DEFINED_IN_ANCESTOR: { @@ -1280,14 +1280,14 @@ errors: message: "Error: Invalid Content. The data type %1 contains properties named %2 which are already defined in one of its ancestors.", messageId: "SVC4597" } -#---------SVC4598------------------------------ +#---------SVC4598------------------------------ # %1 - Data type name DATA_TYPE_DUPLICATE_PROPERTY: { code: 400, message: "Error: Invalid Content. The data type %1 contains duplicate property.", messageId: "SVC4598" } -#---------SVC4599------------------------------ +#---------SVC4599------------------------------ # %1 - Data type name # %2 - Property names DATA_TYPE_PROEPRTY_CANNOT_HAVE_SAME_TYPE_OF_DATA_TYPE: { @@ -1295,14 +1295,14 @@ errors: message: "Error: Invalid Content. The data type %1 contains properties %2 which their type is this data type.", messageId: "SVC4599" } -#---------SVC4600------------------------------ +#---------SVC4600------------------------------ # %1 - Data type name DATA_TYPE_CANNOT_HAVE_PROPERTIES: { code: 400, message: "Error: Invalid Content. The data type %1 cannot have properties since it is of type scalar", messageId: "SVC4600" } -#---------SVC4601------------------------------ +#---------SVC4601------------------------------ NOT_TOPOLOGY_TOSCA_TEMPLATE: { code: 400, message: "Error: TOSCA yaml file %1 cannot be modeled to VF as it does not contain 'topology_template.", @@ -1317,7 +1317,7 @@ errors: message: "Error: TOSCA yaml file '%1' contains node_template '%2' of type '%3' that does not represent existing VFC/CP/VL", messageId: "SVC4602" } -#---------SVC4603------------------------------ +#---------SVC4603------------------------------ # %1 - component type # %2 - component name # %3 - state @@ -1326,21 +1326,21 @@ errors: message: "Error: Component instance of %1 can not be created because the component '%2' is in an illegal state %3.", messageId: "SVC4603" } -#---------SVC4604------------------------------ +#---------SVC4604------------------------------ # %1 - csar file name CSAR_INVALID: { code: 400, message: "Error: TOSCA CSAR '%1' is invalid. 'TOSCA-Metadata/Tosca.meta' file must be provided.", messageId: "SVC4604" } -#---------SVC4605------------------------------ +#---------SVC4605------------------------------ # %1 - csar file name CSAR_INVALID_FORMAT: { code: 400, message: "Error: TOSCA CSAR '%1' is invalid. Invalid 'TOSCA-Metadata/Tosca.meta' file format.", messageId: "SVC4605" } -#---------SVC4606------------------------------ +#---------SVC4606------------------------------ # %1 - property name # %2 - property type # %3 - property innerType @@ -1350,14 +1350,14 @@ errors: message: "Error: Invalid default value of property %1. Data type is %2 with inner type %3 and default value found is %4.", messageId: "SVC4606" } -#---------SVC4607------------------------------ +#---------SVC4607------------------------------ # %1 - csar file name CSAR_NOT_FOUND: { code: 400, message: "Error: TOSCA CSAR '%1' is not found.", messageId: "SVC4607" } -#---------SVC4608------------------------------ +#---------SVC4608------------------------------ # %1 - artifact name # %2 - component type # %3 - actual component type @@ -1367,14 +1367,14 @@ errors: messageId: "SVC4608" } -#---------SVC4609------------------------------ -# %1 - "INVALID_JSON" +#---------SVC4609------------------------------ +# %1 - "INVALID_JSON" INVALID_JSON: { code: 400, message: "Error: Uploaded JSON file for %1 artifact is invalid.", messageId: "SVC4609" } -#---------SVC4610------------------------------ +#---------SVC4610------------------------------ # %1 - csar file name # %2 - missing file name YAML_NOT_FOUND_IN_CSAR: { @@ -1382,21 +1382,21 @@ errors: message: "Error - TOSCA CSAR %1 is invalid. TOSCA-Metadata/Tosca.meta refers to file %2 that is not provided.", messageId: "SVC4610" } -#---------SVC4611------------------------------ +#---------SVC4611------------------------------ # %1 - group name GROUP_MEMBER_EMPTY: { code: 400, message: "Error: Invalid Content. Group %1 member list was provided but does not have values", messageId: "SVC4611" } -#---------SVC4612------------------------------ -# %1 - group name +#---------SVC4612------------------------------ +# %1 - group name GROUP_TYPE_ALREADY_EXIST: { code: 409, message: 'Error: Group type %1 already exists.', messageId: "SVC4612" } -#---------SVC4613------------------------------ +#---------SVC4613------------------------------ # %1 - group name # %2 - VF name(component name) # %3 - actual component type [VF] @@ -1404,15 +1404,15 @@ errors: code: 409, message: "Error: Group with name '%1' already exists in %2 %3.", messageId: "SVC4613" - } -#---------SVC4614------------------------------ + } +#---------SVC4614------------------------------ # %1 - group type GROUP_TYPE_IS_INVALID: { code: 400, message: "Error: Invalid content. Group type %1 does not exist", messageId: "SVC4614" } -#---------SVC4615------------------------------ +#---------SVC4615------------------------------ # %1 - group name GROUP_MISSING_GROUP_TYPE: { code: 400, @@ -1428,7 +1428,7 @@ errors: code: 400, message: "Error: Member '%1' listed in group '%2' is not part of '%3' %4.", messageId: "SVC4616" - } + } #---------SVC4617------------------------------ # %1 - member name # %2 - group name @@ -1438,7 +1438,7 @@ errors: message: "Error: member %1 listed in group %2 is not part of allowed members of group type %3.", messageId: "SVC4617" } -#---------SVC4618------------------------------ +#---------SVC4618------------------------------ # %1 - missing file name # %2 - csar file name ARTIFACT_NOT_FOUND_IN_CSAR: { @@ -1446,7 +1446,7 @@ errors: message: "Error: artifact %1 is defined in CSAR %2 manifest but is not provided", messageId: "SVC4618" } -#---------SVC4619------------------------------ +#---------SVC4619------------------------------ # %1 - artifact name # %2 - artifact type # %3 - existing artifact type @@ -1455,23 +1455,23 @@ errors: message: "Error: artifact %1 in type %2 already exists in type %3.", messageId: "SVC4619" } -#---------SVC4620------------------------------ +#---------SVC4620------------------------------ FAILED_RETRIVE_ARTIFACTS_TYPES: { code: 400, message: "Error: Failed to retrieve list of suported artifact types.", messageId: "SVC4620" } -#---------SVC4621------------------------------ +#---------SVC4621------------------------------ # %1 - artifact name -# %2 - master +# %2 - master ARTIFACT_ALRADY_EXIST_IN_MASTER_IN_CSAR: { code: 400, message: "Error: artifact %1 already exists in master %2 .", messageId: "SVC4621" } -#---------SVC4622------------------------------ +#---------SVC4622------------------------------ # %1 - artifact name -# %2 - artifact type +# %2 - artifact type # %3 - master name # %4 - master type ARTIFACT_NOT_VALID_IN_MASTER: { @@ -1479,9 +1479,9 @@ errors: message: "Error: artifact %1 in type %2 can not be exists under master %3 in type %4.", messageId: "SVC4622" } -#---------SVC4623------------------------------ +#---------SVC4623------------------------------ # %1 - artifact name -# %2 - artifact type +# %2 - artifact type # %3 - env name # %4 - existing env ARTIFACT_NOT_VALID_ENV: { @@ -1489,7 +1489,7 @@ errors: message: "Error: Artifact %1 in type %2 with env %3 already exists with another env %4", messageId: "SVC4623" } -#---------SVC4624------------------------------ +#---------SVC4624------------------------------ # %1 - groups names # %2 - VF name # %3 - component type [VF ] @@ -1498,14 +1498,14 @@ errors: message: "Error: Invalid Content. The groups '%1' cannot be found under %2 %3.", messageId: "SVC4624" } -#---------SVC4625------------------------------ +#---------SVC4625------------------------------ # %1 - groups name GROUP_ARTIFACT_ALREADY_ASSOCIATED: { code: 400, message: "Error: Invalid Content. Artifact already associated to group '%1'.", messageId: "SVC4625" } -#---------SVC4626------------------------------ +#---------SVC4626------------------------------ # %1 - groups name GROUP_ARTIFACT_ALREADY_DISSOCIATED: { code: 400, @@ -1521,7 +1521,7 @@ errors: message: "Error: property %1 listed in group %2 is not exist in group type %3.", messageId: "SVC4627" } -#---------SVC4628------------------------------ +#---------SVC4628------------------------------ # %1 - csarUUID # %2 - VF name VSP_ALREADY_EXISTS: { @@ -1529,14 +1529,14 @@ errors: message: "Error: The VSP with UUID %1 was already imported for VF %2. Please select another or update the existing VF.", messageId: "SVC4628" } -#---------SVC4629------------------------------ +#---------SVC4629------------------------------ # %1 - VF name MISSING_CSAR_UUID: { code: 400, message: "Error: The Csar UUID or payload name is missing for VF %1.", messageId: "SVC4629" } -#---------SVC4630------------------------------ +#---------SVC4630------------------------------ # %1 - VF name # %2 - new csarUUID # %3 - old csarUUID @@ -1545,8 +1545,8 @@ errors: message: "Error: Resource %1 cannot be updated using CsarUUID %2 since the resource is linked to a different VSP with csarUUID %3.", messageId: "SVC4630" } -#---------SVC4631------------------------------ -# %1 - policy name +#---------SVC4631------------------------------ +# %1 - policy name POLICY_TYPE_ALREADY_EXIST: { code: 409, message: "Error: Policy type %1 already exists.", @@ -1593,7 +1593,7 @@ errors: code: 404, message: "Error: Requested '%1' attribute was not found.", messageId: "SVC4637" - } + } #-----------SVC4638--------------------------- #%1 - attribute name ATTRIBUTE_ALREADY_EXIST: { @@ -1661,7 +1661,7 @@ errors: message: "Error: Invalid Content. VF Module name '%1' contains invalid characters", messageId: "SVC4646" } - + #---------SVC4647------------------------------ # %1 - "modifiedName" INVALID_VF_MODULE_NAME_MODIFICATION: { @@ -1699,23 +1699,23 @@ errors: message: "Error: Once resource is certified, derived_from can be changed only to a sibling", messageId: "SVC4651" } -#---------SVC4652------------------------------ +#---------SVC4652------------------------------ # %1 - resource/service COMPONENT_INVALID_SUBCATEGORY: { code: 400, message: "Error: Invalid Content. Invalid %1 sub category.", messageId: "SVC4652" } -#---------SVC4653------------------------------ -# %1 - group instance uniqueId +#---------SVC4653------------------------------ +# %1 - group instance uniqueId # %2 - service uniqueId GROUP_INSTANCE_NOT_FOUND_ON_COMPONENT_INSTANCE: { code: 404, message: "Error: Requested group instance %1 was not found on component %2.", messageId: "SVC4653" } -#---------SVC4654------------------------------ -# %1 - group property name +#---------SVC4654------------------------------ +# %1 - group property name # %2 - valid min limit value # %3 - valid max limit value INVALID_GROUP_MIN_MAX_INSTANCES_PROPERTY_VALUE: { @@ -1723,8 +1723,8 @@ errors: message: "Error: Value of %1 must be not higher than %2, and not lower than %3.", messageId: "SVC4654" } -#---------SVC4655------------------------------ -# %1 - group property name +#---------SVC4655------------------------------ +# %1 - group property name # %2 - valid min limit value # %3 - valid max limit value INVALID_GROUP_INITIAL_COUNT_PROPERTY_VALUE: { @@ -1732,15 +1732,15 @@ errors: message: "Error: Value of %1 must be between %2 and %3.", messageId: "SVC4655" } -#---------SVC4656------------------------------ -# %1 - group property name +#---------SVC4656------------------------------ +# %1 - group property name # %2 - lower/higher # %3 - valid max/min value INVALID_GROUP_PROPERTY_VALUE_LOWER_HIGHER: { code: 400, message: "Error: Value of %1 must be %2 or equals to %3.", messageId: "SVC4656" - } + } #---------SVC4657------------------------------ # %1 - certificationRequest / startTesting RESOURCE_VFCMT_LIFECYCLE_STATE_NOT_VALID: { @@ -1752,7 +1752,7 @@ errors: # %1 – asset type [service / resource ] # %2 – main asset uuid # %3 – not found asset type [service / resource] -# %4 – not found asset name +# %4 – not found asset name ASSET_NOT_FOUND_DURING_CSAR_CREATION: { code: 400, message: "Error: CSAR packaging failed for %1 %2. %3 %4 was not found", @@ -1761,10 +1761,87 @@ errors: #---------SVC4659------------------------------ # %1 – asset type [service / resource ] # %2 – main asset uuid -# %3 – Artifact name +# %3 – Artifact name # %4 – Artifact uuid ARTIFACT_PAYLOAD_NOT_FOUND_DURING_CSAR_CREATION: { code: 400, - message: " Error: CSAR packaging failed for %1 %2. Artifact %3 [%4] was not found", + message: "Error: CSAR packaging failed for %1 %2. Artifact %3 [%4] was not found", messageId: "SVC4659" + } +#---------SVC4660------------------------------ +# %1 - assetType +# %2 - matching generic node type name + GENERIC_TYPE_NOT_FOUND: { + code: 404, + message: "Creation of %1 failed. Generic type %2 was not found", + messageId: "SVC4660" + } +#---------SVC4661------------------------------ +# %1 - assetType +# %2 - matching generic node type name + TOSCA_SCHEMA_FILES_NOT_FOUND: { + code: 400, + message: "Error: CSAR packaging failed. TOSCA schema files for SDC-Version: %1 and Conformance-Level %2 were not found", + messageId: "SVC4661" + } +#---------SVC4662------------------------------ +# %1 - file name +# %2 - parser error + TOSCA_PARSE_ERROR: { + code: 400, + message: "Error: Invalid TOSCA template in file %1. %2", + messageId: "SVC4662" + } +#---------SVC4663------------------------------ +# %1 - max length + RESOURCE_VENDOR_MODEL_NUMBER_EXCEEDS_LIMIT: { + code: 400, + message: "Error: Invalid Content. Resource vendor model number exceeds limit of %1 characters.", + messageId: "SVC4663" + } +#---------SVC4664------------------------------ + INVALID_RESOURCE_VENDOR_MODEL_NUMBER: { + code: 400, + message: 'Error: Invalid Content. Resource vendor model number is not allowed to contain characters like <>:"\/|?* and space characters other than regular space.', + messageId: "SVC4664" + } +#---------SVC4665------------------------------ +# %1 - max length + SERVICE_TYPE_EXCEEDS_LIMIT: { + code: 400, + message: "Error: Invalid Content. Service type exceeds limit of %1 characters.", + messageId: "SVC4665" + } +#---------SVC4666------------------------------ + INVALID_SERVICE_TYPE: { + code: 400, + message: 'Error: Invalid Content. Serivce type is not allowed to contain characters like <>:"\/|?* and space characters other than regular space.', + messageId: "SVC4666" + } +#---------SVC4667------------------------------ +# %1 - max length + SERVICE_ROLE_EXCEEDS_LIMIT: { + code: 400, + message: "Error: Invalid Content. Service role exceeds limit of %1 characters.", + messageId: "SVC4667" + } +#---------SVC4668------------------------------ + INVALID_SERVICE_ROLE: { + code: 400, + message: 'Error: Invalid Content. Service role is not allowed to contain characters like <>:"\/|?* and space characters other than regular space.', + messageId: "SVC4668" + } + + #---------SVC4669----------------------------- + INVALID_RESOURCE_TYPE: { + code: 400, + message: "Error: Invalid resource type.", + messageId: "SVC4669" + } + + #---------SVC4670------------------------------ + ARTIFACT_NAME_INVALID: { + code: 400, + message: "Error: Artifact name is invalid.", + messageId: "SVC4670" } \ No newline at end of file diff --git a/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/ActionStatus.java b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/ActionStatus.java index 0a7a009ad4..4ae3e61841 100644 --- a/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/ActionStatus.java +++ b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/ActionStatus.java @@ -27,7 +27,9 @@ public enum ActionStatus { // CapabilityType related CAPABILITY_TYPE_ALREADY_EXIST, MISSING_CAPABILITY_TYPE, REQ_CAP_NOT_SATISFIED_BEFORE_CERTIFICATION, IMPORT_DUPLICATE_REQ_CAP_NAME, IMPORT_REQ_CAP_NAME_EXISTS_IN_DERIVED, // Resource related - RESOURCE_NOT_FOUND, MISSING_DERIVED_FROM_TEMPLATE, PARENT_RESOURCE_NOT_FOUND, PARENT_RESOURCE_DOES_NOT_EXTEND, INVALID_DEFAULT_VALUE, INVALID_COMPLEX_DEFAULT_VALUE, MULTIPLE_PARENT_RESOURCE_FOUND, INVALID_RESOURCE_PAYLOAD, INVALID_TOSCA_FILE_EXTENSION, INVALID_YAML_FILE, INVALID_TOSCA_TEMPLATE, NOT_RESOURCE_TOSCA_TEMPLATE, NOT_SINGLE_RESOURCE, INVALID_RESOURCE_NAMESPACE, RESOURCE_ALREADY_EXISTS, INVALID_RESOURCE_CHECKSUM, RESOURCE_CANNOT_CONTAIN_RESOURCE_INSTANCES, NO_ASSETS_FOUND, GENERIC_TYPE_NOT_FOUND, TOSCA_PARSE_ERROR, + RESOURCE_NOT_FOUND, MISSING_DERIVED_FROM_TEMPLATE, PARENT_RESOURCE_NOT_FOUND, PARENT_RESOURCE_DOES_NOT_EXTEND, INVALID_DEFAULT_VALUE, INVALID_COMPLEX_DEFAULT_VALUE, MULTIPLE_PARENT_RESOURCE_FOUND, INVALID_RESOURCE_PAYLOAD, INVALID_TOSCA_FILE_EXTENSION, INVALID_YAML_FILE, INVALID_TOSCA_TEMPLATE, NOT_RESOURCE_TOSCA_TEMPLATE, NOT_SINGLE_RESOURCE, INVALID_RESOURCE_NAMESPACE, RESOURCE_ALREADY_EXISTS, INVALID_RESOURCE_CHECKSUM, RESOURCE_CANNOT_CONTAIN_RESOURCE_INSTANCES, NO_ASSETS_FOUND, GENERIC_TYPE_NOT_FOUND,INVALID_RESOURCE_TYPE, TOSCA_PARSE_ERROR, + // Service related + SERVICE_TYPE_EXCEEDS_LIMIT, INVALID_SERVICE_TYPE, SERVICE_ROLE_EXCEEDS_LIMIT, INVALID_SERVICE_ROLE, // Component name related COMPONENT_NAME_ALREADY_EXIST, COMPONENT_NAME_EXCEEDS_LIMIT, MISSING_COMPONENT_NAME, INVALID_COMPONENT_NAME, // Component description related @@ -39,7 +41,7 @@ public enum ActionStatus { // contactId related COMPONENT_MISSING_CONTACT, COMPONENT_INVALID_CONTACT, // Vendor related - VENDOR_NAME_EXCEEDS_LIMIT, VENDOR_RELEASE_EXCEEDS_LIMIT, INVALID_VENDOR_NAME, INVALID_VENDOR_RELEASE, MISSING_VENDOR_NAME, MISSING_VENDOR_RELEASE, + VENDOR_NAME_EXCEEDS_LIMIT, VENDOR_RELEASE_EXCEEDS_LIMIT, INVALID_VENDOR_NAME, INVALID_VENDOR_RELEASE, MISSING_VENDOR_NAME, MISSING_VENDOR_RELEASE, RESOURCE_VENDOR_MODEL_NUMBER_EXCEEDS_LIMIT, INVALID_RESOURCE_VENDOR_MODEL_NUMBER, // Category related COMPONENT_MISSING_CATEGORY, COMPONENT_INVALID_CATEGORY, COMPONENT_ELEMENT_INVALID_NAME_FORMAT, COMPONENT_ELEMENT_INVALID_NAME_LENGTH, COMPONENT_CATEGORY_ALREADY_EXISTS, COMPONENT_CATEGORY_NOT_FOUND, COMPONENT_SUB_CATEGORY_NOT_FOUND_FOR_CATEGORY, COMPONENT_SUB_CATEGORY_EXISTS_FOR_CATEGORY, COMPONENT_GROUPING_EXISTS_FOR_SUB_CATEGORY, // Service API URL @@ -71,7 +73,7 @@ public enum ActionStatus { GROUP_MEMBER_EMPTY, GROUP_TYPE_ALREADY_EXIST, // CSAR - MISSING_CSAR_UUID, CSAR_INVALID, CSAR_INVALID_FORMAT, CSAR_NOT_FOUND, YAML_NOT_FOUND_IN_CSAR, VSP_ALREADY_EXISTS, RESOURCE_LINKED_TO_DIFFERENT_VSP, RESOURCE_FROM_CSAR_NOT_FOUND, AAI_ARTIFACT_GENERATION_FAILED, ASSET_NOT_FOUND_DURING_CSAR_CREATION, ARTIFACT_PAYLOAD_NOT_FOUND_DURING_CSAR_CREATION, TOSCA_SCHEMA_FILES_NOT_FOUND, + MISSING_CSAR_UUID, CSAR_INVALID, CSAR_INVALID_FORMAT, CSAR_NOT_FOUND, YAML_NOT_FOUND_IN_CSAR, VSP_ALREADY_EXISTS, RESOURCE_LINKED_TO_DIFFERENT_VSP, RESOURCE_FROM_CSAR_NOT_FOUND, AAI_ARTIFACT_GENERATION_FAILED, ASSET_NOT_FOUND_DURING_CSAR_CREATION, ARTIFACT_PAYLOAD_NOT_FOUND_DURING_CSAR_CREATION, TOSCA_SCHEMA_FILES_NOT_FOUND, ARTIFACT_NAME_INVALID, // Group GROUP_HAS_CYCLIC_DEPENDENCY, GROUP_ALREADY_EXIST, GROUP_TYPE_IS_INVALID, GROUP_MISSING_GROUP_TYPE, GROUP_INVALID_COMPONENT_INSTANCE, GROUP_INVALID_TOSCA_NAME_OF_COMPONENT_INSTANCE, GROUP_IS_MISSING, GROUP_ARTIFACT_ALREADY_ASSOCIATED, GROUP_ARTIFACT_ALREADY_DISSOCIATED, GROUP_PROPERTY_NOT_FOUND, INVALID_VF_MODULE_NAME, INVALID_VF_MODULE_NAME_MODIFICATION, INVALID_VF_MODULE_TYPE, @@ -86,6 +88,7 @@ public enum ActionStatus { // Inputs INPUT_IS_NOT_CHILD_OF_COMPONENT, + CFVC_LOOP_DETECTED, ; } diff --git a/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/cassandra/MigrationTasksAccessor.java b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/cassandra/MigrationTasksAccessor.java new file mode 100644 index 0000000000..e548a594d9 --- /dev/null +++ b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/cassandra/MigrationTasksAccessor.java @@ -0,0 +1,17 @@ +package org.openecomp.sdc.be.dao.cassandra; + +import com.datastax.driver.core.ResultSet; +import com.datastax.driver.mapping.annotations.Accessor; +import com.datastax.driver.mapping.annotations.Param; +import com.datastax.driver.mapping.annotations.Query; + +@Accessor +public interface MigrationTasksAccessor { + + @Query("SELECT minor_version FROM sdcrepository.migrationTasks WHERE major_version = :majorVersion order by minor_version desc limit 1") + ResultSet getLatestMinorVersion(@Param("majorVersion") Long majorVersion); + + @Query("DELETE FROM sdcrepository.migrationTasks WHERE major_version = :majorVersion") + void deleteTasksForMajorVersion(@Param("majorVersion") Long majorVersion); + +} diff --git a/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/cassandra/MigrationTasksDao.java b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/cassandra/MigrationTasksDao.java new file mode 100644 index 0000000000..89ad9662fa --- /dev/null +++ b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/cassandra/MigrationTasksDao.java @@ -0,0 +1,73 @@ +package org.openecomp.sdc.be.dao.cassandra; + +import com.datastax.driver.core.ResultSet; +import com.datastax.driver.core.Row; +import com.datastax.driver.core.Session; +import com.datastax.driver.mapping.Mapper; +import com.datastax.driver.mapping.MappingManager; +import fj.data.Either; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.openecomp.sdc.be.resources.data.MigrationTaskEntry; +import org.openecomp.sdc.be.resources.data.auditing.AuditingTypesConstants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; +import java.math.BigInteger; + +@Component("sdc-migration-tasks-cassandra-dao") +public class MigrationTasksDao extends CassandraDao { + + private static Logger logger = LoggerFactory.getLogger(MigrationTasksDao.class.getName()); + private MigrationTasksAccessor migrationTasksAccessor; + private Mapper migrationTaskMapper; + + @PostConstruct + public void init() { + String keyspace = AuditingTypesConstants.REPO_KEYSPACE; + if (client.isConnected()) { + Either, CassandraOperationStatus> result = client.connect(keyspace); + if (result.isLeft()) { + session = result.left().value().left; + manager = result.left().value().right; + migrationTasksAccessor = manager.createAccessor(MigrationTasksAccessor.class); + migrationTaskMapper = manager.mapper(MigrationTaskEntry.class); + logger.info("** migrationTasksAccessor created"); + } else { + logger.info("** migrationTasksAccessor failed"); + throw new RuntimeException("Artifact keyspace [" + keyspace + "] failed to connect with error : " + + result.right().value()); + } + } else { + logger.info("** Cassandra client isn't connected"); + logger.info("** migrationTasksAccessor created, but not connected"); + } + } + + public BigInteger getLatestMinorVersion(BigInteger majorVersion) { + try { + ResultSet latestMinorVersion = migrationTasksAccessor.getLatestMinorVersion(majorVersion.longValue()); + Row minorVersionRow = latestMinorVersion.one(); + return minorVersionRow == null ? BigInteger.valueOf(Long.MIN_VALUE) : BigInteger.valueOf(minorVersionRow.getLong(0)); + } catch (RuntimeException e) { + logger.error("failed to get latest minor version for major version {}", majorVersion, e); + throw e; + } + } + + public void deleteAllTasksForVersion(BigInteger majorVersion) { + try { + migrationTasksAccessor.deleteTasksForMajorVersion(majorVersion.longValue()); + } catch (RuntimeException e) { + logger.error("failed to delete tasks for major version {}", majorVersion, e); + throw e; + } + } + + public void createMigrationTask(MigrationTaskEntry migrationTask) { + migrationTaskMapper.save(migrationTask); + } + + +} diff --git a/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/cassandra/schema/Table.java b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/cassandra/schema/Table.java index 8fb594f2ff..f6fd29bd1f 100644 --- a/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/cassandra/schema/Table.java +++ b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/cassandra/schema/Table.java @@ -20,24 +20,7 @@ package org.openecomp.sdc.be.dao.cassandra.schema; -import org.openecomp.sdc.be.dao.cassandra.schema.tables.ArtifactTableDescription; -import org.openecomp.sdc.be.dao.cassandra.schema.tables.AuthEventTableDescription; -import org.openecomp.sdc.be.dao.cassandra.schema.tables.CategoryEventTableDescription; -import org.openecomp.sdc.be.dao.cassandra.schema.tables.ComponentCacheTableDescription; -import org.openecomp.sdc.be.dao.cassandra.schema.tables.ConsumerEventTableDefinition; -import org.openecomp.sdc.be.dao.cassandra.schema.tables.DistribDeployEventTableDesc; -import org.openecomp.sdc.be.dao.cassandra.schema.tables.DistribDownloadEventTableDesc; -import org.openecomp.sdc.be.dao.cassandra.schema.tables.DistribEngineEventTableDesc; -import org.openecomp.sdc.be.dao.cassandra.schema.tables.DistribNotifEventTableDesc; -import org.openecomp.sdc.be.dao.cassandra.schema.tables.DistribStatusEventTableDesc; -import org.openecomp.sdc.be.dao.cassandra.schema.tables.ExternalApiEventTableDesc; -import org.openecomp.sdc.be.dao.cassandra.schema.tables.GetCatHierEventTableDesc; -import org.openecomp.sdc.be.dao.cassandra.schema.tables.GetUebClusterEventTableDesc; -import org.openecomp.sdc.be.dao.cassandra.schema.tables.GetUsersListEventTableDesc; -import org.openecomp.sdc.be.dao.cassandra.schema.tables.ResAdminEventTableDescription; -import org.openecomp.sdc.be.dao.cassandra.schema.tables.SdcSchemaFilesTableDescription; -import org.openecomp.sdc.be.dao.cassandra.schema.tables.UserAccessEventTableDescription; -import org.openecomp.sdc.be.dao.cassandra.schema.tables.UserAdminEventTableDescription; +import org.openecomp.sdc.be.dao.cassandra.schema.tables.*; public enum Table { @@ -58,8 +41,8 @@ public enum Table { GET_CATEGORY_HIERARCHY_EVENT(new GetCatHierEventTableDesc()), EXTERNAL_API_EVENT(new ExternalApiEventTableDesc()), COMPONENT_CACHE(new ComponentCacheTableDescription()), - SDC_SCHEMA_FILES(new SdcSchemaFilesTableDescription()); - + SDC_SCHEMA_FILES(new SdcSchemaFilesTableDescription()), + SDC_REPO(new MigrationTasksTableDescription()); ITableDescription tableDescription; Table(ITableDescription tableDescription) { diff --git a/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/cassandra/schema/tables/MigrationTasksTableDescription.java b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/cassandra/schema/tables/MigrationTasksTableDescription.java new file mode 100644 index 0000000000..f7506f77e1 --- /dev/null +++ b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/cassandra/schema/tables/MigrationTasksTableDescription.java @@ -0,0 +1,81 @@ +package org.openecomp.sdc.be.dao.cassandra.schema.tables; + +import com.datastax.driver.core.DataType; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.openecomp.sdc.be.dao.cassandra.schema.ITableDescription; +import org.openecomp.sdc.be.resources.data.auditing.AuditingTypesConstants; + +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.openecomp.sdc.be.dao.cassandra.schema.tables.MigrationTasksTableDescription.SdcRepoFieldsDescription.MAJOR_VERSION; +import static org.openecomp.sdc.be.dao.cassandra.schema.tables.MigrationTasksTableDescription.SdcRepoFieldsDescription.MINOR_VERSION; + +public class MigrationTasksTableDescription implements ITableDescription { + + private static final String MIGRATION_TASKS_TABLE = "migrationTasks"; + + @Override + public List> primaryKeys() { + return Collections.singletonList(ImmutablePair.of(MAJOR_VERSION.getFieldName(), MAJOR_VERSION.getFieldType())); + } + + @Override + public List> clusteringKeys() { + return Collections.singletonList(ImmutablePair.of(MINOR_VERSION.getFieldName(), MINOR_VERSION.getFieldType())); + } + + @Override + public Map> getColumnDescription() { + Map> columns = new HashMap<>(); + Arrays.stream(SdcRepoFieldsDescription.values()) + .filter(column -> !column.equals(MAJOR_VERSION) && !column.equals(MINOR_VERSION)) + .forEach(column -> columns.put(column.getFieldName(), ImmutablePair.of(column.getFieldType(), column.isIndexed()))); + return columns; + } + + @Override + public String getKeyspace() { + return AuditingTypesConstants.REPO_KEYSPACE; + } + + @Override + public String getTableName() { + return MIGRATION_TASKS_TABLE; + } + + enum SdcRepoFieldsDescription { + MAJOR_VERSION("major_version", DataType.bigint(), true), + MINOR_VERSION("minor_version", DataType.bigint(), false), + TIMESTAMP("timestamp", DataType.timestamp(), false), + NAME("task_name", DataType.varchar(), false), + STATUS("task_status", DataType.varchar(), false), + MESSAGE("msg", DataType.varchar(), false), + EXECUTION_TIME("execution_time", DataType.cdouble(), false); + + private String fieldName; + private boolean isIndexed; + private DataType fieldType; + + SdcRepoFieldsDescription(String fieldName, DataType dataType, boolean indexed ) { + this.fieldName = fieldName; + this.fieldType = dataType; + this.isIndexed = indexed; + } + + public String getFieldName() { + return fieldName; + } + + public boolean isIndexed() { + return isIndexed; + } + + public DataType getFieldType() { + return fieldType; + } + } +} diff --git a/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/jsongraph/TitanDao.java b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/jsongraph/TitanDao.java index 2d9c029ea9..387b413dd5 100644 --- a/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/jsongraph/TitanDao.java +++ b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/jsongraph/TitanDao.java @@ -456,7 +456,11 @@ public class TitanDao { } if (hasNotProps != null && !hasNotProps.isEmpty()) { for (Map.Entry entry : hasNotProps.entrySet()) { - query = query.hasNot(entry.getKey().getProperty(), entry.getValue()); + if(entry.getValue() instanceof List){ + buildMultipleNegateQueryFromList(entry, query); + }else{ + query = query.hasNot(entry.getKey().getProperty(), entry.getValue()); + } } } Iterable vertices = query.vertices(); @@ -499,6 +503,15 @@ public class TitanDao { } + + private void buildMultipleNegateQueryFromList(Map.Entry entry, TitanGraphQuery query){ + List negateList = (List) entry.getValue(); + for (Object listItem : negateList) { + query.hasNot(entry.getKey().getProperty(), listItem); + } + } + + /** * * @param parentVertex diff --git a/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/jsongraph/types/EdgeLabelEnum.java b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/jsongraph/types/EdgeLabelEnum.java index 001544c4a4..3018915066 100644 --- a/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/jsongraph/types/EdgeLabelEnum.java +++ b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/jsongraph/types/EdgeLabelEnum.java @@ -67,4 +67,8 @@ public enum EdgeLabelEnum { } return null; } + + public boolean isInstanceArtifactsLabel() { + return this.equals(INSTANCE_ARTIFACTS) || this.equals(INST_DEPLOYMENT_ARTIFACTS); + } } diff --git a/catalog-dao/src/main/java/org/openecomp/sdc/be/resources/data/MigrationTaskEntry.java b/catalog-dao/src/main/java/org/openecomp/sdc/be/resources/data/MigrationTaskEntry.java new file mode 100644 index 0000000000..08376b616f --- /dev/null +++ b/catalog-dao/src/main/java/org/openecomp/sdc/be/resources/data/MigrationTaskEntry.java @@ -0,0 +1,92 @@ +package org.openecomp.sdc.be.resources.data; + +import com.datastax.driver.mapping.annotations.ClusteringColumn; +import com.datastax.driver.mapping.annotations.Column; +import com.datastax.driver.mapping.annotations.PartitionKey; +import com.datastax.driver.mapping.annotations.Table; + +import java.math.BigInteger; +import java.util.Date; + +@Table(keyspace = "sdcrepository", name = "migrationTasks") +public class MigrationTaskEntry { + + @PartitionKey(0) + @Column(name = "major_version") + private Long majorVersion; + + @ClusteringColumn + @Column(name = "minor_version") + private Long minorVersion; + + @Column(name = "timestamp") + private Date timestamp; + + @Column(name = "task_name") + private String taskName; + + @Column(name = "execution_time") + private double executionTime; + + @Column(name = "task_status") + private String taskStatus; + + @Column(name = "msg") + private String message; + + public void setMajorVersion(Long majorVersion) { + this.majorVersion = majorVersion; + } + + public void setMinorVersion(Long minorVersion) { + this.minorVersion = minorVersion; + } + + public void setTimestamp(Date timestamp) { + this.timestamp = timestamp; + } + + public void setTaskName(String taskName) { + this.taskName = taskName; + } + + public void setTaskStatus(String taskStatus) { + this.taskStatus = taskStatus; + } + + public void setMessage(String message) { + this.message = message; + } + + public void setExecutionTime(double executionTime) { + this.executionTime = executionTime; + } + + public Long getMajorVersion() { + return majorVersion; + } + + public Long getMinorVersion() { + return minorVersion; + } + + public Date getTimestamp() { + return timestamp; + } + + public String getTaskName() { + return taskName; + } + + public String getTaskStatus() { + return taskStatus; + } + + public String getMessage() { + return message; + } + + public double getExecutionTime() { + return executionTime; + } +} diff --git a/catalog-dao/src/main/java/org/openecomp/sdc/be/resources/data/auditing/AuditingTypesConstants.java b/catalog-dao/src/main/java/org/openecomp/sdc/be/resources/data/auditing/AuditingTypesConstants.java index 01774ca63f..9f25932b37 100644 --- a/catalog-dao/src/main/java/org/openecomp/sdc/be/resources/data/auditing/AuditingTypesConstants.java +++ b/catalog-dao/src/main/java/org/openecomp/sdc/be/resources/data/auditing/AuditingTypesConstants.java @@ -22,28 +22,29 @@ package org.openecomp.sdc.be.resources.data.auditing; public interface AuditingTypesConstants { - public static final String ARTIFACT_KEYSPACE = "sdcartifact"; - public static final String AUDIT_KEYSPACE = "sdcaudit"; - public static final String COMPONENT_KEYSPACE = "sdccomponent"; - public static final String TITAN_KEYSPACE = "titan"; + String ARTIFACT_KEYSPACE = "sdcartifact"; + String REPO_KEYSPACE = "sdcrepository"; + String AUDIT_KEYSPACE = "sdcaudit"; + String COMPONENT_KEYSPACE = "sdccomponent"; + String TITAN_KEYSPACE = "titan"; - public static final String USER_ADMIN_EVENT_TYPE = "useradminevent"; - public static final String USER_ACCESS_EVENT_TYPE = "useraccessevent"; - public static final String RESOURCE_ADMIN_EVENT_TYPE = "resourceadminevent"; - public static final String DISTRIBUTION_DOWNLOAD_EVENT_TYPE = "distributiondownloadevent"; + String USER_ADMIN_EVENT_TYPE = "useradminevent"; + String USER_ACCESS_EVENT_TYPE = "useraccessevent"; + String RESOURCE_ADMIN_EVENT_TYPE = "resourceadminevent"; + String DISTRIBUTION_DOWNLOAD_EVENT_TYPE = "distributiondownloadevent"; - public static final String DISTRIBUTION_ENGINE_EVENT_TYPE = "distributionengineevent"; - public static final String DISTRIBUTION_NOTIFICATION_EVENT_TYPE = "distributionnotificationevent"; - public static final String DISTRIBUTION_STATUS_EVENT_TYPE = "distributionstatusevent"; - public static final String DISTRIBUTION_DEPLOY_EVENT_TYPE = "distributiondeployevent"; - public static final String DISTRIBUTION_GET_UEB_CLUSTER_EVENT_TYPE = "auditinggetuebclusterevent"; - public static final String DISTRIBUTION_GET_VALID_ARTIFACT_TYPES_EVENT_TYPE = "auditinggetvalidartifacttypesevent"; + String DISTRIBUTION_ENGINE_EVENT_TYPE = "distributionengineevent"; + String DISTRIBUTION_NOTIFICATION_EVENT_TYPE = "distributionnotificationevent"; + String DISTRIBUTION_STATUS_EVENT_TYPE = "distributionstatusevent"; + String DISTRIBUTION_DEPLOY_EVENT_TYPE = "distributiondeployevent"; + String DISTRIBUTION_GET_UEB_CLUSTER_EVENT_TYPE = "auditinggetuebclusterevent"; + String DISTRIBUTION_GET_VALID_ARTIFACT_TYPES_EVENT_TYPE = "auditinggetvalidartifacttypesevent"; - public static final String AUTH_EVENT_TYPE = "authevent"; - public static final String CONSUMER_EVENT_TYPE = "consumerevent"; - public static final String CATEGORY_EVENT_TYPE = "categoryevent"; - public static final String GET_USERS_LIST_EVENT_TYPE = "getuserslistevent"; - public static final String GET_CATEGORY_HIERARCHY_EVENT_TYPE = "getcategoryhierarchyevent"; - public static final String EXTERNAL_API_EVENT_TYPE = "externalapievent"; + String AUTH_EVENT_TYPE = "authevent"; + String CONSUMER_EVENT_TYPE = "consumerevent"; + String CATEGORY_EVENT_TYPE = "categoryevent"; + String GET_USERS_LIST_EVENT_TYPE = "getuserslistevent"; + String GET_CATEGORY_HIERARCHY_EVENT_TYPE = "getcategoryhierarchyevent"; + String EXTERNAL_API_EVENT_TYPE = "externalapievent"; } diff --git a/catalog-fe/src/main/java/org/openecomp/sdc/fe/servlets/HealthCheckService.java b/catalog-fe/src/main/java/org/openecomp/sdc/fe/servlets/HealthCheckService.java index b7fce8d912..4ef7c4974e 100644 --- a/catalog-fe/src/main/java/org/openecomp/sdc/fe/servlets/HealthCheckService.java +++ b/catalog-fe/src/main/java/org/openecomp/sdc/fe/servlets/HealthCheckService.java @@ -199,9 +199,10 @@ public class HealthCheckService { healthCheckInfos.add(new HealthCheckInfo(HealthCheckComponent.FE, HealthCheckStatus.UP, ExternalConfiguration.getAppVersion(), "OK")); healthCheckInfos.add(new HealthCheckInfo(HealthCheckComponent.BE, HealthCheckStatus.DOWN, null, null)); - healthCheckInfos.add(new HealthCheckInfo(HealthCheckComponent.ES, HealthCheckStatus.UNKNOWN, null, null)); healthCheckInfos.add(new HealthCheckInfo(HealthCheckComponent.TITAN, HealthCheckStatus.UNKNOWN, null, null)); + healthCheckInfos.add(new HealthCheckInfo(HealthCheckComponent.CASSANDRA, HealthCheckStatus.UNKNOWN, null, null)); healthCheckInfos.add(new HealthCheckInfo(HealthCheckComponent.DE, HealthCheckStatus.UNKNOWN, null, null)); + healthCheckInfos.add(new HealthCheckInfo(HealthCheckComponent.ON_BOARDING, HealthCheckStatus.UNKNOWN, null, null)); HealthCheckWrapper hcWrapper = new HealthCheckWrapper(healthCheckInfos, "UNKNOWN", "UNKNOWN"); return hcWrapper; } diff --git a/catalog-model/pom.xml b/catalog-model/pom.xml index a4538fd3db..ef485ae870 100644 --- a/catalog-model/pom.xml +++ b/catalog-model/pom.xml @@ -224,7 +224,19 @@ ${commons-jci-core.version} test - + + org.powermock + powermock-module-junit4 + 1.7.0RC4 + test + + + org.powermock + powermock-api-mockito-common + 1.6.5 + test + + diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/Component.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/Component.java index 036108e81f..9ffefa6384 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/Component.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/Component.java @@ -22,9 +22,12 @@ package org.openecomp.sdc.be.model; import java.io.Serializable; 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.Optional; import org.codehaus.jackson.annotate.JsonIgnore; import org.openecomp.sdc.be.config.ConfigurationManager; @@ -288,6 +291,13 @@ public abstract class Component implements Serializable { this.deploymentArtifacts = deploymentArtifacts; } + public Map getAllArtifacts() { + HashMap allArtifacts = new HashMap<>(); + allArtifacts.putAll(Optional.ofNullable(this.deploymentArtifacts).orElse(Collections.emptyMap())); + allArtifacts.putAll(Optional.ofNullable(this.artifacts).orElse(Collections.emptyMap())); + return allArtifacts; + } + public List getCategories() { return categories; } diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/ComponentInstanceInput.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/ComponentInstanceInput.java index abcac352cc..1ffbede599 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/ComponentInstanceInput.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/ComponentInstanceInput.java @@ -25,7 +25,7 @@ import java.util.List; import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition; import org.openecomp.sdc.be.datatypes.elements.PropertyRule; -public class ComponentInstanceInput extends InputDefinition implements IComponentInstanceConnectedElement { +public class ComponentInstanceInput extends InputDefinition implements IComponentInstanceConnectedElement, IPropertyInputCommon { /** * diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/ComponentInstanceProperty.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/ComponentInstanceProperty.java index 25bbb50da4..26c5c02ed5 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/ComponentInstanceProperty.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/ComponentInstanceProperty.java @@ -26,8 +26,7 @@ import java.util.List; import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition; import org.openecomp.sdc.be.datatypes.elements.PropertyRule; - -public class ComponentInstanceProperty extends PropertyDefinition implements IComponentInstanceConnectedElement, Serializable{ +public class ComponentInstanceProperty extends PropertyDefinition implements IComponentInstanceConnectedElement, IPropertyInputCommon, Serializable { /** * diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/GroupDefinition.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/GroupDefinition.java index 167fa2f0a1..625afe4f96 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/GroupDefinition.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/GroupDefinition.java @@ -80,4 +80,12 @@ public class GroupDefinition extends GroupDataDefinition implements Serializable } + //returns true iff groupName has the same prefix has the resource + public boolean isSamePrefix(String resourceName){ + String name = this.getName(); + if ( name != null && name.toLowerCase().trim().startsWith(resourceName.toLowerCase())) + return true; + return false; + } + } diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/IPropertyInputCommon.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/IPropertyInputCommon.java new file mode 100644 index 0000000000..2f7a580bb6 --- /dev/null +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/IPropertyInputCommon.java @@ -0,0 +1,14 @@ +package org.openecomp.sdc.be.model; + +import java.util.List; + +import org.openecomp.sdc.be.datatypes.elements.PropertyRule; +import org.openecomp.sdc.be.datatypes.elements.SchemaDefinition; + +public interface IPropertyInputCommon { + + String getType(); + SchemaDefinition getSchema(); + List getRules(); + String getName(); +} diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/ImportCsarInfo.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/ImportCsarInfo.java new file mode 100644 index 0000000000..460a107c89 --- /dev/null +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/ImportCsarInfo.java @@ -0,0 +1,73 @@ +package org.openecomp.sdc.be.model; + +import java.util.HashMap; +import java.util.Map; +import java.util.PriorityQueue; +import java.util.Queue; + +public class ImportCsarInfo { + String vfResourceName; + User modifier; + String csarUUID; + Map csar; + Map createdNodesToscaResourceNames; + Queue cvfcToCreateQueue; + + public ImportCsarInfo(String vfResourceName, User modifier, String csarUUID, Map csar){ + this.vfResourceName = vfResourceName; + this.modifier = modifier; + this.csarUUID = csarUUID; + this.csar = csar; + this.createdNodesToscaResourceNames = new HashMap<>(); + this.cvfcToCreateQueue = new PriorityQueue<>(); + } + + public String getVfResourceName() { + return vfResourceName; + } + + public void setVfResourceName(String vfResourceName) { + this.vfResourceName = vfResourceName; + } + + public User getModifier() { + return modifier; + } + + public void setModifier(User modifier) { + this.modifier = modifier; + } + + public String getCsarUUID() { + return csarUUID; + } + + public void setCsarUUID(String csarUUID) { + this.csarUUID = csarUUID; + } + + public Map getCsar() { + return csar; + } + + public void setCsar(Map csar) { + this.csar = csar; + } + + public Map getCreatedNodesToscaResourceNames() { + return createdNodesToscaResourceNames; + } + + public void setCreatedNodesToscaResourceNames(Map createdNodesToscaResourceNames) { + this.createdNodesToscaResourceNames = createdNodesToscaResourceNames; + } + + public Queue getCvfcToCreateQueue() { + return cvfcToCreateQueue; + } + + public void setCvfcToCreateQueue(Queue cvfcToCreateQueue) { + this.cvfcToCreateQueue = cvfcToCreateQueue; + } + +} diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/NodeTypeInfo.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/NodeTypeInfo.java new file mode 100644 index 0000000000..1da3b8de1c --- /dev/null +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/NodeTypeInfo.java @@ -0,0 +1,55 @@ +package org.openecomp.sdc.be.model; + +import java.util.List; +import java.util.Map; + +public class NodeTypeInfo { + String type; + String templateFileName; + List derivedFrom; + boolean isNested; + Map mappedToscaTemplate; + + public NodeTypeInfo getUnmarkedCopy(){ + NodeTypeInfo unmarked = new NodeTypeInfo(); + unmarked.type = this.type; + unmarked.templateFileName = this.templateFileName; + unmarked.derivedFrom = this.derivedFrom; + unmarked.isNested = false; + unmarked.mappedToscaTemplate = this.mappedToscaTemplate; + return unmarked; + } + + public String getType() { + return type; + } + public void setType(String type) { + this.type = type; + } + public String getTemplateFileName() { + return templateFileName; + } + public void setTemplateFileName(String templateFileName) { + this.templateFileName = templateFileName; + } + public List getDerivedFrom() { + return derivedFrom; + } + public void setDerivedFrom(List derivedFrom) { + this.derivedFrom = derivedFrom; + } + public boolean isNested() { + return isNested; + } + public void setNested(boolean isNested) { + this.isNested = isNested; + } + + public Map getMappedToscaTemplate() { + return mappedToscaTemplate; + } + + public void setMappedToscaTemplate(Map mappedToscaTemplate) { + this.mappedToscaTemplate = mappedToscaTemplate; + } +} diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/RequirementAndRelationshipPair.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/RequirementAndRelationshipPair.java index afb013d29a..a3e4f48c51 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/RequirementAndRelationshipPair.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/RequirementAndRelationshipPair.java @@ -146,7 +146,7 @@ public class RequirementAndRelationshipPair implements Serializable { if ( !savedRelation.getRequirementId().equals(this.getRequirementUid()) ){ return false; } - if ( !savedRelation.getCapabiltyId().equals(this.getCapabilityUid()) ){ + if ( !savedRelation.getCapabilityId().equals(this.getCapabilityUid()) ){ return false; } if ( !savedRelation.getRequirement().equals(this.getRequirement()) ){ diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/Resource.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/Resource.java index a9c6b44324..45fc5f62b3 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/Resource.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/Resource.java @@ -255,6 +255,11 @@ public class Resource extends Component implements Serializable { ((ResourceMetadataDataDefinition) getComponentMetadataDefinition().getMetadataDataDefinition()) .setVendorRelease(vendorRelease); } + + public void setResourceVendorModelNumber(String resourceVendorModelNumber){ + ((ResourceMetadataDataDefinition) getComponentMetadataDefinition().getMetadataDataDefinition()). + setResourceVendorModelNumber(resourceVendorModelNumber); + } public String getVendorName() { return ((ResourceMetadataDataDefinition) getComponentMetadataDefinition().getMetadataDataDefinition()) @@ -266,6 +271,11 @@ public class Resource extends Component implements Serializable { .getVendorRelease(); } + public String getResourceVendorModelNumber(){ + return ((ResourceMetadataDataDefinition) getComponentMetadataDefinition().getMetadataDataDefinition()) + .getResourceVendorModelNumber(); + } + @Override public String fetchGenericTypeToscaNameFromConfig(){ String result = super.fetchGenericTypeToscaNameFromConfig(); @@ -282,7 +292,7 @@ public class Resource extends Component implements Serializable { @Override public boolean shouldGenerateInputs(){ //TODO add complex VFC condition when supported - return ResourceTypeEnum.VF == this.getResourceType(); + return ResourceTypeEnum.VF == this.getResourceType() || ResourceTypeEnum.CVFC == this.getResourceType() || ResourceTypeEnum.PNF == this.getResourceType(); } @Override diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/Service.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/Service.java index 37a42bd581..cdd171184c 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/Service.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/Service.java @@ -85,10 +85,26 @@ public class Service extends Component { public void setNamingPolicy(String namingPolicy) { getServiceMetadataDefinition().setNamingPolicy(namingPolicy); } - + public String getNamingPolicy() { return getServiceMetadataDefinition().getNamingPolicy(); } + + public void setServiceType(String serviceType){ + getServiceMetadataDefinition().setServiceType(serviceType); + } + + public String getServiceType(){ + return getServiceMetadataDefinition().getServiceType(); + } + + public void setServiceRole(String serviceRole){ + getServiceMetadataDefinition().setServiceRole(serviceRole); + } + + public String getServiceRole(){ + return getServiceMetadataDefinition().getServiceRole(); + } private ServiceMetadataDataDefinition getServiceMetadataDefinition() { return (ServiceMetadataDataDefinition) getComponentMetadataDefinition().getMetadataDataDefinition(); diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/UploadComponentInstanceInfo.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/UploadComponentInstanceInfo.java index 329e816ea7..eb707787c0 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/UploadComponentInstanceInfo.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/UploadComponentInstanceInfo.java @@ -29,6 +29,8 @@ public class UploadComponentInstanceInfo { private Map> capabilities; private Map> requirements; private Map> properties; + private Map capabilitiesNamesToUpdate; + private Map requirementsNamesToUpdate; public Map> getProperties() { return properties; @@ -70,4 +72,20 @@ public class UploadComponentInstanceInfo { this.requirements = requirements; } + public Map getCapabilitiesNamesToUpdate() { + return capabilitiesNamesToUpdate; + } + + public void setCapabilitiesNamesToUpdate(Map capabilitiesNamesToUpdate) { + this.capabilitiesNamesToUpdate = capabilitiesNamesToUpdate; + } + + public Map getRequirementsNamesToUpdate() { + return requirementsNamesToUpdate; + } + + public void setRequirementsNamesToUpdate(Map requirementsNamesToUpdate) { + this.requirementsNamesToUpdate = requirementsNamesToUpdate; + } + } diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/ArtifactsOperations.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/ArtifactsOperations.java index e2766b1092..b8d8cb39de 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/ArtifactsOperations.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/ArtifactsOperations.java @@ -181,6 +181,27 @@ public class ArtifactsOperations extends BaseOperation { return Either.left(resMap); } + /** + * + * @param parentId the id of the instance container + * @param instanceId the id of the instance of which to return its artifacts + * @return instance and instance deployment artifacts mapped by artifact label name + */ + public Either, StorageOperationStatus> getAllInstanceArtifacts(String parentId, String instanceId) { + Map resMap = new HashMap<>(); + Either, TitanOperationStatus> instArtifacts = getInstanceArtifactsByLabel(parentId, instanceId, EdgeLabelEnum.INSTANCE_ARTIFACTS); + if (instArtifacts.isRight()) { + return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(instArtifacts.right().value())); + } + Either, TitanOperationStatus> deployInstArtifacts = getInstanceArtifactsByLabel(parentId, instanceId, EdgeLabelEnum.INST_DEPLOYMENT_ARTIFACTS); + if (deployInstArtifacts.isRight()) { + return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(deployInstArtifacts.right().value())); + } + resMap.putAll(instArtifacts.left().value()); + resMap.putAll(deployInstArtifacts.left().value()); + return Either.left(convertArtifactMapToArtifactDefinitionMap(resMap)); + } + public Either, StorageOperationStatus> getArtifacts(String parentId) { Either, TitanOperationStatus> foundArtifact = null; @@ -384,36 +405,36 @@ public class ArtifactsOperations extends BaseOperation { } private Either, TitanOperationStatus> getArtifactByLabel(String parentId, String instanceId, EdgeLabelEnum edgeLabelEnum) { + Either, TitanOperationStatus> artifactsEither = getArtifactsDataByLabel(parentId, instanceId, edgeLabelEnum); + if (artifactsEither.isRight()) { + log.debug("failed to fetch {} for tosca element with id {}, error {}", edgeLabelEnum, parentId, artifactsEither.right().value()); + return Either.right(artifactsEither.right().value()); + } + Map artifactDataMap = artifactsEither.left().value(); + return Either.left(convertArtifactMapToArtifactDefinitionMap(artifactDataMap)); + } - Map artMap = null; - Map artifactDataMap = null; + private Either, TitanOperationStatus> getArtifactsDataByLabel(String parentId, String instanceId, EdgeLabelEnum edgeLabelEnum) { + return edgeLabelEnum.isInstanceArtifactsLabel() ? getInstanceArtifactsByLabel(parentId, instanceId, edgeLabelEnum) : getDataFromGraph(parentId, edgeLabelEnum); + } - if (edgeLabelEnum != EdgeLabelEnum.INSTANCE_ARTIFACTS) { - Either, TitanOperationStatus> resultEither = getDataFromGraph(parentId, edgeLabelEnum); - if (resultEither.isRight()) { - log.debug("failed to fetch {} for tosca element with id {}, error {}", edgeLabelEnum, parentId, resultEither.right().value()); - return Either.right(resultEither.right().value()); - } - artifactDataMap = resultEither.left().value(); - } else { - Either, TitanOperationStatus> resultEither = getDataFromGraph(parentId, edgeLabelEnum); - if (resultEither.isRight()) { - log.debug("failed to fetch {} for tosca element with id {}, error {}", edgeLabelEnum, parentId, resultEither.right().value()); - return Either.right(resultEither.right().value()); - } - Map mapArtifacts = resultEither.left().value(); - MapArtifactDataDefinition artifactPerInstance = mapArtifacts.get(instanceId); - if (artifactPerInstance != null) { - artifactDataMap = artifactPerInstance.getMapToscaDataDefinition(); - } - } + private Map convertArtifactMapToArtifactDefinitionMap(Map artifactDataMap) { + Map artMap = new HashMap<>(); if (artifactDataMap != null && !artifactDataMap.isEmpty()) { - artMap = artifactDataMap.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> convertArtifactDataToArtifactDefinition(null, e.getValue()))); - } else { - artMap = new HashMap<>(); + artMap = artifactDataMap.entrySet().stream().collect(Collectors.toMap(Entry::getKey, e -> convertArtifactDataToArtifactDefinition(null, e.getValue()))); } - return Either.left(artMap); + return artMap; + } + private Either, TitanOperationStatus> getInstanceArtifactsByLabel(String parentId, String instanceId, EdgeLabelEnum edgeLabelEnum) { + Either, TitanOperationStatus> resultEither = getDataFromGraph(parentId, edgeLabelEnum); + if (resultEither.isRight()) { + log.debug("failed to fetch {} for tosca element with id {}, error {}", edgeLabelEnum, parentId, resultEither.right().value()); + return Either.right(resultEither.right().value()); + } + Map mapArtifacts = resultEither.left().value(); + MapArtifactDataDefinition artifactPerInstance = mapArtifacts.get(instanceId); + return artifactPerInstance != null ? Either.left(artifactPerInstance.getMapToscaDataDefinition()) : Either.left(new HashMap<>()); } private Triple getEdgeLabelEnumFromArtifactGroupType(ArtifactGroupTypeEnum groupType, NodeTypeEnum nodeType) { diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/BaseOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/BaseOperation.java index 69ac568ee9..0b60a07a28 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/BaseOperation.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/BaseOperation.java @@ -1081,12 +1081,10 @@ public abstract class BaseOperation { * * @param toscaElementUid * @param edgeLabel - * @param vertexLabel * @param uniqueKeys - * @param mapKeyField * @return */ - public StorageOperationStatus deleteToscaDataElements(String toscaElementUid, EdgeLabelEnum edgeLabel, VertexTypeEnum vertexLabel, List uniqueKeys, JsonPresentationFields mapKeyField) { + public StorageOperationStatus deleteToscaDataElements(String toscaElementUid, EdgeLabelEnum edgeLabel, List uniqueKeys) { StorageOperationStatus statusRes = StorageOperationStatus.OK; Either getToscaElementRes; @@ -1098,7 +1096,7 @@ public abstract class BaseOperation { statusRes = DaoStatusConverter.convertTitanStatusToStorageStatus(status); } if (statusRes == StorageOperationStatus.OK) { - statusRes = deleteToscaDataElements(getToscaElementRes.left().value(), edgeLabel, vertexLabel, uniqueKeys, mapKeyField); + statusRes = deleteToscaDataElements(getToscaElementRes.left().value(), edgeLabel, uniqueKeys); } return statusRes; } @@ -1219,25 +1217,22 @@ public abstract class BaseOperation { List uniqueKeys = new ArrayList<>(); uniqueKeys.add(uniqueKey); - return deleteToscaDataElements(toscaElement, edgeLabel, vertexLabel, uniqueKeys, mapKeyField); + return deleteToscaDataElements(toscaElement, edgeLabel, uniqueKeys); } @SuppressWarnings("unchecked") - /** - * Deletes tosca data elements belonging to tosca element according label - * - * @param toscaElement - * @param edgeLabel - * @param vertexLabel - * @param uniqueKeys - * @param mapKeyField - * @return - */ - public StorageOperationStatus deleteToscaDataElements(GraphVertex toscaElement, EdgeLabelEnum edgeLabel, VertexTypeEnum vertexLabel, List uniqueKeys, JsonPresentationFields mapKeyField) { +/** + * Deletes tosca data elements belonging to tosca element according label + * @param toscaElement + * @param edgeLabel + * @param uniqueKeys + * @return + */ + public StorageOperationStatus deleteToscaDataElements(GraphVertex toscaElement, EdgeLabelEnum edgeLabel, List uniqueKeys) { StorageOperationStatus result = null; GraphVertex toscaDataVertex; - Map existingToscaDataMap = null; + Map existingToscaDataMap; Either toscaDataVertexRes = titanDao.getChildVertex(toscaElement, edgeLabel, JsonParseFlagEnum.ParseJson); if (toscaDataVertexRes.isRight()) { TitanOperationStatus status = toscaDataVertexRes.right().value(); diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/GroupsOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/GroupsOperation.java index 737c1c2d40..5f7502e7ce 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/GroupsOperation.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/GroupsOperation.java @@ -139,7 +139,7 @@ public class GroupsOperation extends BaseOperation { } if (result == null) { List groupName = groups.stream().map(g -> g.getName()).collect(Collectors.toList()); - status = deleteToscaDataElements(component.getUniqueId(), EdgeLabelEnum.GROUPS, VertexTypeEnum.GROUPS, groupName, JsonPresentationFields.NAME); + status = deleteToscaDataElements(component.getUniqueId(), EdgeLabelEnum.GROUPS, groupName); if (status != StorageOperationStatus.OK) { result = Either.right(status); diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/NodeTemplateOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/NodeTemplateOperation.java index 33db64234b..66d26c748f 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/NodeTemplateOperation.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/NodeTemplateOperation.java @@ -37,8 +37,6 @@ import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.Pair; -import org.apache.tinkerpop.gremlin.structure.Direction; -import org.apache.tinkerpop.gremlin.structure.Edge; import org.openecomp.sdc.be.config.BeEcompErrorManager; import org.openecomp.sdc.be.config.ConfigurationManager; import org.openecomp.sdc.be.dao.jsongraph.GraphVertex; @@ -67,12 +65,10 @@ import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields; import org.openecomp.sdc.be.datatypes.enums.OriginTypeEnum; import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum; import org.openecomp.sdc.be.model.ArtifactDefinition; -import org.openecomp.sdc.be.model.CapabilityDefinition; import org.openecomp.sdc.be.model.Component; import org.openecomp.sdc.be.model.ComponentInstance; import org.openecomp.sdc.be.model.ComponentInstanceInput; import org.openecomp.sdc.be.model.ComponentInstanceProperty; -import org.openecomp.sdc.be.model.DistributionStatusEnum; import org.openecomp.sdc.be.model.GroupDefinition; import org.openecomp.sdc.be.model.GroupInstance; import org.openecomp.sdc.be.model.RelationshipImpl; @@ -849,10 +845,8 @@ public class NodeTemplateOperation extends BaseOperation { dataDefinition.setComponentVersion((String) originToscaElement.getMetadataValue(JsonPresentationFields.VERSION)); if (StringUtils.isEmpty(dataDefinition.getComponentName()) && originToscaElement != null) dataDefinition.setComponentName((String) originToscaElement.getMetadataValue(JsonPresentationFields.NAME)); -// if (StringUtils.isEmpty(dataDefinition.getToscaComponentName()) && originToscaElement != null) - - dataDefinition.setToscaComponentName((String) originToscaElement.getMetadataValue(JsonPresentationFields.TOSCA_RESOURCE_NAME)); - + if (originToscaElement != null) + dataDefinition.setToscaComponentName((String) originToscaElement.getMetadataValue(JsonPresentationFields.TOSCA_RESOURCE_NAME)); if (dataDefinition.getOriginType() == null && originToscaElement != null) { ResourceTypeEnum resourceType = originToscaElement.getResourceType(); OriginTypeEnum originType = null; @@ -863,12 +857,18 @@ public class NodeTemplateOperation extends BaseOperation { case VFC: originType = OriginTypeEnum.VFC; break; + case CVFC: + originType = OriginTypeEnum.CVFC; + break; case VL: originType = OriginTypeEnum.VL; break; case CP: originType = OriginTypeEnum.CP; break; + case PNF: + originType = OriginTypeEnum.PNF; + break; default: break; } @@ -1016,7 +1016,7 @@ public class NodeTemplateOperation extends BaseOperation { CommonUtility.addRecordToLog(logger, LogLevelEnum.DEBUG, "Failed to update topology template {} with new relations error {}. ", componentId, updateElement.right().value()); return DaoStatusConverter.convertTitanStatusToStorageStatus(updateElement.right().value()); } - // update cap/req jsons, fullfilled cap/req jsons!!!!! + // update cap/req jsons, fulfilled cap/req jsons!!!!! Either status; CommonUtility.addRecordToLog(logger, LogLevelEnum.DEBUG, "Update calculated capabilty for container {}", containerV.getUniqueId()); status = updateOrCopyOnUpdate(capResult.left().value().getLeft(), containerV, EdgeLabelEnum.CALCULATED_CAPABILITIES); @@ -1070,7 +1070,7 @@ public class NodeTemplateOperation extends BaseOperation { } GraphVertex containerV = containerVEither.left().value(); - // DE191707 - validatations + // DE191707 - validations Map jsonComposition = (Map) containerV.getJson(); CompositionDataDefinition compositionDataDefinition = jsonComposition.get(JsonConstantKeysEnum.COMPOSITION.getValue()); Map componentInstances = compositionDataDefinition.getComponentInstances(); @@ -1092,16 +1092,15 @@ public class NodeTemplateOperation extends BaseOperation { Either>, StorageOperationStatus> capResult = fetchContainerCalculatedCapability(containerV, EdgeLabelEnum.CALCULATED_CAPABILITIES); if (capResult.isRight()) { return Either.right(capResult.right().value()); - } - Map calculatedCapabilty = capResult.left().value().getRight(); + Map calculatedCapability = capResult.left().value().getRight(); Either>, StorageOperationStatus> capFullResult = fetchContainerCalculatedCapability(containerV, EdgeLabelEnum.FULLFILLED_CAPABILITIES); if (capResult.isRight()) { return Either.right(capResult.right().value()); } - Map fullFilledCapabilty = capFullResult.left().value().getRight(); + Map fulfilledCapability = capFullResult.left().value().getRight(); Either>, StorageOperationStatus> reqResult = fetchContainerCalculatedRequirement(containerV, EdgeLabelEnum.CALCULATED_REQUIREMENTS); if (reqResult.isRight()) { @@ -1113,7 +1112,7 @@ public class NodeTemplateOperation extends BaseOperation { if (reqResult.isRight()) { return Either.right(reqResult.right().value()); } - Map fullfilledRequirement = reqFullResult.left().value().getRight(); + Map fulfilledRequirement = reqFullResult.left().value().getRight(); for (RequirementAndRelationshipPair relationPair : relationPairList) { Iterator> iterator = relations.entrySet().iterator(); @@ -1123,16 +1122,16 @@ public class NodeTemplateOperation extends BaseOperation { RelationshipInstDataDefinition relationInJson = entryInJson.getValue(); if (relationInJson.getFromId().equals(fromResInstanceUid) && relationInJson.getToId().equals(toResInstanceUid)) { if (relationPair.equalsTo(relationInJson)) { - CommonUtility.addRecordToLog(logger, LogLevelEnum.DEBUG, "Remove relation from {} to {} capabilty {} capOwnerId {} reqOwnerId {} ", toResInstanceUid, componentId, relationInJson.getType(), + CommonUtility.addRecordToLog(logger, LogLevelEnum.DEBUG, "Remove relation from {} to {} capability {} capOwnerId {} reqOwnerId {} ", toResInstanceUid, componentId, relationInJson.getType(), relationInJson.getCapabilityOwnerId(), relationInJson.getRequirementOwnerId()); iterator.remove(); // update calculated cap/req - StorageOperationStatus status = updateCalculatedCapabiltyAfterDeleteRelation(calculatedCapabilty, fullFilledCapabilty, toResInstanceUid, relationInJson); + StorageOperationStatus status = updateCalculatedCapabiltyAfterDeleteRelation(calculatedCapability, fulfilledCapability, toResInstanceUid, relationInJson); if (status != StorageOperationStatus.OK) { return Either.right(status); } - status = updateCalculatedRequirementsAfterDeleteRelation(calculatedRequirement, fullfilledRequirement, fromResInstanceUid, relationInJson); + status = updateCalculatedRequirementsAfterDeleteRelation(calculatedRequirement, fulfilledRequirement, fromResInstanceUid, relationInJson); if (status != StorageOperationStatus.OK) { return Either.right(status); } @@ -1168,90 +1167,87 @@ public class NodeTemplateOperation extends BaseOperation { private StorageOperationStatus updateCalculatedRequirementsAfterDeleteRelation(Map calculatedRequirement, Map fullFilledRequirement, String fromResInstanceUid, RelationshipInstDataDefinition relation) { StorageOperationStatus status; + String hereIsTheKey = null; MapListRequirementDataDefinition reqByInstance = calculatedRequirement.get(fromResInstanceUid); - if (reqByInstance == null) { - // move from fullfilled - status = moveFromFullFilledRequirement(calculatedRequirement, fullFilledRequirement, fromResInstanceUid, relation); + if (reqByInstance == null || reqByInstance.findKeyByItemUidMatch(relation.getRequirementId()) == null) { + // move from fulfilled + status = moveFromFullFilledRequirement(calculatedRequirement, fullFilledRequirement, fromResInstanceUid, relation, hereIsTheKey); } else { - ListRequirementDataDefinition reqByType = reqByInstance.findByKey(relation.getType()); - if (reqByType == null) { - // move from fullfilled - status = moveFromFullFilledRequirement(calculatedRequirement, fullFilledRequirement, fromResInstanceUid, relation); - } else { - Optional requirementOptional = reqByType.getListToscaDataDefinition().stream() - .filter(cap -> cap.getOwnerId().equals(relation.getRequirementOwnerId()) && cap.getName().equals(relation.getRequirement()) && cap.getUniqueId().equals(relation.getRequirementId())).findFirst(); + hereIsTheKey = reqByInstance.findKeyByItemUidMatch(relation.getRequirementId()); + ListRequirementDataDefinition reqByType = reqByInstance.findByKey(hereIsTheKey); + Optional requirementOptional = reqByType.getListToscaDataDefinition().stream() + .filter(req -> req.getOwnerId().equals(relation.getRequirementOwnerId()) && req.getName().equals(relation.getRequirement()) && req.getUniqueId().equals(relation.getRequirementId())).findFirst(); - if (requirementOptional.isPresent()) { + if (requirementOptional.isPresent()) { - RequirementDataDefinition requirement = requirementOptional.get(); - String leftOccurrences = requirement.getLeftOccurrences(); - if (leftOccurrences != null && !leftOccurrences.equals(RequirementDataDefinition.MAX_OCCURRENCES)) { - Integer leftIntValue = Integer.parseInt(leftOccurrences); - ++leftIntValue; - requirement.setLeftOccurrences(String.valueOf(leftIntValue)); - } - status = StorageOperationStatus.OK; - } else { - // move from fullfilled - status = moveFromFullFilledRequirement(calculatedRequirement, fullFilledRequirement, fromResInstanceUid, relation); + RequirementDataDefinition requirement = requirementOptional.get(); + String leftOccurrences = requirement.getLeftOccurrences(); + if (leftOccurrences != null && !leftOccurrences.equals(RequirementDataDefinition.MAX_OCCURRENCES)) { + Integer leftIntValue = Integer.parseInt(leftOccurrences); + ++leftIntValue; + requirement.setLeftOccurrences(String.valueOf(leftIntValue)); } + status = StorageOperationStatus.OK; + } else { + // move from fulfilled + status = moveFromFullFilledRequirement(calculatedRequirement, fullFilledRequirement, fromResInstanceUid, relation, hereIsTheKey); } } return status; } - private StorageOperationStatus updateCalculatedCapabiltyAfterDeleteRelation(Map calculatedCapabilty, Map fullFilledCapabilty, String toResInstanceUid, + + private StorageOperationStatus updateCalculatedCapabiltyAfterDeleteRelation(Map calculatedCapability, Map fullFilledCapability, String toResInstanceUid, RelationshipInstDataDefinition relation) { StorageOperationStatus status; - MapListCapabiltyDataDefinition capByInstance = calculatedCapabilty.get(toResInstanceUid); - if (capByInstance == null) { - // move from fullfilled - status = moveFromFullFilledCapabilty(calculatedCapabilty, fullFilledCapabilty, toResInstanceUid, relation); + String hereIsTheKey = null; + MapListCapabiltyDataDefinition capByInstance = calculatedCapability.get(toResInstanceUid); + if (capByInstance == null || capByInstance.findKeyByItemUidMatch(relation.getCapabilityId()) == null) { + // move from fulfilled + status = moveFromFullFilledCapabilty(calculatedCapability, fullFilledCapability, toResInstanceUid, relation, hereIsTheKey); } else { - ListCapabilityDataDefinition capByType = capByInstance.findByKey(relation.getType()); - if (capByType == null) { - // move from fullfilled - status = moveFromFullFilledCapabilty(calculatedCapabilty, fullFilledCapabilty, toResInstanceUid, relation); - } else { - Optional capabiltyOptional = capByType.getListToscaDataDefinition().stream() - .filter(cap -> cap.getOwnerId().equals(relation.getCapabilityOwnerId()) && cap.getUniqueId().equals(relation.getCapabiltyId())).findFirst(); + hereIsTheKey = capByInstance.findKeyByItemUidMatch(relation.getCapabilityId()); + ListCapabilityDataDefinition capByType = capByInstance.findByKey(hereIsTheKey); + Optional capabilityOptional = capByType.getListToscaDataDefinition().stream() + .filter(cap -> cap.getOwnerId().equals(relation.getCapabilityOwnerId()) && cap.getUniqueId().equals(relation.getCapabilityId())).findFirst(); - if (capabiltyOptional.isPresent()) { + if (capabilityOptional.isPresent()) { - CapabilityDataDefinition capability = capabiltyOptional.get(); - String leftOccurrences = capability.getLeftOccurrences(); - if (leftOccurrences != null && !leftOccurrences.equals(CapabilityDataDefinition.MAX_OCCURRENCES)) { - Integer leftIntValue = Integer.parseInt(leftOccurrences); - ++leftIntValue; - capability.setLeftOccurrences(String.valueOf(leftIntValue)); - } - status = StorageOperationStatus.OK; - } else { - // move from fullfilled - status = moveFromFullFilledCapabilty(calculatedCapabilty, fullFilledCapabilty, toResInstanceUid, relation); + CapabilityDataDefinition capability = capabilityOptional.get(); + String leftOccurrences = capability.getLeftOccurrences(); + if (leftOccurrences != null && !leftOccurrences.equals(CapabilityDataDefinition.MAX_OCCURRENCES)) { + Integer leftIntValue = Integer.parseInt(leftOccurrences); + ++leftIntValue; + capability.setLeftOccurrences(String.valueOf(leftIntValue)); } + status = StorageOperationStatus.OK; + } else { + // move from fulfilled + status = moveFromFullFilledCapabilty(calculatedCapability, fullFilledCapability, toResInstanceUid, relation, hereIsTheKey); } } return status; } - private StorageOperationStatus moveFromFullFilledCapabilty(Map calculatedCapabilty, Map fullFilledCapabilty, String toResInstanceUid, - RelationshipInstDataDefinition relation) { - MapListCapabiltyDataDefinition capByInstance = fullFilledCapabilty.get(toResInstanceUid); + private StorageOperationStatus moveFromFullFilledCapabilty(Map calculatedCapability, Map fullFilledCapability, String toResInstanceUid, + RelationshipInstDataDefinition relation, String hereIsTheKey) { + MapListCapabiltyDataDefinition capByInstance = fullFilledCapability.get(toResInstanceUid); if (capByInstance == null) { - CommonUtility.addRecordToLog(logger, LogLevelEnum.DEBUG, "No capabilty in fullfilled list for instance {} ", toResInstanceUid); + CommonUtility.addRecordToLog(logger, LogLevelEnum.DEBUG, "No capability in fulfilled list for instance {} ", toResInstanceUid); return StorageOperationStatus.GENERAL_ERROR; } - ListCapabilityDataDefinition capByType = capByInstance.findByKey(relation.getType()); - if (capByType == null) { - CommonUtility.addRecordToLog(logger, LogLevelEnum.DEBUG, "No capabilty type {} in fullfilled list for instance {} ", relation.getType(), toResInstanceUid); + if (null == hereIsTheKey) + hereIsTheKey = capByInstance.findKeyByItemUidMatch(relation.getCapabilityId()); + if (null == hereIsTheKey) { + CommonUtility.addRecordToLog(logger, LogLevelEnum.DEBUG, "No capability with id {} in fulfilled list for instance {} ", relation.getCapabilityId(), toResInstanceUid); return StorageOperationStatus.GENERAL_ERROR; } + ListCapabilityDataDefinition capByType = capByInstance.findByKey(hereIsTheKey); Iterator iterator = capByType.getListToscaDataDefinition().iterator(); boolean found = false; while (iterator.hasNext()) { CapabilityDataDefinition cap = iterator.next(); - if (cap.getOwnerId().equals(relation.getCapabilityOwnerId()) && cap.getName().equals(relation.getRequirement()) && cap.getUniqueId().equals(relation.getCapabiltyId())) { + if (cap.getOwnerId().equals(relation.getCapabilityOwnerId()) && cap.getUniqueId().equals(relation.getCapabilityId())) { found = true; iterator.remove(); // return to calculated list @@ -1260,38 +1256,40 @@ public class NodeTemplateOperation extends BaseOperation { ++leftIntValue; cap.setLeftOccurrences(String.valueOf(leftIntValue)); - MapListCapabiltyDataDefinition mapListCapaDataDef = calculatedCapabilty.get(toResInstanceUid); + MapListCapabiltyDataDefinition mapListCapaDataDef = calculatedCapability.get(toResInstanceUid); if (mapListCapaDataDef == null) { mapListCapaDataDef = new MapListCapabiltyDataDefinition(); } - ListCapabilityDataDefinition findByKey = mapListCapaDataDef.findByKey(relation.getType()); + ListCapabilityDataDefinition findByKey = mapListCapaDataDef.findByKey(hereIsTheKey); if (findByKey == null) { findByKey = new ListCapabilityDataDefinition(); - mapListCapaDataDef.put(relation.getType(), findByKey); + mapListCapaDataDef.put(hereIsTheKey, findByKey); } findByKey.add(cap); break; } } if (found == false) { - CommonUtility.addRecordToLog(logger, LogLevelEnum.DEBUG, "No capabilty type {} with ownerId {} in fullfilled list for instance {} ", relation.getType(), relation.getCapabilityOwnerId(), toResInstanceUid); + CommonUtility.addRecordToLog(logger, LogLevelEnum.DEBUG, "No capability type {} with ownerId {} in fulfilled list for instance {} ", hereIsTheKey, relation.getCapabilityOwnerId(), toResInstanceUid); return StorageOperationStatus.GENERAL_ERROR; } return StorageOperationStatus.OK; } private StorageOperationStatus moveFromFullFilledRequirement(Map calculatedRequirement, Map fullFilledRequirement, String fromResInstanceUid, - RelationshipInstDataDefinition relation) { + RelationshipInstDataDefinition relation, String hereIsTheKey) { MapListRequirementDataDefinition reqByInstance = fullFilledRequirement.get(fromResInstanceUid); if (reqByInstance == null) { CommonUtility.addRecordToLog(logger, LogLevelEnum.DEBUG, "No requirement in fullfilled list for instance {} ", fromResInstanceUid); return StorageOperationStatus.GENERAL_ERROR; } - ListRequirementDataDefinition reqByType = reqByInstance.findByKey(relation.getType()); - if (reqByType == null) { - CommonUtility.addRecordToLog(logger, LogLevelEnum.DEBUG, "No requirement type {} in fullfilled list for instance {} ", relation.getType(), fromResInstanceUid); + if(null == hereIsTheKey) + hereIsTheKey = reqByInstance.findKeyByItemUidMatch(relation.getRequirementId()); + if (null == hereIsTheKey) { + CommonUtility.addRecordToLog(logger, LogLevelEnum.DEBUG, "No requirement with id {} in fulfilled list for instance {} ", relation.getRequirementId(), fromResInstanceUid); return StorageOperationStatus.GENERAL_ERROR; } + ListRequirementDataDefinition reqByType = reqByInstance.findByKey(hereIsTheKey); Iterator iterator = reqByType.getListToscaDataDefinition().iterator(); boolean found = false; while (iterator.hasNext()) { @@ -1309,17 +1307,17 @@ public class NodeTemplateOperation extends BaseOperation { if (mapListReqDataDef == null) { mapListReqDataDef = new MapListRequirementDataDefinition(); } - ListRequirementDataDefinition findByKey = mapListReqDataDef.findByKey(relation.getType()); + ListRequirementDataDefinition findByKey = mapListReqDataDef.findByKey(hereIsTheKey); if (findByKey == null) { findByKey = new ListRequirementDataDefinition(); - mapListReqDataDef.put(relation.getType(), findByKey); + mapListReqDataDef.put(hereIsTheKey, findByKey); } findByKey.add(req); break; } } if (found == false) { - CommonUtility.addRecordToLog(logger, LogLevelEnum.DEBUG, "No requirement type {} with ownerId {} in fullfilled list for instance {} ", relation.getType(), relation.getCapabilityOwnerId(), fromResInstanceUid); + CommonUtility.addRecordToLog(logger, LogLevelEnum.DEBUG, "No requirement type {} with ownerId {} in fulfilled list for instance {} ", hereIsTheKey, relation.getRequirementOwnerId(), fromResInstanceUid); return StorageOperationStatus.GENERAL_ERROR; } return StorageOperationStatus.OK; @@ -1414,22 +1412,22 @@ public class NodeTemplateOperation extends BaseOperation { CommonUtility.addRecordToLog(logger, LogLevelEnum.DEBUG, "Failed to fetch calculated capabilities for type {} for instance {} in container {}.", type, toInstId, containerId); return Either.right(StorageOperationStatus.MATCH_NOT_FOUND); } - CapabilityDataDefinition capabiltyForRelation = null; + CapabilityDataDefinition capabilityForRelation = null; Iterator iteratorCap = listCapabilityDataDefinition.getListToscaDataDefinition().iterator(); while (iteratorCap.hasNext()) { CapabilityDataDefinition cap = iteratorCap.next(); if (cap.getUniqueId().equals(relationPair.getCapabilityUid()) && cap.getOwnerId().equals(relationPair.getCapabilityOwnerId())) { - capabiltyForRelation = cap; + capabilityForRelation = cap; String leftOccurrences = cap.getLeftOccurrences(); if (leftOccurrences != null && !leftOccurrences.equals(CapabilityDataDefinition.MAX_OCCURRENCES)) { Integer leftIntValue = Integer.parseInt(leftOccurrences); if (leftIntValue > 0) { --leftIntValue; - capabiltyForRelation.setLeftOccurrences(String.valueOf(leftIntValue)); + capabilityForRelation.setLeftOccurrences(String.valueOf(leftIntValue)); if (leftIntValue == 0) { // remove from calculated iteratorCap.remove(); - // move to fullfilled + // move to fulfilled MapListCapabiltyDataDefinition mapListCapabiltyFullFilledInst = fullfilledCapabilty.get(toInstId); if (mapListCapabiltyFullFilledInst == null) { mapListCapabiltyFullFilledInst = new MapListCapabiltyDataDefinition(); @@ -1441,17 +1439,17 @@ public class NodeTemplateOperation extends BaseOperation { listCapabilityFull = new ListCapabilityDataDefinition(); mapListCapabiltyFullFilledInst.put(type, listCapabilityFull); } - listCapabilityFull.add(capabiltyForRelation); + listCapabilityFull.add(capabilityForRelation); } break; } else { - CommonUtility.addRecordToLog(logger, LogLevelEnum.DEBUG, "No left occurrences capabilty {} to {} in container {}.", capabiltyForRelation.getType(), toInstId, containerId); + CommonUtility.addRecordToLog(logger, LogLevelEnum.DEBUG, "No left occurrences capabilty {} to {} in container {}.", capabilityForRelation.getType(), toInstId, containerId); return Either.right(StorageOperationStatus.MATCH_NOT_FOUND); } } } } - if (capabiltyForRelation == null) { + if (capabilityForRelation == null) { CommonUtility.addRecordToLog(logger, LogLevelEnum.DEBUG, "Failed to fetch capabilty for type {} for instance {} in container {}.", type, toInstId, containerId); return Either.right(StorageOperationStatus.MATCH_NOT_FOUND); } @@ -1485,7 +1483,7 @@ public class NodeTemplateOperation extends BaseOperation { if (leftIntValue == 0) { // remove from calculated iteratorReq.remove(); - // move to fullfilled + // move to fulfilled MapListRequirementDataDefinition mapListRequirementFullFilledInst = fullfilledRequirement.get(fromInstId); if (mapListRequirementFullFilledInst == null) { mapListRequirementFullFilledInst = new MapListRequirementDataDefinition(); @@ -1507,16 +1505,14 @@ public class NodeTemplateOperation extends BaseOperation { } } } - if (!capabiltyForRelation.getType().equals(requirementForRelation.getCapability())) { - CommonUtility.addRecordToLog(logger, LogLevelEnum.DEBUG, "No math for capabilty from type {} and requirement {} from {} to {} in container {}.", capabiltyForRelation.getType(), requirementForRelation.getCapability(), fromInstId, toInstId, + if (!capabilityForRelation.getType().equals(requirementForRelation.getCapability())) { + CommonUtility.addRecordToLog(logger, LogLevelEnum.DEBUG, "No math for capability from type {} and requirement {} from {} to {} in container {}.", capabilityForRelation.getType(), requirementForRelation.getCapability(), fromInstId, toInstId, containerId); return Either.right(StorageOperationStatus.MATCH_NOT_FOUND); } RelationshipInstDataDefinition relationshipTypeData = buildRelationshipInstData(fromInstId, toInstId, relationPair); - relationshipTypeData.setType(requirementForRelation.getRelationship()); - return Either.left(relationshipTypeData); } @@ -1531,7 +1527,7 @@ public class NodeTemplateOperation extends BaseOperation { relationshipInstData.setModificationTime(creationDate); relationshipInstData.setCapabilityOwnerId(relationPair.getCapabilityOwnerId()); relationshipInstData.setRequirementOwnerId(relationPair.getRequirementOwnerId()); - relationshipInstData.setCapabiltyId(relationPair.getCapabilityUid()); + relationshipInstData.setCapabilityId(relationPair.getCapabilityUid()); relationshipInstData.setRequirementId(relationPair.getRequirementUid()); relationshipInstData.setFromId(fromResInstanceUid); relationshipInstData.setToId(toInstId); diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/TopologyTemplateOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/TopologyTemplateOperation.java index 99a602f234..2d160bfc82 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/TopologyTemplateOperation.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/TopologyTemplateOperation.java @@ -140,7 +140,7 @@ public class TopologyTemplateOperation extends ToscaElementOperation { return result; } StorageOperationStatus associateInstGroups = associateInstGroupsToComponent(topologyTemplateVertex, topologyTemplate); - if (associateInstProperties != StorageOperationStatus.OK) { + if (associateInstGroups != StorageOperationStatus.OK) { result = Either.right(associateInstInputs); return result; } @@ -786,12 +786,11 @@ public class TopologyTemplateOperation extends ToscaElementOperation { GraphVertex categoryV = childVertex.left().value(); Map metadataProperties = categoryV.getMetadataProperties(); CategoryDefinition category = new CategoryDefinition(); - category.setUniqueId((String) metadataProperties.get(GraphPropertyEnum.UNIQUE_ID)); + category.setUniqueId(categoryV.getUniqueId()); category.setNormalizedName((String) metadataProperties.get(GraphPropertyEnum.NORMALIZED_NAME)); category.setName((String) metadataProperties.get(GraphPropertyEnum.NAME)); - Type listTypeCat = new TypeToken>() { - }.getType(); + Type listTypeCat = new TypeToken>() {}.getType(); List iconsfromJsonCat = getGson().fromJson((String) metadataProperties.get(GraphPropertyEnum.ICONS.getProperty()), listTypeCat); category.setIcons(iconsfromJsonCat); categories.add(category); diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/ToscaElementLifecycleOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/ToscaElementLifecycleOperation.java index d57e7cc255..4282a2cba8 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/ToscaElementLifecycleOperation.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/ToscaElementLifecycleOperation.java @@ -27,7 +27,6 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Optional; -import java.util.Map.Entry; import java.util.stream.Collectors; import org.apache.commons.collections.CollectionUtils; @@ -37,9 +36,7 @@ import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.tinkerpop.gremlin.structure.Direction; import org.apache.tinkerpop.gremlin.structure.Edge; import org.apache.tinkerpop.gremlin.structure.Vertex; - import org.openecomp.sdc.be.config.ConfigurationManager; -import org.openecomp.sdc.be.dao.api.ActionStatus; import org.openecomp.sdc.be.dao.jsongraph.GraphVertex; import org.openecomp.sdc.be.dao.jsongraph.types.EdgeLabelEnum; import org.openecomp.sdc.be.dao.jsongraph.types.EdgePropertyEnum; @@ -55,20 +52,16 @@ import org.openecomp.sdc.be.datatypes.elements.CompositionDataDefinition; import org.openecomp.sdc.be.datatypes.elements.GroupDataDefinition; import org.openecomp.sdc.be.datatypes.elements.GroupInstanceDataDefinition; import org.openecomp.sdc.be.datatypes.elements.MapArtifactDataDefinition; -import org.openecomp.sdc.be.datatypes.elements.MapDataDefinition; import org.openecomp.sdc.be.datatypes.elements.MapGroupsDataDefinition; import org.openecomp.sdc.be.datatypes.elements.MapPropertiesDataDefinition; import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition; import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; import org.openecomp.sdc.be.datatypes.enums.GraphPropertyEnum; import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields; -import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum; import org.openecomp.sdc.be.datatypes.enums.OriginTypeEnum; import org.openecomp.sdc.be.datatypes.tosca.ToscaDataDefinition; -import org.openecomp.sdc.be.model.ArtifactDefinition; import org.openecomp.sdc.be.model.ComponentParametersView; import org.openecomp.sdc.be.model.DistributionStatusEnum; -import org.openecomp.sdc.be.model.GroupDefinition; import org.openecomp.sdc.be.model.LifecycleStateEnum; import org.openecomp.sdc.be.model.User; import org.openecomp.sdc.be.model.jsontitan.datamodel.TopologyTemplate; @@ -78,10 +71,8 @@ import org.openecomp.sdc.be.model.jsontitan.enums.JsonConstantKeysEnum; import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; import org.openecomp.sdc.be.model.operations.impl.DaoStatusConverter; import org.openecomp.sdc.be.model.operations.impl.UniqueIdBuilder; -import org.openecomp.sdc.common.api.ArtifactTypeEnum; import org.openecomp.sdc.common.jsongraph.util.CommonUtility; import org.openecomp.sdc.common.jsongraph.util.CommonUtility.LogLevelEnum; -import org.openecomp.sdc.exception.ResponseFormat; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -1014,8 +1005,8 @@ public class ToscaElementLifecycleOperation extends BaseOperation { } //TODO remove after jsonModelMigration - public void resolveToscaComponentName(ComponentInstanceDataDefinition vfInst, Map origCompMap) { - fixToscaComponentName(vfInst, origCompMap); + public boolean resolveToscaComponentName(ComponentInstanceDataDefinition vfInst, Map origCompMap) { + return fixToscaComponentName(vfInst, origCompMap); } private boolean fixToscaComponentName(ComponentInstanceDataDefinition vfInst, Map origCompMap) { @@ -1035,7 +1026,7 @@ public class ToscaElementLifecycleOperation extends BaseOperation { CommonUtility.addRecordToLog(logger, LogLevelEnum.DEBUG, "Failed to find orig component {} . Status is {}. ", origCompEither.right().value()); return false; } - origComp = origCompEither.left().value(); + origComp = origCompEither.left().value(); origCompMap.put(origCompUid, origComp); } else { origComp = origCompMap.get(origCompUid); @@ -1460,4 +1451,72 @@ public class ToscaElementLifecycleOperation extends BaseOperation { } return false; } + + public Either forceCerificationOfToscaElement(String toscaElementId, String modifierId, String ownerId) { + Either resultUpdate = null; + Either result = null; + GraphVertex toscaElement = null; + GraphVertex modifier = null; + GraphVertex owner; + try { + Either, TitanOperationStatus> getVerticesRes = titanDao.getVerticesByUniqueIdAndParseFlag(prepareParametersToGetVerticesForRequestCertification(toscaElementId, modifierId, ownerId)); + if (getVerticesRes.isRight()) { + CommonUtility.addRecordToLog(logger, LogLevelEnum.DEBUG, FAILED_TO_GET_VERTICES, toscaElementId); + result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(getVerticesRes.right().value())); + } + if (result == null) { + toscaElement = getVerticesRes.left().value().get(toscaElementId); + modifier = getVerticesRes.left().value().get(modifierId); + owner = getVerticesRes.left().value().get(ownerId); + + StorageOperationStatus status = handleRelationsUponForceCertification(toscaElement, modifier, owner); + if (status != StorageOperationStatus.OK) { + CommonUtility.addRecordToLog(logger, LogLevelEnum.DEBUG, "Failed to handle relations on certification request for tosca element {}. Status is {}. ", toscaElement.getUniqueId(), status); + } + } + if (result == null) { + LifecycleStateEnum nextState = LifecycleStateEnum.CERTIFIED; + + toscaElement.addMetadataProperty(GraphPropertyEnum.STATE, LifecycleStateEnum.CERTIFIED.name()); + toscaElement.addMetadataProperty(GraphPropertyEnum.VERSION, "1.0"); + + resultUpdate = updateToscaElementVertexMetadataPropertiesAndJson(toscaElement); + if (resultUpdate.isRight()) { + CommonUtility.addRecordToLog(logger, LogLevelEnum.DEBUG, "Failed to set lifecycle for tosca elememt {} to state {}, error: {}", toscaElement.getUniqueId(), nextState, resultUpdate.right().value()); + result = Either.right(resultUpdate.right().value()); + } + } + if (result == null) { + ToscaElementOperation operation = getToscaElementOperation(toscaElement.getLabel()); + result = operation.getToscaElement(toscaElement.getUniqueId()); + } + return result; + + } catch (Exception e) { + CommonUtility.addRecordToLog(logger, LogLevelEnum.DEBUG, "Exception occured during request certification tosca element {}. {}", toscaElementId, e.getMessage()); + } + return result; + } + + private StorageOperationStatus handleRelationsUponForceCertification(GraphVertex toscaElement, GraphVertex modifier, GraphVertex owner) { + + StorageOperationStatus result = null; + TitanOperationStatus status = titanDao.replaceEdgeLabel(owner.getVertex(), toscaElement.getVertex(), EdgeLabelEnum.STATE, EdgeLabelEnum.LAST_STATE); + if (status != TitanOperationStatus.OK) { + result = DaoStatusConverter.convertTitanStatusToStorageStatus(status); + } + if (result == null) { + Map properties = new EnumMap<>(EdgePropertyEnum.class); + properties.put(EdgePropertyEnum.STATE, LifecycleStateEnum.CERTIFIED); + status = titanDao.createEdge(modifier, toscaElement, EdgeLabelEnum.STATE, properties); + if (status != TitanOperationStatus.OK) { + CommonUtility.addRecordToLog(logger, LogLevelEnum.DEBUG, "failed to create edge. Status is {}", status); + result = DaoStatusConverter.convertTitanStatusToStorageStatus(status); + } + } + if (result == null) { + result = StorageOperationStatus.OK; + } + return result; + } } diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/ToscaElementOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/ToscaElementOperation.java index 99cbd34c9b..5aceb2ffd2 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/ToscaElementOperation.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/ToscaElementOperation.java @@ -20,16 +20,9 @@ package org.openecomp.sdc.be.model.jsontitan.operations; -import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; - +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import fj.data.Either; import org.apache.tinkerpop.gremlin.structure.Direction; import org.apache.tinkerpop.gremlin.structure.Edge; import org.apache.tinkerpop.gremlin.structure.Vertex; @@ -59,7 +52,6 @@ import org.openecomp.sdc.be.model.jsontitan.datamodel.ToscaElementTypeEnum; import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; import org.openecomp.sdc.be.model.operations.impl.DaoStatusConverter; import org.openecomp.sdc.be.model.operations.impl.UniqueIdBuilder; -import org.openecomp.sdc.be.resources.data.UserData; import org.openecomp.sdc.common.jsongraph.util.CommonUtility; import org.openecomp.sdc.common.jsongraph.util.CommonUtility.LogLevelEnum; import org.openecomp.sdc.common.util.ValidationUtils; @@ -67,10 +59,9 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import com.google.gson.Gson; -import com.google.gson.reflect.TypeToken; - -import fj.data.Either; +import java.lang.reflect.Type; +import java.util.*; +import java.util.Map.Entry; public abstract class ToscaElementOperation extends BaseOperation { private static Logger log = LoggerFactory.getLogger(ToscaElementOperation.class.getName()); @@ -1074,13 +1065,15 @@ public abstract class ToscaElementOperation extends BaseOperation { return status; } - public Either, StorageOperationStatus> getElementCatalogData(ComponentTypeEnum componentType, ToscaElementTypeEnum toscaElement, boolean isHighestVersions) { + public Either, StorageOperationStatus> getElementCatalogData(ComponentTypeEnum componentType, List excludeTypes, boolean isHighestVersions) { Either, TitanOperationStatus> listOfComponents; if (isHighestVersions) { - listOfComponents = getListOfHighestComponents(componentType, toscaElement); - } else { - listOfComponents = getListOfHighestAndAllCertifiedComponents(componentType, toscaElement); + listOfComponents = getListOfHighestComponents(componentType, excludeTypes); } + else { + listOfComponents = getListOfHighestAndAllCertifiedComponents(componentType, excludeTypes); + } + if (listOfComponents.isRight() && listOfComponents.right().value() != TitanOperationStatus.NOT_FOUND) { return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(listOfComponents.right().value())); } @@ -1091,7 +1084,7 @@ public abstract class ToscaElementOperation extends BaseOperation { for (GraphVertex vertexComponent : highestAndAllCertified) { Either component = getLightComponent(vertexComponent, componentType, new ComponentParametersView(true)); if (component.isRight()) { - log.debug("Failed to fetch ligth element for {} error {}", vertexComponent.getUniqueId(), component.right().value()); + log.debug("Failed to fetch light element for {} error {}", vertexComponent.getUniqueId(), component.right().value()); return Either.right(component.right().value()); } else { result.add(component.left().value()); @@ -1102,82 +1095,55 @@ public abstract class ToscaElementOperation extends BaseOperation { return Either.left(result); } - private Either, TitanOperationStatus> getListOfHighestComponents(ComponentTypeEnum componentType, ToscaElementTypeEnum toscaElement) { + private Either, TitanOperationStatus> getListOfHighestComponents(ComponentTypeEnum componentType, List excludeTypes) { Map propertiesToMatch = new HashMap<>(); + Map propertiesHasNotToMatch = new HashMap<>(); propertiesToMatch.put(GraphPropertyEnum.COMPONENT_TYPE, componentType.name()); propertiesToMatch.put(GraphPropertyEnum.IS_HIGHEST_VERSION, true); if (componentType == ComponentTypeEnum.RESOURCE) { propertiesToMatch.put(GraphPropertyEnum.IS_ABSTRACT, false); + propertiesHasNotToMatch.put(GraphPropertyEnum.RESOURCE_TYPE, excludeTypes); } - - Map propertiesHasNotToMatch = new HashMap<>(); propertiesHasNotToMatch.put(GraphPropertyEnum.IS_DELETED, true); - return titanDao.getByCriteria(ToscaElementTypeEnum.getVertexTypeByToscaType(toscaElement), propertiesToMatch, propertiesHasNotToMatch, JsonParseFlagEnum.ParseMetadata); + return titanDao.getByCriteria(null, propertiesToMatch, propertiesHasNotToMatch, JsonParseFlagEnum.ParseMetadata); } - public Either, TitanOperationStatus> getListOfHighestAndAllCertifiedComponents(ComponentTypeEnum componentType, ToscaElementTypeEnum toscaElement) { + // highest + (certified && !highest) + public Either, TitanOperationStatus> getListOfHighestAndAllCertifiedComponents(ComponentTypeEnum componentType, List excludeTypes) { long startFetchAllStates = System.currentTimeMillis(); + Either, TitanOperationStatus> highestNodes = getListOfHighestComponents(componentType, excludeTypes); + Map propertiesToMatchCertified = new HashMap<>(); + Map propertiesHasNotToMatchCertified = new HashMap<>(); propertiesToMatchCertified.put(GraphPropertyEnum.STATE, LifecycleStateEnum.CERTIFIED.name()); propertiesToMatchCertified.put(GraphPropertyEnum.COMPONENT_TYPE, componentType.name()); if (componentType == ComponentTypeEnum.RESOURCE) { propertiesToMatchCertified.put(GraphPropertyEnum.IS_ABSTRACT, false); + propertiesHasNotToMatchCertified.put(GraphPropertyEnum.RESOURCE_TYPE, excludeTypes); } - Map propertiesHasNotToMatchCertified = new HashMap<>(); propertiesHasNotToMatchCertified.put(GraphPropertyEnum.IS_DELETED, true); + propertiesHasNotToMatchCertified.put(GraphPropertyEnum.IS_HIGHEST_VERSION, true); - Either, TitanOperationStatus> certifiedNodes = titanDao.getByCriteria(ToscaElementTypeEnum.getVertexTypeByToscaType(toscaElement), propertiesToMatchCertified, propertiesHasNotToMatchCertified, + Either, TitanOperationStatus> certifiedNotHighestNodes = titanDao.getByCriteria(null, propertiesToMatchCertified, propertiesHasNotToMatchCertified, JsonParseFlagEnum.ParseMetadata); - if (certifiedNodes.isRight() && certifiedNodes.right().value() != TitanOperationStatus.NOT_FOUND) { - return Either.right(certifiedNodes.right().value()); - } - - Map propertiesToMatchHighest = new HashMap<>(); - propertiesToMatchHighest.put(GraphPropertyEnum.IS_HIGHEST_VERSION, true); - propertiesToMatchHighest.put(GraphPropertyEnum.COMPONENT_TYPE, componentType.name()); - if (componentType == ComponentTypeEnum.RESOURCE) { - propertiesToMatchHighest.put(GraphPropertyEnum.IS_ABSTRACT, false); - } - - Map propertiesHasNotToMatchHighest = new HashMap<>(); - propertiesHasNotToMatchHighest.put(GraphPropertyEnum.IS_DELETED, true); - propertiesHasNotToMatchHighest.put(GraphPropertyEnum.STATE, LifecycleStateEnum.CERTIFIED.name()); - - Either, TitanOperationStatus> highestNode = titanDao.getByCriteria(ToscaElementTypeEnum.getVertexTypeByToscaType(toscaElement), propertiesToMatchHighest, propertiesHasNotToMatchHighest, JsonParseFlagEnum.ParseMetadata); - if (highestNode.isRight() && highestNode.right().value() != TitanOperationStatus.NOT_FOUND) { - return Either.right(highestNode.right().value()); + if (certifiedNotHighestNodes.isRight() && certifiedNotHighestNodes.right().value() != TitanOperationStatus.NOT_FOUND) { + return Either.right(certifiedNotHighestNodes.right().value()); } long endFetchAllStates = System.currentTimeMillis(); List allNodes = new ArrayList<>(); - if (certifiedNodes.isLeft()) { - allNodes.addAll(certifiedNodes.left().value()); - } - if (highestNode.isLeft()) { - allNodes.addAll(highestNode.left().value()); - } - - int certifiedSize; - int nonCertifiedSize; - - if (certifiedNodes.isRight()) { - certifiedSize = 0; - } else { - certifiedSize = certifiedNodes.left().value().size(); + if (certifiedNotHighestNodes.isLeft()) { + allNodes.addAll(certifiedNotHighestNodes.left().value()); } - - if (highestNode.isRight()) { - nonCertifiedSize = 0; - } else { - nonCertifiedSize = highestNode.left().value().size(); + if (highestNodes.isLeft()) { + allNodes.addAll(highestNodes.left().value()); } - log.debug("Fetch catalog {}s all states: certified {}, noncertified {}", componentType, certifiedSize, nonCertifiedSize); log.debug("Fetch catalog {}s all states from graph took {} ms", componentType, endFetchAllStates - startFetchAllStates); return Either.left(allNodes); } diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/ToscaOperationFacade.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/ToscaOperationFacade.java index 8999340f0a..64424a8070 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/ToscaOperationFacade.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/ToscaOperationFacade.java @@ -21,9 +21,9 @@ package org.openecomp.sdc.be.model.jsontitan.operations; import java.util.*; +import fj.data.Either; import java.util.Map.Entry; import java.util.stream.Collectors; - import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.ImmutablePair; @@ -36,45 +36,11 @@ import org.openecomp.sdc.be.dao.jsongraph.types.VertexTypeEnum; import org.openecomp.sdc.be.dao.titan.TitanOperationStatus; import org.openecomp.sdc.be.datatypes.components.ComponentMetadataDataDefinition; import org.openecomp.sdc.be.datatypes.components.ResourceMetadataDataDefinition; -import org.openecomp.sdc.be.datatypes.elements.ArtifactDataDefinition; -import org.openecomp.sdc.be.datatypes.elements.CapabilityDataDefinition; -import org.openecomp.sdc.be.datatypes.elements.ComponentInstanceDataDefinition; -import org.openecomp.sdc.be.datatypes.elements.GroupDataDefinition; -import org.openecomp.sdc.be.datatypes.elements.ListCapabilityDataDefinition; -import org.openecomp.sdc.be.datatypes.elements.ListRequirementDataDefinition; -import org.openecomp.sdc.be.datatypes.elements.MapArtifactDataDefinition; -import org.openecomp.sdc.be.datatypes.elements.MapCapabiltyProperty; -import org.openecomp.sdc.be.datatypes.elements.MapListCapabiltyDataDefinition; -import org.openecomp.sdc.be.datatypes.elements.MapListRequirementDataDefinition; -import org.openecomp.sdc.be.datatypes.elements.MapPropertiesDataDefinition; -import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition; -import org.openecomp.sdc.be.datatypes.elements.RequirementDataDefinition; -import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; -import org.openecomp.sdc.be.datatypes.enums.GraphPropertyEnum; -import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields; -import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum; -import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum; -import org.openecomp.sdc.be.model.ArtifactDefinition; -import org.openecomp.sdc.be.model.CapabilityDefinition; -import org.openecomp.sdc.be.model.Component; -import org.openecomp.sdc.be.model.ComponentInstance; -import org.openecomp.sdc.be.model.ComponentInstanceInput; -import org.openecomp.sdc.be.model.ComponentInstanceProperty; -import org.openecomp.sdc.be.model.ComponentParametersView; -import org.openecomp.sdc.be.model.DistributionStatusEnum; -import org.openecomp.sdc.be.model.GroupDefinition; -import org.openecomp.sdc.be.model.GroupInstance; -import org.openecomp.sdc.be.model.InputDefinition; -import org.openecomp.sdc.be.model.LifecycleStateEnum; -import org.openecomp.sdc.be.model.PropertyDefinition; -import org.openecomp.sdc.be.model.RequirementCapabilityRelDef; -import org.openecomp.sdc.be.model.RequirementDefinition; -import org.openecomp.sdc.be.model.Resource; -import org.openecomp.sdc.be.model.Service; -import org.openecomp.sdc.be.model.User; +import org.openecomp.sdc.be.datatypes.elements.*; +import org.openecomp.sdc.be.datatypes.enums.*; +import org.openecomp.sdc.be.model.*; import org.openecomp.sdc.be.model.jsontitan.datamodel.TopologyTemplate; import org.openecomp.sdc.be.model.jsontitan.datamodel.ToscaElement; -import org.openecomp.sdc.be.model.jsontitan.datamodel.ToscaElementTypeEnum; import org.openecomp.sdc.be.model.jsontitan.utils.ModelConverter; import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; import org.openecomp.sdc.be.model.operations.impl.DaoStatusConverter; @@ -88,2088 +54,2121 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import fj.data.Either; +import java.util.*; +import java.util.Map.Entry; +import java.util.stream.Collectors; @org.springframework.stereotype.Component("tosca-operation-facade") public class ToscaOperationFacade { - @Autowired - private NodeTypeOperation nodeTypeOperation; - @Autowired - private TopologyTemplateOperation topologyTemplateOperation; - @Autowired - private NodeTemplateOperation nodeTemplateOperation; - @Autowired - private GroupsOperation groupsOperation; - @Autowired - private TitanDao titanDao; - - private static Logger log = LoggerFactory.getLogger(ToscaOperationFacade.class.getName()); - - public Either getToscaElement(String componentId) { + @Autowired + private NodeTypeOperation nodeTypeOperation; + @Autowired + private TopologyTemplateOperation topologyTemplateOperation; + @Autowired + private NodeTemplateOperation nodeTemplateOperation; + @Autowired + private GroupsOperation groupsOperation; + @Autowired + private TitanDao titanDao; + + private static Logger log = LoggerFactory.getLogger(ToscaOperationFacade.class.getName()); + + public Either getToscaElement(String componentId) { + + return getToscaElement(componentId, JsonParseFlagEnum.ParseAll); + + } + + public Either getToscaFullElement(String componentId) { + ComponentParametersView filters = new ComponentParametersView(); + filters.setIgnoreCapabiltyProperties(false); + + return getToscaElement(componentId, filters); + } + + public Either getToscaElement(String componentId, ComponentParametersView filters) { + + Either getVertexEither = titanDao.getVertexById(componentId, filters.detectParseFlag()); + if (getVertexEither.isRight()) { + log.debug("Couldn't fetch component with and unique id {}, error: {}", componentId, getVertexEither.right().value()); + return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(getVertexEither.right().value())); + + } + return getToscaElementByOperation(getVertexEither.left().value(), filters); + } + + public Either getToscaElement(String componentId, JsonParseFlagEnum parseFlag) { + + Either getVertexEither = titanDao.getVertexById(componentId, parseFlag); + if (getVertexEither.isRight()) { + log.debug("Couldn't fetch component with and unique id {}, error: {}", componentId, getVertexEither.right().value()); + return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(getVertexEither.right().value())); + + } + return getToscaElementByOperation(getVertexEither.left().value()); + } + + public Either getToscaElement(GraphVertex componentVertex) { + return getToscaElementByOperation(componentVertex); + } + + public Either validateComponentExists(String componentId) { + + Either getVertexEither = titanDao.getVertexById(componentId, JsonParseFlagEnum.NoParse); + if (getVertexEither.isRight()) { + TitanOperationStatus status = getVertexEither.right().value(); + if (status == TitanOperationStatus.NOT_FOUND) { + return Either.left(false); + } else { + log.debug("Couldn't fetch component with and unique id {}, error: {}", componentId, getVertexEither.right().value()); + return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(getVertexEither.right().value())); + } + } + return Either.left(true); + } + + public Either findLastCertifiedToscaElementByUUID(T component) { + Map props = new HashMap<>(); + props.put(GraphPropertyEnum.UUID, component.getUUID()); + props.put(GraphPropertyEnum.STATE, LifecycleStateEnum.CERTIFIED.name()); + props.put(GraphPropertyEnum.IS_HIGHEST_VERSION, true); + + Either, TitanOperationStatus> getVertexEither = titanDao.getByCriteria(ModelConverter.getVertexType(component), props); + if (getVertexEither.isRight()) { + log.debug("Couldn't fetch component with and unique id {}, error: {}", component.getUniqueId(), getVertexEither.right().value()); + return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(getVertexEither.right().value())); + + } + return getToscaElementByOperation(getVertexEither.left().value().get(0)); + } + + private Either getToscaElementByOperation(GraphVertex componentV) { + return getToscaElementByOperation(componentV, new ComponentParametersView()); + } + + private Either getToscaElementByOperation(GraphVertex componentV, ComponentParametersView filters) { + VertexTypeEnum label = componentV.getLabel(); + + ToscaElementOperation toscaOperation = getToscaElementOperation(componentV); + Either toscaElement; + String componentId = componentV.getUniqueId(); + if (toscaOperation != null) { + log.debug("Need to fetch tosca element for id {}", componentId); + toscaElement = toscaOperation.getToscaElement(componentV, filters); + } else { + log.debug("not supported tosca type {} for id {}", label, componentId); + toscaElement = Either.right(StorageOperationStatus.BAD_REQUEST); + } + if (toscaElement.isRight()) { + return Either.right(toscaElement.right().value()); + } + return Either.left(ModelConverter.convertFromToscaElement(toscaElement.left().value())); + } + + private ToscaElementOperation getToscaElementOperation(GraphVertex componentV) { + VertexTypeEnum label = componentV.getLabel(); + switch (label) { + case NODE_TYPE: + return nodeTypeOperation; + case TOPOLOGY_TEMPLATE: + return topologyTemplateOperation; + default: + return null; + } + } + + /** + * + * @param resource + * @return + */ + public Either createToscaComponent(T resource) { + ToscaElement toscaElement = ModelConverter.convertToToscaElement(resource); + + ToscaElementOperation toscaElementOperation = getToscaElementOperation(resource); + Either createToscaElement = toscaElementOperation.createToscaElement(toscaElement); + if (createToscaElement.isLeft()) { + log.debug("Component created successfully!!!"); + T dataModel = ModelConverter.convertFromToscaElement(createToscaElement.left().value()); + return Either.left(dataModel); + } + return Either.right(createToscaElement.right().value()); + } + + /** + * + * @param componentToDelete + * @return + */ + public StorageOperationStatus markComponentToDelete(Component componentToDelete) { + + if ((componentToDelete.getIsDeleted() != null) && componentToDelete.getIsDeleted() && !componentToDelete.isHighestVersion()) { + // component already marked for delete + return StorageOperationStatus.OK; + } else { + + Either getResponse = titanDao.getVertexById(componentToDelete.getUniqueId(), JsonParseFlagEnum.ParseAll); + if (getResponse.isRight()) { + log.debug("Couldn't fetch component with and unique id {}, error: {}", componentToDelete.getUniqueId(), getResponse.right().value()); + return DaoStatusConverter.convertTitanStatusToStorageStatus(getResponse.right().value()); + + } + GraphVertex componentV = getResponse.left().value(); + + // same operation for node type and topology template operations + Either result = nodeTypeOperation.markComponentToDelete(componentV); + if (result.isRight()) { + return result.right().value(); + } + return StorageOperationStatus.OK; + } + } + + /** + * + * @param componentId + * @return + */ + public Either deleteToscaComponent(String componentId) { + + Either getVertexEither = titanDao.getVertexById(componentId, JsonParseFlagEnum.ParseAll); + if (getVertexEither.isRight()) { + log.debug("Couldn't fetch component vertex with and unique id {}, error: {}", componentId, getVertexEither.right().value()); + return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(getVertexEither.right().value())); + + } + Either deleteElement = deleteToscaElement(getVertexEither.left().value()); + if (deleteElement.isRight()) { + log.debug("Failed to delete component with and unique id {}, error: {}", componentId, deleteElement.right().value()); + return Either.right(deleteElement.right().value()); + } + T dataModel = ModelConverter.convertFromToscaElement(deleteElement.left().value()); + + return Either.left(dataModel); + } + + private Either deleteToscaElement(GraphVertex componentV) { + VertexTypeEnum label = componentV.getLabel(); + Either toscaElement; + Object componentId = componentV.getUniqueId(); + switch (label) { + case NODE_TYPE: + log.debug("Need to fetch node type for id {}", componentId); + toscaElement = nodeTypeOperation.deleteToscaElement(componentV); + break; + case TOPOLOGY_TEMPLATE: + log.debug("Need to fetch topology template for id {}", componentId); + toscaElement = topologyTemplateOperation.deleteToscaElement(componentV); + break; + default: + log.debug("not supported tosca type {} for id {}", label, componentId); + toscaElement = Either.right(StorageOperationStatus.BAD_REQUEST); + break; + } + return toscaElement; + } + + private ToscaElementOperation getToscaElementOperation(Component component) { + return ModelConverter.isAtomicComponent(component) ? nodeTypeOperation : topologyTemplateOperation; + } + + public Either getLatestByToscaResourceName(String toscaResourceName) { + return getLatestByName(GraphPropertyEnum.TOSCA_RESOURCE_NAME, toscaResourceName); + + } + + public Either getLatestByName(String resourceName) { + return getLatestByName(GraphPropertyEnum.NAME, resourceName); + + } + + public Either validateCsarUuidUniqueness(String csarUUID) { + Either, StorageOperationStatus> byCsar = null; + + Map properties = new HashMap(); + properties.put(GraphPropertyEnum.CSAR_UUID, csarUUID); + + Either, TitanOperationStatus> resources = titanDao.getByCriteria(null, properties, JsonParseFlagEnum.ParseMetadata); + + if (resources.isRight()) { + if (resources.right().value() == TitanOperationStatus.NOT_FOUND) { + return Either.left(new Integer(0)); + } else { + log.debug("failed to get resources from graph with property name: {}", csarUUID); + return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(resources.right().value())); + } + } + + List resourceList = (resources.isLeft() ? resources.left().value() : null); + + return Either.left(new Integer(resourceList.size())); + + } - return getToscaElement(componentId, JsonParseFlagEnum.ParseAll); - - } - - public Either getToscaFullElement(String componentId) { - ComponentParametersView filters = new ComponentParametersView(); - filters.setIgnoreCapabiltyProperties(false); + public Either, StorageOperationStatus> getFollowed(String userId, Set lifecycleStates, Set lastStateStates, ComponentTypeEnum componentType) { + Either, StorageOperationStatus> followedResources; + if (componentType == ComponentTypeEnum.RESOURCE) { + followedResources = nodeTypeOperation.getFollowedComponent(userId, lifecycleStates, lastStateStates, componentType); + } else { + followedResources = topologyTemplateOperation.getFollowedComponent(userId, lifecycleStates, lastStateStates, componentType); + } - return getToscaElement(componentId, filters); - } + Set components = new HashSet<>(); + if (followedResources.isRight() && followedResources.right().value() != StorageOperationStatus.NOT_FOUND) { + return Either.right(followedResources.right().value()); + } + if (followedResources.isLeft()) { + List toscaElements = followedResources.left().value(); + toscaElements.forEach(te -> { + T component = ModelConverter.convertFromToscaElement(te); + components.add(component); + }); + } + return Either.left(components); + } + + public Either getLatestCertifiedNodeTypeByToscaResourceName(String toscaResourceName) { + + return getLatestCertifiedByToscaResourceName(toscaResourceName, VertexTypeEnum.NODE_TYPE, JsonParseFlagEnum.ParseMetadata); + } + + public Either getLatestCertifiedByToscaResourceName(String toscaResourceName, VertexTypeEnum vertexType, JsonParseFlagEnum parseFlag) { + + Either result = null; + Map props = new HashMap(); + props.put(GraphPropertyEnum.TOSCA_RESOURCE_NAME, toscaResourceName); + props.put(GraphPropertyEnum.IS_HIGHEST_VERSION, true); + props.put(GraphPropertyEnum.STATE, LifecycleStateEnum.CERTIFIED.name()); + Either, TitanOperationStatus> getLatestRes = titanDao.getByCriteria(vertexType, props, parseFlag); + + if (getLatestRes.isRight()) { + TitanOperationStatus status = getLatestRes.right().value(); + CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to fetch {} with name {}. status={} ", vertexType, toscaResourceName, status); + result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status)); + } + if (result == null) { + List resources = getLatestRes.left().value(); + double version = 0.0; + GraphVertex highestResource = null; + for (GraphVertex resource : resources) { + double resourceVersion = Double.parseDouble((String) resource.getJsonMetadataField(JsonPresentationFields.VERSION)); + if (resourceVersion > version) { + version = resourceVersion; + highestResource = resource; + } + } + result = getToscaElement(highestResource.getUniqueId()); + } + return result; + } + + public Either validateToscaResourceNameExists(String templateName) { + Either validateUniquenessRes = validateToscaResourceNameUniqueness(templateName); + if (validateUniquenessRes.isLeft()) { + return Either.left(!validateUniquenessRes.left().value()); + } + return validateUniquenessRes; + } + + public Either dissociateResourceInstances(String componentId, RequirementCapabilityRelDef requirementDef) { + return nodeTemplateOperation.dissociateResourceInstances(componentId, requirementDef); + + } + + public StorageOperationStatus associateResourceInstances(String componentId, List relations) { + Either, StorageOperationStatus> status = nodeTemplateOperation.associateResourceInstances(componentId, relations); + if (status.isRight()) { + return status.right().value(); + } + return StorageOperationStatus.OK; + } + + protected Either validateToscaResourceNameUniqueness(String name) { + + Map properties = new HashMap(); + properties.put(GraphPropertyEnum.TOSCA_RESOURCE_NAME, name); + + Either, TitanOperationStatus> resources = titanDao.getByCriteria(null, properties, JsonParseFlagEnum.ParseMetadata); + + if (resources.isRight() && resources.right().value() != TitanOperationStatus.NOT_FOUND) { + log.debug("failed to get resources from graph with property name: {}", name); + return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(resources.right().value())); + } + List resourceList = (resources.isLeft() ? resources.left().value() : null); + if (resourceList != null && resourceList.size() > 0) { + if (log.isDebugEnabled()) { + StringBuilder builder = new StringBuilder(); + for (GraphVertex resourceData : resourceList) { + builder.append(resourceData.getUniqueId() + "|"); + } + log.debug("resources with property name:{} exists in graph. found {}", name, builder.toString()); + } + return Either.left(false); + } else { + log.debug("resources with property name:{} does not exists in graph", name); + return Either.left(true); + } + + } + + /** + * + * @param newComponent + * @param oldComponent + * @return + */ + public Either overrideComponent(T newComponent, T oldComponent) { + + // TODO + // newComponent.setInterfaces(oldComponent.getInterfaces); + newComponent.setArtifacts(oldComponent.getArtifacts()); + newComponent.setDeploymentArtifacts(oldComponent.getDeploymentArtifacts()); + newComponent.setGroups(oldComponent.getGroups()); + newComponent.setInputs(null); + newComponent.setLastUpdateDate(null); + newComponent.setHighestVersion(true); + + Either componentVEither = titanDao.getVertexById(oldComponent.getUniqueId(), JsonParseFlagEnum.NoParse); + if (componentVEither.isRight()) { + log.debug("Falied to fetch component {} error {}", oldComponent.getUniqueId(), componentVEither.right().value()); + return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(componentVEither.right().value())); + } + GraphVertex componentv = componentVEither.left().value(); + Either parentVertexEither = titanDao.getParentVertex(componentv, EdgeLabelEnum.VERSION, JsonParseFlagEnum.NoParse); + if (parentVertexEither.isRight() && parentVertexEither.right().value() != TitanOperationStatus.NOT_FOUND) { + log.debug("Falied to fetch parent version for component {} error {}", oldComponent.getUniqueId(), parentVertexEither.right().value()); + return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(parentVertexEither.right().value())); + } + + Either deleteToscaComponent = deleteToscaElement(componentv); + if (deleteToscaComponent.isRight()) { + log.debug("Falied to remove old component {} error {}", oldComponent.getUniqueId(), deleteToscaComponent.right().value()); + return Either.right(deleteToscaComponent.right().value()); + } + Either createToscaComponent = createToscaComponent(newComponent); + if (createToscaComponent.isRight()) { + log.debug("Falied to create tosca element component {} error {}", newComponent.getUniqueId(), createToscaComponent.right().value()); + return Either.right(createToscaComponent.right().value()); + } + T newElement = createToscaComponent.left().value(); + Either newVersionEither = titanDao.getVertexById(newElement.getUniqueId(), JsonParseFlagEnum.NoParse); + if (newVersionEither.isRight()) { + log.debug("Falied to fetch new tosca element component {} error {}", newComponent.getUniqueId(), newVersionEither.right().value()); + return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(newVersionEither.right().value())); + } + if (parentVertexEither.isLeft()) { + GraphVertex previousVersionV = parentVertexEither.left().value(); + TitanOperationStatus createEdge = titanDao.createEdge(previousVersionV, newVersionEither.left().value(), EdgeLabelEnum.VERSION, null); + if (createEdge != TitanOperationStatus.OK) { + log.debug("Falied to associate to previous version {} new version {} error {}", previousVersionV.getUniqueId(), newVersionEither.right().value(), createEdge); + return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(createEdge)); + } + } + return Either.left(newElement); + } + + /** + * + * @param componentToUpdate + * @return + */ + public Either updateToscaElement(T componentToUpdate) { + return updateToscaElement(componentToUpdate, new ComponentParametersView()); + } + + /** + * + * @param componentToUpdate + * @param type + * @param filterResult + * @return + */ + public Either updateToscaElement(T componentToUpdate, ComponentParametersView filterResult) { + String componentId = componentToUpdate.getUniqueId(); + Either getVertexEither = titanDao.getVertexById(componentId, JsonParseFlagEnum.ParseAll); + if (getVertexEither.isRight()) { + log.debug("Couldn't fetch component with and unique id {}, error: {}", componentId, getVertexEither.right().value()); + return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(getVertexEither.right().value())); + } + GraphVertex elementV = getVertexEither.left().value(); + ToscaElementOperation toscaElementOperation = getToscaElementOperation(elementV); + + ToscaElement toscaElementToUpdate = ModelConverter.convertToToscaElement(componentToUpdate); + Either updateToscaElement = toscaElementOperation.updateToscaElement(toscaElementToUpdate, elementV, filterResult); + if (updateToscaElement.isRight()) { + log.debug("Failed to update tosca element {} error {}", componentId, updateToscaElement.right().value()); + return Either.right(updateToscaElement.right().value()); + } + return Either.left(ModelConverter.convertFromToscaElement(updateToscaElement.left().value())); + } + + private Either getLatestByName(GraphPropertyEnum property, String nodeName) { + Either result; + + Map propertiesToMatch = new EnumMap<>(GraphPropertyEnum.class); + Map propertiesNotToMatch = new EnumMap<>(GraphPropertyEnum.class); + + propertiesToMatch.put(property, nodeName); + propertiesToMatch.put(GraphPropertyEnum.IS_HIGHEST_VERSION, true); + + propertiesNotToMatch.put(GraphPropertyEnum.IS_DELETED, true); + + Either, TitanOperationStatus> highestResources = titanDao.getByCriteria(null, propertiesToMatch, propertiesNotToMatch, JsonParseFlagEnum.ParseMetadata); + if (highestResources.isRight()) { + TitanOperationStatus status = highestResources.right().value(); + log.debug("failed to find resource with name {}. status={} ", nodeName, status); + result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status)); + return result; + } + + List resources = highestResources.left().value(); + double version = 0.0; + GraphVertex highestResource = null; + for (GraphVertex vertex : resources) { + Object versionObj = vertex.getMetadataProperty(GraphPropertyEnum.VERSION); + double resourceVersion = Double.valueOf((String) versionObj); + if (resourceVersion > version) { + version = resourceVersion; + highestResource = vertex; + } + } + return getToscaElementByOperation(highestResource); + } + + public Either, StorageOperationStatus> getBySystemName(ComponentTypeEnum componentType, String systemName) { + + Either, StorageOperationStatus> result = null; + Either getComponentRes; + List components = new ArrayList<>(); + List componentVertices; + Map propertiesToMatch = new EnumMap<>(GraphPropertyEnum.class); + Map propertiesNotToMatch = new EnumMap<>(GraphPropertyEnum.class); + + propertiesToMatch.put(GraphPropertyEnum.SYSTEM_NAME, systemName); + if (componentType != null) + propertiesToMatch.put(GraphPropertyEnum.COMPONENT_TYPE, componentType.name()); + + propertiesNotToMatch.put(GraphPropertyEnum.IS_DELETED, true); + + Either, TitanOperationStatus> getComponentsRes = titanDao.getByCriteria(null, propertiesToMatch, propertiesNotToMatch, JsonParseFlagEnum.ParseAll); + if (getComponentsRes.isRight()) { + TitanOperationStatus status = getComponentsRes.right().value(); + log.debug("Failed to fetch the component with system name {}. Status is {} ", systemName, status); + result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status)); + } + if (result == null) { + componentVertices = getComponentsRes.left().value(); + for (GraphVertex componentVertex : componentVertices) { + getComponentRes = getToscaElementByOperation(componentVertex); + if (getComponentRes.isRight()) { + log.debug("Failed to get the component {}. Status is {} ", componentVertex.getJsonMetadataField(JsonPresentationFields.NAME), getComponentRes.right().value()); + result = Either.right(getComponentRes.right().value()); + break; + } + T componentBySystemName = getComponentRes.left().value(); + log.debug("Found component, id: {}", componentBySystemName.getUniqueId()); + components.add(componentBySystemName); + } + } + if (result == null) { + result = Either.left(components); + } + return result; + } + + public Either getComponentByNameAndVersion(ComponentTypeEnum componentType, String name, String version) { + return getComponentByNameAndVersion(componentType, name, version, JsonParseFlagEnum.ParseAll); + } + + public Either getComponentByNameAndVersion(ComponentTypeEnum componentType, String name, String version, JsonParseFlagEnum parseFlag) { + Either result; + + Map hasProperties = new EnumMap<>(GraphPropertyEnum.class); + Map hasNotProperties = new EnumMap<>(GraphPropertyEnum.class); + + hasProperties.put(GraphPropertyEnum.NAME, name); + hasProperties.put(GraphPropertyEnum.VERSION, version); + hasNotProperties.put(GraphPropertyEnum.IS_DELETED, true); + if (componentType != null) { + hasProperties.put(GraphPropertyEnum.COMPONENT_TYPE, componentType.name()); + } + Either, TitanOperationStatus> getResourceRes = titanDao.getByCriteria(null, hasProperties, hasNotProperties, parseFlag); + if (getResourceRes.isRight()) { + TitanOperationStatus status = getResourceRes.right().value(); + log.debug("failed to find resource with name {}, version {}. Status is {} ", name, version, status); + result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status)); + return result; + } + return getToscaElementByOperation(getResourceRes.left().value().get(0)); + } + + public Either, StorageOperationStatus> getCatalogComponents(ComponentTypeEnum componentType, List excludeTypes, boolean isHighestVersions) { + List components = new ArrayList<>(); + Either, StorageOperationStatus> catalogDataResult; + List toscaElements = new ArrayList<>(); + List excludedResourceTypes = + Optional.ofNullable(excludeTypes).orElse(Collections.emptyList()) + .stream() + .filter(type -> !type.equals(OriginTypeEnum.SERVICE)) + .map(type -> ResourceTypeEnum.getTypeByName(type.name())).collect(Collectors.toList()); + + switch (componentType) { + case RESOURCE: + catalogDataResult = nodeTypeOperation.getElementCatalogData(ComponentTypeEnum.RESOURCE,excludedResourceTypes , isHighestVersions); + if (catalogDataResult.isRight()) { + return Either.right(catalogDataResult.right().value()); + } + toscaElements = catalogDataResult.left().value(); + break; + case SERVICE: + if (excludeTypes!= null && excludeTypes.contains(OriginTypeEnum.SERVICE)) { + break; + } + catalogDataResult = topologyTemplateOperation.getElementCatalogData(ComponentTypeEnum.SERVICE, null, isHighestVersions); + if (catalogDataResult.isRight()) { + return Either.right(catalogDataResult.right().value()); + } + toscaElements = catalogDataResult.left().value(); + break; + default: + log.debug("Not supported component type {}", componentType); + return Either.right(StorageOperationStatus.BAD_REQUEST); + } + toscaElements.forEach(te -> { + T component = ModelConverter.convertFromToscaElement(te); + components.add(component); + }); + return Either.left(components); + } + + public Either, StorageOperationStatus> deleteMarkedElements(ComponentTypeEnum componentType) { + Either, StorageOperationStatus> allComponentsMarkedForDeletion; + List deleted = new ArrayList<>(); + switch (componentType) { + case RESOURCE: + allComponentsMarkedForDeletion = nodeTypeOperation.getAllComponentsMarkedForDeletion(componentType); + break; + case SERVICE: + case PRODUCT: + allComponentsMarkedForDeletion = topologyTemplateOperation.getAllComponentsMarkedForDeletion(componentType); + break; + default: + log.debug("Not supported component type {}", componentType); + return Either.right(StorageOperationStatus.BAD_REQUEST); + } + if (allComponentsMarkedForDeletion.isRight()) { + return Either.right(allComponentsMarkedForDeletion.right().value()); + } + List allMarked = allComponentsMarkedForDeletion.left().value(); + + Either, TitanOperationStatus> allNotDeletedElements = topologyTemplateOperation.getAllNotDeletedElements(); + if (allNotDeletedElements.isRight()) { + return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(allNotDeletedElements.right().value())); + } + List allNonMarked = allNotDeletedElements.left().value(); + for (GraphVertex elementV : allMarked) { + if (topologyTemplateOperation.isInUse(elementV, allNonMarked) == false) { + Either deleteToscaElement = deleteToscaElement(elementV); + if (deleteToscaElement.isRight()) { + log.debug("Failed to delete marked element {} error {}", elementV.getUniqueId(), deleteToscaElement.right().value()); + } + } else { + deleted.add(elementV.getUniqueId()); + log.debug("Marked element {} in use. don't delete it", elementV.getUniqueId()); + } + } + return Either.left(deleted); + } + + public Either, StorageOperationStatus> getAllComponentsMarkedForDeletion(ComponentTypeEnum componentType) { + Either, StorageOperationStatus> allComponentsMarkedForDeletion; + switch (componentType) { + case RESOURCE: + allComponentsMarkedForDeletion = nodeTypeOperation.getAllComponentsMarkedForDeletion(componentType); + break; + case SERVICE: + case PRODUCT: + allComponentsMarkedForDeletion = topologyTemplateOperation.getAllComponentsMarkedForDeletion(componentType); + break; + default: + log.debug("Not supported component type {}", componentType); + return Either.right(StorageOperationStatus.BAD_REQUEST); + } + if (allComponentsMarkedForDeletion.isRight()) { + return Either.right(allComponentsMarkedForDeletion.right().value()); + } + return Either.left(allComponentsMarkedForDeletion.left().value().stream().map(v -> v.getUniqueId()).collect(Collectors.toList())); + } + + public Either isComponentInUse(String componentId) { + Either result; + Either, TitanOperationStatus> allNotDeletedElements = topologyTemplateOperation.getAllNotDeletedElements(); + if (allNotDeletedElements.isRight()) { + result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(allNotDeletedElements.right().value())); + } else { + result = Either.left(topologyTemplateOperation.isInUse(componentId, allNotDeletedElements.left().value())); + } + return result; + } + + public Either, StorageOperationStatus> addComponentInstanceToTopologyTemplate(Component containerComponent, Component origComponent, ComponentInstance componentInstance, boolean allowDeleted, User user) { + + Either, StorageOperationStatus> result = null; + Either updateContainerComponentRes = null; + componentInstance.setIcon(origComponent.getIcon()); + Either, StorageOperationStatus> addResult = nodeTemplateOperation.addComponentInstanceToTopologyTemplate(ModelConverter.convertToToscaElement(containerComponent), + ModelConverter.convertToToscaElement(origComponent), getNextComponentInstanceCounter(containerComponent, origComponent.getName()), componentInstance, allowDeleted, user); + + if (addResult.isRight()) { + CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to add the component instance {} to container component {}. ", componentInstance.getName(), containerComponent.getName()); + result = Either.right(addResult.right().value()); + } + if (result == null) { + updateContainerComponentRes = topologyTemplateOperation.getToscaElement(containerComponent.getUniqueId()); + if (updateContainerComponentRes.isRight()) { + CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to fetch updated topology template {} with updated component instance {}. ", containerComponent.getName(), componentInstance.getName()); + result = Either.right(updateContainerComponentRes.right().value()); + } + } + if (result == null) { + Component updatedComponent = ModelConverter.convertFromToscaElement(updateContainerComponentRes.left().value()); + String createdInstanceId = addResult.left().value().getRight(); + CommonUtility.addRecordToLog(log, LogLevelEnum.TRACE, "The component instance {} has been added to container component {}. ", createdInstanceId, updatedComponent.getName()); + result = Either.left(new ImmutablePair<>(updatedComponent, createdInstanceId)); + } + return result; + } + + public StorageOperationStatus associateComponentInstancesToComponent(Component containerComponent, Map resourcesInstancesMap, boolean allowDeleted) { + + StorageOperationStatus result = null; + CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Going to add component instances to component {}", containerComponent.getUniqueId()); + + Either metadataVertex = titanDao.getVertexById(containerComponent.getUniqueId(), JsonParseFlagEnum.ParseAll); + if (metadataVertex.isRight()) { + TitanOperationStatus status = metadataVertex.right().value(); + if (status == TitanOperationStatus.NOT_FOUND) { + status = TitanOperationStatus.INVALID_ID; + } + result = DaoStatusConverter.convertTitanStatusToStorageStatus(status); + } + if (result == null) { + result = nodeTemplateOperation.associateComponentInstancesToComponent(containerComponent, resourcesInstancesMap, metadataVertex.left().value(), allowDeleted); + } + return result; + } + + public Either, StorageOperationStatus> updateComponentInstanceMetadataOfTopologyTemplate(Component containerComponent, Component origComponent, ComponentInstance componentInstance) { + + Either, StorageOperationStatus> result = null; + + CommonUtility.addRecordToLog(log, LogLevelEnum.TRACE, "Going to update the metadata of the component instance {} belonging to container component {}. ", componentInstance.getName(), containerComponent.getName()); + componentInstance.setIcon(origComponent.getIcon()); + Either, StorageOperationStatus> updateResult = nodeTemplateOperation.updateComponentInstanceMetadataOfTopologyTemplate(ModelConverter.convertToToscaElement(containerComponent), + ModelConverter.convertToToscaElement(origComponent), componentInstance); + if (updateResult.isRight()) { + CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to update the metadata of the component instance {} belonging to container component {}. ", componentInstance.getName(), containerComponent.getName()); + result = Either.right(updateResult.right().value()); + } + if (result == null) { + Component updatedComponent = ModelConverter.convertFromToscaElement(updateResult.left().value().getLeft()); + String createdInstanceId = updateResult.left().value().getRight(); + CommonUtility.addRecordToLog(log, LogLevelEnum.TRACE, "The metadata of the component instance {} has been updated to container component {}. ", createdInstanceId, updatedComponent.getName()); + result = Either.left(new ImmutablePair<>(updatedComponent, createdInstanceId)); + } + return result; + } + + public Either updateComponentInstanceMetadataOfTopologyTemplate(Component containerComponent) { + + Either result = null; + + CommonUtility.addRecordToLog(log, LogLevelEnum.TRACE, "Going to update the metadata belonging to container component {}. ", containerComponent.getName()); + + Either updateResult = nodeTemplateOperation.updateComponentInstanceMetadataOfTopologyTemplate(ModelConverter.convertToToscaElement(containerComponent)); + if (updateResult.isRight()) { + CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to update the metadata belonging to container component {}. ", containerComponent.getName()); + result = Either.right(updateResult.right().value()); + } + if (result == null) { + Component updatedComponent = ModelConverter.convertFromToscaElement(updateResult.left().value()); + CommonUtility.addRecordToLog(log, LogLevelEnum.TRACE, "The metadata has been updated to container component {}. ", updatedComponent.getName()); + result = Either.left(updatedComponent); + } + return result; + } + + public Either, StorageOperationStatus> deleteComponentInstanceFromTopologyTemplate(Component containerComponent, String resourceInstanceId) { + + Either, StorageOperationStatus> result = null; + + CommonUtility.addRecordToLog(log, LogLevelEnum.TRACE, "Going to delete the component instance {} belonging to container component {}. ", resourceInstanceId, containerComponent.getName()); + + Either, StorageOperationStatus> updateResult = nodeTemplateOperation.deleteComponentInstanceFromTopologyTemplate(ModelConverter.convertToToscaElement(containerComponent), resourceInstanceId); + if (updateResult.isRight()) { + CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to delete the component instance {} belonging to container component {}. ", resourceInstanceId, containerComponent.getName()); + result = Either.right(updateResult.right().value()); + } + if (result == null) { + Component updatedComponent = ModelConverter.convertFromToscaElement(updateResult.left().value().getLeft()); + String deletedInstanceId = updateResult.left().value().getRight(); + CommonUtility.addRecordToLog(log, LogLevelEnum.TRACE, "The component instance {} has been deleted from container component {}. ", deletedInstanceId, updatedComponent.getName()); + result = Either.left(new ImmutablePair<>(updatedComponent, deletedInstanceId)); + } + return result; + } + + private String getNextComponentInstanceCounter(Component containerComponent, String originResourceName) { + + Integer nextCounter = 0; + + if (CollectionUtils.isNotEmpty(containerComponent.getComponentInstances())) { + + String normalizedName = ValidationUtils.normalizeComponentInstanceName(originResourceName); + Integer maxCounterFromNames = getMaxCounterFromNames(containerComponent, normalizedName); + Integer maxCounterFromIds = getMaxCounterFromIds(containerComponent, normalizedName); + + if (maxCounterFromNames == null && maxCounterFromIds != null) { + nextCounter = maxCounterFromIds + 1; + } else if (maxCounterFromIds == null && maxCounterFromNames != null) { + nextCounter = maxCounterFromNames + 1; + } else if (maxCounterFromIds != null && maxCounterFromNames != null) { + nextCounter = maxCounterFromNames > maxCounterFromIds ? maxCounterFromNames + 1 : maxCounterFromIds + 1; + } + } + return nextCounter.toString(); + } + + private Integer getMaxCounterFromNames(Component containerComponent, String normalizedName) { + + Integer maxCounter = 0; + List countersStr = containerComponent.getComponentInstances().stream().filter(ci -> ci.getNormalizedName() != null && ci.getNormalizedName().startsWith(normalizedName)).map(ci -> ci.getNormalizedName().split(normalizedName)[1]) + .collect(Collectors.toList()); + + if (CollectionUtils.isEmpty(countersStr)) { + return null; + } + Integer currCounter = null; + for (String counter : countersStr) { + if (StringUtils.isEmpty(counter)) { + continue; + } + try { + currCounter = Integer.parseInt(counter); + } catch (Exception e) { + continue; + } + maxCounter = maxCounter < currCounter ? currCounter : maxCounter; + } + if (currCounter == null) { + return null; + } + return maxCounter; + } + + private Integer getMaxCounterFromIds(Component containerComponent, String normalizedName) { + + Integer maxCounter = 0; + List countersStr = containerComponent.getComponentInstances().stream().filter(ci -> ci.getUniqueId() != null && ci.getUniqueId().contains(normalizedName)).map(ci -> ci.getUniqueId().split(normalizedName)[1]) + .collect(Collectors.toList()); + + if (CollectionUtils.isEmpty(countersStr)) { + return null; + } + Integer currCounter = null; + for (String counter : countersStr) { + if (StringUtils.isEmpty(counter)) { + continue; + } + try { + currCounter = Integer.parseInt(counter); + } catch (Exception e) { + continue; + } + maxCounter = maxCounter < currCounter ? currCounter : maxCounter; + } + if (currCounter == null) { + return null; + } + return maxCounter; + } + + public Either associateResourceInstances(String componentId, RequirementCapabilityRelDef requirementDef) { + return nodeTemplateOperation.associateResourceInstances(componentId, requirementDef); + + } + + public Either, StorageOperationStatus> createAndAssociateInputs(Map inputs, String componentId) { + + Either getVertexEither = titanDao.getVertexById(componentId, JsonParseFlagEnum.NoParse); + if (getVertexEither.isRight()) { + log.debug("Couldn't fetch component with and unique id {}, error: {}", componentId, getVertexEither.right().value()); + return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(getVertexEither.right().value())); + + } + + GraphVertex vertex = getVertexEither.left().value(); + Map inputsMap = inputs.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> new PropertyDataDefinition(e.getValue()))); + + StorageOperationStatus status = topologyTemplateOperation.associateInputsToComponent(vertex, inputsMap, componentId); + + if (StorageOperationStatus.OK == status) { + log.debug("Component created successfully!!!"); + List inputsResList = null; + if (inputsMap != null && !inputsMap.isEmpty()) { + inputsResList = inputsMap.values().stream().map(i -> new InputDefinition(i)).collect(Collectors.toList()); + } + return Either.left(inputsResList); + } + return Either.right(status); + + } + + public Either, StorageOperationStatus> addInputsToComponent(Map inputs, String componentId) { + + Either getVertexEither = titanDao.getVertexById(componentId, JsonParseFlagEnum.NoParse); + if (getVertexEither.isRight()) { + log.debug("Couldn't fetch component with and unique id {}, error: {}", componentId, getVertexEither.right().value()); + return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(getVertexEither.right().value())); + + } + + GraphVertex vertex = getVertexEither.left().value(); + Map inputsMap = inputs.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> new PropertyDataDefinition(e.getValue()))); + + StorageOperationStatus status = topologyTemplateOperation.addToscaDataToToscaElement(vertex, EdgeLabelEnum.INPUTS, VertexTypeEnum.INPUTS, inputsMap, JsonPresentationFields.NAME); + + if (StorageOperationStatus.OK == status) { + log.debug("Component created successfully!!!"); + List inputsResList = null; + if (inputsMap != null && !inputsMap.isEmpty()) { + inputsResList = inputsMap.values().stream().map(i -> new InputDefinition(i)).collect(Collectors.toList()); + } + return Either.left(inputsResList); + } + return Either.right(status); + + } + + public Either>, StorageOperationStatus> associateComponentInstancePropertiesToComponent(Map> instProperties, String componentId) { + + Either getVertexEither = titanDao.getVertexById(componentId, JsonParseFlagEnum.NoParse); + if (getVertexEither.isRight()) { + log.debug("Couldn't fetch component with and unique id {}, error: {}", componentId, getVertexEither.right().value()); + return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(getVertexEither.right().value())); + + } + + GraphVertex vertex = getVertexEither.left().value(); + Map instPropsMap = new HashMap<>(); + if (instProperties != null) { - public Either getToscaElement(String componentId, ComponentParametersView filters) { + MapPropertiesDataDefinition propertiesMap; + for (Entry> entry : instProperties.entrySet()) { + propertiesMap = new MapPropertiesDataDefinition(); - Either getVertexEither = titanDao.getVertexById(componentId, filters.detectParseFlag()); - if (getVertexEither.isRight()) { - log.debug("Couldn't fetch component with and unique id {}, error: {}", componentId, getVertexEither.right().value()); - return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(getVertexEither.right().value())); + propertiesMap.setMapToscaDataDefinition(entry.getValue().stream().map(e -> new PropertyDataDefinition(e)).collect(Collectors.toMap(e -> e.getName(), e -> e))); + + instPropsMap.put(entry.getKey(), propertiesMap); + } + } + + StorageOperationStatus status = topologyTemplateOperation.associateInstPropertiesToComponent(vertex, instPropsMap); - } - return getToscaElementByOperation(getVertexEither.left().value(), filters); - } + if (StorageOperationStatus.OK == status) { + log.debug("Component created successfully!!!"); + return Either.left(instProperties); + } + return Either.right(status); - public Either getToscaElement(String componentId, JsonParseFlagEnum parseFlag) { + } + public Either>, StorageOperationStatus> associateComponentInstanceInputsToComponent(Map> instInputs, String componentId) { - Either getVertexEither = titanDao.getVertexById(componentId, parseFlag); + Either getVertexEither = titanDao.getVertexById(componentId, JsonParseFlagEnum.NoParse); if (getVertexEither.isRight()) { log.debug("Couldn't fetch component with and unique id {}, error: {}", componentId, getVertexEither.right().value()); return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(getVertexEither.right().value())); } - return getToscaElementByOperation(getVertexEither.left().value()); - } + GraphVertex vertex = getVertexEither.left().value(); + Map instPropsMap = new HashMap<>(); + if (instInputs != null) { - public Either getToscaElement(GraphVertex componentVertex) { - return getToscaElementByOperation(componentVertex); - } + MapPropertiesDataDefinition propertiesMap; + for (Entry> entry : instInputs.entrySet()) { + propertiesMap = new MapPropertiesDataDefinition(); - public Either validateComponentExists(String componentId) { + propertiesMap.setMapToscaDataDefinition(entry.getValue().stream().map(e -> new PropertyDataDefinition(e)).collect(Collectors.toMap(e -> e.getName(), e -> e))); - Either getVertexEither = titanDao.getVertexById(componentId, JsonParseFlagEnum.NoParse); - if (getVertexEither.isRight()) { - TitanOperationStatus status = getVertexEither.right().value(); - if (status == TitanOperationStatus.NOT_FOUND) { - return Either.left(false); - } else { - log.debug("Couldn't fetch component with and unique id {}, error: {}", componentId, getVertexEither.right().value()); - return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(getVertexEither.right().value())); + instPropsMap.put(entry.getKey(), propertiesMap); } } - return Either.left(true); - } - - public Either findLastCertifiedToscaElementByUUID(T component) { - Map props = new HashMap<>(); - props.put(GraphPropertyEnum.UUID, component.getUUID()); - props.put(GraphPropertyEnum.STATE, LifecycleStateEnum.CERTIFIED.name()); - props.put(GraphPropertyEnum.IS_HIGHEST_VERSION, true); - - Either, TitanOperationStatus> getVertexEither = titanDao.getByCriteria(ModelConverter.getVertexType(component), props); - if (getVertexEither.isRight()) { - log.debug("Couldn't fetch component with and unique id {}, error: {}", component.getUniqueId(), getVertexEither.right().value()); - return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(getVertexEither.right().value())); - - } - return getToscaElementByOperation(getVertexEither.left().value().get(0)); - } - - private Either getToscaElementByOperation(GraphVertex componentV) { - return getToscaElementByOperation(componentV, new ComponentParametersView()); - } - - private Either getToscaElementByOperation(GraphVertex componentV, ComponentParametersView filters) { - VertexTypeEnum label = componentV.getLabel(); - - ToscaElementOperation toscaOperation = getToscaElementOperation(componentV); - Either toscaElement; - String componentId = componentV.getUniqueId(); - if (toscaOperation != null) { - log.debug("Need to fetch tosca element for id {}", componentId); - toscaElement = toscaOperation.getToscaElement(componentV, filters); - } else { - log.debug("not supported tosca type {} for id {}", label, componentId); - toscaElement = Either.right(StorageOperationStatus.BAD_REQUEST); - } - if (toscaElement.isRight()) { - return Either.right(toscaElement.right().value()); - } - return Either.left(ModelConverter.convertFromToscaElement(toscaElement.left().value())); - } - private ToscaElementOperation getToscaElementOperation(GraphVertex componentV) { - VertexTypeEnum label = componentV.getLabel(); - switch (label) { - case NODE_TYPE: - return nodeTypeOperation; - case TOPOLOGY_TEMPLATE: - return topologyTemplateOperation; - default: - return null; - } - } + StorageOperationStatus status = topologyTemplateOperation.associateInstInputsToComponent(vertex, instPropsMap); - /** - * - * @param resource - * @return - */ - public Either createToscaComponent(T resource) { - ToscaElement toscaElement = ModelConverter.convertToToscaElement(resource); - - ToscaElementOperation toscaElementOperation = getToscaElementOperation(toscaElement); - Either createToscaElement = toscaElementOperation.createToscaElement(toscaElement); - if (createToscaElement.isLeft()) { + if (StorageOperationStatus.OK == status) { log.debug("Component created successfully!!!"); - T dataModel = ModelConverter.convertFromToscaElement(createToscaElement.left().value()); - return Either.left(dataModel); - } - return Either.right(createToscaElement.right().value()); - } - - /** - * - * @param componentToDelete - * @return - */ - public StorageOperationStatus markComponentToDelete(Component componentToDelete) { - - if ((componentToDelete.getIsDeleted() != null) && componentToDelete.getIsDeleted() && !componentToDelete.isHighestVersion()) { - // component already marked for delete - return StorageOperationStatus.OK; - } else { - - Either getResponse = titanDao.getVertexById(componentToDelete.getUniqueId(), JsonParseFlagEnum.ParseAll); - if (getResponse.isRight()) { - log.debug("Couldn't fetch component with and unique id {}, error: {}", componentToDelete.getUniqueId(), getResponse.right().value()); - return DaoStatusConverter.convertTitanStatusToStorageStatus(getResponse.right().value()); - - } - GraphVertex componentV = getResponse.left().value(); - - // same operation for node type and topology template operations - Either result = nodeTypeOperation.markComponentToDelete(componentV); - if (result.isRight()) { - return result.right().value(); - } - return StorageOperationStatus.OK; - } - } - - /** - * - * @param componentId - * @return - */ - public Either deleteToscaComponent(String componentId) { - - Either getVertexEither = titanDao.getVertexById(componentId, JsonParseFlagEnum.ParseAll); - if (getVertexEither.isRight()) { - log.debug("Couldn't fetch component vertex with and unique id {}, error: {}", componentId, getVertexEither.right().value()); - return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(getVertexEither.right().value())); - - } - Either deleteElement = deleteToscaElement(getVertexEither.left().value()); - if (deleteElement.isRight()) { - log.debug("Failed to delete component with and unique id {}, error: {}", componentId, deleteElement.right().value()); - return Either.right(deleteElement.right().value()); + return Either.left(instInputs); } - T dataModel = ModelConverter.convertFromToscaElement(deleteElement.left().value()); - - return Either.left(dataModel); - } - - private Either deleteToscaElement(GraphVertex componentV) { - VertexTypeEnum label = componentV.getLabel(); - Either toscaElement; - Object componentId = componentV.getUniqueId(); - switch (label) { - case NODE_TYPE: - log.debug("Need to fetch node type for id {}", componentId); - toscaElement = nodeTypeOperation.deleteToscaElement(componentV); - break; - case TOPOLOGY_TEMPLATE: - log.debug("Need to fetch topology template for id {}", componentId); - toscaElement = topologyTemplateOperation.deleteToscaElement(componentV); - break; - default: - log.debug("not supported tosca type {} for id {}", label, componentId); - toscaElement = Either.right(StorageOperationStatus.BAD_REQUEST); - break; - } - return toscaElement; - } - - private ToscaElementOperation getToscaElementOperation(ToscaElement toscaElement) { - - ComponentTypeEnum componentType = toscaElement.getComponentType(); - switch (componentType) { - case RESOURCE: - ResourceTypeEnum resourceType = toscaElement.getResourceType(); - if (resourceType == ResourceTypeEnum.VF) { - return topologyTemplateOperation; - } else { - return nodeTypeOperation; - } - case SERVICE: - case PRODUCT: - return topologyTemplateOperation; - default: - break; - } - return null; - } - - private ToscaElementOperation getToscaElementOperation(Component component) { - - switch (component.getComponentType()) { - case RESOURCE: - ResourceTypeEnum resourceType = ((Resource) component).getResourceType(); - if (resourceType != null && resourceType == ResourceTypeEnum.VF) { - return topologyTemplateOperation; - } else { - return nodeTypeOperation; - } - case SERVICE: - case PRODUCT: - return topologyTemplateOperation; - default: - break; - } - return null; - } - - public Either getLatestByToscaResourceName(String toscaResourceName) { - return getLatestByName(GraphPropertyEnum.TOSCA_RESOURCE_NAME, toscaResourceName); - - } - - public Either getLatestByName(String resourceName) { - return getLatestByName(GraphPropertyEnum.NAME, resourceName); + return Either.right(status); } + public Either>, StorageOperationStatus> addComponentInstanceInputsToComponent(Component containerComponent, Map> instProperties) { + + StorageOperationStatus status = StorageOperationStatus.OK; + if (instProperties != null) { + + for (Entry> entry : instProperties.entrySet()) { + List props = entry.getValue(); + String componentInstanseId = entry.getKey(); + if (props != null && !props.isEmpty()) { + for (ComponentInstanceInput property : props) { + List componentInstancesInputs = containerComponent.getComponentInstancesInputs().get(componentInstanseId); + Optional instanceProperty = componentInstancesInputs.stream().filter(p -> p.getName().equals(property.getName())).findAny(); + if (instanceProperty.isPresent()) { + status = updateComponentInstanceInput(containerComponent, componentInstanseId, property); + } else { + status = addComponentInstanceInput(containerComponent, componentInstanseId, property); + } + if (status != StorageOperationStatus.OK) { + log.debug("Failed to update instance input {} for instance {} error {} ", property, componentInstanseId, status); + return Either.right(status); + } else { + log.trace("instance input {} for instance {} updated", property, componentInstanseId); + } + } + } + } + } + return Either.left(instProperties); + } + + public StorageOperationStatus deleteComponentInstanceInputsToComponent(Map> instProperties, String componentId) { - public Either validateCsarUuidUniqueness(String csarUUID) { - Either, StorageOperationStatus> byCsar = null; - - Map properties = new HashMap(); - properties.put(GraphPropertyEnum.CSAR_UUID, csarUUID); - - Either, TitanOperationStatus> resources = titanDao.getByCriteria(null, properties, JsonParseFlagEnum.ParseMetadata); - - if (resources.isRight()) { - if (resources.right().value() == TitanOperationStatus.NOT_FOUND) { - return Either.left(new Integer(0)); - } else { - log.debug("failed to get resources from graph with property name: {}", csarUUID); - return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(resources.right().value())); - } - } + Either getVertexEither = titanDao.getVertexById(componentId, JsonParseFlagEnum.NoParse); + if (getVertexEither.isRight()) { + log.debug("Couldn't fetch component with and unique id {}, error: {}", componentId, getVertexEither.right().value()); + return DaoStatusConverter.convertTitanStatusToStorageStatus(getVertexEither.right().value()); - List resourceList = (resources.isLeft() ? resources.left().value() : null); + } - return Either.left(new Integer(resourceList.size())); + GraphVertex vertex = getVertexEither.left().value(); + Map instPropsMap = new HashMap<>(); + if (instProperties != null) { - } + MapPropertiesDataDefinition propertiesMap; + for (Entry> entry : instProperties.entrySet()) { + propertiesMap = new MapPropertiesDataDefinition(); - public Either, StorageOperationStatus> getFollowed(String userId, Set lifecycleStates, Set lastStateStates, ComponentTypeEnum componentType) { - Either, StorageOperationStatus> followedResources; - if (componentType == ComponentTypeEnum.RESOURCE) { - followedResources = nodeTypeOperation.getFollowedComponent(userId, lifecycleStates, lastStateStates, componentType); - } else { - followedResources = topologyTemplateOperation.getFollowedComponent(userId, lifecycleStates, lastStateStates, componentType); - } + propertiesMap.setMapToscaDataDefinition(entry.getValue().stream().map(e -> new PropertyDataDefinition(e)).collect(Collectors.toMap(e -> e.getName(), e -> e))); - Set components = new HashSet<>(); - if (followedResources.isRight() && followedResources.right().value() != StorageOperationStatus.NOT_FOUND) { - return Either.right(followedResources.right().value()); - } - if (followedResources.isLeft()) { - List toscaElements = followedResources.left().value(); - toscaElements.forEach(te -> { - T component = ModelConverter.convertFromToscaElement(te); - components.add(component); - }); - } - return Either.left(components); - } + instPropsMap.put(entry.getKey(), propertiesMap); + } + } - public Either getLatestCertifiedNodeTypeByToscaResourceName(String toscaResourceName) { + return topologyTemplateOperation.deleteInstInputsToComponent(vertex, instPropsMap); - return getLatestCertifiedByToscaResourceName(toscaResourceName, VertexTypeEnum.NODE_TYPE, JsonParseFlagEnum.ParseMetadata); - } + } - public Either getLatestCertifiedByToscaResourceName(String toscaResourceName, VertexTypeEnum vertexType, JsonParseFlagEnum parseFlag) { + public Either>, StorageOperationStatus> addComponentInstancePropertiesToComponent(Component containerComponent, Map> instProperties, String componentId) { - Either result = null; - Map props = new HashMap(); - props.put(GraphPropertyEnum.TOSCA_RESOURCE_NAME, toscaResourceName); - props.put(GraphPropertyEnum.IS_HIGHEST_VERSION, true); - props.put(GraphPropertyEnum.STATE, LifecycleStateEnum.CERTIFIED.name()); - Either, TitanOperationStatus> getLatestRes = titanDao.getByCriteria(vertexType, props, parseFlag); + StorageOperationStatus status = StorageOperationStatus.OK; + if (instProperties != null) { - if (getLatestRes.isRight()) { - TitanOperationStatus status = getLatestRes.right().value(); - CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to fetch {} with name {}. status={} ", vertexType, toscaResourceName, status); - result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status)); - } - if (result == null) { - List resources = getLatestRes.left().value(); - double version = 0.0; - GraphVertex highestResource = null; - for (GraphVertex resource : resources) { - double resourceVersion = Double.parseDouble((String) resource.getJsonMetadataField(JsonPresentationFields.VERSION)); - if (resourceVersion > version) { - version = resourceVersion; - highestResource = resource; - } - } - result = getToscaElement(highestResource.getUniqueId()); - } - return result; - } + for (Entry> entry : instProperties.entrySet()) { + List props = entry.getValue(); + String componentInstanseId = entry.getKey(); + List instanceProperties = containerComponent.getComponentInstancesProperties().get(componentInstanseId); + if (props != null && !props.isEmpty()) { + for (ComponentInstanceProperty property : props) { + Optional instanceProperty = instanceProperties.stream().filter(p -> p.getUniqueId().equals(property.getUniqueId())).findAny(); + if (instanceProperty.isPresent()) { + status = updateComponentInstanceProperty(containerComponent, componentInstanseId, property); + } else { + status = addComponentInstanceProperty(containerComponent, componentInstanseId, property); + } - public Either validateToscaResourceNameExists(String templateName) { - Either validateUniquenessRes = validateToscaResourceNameUniqueness(templateName); - if (validateUniquenessRes.isLeft()) { - return Either.left(!validateUniquenessRes.left().value()); - } - return validateUniquenessRes; - } + } + } + } + } - public Either dissociateResourceInstances(String componentId, RequirementCapabilityRelDef requirementDef) { - return nodeTemplateOperation.dissociateResourceInstances(componentId, requirementDef); + return Either.left(instProperties); - } + } - public StorageOperationStatus associateResourceInstances(String componentId, List relations) { - Either, StorageOperationStatus> status = nodeTemplateOperation.associateResourceInstances(componentId, relations); - if (status.isRight()) { - return status.right().value(); - } - return StorageOperationStatus.OK; - } + public StorageOperationStatus associateArtifactToInstances(Map> instArtifacts, String componentId, User user) { - protected Either validateToscaResourceNameUniqueness(String name) { + Either getVertexEither = titanDao.getVertexById(componentId, JsonParseFlagEnum.NoParse); + if (getVertexEither.isRight()) { + log.debug("Couldn't fetch component with and unique id {}, error: {}", componentId, getVertexEither.right().value()); + return DaoStatusConverter.convertTitanStatusToStorageStatus(getVertexEither.right().value()); - Map properties = new HashMap(); - properties.put(GraphPropertyEnum.TOSCA_RESOURCE_NAME, name); + } - Either, TitanOperationStatus> resources = titanDao.getByCriteria(null, properties, JsonParseFlagEnum.ParseMetadata); + GraphVertex vertex = getVertexEither.left().value(); + Map instArtMap = new HashMap<>(); + if (instArtifacts != null) { - if (resources.isRight() && resources.right().value() != TitanOperationStatus.NOT_FOUND) { - log.debug("failed to get resources from graph with property name: {}", name); - return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(resources.right().value())); - } - List resourceList = (resources.isLeft() ? resources.left().value() : null); - if (resourceList != null && resourceList.size() > 0) { - if (log.isDebugEnabled()) { - StringBuilder builder = new StringBuilder(); - for (GraphVertex resourceData : resourceList) { - builder.append(resourceData.getUniqueId() + "|"); - } - log.debug("resources with property name:{} exists in graph. found {}", name, builder.toString()); - } - return Either.left(false); - } else { - log.debug("resources with property name:{} does not exists in graph", name); - return Either.left(true); - } + MapArtifactDataDefinition artifactsMap; + for (Entry> entry : instArtifacts.entrySet()) { + Map artList = entry.getValue(); + Map artifacts = artList.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> new ArtifactDataDefinition(e.getValue()))); + artifactsMap = nodeTemplateOperation.prepareInstDeploymentArtifactPerInstance(artifacts, entry.getKey(), user, NodeTemplateOperation.HEAT_VF_ENV_NAME); - } + instArtMap.put(entry.getKey(), artifactsMap); + } + } + + return topologyTemplateOperation.associateInstArtifactToComponent(vertex, instArtMap); + + } + + public StorageOperationStatus associateInstAttributeToComponentToInstances(Map> instArttributes, String componentId) { + + Either getVertexEither = titanDao.getVertexById(componentId, JsonParseFlagEnum.NoParse); + if (getVertexEither.isRight()) { + log.debug("Couldn't fetch component with and unique id {}, error: {}", componentId, getVertexEither.right().value()); + return DaoStatusConverter.convertTitanStatusToStorageStatus(getVertexEither.right().value()); - /** - * - * @param newComponent - * @param oldComponent - * @return - */ - public Either overrideComponent(T newComponent, T oldComponent) { - - // TODO - // newComponent.setInterfaces(oldComponent.getInterfaces); - newComponent.setArtifacts(oldComponent.getArtifacts()); - newComponent.setDeploymentArtifacts(oldComponent.getDeploymentArtifacts()); - newComponent.setGroups(oldComponent.getGroups()); - newComponent.setInputs(null); - newComponent.setLastUpdateDate(null); - newComponent.setHighestVersion(true); - - Either componentVEither = titanDao.getVertexById(oldComponent.getUniqueId(), JsonParseFlagEnum.NoParse); - if (componentVEither.isRight()) { - log.debug("Falied to fetch component {} error {}", oldComponent.getUniqueId(), componentVEither.right().value()); - return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(componentVEither.right().value())); - } - GraphVertex componentv = componentVEither.left().value(); - Either parentVertexEither = titanDao.getParentVertex(componentv, EdgeLabelEnum.VERSION, JsonParseFlagEnum.NoParse); - if (parentVertexEither.isRight() && parentVertexEither.right().value() != TitanOperationStatus.NOT_FOUND) { - log.debug("Falied to fetch parent version for component {} error {}", oldComponent.getUniqueId(), parentVertexEither.right().value()); - return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(parentVertexEither.right().value())); - } + } - Either deleteToscaComponent = deleteToscaElement(componentv); - if (deleteToscaComponent.isRight()) { - log.debug("Falied to remove old component {} error {}", oldComponent.getUniqueId(), deleteToscaComponent.right().value()); - return Either.right(deleteToscaComponent.right().value()); - } - Either createToscaComponent = createToscaComponent(newComponent); - if (createToscaComponent.isRight()) { - log.debug("Falied to create tosca element component {} error {}", newComponent.getUniqueId(), createToscaComponent.right().value()); - return Either.right(createToscaComponent.right().value()); - } - T newElement = createToscaComponent.left().value(); - Either newVersionEither = titanDao.getVertexById(newElement.getUniqueId(), JsonParseFlagEnum.NoParse); - if (newVersionEither.isRight()) { - log.debug("Falied to fetch new tosca element component {} error {}", newComponent.getUniqueId(), newVersionEither.right().value()); - return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(newVersionEither.right().value())); - } - if (parentVertexEither.isLeft()) { - GraphVertex previousVersionV = parentVertexEither.left().value(); - TitanOperationStatus createEdge = titanDao.createEdge(previousVersionV, newVersionEither.left().value(), EdgeLabelEnum.VERSION, null); - if (createEdge != TitanOperationStatus.OK) { - log.debug("Falied to associate to previous version {} new version {} error {}", previousVersionV.getUniqueId(), newVersionEither.right().value(), createEdge); - return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(createEdge)); - } - } - return Either.left(newElement); - } + GraphVertex vertex = getVertexEither.left().value(); + Map instAttr = new HashMap<>(); + if (instArttributes != null) { - /** - * - * @param componentToUpdate - * @return - */ - public Either updateToscaElement(T componentToUpdate) { - return updateToscaElement(componentToUpdate, new ComponentParametersView()); - } + MapPropertiesDataDefinition attributesMap; + for (Entry> entry : instArttributes.entrySet()) { + attributesMap = new MapPropertiesDataDefinition(); + attributesMap.setMapToscaDataDefinition(entry.getValue().stream().map(e -> new PropertyDataDefinition(e)).collect(Collectors.toMap(e -> e.getName(), e -> e))); + instAttr.put(entry.getKey(), attributesMap); + } + } - /** - * - * @param componentToUpdate - * @param type - * @param filterResult - * @return - */ - public Either updateToscaElement(T componentToUpdate, ComponentParametersView filterResult) { - String componentId = componentToUpdate.getUniqueId(); - Either getVertexEither = titanDao.getVertexById(componentId, JsonParseFlagEnum.ParseAll); - if (getVertexEither.isRight()) { - log.debug("Couldn't fetch component with and unique id {}, error: {}", componentId, getVertexEither.right().value()); - return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(getVertexEither.right().value())); - } - GraphVertex elementV = getVertexEither.left().value(); - ToscaElementOperation toscaElementOperation = getToscaElementOperation(elementV); - - ToscaElement toscaElementToUpdate = ModelConverter.convertToToscaElement(componentToUpdate); - Either updateToscaElement = toscaElementOperation.updateToscaElement(toscaElementToUpdate, elementV, filterResult); - if (updateToscaElement.isRight()) { - log.debug("Failed to update tosca element {} error {}", componentId, updateToscaElement.right().value()); - return Either.right(updateToscaElement.right().value()); - } - return Either.left(ModelConverter.convertFromToscaElement(updateToscaElement.left().value())); - } + return topologyTemplateOperation.associateInstAttributeToComponent(vertex, instAttr); - private Either getLatestByName(GraphPropertyEnum property, String nodeName) { - Either result; + } - Map propertiesToMatch = new EnumMap<>(GraphPropertyEnum.class); - Map propertiesNotToMatch = new EnumMap<>(GraphPropertyEnum.class); + public StorageOperationStatus associateCalculatedCapReq(Map>> instCapabilties, Map>> instReg, String componentId) { + Either getVertexEither = titanDao.getVertexById(componentId, JsonParseFlagEnum.NoParse); + if (getVertexEither.isRight()) { + log.debug("Couldn't fetch component with and unique id {}, error: {}", componentId, getVertexEither.right().value()); + return DaoStatusConverter.convertTitanStatusToStorageStatus(getVertexEither.right().value()); - propertiesToMatch.put(property, nodeName); - propertiesToMatch.put(GraphPropertyEnum.IS_HIGHEST_VERSION, true); + } - propertiesNotToMatch.put(GraphPropertyEnum.IS_DELETED, true); + GraphVertex vertex = getVertexEither.left().value(); - Either, TitanOperationStatus> highestResources = titanDao.getByCriteria(null, propertiesToMatch, propertiesNotToMatch, JsonParseFlagEnum.ParseMetadata); - if (highestResources.isRight()) { - TitanOperationStatus status = highestResources.right().value(); - log.debug("failed to find resource with name {}. status={} ", nodeName, status); - result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status)); - return result; - } + Map calcRequirements = new HashMap<>(); - List resources = highestResources.left().value(); - double version = 0.0; - GraphVertex highestResource = null; - for (GraphVertex vertex : resources) { - Object versionObj = vertex.getMetadataProperty(GraphPropertyEnum.VERSION); - double resourceVersion = Double.valueOf((String) versionObj); - if (resourceVersion > version) { - version = resourceVersion; - highestResource = vertex; - } - } - return getToscaElementByOperation(highestResource); - } + Map calcCapabilty = new HashMap<>(); + Map calculatedCapabilitiesProperties = new HashMap<>(); + ; + if (instCapabilties != null) { + for (Entry>> entry : instCapabilties.entrySet()) { - public Either, StorageOperationStatus> getBySystemName(ComponentTypeEnum componentType, String systemName) { + Map> caps = entry.getValue(); + Map mapToscaDataDefinition = new HashMap<>(); + for (Entry> instCapability : caps.entrySet()) { + mapToscaDataDefinition.put(instCapability.getKey(), new ListCapabilityDataDefinition(instCapability.getValue().stream().map(iCap -> new CapabilityDataDefinition(iCap)).collect(Collectors.toList()))); + } + + ComponentInstanceDataDefinition componentInstance = new ComponentInstanceDataDefinition(entry.getKey()); + MapListCapabiltyDataDefinition capMap = nodeTemplateOperation.prepareCalculatedCapabiltyForNodeType(mapToscaDataDefinition, componentInstance); + + MapCapabiltyProperty mapCapabiltyProperty = ModelConverter.convertToMapOfMapCapabiltyProperties(caps, componentInstance.getUniqueId(), true); + + calcCapabilty.put(entry.getKey().getUniqueId(), capMap); + calculatedCapabilitiesProperties.put(entry.getKey().getUniqueId(), mapCapabiltyProperty); + } + } + + if (instReg != null) { + for (Entry>> entry : instReg.entrySet()) { + + Map> req = entry.getValue(); + Map mapToscaDataDefinition = new HashMap<>(); + for (Entry> instReq : req.entrySet()) { + mapToscaDataDefinition.put(instReq.getKey(), new ListRequirementDataDefinition(instReq.getValue().stream().map(iCap -> new RequirementDataDefinition(iCap)).collect(Collectors.toList()))); + } + + MapListRequirementDataDefinition capMap = nodeTemplateOperation.prepareCalculatedRequirementForNodeType(mapToscaDataDefinition, new ComponentInstanceDataDefinition(entry.getKey())); + + calcRequirements.put(entry.getKey().getUniqueId(), capMap); + } + } + + StorageOperationStatus status = topologyTemplateOperation.associateCalcCapReqToComponent(vertex, calcRequirements, calcCapabilty, calculatedCapabilitiesProperties); + + return status; + } + + private Either, StorageOperationStatus> getLatestVersionNotAbstractToscaElementsMetadataOnly(boolean isAbstract, Boolean isHighest, ComponentTypeEnum componentTypeEnum, String internalComponentType, VertexTypeEnum vertexType) { + + Map hasProps = new EnumMap<>(GraphPropertyEnum.class); + Map hasNotProps = new EnumMap<>(GraphPropertyEnum.class); + + fillPropsMap(hasProps, hasNotProps, internalComponentType, componentTypeEnum, isAbstract, vertexType); + + Either, TitanOperationStatus> getRes = titanDao.getByCriteria(vertexType, hasProps, hasNotProps, JsonParseFlagEnum.ParseMetadata); + if (getRes.isRight()) { + if (getRes.right().value().equals(TitanOperationStatus.NOT_FOUND)) { + return Either.left(new ArrayList<>()); + } else { + return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(getRes.right().value())); + } + } else { + List nonAbstractLatestComponents = new ArrayList<>(); + ComponentParametersView params = new ComponentParametersView(true); + params.setIgnoreAllVersions(false); + for (GraphVertex vertexComponent : getRes.left().value()) { + Either componentRes = topologyTemplateOperation.getLightComponent(vertexComponent, componentTypeEnum, params); + if (componentRes.isRight()) { + log.debug("Failed to fetch ligth element for {} error {}", vertexComponent.getUniqueId(), componentRes.right().value()); + return Either.right(componentRes.right().value()); + } else { + Component component = ModelConverter.convertFromToscaElement(componentRes.left().value()); + + nonAbstractLatestComponents.add(component); + } + } + + return Either.left(nonAbstractLatestComponents); + } + } + + public Either getLatestComponentMetadataByUuid(String componentUuid, JsonParseFlagEnum parseFlag, Boolean isHighest) { + + Either result; + + Map hasProperties = new EnumMap<>(GraphPropertyEnum.class); + + hasProperties.put(GraphPropertyEnum.UUID, componentUuid); + if (isHighest != null) { + hasProperties.put(GraphPropertyEnum.IS_HIGHEST_VERSION, isHighest.booleanValue()); + } + + Map propertiesNotToMatch = new EnumMap<>(GraphPropertyEnum.class); + propertiesNotToMatch.put(GraphPropertyEnum.IS_DELETED, true); + + Either, TitanOperationStatus> getRes = titanDao.getByCriteria(null, hasProperties, propertiesNotToMatch, parseFlag); + if (getRes.isRight()) { + result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(getRes.right().value())); + } else { + List latestVersionList = getRes.left().value().stream().map(ModelConverter::convertToComponentMetadata).collect(Collectors.toList()); + ComponentMetadataData latestVersion = latestVersionList.size() == 1 ? latestVersionList.get(0) + : latestVersionList.stream().max((c1, c2) -> Double.compare(Double.parseDouble(c1.getMetadataDataDefinition().getVersion()), Double.parseDouble(c2.getMetadataDataDefinition().getVersion()))).get(); + result = Either.left(latestVersion); + } + return result; + } + + public Either getComponentMetadata(String componentId) { + + Either result; + Either getRes = titanDao.getVertexById(componentId, JsonParseFlagEnum.ParseMetadata); + if (getRes.isRight()) { + result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(getRes.right().value())); + } else { + ComponentMetadataData componentMetadata = ModelConverter.convertToComponentMetadata(getRes.left().value()); + result = Either.left(componentMetadata); + } + return result; + } + + private Map findLatestVersion(List resourceDataList) { + Map, ComponentMetadataData> latestVersionMap = new HashMap, ComponentMetadataData>(); + for (ComponentMetadataData resourceData : resourceDataList) { + ComponentMetadataData latestVersionData = resourceData; + + ComponentMetadataDataDefinition metadataDataDefinition = resourceData.getMetadataDataDefinition(); + Pair pair = createKeyPair(latestVersionData); + if (latestVersionMap.containsKey(pair)) { + latestVersionData = latestVersionMap.get(pair); + String currentVersion = latestVersionData.getMetadataDataDefinition().getVersion(); + String newVersion = metadataDataDefinition.getVersion(); + if (CommonBeUtils.compareAsdcComponentVersions(newVersion, currentVersion)) { + latestVersionData = resourceData; + } + } + if (log.isDebugEnabled()) + log.debug("last certified version of resource = {} version is {}", latestVersionData.getMetadataDataDefinition().getName(), latestVersionData.getMetadataDataDefinition().getVersion()); + + latestVersionMap.put(pair, latestVersionData); + } + + Map resVersionMap = new HashMap(); + for (ComponentMetadataData resourceData : latestVersionMap.values()) { + ComponentMetadataData latestVersionData = resourceData; + ComponentMetadataDataDefinition metadataDataDefinition = resourceData.getMetadataDataDefinition(); + if (resVersionMap.containsKey(metadataDataDefinition.getUUID())) { + latestVersionData = resVersionMap.get(metadataDataDefinition.getUUID()); + String currentVersion = latestVersionData.getMetadataDataDefinition().getVersion(); + String newVersion = metadataDataDefinition.getVersion(); + if (CommonBeUtils.compareAsdcComponentVersions(newVersion, currentVersion)) { + latestVersionData = resourceData; + } + } + if (log.isDebugEnabled()) + log.debug("last uuid version of resource = {} version is {}", latestVersionData.getMetadataDataDefinition().getName(), latestVersionData.getMetadataDataDefinition().getVersion()); + resVersionMap.put(latestVersionData.getMetadataDataDefinition().getUUID(), latestVersionData); + } + + return resVersionMap; + } + + private Pair createKeyPair(ComponentMetadataData metadataData) { + Pair pair; + NodeTypeEnum label = NodeTypeEnum.getByName(metadataData.getLabel()); + switch (label) { + case Resource: + pair = new ImmutablePair<>(metadataData.getMetadataDataDefinition().getName(), ((ResourceMetadataDataDefinition) metadataData.getMetadataDataDefinition()).getResourceType().name()); + break; + default: + pair = new ImmutablePair<>(metadataData.getMetadataDataDefinition().getName(), metadataData.getLabel()); + break; + } + + return pair; + } + + public Either, StorageOperationStatus> getLatestVersionNotAbstractComponents(boolean isAbstract, Boolean isHighest, ComponentTypeEnum componentTypeEnum, String internalComponentType, List componentUids) { + + Either, StorageOperationStatus> result = null; + List components = new ArrayList<>(); + if (componentUids == null) { + Either, StorageOperationStatus> componentUidsRes = getComponentUids(isAbstract, isHighest, componentTypeEnum, internalComponentType, componentUids); + if (componentUidsRes.isRight()) { + result = Either.right(componentUidsRes.right().value()); + } else { + componentUids = componentUidsRes.left().value(); + } + } + if (!componentUids.isEmpty()) { + for (String componentUid : componentUids) { + ComponentParametersView componentParametersView = buildComponentViewForNotAbstract(); + if (internalComponentType != null && "vl".equalsIgnoreCase(internalComponentType)) { + componentParametersView.setIgnoreCapabilities(false); + componentParametersView.setIgnoreRequirements(false); + } + Either getToscaElementRes = nodeTemplateOperation.getToscaElementOperation(componentTypeEnum).getLightComponent(componentUid, componentTypeEnum, componentParametersView); + if (getToscaElementRes.isRight()) { + if (log.isDebugEnabled()) + log.debug("Failed to fetch resource for error is {}", getToscaElementRes.right().value()); + result = Either.right(getToscaElementRes.right().value()); + break; + } + Component component = ModelConverter.convertFromToscaElement(getToscaElementRes.left().value()); + component.setContactId(null); + component.setCreationDate(null); + component.setCreatorUserId(null); + component.setCreatorFullName(null); + component.setLastUpdateDate(null); + component.setLastUpdaterUserId(null); + component.setLastUpdaterFullName(null); + component.setNormalizedName(null); + components.add(component); + } + } + if (result == null) { + result = Either.left(components); + } + return result; + } + + private Either, StorageOperationStatus> getComponentUids(boolean isAbstract, Boolean isHighest, ComponentTypeEnum componentTypeEnum, String internalComponentType, List componentUids) { + + Either, StorageOperationStatus> result = null; + Either, StorageOperationStatus> getToscaElementsRes = getLatestVersionNotAbstractMetadataOnly(isAbstract, isHighest, componentTypeEnum, internalComponentType); + if (getToscaElementsRes.isRight()) { + result = Either.right(getToscaElementsRes.right().value()); + } else { + List collection = getToscaElementsRes.left().value(); + if (collection == null) { + componentUids = new ArrayList<>(); + } else { + componentUids = collection.stream().map(p -> p.getUniqueId()).collect(Collectors.toList()); + } + } + if (result == null) { + result = Either.left(componentUids); + } + return result; + } + + private ComponentParametersView buildComponentViewForNotAbstract() { + ComponentParametersView componentParametersView = new ComponentParametersView(); + componentParametersView.disableAll(); + componentParametersView.setIgnoreCategories(false); + componentParametersView.setIgnoreAllVersions(false); + return componentParametersView; + } + + public Either validateComponentNameExists(String name, ResourceTypeEnum resourceType, ComponentTypeEnum componentType) { + Either result = validateComponentNameUniqueness(name, resourceType, componentType); + if (result.isLeft()) { + result = Either.left(!result.left().value()); + } + return result; + } + + public Either validateComponentNameUniqueness(String name, ResourceTypeEnum resourceType, ComponentTypeEnum componentType) { + VertexTypeEnum vertexType = ModelConverter.isAtomicComponent(resourceType) ? VertexTypeEnum.NODE_TYPE : VertexTypeEnum.TOPOLOGY_TEMPLATE; + String normalizedName = ValidationUtils.normaliseComponentName(name); + Map properties = new EnumMap<>(GraphPropertyEnum.class); + properties.put(GraphPropertyEnum.NORMALIZED_NAME, normalizedName); + properties.put(GraphPropertyEnum.COMPONENT_TYPE, componentType.name()); + + Either, TitanOperationStatus> vertexEither = titanDao.getByCriteria(vertexType, properties, JsonParseFlagEnum.NoParse); + if (vertexEither.isRight() && vertexEither.right().value() != TitanOperationStatus.NOT_FOUND) { + log.debug("failed to get vertex from graph with property normalizedName: {}", normalizedName); + return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(vertexEither.right().value())); + } + List vertexList = vertexEither.isLeft() ? vertexEither.left().value() : null; + if (vertexList != null && !vertexList.isEmpty()) { + return Either.left(false); + } else { + return Either.left(true); + } + } + + + private void fillNodeTypePropsMap(Map hasProps, Map hasNotProps, String internalComponentType) { + switch (internalComponentType.toLowerCase()) { + case "vf": + case "cvfc": + hasNotProps.put(GraphPropertyEnum.RESOURCE_TYPE, ResourceTypeEnum.VFCMT.name()); + break; + case "service": + case "pnf" : + hasNotProps.put(GraphPropertyEnum.RESOURCE_TYPE, Arrays.asList(ResourceTypeEnum.VFC.name(), ResourceTypeEnum.VFCMT.name())); + break; + case "vl": + hasProps.put(GraphPropertyEnum.RESOURCE_TYPE, ResourceTypeEnum.VL.name()); + break; + default: + break; + } + } + + + private void fillTopologyTemplatePropsMap(Map hasProps, Map hasNotProps, ComponentTypeEnum componentTypeEnum, String internalComponentType) { + switch (componentTypeEnum) { + case RESOURCE: + hasProps.put(GraphPropertyEnum.COMPONENT_TYPE, ComponentTypeEnum.RESOURCE.name()); + break; + case SERVICE: + hasProps.put(GraphPropertyEnum.COMPONENT_TYPE, ComponentTypeEnum.SERVICE.name()); + break; + default: + break; + } + switch (internalComponentType.toLowerCase()) { + case "vf": + case "cvfc": + hasProps.put(GraphPropertyEnum.RESOURCE_TYPE, ResourceTypeEnum.CVFC.name()); + break; + case "service": + hasNotProps.put(GraphPropertyEnum.RESOURCE_TYPE, ResourceTypeEnum.CVFC.name()); + break; + default: + break; + } + } + + private void fillPropsMap(Map hasProps, Map hasNotProps, String internalComponentType, ComponentTypeEnum componentTypeEnum, boolean isAbstract, VertexTypeEnum internalVertexType) { + hasNotProps.put(GraphPropertyEnum.STATE, LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT.name()); + + hasNotProps.put(GraphPropertyEnum.IS_DELETED, true); + hasProps.put(GraphPropertyEnum.IS_HIGHEST_VERSION, true); + if (VertexTypeEnum.NODE_TYPE == internalVertexType) { + hasProps.put(GraphPropertyEnum.IS_ABSTRACT, isAbstract); + if (internalComponentType != null) { + fillNodeTypePropsMap(hasProps, hasNotProps, internalComponentType); + } + } else { + fillTopologyTemplatePropsMap(hasProps, hasNotProps, componentTypeEnum, internalComponentType); + } + } + + private List getInternalVertexTypes(ComponentTypeEnum componentTypeEnum, String internalComponentType) { + List internalVertexTypes = new ArrayList<>(); + if (ComponentTypeEnum.RESOURCE == componentTypeEnum) { + internalVertexTypes.add(VertexTypeEnum.NODE_TYPE); + } + if (ComponentTypeEnum.SERVICE == componentTypeEnum || "service".equalsIgnoreCase(internalComponentType) || "vf".equalsIgnoreCase(internalComponentType)) { + internalVertexTypes.add(VertexTypeEnum.TOPOLOGY_TEMPLATE); + } + return internalVertexTypes; + } + + public Either, StorageOperationStatus> getLatestVersionNotAbstractMetadataOnly(boolean isAbstract, Boolean isHighest, ComponentTypeEnum componentTypeEnum, String internalComponentType) { + List internalVertexTypes = getInternalVertexTypes(componentTypeEnum, internalComponentType); + List result = new ArrayList<>(); + for (VertexTypeEnum vertexType : internalVertexTypes) { + Either, StorageOperationStatus> listByVertexType = getLatestVersionNotAbstractToscaElementsMetadataOnly(isAbstract, isHighest, componentTypeEnum, internalComponentType, vertexType); + if (listByVertexType.isRight()) { + return listByVertexType; + } + result.addAll(listByVertexType.left().value()); + } + return Either.left(result); + + } + + public Either, StorageOperationStatus> getLatestComponentListByUuid(String componentUuid) { + Map propertiesToMatch = new EnumMap<>(GraphPropertyEnum.class); + propertiesToMatch.put(GraphPropertyEnum.IS_HIGHEST_VERSION, true); + Either, StorageOperationStatus> componentListByUuid = getComponentListByUuid(componentUuid, propertiesToMatch); + return componentListByUuid; + } - Either, StorageOperationStatus> result = null; - Either getComponentRes; - List components = new ArrayList<>(); - List componentVertices; - Map propertiesToMatch = new EnumMap<>(GraphPropertyEnum.class); - Map propertiesNotToMatch = new EnumMap<>(GraphPropertyEnum.class); + public Either, StorageOperationStatus> getComponentListByUuid(String componentUuid, Map additionalPropertiesToMatch) { - propertiesToMatch.put(GraphPropertyEnum.SYSTEM_NAME, systemName); - if (componentType != null) - propertiesToMatch.put(GraphPropertyEnum.COMPONENT_TYPE, componentType.name()); + Map propertiesToMatch = new EnumMap<>(GraphPropertyEnum.class); - propertiesNotToMatch.put(GraphPropertyEnum.IS_DELETED, true); + if (additionalPropertiesToMatch != null) { + propertiesToMatch.putAll(additionalPropertiesToMatch); + } - Either, TitanOperationStatus> getComponentsRes = titanDao.getByCriteria(null, propertiesToMatch, propertiesNotToMatch, JsonParseFlagEnum.ParseAll); - if (getComponentsRes.isRight()) { - TitanOperationStatus status = getComponentsRes.right().value(); - log.debug("Failed to fetch the component with system name {}. Status is {} ", systemName, status); - result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status)); - } - if (result == null) { - componentVertices = getComponentsRes.left().value(); - for (GraphVertex componentVertex : componentVertices) { - getComponentRes = getToscaElementByOperation(componentVertex); - if (getComponentRes.isRight()) { - log.debug("Failed to get the component {}. Status is {} ", componentVertex.getJsonMetadataField(JsonPresentationFields.NAME), getComponentRes.right().value()); - result = Either.right(getComponentRes.right().value()); - break; - } - T componentBySystemName = getComponentRes.left().value(); - log.debug("Found component, id: {}", componentBySystemName.getUniqueId()); - components.add(componentBySystemName); - } - } - if (result == null) { - result = Either.left(components); - } - return result; - } + propertiesToMatch.put(GraphPropertyEnum.UUID, componentUuid); - public Either getComponentByNameAndVersion(ComponentTypeEnum componentType, String name, String version) { - return getComponentByNameAndVersion(componentType, name, version, JsonParseFlagEnum.ParseAll); - } + Map propertiesNotToMatch = new EnumMap<>(GraphPropertyEnum.class); + propertiesNotToMatch.put(GraphPropertyEnum.IS_DELETED, true); - public Either getComponentByNameAndVersion(ComponentTypeEnum componentType, String name, String version, JsonParseFlagEnum parseFlag) { - Either result; + Either, TitanOperationStatus> vertexEither = titanDao.getByCriteria(null, propertiesToMatch, propertiesNotToMatch, JsonParseFlagEnum.ParseAll); - Map hasProperties = new EnumMap<>(GraphPropertyEnum.class); - Map hasNotProperties = new EnumMap<>(GraphPropertyEnum.class); + if (vertexEither.isRight()) { + log.debug("Couldn't fetch metadata for component with type {} and uuid {}, error: {}", componentUuid, vertexEither.right().value()); + return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(vertexEither.right().value())); + } + List vertexList = vertexEither.isLeft() ? vertexEither.left().value() : null; - hasProperties.put(GraphPropertyEnum.NAME, name); - hasProperties.put(GraphPropertyEnum.VERSION, version); - hasNotProperties.put(GraphPropertyEnum.IS_DELETED, true); - if (componentType != null) { - hasProperties.put(GraphPropertyEnum.COMPONENT_TYPE, componentType.name()); - } - Either, TitanOperationStatus> getResourceRes = titanDao.getByCriteria(null, hasProperties, hasNotProperties, parseFlag); - if (getResourceRes.isRight()) { - TitanOperationStatus status = getResourceRes.right().value(); - log.debug("failed to find resource with name {}, version {}. Status is {} ", name, version, status); - result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status)); - return result; - } - return getToscaElementByOperation(getResourceRes.left().value().get(0)); - } + if (vertexList == null || vertexList.isEmpty()) { + log.debug("Component with uuid {} was not found", componentUuid); + return Either.right(StorageOperationStatus.NOT_FOUND); + } - public Either, StorageOperationStatus> getCatalogComponents(ComponentTypeEnum componentType, boolean isHighestVersions) { - List components = new ArrayList<>(); - Either, StorageOperationStatus> catalogDataResult; - List toscaElements; - switch (componentType) { - case RESOURCE: - catalogDataResult = nodeTypeOperation.getElementCatalogData(ComponentTypeEnum.RESOURCE, ToscaElementTypeEnum.NodeType, isHighestVersions); - if (catalogDataResult.isRight()) { - return Either.right(catalogDataResult.right().value()); - } - toscaElements = catalogDataResult.left().value(); - Either, StorageOperationStatus> resourceCatalogData = topologyTemplateOperation.getElementCatalogData(ComponentTypeEnum.RESOURCE, ToscaElementTypeEnum.TopologyTemplate, isHighestVersions); - if (resourceCatalogData.isRight()) { - return Either.right(resourceCatalogData.right().value()); - } - toscaElements.addAll(resourceCatalogData.left().value()); - break; - case SERVICE: - catalogDataResult = topologyTemplateOperation.getElementCatalogData(ComponentTypeEnum.SERVICE, ToscaElementTypeEnum.TopologyTemplate, isHighestVersions); - if (catalogDataResult.isRight()) { - return Either.right(catalogDataResult.right().value()); + ArrayList latestComponents = new ArrayList<>(); + for (GraphVertex vertex : vertexList) { + Either toscaElementByOperation = getToscaElementByOperation(vertex); + + if(toscaElementByOperation.isRight()){ + log.debug("Could not fetch the following Component by UUID {}", vertex.getUniqueId()); + return Either.right(toscaElementByOperation.right().value()); } - toscaElements = catalogDataResult.left().value(); - break; - default: - log.debug("Not supported component type {}", componentType); - return Either.right(StorageOperationStatus.BAD_REQUEST); - } - toscaElements.forEach(te -> { - T component = ModelConverter.convertFromToscaElement(te); - components.add(component); - }); - return Either.left(components); - } - - public Either, StorageOperationStatus> deleteMarkedElements(ComponentTypeEnum componentType) { - Either, StorageOperationStatus> allComponentsMarkedForDeletion; - List deleted = new ArrayList<>(); - switch (componentType) { - case RESOURCE: - allComponentsMarkedForDeletion = nodeTypeOperation.getAllComponentsMarkedForDeletion(componentType); - break; - case SERVICE: - case PRODUCT: - allComponentsMarkedForDeletion = topologyTemplateOperation.getAllComponentsMarkedForDeletion(componentType); - break; - default: - log.debug("Not supported component type {}", componentType); - return Either.right(StorageOperationStatus.BAD_REQUEST); - } - if (allComponentsMarkedForDeletion.isRight()) { - return Either.right(allComponentsMarkedForDeletion.right().value()); - } - List allMarked = allComponentsMarkedForDeletion.left().value(); - - Either, TitanOperationStatus> allNotDeletedElements = topologyTemplateOperation.getAllNotDeletedElements(); - if (allNotDeletedElements.isRight()) { - return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(allNotDeletedElements.right().value())); + + latestComponents.add(toscaElementByOperation.left().value()); } - List allNonMarked = allNotDeletedElements.left().value(); - for (GraphVertex elementV : allMarked) { - if (topologyTemplateOperation.isInUse(elementV, allNonMarked) == false) { - Either deleteToscaElement = deleteToscaElement(elementV); - if (deleteToscaElement.isRight()) { - log.debug("Failed to delete marked element {} error {}", elementV.getUniqueId(), deleteToscaElement.right().value()); + + if(latestComponents.size() > 1) { + for (Component component : latestComponents) { + if(component.isHighestVersion()){ + LinkedList highestComponent = new LinkedList<>(); + highestComponent.add(component); + return Either.left(highestComponent); } - } else { - deleted.add(elementV.getUniqueId()); - log.debug("Marked element {} in use. don't delete it", elementV.getUniqueId()); - } - } - return Either.left(deleted); - } - - public Either, StorageOperationStatus> getAllComponentsMarkedForDeletion(ComponentTypeEnum componentType) { - Either, StorageOperationStatus> allComponentsMarkedForDeletion; - switch (componentType) { - case RESOURCE: - allComponentsMarkedForDeletion = nodeTypeOperation.getAllComponentsMarkedForDeletion(componentType); - break; - case SERVICE: - case PRODUCT: - allComponentsMarkedForDeletion = topologyTemplateOperation.getAllComponentsMarkedForDeletion(componentType); - break; - default: - log.debug("Not supported component type {}", componentType); - return Either.right(StorageOperationStatus.BAD_REQUEST); - } - if (allComponentsMarkedForDeletion.isRight()) { - return Either.right(allComponentsMarkedForDeletion.right().value()); - } - return Either.left(allComponentsMarkedForDeletion.left().value().stream().map(v -> v.getUniqueId()).collect(Collectors.toList())); - } - - public Either isComponentInUse(String componentId) { - Either result; - Either, TitanOperationStatus> allNotDeletedElements = topologyTemplateOperation.getAllNotDeletedElements(); - if (allNotDeletedElements.isRight()) { - result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(allNotDeletedElements.right().value())); - } else { - result = Either.left(topologyTemplateOperation.isInUse(componentId, allNotDeletedElements.left().value())); - } - return result; - } - - public Either, StorageOperationStatus> addComponentInstanceToTopologyTemplate(Component containerComponent, Component origComponent, ComponentInstance componentInstance, boolean allowDeleted, User user) { - - Either, StorageOperationStatus> result = null; - Either updateContainerComponentRes = null; - componentInstance.setIcon(origComponent.getIcon()); - Either, StorageOperationStatus> addResult = nodeTemplateOperation.addComponentInstanceToTopologyTemplate(ModelConverter.convertToToscaElement(containerComponent), - ModelConverter.convertToToscaElement(origComponent), getNextComponentInstanceCounter(containerComponent, origComponent.getName()), componentInstance, allowDeleted, user); - - if (addResult.isRight()) { - CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to add the component instance {} to container component {}. ", componentInstance.getName(), containerComponent.getName()); - result = Either.right(addResult.right().value()); - } - if (result == null) { - updateContainerComponentRes = topologyTemplateOperation.getToscaElement(containerComponent.getUniqueId()); - if (updateContainerComponentRes.isRight()) { - CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to fetch updated topology template {} with updated component instance {}. ", containerComponent.getName(), componentInstance.getName()); - result = Either.right(updateContainerComponentRes.right().value()); - } - } - if (result == null) { - Component updatedComponent = ModelConverter.convertFromToscaElement(updateContainerComponentRes.left().value()); - String createdInstanceId = addResult.left().value().getRight(); - CommonUtility.addRecordToLog(log, LogLevelEnum.TRACE, "The component instance {} has been added to container component {}. ", createdInstanceId, updatedComponent.getName()); - result = Either.left(new ImmutablePair<>(updatedComponent, createdInstanceId)); - } - return result; - } - - public StorageOperationStatus associateComponentInstancesToComponent(Component containerComponent, Map resourcesInstancesMap, boolean allowDeleted) { - - StorageOperationStatus result = null; - CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Going to add component instances to component {}", containerComponent.getUniqueId()); - - Either metadataVertex = titanDao.getVertexById(containerComponent.getUniqueId(), JsonParseFlagEnum.ParseAll); - if (metadataVertex.isRight()) { - TitanOperationStatus status = metadataVertex.right().value(); - if (status == TitanOperationStatus.NOT_FOUND) { - status = TitanOperationStatus.INVALID_ID; - } - result = DaoStatusConverter.convertTitanStatusToStorageStatus(status); - } - if (result == null) { - result = nodeTemplateOperation.associateComponentInstancesToComponent(containerComponent, resourcesInstancesMap, metadataVertex.left().value(), allowDeleted); - } - return result; - } - - public Either, StorageOperationStatus> updateComponentInstanceMetadataOfTopologyTemplate(Component containerComponent, Component origComponent, ComponentInstance componentInstance) { - - Either, StorageOperationStatus> result = null; - - CommonUtility.addRecordToLog(log, LogLevelEnum.TRACE, "Going to update the metadata of the component instance {} belonging to container component {}. ", componentInstance.getName(), containerComponent.getName()); - componentInstance.setIcon(origComponent.getIcon()); - Either, StorageOperationStatus> updateResult = nodeTemplateOperation.updateComponentInstanceMetadataOfTopologyTemplate(ModelConverter.convertToToscaElement(containerComponent), - ModelConverter.convertToToscaElement(origComponent), componentInstance); - if (updateResult.isRight()) { - CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to update the metadata of the component instance {} belonging to container component {}. ", componentInstance.getName(), containerComponent.getName()); - result = Either.right(updateResult.right().value()); - } - if (result == null) { - Component updatedComponent = ModelConverter.convertFromToscaElement(updateResult.left().value().getLeft()); - String createdInstanceId = updateResult.left().value().getRight(); - CommonUtility.addRecordToLog(log, LogLevelEnum.TRACE, "The metadata of the component instance {} has been updated to container component {}. ", createdInstanceId, updatedComponent.getName()); - result = Either.left(new ImmutablePair<>(updatedComponent, createdInstanceId)); - } - return result; - } - - public Either updateComponentInstanceMetadataOfTopologyTemplate(Component containerComponent) { - - Either result = null; - - CommonUtility.addRecordToLog(log, LogLevelEnum.TRACE, "Going to update the metadata belonging to container component {}. ", containerComponent.getName()); - - Either updateResult = nodeTemplateOperation.updateComponentInstanceMetadataOfTopologyTemplate(ModelConverter.convertToToscaElement(containerComponent)); - if (updateResult.isRight()) { - CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to update the metadata belonging to container component {}. ", containerComponent.getName()); - result = Either.right(updateResult.right().value()); - } - if (result == null) { - Component updatedComponent = ModelConverter.convertFromToscaElement(updateResult.left().value()); - CommonUtility.addRecordToLog(log, LogLevelEnum.TRACE, "The metadata has been updated to container component {}. ", updatedComponent.getName()); - result = Either.left(updatedComponent); - } - return result; - } - - public Either, StorageOperationStatus> deleteComponentInstanceFromTopologyTemplate(Component containerComponent, String resourceInstanceId) { - - Either, StorageOperationStatus> result = null; - - CommonUtility.addRecordToLog(log, LogLevelEnum.TRACE, "Going to delete the component instance {} belonging to container component {}. ", resourceInstanceId, containerComponent.getName()); - - Either, StorageOperationStatus> updateResult = nodeTemplateOperation.deleteComponentInstanceFromTopologyTemplate(ModelConverter.convertToToscaElement(containerComponent), resourceInstanceId); - if (updateResult.isRight()) { - CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to delete the component instance {} belonging to container component {}. ", resourceInstanceId, containerComponent.getName()); - result = Either.right(updateResult.right().value()); - } - if (result == null) { - Component updatedComponent = ModelConverter.convertFromToscaElement(updateResult.left().value().getLeft()); - String deletedInstanceId = updateResult.left().value().getRight(); - CommonUtility.addRecordToLog(log, LogLevelEnum.TRACE, "The component instance {} has been deleted from container component {}. ", deletedInstanceId, updatedComponent.getName()); - result = Either.left(new ImmutablePair<>(updatedComponent, deletedInstanceId)); - } - return result; - } - - private String getNextComponentInstanceCounter(Component containerComponent, String originResourceName) { - - Integer nextCounter = 0; - - if (CollectionUtils.isNotEmpty(containerComponent.getComponentInstances())) { - - String normalizedName = ValidationUtils.normalizeComponentInstanceName(originResourceName); - Integer maxCounterFromNames = getMaxCounterFromNames(containerComponent, normalizedName); - Integer maxCounterFromIds = getMaxCounterFromIds(containerComponent, normalizedName); - - if (maxCounterFromNames == null && maxCounterFromIds != null) { - nextCounter = maxCounterFromIds + 1; - } else if (maxCounterFromIds == null && maxCounterFromNames != null) { - nextCounter = maxCounterFromNames + 1; - } else if (maxCounterFromIds != null && maxCounterFromNames != null) { - nextCounter = maxCounterFromNames > maxCounterFromIds ? maxCounterFromNames + 1 : maxCounterFromIds + 1; - } - } - return nextCounter.toString(); - } - - private Integer getMaxCounterFromNames(Component containerComponent, String normalizedName) { - - Integer maxCounter = 0; - List countersStr = containerComponent.getComponentInstances().stream().filter(ci -> ci.getNormalizedName() != null && ci.getNormalizedName().startsWith(normalizedName)).map(ci -> ci.getNormalizedName().split(normalizedName)[1]) - .collect(Collectors.toList()); - - if (CollectionUtils.isEmpty(countersStr)) { - return null; - } - Integer currCounter = null; - for (String counter : countersStr) { - if (StringUtils.isEmpty(counter)) { - continue; - } - try { - currCounter = Integer.parseInt(counter); - } catch (Exception e) { - continue; } - maxCounter = maxCounter < currCounter ? currCounter : maxCounter; - } - if (currCounter == null) { - return null; - } - return maxCounter; - } - - private Integer getMaxCounterFromIds(Component containerComponent, String normalizedName) { - - Integer maxCounter = 0; - List countersStr = containerComponent.getComponentInstances().stream().filter(ci -> ci.getUniqueId() != null && ci.getUniqueId().contains(normalizedName)).map(ci -> ci.getUniqueId().split(normalizedName)[1]) - .collect(Collectors.toList()); - - if (CollectionUtils.isEmpty(countersStr)) { - return null; - } - Integer currCounter = null; - for (String counter : countersStr) { - if (StringUtils.isEmpty(counter)) { - continue; - } - try { - currCounter = Integer.parseInt(counter); - } catch (Exception e) { - continue; - } - maxCounter = maxCounter < currCounter ? currCounter : maxCounter; - } - if (currCounter == null) { - return null; - } - return maxCounter; - } - - public Either associateResourceInstances(String componentId, RequirementCapabilityRelDef requirementDef) { - return nodeTemplateOperation.associateResourceInstances(componentId, requirementDef); - - } - - public Either, StorageOperationStatus> createAndAssociateInputs(Map inputs, String componentId) { - - Either getVertexEither = titanDao.getVertexById(componentId, JsonParseFlagEnum.NoParse); - if (getVertexEither.isRight()) { - log.debug("Couldn't fetch component with and unique id {}, error: {}", componentId, getVertexEither.right().value()); - return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(getVertexEither.right().value())); - - } - - GraphVertex vertex = getVertexEither.left().value(); - Map inputsMap = inputs.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> new PropertyDataDefinition(e.getValue()))); - - StorageOperationStatus status = topologyTemplateOperation.associateInputsToComponent(vertex, inputsMap, componentId); - - if (StorageOperationStatus.OK == status) { - log.debug("Component created successfully!!!"); - List inputsResList = null; - if (inputsMap != null && !inputsMap.isEmpty()) { - inputsResList = inputsMap.values().stream().map(i -> new InputDefinition(i)).collect(Collectors.toList()); - } - return Either.left(inputsResList); - } - return Either.right(status); - - } - - public Either, StorageOperationStatus> addInputsToComponent(Map inputs, String componentId) { - - Either getVertexEither = titanDao.getVertexById(componentId, JsonParseFlagEnum.NoParse); - if (getVertexEither.isRight()) { - log.debug("Couldn't fetch component with and unique id {}, error: {}", componentId, getVertexEither.right().value()); - return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(getVertexEither.right().value())); - - } - - GraphVertex vertex = getVertexEither.left().value(); - Map inputsMap = inputs.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> new PropertyDataDefinition(e.getValue()))); - - StorageOperationStatus status = topologyTemplateOperation.addToscaDataToToscaElement(vertex, EdgeLabelEnum.INPUTS, VertexTypeEnum.INPUTS, inputsMap, JsonPresentationFields.NAME); - - if (StorageOperationStatus.OK == status) { - log.debug("Component created successfully!!!"); - List inputsResList = null; - if (inputsMap != null && !inputsMap.isEmpty()) { - inputsResList = inputsMap.values().stream().map(i -> new InputDefinition(i)).collect(Collectors.toList()); - } - return Either.left(inputsResList); - } - return Either.right(status); - - } - - public Either>, StorageOperationStatus> associateComponentInstancePropertiesToComponent(Map> instProperties, String componentId) { - - Either getVertexEither = titanDao.getVertexById(componentId, JsonParseFlagEnum.NoParse); - if (getVertexEither.isRight()) { - log.debug("Couldn't fetch component with and unique id {}, error: {}", componentId, getVertexEither.right().value()); - return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(getVertexEither.right().value())); - - } - - GraphVertex vertex = getVertexEither.left().value(); - Map instPropsMap = new HashMap<>(); - if (instProperties != null) { - - MapPropertiesDataDefinition propertiesMap; - for (Entry> entry : instProperties.entrySet()) { - propertiesMap = new MapPropertiesDataDefinition(); - - propertiesMap.setMapToscaDataDefinition(entry.getValue().stream().map(e -> new PropertyDataDefinition(e)).collect(Collectors.toMap(e -> e.getName(), e -> e))); - - instPropsMap.put(entry.getKey(), propertiesMap); - } - } - - StorageOperationStatus status = topologyTemplateOperation.associateInstPropertiesToComponent(vertex, instPropsMap); - - if (StorageOperationStatus.OK == status) { - log.debug("Component created successfully!!!"); - return Either.left(instProperties); - } - return Either.right(status); - - } - - public Either>, StorageOperationStatus> addComponentInstanceInputsToComponent(Component containerComponent, Map> instProperties) { - - StorageOperationStatus status = StorageOperationStatus.OK; - if (instProperties != null) { - - for (Entry> entry : instProperties.entrySet()) { - List props = entry.getValue(); - String componentInstanseId = entry.getKey(); - if (props != null && !props.isEmpty()) { - for (ComponentInstanceInput property : props) { - List componentInstancesInputs = containerComponent.getComponentInstancesInputs().get(componentInstanseId); - Optional instanceProperty = componentInstancesInputs.stream().filter(p -> p.getName().equals(property.getName())).findAny(); - if (instanceProperty.isPresent()) { - status = updateComponentInstanceInput(containerComponent, componentInstanseId, property); - } else { - status = addComponentInstanceInput(containerComponent, componentInstanseId, property); - } - if (status != StorageOperationStatus.OK) { - log.debug("Failed to update instance input {} for instance {} error {} ", property, componentInstanseId, status); - return Either.right(status); - } else { - log.trace("instance input {} for instance {} updated", property, componentInstanseId); - } - } - } - } - } - return Either.left(instProperties); - } - - public StorageOperationStatus deleteComponentInstanceInputsToComponent(Map> instProperties, String componentId) { - - Either getVertexEither = titanDao.getVertexById(componentId, JsonParseFlagEnum.NoParse); - if (getVertexEither.isRight()) { - log.debug("Couldn't fetch component with and unique id {}, error: {}", componentId, getVertexEither.right().value()); - return DaoStatusConverter.convertTitanStatusToStorageStatus(getVertexEither.right().value()); - - } - - GraphVertex vertex = getVertexEither.left().value(); - Map instPropsMap = new HashMap<>(); - if (instProperties != null) { - - MapPropertiesDataDefinition propertiesMap; - for (Entry> entry : instProperties.entrySet()) { - propertiesMap = new MapPropertiesDataDefinition(); - - propertiesMap.setMapToscaDataDefinition(entry.getValue().stream().map(e -> new PropertyDataDefinition(e)).collect(Collectors.toMap(e -> e.getName(), e -> e))); - - instPropsMap.put(entry.getKey(), propertiesMap); - } - } - - return topologyTemplateOperation.deleteInstInputsToComponent(vertex, instPropsMap); - - } - - public Either>, StorageOperationStatus> addComponentInstancePropertiesToComponent(Component containerComponent, Map> instProperties, String componentId) { - - StorageOperationStatus status = StorageOperationStatus.OK; - if (instProperties != null) { - - for (Entry> entry : instProperties.entrySet()) { - List props = entry.getValue(); - String componentInstanseId = entry.getKey(); - List instanceProperties = containerComponent.getComponentInstancesProperties().get(componentInstanseId); - if (props != null && !props.isEmpty()) { - for (ComponentInstanceProperty property : props) { - Optional instanceProperty = instanceProperties.stream().filter(p -> p.getUniqueId().equals(property.getUniqueId())).findAny(); - if (instanceProperty.isPresent()) { - status = updateComponentInstanceProperty(containerComponent, componentInstanseId, property); - } else { - status = addComponentInstanceProperty(containerComponent, componentInstanseId, property); - } - - } - } - } - } - - return Either.left(instProperties); - - } - - public StorageOperationStatus associateArtifactToInstances(Map> instArtifacts, String componentId, User user) { - - Either getVertexEither = titanDao.getVertexById(componentId, JsonParseFlagEnum.NoParse); - if (getVertexEither.isRight()) { - log.debug("Couldn't fetch component with and unique id {}, error: {}", componentId, getVertexEither.right().value()); - return DaoStatusConverter.convertTitanStatusToStorageStatus(getVertexEither.right().value()); - - } - - GraphVertex vertex = getVertexEither.left().value(); - Map instArtMap = new HashMap<>(); - if (instArtifacts != null) { - - MapArtifactDataDefinition artifactsMap; - for (Entry> entry : instArtifacts.entrySet()) { - Map artList = entry.getValue(); - Map artifacts = artList.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> new ArtifactDataDefinition(e.getValue()))); - artifactsMap = nodeTemplateOperation.prepareInstDeploymentArtifactPerInstance(artifacts, entry.getKey(), user, NodeTemplateOperation.HEAT_VF_ENV_NAME); - - instArtMap.put(entry.getKey(), artifactsMap); - } - } - - return topologyTemplateOperation.associateInstArtifactToComponent(vertex, instArtMap); - - } - - public StorageOperationStatus associateInstAttributeToComponentToInstances(Map> instArttributes, String componentId) { - - Either getVertexEither = titanDao.getVertexById(componentId, JsonParseFlagEnum.NoParse); - if (getVertexEither.isRight()) { - log.debug("Couldn't fetch component with and unique id {}, error: {}", componentId, getVertexEither.right().value()); - return DaoStatusConverter.convertTitanStatusToStorageStatus(getVertexEither.right().value()); - - } - - GraphVertex vertex = getVertexEither.left().value(); - Map instAttr = new HashMap<>(); - if (instArttributes != null) { - - MapPropertiesDataDefinition attributesMap; - for (Entry> entry : instArttributes.entrySet()) { - attributesMap = new MapPropertiesDataDefinition(); - attributesMap.setMapToscaDataDefinition(entry.getValue().stream().map(e -> new PropertyDataDefinition(e)).collect(Collectors.toMap(e -> e.getName(), e -> e))); - instAttr.put(entry.getKey(), attributesMap); - } - } - - return topologyTemplateOperation.associateInstAttributeToComponent(vertex, instAttr); - - } - - public StorageOperationStatus associateCalculatedCapReq(Map>> instCapabilties, Map>> instReg, String componentId) { - Either getVertexEither = titanDao.getVertexById(componentId, JsonParseFlagEnum.NoParse); - if (getVertexEither.isRight()) { - log.debug("Couldn't fetch component with and unique id {}, error: {}", componentId, getVertexEither.right().value()); - return DaoStatusConverter.convertTitanStatusToStorageStatus(getVertexEither.right().value()); - - } - - GraphVertex vertex = getVertexEither.left().value(); - - Map calcRequirements = new HashMap<>(); - - Map calcCapabilty = new HashMap<>(); - Map calculatedCapabilitiesProperties = new HashMap<>(); - ; - if (instCapabilties != null) { - for (Entry>> entry : instCapabilties.entrySet()) { - - Map> caps = entry.getValue(); - Map mapToscaDataDefinition = new HashMap<>(); - for (Entry> instCapability : caps.entrySet()) { - mapToscaDataDefinition.put(instCapability.getKey(), new ListCapabilityDataDefinition(instCapability.getValue().stream().map(iCap -> new CapabilityDataDefinition(iCap)).collect(Collectors.toList()))); - } - - ComponentInstanceDataDefinition componentInstance = new ComponentInstanceDataDefinition(entry.getKey()); - MapListCapabiltyDataDefinition capMap = nodeTemplateOperation.prepareCalculatedCapabiltyForNodeType(mapToscaDataDefinition, componentInstance); - - MapCapabiltyProperty mapCapabiltyProperty = ModelConverter.convertToMapOfMapCapabiltyProperties(caps, componentInstance.getUniqueId(), true); - - calcCapabilty.put(entry.getKey().getUniqueId(), capMap); - calculatedCapabilitiesProperties.put(entry.getKey().getUniqueId(), mapCapabiltyProperty); - } - } - - if (instReg != null) { - for (Entry>> entry : instReg.entrySet()) { - - Map> req = entry.getValue(); - Map mapToscaDataDefinition = new HashMap<>(); - for (Entry> instReq : req.entrySet()) { - mapToscaDataDefinition.put(instReq.getKey(), new ListRequirementDataDefinition(instReq.getValue().stream().map(iCap -> new RequirementDataDefinition(iCap)).collect(Collectors.toList()))); - } - - MapListRequirementDataDefinition capMap = nodeTemplateOperation.prepareCalculatedRequirementForNodeType(mapToscaDataDefinition, new ComponentInstanceDataDefinition(entry.getKey())); - - calcRequirements.put(entry.getKey().getUniqueId(), capMap); - } - } - - StorageOperationStatus status = topologyTemplateOperation.associateCalcCapReqToComponent(vertex, calcRequirements, calcCapabilty, calculatedCapabilitiesProperties); - - return status; - } - - private Either, StorageOperationStatus> getLatestVersionNotAbstractToscaElementsMetadataOnly(boolean isAbstract, Boolean isHighest, ComponentTypeEnum componentTypeEnum, String internalComponentType, VertexTypeEnum vertexType) { - - Map hasProps = new EnumMap<>(GraphPropertyEnum.class); - Map hasNotProps = new EnumMap<>(GraphPropertyEnum.class); - - fillPropsMap(hasProps, hasNotProps, internalComponentType, componentTypeEnum, isAbstract, vertexType); - - Either, TitanOperationStatus> getRes = titanDao.getByCriteria(vertexType, hasProps, hasNotProps, JsonParseFlagEnum.ParseMetadata); - if (getRes.isRight()) { - if (getRes.right().value().equals(TitanOperationStatus.NOT_FOUND)) { - return Either.left(new ArrayList<>()); - } else { - return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(getRes.right().value())); - } - } else { - List nonAbstractLatestComponents = new ArrayList<>(); - ComponentParametersView params = new ComponentParametersView(true); - params.setIgnoreAllVersions(false); - for (GraphVertex vertexComponent : getRes.left().value()) { - Either componentRes = topologyTemplateOperation.getLightComponent(vertexComponent, componentTypeEnum, params); - if (componentRes.isRight()) { - log.debug("Failed to fetch ligth element for {} error {}", vertexComponent.getUniqueId(), componentRes.right().value()); - return Either.right(componentRes.right().value()); - } else { - Component component = ModelConverter.convertFromToscaElement(componentRes.left().value()); - - nonAbstractLatestComponents.add(component); - } - } - - return Either.left(nonAbstractLatestComponents); - } - } - - public Either getLatestComponentMetadataByUuid(String componentUuid, JsonParseFlagEnum parseFlag, Boolean isHighest) { - - Either result; - - Map hasProperties = new EnumMap<>(GraphPropertyEnum.class); - - hasProperties.put(GraphPropertyEnum.UUID, componentUuid); - if (isHighest != null) { - hasProperties.put(GraphPropertyEnum.IS_HIGHEST_VERSION, isHighest.booleanValue()); - } - - Map propertiesNotToMatch = new EnumMap<>(GraphPropertyEnum.class); - propertiesNotToMatch.put(GraphPropertyEnum.IS_DELETED, true); - - Either, TitanOperationStatus> getRes = titanDao.getByCriteria(null, hasProperties, propertiesNotToMatch, parseFlag); - if (getRes.isRight()) { - result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(getRes.right().value())); - } else { - List latestVersionList = getRes.left().value().stream().map(ModelConverter::convertToComponentMetadata).collect(Collectors.toList()); - ComponentMetadataData latestVersion = latestVersionList.size() == 1 ? latestVersionList.get(0) - : latestVersionList.stream().max((c1, c2) -> Double.compare(Double.parseDouble(c1.getMetadataDataDefinition().getVersion()), Double.parseDouble(c2.getMetadataDataDefinition().getVersion()))).get(); - result = Either.left(latestVersion); - } - return result; - } - - public Either getComponentMetadata(String componentId) { - - Either result; - Either getRes = titanDao.getVertexById(componentId, JsonParseFlagEnum.ParseMetadata); - if (getRes.isRight()) { - result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(getRes.right().value())); - } else { - ComponentMetadataData componentMetadata = ModelConverter.convertToComponentMetadata(getRes.left().value()); - result = Either.left(componentMetadata); - } - return result; - } - - private Map findLatestVersion(List resourceDataList) { - Map, ComponentMetadataData> latestVersionMap = new HashMap, ComponentMetadataData>(); - for (ComponentMetadataData resourceData : resourceDataList) { - ComponentMetadataData latestVersionData = resourceData; - - ComponentMetadataDataDefinition metadataDataDefinition = resourceData.getMetadataDataDefinition(); - Pair pair = createKeyPair(latestVersionData); - if (latestVersionMap.containsKey(pair)) { - latestVersionData = latestVersionMap.get(pair); - String currentVersion = latestVersionData.getMetadataDataDefinition().getVersion(); - String newVersion = metadataDataDefinition.getVersion(); - if (CommonBeUtils.compareAsdcComponentVersions(newVersion, currentVersion)) { - latestVersionData = resourceData; - } - } - if (log.isDebugEnabled()) - log.debug("last certified version of resource = {} version is {}", latestVersionData.getMetadataDataDefinition().getName(), latestVersionData.getMetadataDataDefinition().getVersion()); - - latestVersionMap.put(pair, latestVersionData); - } - - Map resVersionMap = new HashMap(); - for (ComponentMetadataData resourceData : latestVersionMap.values()) { - ComponentMetadataData latestVersionData = resourceData; - ComponentMetadataDataDefinition metadataDataDefinition = resourceData.getMetadataDataDefinition(); - if (resVersionMap.containsKey(metadataDataDefinition.getUUID())) { - latestVersionData = resVersionMap.get(metadataDataDefinition.getUUID()); - String currentVersion = latestVersionData.getMetadataDataDefinition().getVersion(); - String newVersion = metadataDataDefinition.getVersion(); - if (CommonBeUtils.compareAsdcComponentVersions(newVersion, currentVersion)) { - latestVersionData = resourceData; - } - } - if (log.isDebugEnabled()) - log.debug("last uuid version of resource = {} version is {}", latestVersionData.getMetadataDataDefinition().getName(), latestVersionData.getMetadataDataDefinition().getVersion()); - resVersionMap.put(latestVersionData.getMetadataDataDefinition().getUUID(), latestVersionData); - } - - return resVersionMap; - } - - private Pair createKeyPair(ComponentMetadataData metadataData) { - Pair pair; - NodeTypeEnum label = NodeTypeEnum.getByName(metadataData.getLabel()); - switch (label) { - case Resource: - pair = new ImmutablePair<>(metadataData.getMetadataDataDefinition().getName(), ((ResourceMetadataDataDefinition) metadataData.getMetadataDataDefinition()).getResourceType().name()); - break; - default: - pair = new ImmutablePair<>(metadataData.getMetadataDataDefinition().getName(), metadataData.getLabel()); - break; - } - - return pair; - } - - public Either, StorageOperationStatus> getLatestVersionNotAbstractComponents(boolean isAbstract, Boolean isHighest, ComponentTypeEnum componentTypeEnum, String internalComponentType, List componentUids) { - - Either, StorageOperationStatus> result = null; - List components = new ArrayList<>(); - if (componentUids == null) { - Either, StorageOperationStatus> componentUidsRes = getComponentUids(isAbstract, isHighest, componentTypeEnum, internalComponentType, componentUids); - if (componentUidsRes.isRight()) { - result = Either.right(componentUidsRes.right().value()); - } else { - componentUids = componentUidsRes.left().value(); - } - } - if (!componentUids.isEmpty()) { - for (String componentUid : componentUids) { - ComponentParametersView componentParametersView = buildComponentViewForNotAbstract(); - if (internalComponentType != null && "vl".equalsIgnoreCase(internalComponentType)) { - componentParametersView.setIgnoreCapabilities(false); - componentParametersView.setIgnoreRequirements(false); - } - Either getToscaElementRes = nodeTemplateOperation.getToscaElementOperation(componentTypeEnum).getLightComponent(componentUid, componentTypeEnum, componentParametersView); - if (getToscaElementRes.isRight()) { - if (log.isDebugEnabled()) - log.debug("Failed to fetch resource for error is {}", getToscaElementRes.right().value()); - result = Either.right(getToscaElementRes.right().value()); - break; - } - Component component = ModelConverter.convertFromToscaElement(getToscaElementRes.left().value()); - component.setContactId(null); - component.setCreationDate(null); - component.setCreatorUserId(null); - component.setCreatorFullName(null); - component.setLastUpdateDate(null); - component.setLastUpdaterUserId(null); - component.setLastUpdaterFullName(null); - component.setNormalizedName(null); - components.add(component); - } - } - if (result == null) { - result = Either.left(components); - } - return result; - } - - private Either, StorageOperationStatus> getComponentUids(boolean isAbstract, Boolean isHighest, ComponentTypeEnum componentTypeEnum, String internalComponentType, List componentUids) { - - Either, StorageOperationStatus> result = null; - Either, StorageOperationStatus> getToscaElementsRes = getLatestVersionNotAbstractMetadataOnly(isAbstract, isHighest, componentTypeEnum, internalComponentType); - if (getToscaElementsRes.isRight()) { - result = Either.right(getToscaElementsRes.right().value()); - } else { - List collection = getToscaElementsRes.left().value(); - if (collection == null) { - componentUids = new ArrayList<>(); - } else { - componentUids = collection.stream().map(p -> p.getUniqueId()).collect(Collectors.toList()); - } - } - if (result == null) { - result = Either.left(componentUids); - } - return result; - } - - private ComponentParametersView buildComponentViewForNotAbstract() { - ComponentParametersView componentParametersView = new ComponentParametersView(); - componentParametersView.disableAll(); - componentParametersView.setIgnoreCategories(false); - componentParametersView.setIgnoreAllVersions(false); - return componentParametersView; - } - - public Either validateComponentNameExists(String name, ResourceTypeEnum resourceType, ComponentTypeEnum componentType) { - Either result = validateComponentNameUniqueness(name, resourceType, componentType); - if (result.isLeft()) { - result = Either.left(!result.left().value()); - } - return result; - } - - public Either validateComponentNameUniqueness(String name, ResourceTypeEnum resourceType, ComponentTypeEnum componentType) { - VertexTypeEnum vertexType = getVertexTypeByComponentAndResourceTypeEnum(resourceType, componentType); - String normalizedName = ValidationUtils.normaliseComponentName(name); - Map properties = new EnumMap<>(GraphPropertyEnum.class); - properties.put(GraphPropertyEnum.NORMALIZED_NAME, normalizedName); - properties.put(GraphPropertyEnum.COMPONENT_TYPE, componentType.name()); - - Either, TitanOperationStatus> vertexEither = titanDao.getByCriteria(vertexType, properties, JsonParseFlagEnum.NoParse); - if (vertexEither.isRight() && vertexEither.right().value() != TitanOperationStatus.NOT_FOUND) { - log.debug("failed to get vertex from graph with property normalizedName: {}", normalizedName); - return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(vertexEither.right().value())); - } - List vertexList = vertexEither.isLeft() ? vertexEither.left().value() : null; - if (vertexList != null && !vertexList.isEmpty()) { - return Either.left(false); - } else { - return Either.left(true); - } - } - - // UI query parameter is either VFC/CP/VL(for yaml upload/update) or VF (for CSAR upload/user composed VF) - // TODO implementation of topology template VFCs may require updating this method - depending on UI implementation - private VertexTypeEnum getVertexTypeByComponentAndResourceTypeEnum(ResourceTypeEnum resourceType, ComponentTypeEnum componentType) { - VertexTypeEnum vertexType = VertexTypeEnum.TOPOLOGY_TEMPLATE; - if (ComponentTypeEnum.RESOURCE == componentType && ResourceTypeEnum.VF != resourceType) { - vertexType = VertexTypeEnum.NODE_TYPE; - } - return vertexType; - } - - private void fillNodeTypePropsMap(Map hasProps, Map hasNotProps, String internalComponentType) { - switch (internalComponentType.toLowerCase()) { - case "vf": - hasNotProps.put(GraphPropertyEnum.RESOURCE_TYPE, ResourceTypeEnum.VF.name()); - hasNotProps.put(GraphPropertyEnum.RESOURCE_TYPE, ResourceTypeEnum.VFCMT.name()); - break; - case "service": - hasNotProps.put(GraphPropertyEnum.RESOURCE_TYPE, ResourceTypeEnum.VFC.name()); - hasNotProps.put(GraphPropertyEnum.RESOURCE_TYPE, ResourceTypeEnum.VFCMT.name()); - break; - case "vl": - hasProps.put(GraphPropertyEnum.RESOURCE_TYPE, ResourceTypeEnum.VL.name()); - break; - default: - break; - } - } - - private void fillTopologyTemplatePropsMap(Map hasProps, ComponentTypeEnum componentTypeEnum) { - switch (componentTypeEnum) { - case RESOURCE: - hasProps.put(GraphPropertyEnum.COMPONENT_TYPE, ComponentTypeEnum.RESOURCE.name()); - break; - case SERVICE: - hasProps.put(GraphPropertyEnum.COMPONENT_TYPE, ComponentTypeEnum.SERVICE.name()); - break; - default: - break; - } - } - - private void fillPropsMap(Map hasProps, Map hasNotProps, String internalComponentType, ComponentTypeEnum componentTypeEnum, boolean isAbstract, VertexTypeEnum internalVertexType) { - hasNotProps.put(GraphPropertyEnum.STATE, LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT.name()); - - hasNotProps.put(GraphPropertyEnum.IS_DELETED, true); - hasProps.put(GraphPropertyEnum.IS_HIGHEST_VERSION, true); - if (VertexTypeEnum.NODE_TYPE == internalVertexType) { - hasProps.put(GraphPropertyEnum.IS_ABSTRACT, isAbstract); - if (internalComponentType != null) { - fillNodeTypePropsMap(hasProps, hasNotProps, internalComponentType); - } - } else { - fillTopologyTemplatePropsMap(hasProps, componentTypeEnum); - } - } - - private List getInternalVertexTypes(ComponentTypeEnum componentTypeEnum, String internalComponentType) { - List internalVertexTypes = new ArrayList<>(); - if (ComponentTypeEnum.RESOURCE == componentTypeEnum) { - internalVertexTypes.add(VertexTypeEnum.NODE_TYPE); - } - if (ComponentTypeEnum.SERVICE == componentTypeEnum || "service".equalsIgnoreCase(internalComponentType)) { - internalVertexTypes.add(VertexTypeEnum.TOPOLOGY_TEMPLATE); - } - return internalVertexTypes; - } - - public Either, StorageOperationStatus> getLatestVersionNotAbstractMetadataOnly(boolean isAbstract, Boolean isHighest, ComponentTypeEnum componentTypeEnum, String internalComponentType) { - List internalVertexTypes = getInternalVertexTypes(componentTypeEnum, internalComponentType); - List result = new ArrayList<>(); - for (VertexTypeEnum vertexType : internalVertexTypes) { - Either, StorageOperationStatus> listByVertexType = getLatestVersionNotAbstractToscaElementsMetadataOnly(isAbstract, isHighest, componentTypeEnum, internalComponentType, vertexType); - if (listByVertexType.isRight()) { - return listByVertexType; - } - result.addAll(listByVertexType.left().value()); - } - return Either.left(result); - - } - - public Either, StorageOperationStatus> getLatestComponentListByUuid(String componentUuid) { - Map propertiesToMatch = new EnumMap<>(GraphPropertyEnum.class); - propertiesToMatch.put(GraphPropertyEnum.IS_HIGHEST_VERSION, true); - Either, StorageOperationStatus> componentListByUuid = getComponentListByUuid(componentUuid, propertiesToMatch); - return componentListByUuid; - } - - public Either, StorageOperationStatus> getComponentListByUuid(String componentUuid, Map additionalPropertiesToMatch) { - - Map propertiesToMatch = new EnumMap<>(GraphPropertyEnum.class); - - if (additionalPropertiesToMatch != null) { - propertiesToMatch.putAll(additionalPropertiesToMatch); - } - - propertiesToMatch.put(GraphPropertyEnum.UUID, componentUuid); - - Map propertiesNotToMatch = new EnumMap<>(GraphPropertyEnum.class); - propertiesNotToMatch.put(GraphPropertyEnum.IS_DELETED, true); - - Either, TitanOperationStatus> vertexEither = titanDao.getByCriteria(null, propertiesToMatch, propertiesNotToMatch, JsonParseFlagEnum.ParseAll); - - if (vertexEither.isRight()) { - log.debug("Couldn't fetch metadata for component with type {} and uuid {}, error: {}", componentUuid, vertexEither.right().value()); - return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(vertexEither.right().value())); - } - List vertexList = vertexEither.isLeft() ? vertexEither.left().value() : null; - - if (vertexList == null || vertexList.isEmpty()) { - log.debug("Component with uuid {} was not found", componentUuid); - return Either.right(StorageOperationStatus.NOT_FOUND); - } - - ArrayList latestComponents = new ArrayList<>(); - for (GraphVertex vertex : vertexList) { - Either toscaElementByOperation = getToscaElementByOperation(vertex); - - if(toscaElementByOperation.isRight()){ - log.debug("Could not fetch the following Component by UUID {}", vertex.getUniqueId()); - return Either.right(toscaElementByOperation.right().value()); - } - - latestComponents.add(toscaElementByOperation.left().value()); - } - - if(latestComponents.size() > 1) { - for (Component component : latestComponents) { - if(component.isHighestVersion()){ - LinkedList highestComponent = new LinkedList<>(); - highestComponent.add(component); - return Either.left(highestComponent); - } - } - } + } - return Either.left(latestComponents); - } - - public Either getLatestComponentByUuid(String componentUuid) { - - Either, StorageOperationStatus> latestVersionListEither = getLatestComponentListByUuid(componentUuid); - - if (latestVersionListEither.isRight()) { - return Either.right(latestVersionListEither.right().value()); - } - - List latestVersionList = latestVersionListEither.left().value(); - - if (latestVersionList.isEmpty()) { - return Either.right(StorageOperationStatus.NOT_FOUND); - } - Component component = latestVersionList.size() == 1 ? latestVersionList.get(0) : latestVersionList.stream().max((c1, c2) -> Double.compare(Double.parseDouble(c1.getVersion()), Double.parseDouble(c2.getVersion()))).get(); - - return Either.left(component); - } - - public Either, StorageOperationStatus> getAllCertifiedResources(boolean isAbstract, Boolean isHighest) { - - List resources = new ArrayList<>(); - Map propertiesToMatch = new EnumMap<>(GraphPropertyEnum.class); - Map propertiesNotToMatch = new EnumMap<>(GraphPropertyEnum.class); - - propertiesToMatch.put(GraphPropertyEnum.IS_ABSTRACT, isAbstract); - if (isHighest != null) { - propertiesToMatch.put(GraphPropertyEnum.IS_HIGHEST_VERSION, isHighest.booleanValue()); - } - propertiesToMatch.put(GraphPropertyEnum.STATE, LifecycleStateEnum.CERTIFIED.name()); - propertiesToMatch.put(GraphPropertyEnum.COMPONENT_TYPE, ComponentTypeEnum.RESOURCE.name()); - propertiesNotToMatch.put(GraphPropertyEnum.IS_DELETED, true); - - Either, TitanOperationStatus> getResourcesRes = titanDao.getByCriteria(null, propertiesToMatch, propertiesNotToMatch, JsonParseFlagEnum.ParseAll); - - if (getResourcesRes.isRight()) { - log.debug("Failed to fetch all certified resources. Status is {}", getResourcesRes.right().value()); - return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(getResourcesRes.right().value())); - } - List resourceVerticies = getResourcesRes.left().value(); - for (GraphVertex resourceV : resourceVerticies) { - Either getResourceRes = getToscaElement(resourceV); - if (getResourceRes.isRight()) { - return Either.right(getResourceRes.right().value()); - } - resources.add(getResourceRes.left().value()); - } - return Either.left(resources); - } - - public Either getLatestByNameAndVersion(String name, String version, JsonParseFlagEnum parseFlag) { - Either result; - - Map hasProperties = new EnumMap<>(GraphPropertyEnum.class); - Map hasNotProperties = new EnumMap<>(GraphPropertyEnum.class); - - hasProperties.put(GraphPropertyEnum.NAME, name); - hasProperties.put(GraphPropertyEnum.VERSION, version); - hasProperties.put(GraphPropertyEnum.IS_HIGHEST_VERSION, true); - - hasNotProperties.put(GraphPropertyEnum.IS_DELETED, true); - - Either, TitanOperationStatus> getResourceRes = titanDao.getByCriteria(null, hasProperties, hasNotProperties, parseFlag); - if (getResourceRes.isRight()) { - TitanOperationStatus status = getResourceRes.right().value(); - log.debug("failed to find resource with name {}, version {}. Status is {} ", name, version, status); - result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status)); - return result; - } - return getToscaElementByOperation(getResourceRes.left().value().get(0)); - } - - public Either getLatestComponentByCsarOrName(ComponentTypeEnum componentType, String csarUUID, String systemName) { - return getLatestComponentByCsarOrName(componentType, csarUUID, systemName, false, JsonParseFlagEnum.ParseAll); - } - - public Either getLatestComponentByCsarOrName(ComponentTypeEnum componentType, String csarUUID, String systemName, boolean allowDeleted, JsonParseFlagEnum parseFlag) { - Map props = new EnumMap<>(GraphPropertyEnum.class); - props.put(GraphPropertyEnum.CSAR_UUID, csarUUID); - props.put(GraphPropertyEnum.IS_HIGHEST_VERSION, true); - if (componentType != null) { - props.put(GraphPropertyEnum.COMPONENT_TYPE, componentType.name()); - } - Map propsHasNot = new EnumMap<>(GraphPropertyEnum.class); - propsHasNot.put(GraphPropertyEnum.IS_DELETED, true); - - GraphVertex resourceMetadataData = null; - List resourceMetadataDataList = null; - Either, TitanOperationStatus> byCsar = titanDao.getByCriteria(null, props, propsHasNot, JsonParseFlagEnum.ParseMetadata); - if (byCsar.isRight()) { - if (TitanOperationStatus.NOT_FOUND == byCsar.right().value()) { - // Fix Defect DE256036 - if (StringUtils.isEmpty(systemName)) { - return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(TitanOperationStatus.NOT_FOUND)); - } - - props.clear(); - props.put(GraphPropertyEnum.IS_HIGHEST_VERSION, true); - props.put(GraphPropertyEnum.SYSTEM_NAME, systemName); - Either, TitanOperationStatus> bySystemname = titanDao.getByCriteria(null, props, JsonParseFlagEnum.ParseMetadata); - if (bySystemname.isRight()) { - log.debug("getLatestResourceByCsarOrName - Failed to find by system name {} error {} ", systemName, bySystemname.right().value()); - return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(bySystemname.right().value())); - } - if (bySystemname.left().value().size() > 2) { - log.debug("getLatestResourceByCsarOrName - getByCriteria(by system name) must return only 2 latest version, but was returned - {}", bySystemname.left().value().size()); - return Either.right(StorageOperationStatus.GENERAL_ERROR); - } - resourceMetadataDataList = bySystemname.left().value(); - if (resourceMetadataDataList.size() == 1) { - resourceMetadataData = resourceMetadataDataList.get(0); - } else { - for (GraphVertex curResource : resourceMetadataDataList) { - if (!((String) curResource.getJsonMetadataField(JsonPresentationFields.LIFECYCLE_STATE)).equals("CERTIFIED")) { - resourceMetadataData = curResource; - break; - } - } - } - if (resourceMetadataData == null) { - log.debug("getLatestResourceByCsarOrName - getByCriteria(by system name) returned 2 latest CERTIFIED versions"); - return Either.right(StorageOperationStatus.GENERAL_ERROR); - } - if (resourceMetadataData.getJsonMetadataField(JsonPresentationFields.CSAR_UUID) != null && !((String) resourceMetadataData.getJsonMetadataField(JsonPresentationFields.CSAR_UUID)).equals(csarUUID)) { - log.debug("getLatestResourceByCsarOrName - same system name {} but different csarUUID. exist {} and new {} ", systemName, resourceMetadataData.getJsonMetadataField(JsonPresentationFields.CSAR_UUID), csarUUID); - // correct error will be returned from create flow. with all - // correct audit records!!!!! - return Either.right(StorageOperationStatus.NOT_FOUND); - } - Either resource = getToscaElement((String) resourceMetadataData.getUniqueId()); - return resource; - } - } else { - resourceMetadataDataList = byCsar.left().value(); - if (resourceMetadataDataList.size() > 2) { - log.debug("getLatestResourceByCsarOrName - getByCriteria(by csar) must return only 2 latest version, but was returned - {}", byCsar.left().value().size()); - return Either.right(StorageOperationStatus.GENERAL_ERROR); - } - if (resourceMetadataDataList.size() == 1) { - resourceMetadataData = resourceMetadataDataList.get(0); - } else { - for (GraphVertex curResource : resourceMetadataDataList) { - if (!((String) curResource.getJsonMetadataField(JsonPresentationFields.LIFECYCLE_STATE)).equals("CERTIFIED")) { - resourceMetadataData = curResource; - break; - } - } - } - if (resourceMetadataData == null) { - log.debug("getLatestResourceByCsarOrName - getByCriteria(by csar) returned 2 latest CERTIFIED versions"); - return Either.right(StorageOperationStatus.GENERAL_ERROR); - } - Either resource = getToscaElement((String) resourceMetadataData.getJsonMetadataField(JsonPresentationFields.UNIQUE_ID), parseFlag); - return resource; - } - return null; - } - - public Either validateToscaResourceNameExtends(String templateNameCurrent, String templateNameExtends) { - - String currentTemplateNameChecked = templateNameExtends; - - while (currentTemplateNameChecked != null && !currentTemplateNameChecked.equalsIgnoreCase(templateNameCurrent)) { - Either latestByToscaResourceName = getLatestByToscaResourceName(currentTemplateNameChecked); - - if (latestByToscaResourceName.isRight()) { - return latestByToscaResourceName.right().value() == StorageOperationStatus.NOT_FOUND ? Either.left(false) : Either.right(latestByToscaResourceName.right().value()); - } - - Resource value = latestByToscaResourceName.left().value(); - - if (value.getDerivedFrom() != null) { - currentTemplateNameChecked = value.getDerivedFrom().get(0); - } else { - currentTemplateNameChecked = null; - } - } - - return (currentTemplateNameChecked != null && currentTemplateNameChecked.equalsIgnoreCase(templateNameCurrent)) ? Either.left(true) : Either.left(false); - } - - public Either, StorageOperationStatus> fetchByResourceType(String resourceType) { - - Map props = new EnumMap<>(GraphPropertyEnum.class); - props.put(GraphPropertyEnum.RESOURCE_TYPE, resourceType); - props.put(GraphPropertyEnum.IS_HIGHEST_VERSION, true); - Either, TitanOperationStatus> resourcesByTypeEither = titanDao.getByCriteria(null, props); - - if (resourcesByTypeEither.isRight()) { - return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(resourcesByTypeEither.right().value())); - } - - List vertexList = resourcesByTypeEither.left().value(); - List components = new ArrayList<>(); - - for (GraphVertex vertex : vertexList) { - components.add(getToscaElementByOperation(vertex).left().value()); - } - - return Either.left(components); - - } - - public void commit() { - titanDao.commit(); - } - - public Either updateDistributionStatus(Service service, User user, DistributionStatusEnum distributionStatus) { - Either updateDistributionStatus = topologyTemplateOperation.updateDistributionStatus(service.getUniqueId(), user, distributionStatus); - if (updateDistributionStatus.isRight()) { - return Either.right(updateDistributionStatus.right().value()); - } - GraphVertex serviceV = updateDistributionStatus.left().value(); - service.setDistributionStatus(distributionStatus); - service.setLastUpdateDate((Long) serviceV.getJsonMetadataField(JsonPresentationFields.LAST_UPDATE_DATE)); - return Either.left(service); - } - - public Either updateComponentLastUpdateDateOnGraph(Component component, Long modificationTime) { - - Either result = null; - GraphVertex serviceVertex; - Either updateRes = null; - Either getRes = titanDao.getVertexById(component.getUniqueId(), JsonParseFlagEnum.ParseMetadata); - if (getRes.isRight()) { - TitanOperationStatus status = getRes.right().value(); - log.error("Failed to fetch component {}. status is {}", component.getUniqueId(), status); - result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status)); - } - if (result == null) { - serviceVertex = getRes.left().value(); - long lastUpdateDate = System.currentTimeMillis(); - serviceVertex.setJsonMetadataField(JsonPresentationFields.LAST_UPDATE_DATE, lastUpdateDate); - component.setLastUpdateDate(lastUpdateDate); - updateRes = titanDao.updateVertex(serviceVertex); - if (updateRes.isRight()) { - result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(updateRes.right().value())); - } - } - if (result == null) { - result = Either.left(ModelConverter.convertToComponentMetadata(updateRes.left().value())); - } - return result; - } - - public TitanDao getTitanDao() { - return titanDao; - } - - public Either, StorageOperationStatus> getCertifiedServicesWithDistStatus(Set distStatus) { - Map propertiesToMatch = new EnumMap<>(GraphPropertyEnum.class); - propertiesToMatch.put(GraphPropertyEnum.STATE, LifecycleStateEnum.CERTIFIED.name()); - - return getServicesWithDistStatus(distStatus, propertiesToMatch); - } - - public Either, StorageOperationStatus> getServicesWithDistStatus(Set distStatus, Map additionalPropertiesToMatch) { - - List servicesAll = new ArrayList<>(); - - Map propertiesToMatch = new EnumMap<>(GraphPropertyEnum.class); - Map propertiesNotToMatch = new EnumMap<>(GraphPropertyEnum.class); - - if (additionalPropertiesToMatch != null && !additionalPropertiesToMatch.isEmpty()) { - propertiesToMatch.putAll(additionalPropertiesToMatch); - } - - propertiesToMatch.put(GraphPropertyEnum.COMPONENT_TYPE, ComponentTypeEnum.SERVICE.name()); - - propertiesNotToMatch.put(GraphPropertyEnum.IS_DELETED, true); - - if (distStatus != null && !distStatus.isEmpty()) { - for (DistributionStatusEnum state : distStatus) { - propertiesToMatch.put(GraphPropertyEnum.DISTRIBUTION_STATUS, state.name()); - Either, StorageOperationStatus> fetchServicesByCriteria = fetchServicesByCriteria(servicesAll, propertiesToMatch, propertiesNotToMatch); - if (fetchServicesByCriteria.isRight()) { - return fetchServicesByCriteria; - } else { - servicesAll = fetchServicesByCriteria.left().value(); - } - } - return Either.left(servicesAll); - } else { - return fetchServicesByCriteria(servicesAll, propertiesToMatch, propertiesNotToMatch); - } - } - - // private Either, StorageOperationStatus> fetchServicesByCriteria(List servicesAll, Map propertiesToMatch, Map propertiesNotToMatch) { - // Either, TitanOperationStatus> getRes = titanDao.getByCriteria(VertexTypeEnum.TOPOLOGY_TEMPLATE, propertiesToMatch, propertiesNotToMatch, JsonParseFlagEnum.ParseAll); - // if (getRes.isRight()) { - // if (getRes.right().value() != TitanOperationStatus.NOT_FOUND) { - // CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to fetch certified services by match properties {} not match properties {} . Status is {}. ", propertiesToMatch, propertiesNotToMatch, getRes.right().value()); - // return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(getRes.right().value())); - // } - // } else { - // for (GraphVertex vertex : getRes.left().value()) { - // Either getServiceRes = getToscaElementByOperation(vertex); - // if (getServiceRes.isRight()) { - // CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to fetch certified service {}. Status is {}. ", vertex.getJsonMetadataField(JsonPresentationFields.NAME), getServiceRes.right().value()); - // return Either.right(getServiceRes.right().value()); - // } else { - // servicesAll.add((Service) getToscaElementByOperation(vertex).left().value()); - // } - // } - // } - // return Either.left(servicesAll); - // } - - private Either, StorageOperationStatus> fetchServicesByCriteria(List servicesAll, Map propertiesToMatch, Map propertiesNotToMatch) { - Either, TitanOperationStatus> getRes = titanDao.getByCriteria(VertexTypeEnum.TOPOLOGY_TEMPLATE, propertiesToMatch, propertiesNotToMatch, JsonParseFlagEnum.ParseAll); - if (getRes.isRight()) { - if (getRes.right().value() != TitanOperationStatus.NOT_FOUND) { - CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to fetch certified services by match properties {} not match properties {} . Status is {}. ", propertiesToMatch, propertiesNotToMatch, getRes.right().value()); - return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(getRes.right().value())); - } - } else { - for (GraphVertex vertex : getRes.left().value()) { - // Either getServiceRes = getToscaElementByOperation(vertex); - Either getServiceRes = topologyTemplateOperation.getLightComponent(vertex, ComponentTypeEnum.SERVICE, new ComponentParametersView(true)); - - if (getServiceRes.isRight()) { - CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to fetch certified service {}. Status is {}. ", vertex.getJsonMetadataField(JsonPresentationFields.NAME), getServiceRes.right().value()); - return Either.right(getServiceRes.right().value()); - } else { - servicesAll.add(ModelConverter.convertFromToscaElement(getServiceRes.left().value())); - } - } - } - return Either.left(servicesAll); - } - - public void rollback() { - titanDao.rollback(); - } - - public StorageOperationStatus addDeploymentArtifactsToInstance(String componentId, ComponentInstance componentInstance, Map finalDeploymentArtifacts) { - Map instDeplArtifacts = finalDeploymentArtifacts.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> new ArtifactDataDefinition(e.getValue()))); - - return nodeTemplateOperation.addDeploymentArtifactsToInstance(componentId, componentInstance.getUniqueId(), instDeplArtifacts); - } - - public StorageOperationStatus generateCustomizationUUIDOnInstance(String componentId, String instanceId) { - return nodeTemplateOperation.generateCustomizationUUIDOnInstance(componentId, instanceId); - } - - public StorageOperationStatus generateCustomizationUUIDOnInstanceGroup(String componentId, String instanceId, List groupInstances) { - return nodeTemplateOperation.generateCustomizationUUIDOnInstanceGroup(componentId, instanceId, groupInstances); - } - - public Either addPropertyToResource(String propertyName, PropertyDefinition newPropertyDefinition, Resource resource) { - - Either result = null; - Either getUpdatedComponentRes = null; - newPropertyDefinition.setName(propertyName); - newPropertyDefinition.setParentUniqueId(resource.getUniqueId()); - StorageOperationStatus status = getToscaElementOperation(resource).addToscaDataToToscaElement(resource.getUniqueId(), EdgeLabelEnum.PROPERTIES, VertexTypeEnum.PROPERTIES, newPropertyDefinition, JsonPresentationFields.NAME); - if (status != StorageOperationStatus.OK) { - CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to add the property {} to the resource {}. Status is {}. ", propertyName, resource.getName(), status); - result = Either.right(status); - } - if (result == null) { - ComponentParametersView filter = new ComponentParametersView(true); - filter.setIgnoreProperties(false); - getUpdatedComponentRes = getToscaElement(resource.getUniqueId(), filter); - if (getUpdatedComponentRes.isRight()) { - CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to get updated resource {}. Status is {}. ", resource.getUniqueId(), getUpdatedComponentRes.right().value()); - result = Either.right(status); - } - } - if (result == null) { - PropertyDefinition newProperty = null; - List properties = ((Resource) getUpdatedComponentRes.left().value()).getProperties(); - if (CollectionUtils.isNotEmpty(properties)) { - Optional newPropertyOptional = properties.stream().filter(p -> p.getName().equals(propertyName)).findAny(); - if (newPropertyOptional.isPresent()) { - newProperty = newPropertyOptional.get(); - } - } - if (newProperty == null) { - CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to find recently added property {} on the resource {}. Status is {}. ", propertyName, resource.getUniqueId(), StorageOperationStatus.NOT_FOUND); - result = Either.right(StorageOperationStatus.NOT_FOUND); - } else { - result = Either.left(newProperty); - } - } - return result; - } - - public StorageOperationStatus deletePropertyOfResource(Resource resource, String propertyName) { - return getToscaElementOperation(resource).deleteToscaDataElement(resource.getUniqueId(), EdgeLabelEnum.PROPERTIES, VertexTypeEnum.PROPERTIES, propertyName, JsonPresentationFields.NAME); - } - - public StorageOperationStatus deleteAttributeOfResource(Component component, String attributeName) { - return getToscaElementOperation(component).deleteToscaDataElement(component.getUniqueId(), EdgeLabelEnum.ATTRIBUTES, VertexTypeEnum.ATTRIBUTES, attributeName, JsonPresentationFields.NAME); - } - - public StorageOperationStatus deleteInputOfResource(Component resource, String inputName) { - return getToscaElementOperation(resource).deleteToscaDataElement(resource.getUniqueId(), EdgeLabelEnum.INPUTS, VertexTypeEnum.INPUTS, inputName, JsonPresentationFields.NAME); - } - - public Either updatePropertyOfResource(Resource resource, PropertyDefinition newPropertyDefinition) { - - Either getUpdatedComponentRes = null; - Either result = null; - StorageOperationStatus status = getToscaElementOperation(resource).updateToscaDataOfToscaElement(resource.getUniqueId(), EdgeLabelEnum.PROPERTIES, VertexTypeEnum.PROPERTIES, newPropertyDefinition, JsonPresentationFields.NAME); - if (status != StorageOperationStatus.OK) { - CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to add the property {} to the resource {}. Status is {}. ", newPropertyDefinition.getName(), resource.getName(), status); - result = Either.right(status); - } - if (result == null) { - ComponentParametersView filter = new ComponentParametersView(true); - filter.setIgnoreProperties(false); - getUpdatedComponentRes = getToscaElement(resource.getUniqueId(), filter); - if (getUpdatedComponentRes.isRight()) { - CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to get updated resource {}. Status is {}. ", resource.getUniqueId(), getUpdatedComponentRes.right().value()); - result = Either.right(status); - } - } - if (result == null) { - Optional newProperty = ((Resource) getUpdatedComponentRes.left().value()).getProperties().stream().filter(p -> p.getName().equals(newPropertyDefinition.getName())).findAny(); - if (newProperty.isPresent()) { - result = Either.left(newProperty.get()); - } else { - CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to find recently added property {} on the resource {}. Status is {}. ", newPropertyDefinition.getName(), resource.getUniqueId(), StorageOperationStatus.NOT_FOUND); - result = Either.right(StorageOperationStatus.NOT_FOUND); - } - } - return result; - } - - public Either addAttributeOfResource(Component component, PropertyDefinition newAttributeDef) { - - Either getUpdatedComponentRes = null; - Either result = null; - if (newAttributeDef.getUniqueId() == null || newAttributeDef.getUniqueId().isEmpty()) { - String attUniqueId = UniqueIdBuilder.buildAttributeUid(component.getUniqueId(), newAttributeDef.getName()); - newAttributeDef.setUniqueId(attUniqueId); - } - - StorageOperationStatus status = getToscaElementOperation(component).addToscaDataToToscaElement(component.getUniqueId(), EdgeLabelEnum.ATTRIBUTES, VertexTypeEnum.ATTRIBUTES, newAttributeDef, JsonPresentationFields.NAME); - if (status != StorageOperationStatus.OK) { - CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to add the property {} to the resource {}. Status is {}. ", newAttributeDef.getName(), component.getName(), status); - result = Either.right(status); - } - if (result == null) { - ComponentParametersView filter = new ComponentParametersView(true); - filter.setIgnoreAttributesFrom(false); - getUpdatedComponentRes = getToscaElement(component.getUniqueId(), filter); - if (getUpdatedComponentRes.isRight()) { - CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to get updated resource {}. Status is {}. ", component.getUniqueId(), getUpdatedComponentRes.right().value()); - result = Either.right(status); - } - } - if (result == null) { - Optional newAttribute = ((Resource) getUpdatedComponentRes.left().value()).getAttributes().stream().filter(p -> p.getName().equals(newAttributeDef.getName())).findAny(); - if (newAttribute.isPresent()) { - result = Either.left(newAttribute.get()); - } else { - CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to find recently added property {} on the resource {}. Status is {}. ", newAttributeDef.getName(), component.getUniqueId(), StorageOperationStatus.NOT_FOUND); - result = Either.right(StorageOperationStatus.NOT_FOUND); - } - } - return result; - } - - public Either updateAttributeOfResource(Component component, PropertyDefinition newAttributeDef) { - - Either getUpdatedComponentRes = null; - Either result = null; - StorageOperationStatus status = getToscaElementOperation(component).updateToscaDataOfToscaElement(component.getUniqueId(), EdgeLabelEnum.ATTRIBUTES, VertexTypeEnum.ATTRIBUTES, newAttributeDef, JsonPresentationFields.NAME); - if (status != StorageOperationStatus.OK) { - CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to add the property {} to the resource {}. Status is {}. ", newAttributeDef.getName(), component.getName(), status); - result = Either.right(status); - } - if (result == null) { - ComponentParametersView filter = new ComponentParametersView(true); - filter.setIgnoreAttributesFrom(false); - getUpdatedComponentRes = getToscaElement(component.getUniqueId(), filter); - if (getUpdatedComponentRes.isRight()) { - CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to get updated resource {}. Status is {}. ", component.getUniqueId(), getUpdatedComponentRes.right().value()); - result = Either.right(status); - } - } - if (result == null) { - Optional newProperty = ((Resource) getUpdatedComponentRes.left().value()).getAttributes().stream().filter(p -> p.getName().equals(newAttributeDef.getName())).findAny(); - if (newProperty.isPresent()) { - result = Either.left(newProperty.get()); - } else { - CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to find recently added property {} on the resource {}. Status is {}. ", newAttributeDef.getName(), component.getUniqueId(), StorageOperationStatus.NOT_FOUND); - result = Either.right(StorageOperationStatus.NOT_FOUND); - } - } - return result; - } - - public Either updateInputOfComponent(Component component, InputDefinition newInputDefinition) { - - Either getUpdatedComponentRes = null; - Either result = null; - StorageOperationStatus status = getToscaElementOperation(component).updateToscaDataOfToscaElement(component.getUniqueId(), EdgeLabelEnum.INPUTS, VertexTypeEnum.INPUTS, newInputDefinition, JsonPresentationFields.NAME); - if (status != StorageOperationStatus.OK) { - CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to update the input {} to the component {}. Status is {}. ", newInputDefinition.getName(), component.getName(), status); - result = Either.right(status); - } - if (result == null) { - ComponentParametersView filter = new ComponentParametersView(true); - filter.setIgnoreInputs(false); - getUpdatedComponentRes = getToscaElement(component.getUniqueId(), filter); - if (getUpdatedComponentRes.isRight()) { - CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to get updated resource {}. Status is {}. ", component.getUniqueId(), getUpdatedComponentRes.right().value()); - result = Either.right(status); - } - } - if (result == null) { - Optional updatedInput = getUpdatedComponentRes.left().value().getInputs().stream().filter(p -> p.getName().equals(newInputDefinition.getName())).findAny(); - if (updatedInput.isPresent()) { - result = Either.left(updatedInput.get()); - } else { - CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to find recently updated inputs {} on the resource {}. Status is {}. ", newInputDefinition.getName(), component.getUniqueId(), StorageOperationStatus.NOT_FOUND); - result = Either.right(StorageOperationStatus.NOT_FOUND); - } - } - return result; - } - - public StorageOperationStatus addGroupInstancesToComponentInstance(Component containerComponent, ComponentInstance componentInstance, List groups, Map> groupInstancesArtifacts) { - return nodeTemplateOperation.addGroupInstancesToComponentInstance(containerComponent, componentInstance, groups, groupInstancesArtifacts); - } - - public Either, StorageOperationStatus> updateGroupsOnComponent(Component component, ComponentTypeEnum componentType, List updatedGroups) { - return groupsOperation.updateGroups(component, componentType, updatedGroups); - } - - public Either, StorageOperationStatus> updateGroupInstancesOnComponent(Component component, ComponentTypeEnum componentType, String instanceId, List updatedGroupInstances) { - return groupsOperation.updateGroupInstances(component, componentType, instanceId, updatedGroupInstances); - } - - public StorageOperationStatus addGroupInstancesToComponentInstance(Component containerComponent, ComponentInstance componentInstance, List groupInstances) { - return nodeTemplateOperation.addGroupInstancesToComponentInstance(containerComponent, componentInstance, groupInstances); - } - - public StorageOperationStatus addDeploymentArtifactsToComponentInstance(Component containerComponent, ComponentInstance componentInstance, Map deploymentArtifacts) { - return nodeTemplateOperation.addDeploymentArtifactsToComponentInstance(containerComponent, componentInstance, deploymentArtifacts); - } - - public StorageOperationStatus updateComponentInstanceProperty(Component containerComponent, String componentInstanceId, ComponentInstanceProperty property) { - return nodeTemplateOperation.updateComponentInstanceProperty(containerComponent, componentInstanceId, property); - } - - public StorageOperationStatus addComponentInstanceProperty(Component containerComponent, String componentInstanceId, ComponentInstanceProperty property) { - return nodeTemplateOperation.addComponentInstanceProperty(containerComponent, componentInstanceId, property); - } - - public StorageOperationStatus updateComponentInstanceInput(Component containerComponent, String componentInstanceId, ComponentInstanceInput property) { - return nodeTemplateOperation.updateComponentInstanceInput(containerComponent, componentInstanceId, property); - } - - public StorageOperationStatus addComponentInstanceInput(Component containerComponent, String componentInstanceId, ComponentInstanceInput property) { - return nodeTemplateOperation.addComponentInstanceInput(containerComponent, componentInstanceId, property); - } - - public void setNodeTypeOperation(NodeTypeOperation nodeTypeOperation) { - this.nodeTypeOperation = nodeTypeOperation; - } - - public void setTopologyTemplateOperation(TopologyTemplateOperation topologyTemplateOperation) { - this.topologyTemplateOperation = topologyTemplateOperation; + return Either.left(latestComponents); + } + + public Either getLatestComponentByUuid(String componentUuid) { + + Either, StorageOperationStatus> latestVersionListEither = getLatestComponentListByUuid(componentUuid); + + if (latestVersionListEither.isRight()) { + return Either.right(latestVersionListEither.right().value()); + } + + List latestVersionList = latestVersionListEither.left().value(); + + if (latestVersionList.isEmpty()) { + return Either.right(StorageOperationStatus.NOT_FOUND); + } + Component component = latestVersionList.size() == 1 ? latestVersionList.get(0) : latestVersionList.stream().max((c1, c2) -> Double.compare(Double.parseDouble(c1.getVersion()), Double.parseDouble(c2.getVersion()))).get(); + + return Either.left(component); + } + + public Either, StorageOperationStatus> getAllCertifiedResources(boolean isAbstract, Boolean isHighest) { + + List resources = new ArrayList<>(); + Map propertiesToMatch = new EnumMap<>(GraphPropertyEnum.class); + Map propertiesNotToMatch = new EnumMap<>(GraphPropertyEnum.class); + + propertiesToMatch.put(GraphPropertyEnum.IS_ABSTRACT, isAbstract); + if (isHighest != null) { + propertiesToMatch.put(GraphPropertyEnum.IS_HIGHEST_VERSION, isHighest.booleanValue()); + } + propertiesToMatch.put(GraphPropertyEnum.STATE, LifecycleStateEnum.CERTIFIED.name()); + propertiesToMatch.put(GraphPropertyEnum.COMPONENT_TYPE, ComponentTypeEnum.RESOURCE.name()); + propertiesNotToMatch.put(GraphPropertyEnum.IS_DELETED, true); + + Either, TitanOperationStatus> getResourcesRes = titanDao.getByCriteria(null, propertiesToMatch, propertiesNotToMatch, JsonParseFlagEnum.ParseAll); + + if (getResourcesRes.isRight()) { + log.debug("Failed to fetch all certified resources. Status is {}", getResourcesRes.right().value()); + return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(getResourcesRes.right().value())); + } + List resourceVerticies = getResourcesRes.left().value(); + for (GraphVertex resourceV : resourceVerticies) { + Either getResourceRes = getToscaElement(resourceV); + if (getResourceRes.isRight()) { + return Either.right(getResourceRes.right().value()); + } + resources.add(getResourceRes.left().value()); + } + return Either.left(resources); + } + + public Either getLatestByNameAndVersion(String name, String version, JsonParseFlagEnum parseFlag) { + Either result; + + Map hasProperties = new EnumMap<>(GraphPropertyEnum.class); + Map hasNotProperties = new EnumMap<>(GraphPropertyEnum.class); + + hasProperties.put(GraphPropertyEnum.NAME, name); + hasProperties.put(GraphPropertyEnum.VERSION, version); + hasProperties.put(GraphPropertyEnum.IS_HIGHEST_VERSION, true); + + hasNotProperties.put(GraphPropertyEnum.IS_DELETED, true); + + Either, TitanOperationStatus> getResourceRes = titanDao.getByCriteria(null, hasProperties, hasNotProperties, parseFlag); + if (getResourceRes.isRight()) { + TitanOperationStatus status = getResourceRes.right().value(); + log.debug("failed to find resource with name {}, version {}. Status is {} ", name, version, status); + result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status)); + return result; + } + return getToscaElementByOperation(getResourceRes.left().value().get(0)); + } + + public Either getLatestComponentByCsarOrName(ComponentTypeEnum componentType, String csarUUID, String systemName) { + return getLatestComponentByCsarOrName(componentType, csarUUID, systemName, false, JsonParseFlagEnum.ParseAll); + } + + public Either getLatestComponentByCsarOrName(ComponentTypeEnum componentType, String csarUUID, String systemName, boolean allowDeleted, JsonParseFlagEnum parseFlag) { + Map props = new EnumMap<>(GraphPropertyEnum.class); + props.put(GraphPropertyEnum.CSAR_UUID, csarUUID); + props.put(GraphPropertyEnum.IS_HIGHEST_VERSION, true); + if (componentType != null) { + props.put(GraphPropertyEnum.COMPONENT_TYPE, componentType.name()); + } + Map propsHasNot = new EnumMap<>(GraphPropertyEnum.class); + propsHasNot.put(GraphPropertyEnum.IS_DELETED, true); + + GraphVertex resourceMetadataData = null; + List resourceMetadataDataList = null; + Either, TitanOperationStatus> byCsar = titanDao.getByCriteria(null, props, propsHasNot, JsonParseFlagEnum.ParseMetadata); + if (byCsar.isRight()) { + if (TitanOperationStatus.NOT_FOUND == byCsar.right().value()) { + // Fix Defect DE256036 + if (StringUtils.isEmpty(systemName)) { + return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(TitanOperationStatus.NOT_FOUND)); + } + + props.clear(); + props.put(GraphPropertyEnum.IS_HIGHEST_VERSION, true); + props.put(GraphPropertyEnum.SYSTEM_NAME, systemName); + Either, TitanOperationStatus> bySystemname = titanDao.getByCriteria(null, props, JsonParseFlagEnum.ParseMetadata); + if (bySystemname.isRight()) { + log.debug("getLatestResourceByCsarOrName - Failed to find by system name {} error {} ", systemName, bySystemname.right().value()); + return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(bySystemname.right().value())); + } + if (bySystemname.left().value().size() > 2) { + log.debug("getLatestResourceByCsarOrName - getByCriteria(by system name) must return only 2 latest version, but was returned - {}", bySystemname.left().value().size()); + return Either.right(StorageOperationStatus.GENERAL_ERROR); + } + resourceMetadataDataList = bySystemname.left().value(); + if (resourceMetadataDataList.size() == 1) { + resourceMetadataData = resourceMetadataDataList.get(0); + } else { + for (GraphVertex curResource : resourceMetadataDataList) { + if (!((String) curResource.getJsonMetadataField(JsonPresentationFields.LIFECYCLE_STATE)).equals("CERTIFIED")) { + resourceMetadataData = curResource; + break; + } + } + } + if (resourceMetadataData == null) { + log.debug("getLatestResourceByCsarOrName - getByCriteria(by system name) returned 2 latest CERTIFIED versions"); + return Either.right(StorageOperationStatus.GENERAL_ERROR); + } + if (resourceMetadataData.getJsonMetadataField(JsonPresentationFields.CSAR_UUID) != null && !((String) resourceMetadataData.getJsonMetadataField(JsonPresentationFields.CSAR_UUID)).equals(csarUUID)) { + log.debug("getLatestResourceByCsarOrName - same system name {} but different csarUUID. exist {} and new {} ", systemName, resourceMetadataData.getJsonMetadataField(JsonPresentationFields.CSAR_UUID), csarUUID); + // correct error will be returned from create flow. with all + // correct audit records!!!!! + return Either.right(StorageOperationStatus.NOT_FOUND); + } + Either resource = getToscaElement((String) resourceMetadataData.getUniqueId()); + return resource; + } + } else { + resourceMetadataDataList = byCsar.left().value(); + if (resourceMetadataDataList.size() > 2) { + log.debug("getLatestResourceByCsarOrName - getByCriteria(by csar) must return only 2 latest version, but was returned - {}", byCsar.left().value().size()); + return Either.right(StorageOperationStatus.GENERAL_ERROR); + } + if (resourceMetadataDataList.size() == 1) { + resourceMetadataData = resourceMetadataDataList.get(0); + } else { + for (GraphVertex curResource : resourceMetadataDataList) { + if (!((String) curResource.getJsonMetadataField(JsonPresentationFields.LIFECYCLE_STATE)).equals("CERTIFIED")) { + resourceMetadataData = curResource; + break; + } + } + } + if (resourceMetadataData == null) { + log.debug("getLatestResourceByCsarOrName - getByCriteria(by csar) returned 2 latest CERTIFIED versions"); + return Either.right(StorageOperationStatus.GENERAL_ERROR); + } + Either resource = getToscaElement((String) resourceMetadataData.getJsonMetadataField(JsonPresentationFields.UNIQUE_ID), parseFlag); + return resource; + } + return null; + } + + public Either validateToscaResourceNameExtends(String templateNameCurrent, String templateNameExtends) { + + String currentTemplateNameChecked = templateNameExtends; + + while (currentTemplateNameChecked != null && !currentTemplateNameChecked.equalsIgnoreCase(templateNameCurrent)) { + Either latestByToscaResourceName = getLatestByToscaResourceName(currentTemplateNameChecked); + + if (latestByToscaResourceName.isRight()) { + return latestByToscaResourceName.right().value() == StorageOperationStatus.NOT_FOUND ? Either.left(false) : Either.right(latestByToscaResourceName.right().value()); + } + + Resource value = latestByToscaResourceName.left().value(); + + if (value.getDerivedFrom() != null) { + currentTemplateNameChecked = value.getDerivedFrom().get(0); + } else { + currentTemplateNameChecked = null; + } + } + + return (currentTemplateNameChecked != null && currentTemplateNameChecked.equalsIgnoreCase(templateNameCurrent)) ? Either.left(true) : Either.left(false); + } + + public Either, StorageOperationStatus> fetchByResourceType(String resourceType) { + + Map props = new EnumMap<>(GraphPropertyEnum.class); + props.put(GraphPropertyEnum.RESOURCE_TYPE, resourceType); + props.put(GraphPropertyEnum.IS_HIGHEST_VERSION, true); + Either, TitanOperationStatus> resourcesByTypeEither = titanDao.getByCriteria(null, props); + + if (resourcesByTypeEither.isRight()) { + return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(resourcesByTypeEither.right().value())); + } + + List vertexList = resourcesByTypeEither.left().value(); + List components = new ArrayList<>(); + + for (GraphVertex vertex : vertexList) { + components.add(getToscaElementByOperation(vertex).left().value()); + } + + return Either.left(components); + + } + + public void commit() { + titanDao.commit(); + } + + public Either updateDistributionStatus(Service service, User user, DistributionStatusEnum distributionStatus) { + Either updateDistributionStatus = topologyTemplateOperation.updateDistributionStatus(service.getUniqueId(), user, distributionStatus); + if (updateDistributionStatus.isRight()) { + return Either.right(updateDistributionStatus.right().value()); + } + GraphVertex serviceV = updateDistributionStatus.left().value(); + service.setDistributionStatus(distributionStatus); + service.setLastUpdateDate((Long) serviceV.getJsonMetadataField(JsonPresentationFields.LAST_UPDATE_DATE)); + return Either.left(service); + } + + public Either updateComponentLastUpdateDateOnGraph(Component component, Long modificationTime) { + + Either result = null; + GraphVertex serviceVertex; + Either updateRes = null; + Either getRes = titanDao.getVertexById(component.getUniqueId(), JsonParseFlagEnum.ParseMetadata); + if (getRes.isRight()) { + TitanOperationStatus status = getRes.right().value(); + log.error("Failed to fetch component {}. status is {}", component.getUniqueId(), status); + result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status)); + } + if (result == null) { + serviceVertex = getRes.left().value(); + long lastUpdateDate = System.currentTimeMillis(); + serviceVertex.setJsonMetadataField(JsonPresentationFields.LAST_UPDATE_DATE, lastUpdateDate); + component.setLastUpdateDate(lastUpdateDate); + updateRes = titanDao.updateVertex(serviceVertex); + if (updateRes.isRight()) { + result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(updateRes.right().value())); + } + } + if (result == null) { + result = Either.left(ModelConverter.convertToComponentMetadata(updateRes.left().value())); + } + return result; + } + + public TitanDao getTitanDao() { + return titanDao; + } + + public Either, StorageOperationStatus> getCertifiedServicesWithDistStatus(Set distStatus) { + Map propertiesToMatch = new EnumMap<>(GraphPropertyEnum.class); + propertiesToMatch.put(GraphPropertyEnum.STATE, LifecycleStateEnum.CERTIFIED.name()); + + return getServicesWithDistStatus(distStatus, propertiesToMatch); + } + + public Either, StorageOperationStatus> getServicesWithDistStatus(Set distStatus, Map additionalPropertiesToMatch) { + + List servicesAll = new ArrayList<>(); + + Map propertiesToMatch = new EnumMap<>(GraphPropertyEnum.class); + Map propertiesNotToMatch = new EnumMap<>(GraphPropertyEnum.class); + + if (additionalPropertiesToMatch != null && !additionalPropertiesToMatch.isEmpty()) { + propertiesToMatch.putAll(additionalPropertiesToMatch); + } + + propertiesToMatch.put(GraphPropertyEnum.COMPONENT_TYPE, ComponentTypeEnum.SERVICE.name()); + + propertiesNotToMatch.put(GraphPropertyEnum.IS_DELETED, true); + + if (distStatus != null && !distStatus.isEmpty()) { + for (DistributionStatusEnum state : distStatus) { + propertiesToMatch.put(GraphPropertyEnum.DISTRIBUTION_STATUS, state.name()); + Either, StorageOperationStatus> fetchServicesByCriteria = fetchServicesByCriteria(servicesAll, propertiesToMatch, propertiesNotToMatch); + if (fetchServicesByCriteria.isRight()) { + return fetchServicesByCriteria; + } else { + servicesAll = fetchServicesByCriteria.left().value(); + } + } + return Either.left(servicesAll); + } else { + return fetchServicesByCriteria(servicesAll, propertiesToMatch, propertiesNotToMatch); + } + } + + // private Either, StorageOperationStatus> fetchServicesByCriteria(List servicesAll, Map propertiesToMatch, Map propertiesNotToMatch) { + // Either, TitanOperationStatus> getRes = titanDao.getByCriteria(VertexTypeEnum.TOPOLOGY_TEMPLATE, propertiesToMatch, propertiesNotToMatch, JsonParseFlagEnum.ParseAll); + // if (getRes.isRight()) { + // if (getRes.right().value() != TitanOperationStatus.NOT_FOUND) { + // CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to fetch certified services by match properties {} not match properties {} . Status is {}. ", propertiesToMatch, propertiesNotToMatch, getRes.right().value()); + // return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(getRes.right().value())); + // } + // } else { + // for (GraphVertex vertex : getRes.left().value()) { + // Either getServiceRes = getToscaElementByOperation(vertex); + // if (getServiceRes.isRight()) { + // CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to fetch certified service {}. Status is {}. ", vertex.getJsonMetadataField(JsonPresentationFields.NAME), getServiceRes.right().value()); + // return Either.right(getServiceRes.right().value()); + // } else { + // servicesAll.add((Service) getToscaElementByOperation(vertex).left().value()); + // } + // } + // } + // return Either.left(servicesAll); + // } + + private Either, StorageOperationStatus> fetchServicesByCriteria(List servicesAll, Map propertiesToMatch, Map propertiesNotToMatch) { + Either, TitanOperationStatus> getRes = titanDao.getByCriteria(VertexTypeEnum.TOPOLOGY_TEMPLATE, propertiesToMatch, propertiesNotToMatch, JsonParseFlagEnum.ParseAll); + if (getRes.isRight()) { + if (getRes.right().value() != TitanOperationStatus.NOT_FOUND) { + CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to fetch certified services by match properties {} not match properties {} . Status is {}. ", propertiesToMatch, propertiesNotToMatch, getRes.right().value()); + return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(getRes.right().value())); + } + } else { + for (GraphVertex vertex : getRes.left().value()) { + // Either getServiceRes = getToscaElementByOperation(vertex); + Either getServiceRes = topologyTemplateOperation.getLightComponent(vertex, ComponentTypeEnum.SERVICE, new ComponentParametersView(true)); + + if (getServiceRes.isRight()) { + CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to fetch certified service {}. Status is {}. ", vertex.getJsonMetadataField(JsonPresentationFields.NAME), getServiceRes.right().value()); + return Either.right(getServiceRes.right().value()); + } else { + servicesAll.add(ModelConverter.convertFromToscaElement(getServiceRes.left().value())); + } + } + } + return Either.left(servicesAll); + } + + public void rollback() { + titanDao.rollback(); + } + + public StorageOperationStatus addDeploymentArtifactsToInstance(String componentId, ComponentInstance componentInstance, Map finalDeploymentArtifacts) { + Map instDeplArtifacts = finalDeploymentArtifacts.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> new ArtifactDataDefinition(e.getValue()))); + + return nodeTemplateOperation.addDeploymentArtifactsToInstance(componentId, componentInstance.getUniqueId(), instDeplArtifacts); + } + + public StorageOperationStatus generateCustomizationUUIDOnInstance(String componentId, String instanceId) { + return nodeTemplateOperation.generateCustomizationUUIDOnInstance(componentId, instanceId); + } + + public StorageOperationStatus generateCustomizationUUIDOnInstanceGroup(String componentId, String instanceId, List groupInstances) { + return nodeTemplateOperation.generateCustomizationUUIDOnInstanceGroup(componentId, instanceId, groupInstances); + } + + public Either addPropertyToResource(String propertyName, PropertyDefinition newPropertyDefinition, Resource resource) { + + Either result = null; + Either getUpdatedComponentRes = null; + newPropertyDefinition.setName(propertyName); + newPropertyDefinition.setParentUniqueId(resource.getUniqueId()); + StorageOperationStatus status = getToscaElementOperation(resource).addToscaDataToToscaElement(resource.getUniqueId(), EdgeLabelEnum.PROPERTIES, VertexTypeEnum.PROPERTIES, newPropertyDefinition, JsonPresentationFields.NAME); + if (status != StorageOperationStatus.OK) { + CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to add the property {} to the resource {}. Status is {}. ", propertyName, resource.getName(), status); + result = Either.right(status); + } + if (result == null) { + ComponentParametersView filter = new ComponentParametersView(true); + filter.setIgnoreProperties(false); + getUpdatedComponentRes = getToscaElement(resource.getUniqueId(), filter); + if (getUpdatedComponentRes.isRight()) { + CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to get updated resource {}. Status is {}. ", resource.getUniqueId(), getUpdatedComponentRes.right().value()); + result = Either.right(status); + } + } + if (result == null) { + PropertyDefinition newProperty = null; + List properties = ((Resource) getUpdatedComponentRes.left().value()).getProperties(); + if (CollectionUtils.isNotEmpty(properties)) { + Optional newPropertyOptional = properties.stream().filter(p -> p.getName().equals(propertyName)).findAny(); + if (newPropertyOptional.isPresent()) { + newProperty = newPropertyOptional.get(); + } + } + if (newProperty == null) { + CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to find recently added property {} on the resource {}. Status is {}. ", propertyName, resource.getUniqueId(), StorageOperationStatus.NOT_FOUND); + result = Either.right(StorageOperationStatus.NOT_FOUND); + } else { + result = Either.left(newProperty); + } + } + return result; + } + + public StorageOperationStatus deletePropertyOfResource(Resource resource, String propertyName) { + return getToscaElementOperation(resource).deleteToscaDataElement(resource.getUniqueId(), EdgeLabelEnum.PROPERTIES, VertexTypeEnum.PROPERTIES, propertyName, JsonPresentationFields.NAME); + } + + public StorageOperationStatus deleteAttributeOfResource(Component component, String attributeName) { + return getToscaElementOperation(component).deleteToscaDataElement(component.getUniqueId(), EdgeLabelEnum.ATTRIBUTES, VertexTypeEnum.ATTRIBUTES, attributeName, JsonPresentationFields.NAME); + } + + public StorageOperationStatus deleteInputOfResource(Component resource, String inputName) { + return getToscaElementOperation(resource).deleteToscaDataElement(resource.getUniqueId(), EdgeLabelEnum.INPUTS, VertexTypeEnum.INPUTS, inputName, JsonPresentationFields.NAME); + } + + public Either updatePropertyOfResource(Resource resource, PropertyDefinition newPropertyDefinition) { + + Either getUpdatedComponentRes = null; + Either result = null; + StorageOperationStatus status = getToscaElementOperation(resource).updateToscaDataOfToscaElement(resource.getUniqueId(), EdgeLabelEnum.PROPERTIES, VertexTypeEnum.PROPERTIES, newPropertyDefinition, JsonPresentationFields.NAME); + if (status != StorageOperationStatus.OK) { + CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to add the property {} to the resource {}. Status is {}. ", newPropertyDefinition.getName(), resource.getName(), status); + result = Either.right(status); + } + if (result == null) { + ComponentParametersView filter = new ComponentParametersView(true); + filter.setIgnoreProperties(false); + getUpdatedComponentRes = getToscaElement(resource.getUniqueId(), filter); + if (getUpdatedComponentRes.isRight()) { + CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to get updated resource {}. Status is {}. ", resource.getUniqueId(), getUpdatedComponentRes.right().value()); + result = Either.right(status); + } + } + if (result == null) { + Optional newProperty = ((Resource) getUpdatedComponentRes.left().value()).getProperties().stream().filter(p -> p.getName().equals(newPropertyDefinition.getName())).findAny(); + if (newProperty.isPresent()) { + result = Either.left(newProperty.get()); + } else { + CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to find recently added property {} on the resource {}. Status is {}. ", newPropertyDefinition.getName(), resource.getUniqueId(), StorageOperationStatus.NOT_FOUND); + result = Either.right(StorageOperationStatus.NOT_FOUND); + } + } + return result; + } + + public Either addAttributeOfResource(Component component, PropertyDefinition newAttributeDef) { + + Either getUpdatedComponentRes = null; + Either result = null; + if (newAttributeDef.getUniqueId() == null || newAttributeDef.getUniqueId().isEmpty()) { + String attUniqueId = UniqueIdBuilder.buildAttributeUid(component.getUniqueId(), newAttributeDef.getName()); + newAttributeDef.setUniqueId(attUniqueId); + } + + StorageOperationStatus status = getToscaElementOperation(component).addToscaDataToToscaElement(component.getUniqueId(), EdgeLabelEnum.ATTRIBUTES, VertexTypeEnum.ATTRIBUTES, newAttributeDef, JsonPresentationFields.NAME); + if (status != StorageOperationStatus.OK) { + CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to add the property {} to the resource {}. Status is {}. ", newAttributeDef.getName(), component.getName(), status); + result = Either.right(status); + } + if (result == null) { + ComponentParametersView filter = new ComponentParametersView(true); + filter.setIgnoreAttributesFrom(false); + getUpdatedComponentRes = getToscaElement(component.getUniqueId(), filter); + if (getUpdatedComponentRes.isRight()) { + CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to get updated resource {}. Status is {}. ", component.getUniqueId(), getUpdatedComponentRes.right().value()); + result = Either.right(status); + } + } + if (result == null) { + Optional newAttribute = ((Resource) getUpdatedComponentRes.left().value()).getAttributes().stream().filter(p -> p.getName().equals(newAttributeDef.getName())).findAny(); + if (newAttribute.isPresent()) { + result = Either.left(newAttribute.get()); + } else { + CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to find recently added property {} on the resource {}. Status is {}. ", newAttributeDef.getName(), component.getUniqueId(), StorageOperationStatus.NOT_FOUND); + result = Either.right(StorageOperationStatus.NOT_FOUND); + } + } + return result; + } + + public Either updateAttributeOfResource(Component component, PropertyDefinition newAttributeDef) { + + Either getUpdatedComponentRes = null; + Either result = null; + StorageOperationStatus status = getToscaElementOperation(component).updateToscaDataOfToscaElement(component.getUniqueId(), EdgeLabelEnum.ATTRIBUTES, VertexTypeEnum.ATTRIBUTES, newAttributeDef, JsonPresentationFields.NAME); + if (status != StorageOperationStatus.OK) { + CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to add the property {} to the resource {}. Status is {}. ", newAttributeDef.getName(), component.getName(), status); + result = Either.right(status); + } + if (result == null) { + ComponentParametersView filter = new ComponentParametersView(true); + filter.setIgnoreAttributesFrom(false); + getUpdatedComponentRes = getToscaElement(component.getUniqueId(), filter); + if (getUpdatedComponentRes.isRight()) { + CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to get updated resource {}. Status is {}. ", component.getUniqueId(), getUpdatedComponentRes.right().value()); + result = Either.right(status); + } + } + if (result == null) { + Optional newProperty = ((Resource) getUpdatedComponentRes.left().value()).getAttributes().stream().filter(p -> p.getName().equals(newAttributeDef.getName())).findAny(); + if (newProperty.isPresent()) { + result = Either.left(newProperty.get()); + } else { + CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to find recently added property {} on the resource {}. Status is {}. ", newAttributeDef.getName(), component.getUniqueId(), StorageOperationStatus.NOT_FOUND); + result = Either.right(StorageOperationStatus.NOT_FOUND); + } + } + return result; + } + + public Either updateInputOfComponent(Component component, InputDefinition newInputDefinition) { + + Either getUpdatedComponentRes = null; + Either result = null; + StorageOperationStatus status = getToscaElementOperation(component).updateToscaDataOfToscaElement(component.getUniqueId(), EdgeLabelEnum.INPUTS, VertexTypeEnum.INPUTS, newInputDefinition, JsonPresentationFields.NAME); + if (status != StorageOperationStatus.OK) { + CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to update the input {} to the component {}. Status is {}. ", newInputDefinition.getName(), component.getName(), status); + result = Either.right(status); + } + if (result == null) { + ComponentParametersView filter = new ComponentParametersView(true); + filter.setIgnoreInputs(false); + getUpdatedComponentRes = getToscaElement(component.getUniqueId(), filter); + if (getUpdatedComponentRes.isRight()) { + CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to get updated resource {}. Status is {}. ", component.getUniqueId(), getUpdatedComponentRes.right().value()); + result = Either.right(status); + } + } + if (result == null) { + Optional updatedInput = getUpdatedComponentRes.left().value().getInputs().stream().filter(p -> p.getName().equals(newInputDefinition.getName())).findAny(); + if (updatedInput.isPresent()) { + result = Either.left(updatedInput.get()); + } else { + CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to find recently updated inputs {} on the resource {}. Status is {}. ", newInputDefinition.getName(), component.getUniqueId(), StorageOperationStatus.NOT_FOUND); + result = Either.right(StorageOperationStatus.NOT_FOUND); + } + } + return result; + } + + /** + * method - ename the group instances after referenced container name renamed + * flow - VF rename -(triggers)-> Group rename + * + * @param containerComponent - container such as service + * @param componentInstance - context component + * @param componentInstanceId - id + * + * @return - successfull/failed status + * **/ + public Either cleanAndAddGroupInstancesToComponentInstance(Component containerComponent, ComponentInstance componentInstance, String componentInstanceId){ + String uniqueId = componentInstance.getUniqueId(); + StorageOperationStatus status = nodeTemplateOperation.deleteToscaDataDeepElementsBlockToToscaElement( containerComponent.getUniqueId(), EdgeLabelEnum.INST_GROUPS, VertexTypeEnum.INST_GROUPS, uniqueId ); + if (status != StorageOperationStatus.OK && status != StorageOperationStatus.NOT_FOUND) { + CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to delete group instances for container {}. error {] ", componentInstanceId, status); + return Either.right(status); + } + status = addGroupInstancesToComponentInstance( containerComponent , componentInstance, componentInstance.getGroupInstances() ); + if (status != StorageOperationStatus.OK && status != StorageOperationStatus.NOT_FOUND) { + CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to add group instances for container {}. error {] ", componentInstanceId, status); + return Either.right(status); + } + return Either.left(status); + } + + public StorageOperationStatus addGroupInstancesToComponentInstance(Component containerComponent, ComponentInstance componentInstance, List groups, Map> groupInstancesArtifacts) { + return nodeTemplateOperation.addGroupInstancesToComponentInstance(containerComponent, componentInstance, groups, groupInstancesArtifacts); + } + + public Either, StorageOperationStatus> updateGroupsOnComponent(Component component, ComponentTypeEnum componentType, List updatedGroups) { + return groupsOperation.updateGroups(component, componentType, updatedGroups); + } + + public Either, StorageOperationStatus> updateGroupInstancesOnComponent(Component component, ComponentTypeEnum componentType, String instanceId, List updatedGroupInstances) { + return groupsOperation.updateGroupInstances(component, componentType, instanceId, updatedGroupInstances); + } + + public StorageOperationStatus addGroupInstancesToComponentInstance(Component containerComponent, ComponentInstance componentInstance, List groupInstances) { + return nodeTemplateOperation.addGroupInstancesToComponentInstance(containerComponent, componentInstance, groupInstances); + } + + public StorageOperationStatus addDeploymentArtifactsToComponentInstance(Component containerComponent, ComponentInstance componentInstance, Map deploymentArtifacts) { + return nodeTemplateOperation.addDeploymentArtifactsToComponentInstance(containerComponent, componentInstance, deploymentArtifacts); + } + + public StorageOperationStatus updateComponentInstanceProperty(Component containerComponent, String componentInstanceId, ComponentInstanceProperty property) { + return nodeTemplateOperation.updateComponentInstanceProperty(containerComponent, componentInstanceId, property); + } + + public StorageOperationStatus addComponentInstanceProperty(Component containerComponent, String componentInstanceId, ComponentInstanceProperty property) { + return nodeTemplateOperation.addComponentInstanceProperty(containerComponent, componentInstanceId, property); + } + + public StorageOperationStatus updateComponentInstanceInput(Component containerComponent, String componentInstanceId, ComponentInstanceInput property) { + return nodeTemplateOperation.updateComponentInstanceInput(containerComponent, componentInstanceId, property); + } + + public StorageOperationStatus addComponentInstanceInput(Component containerComponent, String componentInstanceId, ComponentInstanceInput property) { + return nodeTemplateOperation.addComponentInstanceInput(containerComponent, componentInstanceId, property); + } + + public void setNodeTypeOperation(NodeTypeOperation nodeTypeOperation) { + this.nodeTypeOperation = nodeTypeOperation; + } + + public void setTopologyTemplateOperation(TopologyTemplateOperation topologyTemplateOperation) { + this.topologyTemplateOperation = topologyTemplateOperation; + } + + public StorageOperationStatus deleteComponentInstanceInputsFromTopologyTemplate(Component containerComponent, ComponentTypeEnum componentType, List inputsToDelete) { + return topologyTemplateOperation.deleteToscaDataElements(containerComponent.getUniqueId(), EdgeLabelEnum.INPUTS, inputsToDelete.stream().map(i -> i.getName()).collect(Collectors.toList())); } } diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/utils/ModelConverter.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/utils/ModelConverter.java index 0ac5a8dbe4..03a5f41d55 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/utils/ModelConverter.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/utils/ModelConverter.java @@ -117,8 +117,8 @@ public class ModelConverter { return vertexType; } - private static boolean isAtomicComponent(ResourceTypeEnum resourceType) { - if (resourceType == null || resourceType == ResourceTypeEnum.VF) + public static boolean isAtomicComponent(ResourceTypeEnum resourceType) { + if (resourceType == null || resourceType == ResourceTypeEnum.VF || resourceType == ResourceTypeEnum.PNF || resourceType == ResourceTypeEnum.CVFC) return false; return true; } @@ -302,7 +302,7 @@ public class ModelConverter { relationshipPair.setId(relation.getUniqueId()); relationshipPair.setCapabilityOwnerId(relation.getCapabilityOwnerId()); - relationshipPair.setCapabilityUid(relation.getCapabiltyId()); + relationshipPair.setCapabilityUid(relation.getCapabilityId()); relationshipPair.setRequirementOwnerId(relation.getRequirementOwnerId()); relationshipPair.setRequirementUid(relation.getRequirementId()); relationshipPair.setRequirement(relation.getRequirement()); @@ -326,7 +326,7 @@ public class ModelConverter { requirementCapabilityRelDef.setToId(relation.getToNode()); requirementCapabilityRelDef.setUniqueId(p.getId()); requirementCapabilityRelDef.setCapabilityOwnerId(p.getCapabilityOwnerId()); - requirementCapabilityRelDef.setCapabiltyId(p.getCapabilityUid()); + requirementCapabilityRelDef.setCapabilityId(p.getCapabilityUid()); requirementCapabilityRelDef.setRequirementOwnerId(p.getRequirementOwnerId()); requirementCapabilityRelDef.setRequirementId(p.getRequirementUid()); requirementCapabilityRelDef.setRequirement(p.getRequirement()); @@ -518,6 +518,24 @@ public class ModelConverter { resource.setToscaResourceName((String) toscaElement.getMetadataValue(JsonPresentationFields.TOSCA_RESOURCE_NAME)); resource.setVendorName((String) toscaElement.getMetadataValue(JsonPresentationFields.VENDOR_NAME)); resource.setVendorRelease((String) toscaElement.getMetadataValue(JsonPresentationFields.VENDOR_RELEASE)); + // field isn't mandatory , but shouldn't be null(should be an empty string instead) + if (((String) toscaElement.getMetadataValue(JsonPresentationFields.RESOURCE_VENDOR_MODEL_NUMBER)) != null){ + resource.setResourceVendorModelNumber(((String) toscaElement.getMetadataValue(JsonPresentationFields.RESOURCE_VENDOR_MODEL_NUMBER))); + } else { + resource.setResourceVendorModelNumber(""); + } + } else if (component.getComponentType() == ComponentTypeEnum.SERVICE) { + Service service = (Service) component; + if (((String) toscaElement.getMetadataValue(JsonPresentationFields.SERVICE_TYPE)) != null){ + service.setServiceType(((String) toscaElement.getMetadataValue(JsonPresentationFields.SERVICE_TYPE))); + } else { + service.setServiceType(""); + } + if (((String) toscaElement.getMetadataValue(JsonPresentationFields.SERVICE_ROLE)) != null){ + service.setServiceRole(((String) toscaElement.getMetadataValue(JsonPresentationFields.SERVICE_ROLE))); + } else { + service.setServiceRole(""); + } } component.setConformanceLevel((String) toscaElement.getMetadataValue(JsonPresentationFields.CONFORMANCE_LEVEL)); component.setIcon((String) toscaElement.getMetadataValue(JsonPresentationFields.ICON)); @@ -945,6 +963,24 @@ public class ModelConverter { toscaElement.setMetadataValue(JsonPresentationFields.TOSCA_RESOURCE_NAME, ((Resource) component).getToscaResourceName()); toscaElement.setMetadataValue(JsonPresentationFields.VENDOR_NAME, ((Resource) component).getVendorName()); toscaElement.setMetadataValue(JsonPresentationFields.VENDOR_RELEASE, ((Resource) component).getVendorRelease()); + // field isn't mandatory , but shouldn't be null(should be an empty string instead) + if (((Resource) component).getResourceVendorModelNumber() != null){ + toscaElement.setMetadataValue(JsonPresentationFields.RESOURCE_VENDOR_MODEL_NUMBER, ((Resource) component).getResourceVendorModelNumber()); + } else { + toscaElement.setMetadataValue(JsonPresentationFields.RESOURCE_VENDOR_MODEL_NUMBER, ""); + } + } else if (component.getComponentType() == ComponentTypeEnum.SERVICE) { + // field isn't mandatory , but shouldn't be null(should be an empty string instead) + if (((Service) component).getServiceType() != null){ + toscaElement.setMetadataValue(JsonPresentationFields.SERVICE_TYPE, ((Service) component).getServiceType()); + } else { + toscaElement.setMetadataValue(JsonPresentationFields.SERVICE_TYPE, ""); + } + if (((Service) component).getServiceRole() != null){ + toscaElement.setMetadataValue(JsonPresentationFields.SERVICE_ROLE, ((Service) component).getServiceRole()); + } else { + toscaElement.setMetadataValue(JsonPresentationFields.SERVICE_ROLE, ""); + } } toscaElement.setMetadataValue(JsonPresentationFields.CONFORMANCE_LEVEL, component.getConformanceLevel()); toscaElement.setMetadataValue(JsonPresentationFields.IS_DELETED, component.getIsDeleted()); @@ -955,7 +991,7 @@ public class ModelConverter { toscaElement.setMetadataValue(JsonPresentationFields.CONTACT_ID, component.getContactId()); } - private static boolean isAtomicComponent(Component component) { + public static boolean isAtomicComponent(Component component) { ComponentTypeEnum componentType = component.getComponentType(); if (!componentType.equals(ComponentTypeEnum.RESOURCE)) { return false; diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/api/IServiceOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/api/IServiceOperation.java index f08c52e0fa..51f21ce5b8 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/api/IServiceOperation.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/api/IServiceOperation.java @@ -24,10 +24,7 @@ import java.util.List; import java.util.Map; import java.util.Set; -import org.openecomp.sdc.be.model.DistributionStatusEnum; -import org.openecomp.sdc.be.model.LifecycleStateEnum; -import org.openecomp.sdc.be.model.Service; -import org.openecomp.sdc.be.model.User; +import org.openecomp.sdc.be.model.*; import fj.data.Either; @@ -41,6 +38,8 @@ public interface IServiceOperation extends IComponentOperation { public Either getService(String uniqueId, boolean inTransaction); + public Either getService(String uniqueId, ComponentParametersView componentParametersView, boolean inTransaction); + public Either deleteService(String uniqueId); public Either deleteService(String uniqueId, boolean inTransaction); diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/AbstractOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/AbstractOperation.java index 2847367999..f0e4056663 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/AbstractOperation.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/AbstractOperation.java @@ -39,7 +39,6 @@ import org.openecomp.sdc.be.dao.titan.TitanOperationStatus; import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition; import org.openecomp.sdc.be.datatypes.elements.SchemaDefinition; import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum; -import org.openecomp.sdc.be.model.ComponentInstanceProperty; import org.openecomp.sdc.be.model.DataTypeDefinition; import org.openecomp.sdc.be.model.IComplexDefaultValue; import org.openecomp.sdc.be.model.PropertyConstraint; @@ -50,8 +49,6 @@ import org.openecomp.sdc.be.model.tosca.ToscaPropertyType; import org.openecomp.sdc.be.model.tosca.converters.PropertyValueConverter; import org.openecomp.sdc.be.model.tosca.validators.DataTypeValidatorConverter; import org.openecomp.sdc.be.model.tosca.validators.PropertyTypeValidator; -import org.openecomp.sdc.be.resources.data.CapabilityInstData; -import org.openecomp.sdc.be.resources.data.PropertyValueData; import org.openecomp.sdc.be.resources.data.ResourceMetadataData; import org.openecomp.sdc.be.resources.data.UniqueIdData; import org.slf4j.Logger; @@ -118,6 +115,7 @@ public abstract class AbstractOperation { log.debug("Before adding {} to graph. data = {}", defName, someData); + @SuppressWarnings("unchecked") Either eitherSomeData = titanGenericDao.createNode(someData); log.debug("After adding {} to graph. status is = {}", defName, eitherSomeData); @@ -329,7 +327,7 @@ public abstract class AbstractOperation { value = jsonElement.toString(); } - return value; + return value; } protected Either getInnerType(ToscaPropertyType type, Supplier schemeGen) { @@ -368,7 +366,7 @@ public abstract class AbstractOperation { public List convertConstraints(List constraints) { - if (constraints == null || constraints.size() == 0) { + if (constraints == null || constraints.isEmpty()) { return null; } @@ -378,7 +376,6 @@ public abstract class AbstractOperation { Gson gson = new GsonBuilder().registerTypeAdapter(constraintType, new PropertyConstraintDeserialiser()).create(); return constraints.stream().map(c -> gson.fromJson(c, PropertyConstraint.class)).collect(Collectors.toList()); - } } diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/ComponentInstanceOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/ComponentInstanceOperation.java index 43e4d0683b..cb9adeda3f 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/ComponentInstanceOperation.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/ComponentInstanceOperation.java @@ -710,6 +710,13 @@ public class ComponentInstanceOperation extends AbstractOperation implements ICo case VL: componentInstanceData.getComponentInstDataDefinition().setOriginType(OriginTypeEnum.VL); break; + case CVFC: + componentInstanceData.getComponentInstDataDefinition().setOriginType(OriginTypeEnum.CVFC); + break; + case PNF: + componentInstanceData.getComponentInstDataDefinition().setOriginType(OriginTypeEnum.PNF); + break; + } break; default: diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/ComponentOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/ComponentOperation.java index e06649bf77..9d9814efcb 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/ComponentOperation.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/ComponentOperation.java @@ -1963,6 +1963,7 @@ public abstract class ComponentOperation { case "service": properties.add(new ImmutableTriple<>(QueryType.HAS_NOT, GraphPropertiesDictionary.RESOURCE_TYPE.getProperty(), ResourceTypeEnum.VFC.name())); properties.add(new ImmutableTriple<>(QueryType.HAS_NOT, GraphPropertiesDictionary.RESOURCE_TYPE.getProperty(), ResourceTypeEnum.VFCMT.name())); + properties.add(new ImmutableTriple<>(QueryType.HAS_NOT, GraphPropertiesDictionary.RESOURCE_TYPE.getProperty(), ResourceTypeEnum.CVFC.name())); // properties.add(new ImmutableTriple<>(QueryType.HAS_NOT, GraphPropertiesDictionary.RESOURCE_TYPE.getProperty(), ResourceTypeEnum.VL.name())); // hasNotPpropertiesToMatch.put(GraphPropertiesDictionary.RESOURCE_TYPE.getProperty(), // ResourceTypeEnum.VFC.name()); diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/GroupTypeOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/GroupTypeOperation.java index f9057217a6..413ce4c2fa 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/GroupTypeOperation.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/GroupTypeOperation.java @@ -155,7 +155,6 @@ public class GroupTypeOperation extends AbstractOperation implements IGroupTypeO @Override public Either getGroupType(String uniqueId, boolean inTransaction) { return getElementType(this::getGroupTypeByUid, uniqueId, inTransaction); - } @Override diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/PolicyTypeOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/PolicyTypeOperation.java index adea89b9ea..70efe12b86 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/PolicyTypeOperation.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/PolicyTypeOperation.java @@ -167,7 +167,6 @@ public class PolicyTypeOperation extends AbstractOperation implements IPolicyTyp @Override public Either getPolicyType(String uniqueId, boolean inTransaction) { return getElementType(this::getPolicyTypeByUid, uniqueId, inTransaction); - } private Either getPolicyTypeByUid(String uniqueId) { diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/converters/ToscaMapValueConverter.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/converters/ToscaMapValueConverter.java index c40c59facf..0673033546 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/converters/ToscaMapValueConverter.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/converters/ToscaMapValueConverter.java @@ -188,6 +188,9 @@ public class ToscaMapValueConverter extends ToscaValueBaseConverter implements T private Object convertDataTypeToToscaMap(String innerType, Map dataTypes, final boolean isScalarF, JsonElement entryValue) { Object convertedValue; + if (entryValue.isJsonPrimitive()) { + return json2JavaPrimitive(entryValue.getAsJsonPrimitive()); + } JsonObject asJsonObjectIn = entryValue.getAsJsonObject(); DataTypeDefinition dataTypeDefinition = dataTypes.get(innerType); diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/validators/HeatStringValidator.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/validators/HeatStringValidator.java index 0e7b7f6648..8c63090e03 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/validators/HeatStringValidator.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/validators/HeatStringValidator.java @@ -44,8 +44,8 @@ public class HeatStringValidator implements PropertyTypeValidator { return true; } - String coverted = ValidationUtils.removeNoneUtf8Chars(value); - return ValidationUtils.validateIsEnglish(coverted); + String converted = ValidationUtils.removeNoneUtf8Chars(value); + return ValidationUtils.validateIsEnglish(converted); } @Override diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/validators/KeyValidator.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/validators/KeyValidator.java index 4b11e26d05..73b5e939ef 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/validators/KeyValidator.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/validators/KeyValidator.java @@ -49,8 +49,8 @@ public class KeyValidator implements PropertyTypeValidator { if (value.length() > STRING_MAXIMUM_LENGTH) { return false; } - String coverted = ValidationUtils.removeNoneUtf8Chars(value); - return ValidationUtils.validateIsEnglish(coverted); + String converted = ValidationUtils.removeNoneUtf8Chars(value); + return ValidationUtils.validateIsEnglish(converted); } @Override diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/validators/StringValidator.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/validators/StringValidator.java index 750941cc0b..a096990ad7 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/validators/StringValidator.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/validators/StringValidator.java @@ -68,8 +68,8 @@ public class StringValidator implements PropertyTypeValidator { log.debug("parameter String length {} is higher than configured({})", value.length(), STRING_MAXIMUM_LENGTH); return false; } - String coverted = ValidationUtils.removeNoneUtf8Chars(value); - boolean isValid = ValidationUtils.validateIsAscii(coverted); + String converted = ValidationUtils.removeNoneUtf8Chars(value); + boolean isValid = ValidationUtils.validateIsAscii(converted); if (false == isValid && log.isDebugEnabled()) { log.debug("parameter String value {} is not an ascii string.", value.substring(0, Math.min(value.length(), 20))); diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/ui/model/UiResourceMetadata.java b/catalog-model/src/main/java/org/openecomp/sdc/be/ui/model/UiResourceMetadata.java index a2695f8c79..68abb4d749 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/ui/model/UiResourceMetadata.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/ui/model/UiResourceMetadata.java @@ -29,6 +29,7 @@ public class UiResourceMetadata extends UiComponentMetadata { private String vendorName; private String vendorRelease; + private String resourceVendorModelNumber; private ResourceTypeEnum resourceType = ResourceTypeEnum.VFC; private Boolean isAbstract; private String cost; @@ -41,6 +42,7 @@ public class UiResourceMetadata extends UiComponentMetadata { super(categories, metadata); this.vendorName = metadata.getVendorName(); this.vendorRelease = metadata.getVendorRelease(); + this.resourceVendorModelNumber = metadata.getResourceVendorModelNumber(); this.resourceType = metadata.getResourceType(); this.cost = metadata.getCost(); this.licenseType = metadata.getLicenseType(); @@ -75,6 +77,14 @@ public class UiResourceMetadata extends UiComponentMetadata { public void setVendorRelease(String vendorRelease) { this.vendorRelease = vendorRelease; } + + public String getResourceVendorModelNumber() { + return resourceVendorModelNumber; + } + + public void setResourceVendorModelNumber(String resourceVendorModelNumber) { + this.resourceVendorModelNumber = resourceVendorModelNumber; + } public ResourceTypeEnum getResourceType() { return resourceType; diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/ui/model/UiServiceMetadata.java b/catalog-model/src/main/java/org/openecomp/sdc/be/ui/model/UiServiceMetadata.java index 99d586afd2..9a79a26881 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/ui/model/UiServiceMetadata.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/ui/model/UiServiceMetadata.java @@ -30,12 +30,16 @@ public class UiServiceMetadata extends UiComponentMetadata { private String distributionStatus; private Boolean ecompGeneratedNaming; private String namingPolicy; + private String serviceType; + private String serviceRole; public UiServiceMetadata(List categories, ServiceMetadataDataDefinition metadata) { super(categories, metadata); this.distributionStatus = metadata.getDistributionStatus(); this.ecompGeneratedNaming = metadata.isEcompGeneratedNaming(); this.namingPolicy = metadata.getNamingPolicy(); + this.serviceType = metadata.getServiceType(); + this.serviceRole = metadata.getServiceRole(); } public String getDistributionStatus() { @@ -61,5 +65,21 @@ public class UiServiceMetadata extends UiComponentMetadata { public void setNamingPolicy(String namingPolicy) { this.namingPolicy = namingPolicy; } + + public String getServiceType() { + return serviceType; + } + + public void setServiceType(String serviceType) { + this.serviceType = serviceType; + } + + public String getServiceRole() { + return serviceRole; + } + + public void setServiceRole(String serviceRole) { + this.serviceRole = serviceRole; + } } diff --git a/catalog-model/src/test/java/org/openecomp/sdc/be/model/jsontitan/operations/ArtifactsOperationsTest.java b/catalog-model/src/test/java/org/openecomp/sdc/be/model/jsontitan/operations/ArtifactsOperationsTest.java new file mode 100644 index 0000000000..3f80806292 --- /dev/null +++ b/catalog-model/src/test/java/org/openecomp/sdc/be/model/jsontitan/operations/ArtifactsOperationsTest.java @@ -0,0 +1,85 @@ +package org.openecomp.sdc.be.model.jsontitan.operations; + +import fj.data.Either; +import org.junit.Test; +import org.openecomp.sdc.be.dao.jsongraph.types.EdgeLabelEnum; +import org.openecomp.sdc.be.dao.titan.TitanOperationStatus; +import org.openecomp.sdc.be.datatypes.elements.ArtifactDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.MapArtifactDataDefinition; +import org.openecomp.sdc.be.datatypes.tosca.ToscaDataDefinition; +import org.openecomp.sdc.be.model.ArtifactDefinition; +import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.*; + +public class ArtifactsOperationsTest { + + private static final String SERVICE_ID = "serviceId"; + private static final String INSTANCE_ID = "instanceId"; + private ArtifactsOperations testInstance = mock(ArtifactsOperations.class, CALLS_REAL_METHODS); + + @Test + public void getInstanceArtifacts_collectAllInstanceArtifacts() throws Exception { + Map instanceArtifacts = Collections.singletonMap(INSTANCE_ID, getArtifactsByInstance("name1")); + + Map instanceDeploymentArtifacts = new HashMap<>(); + instanceDeploymentArtifacts.put(INSTANCE_ID, getArtifactsByInstance("name2", "name3")); + instanceDeploymentArtifacts.put("instanceId2", getArtifactsByInstance("name4")); + + doReturn(Either.left(instanceArtifacts)).when(testInstance).getDataFromGraph(SERVICE_ID, EdgeLabelEnum.INSTANCE_ARTIFACTS); + doReturn(Either.left(instanceDeploymentArtifacts)).when(testInstance).getDataFromGraph(SERVICE_ID, EdgeLabelEnum.INST_DEPLOYMENT_ARTIFACTS); + Either, StorageOperationStatus> allInstArtifacts = testInstance.getAllInstanceArtifacts(SERVICE_ID, INSTANCE_ID); + + assertTrue(allInstArtifacts.isLeft()); + assertEquals(allInstArtifacts.left().value().size(), 3); + assertTrue(allInstArtifacts.left().value().containsKey("name1")); + assertTrue(allInstArtifacts.left().value().containsKey("name2")); + assertTrue(allInstArtifacts.left().value().containsKey("name3")); + assertFalse(allInstArtifacts.left().value().containsKey("name4"));//this key is of different instance + } + + @Test + public void getInstanceArtifacts_noArtifactsForInstance() throws Exception { + Map instanceArtifacts = Collections.singletonMap(INSTANCE_ID, getArtifactsByInstance("name1")); + + doReturn(Either.left(instanceArtifacts)).when(testInstance).getDataFromGraph(SERVICE_ID, EdgeLabelEnum.INSTANCE_ARTIFACTS); + doReturn(Either.left(new HashMap<>())).when(testInstance).getDataFromGraph(SERVICE_ID, EdgeLabelEnum.INST_DEPLOYMENT_ARTIFACTS); + Either, StorageOperationStatus> allInstArtifacts = testInstance.getAllInstanceArtifacts(SERVICE_ID, "someOtherInstance"); + + assertTrue(allInstArtifacts.isLeft()); + assertTrue(allInstArtifacts.left().value().isEmpty()); + } + + @Test + public void getInstanceArtifacts_errorGettingInstanceArtifacts() throws Exception { + doReturn(Either.right(TitanOperationStatus.GENERAL_ERROR)).when(testInstance).getDataFromGraph(SERVICE_ID, EdgeLabelEnum.INSTANCE_ARTIFACTS); + Either, StorageOperationStatus> allInstArtifacts = testInstance.getAllInstanceArtifacts(SERVICE_ID, INSTANCE_ID); + verify(testInstance, times(0)).getDataFromGraph(SERVICE_ID, EdgeLabelEnum.INST_DEPLOYMENT_ARTIFACTS); + assertTrue(allInstArtifacts.isRight()); + } + + @Test + public void getAllInstanceArtifacts_errorGettingDeploymentArtifacts() throws Exception { + doReturn(Either.left(new HashMap<>())).when(testInstance).getDataFromGraph(SERVICE_ID, EdgeLabelEnum.INSTANCE_ARTIFACTS); + doReturn(Either.right(TitanOperationStatus.GENERAL_ERROR)).when(testInstance).getDataFromGraph(SERVICE_ID, EdgeLabelEnum.INST_DEPLOYMENT_ARTIFACTS); + Either, StorageOperationStatus> allInstArtifacts = testInstance.getAllInstanceArtifacts(SERVICE_ID, INSTANCE_ID); + assertTrue(allInstArtifacts.isRight()); + } + + private ToscaDataDefinition getArtifactsByInstance(String ... artifactsNames) { + MapArtifactDataDefinition artifactsByInstance = new MapArtifactDataDefinition(); + Map artifactsByName = new HashMap<>(); + for (String artifactName : artifactsNames) { + artifactsByName.put(artifactName, new ArtifactDataDefinition()); + } + artifactsByInstance.setMapToscaDataDefinition(artifactsByName); + return artifactsByInstance; + } +} diff --git a/catalog-model/src/test/java/org/openecomp/sdc/be/model/jsontitan/operations/ToscaElementOperationTest.java b/catalog-model/src/test/java/org/openecomp/sdc/be/model/jsontitan/operations/ToscaElementOperationTest.java new file mode 100644 index 0000000000..339023f9a4 --- /dev/null +++ b/catalog-model/src/test/java/org/openecomp/sdc/be/model/jsontitan/operations/ToscaElementOperationTest.java @@ -0,0 +1,344 @@ +package org.openecomp.sdc.be.model.jsontitan.operations; + +import fj.data.Either; +import org.apache.cassandra.cql3.CQL3Type; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestName; +import org.junit.runner.RunWith; +import org.openecomp.sdc.be.dao.jsongraph.GraphVertex; +import org.openecomp.sdc.be.dao.jsongraph.TitanDao; +import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; +import org.openecomp.sdc.be.datatypes.enums.GraphPropertyEnum; +import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum; +import org.openecomp.sdc.be.model.LifecycleStateEnum; +import org.openecomp.sdc.be.model.ModelTestBase; +import org.openecomp.sdc.be.model.jsontitan.datamodel.ToscaElement; +import org.openecomp.sdc.be.model.jsontitan.utils.GraphTestUtils; +import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import java.util.*; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +/** + * Created by chaya on 6/12/2017. + */ + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration("classpath:application-context-test.xml") +public class ToscaElementOperationTest extends ModelTestBase{ + + private List allVertices = new ArrayList<>(); + private boolean isInitialized = false; + + @javax.annotation.Resource + ToscaElementOperationTestImpl toscaElementOperation; + + @javax.annotation.Resource + TitanDao titanDao; + + @BeforeClass + public static void initTest(){ + ModelTestBase.init(); + + } + + @Rule + public TestName testName = new TestName(); + + @Before + public void beforeTest() { + if (!isInitialized) { + GraphTestUtils.clearGraph(titanDao); + //exportGraphMl(titanDao.getGraph().left().value(),""); + initGraphForTest(); + isInitialized = true; + } + } + + @Test + public void testGetAllHighestResourcesNoFilter() { + + Either, StorageOperationStatus> highestResourcesRes = toscaElementOperation.getElementCatalogData(ComponentTypeEnum.RESOURCE, null, true); + assertTrue(highestResourcesRes.isLeft()); + List highestResources = highestResourcesRes.left().value(); + // calculate expected count value + long highestResourcesExpectedCount = calculateCount(new HashMap() { + { + put(GraphPropertyEnum.IS_HIGHEST_VERSION, true); + put(GraphPropertyEnum.COMPONENT_TYPE, ComponentTypeEnum.RESOURCE.name()); + } + }, null); + assertEquals(highestResources.stream().count(), highestResourcesExpectedCount); + } + + @Test + public void testGetAllResourcesCertifiedNoFilter() { + Either, StorageOperationStatus> highestResourcesRes = toscaElementOperation.getElementCatalogData(ComponentTypeEnum.RESOURCE, null, false); + assertTrue(highestResourcesRes.isLeft()); + List highestResources = highestResourcesRes.left().value(); + // calculate expected count value + long highestResourcesExpectedCount = calculateCount(new HashMap() { + { + put(GraphPropertyEnum.COMPONENT_TYPE, ComponentTypeEnum.RESOURCE.name()); + put(GraphPropertyEnum.IS_HIGHEST_VERSION, true); + } + }, null); + highestResourcesExpectedCount += calculateCount(new HashMap() { + { + put(GraphPropertyEnum.COMPONENT_TYPE, ComponentTypeEnum.RESOURCE.name()); + put(GraphPropertyEnum.STATE, LifecycleStateEnum.CERTIFIED.name()); + } + }, new HashMap() { + { + put(GraphPropertyEnum.IS_HIGHEST_VERSION, true); + } + }); + assertEquals(highestResources.stream().count(), highestResourcesExpectedCount); + } + + @Test + public void testGetHighestResourcesExclude() { + + // exclude VFCMT + List excludeList = Arrays.asList(ResourceTypeEnum.VFCMT); + assertTrue(genericTestGetResourcesWithExcludeList(excludeList)); + + // exclude CP & VL + excludeList = Arrays.asList(ResourceTypeEnum.VL, ResourceTypeEnum.CP); + assertTrue(genericTestGetResourcesWithExcludeList(excludeList)); + + // exclude CP & VL & VF & VFC + excludeList = Arrays.asList(ResourceTypeEnum.VL, ResourceTypeEnum.CP, ResourceTypeEnum.VF, ResourceTypeEnum.VFC); + assertTrue(genericTestGetResourcesWithExcludeList(excludeList)); + } + + @Test + public void testGetAllResourcesCertifiedExclude() { + // exclude VFCMT + List excludeList = Arrays.asList(ResourceTypeEnum.VFCMT); + assertTrue(genericTestGetCertifiedResourcesWithExcludeList(excludeList)); + + // exclude CP & VL + excludeList = Arrays.asList(ResourceTypeEnum.VL, ResourceTypeEnum.CP); + assertTrue(genericTestGetCertifiedResourcesWithExcludeList(excludeList)); + + // exclude CP & VL & VF & VFC + excludeList = Arrays.asList(ResourceTypeEnum.VL, ResourceTypeEnum.CP, ResourceTypeEnum.VF, ResourceTypeEnum.VFC); + assertTrue(genericTestGetCertifiedResourcesWithExcludeList(excludeList)); + } + + @Test + public void testGetAllHighestServicesNoFilter() { + Either, StorageOperationStatus> highestResourcesRes = toscaElementOperation.getElementCatalogData(ComponentTypeEnum.SERVICE, null, true); + assertTrue(highestResourcesRes.isLeft()); + List highestResources = highestResourcesRes.left().value(); + // calculate expected count value + long highestResourcesExpectedCount = calculateCount(new HashMap() { + { + put(GraphPropertyEnum.IS_HIGHEST_VERSION, true); + put(GraphPropertyEnum.COMPONENT_TYPE, ComponentTypeEnum.SERVICE.name()); + } + }, null); + assertEquals(highestResources.stream().count(), highestResourcesExpectedCount); + } + + @Test + public void testGetAllCertifiedServicesNoFilter() { + Either, StorageOperationStatus> highestResourcesRes = toscaElementOperation.getElementCatalogData(ComponentTypeEnum.SERVICE, null, false); + assertTrue(highestResourcesRes.isLeft()); + List highestResources = highestResourcesRes.left().value(); + // calculate expected count value + long highestResourcesExpectedCount = calculateCount(new HashMap() { + { + put(GraphPropertyEnum.COMPONENT_TYPE, ComponentTypeEnum.SERVICE.name()); + put(GraphPropertyEnum.IS_HIGHEST_VERSION, true); + } + }, null); + highestResourcesExpectedCount += calculateCount(new HashMap() { + { + put(GraphPropertyEnum.COMPONENT_TYPE, ComponentTypeEnum.SERVICE.name()); + put(GraphPropertyEnum.STATE, LifecycleStateEnum.CERTIFIED.name()); + } + }, new HashMap() { + { + put(GraphPropertyEnum.IS_HIGHEST_VERSION, true); + } + }); + assertEquals(highestResources.stream().count(), highestResourcesExpectedCount); + } + + @Test + public void testGetServicesExcludeList() { + List excludeList = Arrays.asList(ResourceTypeEnum.VF, ResourceTypeEnum.VFCMT); + Either, StorageOperationStatus> highestResourcesRes = toscaElementOperation.getElementCatalogData(ComponentTypeEnum.SERVICE, excludeList, true); + assertTrue(highestResourcesRes.isLeft()); + List highestResources = highestResourcesRes.left().value(); + // calculate expected count value + long highestResourcesExpectedCount = calculateCount(new HashMap() { + { + put(GraphPropertyEnum.IS_HIGHEST_VERSION, true); + put(GraphPropertyEnum.COMPONENT_TYPE, ComponentTypeEnum.SERVICE.name()); + } + }, null); + assertEquals(highestResources.stream().count(), highestResourcesExpectedCount); + } + + @Test + public void testGetCertifiedServicesExcludeList() { + List excludeList = Arrays.asList(ResourceTypeEnum.VL); + Either, StorageOperationStatus> highestResourcesRes = toscaElementOperation.getElementCatalogData(ComponentTypeEnum.SERVICE, excludeList, false); + assertTrue(highestResourcesRes.isLeft()); + List highestResources = highestResourcesRes.left().value(); + // calculate expected count value + long highestResourcesExpectedCount = calculateCount(new HashMap() { + { + put(GraphPropertyEnum.COMPONENT_TYPE, ComponentTypeEnum.SERVICE.name()); + put(GraphPropertyEnum.STATE, LifecycleStateEnum.CERTIFIED.name()); + } + }, null); + highestResourcesExpectedCount += calculateCount(new HashMap() { + { + put(GraphPropertyEnum.COMPONENT_TYPE, ComponentTypeEnum.SERVICE.name()); + put(GraphPropertyEnum.IS_HIGHEST_VERSION, true); + } + }, new HashMap() { + { + put(GraphPropertyEnum.STATE, LifecycleStateEnum.CERTIFIED.name()); + } + }); + assertEquals(highestResources.stream().count(), highestResourcesExpectedCount); + } + + private boolean genericTestGetResourcesWithExcludeList(List excludeList) { + Either, StorageOperationStatus> highestResourcesRes = toscaElementOperation.getElementCatalogData(ComponentTypeEnum.RESOURCE,excludeList, true); + assertTrue(highestResourcesRes.isLeft()); + List highestResources = highestResourcesRes.left().value(); + // calculate expected count value + long highestResourcesExpectedCount = calculateCount(new HashMap() { + { + put(GraphPropertyEnum.IS_HIGHEST_VERSION, true); + put(GraphPropertyEnum.COMPONENT_TYPE, ComponentTypeEnum.RESOURCE.name()); + } + }, new HashMap() { + { + put(GraphPropertyEnum.RESOURCE_TYPE, excludeList); + } + }); + return highestResources.stream().count() == (highestResourcesExpectedCount); + } + + private boolean genericTestGetCertifiedResourcesWithExcludeList(List excludeList) { + Either, StorageOperationStatus> highestResourcesRes = toscaElementOperation.getElementCatalogData(ComponentTypeEnum.RESOURCE, excludeList, false); + assertTrue(highestResourcesRes.isLeft()); + List highestResources = highestResourcesRes.left().value(); + // calculate expected count value + long highestResourcesExpectedCount = calculateCount(new HashMap() { + { + put(GraphPropertyEnum.COMPONENT_TYPE, ComponentTypeEnum.RESOURCE.name()); + put(GraphPropertyEnum.IS_HIGHEST_VERSION, true); + } + }, new HashMap() { + { + put(GraphPropertyEnum.RESOURCE_TYPE, excludeList); + } + }); + highestResourcesExpectedCount += calculateCount(new HashMap() { + { + put(GraphPropertyEnum.COMPONENT_TYPE, ComponentTypeEnum.RESOURCE.name()); + put(GraphPropertyEnum.STATE, LifecycleStateEnum.CERTIFIED.name()); + } + }, new HashMap() { + { + put(GraphPropertyEnum.IS_HIGHEST_VERSION, true); + put(GraphPropertyEnum.RESOURCE_TYPE, excludeList); + } + }); + return highestResources.stream().count() == highestResourcesExpectedCount; + } + + private void initGraphForTest() { + Map highstVerticesProps = new HashMap() { + { + put(GraphPropertyEnum.IS_HIGHEST_VERSION, true); + } + }; + + Map certifiedVerticesProps = new HashMap() { + { + put(GraphPropertyEnum.IS_HIGHEST_VERSION, true); + put(GraphPropertyEnum.STATE, LifecycleStateEnum.CERTIFIED.name()); + } + }; + + // add vertices with higestVersion = true + allVertices.add(GraphTestUtils.createResourceVertex(titanDao, highstVerticesProps, ResourceTypeEnum.VF)); + allVertices.add(GraphTestUtils.createResourceVertex(titanDao, highstVerticesProps, ResourceTypeEnum.VFC)); + allVertices.add(GraphTestUtils.createResourceVertex(titanDao, highstVerticesProps, ResourceTypeEnum.VFCMT)); + allVertices.add(GraphTestUtils.createResourceVertex(titanDao, highstVerticesProps, ResourceTypeEnum.VL)); + allVertices.add(GraphTestUtils.createResourceVertex(titanDao, highstVerticesProps, ResourceTypeEnum.CP)); + allVertices.add(GraphTestUtils.createServiceVertex(titanDao, highstVerticesProps)); + + // add vertices with non-additional properties + for (int i=0 ; i<2 ; i++) { + allVertices.add(GraphTestUtils.createResourceVertex(titanDao, new HashMap<>(), ResourceTypeEnum.VF)); + allVertices.add(GraphTestUtils.createResourceVertex(titanDao, new HashMap<>(), ResourceTypeEnum.VFC)); + allVertices.add(GraphTestUtils.createResourceVertex(titanDao, new HashMap<>(), ResourceTypeEnum.VFCMT)); + allVertices.add(GraphTestUtils.createResourceVertex(titanDao, new HashMap<>(), ResourceTypeEnum.VL)); + allVertices.add(GraphTestUtils.createResourceVertex(titanDao, new HashMap<>(), ResourceTypeEnum.CP)); + allVertices.add(GraphTestUtils.createServiceVertex(titanDao, new HashMap<>())); + } + + // add certified vertices + for (int i=0; i<3; i++) { + allVertices.add(GraphTestUtils.createResourceVertex(titanDao, certifiedVerticesProps, ResourceTypeEnum.VF)); + allVertices.add(GraphTestUtils.createResourceVertex(titanDao, certifiedVerticesProps, ResourceTypeEnum.VFC)); + allVertices.add(GraphTestUtils.createResourceVertex(titanDao, certifiedVerticesProps, ResourceTypeEnum.VFCMT)); + allVertices.add(GraphTestUtils.createResourceVertex(titanDao, certifiedVerticesProps, ResourceTypeEnum.VL)); + allVertices.add(GraphTestUtils.createResourceVertex(titanDao, certifiedVerticesProps, ResourceTypeEnum.CP)); + allVertices.add(GraphTestUtils.createServiceVertex(titanDao, certifiedVerticesProps)); + } + //allVertices.stream().forEach( v -> System.out.println("type: "+v.getMetadataProperty(GraphPropertyEnum.COMPONENT_TYPE))); + //String result = GraphTestUtils.exportGraphMl(titanDao.getGraph().left().value(), ""); + //System.out.println("graph is: " + result); + } + + private long calculateCount(HashMap hasProps, Map doesntHaveProps){ + return allVertices.stream(). + filter(v -> { + Map vertexProps = v.getMetadataProperties(); + if (hasProps != null) { + for (Map.Entry prop: hasProps.entrySet()){ + Object value = vertexProps.get(prop.getKey()); + if ( value == null || !value.equals(prop.getValue())) { + return false; + } + } + } + + if (doesntHaveProps != null) { + for (Map.Entry prop : doesntHaveProps.entrySet()) { + Object value = vertexProps.get(prop.getKey()); + Object propValue = prop.getValue(); + if ( value != null && propValue != null && propValue instanceof List ) { + for (ResourceTypeEnum propVal : (List)propValue) { + if (propVal.name().equals(value)) { + return false; + } + } + } + else if (value != null && value.equals(propValue)){ + return false; + } + } + } + return true; + }).count(); + } +} diff --git a/catalog-model/src/test/java/org/openecomp/sdc/be/model/jsontitan/operations/ToscaElementOperationTestImpl.java b/catalog-model/src/test/java/org/openecomp/sdc/be/model/jsontitan/operations/ToscaElementOperationTestImpl.java new file mode 100644 index 0000000000..27fbce4776 --- /dev/null +++ b/catalog-model/src/test/java/org/openecomp/sdc/be/model/jsontitan/operations/ToscaElementOperationTestImpl.java @@ -0,0 +1,74 @@ +package org.openecomp.sdc.be.model.jsontitan.operations; + +import fj.data.Either; +import org.openecomp.sdc.be.dao.jsongraph.GraphVertex; +import org.openecomp.sdc.be.dao.jsongraph.types.JsonParseFlagEnum; +import org.openecomp.sdc.be.dao.titan.TitanOperationStatus; +import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; +import org.openecomp.sdc.be.model.ComponentParametersView; +import org.openecomp.sdc.be.model.jsontitan.datamodel.ToscaElement; +import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; + +/** + * Created by cb478c on 6/13/2017. + */ +@org.springframework.stereotype.Component("test-tosca-element-operation") +public class ToscaElementOperationTestImpl extends ToscaElementOperation { + + @Override + protected Either getLightComponent(GraphVertex vertexComponent, ComponentTypeEnum nodeType, ComponentParametersView parametersFilter) { + titanDao.parseVertexProperties(vertexComponent, JsonParseFlagEnum.ParseMetadata); + T toscaElement = convertToComponent(vertexComponent); + return Either.left(toscaElement); + } + + @Override + public Either getToscaElement(String uniqueId, ComponentParametersView componentParametersView) { + return null; + } + + @Override + public Either getToscaElement(GraphVertex toscaElementVertex, ComponentParametersView componentParametersView) { + return null; + } + + @Override + public Either deleteToscaElement(GraphVertex toscaElementVertex) { + return null; + } + + @Override + public Either createToscaElement(ToscaElement toscaElement) { + return null; + } + + @Override + protected TitanOperationStatus setCategoriesFromGraph(GraphVertex vertexComponent, T toscaElement) { + return null; + } + + @Override + protected TitanOperationStatus setCapabilitiesFromGraph(GraphVertex componentV, T toscaElement) { + return null; + } + + @Override + protected TitanOperationStatus setRequirementsFromGraph(GraphVertex componentV, T toscaElement) { + return null; + } + + @Override + protected StorageOperationStatus validateCategories(T toscaElementToUpdate, GraphVertex elementV) { + return null; + } + + @Override + protected StorageOperationStatus updateDerived(T toscaElementToUpdate, GraphVertex updateElementV) { + return null; + } + + @Override + public void fillToscaElementVertexData(GraphVertex elementV, T toscaElementToUpdate, JsonParseFlagEnum flag) { + + } +} diff --git a/catalog-model/src/test/java/org/openecomp/sdc/be/model/jsontitan/utils/GraphTestUtils.java b/catalog-model/src/test/java/org/openecomp/sdc/be/model/jsontitan/utils/GraphTestUtils.java new file mode 100644 index 0000000000..8e2a283559 --- /dev/null +++ b/catalog-model/src/test/java/org/openecomp/sdc/be/model/jsontitan/utils/GraphTestUtils.java @@ -0,0 +1,114 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * 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. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdc.be.model.jsontitan.utils; + +import com.thinkaurelius.titan.core.TitanGraph; +import com.thinkaurelius.titan.core.TitanVertex; +import fj.data.Either; +import org.apache.tinkerpop.gremlin.structure.io.IoCore; +import org.openecomp.sdc.be.dao.jsongraph.GraphVertex; +import org.openecomp.sdc.be.dao.jsongraph.TitanDao; +import org.openecomp.sdc.be.dao.jsongraph.types.VertexTypeEnum; +import org.openecomp.sdc.be.dao.titan.TitanOperationStatus; +import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; +import org.openecomp.sdc.be.datatypes.enums.GraphPropertyEnum; +import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum; + +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.OutputStream; +import java.util.Iterator; +import java.util.Map; +import java.util.UUID; + +public final class GraphTestUtils { + + public static GraphVertex createResourceVertex(TitanDao titanDao, Map metadataProps, ResourceTypeEnum type) { + GraphVertex vertex = new GraphVertex(); + if (type == ResourceTypeEnum.VF) { + vertex.setLabel(VertexTypeEnum.TOPOLOGY_TEMPLATE); + vertex.addMetadataProperty(GraphPropertyEnum.LABEL, VertexTypeEnum.TOPOLOGY_TEMPLATE); + } else { + vertex.setLabel(VertexTypeEnum.NODE_TYPE); + vertex.addMetadataProperty(GraphPropertyEnum.LABEL, VertexTypeEnum.NODE_TYPE); + } + String uuid = UUID.randomUUID().toString(); + vertex.setUniqueId(uuid); + + vertex.addMetadataProperty(GraphPropertyEnum.UNIQUE_ID, uuid); + vertex.addMetadataProperty(GraphPropertyEnum.COMPONENT_TYPE, ComponentTypeEnum.RESOURCE.name()); + vertex.addMetadataProperty(GraphPropertyEnum.RESOURCE_TYPE, type.name()); + vertex.addMetadataProperty(GraphPropertyEnum.IS_ABSTRACT, false); + for (Map.Entry prop : metadataProps.entrySet()) { + vertex.addMetadataProperty(prop.getKey(), prop.getValue()); + } + titanDao.createVertex(vertex); + titanDao.commit(); + return vertex; + } + + public static GraphVertex createServiceVertex(TitanDao titanDao, Map metadataProps){ + GraphVertex vertex = new GraphVertex(VertexTypeEnum.TOPOLOGY_TEMPLATE); + String uuid = UUID.randomUUID().toString(); + vertex.setUniqueId(uuid); + vertex.addMetadataProperty(GraphPropertyEnum.LABEL, VertexTypeEnum.TOPOLOGY_TEMPLATE); + vertex.addMetadataProperty(GraphPropertyEnum.UNIQUE_ID, uuid); + vertex.addMetadataProperty(GraphPropertyEnum.COMPONENT_TYPE, ComponentTypeEnum.SERVICE.name()); + for (Map.Entry prop : metadataProps.entrySet()) { + vertex.addMetadataProperty(prop.getKey(), prop.getValue()); + } + titanDao.createVertex(vertex); + titanDao.commit(); + return vertex; + } + + public static void clearGraph(TitanDao titanDao) { + Either graphResult = titanDao.getGraph(); + TitanGraph graph = graphResult.left().value(); + + Iterable vertices = graph.query().vertices(); + if (vertices != null) { + Iterator iterator = vertices.iterator(); + while (iterator.hasNext()) { + TitanVertex vertex = iterator.next(); + vertex.remove(); + } + } + titanDao.commit(); + } + + public static String exportGraphMl(TitanGraph graph, String outputDirectory) { + String result = null; + String outputFile = outputDirectory + File.separator + "exportGraph." + System.currentTimeMillis() + ".graphml"; + try { + try (final OutputStream os = new BufferedOutputStream(new FileOutputStream(outputFile))) { + graph.io(IoCore.graphml()).writer().normalize(true).create().writeGraph(os, graph); + } + result = outputFile; + graph.tx().commit(); + } catch (Exception e) { + graph.tx().rollback(); + e.printStackTrace(); + } + return result; + } +} diff --git a/catalog-ui/configurations/MenuReadMe.txt b/catalog-ui/configurations/MenuReadMe.txt index 660427e5c9..16a7d0f0b7 100644 --- a/catalog-ui/configurations/MenuReadMe.txt +++ b/catalog-ui/configurations/MenuReadMe.txt @@ -8,8 +8,6 @@ Supported roles: ----------------------------- ADMIN DESIGNER -PRODUCT_STRATEGIST -PRODUCT_MANAGER TESTER OPS GOVERNOR diff --git a/catalog-ui/configurations/dev.js b/catalog-ui/configurations/dev.js index 4058071183..b68842c3fc 100644 --- a/catalog-ui/configurations/dev.js +++ b/catalog-ui/configurations/dev.js @@ -55,21 +55,13 @@ const SDC_CONFIG = { "POST_change_instance_version": "/v1/catalog/:entityType/:entityId/resourceInstance/:id/changeVersion", "GET_requirements_capabilities": "/v1/catalog/requirmentsCapabilities/:type/:id", "GET_resource_artifact_types": "/v1/artifactTypes", - "GET_product_catalog": "/v1/productScreen", - "GET_product_category": "/v1/productCategories", - "GET_product_category_temp": "/v1/artifactTypes", - "POST_product": "/v1/catalog/products/:id/metadata", - "GET_product_validate_name": "/v1/catalog/services/validate-name/:name", - "GET_product": "/v1/catalog/products/:id", - "GET_product_sub_category": "/v1/productSubCategories", "GET_onboarding": "/sdc1/feProxy/onboarding-api/v1.0/vendor-software-products/packages", "GET_component_from_csar_uuid": "/v1/catalog/resources/csar/:csar_uuid", "kibana": "/sdc1/kibanaProxy/" }, "resourceTypesFilter":{ "resource":["CP","VFC","VL"], - "service":["CP","VF","VL"], - "product":[] + "service":["CP","VF","VL", "PNF","CVFC"] }, "logConfig": { "minLogLevel": "debug", @@ -104,7 +96,7 @@ const SDC_CONFIG = { "default": "DL-ASDCL1-4ServiceCertificationTeam;DL-ASDCL4-7ServiceCertificationTeam" } }, - "roles": ["ADMIN", "TESTER", "GOVERNOR", "OPS", "DESIGNER", "PRODUCT_MANAGER", "PRODUCT_STRATEGIST"], + "roles": ["ADMIN", "TESTER", "GOVERNOR", "OPS", "DESIGNER"], "tutorial": { "tabs": [ { @@ -428,4 +420,4 @@ const SDC_CONFIG = { } }; -module.exports = SDC_CONFIG; \ No newline at end of file +module.exports = SDC_CONFIG; diff --git a/catalog-ui/configurations/menu.js b/catalog-ui/configurations/menu.js index 12dda2d78b..36f9d8076a 100644 --- a/catalog-ui/configurations/menu.js +++ b/catalog-ui/configurations/menu.js @@ -32,8 +32,7 @@ const SDC_MENU_CONFIG = { "title": "Designer's Workspace", "pages":[], "dashboard": { - "showCreateNew": true, - "showCreateNewProduct": false + "showCreateNew": true }, "changeLifecycleStateButtons":{ "NOT_CERTIFIED_CHECKOUT":{ "submitForTesting": {"text":"Submit for Testing", "url":"lifecycleState/certificationRequest", "emailModal": "lifecycleState/CERTIFICATIONREQUEST"}, @@ -81,99 +80,11 @@ const SDC_MENU_CONFIG = { ] }, - "PRODUCT_STRATEGIST":{ - "title": "Product Strategist's Workspace", - "pages":[], - "dashboard": { - "showCreateNew": false, - "showCreateNewProduct": false - }, - "changeLifecycleStateButtons":{}, - - "states":{ - "NOT_CERTIFIED_CHECKOUT":{ - "ANY":[ - ] - }, - "NOT_CERTIFIED_CHECKIN": { - "ANY": [ - ] - }, - "READY_FOR_CERTIFICATION": { - "ANY":[ - ] - }, - "CERTIFICATION_IN_PROGRESS":{ - "ANY":[ - ] - }, - "CERTIFIED":{ - "ANY":[ - ] - } - }, - "folder":[ - {"text": "Active Projects", "groupname": "IN_PROGRESS" }, - {"text": "Check Out", "group": "IN_PROGRESS", "state": "NOT_CERTIFIED_CHECKOUT"}, - {"text": "Check In", "group": "IN_PROGRESS", "state": "NOT_CERTIFIED_CHECKIN"}, - {"text": "Followed Projects", "groupname": "FOLLOWING" }, - {"text": "Ready For Testing", "group": "FOLLOWING", "state": "READY_FOR_CERTIFICATION"}, - {"text": "In Testing", "group": "FOLLOWING", "state": "CERTIFICATION_IN_PROGRESS"}, - {"text": "Certified", "group": "FOLLOWING", "state": "CERTIFIED"} - ] - }, - "PRODUCT_MANAGER":{ - "title": "Product Manager Workspace", - "pages":[], - "dashboard": { - "showCreateNew": false, - "showCreateNewProduct": true - }, - "changeLifecycleStateButtons":{ - "NOT_CERTIFIED_CHECKOUT":{ "checkIn": {"text":"Check in", "url":"lifecycleState/CHECKIN", "confirmationModal": "lifecycleState/CHECKIN"}, - "deleteVersion":{"text":"Delete Version", "url":"lifecycleState/UNDOCHECKOUT", "alertModal": "lifecycleState/UNDOCHECKOUT"} - }, - "NOT_CERTIFIED_CHECKIN":{ "checkOut": {"text":"Check Out", "url":"lifecycleState/CHECKOUT"} - } - }, - "states":{ - "NOT_CERTIFIED_CHECKOUT":{ - "ANY":[ - ] - }, - "NOT_CERTIFIED_CHECKIN": { - "ANY": [ - ] - }, - "READY_FOR_CERTIFICATION": { - "ANY":[ - ] - }, - "CERTIFICATION_IN_PROGRESS":{ - "ANY":[ - ] - }, - "CERTIFIED":{ - "ANY":[ - ] - } - }, - "folder":[ - {"text": "Active Projects", "groupname": "IN_PROGRESS" }, - {"text": "Check Out", "group": "IN_PROGRESS", "state": "NOT_CERTIFIED_CHECKOUT"}, - {"text": "Check In", "group": "IN_PROGRESS", "state": "NOT_CERTIFIED_CHECKIN"}, - {"text": "Followed Projects", "groupname": "FOLLOWING" }, - {"text": "Ready For Testing", "group": "FOLLOWING", "state": "READY_FOR_CERTIFICATION"}, - {"text": "In Testing", "group": "FOLLOWING", "state": "CERTIFICATION_IN_PROGRESS"}, - {"text": "Certified", "group": "FOLLOWING", "state": "CERTIFIED"} - ] - }, "TESTER":{ "title": "Tester's Workspace", "pages":[], "dashboard": { - "showCreateNew": false, - "showCreateNewProduct": false + "showCreateNew": false }, "changeLifecycleStateButtons":{ "READY_FOR_CERTIFICATION":{ "startTesting": {"text":"Start Testing", "url":"lifecycleState/startCertification"} @@ -208,8 +119,7 @@ const SDC_MENU_CONFIG = { "title": "Operations Workspace", "pages":[], "dashboard": { - "showCreateNew": false, - "showCreateNewProduct": false + "showCreateNew": false }, "changeLifecycleStateButtons":{ "DISTRIBUTION_APPROVED":{ "distribute": {"text":"Distribute", "url":"distribution/PROD/activate", "conformanceLevelModal": { "url":"distribution-state/reject", "confirmationModal": "distribution-state/reject" }}, @@ -240,8 +150,7 @@ const SDC_MENU_CONFIG = { "title": "Governance Rep's Workspace", "pages":[], "dashboard": { - "showCreateNew": false, - "showCreateNewProduct": false + "showCreateNew": false }, "changeLifecycleStateButtons":{ "DISTRIBUTION_NOT_APPROVED":{ "approve": {"text":"Approve", "url":"distribution-state/approve", "confirmationModal": "distribution-state/approve", "conformanceLevelModal": { "url":"distribution-state/reject", "confirmationModal": "distribution-state/reject" }}, @@ -358,82 +267,6 @@ const SDC_MENU_CONFIG = { } }, - "PRODUCT_MANAGER":{ - "states":{ - "NOT_CERTIFIED_CHECKOUT":{ - "ANY":[ - ], - "NOT_OWNER":[ - ] - }, - "NOT_CERTIFIED_CHECKIN": { - "ANY": [ - ] - }, - "READY_FOR_CERTIFICATION": { - "ANY":[ - ] - }, - "CERTIFICATION_IN_PROGRESS":{ - "ANY":[ - ] - }, - "CERTIFIED":{ - "ANY":[ - ] - } - }, - "folder":[ - {"text": "Active Projects", "groupname": "IN_PROGRESS" }, - {"text": "Check Out", "group": "IN_PROGRESS", "state": "NOT_CERTIFIED_CHECKOUT"}, - {"text": "Check In", "group": "IN_PROGRESS", "state": "NOT_CERTIFIED_CHECKIN"}, - {"text": "Followed Projects", "groupname": "FOLLOWING" }, - {"text": "Ready For Testing", "group": "FOLLOWING", "state": "READY_FOR_CERTIFICATION"}, - {"text": "In Testing", "group": "FOLLOWING", "state": "CERTIFICATION_IN_PROGRESS"}, - {"text": "Certified", "group": "FOLLOWING", "state": "CERTIFIED"} - ] - }, - "PRODUCT_STRATEGIST":{ - "title": "Product Strategist's Workspace", - "pages":[], - "dashboard": { - "showCreateNew": false, - "showCreateNewProduct": true - }, - "states":{ - "NOT_CERTIFIED_CHECKOUT":{ - "ANY":[ - ], - "NOT_OWNER":[ - ] - }, - "NOT_CERTIFIED_CHECKIN": { - "ANY": [ - ] - }, - "READY_FOR_CERTIFICATION": { - "ANY":[ - ] - }, - "CERTIFICATION_IN_PROGRESS":{ - "ANY":[ - ] - }, - "CERTIFIED":{ - "ANY":[ - ] - } - }, - "folder":[ - {"text": "Active Projects", "groupname": "IN_PROGRESS" }, - {"text": "Check Out", "group": "IN_PROGRESS", "state": "NOT_CERTIFIED_CHECKOUT"}, - {"text": "Check In", "group": "IN_PROGRESS", "state": "NOT_CERTIFIED_CHECKIN"}, - {"text": "Followed Projects", "groupname": "FOLLOWING" }, - {"text": "Ready For Testing", "group": "FOLLOWING", "state": "READY_FOR_CERTIFICATION"}, - {"text": "In Testing", "group": "FOLLOWING", "state": "CERTIFICATION_IN_PROGRESS"}, - {"text": "Certified", "group": "FOLLOWING", "state": "CERTIFIED"} - ] - }, "OTHER":{ "states":{ "ANY":{ @@ -465,7 +298,6 @@ const SDC_MENU_CONFIG = { "component_workspace_menu_option": { "VFC":[ {"text":"General", "action":"onMenuItemPressed", "state": "workspace.general"}, - {"text":"Icon", "action":"onMenuItemPressed", "state": "workspace.icons"}, {"text":"Deployment Artifact", "action":"onMenuItemPressed", "state": "workspace.deployment_artifacts"}, {"text":"Information Artifact", "action":"onMenuItemPressed", "state": "workspace.information_artifacts"}, {"text":"TOSCA Artifacts", "action":"onMenuItemPressed", "state": "workspace.tosca_artifacts"}, @@ -476,7 +308,6 @@ const SDC_MENU_CONFIG = { ], "VL":[ {"text":"General", "action":"onMenuItemPressed", "state": "workspace.general"}, - {"text":"Icon", "action":"onMenuItemPressed", "state": "workspace.icons"}, {"text":"Deployment Artifact", "action":"onMenuItemPressed", "state": "workspace.deployment_artifacts"}, {"text":"Information Artifact", "action":"onMenuItemPressed", "state": "workspace.information_artifacts"}, {"text":"TOSCA Artifacts", "action":"onMenuItemPressed", "state": "workspace.tosca_artifacts"}, @@ -487,7 +318,6 @@ const SDC_MENU_CONFIG = { ], "CP":[ {"text":"General", "action":"onMenuItemPressed", "state": "workspace.general"}, - {"text":"Icon", "action":"onMenuItemPressed", "state": "workspace.icons"}, {"text":"Deployment Artifact", "action":"onMenuItemPressed", "state": "workspace.deployment_artifacts"}, {"text":"Information Artifact", "action":"onMenuItemPressed", "state": "workspace.information_artifacts"}, {"text":"TOSCA Artifacts", "action":"onMenuItemPressed", "state": "workspace.tosca_artifacts"}, @@ -498,7 +328,6 @@ const SDC_MENU_CONFIG = { ], "VF":[ {"text":"General", "action":"onMenuItemPressed", "state": "workspace.general"}, - {"text":"Icon", "action":"onMenuItemPressed", "state": "workspace.icons"}, {"text":"Deployment Artifact", "action":"onMenuItemPressed", "state": "workspace.deployment_artifacts"}, {"text":"Information Artifact", "action":"onMenuItemPressed", "state": "workspace.information_artifacts"}, {"text":"TOSCA Artifacts", "action":"onMenuItemPressed", "state": "workspace.tosca_artifacts"}, @@ -509,24 +338,25 @@ const SDC_MENU_CONFIG = { // {"text":"Inputs", "action":"onMenuItemPressed", "state": "workspace.resource_inputs"}, {"text":"Properties Assignment", "action":"onMenuItemPressed", "state": "workspace.properties_assignment"} ], + "PNF":[ + {"text":"General", "action":"onMenuItemPressed", "state": "workspace.general"}, + {"text":"Information Artifact", "action":"onMenuItemPressed", "state": "workspace.information_artifacts"}, + {"text":"TOSCA Artifacts", "action":"onMenuItemPressed", "state": "workspace.tosca_artifacts"}, + {"text":"Composition", "action":"onMenuItemPressed", "state": "workspace.composition.details"}, + {"text":"Activity Log", "action":"onMenuItemPressed", "state": "workspace.activity_log"}, + {"text":"Properties Assignment", "action":"onMenuItemPressed", "state": "workspace.properties_assignment"} + ], "SERVICE":[ {"text":"General", "action":"onMenuItemPressed", "state": "workspace.general"}, - {"text":"Icon", "action":"onMenuItemPressed", "state": "workspace.icons"}, {"text":"TOSCA Artifacts", "action":"onMenuItemPressed", "state": "workspace.tosca_artifacts"}, {"text":"Composition", "action":"onMenuItemPressed", "state": "workspace.composition.details"}, {"text":"Activity Log", "action":"onMenuItemPressed", "state": "workspace.activity_log"}, {"text":"Management Workflow", "action":"onMenuItemPressed", "state": "workspace.management_workflow"}, {"text":"Network Call Flow ", "action":"onMenuItemPressed", "state": "workspace.network_call_flow"}, - {"text":"Monitor ", "action":"onMenuItemPressed", "state": "workspace.distribution", "disabledRoles": ["ADMIN", "TESTER", "GOVERNOR", "DESIGNER", "PRODUCT_MANAGER", "PRODUCT_STRATEGIST"]}, + {"text":"Monitor ", "action":"onMenuItemPressed", "state": "workspace.distribution", "disabledRoles": ["ADMIN", "TESTER", "GOVERNOR", "DESIGNER"]}, {"text":"Deployment", "action":"onMenuItemPressed", "state": "workspace.deployment"}, // {"text":"Inputs", "action":"onMenuItemPressed", "state": "workspace.service_inputs"}, {"text":"Properties Assignment", "action":"onMenuItemPressed", "state": "workspace.properties_assignment"} - ], - "PRODUCT":[ - {"text":"General", "action":"onMenuItemPressed", "state": "workspace.general"}, - {"text":"Hierarchy", "action":"onMenuItemPressed", "state": "workspace.hierarchy"}, - {"text":"Icon", "action":"onMenuItemPressed", "state": "workspace.icons"}, - {"text":"Composition", "action":"onMenuItemPressed", "state": "workspace.composition.details"} ] } diff --git a/catalog-ui/configurations/mock.json b/catalog-ui/configurations/mock.json index 2abcbe0ce2..0ce1fbbb5d 100644 --- a/catalog-ui/configurations/mock.json +++ b/catalog-ui/configurations/mock.json @@ -77,20 +77,6 @@ "firstName": "op", "lastName": "ss", "xEcompRequestId": "ccccc" - }, - "product_strategist": { - "userId": "ps0001", - "email": "product_strategist@sdc.com", - "firstName": "Orit", - "lastName": "Barda", - "xEcompRequestId": "ccccc" - }, - "product_manager": { - "userId": "pm0001", - "email": "product_manager@sdc.com", - "firstName": "Orit", - "lastName": "Barda", - "xEcompRequestId": "ccccc" } }, "statuses": { diff --git a/catalog-ui/configurations/prod.js b/catalog-ui/configurations/prod.js index 30cb3f2146..971263b710 100644 --- a/catalog-ui/configurations/prod.js +++ b/catalog-ui/configurations/prod.js @@ -55,21 +55,13 @@ const SDC_CONFIG = { "POST_change_instance_version": "/v1/catalog/:entityType/:entityId/resourceInstance/:id/changeVersion", "GET_requirements_capabilities": "/v1/catalog/requirmentsCapabilities/:type/:id", "GET_resource_artifact_types": "/v1/artifactTypes", - "GET_product_catalog": "/v1/productScreen", - "GET_product_category": "/v1/productCategories", - "GET_product_category_temp": "/v1/artifactTypes", - "POST_product": "/v1/catalog/products/:id/metadata", - "GET_product_validate_name": "/v1/catalog/services/validate-name/:name", - "GET_product": "/v1/catalog/products/:id", - "GET_product_sub_category": "/v1/productSubCategories", "GET_onboarding": "/sdc1/feProxy/onboarding-api/v1.0/vendor-software-products/packages", "GET_component_from_csar_uuid": "/v1/catalog/resources/csar/:csar_uuid", "kibana": "/sdc1/kibanaProxy/" }, "resourceTypesFilter":{ "resource":["CP","VFC","VL"], - "service":["CP","VF","VL"], - "product":[] + "service":["CP","VF","VL", "PNF","CVFC"] }, "logConfig": { "minLogLevel": "debug", @@ -104,7 +96,7 @@ const SDC_CONFIG = { "default": "DL-ASDCL1-4ServiceCertificationTeam;DL-ASDCL4-7ServiceCertificationTeam" } }, - "roles": ["ADMIN", "TESTER", "GOVERNOR", "OPS", "DESIGNER", "PRODUCT_MANAGER", "PRODUCT_STRATEGIST"], + "roles": ["ADMIN", "TESTER", "GOVERNOR", "OPS", "DESIGNER"], "tutorial": { "tabs": [ { @@ -426,7 +418,6 @@ const SDC_CONFIG = { ] } - }; module.exports = SDC_CONFIG; diff --git a/catalog-ui/pom.xml b/catalog-ui/pom.xml index 0505d91cba..737ed33a41 100644 --- a/catalog-ui/pom.xml +++ b/catalog-ui/pom.xml @@ -47,9 +47,6 @@ false - - ${basedir}/node_modules - @@ -100,11 +97,11 @@ com.github.eirslett frontend-maven-plugin 1.4 - + ${project.parent.basedir} - + install node and npm @@ -117,7 +114,7 @@ 3.10.10 - + npm set progress off diff --git a/catalog-ui/src/app/app.ts b/catalog-ui/src/app/app.ts index 50b99e8ab9..707d7e456e 100644 --- a/catalog-ui/src/app/app.ts +++ b/catalog-ui/src/app/app.ts @@ -245,17 +245,6 @@ ng1appModule.config([ data: {unsavedChanges: false, bodyClass: 'general'} } ); - // - $stateProvider.state( - States.WORKSPACE_ICONS, { - url: 'icons', - parent: 'workspace', - controller: viewModelsModuleName + '.IconsViewModel', - templateUrl: './view-models/workspace/tabs/icons/icons-view.html', - data: {unsavedChanges: false, bodyClass: 'icons'} - - } - ); $stateProvider.state( States.WORKSPACE_ACTIVITY_LOG, { @@ -279,17 +268,6 @@ ng1appModule.config([ } ); - $stateProvider.state( - States.WORKSPACE_HIERARCHY, { - url: 'hierarchy', - parent: 'workspace', - controller: viewModelsModuleName + '.ProductHierarchyViewModel', - templateUrl: './view-models/workspace/tabs/product-hierarchy/product-hierarchy-view.html', - data: {unsavedChanges: false} - - } - ); - $stateProvider.state( States.WORKSPACE_INFORMATION_ARTIFACTS, { url: 'information_artifacts', @@ -602,7 +580,7 @@ ng1appModule.value('ValidationPattern', /^[\s\w\&_.:-]{1,1024}$/); ng1appModule.value('ComponentNameValidationPattern', /^(?=.*[^. ])[\s\w\&_.:-]{1,1024}$/); //DE250513 - same as ValidationPattern above, plus requirement that name not consist of dots and/or spaces alone. ng1appModule.value('PropertyNameValidationPattern', /^[a-zA-Z0-9_:-]{1,50}$/);// DE210977 ng1appModule.value('TagValidationPattern', /^[\s\w_.-]{1,50}$/); -ng1appModule.value('VendorValidationPattern', /^[\x20-\x21\x23-\x29\x2B-\x2E\x30-\x39\x3B\x3D\x40-\x5B\x5D-\x7B\x7D-\xFF]{1,25}$/); +ng1appModule.value('VendorReleaseValidationPattern', /^[\x20-\x21\x23-\x29\x2B-\x2E\x30-\x39\x3B\x3D\x40-\x5B\x5D-\x7B\x7D-\xFF]{1,25}$/); ng1appModule.value('VendorNameValidationPattern', /^[\x20-\x21\x23-\x29\x2B-\x2E\x30-\x39\x3B\x3D\x40-\x5B\x5D-\x7B\x7D-\xFF]{1,60}$/); ng1appModule.value('VendorModelNumberValidationPattern', /^[\x20-\x21\x23-\x29\x2B-\x2E\x30-\x39\x3B\x3D\x40-\x5B\x5D-\x7B\x7D-\xFF]{1,65}$/); ng1appModule.value('ContactIdValidationPattern', /^[\s\w-]{1,50}$/); @@ -696,7 +674,6 @@ ng1appModule.run([ categoryResourceService.getAllCategories((categories: Categories):void => { cacheService.set('serviceCategories', categories.serviceCategories); cacheService.set('resourceCategories', categories.resourceCategories); - cacheService.set('productCategories', categories.productCategories); }, onError); }; diff --git a/catalog-ui/src/app/directives/graphs-v2/common/style/component-instances-nodes-style.ts b/catalog-ui/src/app/directives/graphs-v2/common/style/component-instances-nodes-style.ts index 0a13ebd799..0dcc93dfa7 100644 --- a/catalog-ui/src/app/directives/graphs-v2/common/style/component-instances-nodes-style.ts +++ b/catalog-ui/src/app/directives/graphs-v2/common/style/component-instances-nodes-style.ts @@ -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,7 +44,8 @@ export class ComponentInstanceNodesStyle { { selector: 'node', css: { - 'font-family': 'omnes-regular,sans-serif', + 'font-family': 'OpenSans-Regular,sans-serif', + 'font-size': 14, 'events': 'yes', 'text-events': 'yes', diff --git a/catalog-ui/src/app/directives/graphs-v2/palette/palette.directive.ts b/catalog-ui/src/app/directives/graphs-v2/palette/palette.directive.ts index f1c3405cfa..f46dc6c939 100644 --- a/catalog-ui/src/app/directives/graphs-v2/palette/palette.directive.ts +++ b/catalog-ui/src/app/directives/graphs-v2/palette/palette.directive.ts @@ -17,21 +17,14 @@ * limitations under the License. * ============LICENSE_END========================================================= */ - -import { - Component, - IAppMenu, - LeftPanelModel, - NodesFactory, - LeftPaletteComponent, - CompositionCiNodeBase, - ComponentInstance -} from "app/models"; +import {Component, IAppMenu, LeftPanelModel, NodesFactory, LeftPaletteComponent, CompositionCiNodeBase, ComponentInstance} from "app/models"; import {CompositionGraphGeneralUtils} from "../composition-graph/utils/composition-graph-general-utils"; import {EventListenerService} from "app/services"; import {ResourceType, GRAPH_EVENTS, EVENTS, ComponentInstanceFactory, ModalsHandler} from "app/utils"; import 'sdc-angular-dragdrop'; import {LeftPaletteLoaderService} from "../../../services/components/utils/composition-left-palette-service"; +import {Resource} from "app/models/components/resource"; +import {ComponentType} from "app/utils/constants"; interface IPaletteScope { components:Array; @@ -92,7 +85,7 @@ export class Palette implements ng.IDirective { el.append(this.nodeHtmlSubstitute); this.registerEventListenerForLeftPalette(scope); // this.LeftPaletteLoaderService.loadLeftPanel(scope.currentComponent.componentType); - + this.initComponents(scope); this.initEvents(scope); this.initDragEvents(scope); @@ -103,34 +96,31 @@ export class Palette implements ng.IDirective { }); }; - private registerEventListenerForLeftPalette = (scope:IPaletteScope):void => { - if (scope.currentComponent.isResource()) { - this.EventListenerService.registerObserverCallback(EVENTS.RESOURCE_LEFT_PALETTE_UPDATE_EVENT, () => { - this.updateLeftPanelDisplay(scope); - }); - } - if (scope.currentComponent.isService()) { - this.EventListenerService.registerObserverCallback(EVENTS.SERVICE_LEFT_PALETTE_UPDATE_EVENT, () => { - this.updateLeftPanelDisplay(scope); - }); - } - if (scope.currentComponent.isProduct()) { - this.EventListenerService.registerObserverCallback(EVENTS.PRODUCT_LEFT_PALETTE_UPDATE_EVENT, () => { - this.updateLeftPanelDisplay(scope); - }); + private getUpdateLeftPaletteEventName = (component:Component):string => { + switch (component.componentType) { + case ComponentType.SERVICE: + return EVENTS.SERVICE_LEFT_PALETTE_UPDATE_EVENT; + case ComponentType.RESOURCE: + if((component).resourceType == ResourceType.PNF){ + return EVENTS.RESOURCE_PNF_LEFT_PALETTE_UPDATE_EVENT; + }else{ + return EVENTS.RESOURCE_LEFT_PALETTE_UPDATE_EVENT; + } + default: + console.log('ERROR: Component type '+ component.componentType + ' is not exists'); } }; + private registerEventListenerForLeftPalette = (scope:IPaletteScope):void => { + let updateEventName:string = this.getUpdateLeftPaletteEventName(scope.currentComponent); + this.EventListenerService.registerObserverCallback(updateEventName, () => { + this.updateLeftPanelDisplay(scope); + }); + }; + private unRegisterEventListenerForLeftPalette = (scope:IPaletteScope):void => { - if (scope.currentComponent.isResource()) { - this.EventListenerService.unRegisterObserver(EVENTS.RESOURCE_LEFT_PALETTE_UPDATE_EVENT); - } - if (scope.currentComponent.isService()) { - this.EventListenerService.unRegisterObserver(EVENTS.SERVICE_LEFT_PALETTE_UPDATE_EVENT); - } - if (scope.currentComponent.isProduct()) { - this.EventListenerService.unRegisterObserver(EVENTS.PRODUCT_LEFT_PALETTE_UPDATE_EVENT); - } + let updateEventName:string = this.getUpdateLeftPaletteEventName(scope.currentComponent); + this.EventListenerService.unRegisterObserver(updateEventName); }; private leftPanelResourceFilter(resourcesNotAbstract:Array, resourceFilterTypes:Array):Array { @@ -236,7 +226,7 @@ export class Palette implements ng.IDirective { private updateLeftPanelDisplay(scope:IPaletteScope) { let entityType:string = scope.currentComponent.componentType.toLowerCase(); let resourceFilterTypes:Array = this.sdcConfig.resourceTypesFilter[entityType]; - scope.components = this.LeftPaletteLoaderService.getLeftPanelComponentsForDisplay(scope.currentComponent.componentType); + scope.components = this.LeftPaletteLoaderService.getLeftPanelComponentsForDisplay(scope.currentComponent); scope.model = this.initLeftPanel(scope.components, resourceFilterTypes); scope.displaySortedCategories = angular.copy(scope.model.sortedCategories); }; @@ -267,7 +257,7 @@ export class Palette implements ng.IDirective { return; } - let component = _.find(this.LeftPaletteLoaderService.getLeftPanelComponentsForDisplay(scope.currentComponent.componentType), (componentFullData:LeftPaletteComponent) => { + let component = _.find(this.LeftPaletteLoaderService.getLeftPanelComponentsForDisplay(scope.currentComponent), (componentFullData:LeftPaletteComponent) => { return displayComponent.uniqueId === componentFullData.uniqueId; }); this.EventListenerService.notifyObservers(GRAPH_EVENTS.ON_PALETTE_COMPONENT_DRAG_START, scope.dragElement, component); @@ -287,7 +277,7 @@ export class Palette implements ng.IDirective { this.EventListenerService.notifyObservers(GRAPH_EVENTS.ON_PALETTE_COMPONENT_DRAG_ACTION, event); }; scope.setElementTemplate = (e) => { - let dragComponent:LeftPaletteComponent = _.find(this.LeftPaletteLoaderService.getLeftPanelComponentsForDisplay(scope.currentComponent.componentType), + let dragComponent:LeftPaletteComponent = _.find(this.LeftPaletteLoaderService.getLeftPanelComponentsForDisplay(scope.currentComponent), (fullComponent:LeftPaletteComponent) => { return (angular.element(e.currentTarget).scope()).component.uniqueId === fullComponent.uniqueId; }); diff --git a/catalog-ui/src/app/directives/property-types/type-map/type-map-directive.html b/catalog-ui/src/app/directives/property-types/type-map/type-map-directive.html index 3a4720676c..ec9aaf1f7f 100644 --- a/catalog-ui/src/app/directives/property-types/type-map/type-map-directive.html +++ b/catalog-ui/src/app/directives/property-types/type-map/type-map-directive.html @@ -56,7 +56,7 @@
- ;//array of map keys + mapKeysStatic:Array; MapKeyValidationPattern:RegExp; fieldsPrefixName:string; readOnly:boolean; @@ -82,6 +83,8 @@ export class TypeMapDirective implements ng.IDirective { scope.isSchemaTypeDataType = this.DataTypesService.isDataTypeForSchemaType(scope.schemaProperty); if (scope.valueObjRef) { scope.mapKeys = Object.keys(scope.valueObjRef); + //keeping another copy of the keys, as the mapKeys gets overridden sometimes + scope.mapKeysStatic = Object.keys(scope.valueObjRef); } }); @@ -91,6 +94,8 @@ export class TypeMapDirective implements ng.IDirective { scope.valueObjRef = {}; } scope.mapKeys = Object.keys(scope.valueObjRef); + //keeping another copy of the keys, as the mapKeys gets overridden sometimes + scope.mapKeysStatic = Object.keys(scope.valueObjRef); if ($attr.defaultValue) { scope.mapDefaultValue = JSON.parse($attr.defaultValue); diff --git a/catalog-ui/src/app/directives/structure-tree/structure-tree-directive.html b/catalog-ui/src/app/directives/structure-tree/structure-tree-directive.html index 7d8a883b33..706dbefb80 100644 --- a/catalog-ui/src/app/directives/structure-tree/structure-tree-directive.html +++ b/catalog-ui/src/app/directives/structure-tree/structure-tree-directive.html @@ -6,7 +6,7 @@
  • -
    +
    diff --git a/catalog-ui/src/app/directives/utils/sdc-tags/sdc-tags.less b/catalog-ui/src/app/directives/utils/sdc-tags/sdc-tags.less index 942196e663..af24776cd3 100644 --- a/catalog-ui/src/app/directives/utils/sdc-tags/sdc-tags.less +++ b/catalog-ui/src/app/directives/utils/sdc-tags/sdc-tags.less @@ -1,10 +1,10 @@ .tags-box { - height: 297px; + height: 100px; .bg_c; .perfect-scrollbar { - height: 265px; + height: 70px; } .new-tag-input { diff --git a/catalog-ui/src/app/models.ts b/catalog-ui/src/app/models.ts index c7b7577268..f3eb5d5fa6 100644 --- a/catalog-ui/src/app/models.ts +++ b/catalog-ui/src/app/models.ts @@ -35,11 +35,9 @@ export * from './models/category'; export * from './models/comments'; export * from './models/components/component'; export * from './models/components/displayComponent'; -export * from './models/components/product'; export * from './models/components/resource'; export * from './models/components/service'; export * from './models/componentsInstances/componentInstance'; -export * from './models/componentsInstances/productInstance'; export * from './models/componentsInstances/resourceInstance'; export * from './models/componentsInstances/serviceInstance'; export * from './models/csar-component'; @@ -102,7 +100,7 @@ export * from './models/tooltip-data'; export * from './models/user'; export * from './models/validate'; export * from './models/component-metadata'; - +export * from './models/modal'; export * from './models/button'; export * from './models/filter-properties-assignment-data' export * from './models/properties-inputs/input-be-model' diff --git a/catalog-ui/src/app/models/app-config.ts b/catalog-ui/src/app/models/app-config.ts index ef6c195731..40eb18b8b4 100644 --- a/catalog-ui/src/app/models/app-config.ts +++ b/catalog-ui/src/app/models/app-config.ts @@ -54,10 +54,7 @@ export interface IApi { GET_activity_log:string; GET_configuration_ui:string; GET_service:string; - PUT_product:string; - GET_product:string; GET_ecomp_menu_items:string; - GET_product_validate_name:string; GET_service_validate_name:string; GET_service_distributions:string; GET_service_distributions_components:string; @@ -85,13 +82,6 @@ export interface IApi { GET_onboarding:string; GET_component_from_csar_uuid:string; kibana:string; - - //Added by Ikram -- starts - GET_product_category:string; - GET_product_category_temp:string; - GET_product_sub_category:string; - //Added by Ikram -- ends - } export interface ILogConfig { @@ -132,8 +122,6 @@ export interface IConfigRoles { TESTER:IConfigRole; OPS:IConfigRole; GOVERNOR:IConfigRole; - PRODUCT_MANAGER:IConfigRole; - PRODUCT_STRATEGIST:IConfigRole; } export interface IConfigRole { diff --git a/catalog-ui/src/app/models/categories.ts b/catalog-ui/src/app/models/categories.ts index b46c3a6612..0921ca158b 100644 --- a/catalog-ui/src/app/models/categories.ts +++ b/catalog-ui/src/app/models/categories.ts @@ -25,6 +25,5 @@ import {IMainCategory} from "./category"; export class Categories { resourceCategories:Array; - productCategories:Array; serviceCategories:Array; } diff --git a/catalog-ui/src/app/models/component-metadata.ts b/catalog-ui/src/app/models/component-metadata.ts index 2501f0bab5..8c6ed5593d 100644 --- a/catalog-ui/src/app/models/component-metadata.ts +++ b/catalog-ui/src/app/models/component-metadata.ts @@ -56,12 +56,15 @@ export class ComponentMetadata { public vendorName:string; public vendorRelease:string; public derivedFrom: Array; + public resourceVendorModelNumber:string; //Service only public projectCode:string; public distributionStatus:string; public ecompGeneratedNaming: boolean; public namingPolicy: string; + public serviceType:string; + public serviceRole:string; //backend lifecycleState @@ -103,6 +106,9 @@ export class ComponentMetadata { this.ecompGeneratedNaming = response.ecompGeneratedNaming; this.namingPolicy = response.namingPolicy; this.derivedFrom = response.derivedFrom; + this.resourceVendorModelNumber = response.resourceVendorModelNumber; + this.serviceType = response.serviceType; + this.serviceRole = response.serviceRole; return this; } diff --git a/catalog-ui/src/app/models/components/component.ts b/catalog-ui/src/app/models/components/component.ts index 0c47cc4cb2..9b2c942483 100644 --- a/catalog-ui/src/app/models/components/component.ts +++ b/catalog-ui/src/app/models/components/component.ts @@ -22,7 +22,7 @@ import {AsdcComment, ArtifactModel, ArtifactGroupModel, IFileDownload, PropertyModel, PropertiesGroup, AttributeModel, AttributesGroup, ComponentInstance, InputModel, DisplayModule, Module, IValidate, RelationshipModel, IMainCategory, RequirementsGroup, CapabilitiesGroup, AdditionalInformationModel, - Resource, IAppMenu, Product, Service} from "../../models"; + Resource, IAppMenu, Service} from "../../models"; import {IComponentService} from "../../services/components/component-service"; import {CommonUtils} from "../../utils/common-utils"; @@ -92,7 +92,6 @@ export interface IComponent { getComponentSubType():string; isAlreadyCertified():boolean; - isProduct():boolean; isService():boolean; isResource():boolean; isComplex():boolean; @@ -797,10 +796,6 @@ export abstract class Component implements IComponent { //------------------------------------------ Help Functions ----------------------------------------------------------------// - public isProduct = ():boolean => { - return this instanceof Product; - }; - public isService = ():boolean => { return this instanceof Service; }; diff --git a/catalog-ui/src/app/models/components/displayComponent.ts b/catalog-ui/src/app/models/components/displayComponent.ts index a5407e6d17..3a9cbfdaf3 100644 --- a/catalog-ui/src/app/models/components/displayComponent.ts +++ b/catalog-ui/src/app/models/components/displayComponent.ts @@ -97,9 +97,6 @@ export class LeftPaletteComponent { case ComponentType.SERVICE: this.iconClass = "sprite-services-icons " + icon; break; - case ComponentType.PRODUCT: - this.iconClass = "sprite-product-icons " + icon; - break; default: this.iconClass = "sprite-resource-icons " + icon; } diff --git a/catalog-ui/src/app/models/components/product.ts b/catalog-ui/src/app/models/components/product.ts deleted file mode 100644 index dfb429b971..0000000000 --- a/catalog-ui/src/app/models/components/product.ts +++ /dev/null @@ -1,125 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * SDC - * ================================================================================ - * 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. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -/** - * Created by obarda on 2/4/2016. - */ -'use strict'; -import {Component} from "./component"; -import {IProductService} from "../../services/components/product-service"; -import {IGroup, ISubCategory, IMainCategory, ICategoryBase} from "../category"; -import {ComponentMetadata} from "../component-metadata"; - -export class Product extends Component { - - public contacts:Array; - public componentService:IProductService; - public fullName:string; - - constructor(componentService:IProductService, $q:ng.IQService, component?:Product) { - super(componentService, $q, component); - - if (component) { - this.fullName = component.fullName; - this.filterTerm = this.name + ' ' + this.description + ' ' + (this.tags ? this.tags.toString() : '') + ' ' + this.version; - this.contacts = component.contacts; - } - this.componentService = componentService; - this.iconSprite = "sprite-product-icons"; - } - - public deleteGroup = (uniqueId:string):void => { - _.forEach(this.categories, (category:IMainCategory) => { - _.forEach(category.subcategories, (subcategory:ISubCategory) => { - subcategory.groupings = _.reject(subcategory.groupings, (group:IGroup) => { - return group.uniqueId === uniqueId; - }); - if (subcategory.groupings.length == 0) { // if there is no groups, delete the subcategory - category.subcategories = _.reject(category.subcategories, (subcategoryObj:ISubCategory) => { - return subcategoryObj.uniqueId === subcategory.uniqueId; - }); - if (category.subcategories.length == 0) { // if there is no subcategory, delete the category - this.categories = _.reject(this.categories, (categoryObj:IMainCategory) => { - return categoryObj.uniqueId === category.uniqueId; - }); - } - } - }); - }); - }; - - private getCategoryObjectById = (categoriesArray:Array, categoryUniqueId:string):ICategoryBase => { - let categorySelected = _.find(categoriesArray, (category) => { - return category.uniqueId === categoryUniqueId; - }); - return categorySelected; - }; - - public addGroup = (category:IMainCategory, subcategory:ISubCategory, group:IGroup):void => { - if (!this.categories) { - this.categories = new Array(); - } - let existingCategory:IMainCategory = this.getCategoryObjectById(this.categories, category.uniqueId); - let newGroup = angular.copy(group); - newGroup.filterTerms = undefined; - newGroup.isDisabled = undefined; - if (!existingCategory) { - let newCategory:IMainCategory = angular.copy(category); - newCategory.filteredGroup = undefined; - newCategory.subcategories = []; - let newSubcategory:ISubCategory = angular.copy(subcategory); - newSubcategory.groupings = []; - newSubcategory.groupings.push(newGroup); - newCategory.subcategories.push(newSubcategory); - this.categories.push(newCategory); - } - else { - let existingSubcategory:ISubCategory = this.getCategoryObjectById(existingCategory.subcategories, subcategory.uniqueId); - if (!existingSubcategory) { - let newSubcategory:ISubCategory = angular.copy(subcategory); - newSubcategory.groupings = []; - newSubcategory.groupings.push(newGroup); - existingCategory.subcategories.push(newSubcategory); - - } else { - let existingGroup:IGroup = this.getCategoryObjectById(existingSubcategory.groupings, group.uniqueId); - if (!existingGroup) { - existingSubcategory.groupings.push(newGroup); - } - } - } - }; - - getTypeUrl():string { - return 'products/'; - } - - public setComponentMetadata(componentMetadata:ComponentMetadata) { - super.setComponentMetadata(componentMetadata); - this.setComponentDisplayData(); - }; - - setComponentDisplayData():void { - this.filterTerm = this.name + ' ' + this.description + ' ' + (this.tags ? this.tags.toString() : '') + ' ' + this.version; - this.iconSprite = "sprite-product-icons"; - } -} - - diff --git a/catalog-ui/src/app/models/components/resource.ts b/catalog-ui/src/app/models/components/resource.ts index 9f7a123486..138b413028 100644 --- a/catalog-ui/src/app/models/components/resource.ts +++ b/catalog-ui/src/app/models/components/resource.ts @@ -41,6 +41,7 @@ export class Resource extends Component { public payloadData:string; public payloadName:string; public importedFile:FileUploadModel; + public resourceVendorModelNumber:string; // Onboarding parameters public csarUUID:string; @@ -59,6 +60,7 @@ export class Resource extends Component { this.resourceType = component.resourceType; this.csarUUID = component.csarUUID; this.csarVersion = component.csarVersion; + this.resourceVendorModelNumber = component.resourceVendorModelNumber; this.filterTerm = this.name + ' ' + this.description + ' ' + (this.tags ? this.tags.toString() : '') + ' ' + this.version + ' ' + this.resourceType; if (component.categories && component.categories[0] && component.categories[0].subcategories && component.categories[0].subcategories[0]) { component.mainCategory = component.categories[0].name; @@ -80,6 +82,7 @@ export class Resource extends Component { this.csarUUID = componentMetadata.csarUUID; this.csarVersion = componentMetadata.csarVersion; this.derivedFrom = componentMetadata.derivedFrom; + this.resourceVendorModelNumber = componentMetadata.resourceVendorModelNumber; this.setComponentDisplayData(); }; @@ -88,7 +91,7 @@ export class Resource extends Component { }; public isComplex = ():boolean => { - return this.resourceType === ResourceType.VF; + return this.resourceType === ResourceType.VF || this.resourceType === ResourceType.PNF || this.resourceType === ResourceType.CVFC; }; public isVl = ():boolean => { diff --git a/catalog-ui/src/app/models/components/service.ts b/catalog-ui/src/app/models/components/service.ts index fbe32519c3..90a38e895b 100644 --- a/catalog-ui/src/app/models/components/service.ts +++ b/catalog-ui/src/app/models/components/service.ts @@ -34,6 +34,8 @@ export class Service extends Component { public componentService:IServiceService; public ecompGeneratedNaming:boolean; public namingPolicy:string; + public serviceType:string; + public serviceRole:string; constructor(componentService:IServiceService, $q:ng.IQService, component?:Service) { super(componentService, $q, component); @@ -43,6 +45,8 @@ export class Service extends Component { this.filterTerm = this.name + ' ' + this.description + ' ' + (this.tags ? this.tags.toString() : '') + ' ' + this.version; this.ecompGeneratedNaming = component.ecompGeneratedNaming; this.namingPolicy = component.namingPolicy; + this.serviceType = component.serviceType; + this.serviceRole = component.serviceRole; if (component.categories && component.categories[0]) { this.mainCategory = component.categories[0].name; this.selectedCategory = this.mainCategory; @@ -155,6 +159,8 @@ export class Service extends Component { super.setComponentMetadata(componentMetadata); this.ecompGeneratedNaming = componentMetadata.ecompGeneratedNaming; this.namingPolicy = componentMetadata.namingPolicy; + this.serviceType = componentMetadata.serviceType; + this.serviceRole = componentMetadata.serviceRole; this.setComponentDisplayData(); } diff --git a/catalog-ui/src/app/models/componentsInstances/componentInstance.ts b/catalog-ui/src/app/models/componentsInstances/componentInstance.ts index 726e3382ba..06939a7a9e 100644 --- a/catalog-ui/src/app/models/componentsInstances/componentInstance.ts +++ b/catalog-ui/src/app/models/componentsInstances/componentInstance.ts @@ -52,6 +52,7 @@ export class ComponentInstance { public inputs:Array; public properties:Array; public groupInstances:Array; + public invariantName:string; constructor(componentInstance?:ComponentInstance) { @@ -77,6 +78,7 @@ export class ComponentInstance { this.customizationUUID = componentInstance.customizationUUID; this.updatePosition(componentInstance.posX, componentInstance.posY); this.groupInstances = componentInstance.groupInstances; + this.invariantName = componentInstance.invariantName; } } @@ -92,7 +94,7 @@ export class ComponentInstance { }; public isComplex = () : boolean => { - return this.originType === ResourceType.VF; + return this.originType === ResourceType.VF || this.originType === ResourceType.PNF || this.originType === ResourceType.CVFC ; } public setInstanceRC = ():void=> { diff --git a/catalog-ui/src/app/models/componentsInstances/productInstance.ts b/catalog-ui/src/app/models/componentsInstances/productInstance.ts deleted file mode 100644 index 91f0999b9a..0000000000 --- a/catalog-ui/src/app/models/componentsInstances/productInstance.ts +++ /dev/null @@ -1,33 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * SDC - * ================================================================================ - * 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. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -/** - * Created by obarda on 2/4/2016. - */ -'use strict'; -import {ComponentInstance} from "./componentInstance"; - -export class ProductInstance extends ComponentInstance { - - constructor(componentInstance?:ProductInstance) { - super(componentInstance); - this.iconSprite = "sprite-product-icons"; - } -} diff --git a/catalog-ui/src/app/models/modal.ts b/catalog-ui/src/app/models/modal.ts new file mode 100644 index 0000000000..51aa5e19a7 --- /dev/null +++ b/catalog-ui/src/app/models/modal.ts @@ -0,0 +1,16 @@ +import { ButtonModel } from 'app/models'; + +export class ModalModel { + size: string; 'xl|l|md|sm|xsm' + title: string; + content: any; + buttons: Array; + + constructor(size?: string, title?: string, content?: any, buttons?: Array) { + this.size = size; + this.title = title; + this.content = content; + this.buttons = buttons; + } +} + diff --git a/catalog-ui/src/app/models/properties-inputs/input-fe-model.ts b/catalog-ui/src/app/models/properties-inputs/input-fe-model.ts index 04a224bff7..630374aac3 100644 --- a/catalog-ui/src/app/models/properties-inputs/input-fe-model.ts +++ b/catalog-ui/src/app/models/properties-inputs/input-fe-model.ts @@ -40,4 +40,4 @@ export class InputFEModel extends InputBEModel { } } -} +} \ No newline at end of file diff --git a/catalog-ui/src/app/models/properties-inputs/property-fe-model.ts b/catalog-ui/src/app/models/properties-inputs/property-fe-model.ts index 78d01d9af2..b35bb27b65 100644 --- a/catalog-ui/src/app/models/properties-inputs/property-fe-model.ts +++ b/catalog-ui/src/app/models/properties-inputs/property-fe-model.ts @@ -55,7 +55,7 @@ export class PropertyFEModel extends PropertyBEModel { } catch (e){} } - return (this.derivedDataType == DerivedPropertyType.SIMPLE) ? this.valueObj : JSON.stringify(this.valueObj); + return (this.derivedDataType == DerivedPropertyType.SIMPLE) ? this.valueObj : JSON.stringify(this.valueObj); } public setNonDeclared = (childPath?: string): void => { @@ -101,16 +101,16 @@ export class PropertyFEModel extends PropertyBEModel { // this.flattenedChildren.filter(prop => prop.parentName == item.parentName).map(prop => prop.propertiesName).indexOf(item.propertiesName) // } - /* Updates parent valueObj when a child prop's value has changed */ - public childPropUpdated = (childProp: DerivedFEProperty): void => { + /* Updates parent valueObj when a child prop's value has changed */ + public childPropUpdated = (childProp: DerivedFEProperty): void => { let parentNames = this.getParentNamesArray(childProp.propertiesName, []); if (parentNames.length) { _.set(this.valueObj, parentNames.join('.'), childProp.valueObj); } }; - /* Returns array of individual parents for given prop path, with list/map UUIDs replaced with index/mapkey */ - private getParentNamesArray = (parentPropName: string, parentNames?: Array): Array => { + /* Returns array of individual parents for given prop path, with list/map UUIDs replaced with index/mapkey */ + public getParentNamesArray = (parentPropName: string, parentNames?: Array): Array => { if (parentPropName.indexOf("#") == -1) { return parentNames; } //finished recursing parents. return let parentProp: DerivedFEProperty = this.flattenedChildren.find(prop => prop.propertiesName === parentPropName); diff --git a/catalog-ui/src/app/models/user.ts b/catalog-ui/src/app/models/user.ts index ec42aed553..54ddf1e5f6 100644 --- a/catalog-ui/src/app/models/user.ts +++ b/catalog-ui/src/app/models/user.ts @@ -26,9 +26,7 @@ export enum UserRole { DESIGNER, TESTER, GOVERNOR, - OPS, - PRODUCT_MANAGER, - PRODUCT_STRATEGIST + OPS } export interface IUserManager { @@ -99,12 +97,6 @@ export class User implements IUser { case UserRole.OPS: role = UserRole.OPS; break; - case UserRole.PRODUCT_MANAGER: - role = UserRole.PRODUCT_MANAGER; - break; - case UserRole.PRODUCT_STRATEGIST: - role = UserRole.PRODUCT_STRATEGIST; - break; } return role; } diff --git a/catalog-ui/src/app/modules/service-module.ts b/catalog-ui/src/app/modules/service-module.ts index bf9ebce749..99624ada45 100644 --- a/catalog-ui/src/app/modules/service-module.ts +++ b/catalog-ui/src/app/modules/service-module.ts @@ -35,7 +35,6 @@ import {DataTypesService} from "../services/data-types-service"; import {ComponentService} from "../services/components/component-service"; import {ServiceService} from "../services/components/service-service"; import {ResourceService} from "../services/components/resource-service"; -import {ProductService} from "../services/components/product-service"; import {LeftPaletteLoaderService} from "../services/components/utils/composition-left-palette-service"; import {EventListenerService} from "../services/event-listener-service"; import {ProgressService} from "../services/progress-service"; @@ -69,7 +68,6 @@ serviceModule.service('Sdc.Services.DataTypesService', DataTypesService); serviceModule.service('Sdc.Services.Components.ComponentService', ComponentService); serviceModule.service('Sdc.Services.Components.ServiceService',ServiceService); serviceModule.service('Sdc.Services.Components.ResourceService', ResourceService); -serviceModule.service('Sdc.Services.Components.ProductService', ProductService); serviceModule.service('LeftPaletteLoaderService', LeftPaletteLoaderService); serviceModule.service('EventListenerService', EventListenerService); serviceModule.service('Sdc.Services.ProgressService', ProgressService); diff --git a/catalog-ui/src/app/modules/view-model-module.ts b/catalog-ui/src/app/modules/view-model-module.ts index de7bc5ac1f..f94bfc3218 100644 --- a/catalog-ui/src/app/modules/view-model-module.ts +++ b/catalog-ui/src/app/modules/view-model-module.ts @@ -56,13 +56,12 @@ import {OnboardingModalViewModel} from "../view-models/modals/onboarding-modal/o import {DistributionStatusModalViewModel} from "../view-models/workspace/tabs/distribution/disribution-status-modal/disribution-status-modal-view-model"; import {DcaeAppViewModel} from "../view-models/dcae-app/dcae-app-view-model"; import {GeneralViewModel} from "../view-models/workspace/tabs/general/general-view-model"; -import {IconsViewModel} from "../view-models/workspace/tabs/icons/icons-view-model"; +import {IconsModalViewModel} from "../view-models/modals/icons-modal/icons-modal-view"; import {DeploymentArtifactsViewModel} from "../view-models/workspace/tabs/deployment-artifacts/deployment-artifacts-view-model"; import {InformationArtifactsViewModel} from "../view-models/workspace/tabs/information-artifacts/information-artifacts-view-model"; import {ToscaArtifactsViewModel} from "../view-models/workspace/tabs/tosca-artifacts/tosca-artifacts-view-model"; import {PropertiesViewModel} from "../view-models/workspace/tabs/properties/properties-view-model"; import {AttributesViewModel} from "../view-models/workspace/tabs/attributes/attributes-view-model"; -import {ProductHierarchyViewModel} from "../view-models/workspace/tabs/product-hierarchy/product-hierarchy-view-model"; import {ActivityLogViewModel} from "../view-models/workspace/tabs/activity-log/activity-log"; import {ManagementWorkflowViewModel} from "../view-models/workspace/tabs/management-workflow/management-workflow-view-model"; import {NetworkCallFlowViewModel} from "../view-models/workspace/tabs/network-call-flow/network-call-flow-view-model"; @@ -114,6 +113,7 @@ viewModelModule .controller(moduleName + '.UserManagementViewModel', UserManagementViewModel) .controller(moduleName + '.CategoryManagementViewModel', CategoryManagementViewModel) .controller(moduleName + '.OnboardingModalViewModel', OnboardingModalViewModel) + .controller(moduleName + '.IconsModalViewModel', IconsModalViewModel) .controller(moduleName + '.DistributionStatusModalViewModel', DistributionStatusModalViewModel) .controller(moduleName + '.DcaeAppViewModel', DcaeAppViewModel) // @@ -122,13 +122,11 @@ viewModelModule .controller(moduleName + '.ConformanceLevelModalViewModel', ConformanceLevelModalViewModel) .controller(moduleName + '.CompositionViewModel', CompositionViewModel) .controller(moduleName + '.GeneralViewModel', GeneralViewModel) - .controller(moduleName + '.IconsViewModel', IconsViewModel) .controller(moduleName + '.DeploymentArtifactsViewModel', DeploymentArtifactsViewModel) .controller(moduleName + '.InformationArtifactsViewModel', InformationArtifactsViewModel) .controller(moduleName + '.ToscaArtifactsViewModel', ToscaArtifactsViewModel) .controller(moduleName + '.PropertiesViewModel', PropertiesViewModel) .controller(moduleName + '.AttributesViewModel', AttributesViewModel) - .controller(moduleName + '.ProductHierarchyViewModel', ProductHierarchyViewModel) .controller(moduleName + '.ActivityLogViewModel', ActivityLogViewModel) .controller(moduleName + '.ManagementWorkflowViewModel', ManagementWorkflowViewModel) .controller(moduleName + '.NetworkCallFlowViewModel', NetworkCallFlowViewModel) diff --git a/catalog-ui/src/app/ng2/app.component.ts b/catalog-ui/src/app/ng2/app.component.ts index 58f483ae11..cb10581c93 100644 --- a/catalog-ui/src/app/ng2/app.component.ts +++ b/catalog-ui/src/app/ng2/app.component.ts @@ -18,7 +18,7 @@ * ============LICENSE_END========================================================= */ -import { Component, Inject } from '@angular/core'; +import { Component, Inject, ViewContainerRef } from '@angular/core'; import { AuthenticationService } from './services/authentication.service'; @Component({ @@ -28,7 +28,7 @@ import { AuthenticationService } from './services/authentication.service'; }) export class AppComponent { - constructor(auth:AuthenticationService){ + constructor(auth:AuthenticationService, public viewContainerRef:ViewContainerRef){ } diff --git a/catalog-ui/src/app/ng2/components/inputs-table/confirmation-delete-input/confirmation-delete-input.component.html b/catalog-ui/src/app/ng2/components/inputs-table/confirmation-delete-input/confirmation-delete-input.component.html deleted file mode 100644 index 7fdd95b304..0000000000 --- a/catalog-ui/src/app/ng2/components/inputs-table/confirmation-delete-input/confirmation-delete-input.component.html +++ /dev/null @@ -1,3 +0,0 @@ - - Are you sure you want to delete this input? - diff --git a/catalog-ui/src/app/ng2/components/inputs-table/confirmation-delete-input/confirmation-delete-input.component.ts b/catalog-ui/src/app/ng2/components/inputs-table/confirmation-delete-input/confirmation-delete-input.component.ts deleted file mode 100644 index f73692f525..0000000000 --- a/catalog-ui/src/app/ng2/components/inputs-table/confirmation-delete-input/confirmation-delete-input.component.ts +++ /dev/null @@ -1,58 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * SDC - * ================================================================================ - * 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. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -/** - * Created by rc2122 on 6/1/2017. - */ -import {Component, Output, EventEmitter, ViewChild} from "@angular/core"; -import {ButtonsModelMap, ButtonModel} from "app/models/button"; -import {ModalComponent} from "app/ng2/components/modal/modal.component"; - -@Component({ - selector: 'confirm-delete-input', - templateUrl: './confirmation-delete-input.component.html' -}) -export class ConfirmationDeleteInputComponent { - - @Output() deleteInput: EventEmitter = new EventEmitter(); - @ViewChild ('confirmationModal') confirmationModal:ModalComponent; - footerButtons:ButtonsModelMap = {}; - - constructor (){ - } - - ngOnInit() { - this.footerButtons['Delete'] = new ButtonModel('Delete', 'blue', this.onDeleteInput); - this.footerButtons['Close'] = new ButtonModel('Close', 'grey', this.closeModal); - } - - onDeleteInput = (input) => { - this.deleteInput.emit(input); - this.closeModal(); - }; - - openModal = () => { - this.confirmationModal.open(); - } - - closeModal = () => { - this.confirmationModal.close(); - } -} diff --git a/catalog-ui/src/app/ng2/components/inputs-table/inputs-table.component.html b/catalog-ui/src/app/ng2/components/inputs-table/inputs-table.component.html index 331415c26f..38de3ce649 100644 --- a/catalog-ui/src/app/ng2/components/inputs-table/inputs-table.component.html +++ b/catalog-ui/src/app/ng2/components/inputs-table/inputs-table.component.html @@ -45,6 +45,5 @@
    - diff --git a/catalog-ui/src/app/ng2/components/inputs-table/inputs-table.component.ts b/catalog-ui/src/app/ng2/components/inputs-table/inputs-table.component.ts index 526f5de360..30cdb89d8e 100644 --- a/catalog-ui/src/app/ng2/components/inputs-table/inputs-table.component.ts +++ b/catalog-ui/src/app/ng2/components/inputs-table/inputs-table.component.ts @@ -23,7 +23,9 @@ */ import {Component, Input, Output, EventEmitter, ViewChild} from "@angular/core"; import {InputFEModel} from "app/models"; -import {ConfirmationDeleteInputComponent} from "./confirmation-delete-input/confirmation-delete-input.component"; +import { ModalService } from 'app/ng2/services/modal.service'; + + @Component({ selector: 'inputs-table', @@ -38,11 +40,10 @@ export class InputsTableComponent { @Input() isLoading:boolean; @Output() inputValueChanged: EventEmitter = new EventEmitter(); @Output() deleteInput: EventEmitter = new EventEmitter(); - @ViewChild ('deleteInputConfirmation') deleteInputConfirmation:ConfirmationDeleteInputComponent; selectedInputToDelete:InputFEModel; - constructor (){ + constructor(private modalService: ModalService){ } onInputValueChanged = (input) => { @@ -51,11 +52,12 @@ export class InputsTableComponent { onDeleteInput = () => { this.deleteInput.emit(this.selectedInputToDelete); + this.modalService.closeCurrentModal(); }; openDeleteModal = (input:InputFEModel) => { this.selectedInputToDelete = input; - this.deleteInputConfirmation.openModal(); + this.modalService.openActionModal("Delete Input", "Are you sure you want to delete this input?", "Delete", this.onDeleteInput, "Close"); } } diff --git a/catalog-ui/src/app/ng2/components/modal/modal.component.html b/catalog-ui/src/app/ng2/components/modal/modal.component.html index 4882449596..cc411bc751 100644 --- a/catalog-ui/src/app/ng2/components/modal/modal.component.html +++ b/catalog-ui/src/app/ng2/components/modal/modal.component.html @@ -1,17 +1,15 @@ -
    +
    - {{ title }} + {{ input.title }}
    -
    - -
    +
    {{input.content}}
    diff --git a/catalog-ui/src/app/ng2/components/modal/modal.component.ts b/catalog-ui/src/app/ng2/components/modal/modal.component.ts index e432a6fde0..09fb9abdd1 100644 --- a/catalog-ui/src/app/ng2/components/modal/modal.component.ts +++ b/catalog-ui/src/app/ng2/components/modal/modal.component.ts @@ -22,8 +22,9 @@ * Created by rc2122 on 6/1/2017. */ import { Component, ElementRef, Input, OnInit, OnDestroy } from '@angular/core'; +//import {ViewContainerRef, ViewChild} from '@angular/core'; import * as $ from 'jquery'; -import {ButtonsModelMap} from "app/models/button"; +import { ButtonsModelMap, ModalModel } from 'app/models'; @Component({ selector: 'modal', @@ -32,22 +33,17 @@ import {ButtonsModelMap} from "app/models/button"; }) export class ModalComponent implements OnInit, OnDestroy { - @Input() size: string; 'xl|l|md|sm|xsm' - @Input() title: string; - @Input() public buttons:ButtonsModelMap; + @Input() input: ModalModel; private modalElement: JQuery; - private buttonsNames:Array; + //@ViewChild('modalBody', { read: ViewContainerRef }) modalContainer: ViewContainerRef; //TODO: allow for custom component as body instead of simple message + constructor( el: ElementRef ) { this.modalElement = $(el.nativeElement); } ngOnInit(): void { - let modal = this; this.modalElement.appendTo('body'); - if(this.buttons){ - this.buttonsNames = Object.keys(this.buttons); - } } ngOnDestroy(): void { diff --git a/catalog-ui/src/app/ng2/components/modal/modal.module.ts b/catalog-ui/src/app/ng2/components/modal/modal.module.ts new file mode 100644 index 0000000000..d77be2cd23 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/modal/modal.module.ts @@ -0,0 +1,19 @@ +import { NgModule } from "@angular/core"; +import { CommonModule } from '@angular/common'; +import { ModalService } from 'app/ng2/services/modal.service'; +import { ModalComponent } from "app/ng2/components/modal/modal.component" + +@NgModule({ + declarations: [ + ModalComponent, + ], + imports: [CommonModule], + exports: [], + entryComponents: [ + ModalComponent + ], + providers: [ModalService] +}) +export class ModalModule { + +} \ No newline at end of file diff --git a/catalog-ui/src/app/ng2/components/properties-table/dynamic-property/dynamic-property.component.html b/catalog-ui/src/app/ng2/components/properties-table/dynamic-property/dynamic-property.component.html index 92948b3b0d..95cc79dce9 100644 --- a/catalog-ui/src/app/ng2/components/properties-table/dynamic-property/dynamic-property.component.html +++ b/catalog-ui/src/app/ng2/components/properties-table/dynamic-property/dynamic-property.component.html @@ -5,12 +5,12 @@
    - +
    {{property.name}}
    {{property.name}}
    - +
    @@ -36,7 +36,7 @@ - Add value to list + Add value to list diff --git a/catalog-ui/src/app/ng2/components/properties-table/dynamic-property/dynamic-property.component.less b/catalog-ui/src/app/ng2/components/properties-table/dynamic-property/dynamic-property.component.less index 4da98ec736..48d3d035d0 100644 --- a/catalog-ui/src/app/ng2/components/properties-table/dynamic-property/dynamic-property.component.less +++ b/catalog-ui/src/app/ng2/components/properties-table/dynamic-property/dynamic-property.component.less @@ -1,3 +1,4 @@ +@import '../../../../../assets/styles/variables.less'; .flat-children-container { .dynamic-property-row { /*create nested left border classes for up to 10 levels of nesting*/ @@ -64,4 +65,10 @@ overflow: hidden; display: inline; padding-left: 8px; -} \ No newline at end of file +} +.error { + border: solid 1px @func_color_q; + color: @func_color_q; + outline: none; + box-sizing: border-box; +} diff --git a/catalog-ui/src/app/ng2/components/properties-table/dynamic-property/dynamic-property.component.ts b/catalog-ui/src/app/ng2/components/properties-table/dynamic-property/dynamic-property.component.ts index e078b74d65..59811b582d 100644 --- a/catalog-ui/src/app/ng2/components/properties-table/dynamic-property/dynamic-property.component.ts +++ b/catalog-ui/src/app/ng2/components/properties-table/dynamic-property/dynamic-property.component.ts @@ -88,7 +88,7 @@ export class DynamicPropertyComponent { } createNewChildProperty = (): void => { - + let newProps: Array = this.propertiesUtils.createListOrMapChildren(this.property, "", undefined); if (this.property instanceof PropertyFEModel) { this.addChildProps(newProps, this.property.name); @@ -98,11 +98,22 @@ export class DynamicPropertyComponent { } addChildProps = (newProps: Array, childPropName: string) => { - + if (this.property instanceof PropertyFEModel) { - let insertIndex: number = this.property.getIndexOfChild(childPropName) + this.property.getCountOfChildren(childPropName); //insert after parent prop and existing children - this.property.flattenedChildren.splice(insertIndex, 0, ...newProps); //using ES6 spread operator + let insertIndex: number = this.property.getIndexOfChild(childPropName) + this.property.getCountOfChildren(childPropName); //insert after parent prop and existing children + this.property.flattenedChildren.splice(insertIndex, 0, ...newProps); //using ES6 spread operator this.expandChildById(newProps[0].propertiesName); + + + if(!newProps[0].schema.property.isSimpleType){ + angular.forEach(newProps, (prop:DerivedFEProperty):void => { //Update parent PropertyFEModel with value for each child, including nested props + (this.property).childPropUpdated(prop); + },this); + //grab the cumulative value for the new item from parent PropertyFEModel and assign that value to DerivedFEProp[0] (which is the list or map parent with UUID of the set we just added) + let parentNames = (this.property).getParentNamesArray(newProps[0].propertiesName, []); + newProps[0].valueObj = _.get(this.property.valueObj, parentNames.join('.')); + this.valueChanged.emit(this.property.name); + } } } @@ -113,7 +124,7 @@ export class DynamicPropertyComponent { this.dataTypeService.checkForCustomBehavior(this.property); this.valueChanged.emit(this.property.name); } - } + } deleteListOrMapItem = (item: DerivedFEProperty) => { if (this.property instanceof PropertyFEModel) { @@ -123,15 +134,22 @@ export class DynamicPropertyComponent { } } - removeValueFromParent = (item: DerivedFEProperty, replaceKey?: string) => { + removeValueFromParent = (item: DerivedFEProperty, target?: any) => { if (this.property instanceof PropertyFEModel) { let itemParent = (item.parentName == this.property.name) ? this.property : this.property.flattenedChildren.find(prop => prop.propertiesName == item.parentName); if (item.derivedDataType == DerivedPropertyType.MAP) { let oldKey = item.mapKey; - if (typeof replaceKey == 'string') { //allow saving empty string - _.set(itemParent.valueObj, replaceKey, itemParent.valueObj[oldKey]); - item.mapKey = replaceKey; + if (target && typeof target.value == 'string') { //allow saving empty string + let replaceKey:string = target.value; + if(Object.keys(itemParent.valueObj).indexOf(replaceKey) > -1){//the key is exists + target.setCustomValidity('This key is already exists.'); + return; + }else { + target.setCustomValidity(''); + _.set(itemParent.valueObj, replaceKey, itemParent.valueObj[oldKey]); + item.mapKey = replaceKey; + } } delete itemParent.valueObj[oldKey]; } else { @@ -147,4 +165,11 @@ export class DynamicPropertyComponent { } } + preventInsertItem = (property:DerivedFEProperty):boolean => { + if(property.type == PROPERTY_TYPES.MAP && Object.keys(property.valueObj).indexOf('') > -1 ){ + return true; + } + return false; + } + } diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.module.ts b/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.module.ts index 1e09c9e4c6..3a5daba711 100644 --- a/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.module.ts +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.module.ts @@ -37,14 +37,13 @@ import { HierarchyNavService } from './../../services/hierarchy-nav.service'; import { PropertiesUtils } from './properties.utils'; import { DynamicElementModule } from 'app/ng2/components/dynamic-element/dynamic-element.module'; import { DynamicPropertyComponent } from './../../components/properties-table/dynamic-property/dynamic-property.component'; -import {ConfirmationDeleteInputComponent} from "app/ng2/components/inputs-table/confirmation-delete-input/confirmation-delete-input.component" -import { PopoverModule } from "../../components/popover/popover.module" +import { PopoverModule } from "../../components/popover/popover.module"; +import { ModalModule } from "../../components/modal/modal.module"; import { FilterPropertiesAssignmentComponent } from "./../../components/filter-properties-assignment/filter-properties-assignment.component"; import { GroupByPipe } from 'app/ng2/pipes/groupBy.pipe'; import { KeysPipe } from 'app/ng2/pipes/keys.pipe'; import {TooltipModule} from "../../components/tooltip/tooltip.module"; import { ComponentModeService } from "app/ng2/services/component-mode.service" -import { ModalComponent } from "app/ng2/components/modal/modal.component" import {LoaderComponent} from "app/ng2/components/loader/loader.component" import {HttpInterceptor} from "../../services/http.interceptor.service"; @@ -63,8 +62,6 @@ import {HttpInterceptor} from "../../services/http.interceptor.service"; // PopoverContentComponent, // PopoverComponent, FilterPropertiesAssignmentComponent, - ModalComponent, - ConfirmationDeleteInputComponent, LoaderComponent ], imports: [ @@ -75,7 +72,8 @@ import {HttpInterceptor} from "../../services/http.interceptor.service"; CheckboxModule, DynamicElementModule, PopoverModule, - TooltipModule + TooltipModule, + ModalModule ], entryComponents: [PropertiesAssignmentComponent], exports: [ diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.less b/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.less index ab059b1240..8151d001e8 100644 --- a/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.less +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.less @@ -27,7 +27,6 @@ .left-column { flex: 1 0 500px; position: relative; - margin: 0 0 1em 0; /deep/ .tabs { width:33%; @@ -119,7 +118,7 @@ display:flex; flex:0 0 350px; flex-direction:column; - margin: 45px 0 1em 1em; + margin: 45px 0 0 1em; overflow-x:auto; /deep/ .tabs { diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.ts b/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.ts index 30ba6c0755..6782b72fa2 100644 --- a/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.ts +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.ts @@ -170,6 +170,10 @@ export class PropertiesAssignmentComponent { }); } + if(resourceInstance.componentName === "vnfConfiguration") { + this.isReadonly = true; + } + if( this.searchPropertyName ){ this.clearSearch(); } @@ -298,7 +302,7 @@ export class PropertiesAssignmentComponent { angular.forEach(instancesIds, (instanceId: string): void => { let selectedInstanceData: ResourceInstance = this.instances.find(instance => instance.uniqueId == instanceId); - let originType: string = (selectedInstanceData) ? selectedInstanceData.originType : this.selectedInstanceType; + let originType: string = (selectedInstanceData) ? selectedInstanceData.originType : this.selectedInstanceType; if (!this.isInput(originType)) { selectedProperties[instanceId] = this.propertiesService.getCheckedProperties(this.instanceFePropertiesMap[instanceId]); } else { @@ -408,7 +412,7 @@ export class PropertiesAssignmentComponent { }; private isInput = (instanceType:string):boolean =>{ - return instanceType === ResourceType.VF || instanceType === ResourceType.PNF; + return instanceType === ResourceType.VF || instanceType === ResourceType.PNF || instanceType === ResourceType.CVFC; } } diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/properties.utils.ts b/catalog-ui/src/app/ng2/pages/properties-assignment/properties.utils.ts index f876af7f8a..a04d23a16a 100644 --- a/catalog-ui/src/app/ng2/pages/properties-assignment/properties.utils.ts +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/properties.utils.ts @@ -139,8 +139,11 @@ export class PropertiesUtils { let propNameInObj = prop.propertiesName.substring(prop.propertiesName.indexOf(parentName) + parentName.length + 1).split('#').join('.'); //extract everything after parent name prop.valueObj = _.get(parentValueJSON, propNameInObj, prop.value || prop.defaultValue); //assign value -first value of parent if exists. If not, prop.value if not, prop.defaultvalue - if ((prop.derivedDataType == DerivedPropertyType.SIMPLE || prop.isDeclared) && typeof prop.valueObj == 'object') { //Stringify objects that should be strings + if ( prop.isDeclared && typeof prop.valueObj == 'object') { //Stringify objects of items that are declared prop.valueObj = JSON.stringify(prop.valueObj); + } else if(typeof prop.valueObj == PROPERTY_TYPES.STRING + && (prop.type == PROPERTY_TYPES.INTEGER || prop.type == PROPERTY_TYPES.FLOAT || prop.type == PROPERTY_TYPES.BOOLEAN)){ //parse ints and non-string simple types + prop.valueObj = JSON.parse(prop.valueObj); } else { //parse strings that should be objects if (prop.derivedDataType == DerivedPropertyType.COMPLEX && typeof prop.valueObj != 'object') { prop.valueObj = JSON.parse(prop.valueObj || '{}'); diff --git a/catalog-ui/src/app/ng2/services/component-services/component.service.ts b/catalog-ui/src/app/ng2/services/component-services/component.service.ts index c6865fde9d..cd593d5e3e 100644 --- a/catalog-ui/src/app/ng2/services/component-services/component.service.ts +++ b/catalog-ui/src/app/ng2/services/component-services/component.service.ts @@ -59,8 +59,6 @@ export class ComponentServiceNg2 { private getServerTypeUrl = (componentType:string):string => { switch (componentType) { - case ComponentType.PRODUCT: - return ServerTypeUrl.PRODUCTS; case ComponentType.SERVICE: return ServerTypeUrl.SERVICES; default: diff --git a/catalog-ui/src/app/ng2/services/http.interceptor.service.ts b/catalog-ui/src/app/ng2/services/http.interceptor.service.ts index e1653cf0bc..c90bfd2848 100644 --- a/catalog-ui/src/app/ng2/services/http.interceptor.service.ts +++ b/catalog-ui/src/app/ng2/services/http.interceptor.service.ts @@ -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,8 +21,8 @@ import 'rxjs/add/operator/map'; import 'rxjs/add/operator/toPromise'; import 'rxjs/Rx'; -import { sdc2Config } from './../../../main'; -import { Interceptor, InterceptedRequest, InterceptedResponse } from 'ng2-interceptors'; +import {sdc2Config} from './../../../main'; +import {Interceptor, InterceptedRequest, InterceptedResponse} from 'ng2-interceptors'; import {SharingService} from "../../services/sharing-service"; import {ReflectiveInjector} from '@angular/core'; import {Cookie2Service} from "./cookie.service"; @@ -31,23 +31,23 @@ import {Dictionary} from "../../utils/dictionary/dictionary"; import {SEVERITY} from "../../utils/constants"; import {IServerMessageModalModel} from "../../view-models/modals/message-modal/message-server-modal/server-message-modal-view-model"; + export class HttpInterceptor implements Interceptor { - private cookieService: Cookie2Service; + private cookieService:Cookie2Service; private sharingService:SharingService; + constructor() { - let injector = ReflectiveInjector.resolveAndCreate([Cookie2Service,SharingService]); + let injector = ReflectiveInjector.resolveAndCreate([Cookie2Service, SharingService]); this.cookieService = injector.get(Cookie2Service); this.sharingService = injector.get(SharingService); } - public interceptBefore(request: InterceptedRequest): InterceptedRequest { - + public interceptBefore(request:InterceptedRequest):InterceptedRequest { /** * For every request to the server, that the service id, or resource id is sent in the URL, need to pass UUID in the header. * Check if the unique id exists in uuidMap, and if so get the UUID and add it to the header. */ - request.options.headers.append(this.cookieService.getUserIdSuffix(), this.cookieService.getUserId()); request.options.withCredentials = true; var uuidValue = this.getUuidValue(request.url); @@ -56,7 +56,6 @@ export class HttpInterceptor implements Interceptor { } request.options.headers.set('X-ECOMP-RequestID', UUID.UUID()); return request; - } public interceptAfter(response:InterceptedResponse):InterceptedResponse { @@ -66,10 +65,9 @@ export class HttpInterceptor implements Interceptor { //console.log("Error from BE:",response); } return response; - } - private getUuidValue = (url: string) :string => { + private getUuidValue = (url:string):string => { let map:Dictionary = this.sharingService.getUuidMap(); if (map && url.indexOf(sdc2Config.api.root) > 0) { map.forEach((key:string) => { @@ -158,9 +156,7 @@ export class HttpInterceptor implements Interceptor { severity: SEVERITY.ERROR }; } - // let modalsHandler = this.$injector.get('ModalsHandler'); - // this.modalsHandler.openServerMessageModal(data); console.error('ERROR data',data); } } diff --git a/catalog-ui/src/app/ng2/services/modal.service.ts b/catalog-ui/src/app/ng2/services/modal.service.ts new file mode 100644 index 0000000000..32192f40c2 --- /dev/null +++ b/catalog-ui/src/app/ng2/services/modal.service.ts @@ -0,0 +1,73 @@ +import { Injectable, Type, ViewContainerRef, ApplicationRef, ComponentFactory, ComponentFactoryResolver, ComponentRef } from '@angular/core'; +import { ModalModel, ButtonModel } from 'app/models'; +import { ModalComponent } from 'app/ng2/components/modal/modal.component'; + + +@Injectable() +export class ModalService { + currentModal: ComponentRef; + + + constructor(private componentFactoryResolver: ComponentFactoryResolver, private applicationRef: ApplicationRef) { } + + + /* Shortcut method to open a simple modal with title, message, and close button that simply closes the modal. */ + public openAlertModal(title: string, message: string, closeButtonText?:string) { + let closeButton: ButtonModel = new ButtonModel(closeButtonText || 'Close', 'grey', this.closeCurrentModal); + let modalModel: ModalModel = new ModalModel('sm', title, message, [closeButton]); + this.createCustomModal(modalModel).instance.open(); + } + + + /** + * Shortcut method to open a basic modal with title, message, and an action button with callback, as well as close button. + * NOTE: To close the modal from within the callback, use modalService.closeCurrentModal() //if you run into zone issues with callbacks see:https://stackoverflow.com/questions/36566698/how-to-dynamically-create-bootstrap-modals-as-angular2-components + * @param title Heading for modal + * @param message Message for modal + * @param actionButtonText Blue call to action button + * @param actionButtonCallback function to invoke when button is clicked + * @param cancelButtonText text for close/cancel button + */ + public openActionModal = (title:string, message:string, actionButtonText:string, actionButtonCallback:Function, cancelButtonText:string) => { + let actionButton: ButtonModel = new ButtonModel(actionButtonText, 'blue', actionButtonCallback); + let cancelButton: ButtonModel = new ButtonModel(cancelButtonText, 'grey', this.closeCurrentModal); + let modalModel: ModalModel = new ModalModel('sm', title, message, [actionButton, cancelButton]); + this.createCustomModal(modalModel).instance.open(); + } + + + /* Use this method to create a modal with title, message, and completely custom buttons. Use response.instance.open() to open */ + public createCustomModal = (customModalData: ModalModel): ComponentRef => { + let customModal: ComponentRef = this.createDynamicComponent(ModalComponent); + customModal.instance.input = customModalData; + this.currentModal = customModal; + + return customModal; + } + + + public closeCurrentModal = () => { + if (!this.currentModal) return; + this.currentModal.instance.close(); + this.currentModal.destroy(); + } + + + //Creates a component dynamically (aka during runtime). If a view container is not specified, it will append the new component to the app root. + //To subscribe to an event from invoking component: componentRef.instance.clicked.subscribe((m) => console.log(m.name)); + private createDynamicComponent(componentType: Type, viewContainerRef?:ViewContainerRef): ComponentRef { + + viewContainerRef = viewContainerRef || this.getRootViewContainerRef(); + viewContainerRef.clear(); + + let factory: ComponentFactory = this.componentFactoryResolver.resolveComponentFactory(componentType); //Ref: https://angular.io/guide/dynamic-component-loader + let componentRef = viewContainerRef.createComponent(factory); + + return componentRef; + } + + + private getRootViewContainerRef(): ViewContainerRef { + return this.applicationRef.components[0].instance.viewContainerRef; + } +} \ No newline at end of file diff --git a/catalog-ui/src/app/services.ts b/catalog-ui/src/app/services.ts index ce4a8e32d3..5dd08c2d20 100644 --- a/catalog-ui/src/app/services.ts +++ b/catalog-ui/src/app/services.ts @@ -27,7 +27,6 @@ export * from './services/cache-service'; export * from './services/configuration-ui-service'; export * from './services/category-resource-service'; export * from './services/components/component-service'; -export * from './services/components/product-service'; export * from './services/components/resource-service'; export * from './services/components/service-service'; export * from './services/components/resource-service'; diff --git a/catalog-ui/src/app/services/available-icons-service.ts b/catalog-ui/src/app/services/available-icons-service.ts index ebb6c5ff77..13b6caea2a 100644 --- a/catalog-ui/src/app/services/available-icons-service.ts +++ b/catalog-ui/src/app/services/available-icons-service.ts @@ -81,23 +81,6 @@ export class AvailableIconsService implements IAvailableIconsService { 'firewall' ]; break; - - case ComponentType.PRODUCT: - icons = [ - 'vfw', - 'network', - 'security', - 'cloud', - 'setting', - 'orphan', - 'wanx', - 'vrouter', - 'ucpe', - 'mobility' - - ]; - break; - } return icons; } diff --git a/catalog-ui/src/app/services/components/product-service.ts b/catalog-ui/src/app/services/components/product-service.ts deleted file mode 100644 index 09199ea172..0000000000 --- a/catalog-ui/src/app/services/components/product-service.ts +++ /dev/null @@ -1,55 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * SDC - * ================================================================================ - * 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. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -/** - * Created by obarda on 2/8/2016. - */ -'use strict'; -import {IComponentService, ComponentService} from "./component-service"; -import {SharingService} from "../sharing-service"; -import {Product, Component, IAppConfigurtaion} from "../../models"; - -export interface IProductService extends IComponentService { - -} - -export class ProductService extends ComponentService implements IProductService { - - static '$inject' = [ - 'Restangular', - 'sdcConfig', - 'Sdc.Services.SharingService', - '$q', - '$base64' - ]; - - constructor(protected restangular:restangular.IElement, - protected sdcConfig:IAppConfigurtaion, - protected sharingService:SharingService, - protected $q:ng.IQService, - protected $base64:any) { - super(restangular, sdcConfig, sharingService, $q, $base64); - this.restangular = restangular.one("products"); - } - - createComponentObject = (component:Component):Component => { - return new Product(this, this.$q, component); - }; -} diff --git a/catalog-ui/src/app/services/components/utils/composition-left-palette-service.ts b/catalog-ui/src/app/services/components/utils/composition-left-palette-service.ts index 52cb78f6d5..a1fa65159f 100644 --- a/catalog-ui/src/app/services/components/utils/composition-left-palette-service.ts +++ b/catalog-ui/src/app/services/components/utils/composition-left-palette-service.ts @@ -28,6 +28,7 @@ import {ComponentFactory} from "../../../utils/component-factory"; import {IAppConfigurtaion} from "../../../models/app-config"; import {ResourceType, ComponentType, EVENTS} from "../../../utils/constants"; import {ComponentMetadata} from "../../../models/component-metadata"; +import {Resource} from "app/models/components/resource"; export class LeftPaletteDataObject { displayLeftPanelComponents:Array; @@ -58,24 +59,27 @@ export class LeftPaletteLoaderService { protected EventListenerService:EventListenerService) { this.restangular.setBaseUrl(sdcConfig.api.root + sdcConfig.api.component_api_root); - + } private serviceLeftPaletteData:LeftPaletteDataObject; private resourceLeftPaletteData:LeftPaletteDataObject; - private productLeftPaletteData:LeftPaletteDataObject; + private resourcePNFLeftPaletteData:LeftPaletteDataObject; private vlData:LeftPaletteDataObject; - public loadLeftPanel = (componentType: string):void => { + public loadLeftPanel = (component:Component):void => { this.serviceLeftPaletteData = new LeftPaletteDataObject(EVENTS.SERVICE_LEFT_PALETTE_UPDATE_EVENT); this.resourceLeftPaletteData = new LeftPaletteDataObject(EVENTS.RESOURCE_LEFT_PALETTE_UPDATE_EVENT); - this.updateComponentLeftPalette(componentType); + this.resourcePNFLeftPaletteData = new LeftPaletteDataObject(EVENTS.RESOURCE_PNF_LEFT_PALETTE_UPDATE_EVENT); + this.updateComponentLeftPalette(component); } - - private getTypeUrl = (componentType:string):string => { - return ComponentType.PRODUCT === componentType ? "services" : "resources"; - }; + private getResourceLeftPaletteDataByResourceType = (resourceType:string):LeftPaletteDataObject => { + if(resourceType == ResourceType.PNF) { + return this.resourcePNFLeftPaletteData; + } + return this.resourceLeftPaletteData; + } private onFinishLoading = (componentType:string, leftPaletteData:LeftPaletteDataObject):void => { this.EventListenerService.notifyObservers(leftPaletteData.onFinishLoadingEvent); @@ -83,7 +87,7 @@ export class LeftPaletteLoaderService { private updateLeftPalette = (componentType, componentInternalType:string, leftPaletteData:LeftPaletteDataObject):void => { - this.restangular.one(this.getTypeUrl(componentType)).one('/latestversion/notabstract/metadata').get({'internalComponentType': componentInternalType}).then((leftPaletteComponentMetadata:Array) => { + this.restangular.one("resources").one('/latestversion/notabstract/metadata').get({'internalComponentType': componentInternalType}).then((leftPaletteComponentMetadata:Array) => { _.forEach(leftPaletteComponentMetadata, (componentMetadata:ComponentMetadata) => { leftPaletteData.displayLeftPanelComponents.push(new LeftPaletteComponent(componentMetadata)); }); @@ -91,30 +95,25 @@ export class LeftPaletteLoaderService { }); }; - public getLeftPanelComponentsForDisplay = (componentType:string):Array => { - switch (componentType) { + public getLeftPanelComponentsForDisplay = (component:Component):Array => { + switch (component.componentType) { case ComponentType.SERVICE: return this.serviceLeftPaletteData.displayLeftPanelComponents; - case ComponentType.PRODUCT: - return this.productLeftPaletteData.displayLeftPanelComponents; - default: - return this.resourceLeftPaletteData.displayLeftPanelComponents; + default://resource + return this.getResourceLeftPaletteDataByResourceType((component).resourceType).displayLeftPanelComponents; } }; - public updateComponentLeftPalette = (componentType):void => { - switch (componentType) { - case ResourceType.VL: - this.updateLeftPalette(ComponentType.RESOURCE, ResourceType.VL, this.vlData); - break; + public updateComponentLeftPalette = (component:Component):void => { + switch (component.componentType) { case ComponentType.SERVICE: this.updateLeftPalette(ComponentType.SERVICE, ComponentType.SERVICE, this.serviceLeftPaletteData); break; - case ComponentType.PRODUCT: - this.updateLeftPalette(ComponentType.PRODUCT, ComponentType.SERVICE, this.productLeftPaletteData); + case ComponentType.RESOURCE: + this.updateLeftPalette(ComponentType.RESOURCE, (component).resourceType, this.getResourceLeftPaletteDataByResourceType((component).resourceType)); break; default: - this.updateLeftPalette(ComponentType.RESOURCE, ResourceType.VF, this.resourceLeftPaletteData); + console.log('ERROR: Component type '+ component.componentType + ' is not exists'); } }; } diff --git a/catalog-ui/src/app/services/data-types-service.ts b/catalog-ui/src/app/services/data-types-service.ts index a6dbf7f12d..84fe42e9f3 100644 --- a/catalog-ui/src/app/services/data-types-service.ts +++ b/catalog-ui/src/app/services/data-types-service.ts @@ -132,7 +132,8 @@ export class DataTypesService implements IDataTypesService { public isDataTypeForDataTypePropertyType = (property:DataTypePropertyModel):boolean=> { property.simpleType = ""; - if (property.type && PROPERTY_DATA.TYPES.indexOf(property.type) > -1) { + let isScalarForNFoD:boolean = property.type === 'scalar-unit.size'; + if (property.type && PROPERTY_DATA.TYPES.indexOf(property.type) > -1 || isScalarForNFoD) { return false; } let simpleType = this.getTypeForDataTypeDerivedFromSimple(property.type); diff --git a/catalog-ui/src/app/services/entity-service.ts b/catalog-ui/src/app/services/entity-service.ts index a255dcff34..75ea036b3e 100644 --- a/catalog-ui/src/app/services/entity-service.ts +++ b/catalog-ui/src/app/services/entity-service.ts @@ -19,7 +19,7 @@ */ 'use strict'; -import {Product, Service, IApi, IAppConfigurtaion, Resource, Component} from "../models"; +import { Service, IApi, IAppConfigurtaion, Resource, Component} from "../models"; import {SharingService} from "./sharing-service"; import {ComponentFactory} from "../utils/component-factory"; import {CacheService} from "./cache-service"; @@ -31,7 +31,6 @@ interface IEntityService { interface IComponentsArray { services:Array; resources:Array; - products:Array; } export class EntityService implements IEntityService { @@ -66,13 +65,6 @@ export class EntityService implements IEntityService { this.sharingService.addUuidValue(component.uniqueId, component.uuid); }); - followedResponse.products.forEach((productResponse:Product) => { - - let component:Product = this.ComponentFactory.createProduct(productResponse); - componentsList.push(component); - this.sharingService.addUuidValue(component.uniqueId, component.uuid); - }); - this.cacheService.set('breadcrumbsComponents', componentsList); defer.resolve(componentsList); },(responce) => { @@ -99,12 +91,7 @@ export class EntityService implements IEntityService { componentsList.push(component); this.sharingService.addUuidValue(component.uniqueId, component.uuid); }); - - componentResponse.products && componentResponse.products.forEach((productsResponse:Product) => { - let component:Product = this.ComponentFactory.createProduct(productsResponse); - componentsList.push(component); - this.sharingService.addUuidValue(component.uniqueId, component.uuid); - }); + this.cacheService.set('breadcrumbsComponents', componentsList); defer.resolve(componentsList); }); diff --git a/catalog-ui/src/app/utils/component-factory.ts b/catalog-ui/src/app/utils/component-factory.ts index c202a1c8f5..b35918c0f6 100644 --- a/catalog-ui/src/app/utils/component-factory.ts +++ b/catalog-ui/src/app/utils/component-factory.ts @@ -20,8 +20,8 @@ 'use strict'; import {DEFAULT_ICON, ResourceType, ComponentType} from "./constants"; -import {ServiceService, CacheService, ResourceService, ProductService} from "app/services"; -import {IMainCategory, ISubCategory, ICsarComponent, Component, Resource, Service, Product} from "app/models"; +import {ServiceService, CacheService, ResourceService} from "app/services"; +import {IMainCategory, ISubCategory, ICsarComponent, Component, Resource, Service} from "app/models"; import {ComponentMetadata} from "../models/component-metadata"; import {ComponentServiceNg2} from "../ng2/services/component-services/component.service"; import {ComponentGenericResponse} from "../ng2/services/responses/component-generic-response"; @@ -32,7 +32,6 @@ export class ComponentFactory { static '$inject' = [ 'Sdc.Services.Components.ResourceService', 'Sdc.Services.Components.ServiceService', - 'Sdc.Services.Components.ProductService', 'Sdc.Services.CacheService', '$q', 'ComponentServiceNg2' @@ -40,7 +39,6 @@ export class ComponentFactory { constructor(private ResourceService:ResourceService, private ServiceService:ServiceService, - private ProductService:ProductService, private cacheService:CacheService, private $q:ng.IQService, private ComponentServiceNg2: ComponentServiceNg2) { @@ -58,18 +56,10 @@ export class ComponentFactory { newComponent = new Resource(this.ResourceService, this.$q, component); break; - case 'PRODUCT': - newComponent = new Product(this.ProductService, this.$q, component); - break; } return newComponent; }; - public createProduct = (product:Product):Product => { - let newProduct:Product = new Product(this.ProductService, this.$q, product); - return newProduct; - }; - public createService = (service:Service):Service => { let newService:Service = new Service(this.ServiceService, this.$q, service); return newService; @@ -144,12 +134,10 @@ export class ComponentFactory { case ResourceType.VL: case ResourceType.VFC: case ResourceType.CP: + case ResourceType.PNF: + case ResourceType.CVFC: newComponent = new Resource(this.ResourceService, this.$q); break; - - case ComponentType.PRODUCT: - newComponent = new Product(this.ProductService, this.$q); - break; } newComponent.componentType = componentType; newComponent.tags = []; diff --git a/catalog-ui/src/app/utils/component-instance-factory.ts b/catalog-ui/src/app/utils/component-instance-factory.ts index c020c53705..9e25e6b02f 100644 --- a/catalog-ui/src/app/utils/component-instance-factory.ts +++ b/catalog-ui/src/app/utils/component-instance-factory.ts @@ -21,7 +21,7 @@ * Created by obarda on 3/7/2016. */ 'use strict'; -import {ComponentInstance, ServiceInstance, ProductInstance, ResourceInstance, Component} from "../models"; +import {ComponentInstance, ServiceInstance, ResourceInstance, Component} from "../models"; import {LeftPaletteComponent} from "../models/components/displayComponent"; export class ComponentInstanceFactory { @@ -33,10 +33,6 @@ export class ComponentInstanceFactory { newComponentInstance = new ServiceInstance(componentInstance); break; - case 'PRODUCT': - newComponentInstance = new ProductInstance(componentInstance); - break; - default : newComponentInstance = new ResourceInstance(componentInstance); break; @@ -51,10 +47,6 @@ export class ComponentInstanceFactory { newComponentInstance = new ServiceInstance(); break; - case 'PRODUCT': - newComponentInstance = new ProductInstance(); - break; - default : newComponentInstance = new ResourceInstance(); break; diff --git a/catalog-ui/src/app/utils/constants.ts b/catalog-ui/src/app/utils/constants.ts index 636c0c4fbf..d239019455 100644 --- a/catalog-ui/src/app/utils/constants.ts +++ b/catalog-ui/src/app/utils/constants.ts @@ -29,13 +29,11 @@ export let CHANGE_COMPONENT_CSAR_VERSION_FLAG = 'changeComponentCsarVersion'; export class ComponentType { static SERVICE = 'SERVICE'; static RESOURCE = 'RESOURCE'; - static PRODUCT = 'PRODUCT'; } export class ServerTypeUrl { static RESOURCES = 'resources/'; static SERVICES = 'services/'; - static PRODUCTS = 'product/'; } export class ResourceType { @@ -45,6 +43,7 @@ export class ResourceType { static VFC = 'VFC'; static VFCMT = 'VFCMT'; static PNF = 'PNF'; + static CVFC = 'CVFC'; } export class ComponentState { @@ -129,8 +128,6 @@ export class PROPERTY_VALUE_CONSTRAINTS { export class Role { public static ADMIN = 'ADMIN'; public static DESIGNER = 'DESIGNER'; - public static PRODUCT_STRATEGIST = 'PRODUCT_STRATEGIST'; - public static PRODUCT_MANAGER = 'PRODUCT_MANAGER'; public static TESTER = 'TESTER'; public static OPS = 'OPS'; public static GOVERNOR = 'GOVERNOR'; @@ -213,14 +210,12 @@ export class GraphUIObjects { export class States { public static WORKSPACE_GENERAL = 'workspace.general'; - public static WORKSPACE_ICONS = 'workspace.icons'; public static WORKSPACE_ACTIVITY_LOG = 'workspace.activity_log'; public static WORKSPACE_DEPLOYMENT_ARTIFACTS = 'workspace.deployment_artifacts'; public static WORKSPACE_PROPERTIES = 'workspace.properties'; public static WORKSPACE_SERVICE_INPUTS = 'workspace.service_inputs'; public static WORKSPACE_RESOURCE_INPUTS = 'workspace.resource_inputs'; public static WORKSPACE_ATTRIBUTES = 'workspace.attributes'; - public static WORKSPACE_HIERARCHY = 'workspace.hierarchy'; public static WORKSPACE_INFORMATION_ARTIFACTS = 'workspace.information_artifacts'; public static WORKSPACE_TOSCA_ARTIFACTS = 'workspace.tosca_artifacts'; public static WORKSPACE_COMPOSITION = 'workspace.composition'; @@ -237,7 +232,6 @@ export class EVENTS { static RESOURCE_LEFT_PALETTE_UPDATE_EVENT = "resourceLeftPanelUpdateEvent"; static RESOURCE_PNF_LEFT_PALETTE_UPDATE_EVENT = "resourcePNFLeftPanelUpdateEvent"; static SERVICE_LEFT_PALETTE_UPDATE_EVENT = "serviceLeftPanelUpdateEvent"; - static PRODUCT_LEFT_PALETTE_UPDATE_EVENT = "productLeftPanelUdateEvent"; static VL_LEFT_PALETTE_UPDATE_EVENT = "vlLeftPanelUdateEvent"; static ON_CSAR_LOADING = "onCsarLoading"; static DOWNLOAD_ARTIFACT_FINISH_EVENT = "downloadArtifactFinishEvent"; diff --git a/catalog-ui/src/app/utils/modals-handler.ts b/catalog-ui/src/app/utils/modals-handler.ts index ae91b2acb7..0d17683116 100644 --- a/catalog-ui/src/app/utils/modals-handler.ts +++ b/catalog-ui/src/app/utils/modals-handler.ts @@ -187,6 +187,24 @@ export class ModalsHandler implements IModalsHandler { return deferred.promise; }; + openUpdateIconModal = (component: Component):ng.IPromise => { + let deferred = this.$q.defer(); + let modalOptions:ng.ui.bootstrap.IModalSettings = { + templateUrl: '../view-models/modals/icons-modal/icons-modal-view.html', + controller: 'Sdc.ViewModels.IconsModalViewModel', + size: 'sdc-auto', + backdrop: 'static', + resolve: { + component: ():Component => { + return component; + } + } + }; + let modalInstance:ng.ui.bootstrap.IModalServiceInstance = this.$uibModal.open(modalOptions); + deferred.resolve(modalInstance.result); + return deferred.promise; + }; + openEditEnvParametersModal = (artifactResource:ArtifactModel, component?:Component):ng.IPromise => { let deferred = this.$q.defer(); let modalOptions:ng.ui.bootstrap.IModalSettings = { diff --git a/catalog-ui/src/app/view-models/catalog/catalog-view-model.ts b/catalog-ui/src/app/view-models/catalog/catalog-view-model.ts index 8925be0fff..ec9e888eed 100644 --- a/catalog-ui/src/app/view-models/catalog/catalog-view-model.ts +++ b/catalog-ui/src/app/view-models/catalog/catalog-view-model.ts @@ -117,7 +117,7 @@ export class CatalogViewModel { let onSuccess = (followedResponse:Array):void => { this.$scope.catalogFilterdItems = followedResponse; this.$scope.isAllItemDisplay = this.$scope.numberOfItemToDisplay >= this.$scope.catalogFilterdItems.length; - this.$scope.categories = this.cacheService.get('serviceCategories').concat(this.cacheService.get('resourceCategories')).concat(this.cacheService.get('productCategories')); + this.$scope.categories = this.cacheService.get('serviceCategories').concat(this.cacheService.get('resourceCategories')); this.$scope.gui.isLoading = false; }; @@ -137,7 +137,7 @@ export class CatalogViewModel { //this.$scope.categories = this.cacheService.get('categoriesMap'); this.$scope.sdcMenu = this.sdcMenu; this.$scope.confStatus = this.sdcMenu.statuses; - this.$scope.expandedSection = ["type", "category", "product-category", "status"]; + this.$scope.expandedSection = ["type", "category", "status"]; this.$scope.user = this.userResourceService.getLoggedinUser(); this.$scope.catalogMenuItem = this.sdcMenu.catalogMenuItem; this.$scope.version = this.cacheService.get('version'); @@ -147,8 +147,8 @@ export class CatalogViewModel { // Checklist init this.$scope.checkboxes = {}; - this.$scope.checkboxes.componentTypes = ['Resource', 'Service', 'Product']; - this.$scope.checkboxes.resourceSubTypes = ['VF', 'VFC', 'CP', 'VL']; + this.$scope.checkboxes.componentTypes = ['Resource', 'Service']; + this.$scope.checkboxes.resourceSubTypes = ['VF', 'VFC', 'PNF', 'CP', 'VL']; // Checkboxes filter init this.$scope.checkboxesFilter = {}; diff --git a/catalog-ui/src/app/view-models/catalog/catalog.less b/catalog-ui/src/app/view-models/catalog/catalog.less index ff50202243..1f473c9638 100644 --- a/catalog-ui/src/app/view-models/catalog/catalog.less +++ b/catalog-ui/src/app/view-models/catalog/catalog.less @@ -67,28 +67,6 @@ //text-indent: -10px; } - /*Added by - Ikram */ - .i-sdc-product-input, - .i-sdc-product-select { - border: 1px solid @border_color_f; - min-height: 30px; - padding: 0; - width: 100%; - margin: 1px 0; - background-color: #F2F2F2; - outline: none; - - &:disabled { - .disabled; - } - optgroup{ - color: @color_u; - option{ - color: @color_b; - } - } - } - .i-sdc-categories-list-item-icon { display: inline-block; float: right; diff --git a/catalog-ui/src/app/view-models/dashboard/dashboard-view-model.ts b/catalog-ui/src/app/view-models/dashboard/dashboard-view-model.ts index b9e51f098a..5480e4f6cf 100644 --- a/catalog-ui/src/app/view-models/dashboard/dashboard-view-model.ts +++ b/catalog-ui/src/app/view-models/dashboard/dashboard-view-model.ts @@ -310,6 +310,13 @@ export class DashboardViewModel { }; + this.$scope.createPNF = ():void => { + this.$state.go('workspace.general', { + type: ComponentType.RESOURCE.toLowerCase(), + resourceType: ResourceType.PNF + }); + }; + this.$scope.entitiesCount = (folderItem:FoldersItemsMenu):any => { let self = this; let total:number = 0; diff --git a/catalog-ui/src/app/view-models/dashboard/dashboard-view.html b/catalog-ui/src/app/view-models/dashboard/dashboard-view.html index 806bb8138d..baf4aa6e51 100644 --- a/catalog-ui/src/app/view-models/dashboard/dashboard-view.html +++ b/catalog-ui/src/app/view-models/dashboard/dashboard-view.html @@ -13,15 +13,15 @@
    -
    - +
    @@ -44,8 +44,8 @@
    -
- + +
@@ -62,7 +62,7 @@ data-tests-id="{{component.name}}">
+ - + diff --git a/catalog-ui/src/app/view-models/dashboard/dashboard.less b/catalog-ui/src/app/view-models/dashboard/dashboard.less index 7993390769..02280cdb42 100644 --- a/catalog-ui/src/app/view-models/dashboard/dashboard.less +++ b/catalog-ui/src/app/view-models/dashboard/dashboard.less @@ -244,13 +244,6 @@ } } - &.PRODUCT { - .b_14_m; - &::before { - content: 'P'; - } - } - &.green { .d_12; &::before { diff --git a/catalog-ui/src/app/view-models/dcae-app/dcae-app.less b/catalog-ui/src/app/view-models/dcae-app/dcae-app.less index bc1404d7c4..71a3101412 100644 --- a/catalog-ui/src/app/view-models/dcae-app/dcae-app.less +++ b/catalog-ui/src/app/view-models/dcae-app/dcae-app.less @@ -48,28 +48,6 @@ //text-indent: -10px; } - /*Added by - Ikram */ - .i-sdc-product-input, - .i-sdc-product-select { - border: 1px solid @border_color_f; - min-height: 30px; - padding: 0; - width: 100%; - margin: 1px 0; - background-color: #F2F2F2; - outline: none; - - &:disabled { - .disabled; - } - optgroup{ - color: @color_u; - option{ - color: @color_b; - } - } - } - .i-sdc-categories-list-item-icon { display: inline-block; float: right; diff --git a/catalog-ui/src/app/view-models/forms/property-forms/component-property-form/property-form-view-model.ts b/catalog-ui/src/app/view-models/forms/property-forms/component-property-form/property-form-view-model.ts index 8b9acbcab7..ee2e94f934 100644 --- a/catalog-ui/src/app/view-models/forms/property-forms/component-property-form/property-form-view-model.ts +++ b/catalog-ui/src/app/view-models/forms/property-forms/component-property-form/property-form-view-model.ts @@ -23,6 +23,7 @@ import { PROPERTY_TYPES, ModalsHandler, ValidationUtils, PROPERTY_VALUE_CONSTRAINTS, FormState, PROPERTY_DATA} from "app/utils"; import {DataTypesService} from "app/services"; import {PropertyModel, DataTypesMap, Component} from "app/models"; +import {ComponentInstance} from "../../../../models/componentsInstances/componentInstance"; export interface IEditPropertyModel { property:PropertyModel; @@ -50,6 +51,7 @@ interface IPropertyFormViewModelScope extends ng.IScope { isTypeDataType:boolean; maxLength:number; isPropertyValueOwner:boolean; + isVnfConfiguration:boolean; validateJson(json:string):boolean; save(doNotCloseModal?:boolean):void; @@ -192,6 +194,17 @@ export class PropertyFormViewModel { this.$scope.isPropertyValueOwner = this.isPropertyValueOwner; this.initEditPropertyModel(); + //check if property of VnfConfiguration + this.$scope.isVnfConfiguration = false; + if(angular.isArray(this.component.componentInstances)) { + var componentPropertyOwner:ComponentInstance = this.component.componentInstances.find((ci:ComponentInstance) => { + return ci.uniqueId === this.property.resourceInstanceUniqueId; + }); + if (componentPropertyOwner.componentName === 'vnfConfiguration') { + this.$scope.isVnfConfiguration = true; + } + } + this.$scope.nonPrimitiveTypes = _.filter(Object.keys(this.$scope.dataTypes), (type:string)=> { return this.$scope.editPropertyModel.types.indexOf(type) == -1; }); diff --git a/catalog-ui/src/app/view-models/forms/property-forms/component-property-form/property-form-view.html b/catalog-ui/src/app/view-models/forms/property-forms/component-property-form/property-form-view.html index f92d9a5ddc..743de298cd 100644 --- a/catalog-ui/src/app/view-models/forms/property-forms/component-property-form/property-form-view.html +++ b/catalog-ui/src/app/view-models/forms/property-forms/component-property-form/property-form-view.html @@ -142,7 +142,7 @@ schema-property="editPropertyModel.property.schema.property" parent-form-obj="forms.editForm" fields-prefix-name="currentPropertyIndex" - read-only="editPropertyModel.property.readonly && !isPropertyValueOwner" + read-only="(editPropertyModel.property.readonly && !isPropertyValueOwner) || isVnfConfiguration" default-value="{{getDefaultValue()}}" max-length="maxLength"> diff --git a/catalog-ui/src/app/view-models/modals/icons-modal/icons-modal-view.html b/catalog-ui/src/app/view-models/modals/icons-modal/icons-modal-view.html new file mode 100644 index 0000000000..4b89701201 --- /dev/null +++ b/catalog-ui/src/app/view-models/modals/icons-modal/icons-modal-view.html @@ -0,0 +1,18 @@ + + +
+
+
+
+
+
+ + +
diff --git a/catalog-ui/src/app/view-models/modals/icons-modal/icons-modal-view.less b/catalog-ui/src/app/view-models/modals/icons-modal/icons-modal-view.less new file mode 100644 index 0000000000..660846c883 --- /dev/null +++ b/catalog-ui/src/app/view-models/modals/icons-modal/icons-modal-view.less @@ -0,0 +1,33 @@ +.suggested-icons-container { + text-align: left; + width: 370px; + margin-bottom: 20px; + position: relative; + + .suggested-icon-wrapper { + padding: 5px; + margin: 14px 0 14px 28px; + display: inline-block; + height: 71px; + width: 71px; + + &.selected { + border: 2px solid @main_color_a; + border-radius: 35px; + display: inline-block; + line-height: 0px; + padding: 3px; + } + + } + .i-sdc-form-item-suggested-icon { + opacity: 0.8; + &:hover{ + opacity: 1; + } + } + .suggested-icon-wrapper:nth-child(4n+1) { + margin-left: 0; + } +} + diff --git a/catalog-ui/src/app/view-models/workspace/tabs/icons/icons-view-model.ts b/catalog-ui/src/app/view-models/modals/icons-modal/icons-modal-view.ts similarity index 61% rename from catalog-ui/src/app/view-models/workspace/tabs/icons/icons-view-model.ts rename to catalog-ui/src/app/view-models/modals/icons-modal/icons-modal-view.ts index c25bc4a1f1..eeadcd4e83 100644 --- a/catalog-ui/src/app/view-models/workspace/tabs/icons/icons-view-model.ts +++ b/catalog-ui/src/app/view-models/modals/icons-modal/icons-modal-view.ts @@ -19,53 +19,60 @@ */ /** - * Created by obarda on 4/4/2016. + * Created by rc2122 on 7/4/2017. */ 'use strict'; import {ComponentFactory} from "app/utils"; import {AvailableIconsService} from "app/services"; import {IWorkspaceViewModelScope} from "app/view-models/workspace/workspace-view-model"; import {IMainCategory, ISubCategory} from "app/models"; - -export interface IIconsScope extends IWorkspaceViewModelScope { - icons:Array; - iconSprite:string; - setComponentIcon(iconSrc:string):void; +import {Component} from "app/models"; +import {ResourceType} from "app/utils/constants"; + +interface IIconsModalViewModelScope { + modalIcons:ng.ui.bootstrap.IModalServiceInstance; + icons:Array, + iconSprite:string, + selectedIcon:string, + changeIcon(icon:string):void, + cancel():void + updateIcon():void; } -export class IconsViewModel { - +export class IconsModalViewModel { static '$inject' = [ '$scope', 'Sdc.Services.AvailableIconsService', 'ComponentFactory', - '$state' + '$state', + '$uibModalInstance', + 'component' ]; - constructor(private $scope:IIconsScope, + constructor(private $scope:IIconsModalViewModelScope, private availableIconsService:AvailableIconsService, private ComponentFactory:ComponentFactory, - private $state:ng.ui.IStateService) { - - + private $state:ng.ui.IStateService, + private $uibModalInstance:ng.ui.bootstrap.IModalServiceInstance, + private component: Component) { this.initScope(); - this.initIcons(); - this.$scope.updateSelectedMenuItem(); - this.$scope.iconSprite = this.$scope.component.iconSprite; + this._initIcons(); + this.$scope.iconSprite = this.component.iconSprite; + this.$scope.selectedIcon = this.component.icon; - if (this.$scope.component.isResource()) { + if (this.component.isResource()) { this.initVendor(); } + } - private initialIcon:string = this.$scope.component.icon; - private initIcons = ():void => { + private _initIcons = ():void => { // For subcategories that where created by admin, there is no icons this.$scope.icons = new Array(); - if (this.$scope.component.categories && this.$scope.component.categories.length > 0) { + if (this.component.categories && this.component.categories.length > 0) { - _.forEach(this.$scope.component.categories, (category:IMainCategory):void => { + _.forEach(this.component.categories, (category:IMainCategory):void => { if (category.icons) { this.$scope.icons = this.$scope.icons.concat(category.icons); } @@ -79,26 +86,26 @@ export class IconsViewModel { }); } - if (this.$scope.component.isResource()) { - let resourceType:string = this.$scope.component.getComponentSubType(); - if (resourceType === 'VL') { + if (this.component.isResource()) { + let resourceType:string = this.component.getComponentSubType(); + if (resourceType === ResourceType.VL) { this.$scope.icons = ['vl']; } - if (resourceType === 'CP') { + if (resourceType === ResourceType.CP) { this.$scope.icons = ['cp']; } } if (this.$scope.icons.length === 0) { - this.$scope.icons = this.availableIconsService.getIcons(this.$scope.component.componentType); + this.$scope.icons = this.availableIconsService.getIcons(this.component.componentType); } //we always add the defual icon to the list this.$scope.icons.push('defaulticon'); }; private initVendor = ():void => { - let vendors:Array = this.availableIconsService.getIcons(this.$scope.component.componentType).slice(5, 19); - let vendorName = this.$scope.component.vendorName.toLowerCase(); + let vendors:Array = this.availableIconsService.getIcons(this.component.componentType).slice(5, 19); + let vendorName = this.component.vendorName.toLowerCase(); if ('at&t' === vendorName) { vendorName = 'att'; } @@ -115,17 +122,22 @@ export class IconsViewModel { }; private initScope():void { + this.$scope.modalIcons = this.$uibModalInstance; this.$scope.icons = []; - this.$scope.setValidState(true); - //if(this.$scope.component.icon === DEFAULT_ICON){ - // //this.$scope.setValidState(false); - //} - - this.$scope.setComponentIcon = (iconSrc:string):void => { - this.$state.current.data.unsavedChanges = !this.$scope.isViewMode() && (iconSrc != this.initialIcon); - this.$scope.component.icon = iconSrc; - // this.$scope.setValidState(true); + this.$scope.changeIcon = (icon:string):void => { + this.$scope.selectedIcon = icon; }; - + this.$scope.cancel = ():void => { + this.$uibModalInstance.dismiss(); + }; + this.$scope.updateIcon = ():void => { + let isDirty:boolean = this.component.icon != this.$scope.selectedIcon; + this.component.icon = this.$scope.selectedIcon; + this.$uibModalInstance.close(isDirty); + } } + } + + + diff --git a/catalog-ui/src/app/view-models/onboard-vendor/onboard-vendor.less b/catalog-ui/src/app/view-models/onboard-vendor/onboard-vendor.less index bc1404d7c4..71a3101412 100644 --- a/catalog-ui/src/app/view-models/onboard-vendor/onboard-vendor.less +++ b/catalog-ui/src/app/view-models/onboard-vendor/onboard-vendor.less @@ -48,28 +48,6 @@ //text-indent: -10px; } - /*Added by - Ikram */ - .i-sdc-product-input, - .i-sdc-product-select { - border: 1px solid @border_color_f; - min-height: 30px; - padding: 0; - width: 100%; - margin: 1px 0; - background-color: #F2F2F2; - outline: none; - - &:disabled { - .disabled; - } - optgroup{ - color: @color_u; - option{ - color: @color_b; - } - } - } - .i-sdc-categories-list-item-icon { display: inline-block; float: right; diff --git a/catalog-ui/src/app/view-models/workspace/tabs/activity-log/activity-log.less b/catalog-ui/src/app/view-models/workspace/tabs/activity-log/activity-log.less index 61bb3e9f01..24f83ec503 100644 --- a/catalog-ui/src/app/view-models/workspace/tabs/activity-log/activity-log.less +++ b/catalog-ui/src/app/view-models/workspace/tabs/activity-log/activity-log.less @@ -1,7 +1,4 @@ .activity-log { - - margin-top: 30px; - .title-wrapper { display: flex; justify-content: flex-end; @@ -10,7 +7,7 @@ .table-container-flex .table .body .scrollbar-container { max-height: 448px; } - + .view-mode { background-color: @main_color_p; } diff --git a/catalog-ui/src/app/view-models/workspace/tabs/attributes/attributes.less b/catalog-ui/src/app/view-models/workspace/tabs/attributes/attributes.less index ffd28afce4..932daa167d 100644 --- a/catalog-ui/src/app/view-models/workspace/tabs/attributes/attributes.less +++ b/catalog-ui/src/app/view-models/workspace/tabs/attributes/attributes.less @@ -13,7 +13,7 @@ } .table-container-flex { - margin-top: 27px; + margin-top: 0; .text{ overflow: hidden; diff --git a/catalog-ui/src/app/view-models/workspace/tabs/composition/composition-view-model.ts b/catalog-ui/src/app/view-models/workspace/tabs/composition/composition-view-model.ts index 894f8aeb2a..fbd32cc967 100644 --- a/catalog-ui/src/app/view-models/workspace/tabs/composition/composition-view-model.ts +++ b/catalog-ui/src/app/view-models/workspace/tabs/composition/composition-view-model.ts @@ -18,12 +18,14 @@ * ============LICENSE_END========================================================= */ 'use strict'; -import {Component, Product, ComponentInstance, IAppMenu} from "app/models"; +import {Component, ComponentInstance, IAppMenu} from "app/models"; import {SharingService, CacheService, EventListenerService, LeftPaletteLoaderService} from "app/services"; import {ModalsHandler, GRAPH_EVENTS, ComponentFactory, ChangeLifecycleStateHandler, MenuHandler, EVENTS} from "app/utils"; import {IWorkspaceViewModelScope} from "../../workspace-view-model"; import {ComponentServiceNg2} from "app/ng2/services/component-services/component.service"; import {ComponentGenericResponse} from "app/ng2/services/responses/component-generic-response"; +import {Resource} from "app/models/components/resource"; +import {ResourceType} from "../../../../utils/constants"; export interface ICompositionViewModelScope extends IWorkspaceViewModelScope { @@ -205,9 +207,6 @@ export class CompositionViewModel { if (this.$state.current.name === 'workspace.composition.api') { this.$state.go('workspace.composition.details'); } - if (this.$state.current.name === 'workspace.composition.relations' && this.$scope.currentComponent.isProduct()) { - this.$state.go('workspace.composition.details'); - } }; this.$scope.onBackgroundClick = ():void => { @@ -238,7 +237,7 @@ export class CompositionViewModel { this.ModalsHandler.openAlertModal(title, message).then(onOk); }; - this.$scope.onComponentInstanceVersionChange = (component:Product):void => { + this.$scope.onComponentInstanceVersionChange = (component:Component):void => { this.$scope.currentComponent = component; this.$scope.setComponent(this.$scope.currentComponent); this.$scope.updateSelectedComponent(); diff --git a/catalog-ui/src/app/view-models/workspace/tabs/composition/composition-view.html b/catalog-ui/src/app/view-models/workspace/tabs/composition/composition-view.html index 761ae53909..cef942e853 100644 --- a/catalog-ui/src/app/view-models/workspace/tabs/composition/composition-view.html +++ b/catalog-ui/src/app/view-models/workspace/tabs/composition/composition-view.html @@ -57,7 +57,8 @@ diff --git a/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/details/details-view-model.ts b/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/details/details-view-model.ts index 223d6cf964..0d8d17ec73 100644 --- a/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/details/details-view-model.ts +++ b/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/details/details-view-model.ts @@ -82,7 +82,7 @@ export class DetailsViewModel { let highestVersion = _.last(Object.keys(this.$scope.selectedComponent.allVersions)); if (parseFloat(highestVersion) % 1) { //if highest is minor, make sure it is the latest checked in - - let latestVersionComponent:LeftPaletteComponent = _.maxBy(_.filter(this.LeftPaletteLoaderService.getLeftPanelComponentsForDisplay(this.$scope.currentComponent.componentType), (component:LeftPaletteComponent) => { //latest checked in + let latestVersionComponent:LeftPaletteComponent = _.maxBy(_.filter(this.LeftPaletteLoaderService.getLeftPanelComponentsForDisplay(this.$scope.currentComponent), (component:LeftPaletteComponent) => { //latest checked in return (component.systemName === this.$scope.selectedComponent.systemName || component.uuid === this.$scope.selectedComponent.uuid); }),(component)=>{return component.version}); diff --git a/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/details/details-view.html b/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/details/details-view.html index 70dc58075a..8607d65964 100644 --- a/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/details/details-view.html +++ b/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/details/details-view.html @@ -77,6 +77,27 @@ data-tests-id="rightTab_vendorRelease"> +
+ + + +
+
+ + + +
+
+ + + +
this.$scope.component).contacts = []; - (this.$scope.component).contacts.push(this.cacheService.get("user").userId); - } else if (this.$scope.isCreateMode()) { + if (this.$scope.isCreateMode()) { this.$scope.component.contactId = this.cacheService.get("user").userId; } @@ -273,6 +274,24 @@ export class GeneralViewModel { }); }; + this.$scope.updateIcon = ():void => { + this.ModalsHandler.openUpdateIconModal(this.$scope.component).then((isDirty:boolean)=> { + if(!this.$scope.isCreateMode()){ + this.$state.current.data.unsavedChanges = this.$state.current.data.unsavedChanges || isDirty; + } + }, ()=> { + // ERROR + }); + }; + + this.$scope.possibleToUpdateIcon = ():boolean => { + if(this.$scope.componentCategories.selectedCategory && (!this.$scope.component.isResource() || this.$scope.component.vendorName)){ + return true; + }else{ + return false; + } + } + this.$scope.validateName = (isInit:boolean):void => { if (isInit === undefined) { isInit = false; diff --git a/catalog-ui/src/app/view-models/workspace/tabs/general/general-view.html b/catalog-ui/src/app/view-models/workspace/tabs/general/general-view.html index 2ad0cbacd6..d3626803e9 100644 --- a/catalog-ui/src/app/view-models/workspace/tabs/general/general-view.html +++ b/catalog-ui/src/app/view-models/workspace/tabs/general/general-view.html @@ -4,122 +4,121 @@
- -
- - -
- - -
- -
- {{(fileModel && fileModel.filename) || importedToscaBrowseFileText}} -
- -
Browse
-
-
- -
- - - - - -
- -
- - -
- - - -
- - - - - +
+
+
+
+
+
+
+
+
+ +
+ + + +
+ + + + + +
+
+ + + + + +
+ + + + +
+ +
+
+ +
-
- + +
+ - -
- - + -
- - - - - +
+ +
- + -
- +
@@ -130,110 +129,85 @@
- -
- - - - -
- -
-
- - - -
- - +
-
- - +
+ +
+ +
-
+ +
+ +
+ {{(fileModel && fileModel.filename) || importedToscaBrowseFileText}} +
+ +
Browse
+
+
- +
+ + + + + +
+ -
- - -
+ +
+ + +
+ +
- - - -
- - + + +
+ + -
- - +
+ +
- -
@@ -242,20 +216,20 @@ data-ng-class="{'view-mode': isViewMode()}" data-ng-model="component.vendorName" data-ng-model-options="{ debounce: 500 }" - data-ng-maxlength="25" + data-ng-maxlength="60" data-required ng-click="oldValue = component.vendorName" name="vendorName" data-ng-change="onVendorNameChange(oldValue)" - data-ng-pattern="validation.vendorValidationPattern" - maxlength="25" + data-ng-pattern="validation.VendorNameValidationPattern" + maxlength="60" data-ng-disabled="component.isAlreadyCertified() || (component.isCsarComponent() && component.vendorName && component.vendorName!=='')" data-tests-id="vendorName" - /> + />
- +
@@ -275,80 +249,160 @@ data-ng-maxlength="25" data-required name="vendorRelease" - data-ng-pattern="validation.vendorValidationPattern" + data-ng-pattern="validation.VendorReleaseValidationPattern" maxlength="25" data-ng-disabled="component.isCsarComponent() && component.vendorRelease && component.vendorRelease!==''" data-tests-id="vendorRelease" - /> + />
- +
+ +
+ + +
+ + +
+
+ -
- -
- - -
- + - +
+ + +
-
- - +
-
- + - -
- - +
+ + - -
- - +
+ + +
-
- - + + +
+ + +
+ + +
+
+ + + +
+ + +
+ + +
+
+ +
-
diff --git a/catalog-ui/src/app/view-models/workspace/tabs/general/general.less b/catalog-ui/src/app/view-models/workspace/tabs/general/general.less index caa755cce3..9633ec5bb6 100644 --- a/catalog-ui/src/app/view-models/workspace/tabs/general/general.less +++ b/catalog-ui/src/app/view-models/workspace/tabs/general/general.less @@ -1,8 +1,8 @@ .sdc-workspace-general-step { - + display: flex; .w-sdc-form { padding: 0; - + flex-grow: 10; .i-sdc-form-file-upload{ input[type="button"] { cursor: pointer; @@ -33,6 +33,14 @@ } } + .description{ + height: 300px; + } + + .i-sdc-form-item.description-field{ + margin-bottom: 0; + } + .w-sdc-form-section-container { text-align: center; } @@ -43,6 +51,7 @@ width: auto; padding: 10px; } + margin-bottom: 15px; } .i-sdc-form-label { @@ -63,6 +72,73 @@ } + .w-sdc-form-column { + position: relative; + } + + .meta-data{ + padding: 8px 0 2px 20px; + text-align: left; + background-color: @tlv_color_t; + position: absolute; + bottom: 0; + width: 100%; + .meta-data-item-value{ + padding-bottom: 6px; + } + } + + .upper-general-fields{ + display: flex; + } + + .selected-icon-container{ + flex-grow: 1; + display: flex; + align-items: center; + .selected-icon-inner-container{ + height: 64px; + width: 64px; + margin: 0 auto; + } + .update-component-icon{ + position: relative; + float: right; + cursor: pointer; + } + .selected-icon{ + position: relative; + top: -20px; + z-index: -1; + &.disable{ + position: inherit; + } + } + &.show-only-on-over{ + .update-component-icon{ + display: none; + } + .selected-icon{ + position: inherit; + } + &:hover{ + .update-component-icon{ + display: inline-block; + } + .selected-icon{ + position: relative; + } + } + } + } + + .name-and-category-fields{ + flex-grow: 5; + } + + + + } diff --git a/catalog-ui/src/app/view-models/workspace/tabs/icons/icons-view.html b/catalog-ui/src/app/view-models/workspace/tabs/icons/icons-view.html deleted file mode 100644 index aac14e0e84..0000000000 --- a/catalog-ui/src/app/view-models/workspace/tabs/icons/icons-view.html +++ /dev/null @@ -1,26 +0,0 @@ -
- -
- -
-
-
-
-
Select one of the icons below for the asset
-
-
-
-
-
-
-
-
diff --git a/catalog-ui/src/app/view-models/workspace/tabs/icons/icons.less b/catalog-ui/src/app/view-models/workspace/tabs/icons/icons.less deleted file mode 100644 index 65f946f395..0000000000 --- a/catalog-ui/src/app/view-models/workspace/tabs/icons/icons.less +++ /dev/null @@ -1,65 +0,0 @@ -.workspace-icons { - - width: 89%; - display: inline-block; - text-align: center; - align-items: center; - - .w-sdc-form { - padding-top: 0px; - padding-bottom: 0px; - .selected-icon-container { - text-align: left; - border: 1px solid #cfcfcf; - clear: both; - margin-bottom: 30px; - padding: 2px 0px 5px 5px; - .selected-icon { - margin: 8px 5px 0px 6px; - } - } - - .suggested-icons-container { - text-align: left; - border: 1px solid #cfcfcf; - clear: both; - padding: 2px 0px 5px 5px; - height: 340px; - margin-bottom: 0px; - - .suggested-icon-wrapper { - margin: 8px 5px 0px 6px; - display: inline-block; - - &.selected { - border: 2px solid @main_color_a; - border-radius: 35px; - display: inline-block; - line-height: 0px; - padding: 3px; - } - - } - .suggested-icon { - // margin: 8px 5px 0px 6px; - display: inline-block; - &.disable{ - opacity: 0.4; - } - } - } - - .icons-label { - float: left; - } - - .icons-text { - text-align: left; - line-height: 32px; - padding-left: 10px; - width: 100%; - border: 1px solid #cfcfcf; - border-bottom: none; - } - } -} diff --git a/catalog-ui/src/app/view-models/workspace/tabs/information-artifacts/information-artifacts.less b/catalog-ui/src/app/view-models/workspace/tabs/information-artifacts/information-artifacts.less index 3ba9cf47d5..5e69c44e9b 100644 --- a/catalog-ui/src/app/view-models/workspace/tabs/information-artifacts/information-artifacts.less +++ b/catalog-ui/src/app/view-models/workspace/tabs/information-artifacts/information-artifacts.less @@ -12,7 +12,7 @@ } .table-container-flex { - margin-top: 27px; + margin-top: 0; .item-opened{ word-wrap: break-word; diff --git a/catalog-ui/src/app/view-models/workspace/tabs/inputs/inputs.less b/catalog-ui/src/app/view-models/workspace/tabs/inputs/inputs.less index eff5c5395b..17c18e1741 100644 --- a/catalog-ui/src/app/view-models/workspace/tabs/inputs/inputs.less +++ b/catalog-ui/src/app/view-models/workspace/tabs/inputs/inputs.less @@ -216,7 +216,7 @@ } .table-container-flex { - margin-top: 27px; + margin-top: 0; width: 46%; min-width: 46%; display: inline-block; diff --git a/catalog-ui/src/app/view-models/workspace/tabs/product-hierarchy/product-hierarchy-view-model.ts b/catalog-ui/src/app/view-models/workspace/tabs/product-hierarchy/product-hierarchy-view-model.ts deleted file mode 100644 index c891875f52..0000000000 --- a/catalog-ui/src/app/view-models/workspace/tabs/product-hierarchy/product-hierarchy-view-model.ts +++ /dev/null @@ -1,129 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * SDC - * ================================================================================ - * 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. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -'use strict'; -import {ComponentFactory} from "app/utils"; -import {Product, IGroup, ISubCategory, IMainCategory} from "app/models"; -import {IWorkspaceViewModelScope} from "app/view-models/workspace/workspace-view-model"; -import {CacheService} from "app/services"; - -export interface IProductHierarchyScope extends IWorkspaceViewModelScope { - - categoriesOptions:Array; - product:Product; - isLoading:boolean; - showDropDown:boolean; - - onInputTextClicked():void; - onGroupSelected(category:IMainCategory, subcategory:ISubCategory, group:IGroup):void; - clickOutside():void; - deleteGroup(uniqueId:string):void; -} - -export class ProductHierarchyViewModel { - - static '$inject' = [ - '$scope', - 'Sdc.Services.CacheService', - 'ComponentFactory', - '$state' - ]; - - constructor(private $scope:IProductHierarchyScope, - private cacheService:CacheService, - private ComponentFactory:ComponentFactory, - private $state:ng.ui.IStateService) { - - - this.$scope.product = this.$scope.getComponent(); - this.$scope.setValidState(true); - this.initScope(); - this.$scope.updateSelectedMenuItem(); - } - - private initCategories = () => { - this.$scope.categoriesOptions = angular.copy(this.cacheService.get('productCategories')); - let selectedGroup:Array = []; - _.forEach(this.$scope.product.categories, (category:IMainCategory) => { - _.forEach(category.subcategories, (subcategory:ISubCategory) => { - selectedGroup = selectedGroup.concat(subcategory.groupings); - }); - }); - _.forEach(this.$scope.categoriesOptions, (category:IMainCategory) => { - _.forEach(category.subcategories, (subcategory:ISubCategory) => { - _.forEach(subcategory.groupings, (group:ISubCategory) => { - let componentGroup:IGroup = _.find(selectedGroup, (componentGroupObj) => { - return componentGroupObj.uniqueId == group.uniqueId; - }); - if (componentGroup) { - group.isDisabled = true; - } - }); - }); - }); - }; - - private setFormValidation = ():void => { - - this.$scope.setValidState(true); - - }; - - private initScope = ():void => { - this.$scope.isLoading = false; - this.$scope.showDropDown = false; - this.initCategories(); - this.setFormValidation(); - - this.$scope.onGroupSelected = (category:IMainCategory, subcategory:ISubCategory, group:IGroup):void => { - this.$scope.product.addGroup(category, subcategory, group); - this.$state.current.data.unsavedChanges = !this.$scope.isViewMode(); - group.isDisabled = true; - this.$scope.showDropDown = false; - this.setFormValidation(); - }; - - this.$scope.onInputTextClicked = ():void => {//just edit the component in place, no pop up nor server update ? - this.$scope.showDropDown = !this.$scope.showDropDown; - }; - - this.$scope.clickOutside = ():any => { - this.$scope.showDropDown = false; - }; - - this.$scope.deleteGroup = (uniqueId:string):void => { - //delete group from component - this.$scope.product.deleteGroup(uniqueId); - this.$state.current.data.unsavedChanges = !this.$scope.isViewMode(); - this.setFormValidation(); - //enabled group - _.forEach(this.$scope.categoriesOptions, (category:IMainCategory) => { - _.forEach(category.subcategories, (subcategory:ISubCategory) => { - let groupObj:IGroup = _.find(subcategory.groupings, (group) => { - return group.uniqueId === uniqueId; - }); - if (groupObj) { - groupObj.isDisabled = false; - } - }); - }); - } - }; -} diff --git a/catalog-ui/src/app/view-models/workspace/tabs/product-hierarchy/product-hierarchy-view.html b/catalog-ui/src/app/view-models/workspace/tabs/product-hierarchy/product-hierarchy-view.html deleted file mode 100644 index 2335ad7c74..0000000000 --- a/catalog-ui/src/app/view-models/workspace/tabs/product-hierarchy/product-hierarchy-view.html +++ /dev/null @@ -1,40 +0,0 @@ -
- -
- -
-
-
-
- -
-
-
-
-
-
diff --git a/catalog-ui/src/app/view-models/workspace/tabs/product-hierarchy/product-hierarchy.less b/catalog-ui/src/app/view-models/workspace/tabs/product-hierarchy/product-hierarchy.less deleted file mode 100644 index c992558ed2..0000000000 --- a/catalog-ui/src/app/view-models/workspace/tabs/product-hierarchy/product-hierarchy.less +++ /dev/null @@ -1,130 +0,0 @@ -.workspace-hierarchy { - display: inline-block; - width: 93%; - - .scrollbar-container{ - max-height:400px; - .perfect-scrollbar; - } - - .dropdown-container { - position: relative; - display: inline-block; - width: 100%; - - &:after{ - top: 47%; - right: 1%; - border: solid transparent; - content: " "; - height: 0; - width: 0; - position: absolute; - pointer-events: none; - border-color: rgba(0, 0, 0, 0); - border-top-color: black; - border-width: 4px; - margin-left: -4px; - } - - .dropdown-input-text { - width: 100%; - padding: 4px 10px; - } - - .dropdown-content { - .perfect-scrollbar; - border: 1px solid #d8d8d8; - display: none; - position: absolute; - overflow: hidden; - width: 100%; - .bg_c; - max-height: 400px; - z-index: 999999; - - .dropdown-option { - border-bottom: 1px solid #d8d8d8; - display: inline-block; - width: 100%; - } - - .category-container{ - width: 250px; - float: left; - padding-left: 5px; - - .category { - .bold; - padding: 3px 3px 2px 3px; - &:after{ - .sprite; - .arrow-left; - content: ''; - margin-left: 5px; - transform: rotate(180deg); - } - } - .subcategory { - padding-left: 3px; - } - } - - .groupings-container{ - display: inline-block; - width: 424px; - border-left: 1px solid #d8d8d8; - min-height: 55px; - .group{ - padding: 3px 3px 3px 10px; - &:hover{ - .hand; - .bg_n; - } - &.disabled-group { - opacity: 0.5; - &:hover{ - cursor: auto; - .bg_c; - } - } - } - } - - .seperator { - height: 1px; - width: 100%; - .bg_j; - margin: 5px 0px; - } - } - .show { - display: block; - } - } - - .hierarchy-groups-container{ - .b_9; - width: 100%; - border: 1px solid #d8d8d8; - height: 425px; - padding: 15px; - text-align: center; - - .scrollbar-container { - z-index: 0; - } - - .no-group-text{ - text-align: center; - margin-top:25px; - a { - cursor: pointer; - } - } - .group-tag{ - display: inline-block; - float: left; - } - } -} diff --git a/catalog-ui/src/app/view-models/workspace/tabs/properties/properties.less b/catalog-ui/src/app/view-models/workspace/tabs/properties/properties.less index 3e8d6c3fbd..48c462e143 100644 --- a/catalog-ui/src/app/view-models/workspace/tabs/properties/properties.less +++ b/catalog-ui/src/app/view-models/workspace/tabs/properties/properties.less @@ -76,7 +76,7 @@ } .table-container-flex { - margin-top: 27px; + margin-top: 0; .text{ overflow: hidden; diff --git a/catalog-ui/src/app/view-models/workspace/tabs/tosca-artifacts/tosca-artifacts.less b/catalog-ui/src/app/view-models/workspace/tabs/tosca-artifacts/tosca-artifacts.less index 6dfec2980f..23be3c3548 100644 --- a/catalog-ui/src/app/view-models/workspace/tabs/tosca-artifacts/tosca-artifacts.less +++ b/catalog-ui/src/app/view-models/workspace/tabs/tosca-artifacts/tosca-artifacts.less @@ -1,5 +1,5 @@ .workspace-tosca-artifact { - width: 93%; + width: 100%; display: inline-block; .w-sdc-classic-btn { float: right; @@ -18,8 +18,7 @@ .table-container-flex { - margin-top: 27px; - + margin-top: 0; .item-opened{ word-wrap: break-word; } diff --git a/catalog-ui/src/app/view-models/workspace/workspace-view-model.ts b/catalog-ui/src/app/view-models/workspace/workspace-view-model.ts index 21bd199aac..ec8b04dbdb 100644 --- a/catalog-ui/src/app/view-models/workspace/workspace-view-model.ts +++ b/catalog-ui/src/app/view-models/workspace/workspace-view-model.ts @@ -77,7 +77,6 @@ export interface IWorkspaceViewModelScope extends ng.IScope { changeLifecycleState(state:string):void; enabledTabs():void isDesigner():boolean; - isProductManager():boolean; isViewMode():boolean; isEditMode():boolean; isCreateMode():boolean; @@ -91,6 +90,7 @@ export interface IWorkspaceViewModelScope extends ng.IScope { updateSelectedMenuItem():void; uploadFileChangedInGeneralTab():void; updateMenuComponentName(ComponentName:string):void; + getTabTitle():string; reload(component:Component):void; } @@ -149,9 +149,6 @@ export class WorkspaceViewModel { } else { if (this.$scope.component.lifecycleState === ComponentState.NOT_CERTIFIED_CHECKOUT && this.$scope.component.lastUpdaterUserId === this.cacheService.get("user").userId) { - if (this.$scope.component.isProduct() && this.role == Role.PRODUCT_MANAGER) { - mode = WorkspaceMode.EDIT; - } if ((this.$scope.component.isService() || this.$scope.component.isResource()) && this.role == Role.DESIGNER) { mode = WorkspaceMode.EDIT; } @@ -171,7 +168,7 @@ export class WorkspaceViewModel { }; private initLeftPalette = ():void => { - this.LeftPaletteLoaderService.loadLeftPanel(this.$scope.component.componentType); + this.LeftPaletteLoaderService.loadLeftPanel(this.$scope.component); }; private initScope = ():void => { @@ -192,7 +189,7 @@ export class WorkspaceViewModel { this.$scope.$state = this.$state; this.$scope.isLoading = false; this.$scope.isComposition = (this.$state.current.name.indexOf(States.WORKSPACE_COMPOSITION) > -1); - this.$scope.isDeployment = (this.$state.current.name.indexOf(States.WORKSPACE_DEPLOYMENT) > -1); + this.$scope.isDeployment = this.$state.current.name == States.WORKSPACE_DEPLOYMENT; this.$scope.progressService = this.progressService; this.$scope.getComponent = ():Component => { @@ -269,7 +266,7 @@ export class WorkspaceViewModel { type: this.$scope.componentType.toLowerCase(), mode: WorkspaceMode.VIEW, components: this.$state.params['components'] - },{reload: true}); + }, {reload: true}); }; @@ -431,7 +428,7 @@ export class WorkspaceViewModel { switch (url) { case 'lifecycleState/CHECKOUT': // only checkOut get the full component from server - // this.$scope.component = component; + // this.$scope.component = component; // Work around to change the csar version if (this.cacheService.get(CHANGE_COMPONENT_CSAR_VERSION_FLAG)) { (this.$scope.component).csarVersion = this.cacheService.get(CHANGE_COMPONENT_CSAR_VERSION_FLAG); @@ -565,18 +562,13 @@ export class WorkspaceViewModel { return this.role == Role.DESIGNER; }; - this.$scope.isProductManager = ():boolean => { - return this.role == Role.PRODUCT_MANAGER; - }; - this.$scope.isDisableMode = ():boolean => { return this.$scope.mode === WorkspaceMode.VIEW && this.$scope.component.lifecycleState === ComponentState.NOT_CERTIFIED_CHECKIN; }; this.$scope.showFullIcons = ():boolean => { - //we show revert and save icons only in general\icon view - return this.$state.current.name === States.WORKSPACE_GENERAL || - this.$state.current.name === States.WORKSPACE_ICONS; + //we show revert and save icons only in general view + return this.$state.current.name === States.WORKSPACE_GENERAL; }; this.$scope.isCreateMode = ():boolean => { @@ -593,8 +585,7 @@ export class WorkspaceViewModel { }; this.$scope.showLifecycleIcon = ():boolean => { - return this.role == Role.DESIGNER || - this.role == Role.PRODUCT_MANAGER; + return this.role == Role.DESIGNER; }; this.$scope.getStatus = ():string => { @@ -612,13 +603,6 @@ export class WorkspaceViewModel { if (!this.$scope.component.isLatestVersion() && Role.OPS != this.role && Role.GOVERNOR != this.role) { result = false; } - if (this.role === Role.PRODUCT_MANAGER && !this.$scope.component.isProduct()) { - result = false; - } - if ((this.role === Role.DESIGNER || this.role === Role.TESTER) - && this.$scope.component.isProduct()) { - result = false; - } if (ComponentState.NOT_CERTIFIED_CHECKOUT === this.$scope.component.lifecycleState && this.$scope.isViewMode()) { result = false; } @@ -639,10 +623,16 @@ export class WorkspaceViewModel { this.$scope.$watch('$state.current.name', (newVal:string):void => { if (newVal) { this.$scope.isComposition = (newVal.indexOf(States.WORKSPACE_COMPOSITION) > -1); - this.$scope.isDeployment = (newVal.indexOf(States.WORKSPACE_DEPLOYMENT) > -1); + this.$scope.isDeployment = newVal == States.WORKSPACE_DEPLOYMENT; } }); + this.$scope.getTabTitle = ():string => { + return this.$scope.leftBarTabs.menuItems.find((menuItem:MenuItem)=>{ + return menuItem.state == this.$scope.$state.current.name; + }).text; + }; + this.$scope.reload = (component:Component):void => { this.$state.go(this.$state.current.name,{id:component.uniqueId},{reload:true}); }; @@ -658,7 +648,11 @@ export class WorkspaceViewModel { private initVersionObject = ():void => { this.$scope.versionsList = (this.$scope.component.getAllVersionsAsSortedArray()).reverse(); - this.$scope.changeVersion = {selectedVersion: _.find(this.$scope.versionsList, {versionId: this.$scope.component.uniqueId})}; + this.$scope.changeVersion = { + selectedVersion: _.find(this.$scope.versionsList, (versionObj)=> { + return versionObj.versionId === this.$scope.component.uniqueId; + }) + }; }; private getNewComponentBreadcrumbItem = ():MenuItem => { diff --git a/catalog-ui/src/app/view-models/workspace/workspace-view.html b/catalog-ui/src/app/view-models/workspace/workspace-view.html index dbb7fa6d63..19ebefe7a5 100644 --- a/catalog-ui/src/app/view-models/workspace/workspace-view.html +++ b/catalog-ui/src/app/view-models/workspace/workspace-view.html @@ -3,8 +3,11 @@
-
- + +
+
{{menuItem.text}}
@@ -54,22 +57,22 @@ - Delete Revert - + Close
- -
Created: {{component.creationDate | date:'MM/dd/yyyy'}}, {{component.creatorFullName}} | Modifed: {{component.lastUpdateDate | date:'MM/dd/yyyy'}} | UUID: {{component.uuid}} Invariant UUID: {{component.invariantUUID}}
- +
+ {{getTabTitle()}} +
diff --git a/catalog-ui/src/app/view-models/workspace/workspace.less b/catalog-ui/src/app/view-models/workspace/workspace.less index 278708ca33..b7331b5f93 100644 --- a/catalog-ui/src/app/view-models/workspace/workspace.less +++ b/catalog-ui/src/app/view-models/workspace/workspace.less @@ -27,10 +27,46 @@ } .w-sdc-left-sidebar { - padding: 3px 3px 0px 0px; - background-color: @main_color_p; - box-shadow: 7px -3px 6px -8px @main_color_n; + padding: 0px; + background-color: @tlv_color_t; + box-shadow: none; z-index: 2; + border-right: 1px solid @main_color_o; + .menu-header{ + border-bottom: 1px solid @main_color_o; + height: 53px; + .f-type._16_m; + font-weight: 700; + line-height: 53px; + padding-left: 40px; + padding-right: 10px; + width: 100%; + overflow: hidden; + text-overflow: ellipsis; + display: inline-block; + white-space: nowrap; + } + .i-sdc-designer-sidebar-section-content-item{ + .f-type._13_m; + color: @main_color_m; + margin-left: 20px; + padding-left: 20px; + margin-top: 20px; + height: 17px; + .hand; + &:hover{ + color: @func_color_s; + font-weight: 600; + } + &.selected{ + border-left: 4px solid @main_color_a; + color: @main_color_a; + margin-left: 18px; + padding-left: 18px; + font-weight: 600; + + } + } } .sdc-asset-creation-info { @@ -128,17 +164,21 @@ margin-top: 6px; } } + .tab-title{ + height: 110px; + padding-left: 100px; + line-height: 110px; + .f-type ._28; + } .w-sdc-main-container-body-content { - height:calc(~'100% - @{action_nav_height}'); - - text-align: center; + height:calc(~'100% - @{action_nav_height} - @{tab_title}'); align-items: center; - padding: 40px 14% 20px 14%; + padding: 0 100px 20px 100px; &.third-party { text-align: left; padding: 0; position: absolute; - top: @action_nav_height; + top: @action_nav_height + @tab_title; left: 0; right: 0; bottom: 0; @@ -147,7 +187,3 @@ } } - -.properties-assignment .sdc-workspace-container .w-sdc-main-right-container .w-sdc-main-container-body-content{ - padding: 80px 2% 40px 2%; -} diff --git a/catalog-ui/src/assets/languages/en_US.json b/catalog-ui/src/assets/languages/en_US.json index 2957f8ac4a..85acea6d02 100644 --- a/catalog-ui/src/assets/languages/en_US.json +++ b/catalog-ui/src/assets/languages/en_US.json @@ -200,10 +200,8 @@ "=========== NEW RESOURCE SERVICE ===========": "", "NEW_SERVICE_RESOURCE_WRAPPER_TAB_GENERAL_INFORMATION": "General Information", - "NEW_SERVICE_RESOURCE_WRAPPER_TAB_ASSIGN_PRODUCT_HIERARCHY": "Assign Product Hierarchy", "NEW_SERVICE_RESOURCE_WRAPPER_TAB_ADDITIONAL_INFO": "Additional Information", "NEW_SERVICE_RESOURCE_WRAPPER_TAB_BILLING_AND_ORDERING": "Order Attributes & Rules", - "NEW_SERVICE_RESOURCE_WRAPPER_TAB_PRODUCT_COMPOSITION": "Bill Attributes & Rules", "NEW_SERVICE_RESOURCE_SAVE_BUTTON": "Save", "NEW_SERVICE_RESOURCE_DONE_BUTTON": "Done", @@ -226,9 +224,7 @@ "NEW_SERVICE_RESOURCE_ERROR_SERVICE_ICON": "Icon required.", "NEW_SERVICE_RESOURCE_ERROR_RESOURCE_ICON": "Icon required.", "NEW_SERVICE_RESOURCE_ERROR_RESOURCE_NAME_REQUIRED": "Name is required.", - "NEW_SERVICE_RESOURCE_ERROR_PRODUCT_NAME_REQUIRED": "Name is required.", "NEW_SERVICE_RESOURCE_ERROR_RESOURCE_DESCRIPTION_REQUIRED": "Description is required.", - "NEW_SERVICE_RESOURCE_ERROR_PRODUCT_DESCRIPTION_REQUIRED": "Description is required.", "NEW_SERVICE_RESOURCE_ERROR_VENDOR_NAME_REQUIRED": "Vendor name is required.", "NEW_SERVICE_RESOURCE_ERROR_VENDOR_RELEASE_REQUIRED": "Vendor Release is required.", "NEW_SERVICE_RESOURCE_ERROR_TEMPLATE_REQUIRED": "Template is required.", @@ -238,7 +234,6 @@ "NEW_SERVICE_RESOURCE_ERROR_TOSCA_FILE_REQUIRED": "Tosca file is required.", "NEW_SERVICE_RESOURCE_ERROR_VALID_CSAR_EXTENSIONS_TITLE": "Invalid csar file", "NEW_SERVICE_RESOURCE_ERROR_VALID_CSAR_EXTENSIONS": "File extension should be {{extensions}}.", - "NEW_PRODUCT_NO_CATEGORIES_TO_DISPLAY": "Your product is not assigned to any group yet.
To select/find a group, begin typing above and select group to add", "=========== SUGGESTED ICONS TOOLTIP ===========": "", "call_controll": "Call Control", diff --git a/catalog-ui/src/assets/styles/app.less b/catalog-ui/src/assets/styles/app.less index 1ce1801d9b..13d88a388e 100644 --- a/catalog-ui/src/assets/styles/app.less +++ b/catalog-ui/src/assets/styles/app.less @@ -11,7 +11,6 @@ @import 'sprite-old.less'; @import 'sprite.less'; -@import 'sprite-product-icons.less'; @import 'sprite-resource-icons.less'; @import 'sprite-services-icons.less'; @@ -90,6 +89,7 @@ @import '../../app/view-models/modals/message-modal/message-client-modal/client-message-modal.less'; @import '../../app/view-models/modals/message-modal/message-server-modal/server-message-modal.less'; @import '../../app/view-models/modals/onboarding-modal/onboarding-modal.less'; +@import '../../app/view-models/modals/icons-modal/icons-modal-view.less'; @import '../../app/view-models/onboard-vendor/onboard-vendor.less'; @import '../../app/view-models/support/support.less'; @import '../../app/view-models/tabs/general-tab.less'; @@ -107,12 +107,10 @@ @import '../../app/view-models/workspace/tabs/distribution/disribution-status-modal/disribution-status-modal.less'; @import '../../app/view-models/workspace/tabs/distribution/distribution.less'; @import '../../app/view-models/workspace/tabs/general/general.less'; -@import '../../app/view-models/workspace/tabs/icons/icons.less'; @import '../../app/view-models/workspace/tabs/information-artifacts/information-artifacts.less'; @import '../../app/view-models/workspace/tabs/inputs/inputs.less'; @import '../../app/view-models/workspace/tabs/inputs/resource-input/resource-inputs.less'; @import '../../app/view-models/workspace/tabs/inputs/service-input/service-inputs.less'; -@import '../../app/view-models/workspace/tabs/product-hierarchy/product-hierarchy.less'; @import '../../app/view-models/workspace/tabs/properties/properties.less'; @import '../../app/view-models/workspace/tabs/req-and-capabilities/req-and-capabilities.less'; @import '../../app/view-models/workspace/tabs/tosca-artifacts/tosca-artifacts.less'; diff --git a/catalog-ui/src/assets/styles/images/resource-icons/vnfconfiguration.png b/catalog-ui/src/assets/styles/images/resource-icons/vnfconfiguration.png new file mode 100644 index 0000000000000000000000000000000000000000..66c64c3fe642a66acef23aec97266f40e6ea3a2c GIT binary patch literal 2835 zcmaJ@dpK128=u{zP%5&bXd0;@b2(#X%uL2*W{k834WYZaoMD&?GlOC6O0F5VO0q<{ z(N!r)QE60Yv(>teEQYaIx7x0(&2Lopw}0%j=XuWge!uVc{k-qzy*6TUCd-|fihn)PZrIRfDl)%m<>WbgsfnY39`5`5lx^Y z1hOE7?-wWwWO$M|Vj+?>r-PIW!?kD##L-zE&fhKH zMmQA=;ctnRfWEO_ew^4a4v`CUc7i&}Nm>I!P{xAFg#wY3Bqzf@*(GWBb7B+>`bk9= zMuvSR70B>`QpFMwibLWN9KfCcbs!=E9Fc&*+CedB0FOcwQ2-W!21sZk2@OEMJTR>{ z371D=(&%4&X-{NWh)fnvLZPCgqmj|}NUE{rH;S9##hDFjZiPEMFC1-`B03;eE6wbxG*=Udhpn0$_cN`SD8eSCH(VSQzOep_S- zYyHmet8^CH7zwv2T+&eRP#c8~XdJfX$YI^b1uNk?lt#M0fZ|{CKI=qtr{(5>CsKB* zRT13Y@?LayaL=Be+A@rJ=1Zh9`{T^jSEV&w%c#6{8(}RuOy4NU$gRz*rDU1*~oWC+=gm$Iu14DxaSNyX1-B(wtH$k zG`<=y4c6>b(fwmLDvpr#THo1u8xt-N)2nZ@f^Uj2ohvZ3i?EWmiyFedO30gC zK%H^9Y!(#Fa6xy#P=$OcJZ|;V9=ccN{-wQVs7jw3ZBuF0E*A$Hlc1w^TraHP1Kxt} zd9aWFGu~av$uWp|i+TH(Jn$-@M^P@S`{nZa9JJ?B+qEX^vz8>QkKo!VL-fR`q>?*xq4u9O~#bv$%@i(;k4$b*6S zf|9$}j+X7XRh4}^2A{h+L)WVN?g!?!)z%B&*53Ip@78|6Ab#+YMfIf3v5EPPl$$iDj>#U)`shK3QGhuCNg5-j~~~x}D*Z==Inv zw76<9%f}WgF+#L%k(3rYe*MG8-OU11gO1msIGk^6>xT~)puF(#n`*@$kxi>A;dvd) zN=yv`X4Y(5SoND?#Z|5}y*_LMB1_u!=*;^y@lNCbgSBx*x*Xmnvb6}l(n@(u7-~_k%OA~t%-nsUJ?&1cS>V0gXfsV5J4Gk@1Rjx| zcqRia4{TjLU24cOI`F&b@ng+?$|*|j!Q|crEw(9^1KT33LQ*dRo5B)PF8HT03{#%B zSXp1m+`7aFzUU^hl^qvvedd9>;wy@?e#Abz8QtvZKR=Yu_V_QDvQ480m#*Jewx-C) zGJRmsy1O>ELY`r|pWm$KkW^3iWvsj6{ajeBi*e`Z?*^~T$zeuaB1;pG&$Crg;R zU0?Wm-Q{&Z4XFxStJ`sv)IST67tPGhpQ~Fj<++-0dmu^Mc@yQ;@8V)>91Lnvlf zv=bN;Hgc+{-pMU9ty?vFP)3ZZ@}R2sfrNyf?&j0nC*RVZa`1^v^>4Dgs71Tq1wHSm ztK5Ij|L2G0p1bZ+kd%*_gj4bKpUcJqCQNr1T{+v4TS<$>Rr6DG6!M3HseG00gpo*h zT;JRp`Fa|XddTWW1d`gcgxsd6B(w38%F@*{dZli+NAs6Hd!cMDAvh-z^PF>Z9nx@D ztIlT&EWPrEQfe+{B&w=U2X2+VCGTNVBEweXw-@{BK8ma_+8kwmIAOEd!(Dd#wuN_c z%d8EVyX;2muqyA0&da;(^e#k4`i{?jy#%5k`2Jkyva=y`zo{N>UbJ#b(1HH}qDIAF literal 0 HcmV?d00001 diff --git a/catalog-ui/src/assets/styles/images/sprites/sprite-global.png b/catalog-ui/src/assets/styles/images/sprites/sprite-global.png index 7a795c7a91cb6a3b2b42eeadca2b6e8e567451b8..962478fed386d15b7195a000cbce03b67df8769d 100644 GIT binary patch delta 31904 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 d<=h(=^lHA;04(7z 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 delta 29043 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 A)&Kwi diff --git a/catalog-ui/src/assets/styles/images/sprites/sprite-product-icons.png b/catalog-ui/src/assets/styles/images/sprites/sprite-product-icons.png deleted file mode 100644 index e85467a09c161803d765e0cebd313473b9b178a2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 132122 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 !<9dr9OE|2Z6e($kDeP^p2LDOW9Oi;pDAPP? zAo`g{0~UP;k&(`%#6!pZG&_cr9B-?Vam^@X<{=TZLJ!V)oG`AiLo3~2coJKknFtP# zc(9;28!gzT_pyf{ip`{*(wl3}9g@!HVXdr4GVMA`=oeU6YFVC8r;x7YJRQ4_B$95D z-W?(tXKhY__5(3_|S^LMGqi5Z$cnV3BjubdqwAnxk9i(mei z+%pUF^uG9h>1gtim?>T~Ks$}b1vhXj@>bseZ-$U?+vc3R_m-QmgT0*=hFQ}Skg-dT zAI`gHyz^M@yqcvGx%sA~nIC%Q=?*3M-4}iKDX_ZEE#(-!T1|eal+!Y9#G>`Ms9kvF zz8PuVa}ra9*4@$G?C3d=e0i4;bQzwT$2$2o8&UX*B7W-3@PURwf5L}7i#}+6S?WEf*)Yvb#VLnL z)x3VNh@0|^r~A>K(wdV$=tB*zg}4i2F>?m|&IxhZ=0{dWQ-(EG~754e(#_!sK&w zTj^Gz76`^V86PN=)88l%ef_&!!BqHcQ9lP~8Xr)8asd2M!Qn>`AN>8O(Ursrvfz#X z=C`E1r$3TMrss(|lTN}nU(JY%p&`W=Gmo_lWU6jeQFkDWA9fa0e_1k2d@npGMJis+ zJ^Vbv&85XOz|NUjPKoy{D~DAHOn$3<_!Q-yiCeO+@Y}zeVa1?^@2(?cA*HxQWJ* zpZvAo>5!Wjw(!vAN2|r%dFJFbog1Jll_i1K8rUH;Fr8`d_Y>=}CU+D-1GDk6XGkTu zZ;L|B)d8ZBuw{>e?)+3*s0TCrq|Gn8j>QVmV@FL~BY=<9{%k*8z<3n-`N-^`Mxx5C z3w%t?-a??c{YJH#LBDCXVbq&cpbK7;V6^0YD5E}?+v-W3t?uRLIk`{{#|?Z! z7=QQf?VT4zn4!^Y#09Ov{TpdN{(ke!Sb-K{RAE|%J>hS4W(LU&u0$K`tDi56>oS9b zyJsn1w6psipjEcHSOCA06TO_5vU2;W6re0(F8uz2?Wy?C8W3Bc8M8pyplLC;2+U~w zvQAx_n>=gsjlI6Wdh#YO)nN0zDQ{-bC~EyaTN`IPiNq!Zk!O4aaVKtnFlqbLj)(JY zMH;To6`OkatlbB;lbv|Zsrz;u5L+NV;7Ly;LHEKspW~VQGaF7bFbfdcCgJaC9jn6m zd}gLY+X9WjC`sBULqU{74a5;2HC8n@s>~8QNN!*Xl+i`1#(>LZ=Tq@uk@Kt;q1)sf z5L*3QZHAt$B6mZM1~UCWG6#C$fnJztfY9k*1Bn=G1IRyp9Aj&V)^AV*iJK?yj{Hd?18GWGDoK&dD zNA)%mKGO*nOBv>W-v>5#wWQsOHx2DLGU$ z0r6%wHtY9gQNg2AsE)k`^yV7)5B*r;U>8&O2qrQ>PY5{b@H1* zO%aKmauDQSei6hqmxm|SluGwIPCB!?DL zG4G%dHl?1;`Q$J^PEym9h9+Q7H5o&0zQVDCX&b$jZT`)IzjCYVg5W+=WlLhws!iaY zF6JL8eX~?rpItT{8-XHicGpG&drUgnn&gFcm}gNrg)_(~fg+0+Yh<}#GrQ?y-H!0& zci837Hm7awm2KNX&0@@22r4&#d+nX_SJGTjPJ+K1$&GK+>!~kXd_;#9AH3zN{`V^b z#!r}6Dq{$j@!~AD!i&w)yuuaN(E+%_wk=-m-e+z0Hp#iEpG`L<6Ja-0mC9+aJRX4+ zY2^(#<{lTw^jiXiZH00l&4Vj^62`G_{^RI+@z(#|byK?W{`f(GXtYXh6YIfxy9hSY zmKIW`;kCj{2#r2Z^ak+Za|Qzj1gXDg^Uix8R*sBJhOpXj@|VWJEG{BvG``f8F7gzd zBTL@1NV@5DL0@UtkK0eHDs_blE4^>O;#pK|^X}nBv00@x(ULr4(4R?vld0J>XtKtN zpHnN0A$9fR`)e(#Gxar@mUR`3*7mblL=-?&gEUWqQMqYY!RqcZ zAIL``&3ox+QRDNUA**k3C(*l{)tu;(p=w3tgx-ctahyP6H}m4sKz=KzdW=CAv3)tw zpUAKESvMR}oN~v4ROH1Xrn4ReE}^HlOF4oli;W5`&IH9-4J7rWS77wRHop}=OJX|3 zcdyC=7_kN0nMo0Qgqf*tYVE9Pi73DMPcTYc6)YjJ;~R``42Y6V9zU94(zL_x6Ose7 z%A!9TX%d|_f6qQ^r{Q(GQ?xT|ex<3{asicgTsHlg&t2a!hVOm|{ z4hqEV#>oY1h`?&*#ckjW(_ZEH76!UL$C*7q{Hr%gmwF8~?AJfB|H*npJ3R?qCQlon(D1t|H9^OY z*9)CDh-)EOy2$mPs$nb_d1lYlVyT2`D(eN}s6I8#Ow;*hq3DMlnIjvjZpnaZGAER{ zpc|VNlP$Lr^5fBiQ5a%gtrRr}XYz3$$*SWnnE{Abo)$3Q5>?x(y?{#V7H~-=dP5w7 zPV}Ju-y}=1D~}t@R#~o>*`r5zCIG@z=FIvTTTNVb1LVlx8!ND@m zlzwLoaLFk-jrPLj^>+U$zD&#x`nJO7*kO36_j!~-(~?7iH844zS>h^k>HGzAAzE(6R@qL(u_dRrQ0-HQ$XMZ6r=K#fy=RNB!5Au8;n|O?w`^~h+DeDPkGs)c{4j=q zB87R1~_ZIMDQUW6-cAq3Sh(phSXzo)njt$Y#R!YH>$YqRk)u3 zRjb){XAJ9ypxB>?PuC z5FY&OQ@2m4bTUvZ1+;aNL`T9$`1S#z@LJqQ^-ZCU)7KBEXeyF7_-*?*naU>vKRr1* zN$j45JYDzv=cGTMkWh5@2RL!@PwX3zha^f-WE2?_Wbu=K@1_?{Epv|GMw1ykjB#+Y!$2N zcnX)}cTTR)GE0Eb8gF3)2ltf$`t4NH4;wVS&FH5`*Gb8!F^HjIi9H`K7CpsVSh97a zmC>&En;qhzt}z}2*MaOs6e?I)0^;A@;N7)&6aHa(fOz}?-JsXV`|TO4nrXu@Uc z8^f%DEWmDddN|n5TSm4$GK*tG7^jd2Y16WyoU{(EF7FV@_)k{$p3qQlP3Ld z^MAuv2E>=m{|&&M{BP&~2Dp68|2F?O0LOjV{NDfi(RtByd91_-E z*Qlt2+Ep`n86v7NGxJJfC+0I_FjOHKER>(|f4=E+o(hDB(V(2a<9p;0z{zs1lf0YEm|IRm`Wfrf>E*ktauN(fP5&k6`>*eEomS)`i zLq$;1M{2!{WrDOer=0W6iC%qWaErvNo@jUI_JUqFms(=8V=nXExWG)hF$%bnr*W3`mob{}MC)bM;3bVY+J; z3hgHC`ECf?`UiNpH;@N%phI?9r8nH)#z?RpL=Ycu0^#{v5*=(Uxg3&<=ghkjeqU2_ z_#WiR$h`MC2L`!gx<@I&fLmk5(cCfO4?CQI!?i#jD;%fc_wT_jmGNmyFF$Yn3U-Ec zC0*-1Cfu>@=eGLFBsgpA@IanQ0CBp7UUMzjhaY%kBeAOk-mQmyP%jN@|nH9;) zhui+J_%mWqb0$^woH?KDyz_0Y9E%w1s_Lg1)p@OKUbwG1C+lAjYI>5whFZX8>kqvj zF3*}i)k#bI@Z zuaG%YjzCPm-b_ZI?x*6sQpnMmF`8G<%Pl?>xg9ktZK%AD12?A>`IxRAhPErNbXOiC zMt{E7p2xX;C;*2`ze51d<6Ft7(5a>ynhw(ZbMl)Coh}AS5#J1=?zu$3&YV$G$bpbb zmV7lPf46RyfA8mZnS?VpkhyYD%&OR)d_pK@j)sOFMz#VRoV4CmFD)^*lC}jZ zxJ@Bp`C?up>dt~Q)}$>fAfWbDY?Q;6x~F9lWWai6>d5->8~3M^%lV7Hh3+4Gr*M7B z6_o`8Z<*X5-8dMrSu#2|h6QQ$;$CAPU#b6|$5z zDf!_6^1s_yY7CW&tO5;Gu}dd{9ZOZXb8S?MqT6yU@?@4m!u5Ycmg&o8`Jj6@^A=3T z4AjbjU`j14=2A2;;Hcv5qvW{J0Ng60ou$y>0&=}Irx=~uoJ(C{=Z8&k5OK1WCa;d3 z9`^O3fw4fqk=WGvZpt$KNq4e;u>g*R`^Wfj?xhvaO*aHMVH$?9v8Sq~xc7(x^q-CP zARa8~sU35PvZn^ zJiq2&!L?urgEBT>>F5aiucKdT2UTciyuAQ*Uv#npl)!vm+MTH;S}W@Xe0w7@k@DpYSb4!##QOZHmwZ2rM+I?4?-CLp4eSi#h}B^iYTHLmYKsOck7$fgpQ>FBY^5Q?W zgt0lV^tkL+C3h&Hdt)2l2CkKEB_OW|eS|5$R>+Ne$SN zP)O{arOLl9b}Ul8|4=-`(>Lkwxo^W%R9LK@)<$ak^T8XY<`T8?iY%L6{@!n4l6Af) zmu@VwMh)a*#*oFZcId8YRRm2tdp^v>T#jX@!25 z3pnqnGx{!fy;b?Vy?u|!ANsQ5uDYa^kar2$GmkC%BnSAnyiZ}aoWdtg()_X)!tpm=)8%59w(Si$M*tz=NM2fbDvNZx zs^RGfXPeWqbGAx8xMl=qUFOy9SePB|EV9d>d+0>u-}TuWQZ(WbBG_N>)+Fh=IqEC( zUKoSW7d&_5#gSC{BYIp@WY2`$+~BDprzJi5_ro(#Py6jlv20Ob>B%@*^Gf2)b;!=l zltmmGnvx;XWM2|DNB&S^)jmDhb$_-h@?mS2=R)#YUnO+D?XjfH7tvr3Vvawn_6Nb+ zdKP8bdSW<>N8$u=QNNT<{AfHKhJGn_RfV!vK^b}cE}o}ViQT|eneVu zz%>mVaoqTU3Lfil8UD@4f)ty9ytDQf9!?mZ^id=@FCv&*6AtBR_2$gX=QdUFQ-vKa z*<5i{D&A(17_UuV3@P^y(pRr=I|V_SZT60i`nkD#hQR>|m+3}BMnd=byT~ z;8_z7A=3T?^lA69@jeT8^b_>$nq!{@W=M@~_`0kgCE4CBjQ#S~tE%h<@3$zqB6TN< z_MP$ITIN^?#5WvD_%NYczT4;gOwAbm*8kk;>8T?L>`jN&kD)z#w^UGxxKGRFoouBw z<>@NTl4;fTxo#K`w4(5$mArn5GlVjI3vg5p?{3&_8?Oc!M~=f$tW#(juTpg?GVK}JAWA^Lmt$z(Z$sUqgGi~onXx9n@fdD^#WOOaBb z&|(FGySqb+J4FfvEfS=~-T9)$-L<$w3GNhkx8N2aNN~41{H_Q8mvBD^KAUATyEAi~ z=iJRGWod9tDda{tibf8Xr#SoJZZd4lyc6408^vi=zRO5nmKqfpaidn0!!cOSB&0j= zX3pJn#IfZ{ToH!_++dc*00=bWFP6=(7l6Ot`f%acU`k%ti`1uRy(1DVz=Js4M=AhT z9LbasPovxsSMD`Q^!%eqA-+Z7R_1|G8SiCP z4W@F-xENe>z%>S=z9yvLaCU`-c*#q~PkG13;eVM1o;=Dir8F@MV%CK}#m(c>y2*xC zv+cn1$2VQ3niRBZ4zzCzc_6?2N0>(%4~F-qkOh9P5$YtMez7!6P>9K06BoW=v0 zY(F@0~P2z6U6&#kj zP+yEj)nfV14JDwAA?th0E-uu1l#6PCqT?_-XalHMFYwL;pop)L!5B1cbU~4B?o^J( zb(P|9ZQ=?dHuc6@-PPs-R9Mtv+y@(zJs}y#IRK!6P<$02Ov5) zlAq;&QB0kZ3B%l|&p*#S5!Xqk<{kHG4!+A<$V~sDT6b9QUg3DsM6F-SUj~}bYhN&!+o8HZxFlX|9uvc=WR@nBFoy-1%XI_58UnQ+L>|<; zc)q&KHw;_us(R~`px}k6{)_oxj!nk)c7did)lULl{i?AG2gmGSTTg{rcZ^-xy!t<@ zb9EPI@&Oxi?*tAE&h9t;93~lGVz&DE8OS}y`Tu0MNUV{!VIaOcV`ujtXStc3E@-69x1Vh)( zr{^^o=2APibnf3|{-V(-oBsoFn)t|%8P*St)$@gsGf|3{eJr>xEet&o3NS-?c^r@d z@x|g|$xWhTfHAZ5`r79oSQc$Qnu&=K!jz15M~S(=7R2{5{!R_l+XhS_bXhGGP8Q3qnOA>|#8}YRDeu}%=RX`CNsM$a?P$t+R zZW=`SemN)I>ROSdO5xlUIAx{R1cmiSuQ@nm_@R6z7GWRdeWg`F+TMMb0_v_SI+%Q z5h*N7GU{27T6}m_13x3%DohVs_?3X?0>AFLIF8*R5DJTfe~o|rztlSV9LGLx9@AEG zQlVj{025VtdRU!zidda*y1sjNFHb9P4q!!ZRVaPMm_yM6$x4- zVhR=E$u0hoKfLixb&tyD6@ca754Tw&mVFPV4>R5RnZIPCmF|I%FWiXWn>*qwcVbEf zFHApm5?XZHdq3-G%`3ubgc%9EA@gn_k41S*`C`jxzcV1A$xqG3;?+)tx&KY+{;4|j z7wo3VH0|07^_`meX`c$d`d}9Y_W|rG?Jq|l@EQfg#Wb?HqPIphS>tld@R?uqDUH2l z>%g}}+pjf^eCvYTgy4AYEWz7H<>TV1f$QB??3|9SvL~3dm-$KMepPB8bY9mjr<9&b zaMI+Gs3s**Z1L{^rOv^9%i-2GPF*V{;1c-9x}gR@m-48D3^Bv8nX?Q0NI9}8l@dwk z{n`NuX+SNeXoTzOdy=?~GURuj1 zXm4m%164n%2(|*#g&p|ZJ!VMBUaKTeIMFC>X2HI!i0X>#C$Mi_*JN9&tjwBAq}VI7 z9}roFAp3O||}E>9<%?V#sM+xDqmP6gGX zFI;CeuETBQ&9|Jp7ZbTNIPcsV5@AASNT})wJ zjxHixaxMxhRq0JpLS82K-!&S~&^i}RGMoh4V6yuH|=W{we+^&{U|JKM( z2!?_K8*4m}VfIPr4<zRD*;3=mscRoa6jQmD(lh?exx?d~=9defczQkGr8RGgTl^ zTB8G7ueE?Yn@d$*?|&Smzmn(tA;-5iQq6y!T%T4Qlv1ku4`+IrbQnY1=-4cb%fHF~ z-Qn2M!g|_G;i~CBZ1Edi5m6SEc9lspW30l*sIif^QYM+1sw7`>I*GvdtcR`xRgj5d zv2mXT|7%fRQz`nO^LM-0{8VRs@H)nG*18 zpGGy;iWU1_i3AXxZ(|K-c=@!vG*xM`YY~NOwhZm>ig-JcVZQVWat=(nytgT!eZ4f#oC@mS z!*o*~&PJ_6JQ4Xjv!(W*0k#s~V)X{-BOSO#iDPES=!xR%%eqqBA42$}>OI{iw9+IBx}{pd z%$p1T(ZFob^`>^Pan*iG**kyq#)EVOn?jg-{cZUN$jt+oP|VxTs> z%Lef{XS5zZ)qjT-Fc8FC*UqLDStInUSl}6Qw6}-1x|?Fm z?Jiqq%3{MCI5i-yXNC=W$f->Sh5s!VHoI zfpI8l??~j7;ib&dz;aG}WFA?Subiosm0<`$Wrtg$K=W>YeUxA=4<|i4y)6L8R(YO#T41y7u8i;Kg7#k6oOEy2&n z<%VdV4xT)Zsn`y5f97IeG{FhGUxcp~j~wi6)dTWS-dQPW~K?fmpg(Mrf3p zeyV4yd$l3{%sts^Ye1-0VNS>r68#TNJ(;2dtA^zFB;IF`&T&4Pa<-9Wm5~dwR%=Py zPRb&)cv2*LT~3pdgcM&lag@BxALFyv^=mn7}((6Yq)Mt*h{h_dM7m}jf zw`Xd}f(3PiV0YbUO9p1z@`W;Yxx4ye$*pAg94!>E$dJKms8j$ArOQmZ9TU5=@WnS9 zaSeZ(mS%AvSg^%z$X%=&%gr-)GV140=uP~P(f;&TsDB52Ngo*6@|{j}Sxw;`afeW7 z8sopq#|}@6E^r$R8FKv$pF@TeAucLR)Uk;odm)QO^`lz;COSG8pk}E%z!G&O}QF^^5=4JbiN3FDC(*8RL%7` zS4BSn?7u0}sAZ#;2}Sv?d^Oy0N<%pUr}qB#YW}z_CP)2@CK`T=|MU(Kt@$3b>BOm2 zSBkeJg=6KY1H(@UZTiD`e_O41n&MivuF47>^o9H$q~{u}T{VSd&CA8Cy~jYST#{Ar zu4GcENH*0OC+IqCzKVm72uzJhCvUR@@frGOW$KBnel{Sh6Q6QmRa@zHgFR(d6=jAa zAC;3_xP+Y$ui;@JweQ>!m&WVgV?T`#9}O@qVZ}jChzw@0$)*lACk@?;!~Mbb*c94s z@Hd<>7(YMRwj}SZW6d=a)ks%Fui}U}zS%H+YXZw^*15O0i|fZbyEzx@iy{o>Sd(*P ze39k18eKWW)G8m80E=M=o94v1V=;*p;-s8{7UhXEeY$CMPC)E{f!I}68?Q6hnF@rX83dKM>K{UjE*kgDbdku#z&8D5X(}qf< zpjUkeK;hk7!Ep9yP1)+U=>V_Xg)0I+Ovnj?@TAsPS+m(f*~1e-wv0yjxq%R-8=+R| zMzqkz_j3xhA)EoRE|U0zqito-nhopl>gAi?xOHpK6YD*-A!l-q~BWfy(Vye)dK@XeMJ zZ$WE?Y34yi?2C*mI<8V0`Jvb_uD7i)kJME6GnGNv38`5o30>^$*&T4ksfG{>3Vd{F z|JTajmqI*kqJo8f5{a*Czt;25H=p1(s&Wd9OJzVQMqO^P$du~HC)F;irP!MJW=_)H zb)ck^Jg**A?=tZAI`B2lc!^G-_=&it{7=c7)dOGXAxBl z7%*Ph*a0d>ZC&#a7wKeQfO)Muv92a|p3UX(MCpp0({)PXVzIpI52GYnKn?LhQcj?V zoK9*3539-=t75*nkFF~Vhc$}g;D~x$4pUF~k7Q}Qa7!w2PrfQy!_l<@=awi#u*|v7 zWAo4Kr0&sTrd>)Cjy~}u*yRx?OMsY4$;FkJuEkya(O$4BM%~d}L#g80h{{N@fe)t2 zzsrO5q(%Cb?4+aF&5^=#0olavcR%x-1Tw=gkc}TuP?tJbkA2x!tOSR58Ivvr8ne%% zDtK5-Ca11mzf(TV|DBp0o=ADffJk45TpWf%iR| zF1R(D91u!?c(XrG?;=X)BS)uPp}}?oox1o&XH(iD;&8XN@I3$jS zWYuEH2wjdi~S^8|M5~qTgfZGZWvDdk41q;o?tTScnYr#gKhSfBa6$O z*J~7AOLOxTAmb)kim*t2gH=CD>JU=?`a2ejWcH=C@u)&l$>S}ND-#prE=&N}cdkA5 z>1&_&EmKckFI|SYnf4ct&lmyoiU6>XlK;qhaR}S_C;2zqLR54_af#@gqZF>Og43GjFVl25}XEPnetfKpK zlL#AyEAh+(;vNeeaiN4+I*}UDwG{qw3`6Q=rTglV2v8w$ZC?AzmIIeOxvpygM-cAy zts?={>UP9lz&6g>*zsxzig*eZUum$ghf*0kXhXPt$KsA}ulJaKLRahhtu&O3sZ z;QDb$2L=g=4`gYX|CK^(_MfaHV6ddarN$a!YcrcNkbYkNn}r z-C|X9#_+=!=6ek8{o#X-vmw80Oz5Ko<;eR5-M&1gCX6%MsTSj#!e+@<9Zar;c{#9B zP7ecH-;gf_20GPc?=j`4HFA-gY};VIFoLMI4_lyH3w$&A5E1%SlqBGs*#8+^H0lUn#s~lU7 zS~$@<>}@)>Xb|b_zO=;w!t!c3o)0&8G)y8+(|4nE!J6~EkGiY9J*r$>&LDXp6Y*%Gs*Y7o;VIXS(CnBC z3SRz}ncL4?gb)o2l?|t>Wgq(6UN}~H_8eo#8{^Ze4gWNnx4xO*54fnq z&3>uJZDI;MorL`)yTTXzk#)#6K~Gopn?>c$i#hzLyrbuWOcS#G)}%{sfy{N*(UoSG zjjPomddPLz*M|UN{NdINF$WioaLFsLN82^N->STP?Xz!Cn%y3w|KLf4Qc^lsc+h8; z%~4KVO)5|(2jy6<RpretFQ z6iPmsr5!sXe2Mw!KqpD*16tL)3v76Tk^Wd0``lRIA{AF@OM3sdvhG{=znBU+Kb~p)<^6&T`~=ef!N2wwPH{gd;{A^U;u}U* z%hNA!&CPc6bCs1bh7FtaDgXD?9kewQi*JWe5`fgXk~xW!XfZ*wr2ppVu_GwgQI`gqMYMI8VXmB{@`(biAz_sj_(|67ia_l2! zd8~0-Kf;wI4cVGMNQbf#bcXstNMdNAMJRi=eQulPRYzr%UaNF%!+}9K(e)4N$UtBB z*D72h|ITY=^|v2i^IebX=ZkD#53LC1$zG>;lXo2&P02WjN_%`0bM602aI+Y4fJh65 zVp%lzeQz+3k=$MjgMg@FP{;X!c^~Zt+wC34DVh7NPAkCdPFc$9)$t0jp|7#u@=48W zR#zXSXM>2Zw9Zma9As%eVk}aB+F1P~)J;#8lYED-nYZ1Vsg+AM^`1(_F2Cf<`5y-@+qIRI@)GVb?;hMp7;m_MPq zyG;)<3zt@Ax(V%@ZTQ>-53VM$_;@ItP|wW{wotVhGn~-%?~s4J(x|>pGC}&dO(M$b zfAk83DH+i_91uhi!X6_WZEXgMXLbB0{2 z<7$q$2l~+(12a=tWvKtueX&8x;#}+GQ-b^4(hwi8%k_M78I$Pa0|JzK^1@nIMw1w! z(s$M5R897dU6ZE!vd}p3!><{?23IP)@IOeM==4px!6qX~H+CHg(49Gz z{g@RyzR7P*O{^DcsTc*qtk+&hdKg}Bd}Wb)8L)@fk5J?Uv>XR)1Gz|Reut^++C>mz z&+bZA2ov^ZY(HQL4$lu#qQ-k1Fs*uHQa<^vge<&-Y+$ff5sRO0sV>n$ z6M4O^^Kw@JPXI77%gSePOa-yg!+P*8r(RiVl7Gs+3+Fef9tA!`hmeD!k1@fRo^^|% z#pn3KLAXUdDb(3yN#5tO7y!vG{nA7zMP380X$OKeGR5sl0Fhzzx*3R#wRPKnTNe3v zXyne|AaSp5L+JS?pEN1d{)tYxc`#42sVsS`Qa)76-!`Tn8r&$gXx)_DN(sRvn-9JS{Cy&A)zTZ7c&PK4>NKRdnxWwP1-+jnjc# zpnS82i&^8?yJTgwYxWTkC(t<4*WgctFZ)8$WpL_+XzM8wpMK)zME?kw{Vq8tMwj(k zBHymE+6{-d=uIQ(4Q0a<6-rat511UhgncOpf)4u*6KKo^ES`!GGYBN1fN%}o}fX|KiEH98PILpFazu2nE z(*3KuNWlO5VI2bk?WE)Q`Og-V|F`+3BD34hMId+oR+ldyUm-2O8Z=pWEpUg_ z81?$hV-f6y0@F`#U|`BQ{FL?%@j37t?Z)z?&!`PzFGkjL&PeGBwyic$6OJ_N{VoC% zk&xCL2N-(o%NddGuVjp2Q{hm_toB1_C*&_`4xQ_|mw ziFN0m(BFk@k`Zmihh!k8Nj;?hBEBdhs6l}!8`Z1ihb9%ZD|UB$5b{_&Lfg?xx`DE(&jX@&h?YqV%}ByL zvD|e^>PAV@9evB6@;ER*SV(S88=Akn4kDK*QK#bRI0%U;z5UkKbHA*}|Gc|{Ee zOmw@n8>-xGZx0TAjsX}T8KJy1=FP(B@0B6AASJNTb7Ue*lHjLa7*Z!om!y+->7fEx zDX(Ys@8nt5Zs&-(`4SPW(OisEG|--#;iZG>X(8Y2YV`qR8=)05DDp(x#>52##5_5XufHss9HU7W!U?ML zs;)`@oK#TIEi`#LZj*=L$Ve*soPqd=Q!a*JGf33F^vo>f_j@_8f>+K+i#pkb$Cwu) zLI+v|8Ei|zsEGv#%I8jro8zTD=PI0YNC2iu8BsH6FTnC%Xu*-vVEHODrk6{3dv4~` zo%$yb;>fRrv;g&-nx6R^au;&p<<}1tilSLE(YZEsAEj4zqJ-sfrV^k{v%ma5yk76p z-gRjmdFoD|%@j$|q_sflNrloCiLoD!g=&=XbL{TTx{&&$^Ra+ie2W@mN^f4$hykEDk^;N97r+Pu@u_6=V< zR>mQd&3uIDA3I!AiQHO->yKQ?BV+-3W*}*yr!3CG4ML@v4G8W zq16GM@e{71;mDF)L0I6#Y=Xw3m4(Yg*MLGo3NOF5t|k zE&Tol!Em0`h^CReuub0l?$rGeHy48q_R!5wI`m{L%Ptu%q(Uk|XQ=91^1aI}wA%Xy z_(eF|4*Rjzti$ewP+cfbh858R1|xAnd5~Au`lcwZoJ!F@4XOAyh;3`d5My~(gs>;d zBk+fzbUJMP<}`8CIM%85cmmi{{j4xUX~wb!JI}{~QH@xwEU~MrgNwMz`fljBvx+ecn$a66ZM({i(95JsrQ9JK$sHfaHK7Z9HF-1YHI})O!e@Z4td3mOi{G84b~mK2d+AdpX>% zbCDN4;EZdl$~zK&L@1LavLo{;eI##jX?MG~XH;b;yNoI>_I?t1LaKnchKU}o#Gurc zY|6zRGckouzjI(HQEp$7^3e2&qS#VR6&8*G`Lf+6FAMb zuJIB@m(5eyq~1r@lg#9N9`&hjGh0UZBKjak9#t|zhs(0ZWaugjo-0Ho5!KA;%u%Ms z77WoO0(+gWtU)cbO=V}EsB1MhY0`ISLu(17XFtfKcb-=U^E~14*SAm}DFZ`vM6%4O zjEXoKoz4piSH)E>_#`Bf9hf$9*9{f&b;F->9D3h<%M0tZm>Tj<@Zw3NEK8c0Ysp<* z6Y{|uU2=(N?_i57O=dlWSKg$E+k1Rv4czKkRGl+h?$9+DeS;oBF})l#=swOr_kJ+* z6+$jyb3zS^kGv0jRZ;dW2=}dJSD1IL9b(^7*its@NeW2&$1I5+n116m*V`aU?Vs6Q z@buf$azXd5@sti$NJz(Bd3;O5_lAnYk)6I*J>HDRWC)7wZ4NThHsx6^Iwy?<*%=h; zzM)jS#L|-6<16J#*{ZFeQ*dQrzUo$3FKiiFR(oxF_h59$V@Bi(fgdZj%@@ zv6{-UA%Ep~#!l2?*sbrbB%8f0^zHSkJNWcX{w||}3m8E6b7!HtE#Eb9@t$obHlvE( zWd0fnl)Vx6a>DqFYQXaC%SPP@oT}gVlHnR*QK_u5q8+~@yyU0z9lPN2etaUVCw|_# z=6PGHB0U~P3XEl?Et;sk{H+hs2MP2wi3&?r((ih02BrzK{jjf|HYTxX140-<$#&>F z{0kEIh2Vdt=_f)H>tqz;d#C97WDn!U=RWRaChqGDR8>VYZ@L98|KkEKQhY{SiXoga z9FJaY-3TPkX}=5a=uy|#cG4hSi{zyP;(<}d)o3v1Q^V}64V=g?NeX3yB;UoUcBJ#>_CrqT%4$l82{z) z-%PfMM-Y@>JHej)`6yqd%(Qdfok5`Rn0bjWW?tz`P)ZWWL^Bb_nB#(PR zW$4fbtaw%IOt5v6J`Tm>tL%iL;vk@le=9qOa)P)&`a4&lyK>{eIic*;Z))0I?q3yFSgbfm4x(rm*YC%;GzRB|G8?_vj)XnNpqIMy zXn9=}?y&irN2gPHMkwZ(gkuAs;Bx_ny6N|16sJeOc|GvzMMfm#)JBAX_;0+Z9B9w*C^vwu`p^<|RqLS=5U*0z@Erz{sVt|-iIZ{!%pvsCt_+kNBTjcf)&OiUFxkRGyywt4)fqGh+A zi&%$BK^yJv0C{C4BhrbkmA%7ImMw9jhx_$PEvo<4B|z8%Z!n8G+%hjzlW({0p?$%K zi^DG1oQiGTRX!rMMaY$YD`%R=F7zcXkxcg_CN5C%9Hd?$w&>kUee^4kzic}-T&r07 zpV!4iG`fzaFTTl3?!7$qTzf&tH^)}-_MvLoI}YDkOgZys^4WfMGt#l0AcWTTDn)a{ zh&xwHqV!uXl2kii^q7Gnfr@vB8=VcPB20mYoP7sb_oq(ZDZ+ebVF>l!@XsMWSP6G* zB~+LboJ0&dsT&2}R)ut?Gv$t)B&2QuZd0D{{}C|tdt_W_b942DWK1|x_~ z!#+wSU)q1LbU*F4$tA?aC4ult^}rvzE3W#154+X^(xC9&A_e*PtcZ3IV-Q|`QQl8W zK+TqUyyb9C%}ht#@L*Tlq&HB!6(^EY_k-);m{)0AQeLF`e}C6&B`}&8z{$s-ShYI( z2h41*Y(%LxgH+hD1;)b2uw9AHxaAQ2?$T$yqz;-6dwlJCPI@Zsp&zPz-yr-zpG5~N zVF$M$l4-+y&v`eYs{#ANg-1lV&ib3+y-NM<GH~78+url#dHr**jd*4o z>O>kd>^lcF%g!olrppwJUIdeyh_M`j6GrXD){r=RLOTnC(|UPWR0$~!uCXL*y2 zf(VbM5emS16~k8X{&9Wfh8OtpVx@COqrLGLhuLps!(6RGtK2bX1@-I!`2;arfKmvF znlZC)yRb&Hg%9E}Ap7x0O#(YpoS62#*M`G8DevYKz=4Lu0q-NF4c(DQju53=OIZo4 z5P&nCZQtZfjo?!Q@SKqb0k$T8vW(OddMoQ*z%I*-Z1$poHiMW4D(PSG{H*^~ zeNIv?25(1ej>!;TV|j}90k%ia9f~pN zD?)@k{nUc+?III%wtMjed-=%zw%NUcuziuQo>7K>K%sOczGXufGF^TVyqM)|=RiZNwaUwyFLa*9De_7Xip)$T0R=Rv0I|{$Vjavi-Q{?P&LW zql3N2b#?{!R*B1n(|pd7>@lsxQMXR#MV5YSFf4)4CJ_FuqjD;DY1qvFGX zH`zOK5BVx4h?X$Fwa_+qj@W#^;MyOt$>59ahK%I!t;jQAAjf!FujOZcf+fxeWJg{^ zkUTlDpi(q;B%f`wl0|cE=tICM0QkBm045lG(KDXG96KLP^(_B1a!R3JV4&I99tE~_ ztP}yzcR40YtM0^`nDcnC2CLrbxs64wkjsxzi19ba9WrPvT8BJfFPQ|+&_!4|4n#R= z7B}}r{0ckht}zHK0U>BbvNyZrB)OvfUlX8S%5IE9jk?t;lD$sigYwtGpt=kb2_FOR zOmYRc>NmX=LbBavNAe911z3qCuIWENoo*Ogr~mu8#8b6W?CjV6lzb%i_=4`p%YSBB zweQL_aZVmPGa2PZ^dIJoVU(r8KL_oZlIUY>qEz7TcC-Zn$fr>wsQXBjDs)rojyE44 zcCRbJNy>9ZeskIpTzyp|PgBrV;uPEwD(_WOqVJd2|&nQD)ez_>Nw!0}cCDwSxz%>)=%_J;-Cb zcAF5rb}P#{&_eJ6Vf^-@sljU+GP-^7)x-#rY9A}JDL=Fh#O9p4_7RIeq5#1chtqFa zy0)wGb_Q4jJ5M{`D({}q8#x&$=hw7WDgsu{fBrX{Y1=$`h@;Ne?Zo$^j#79->1M(@&Ezumy44e%X zURxT+vn(wvWnZE@1(qDft4S9pr&BDB`H+$(Q!wtNME$}l7|(Q_`ga;z5Wzj{vSYFW zlG$qvSKXyZg3@KyKFbXYM7vBF$k7@l{@6vB&}G9H)%=G~t{~^iSk*I2#|TX**PPk+ zf00c4M%2QaQ-JCvb$ACST3I z`KZhnHY3$wd_CXjjwT%H&SP8Gzha_kp)S2Lm*1N7sUZP3HRGPeXqoxz{lT;LuH7<1vw!Gp%1fX*x(&xV zKg;^m3{Z!F)AB@+#{*EcYY$7H5~GL6RHn_{15y|p}&maNE8#V53LJHLY}Uc9^^$Ztx@cC1ucPTi(?*7 zoB3A1=C|47C*>6C6!RltMTh+}kqgD~J`K+^lq1LcU?_uG-{q;sZi*|kNZ%J)Qpg&amJ|&7lGYRwjTY|tRF$d*57HdM9dtzhrHVdIFu5;&DYHK`D zX&LYbRucGQ0cHfNf+wLhL1O3uO76(`#uFFZuzVdJtaG+d28-`U7#7QYB-~(wz%dXW zM+MZV0k8U4mSh5KD`l|jN-}I9&UAdyt3sKGgbM!PL1Znwe)VN2VEf6=tH=Osd&idt zFnm%#jms#yS+5iXe24row)a@Szd6_!HSXj6sa;Lz{rrWxt{hMbAuGe4SoAKklQK#De6DF3h!-xO&H6@F! zAdYZX5w`FiaQ`BpLO7-(aSwHTi}MIong<5D&FXo4Mr83pQo~x%@#~R73h#Cj8)RJl?uQ_Ytg&p;IRmDj2C#T+sa&HMx6j+^6sj9!pGeR(h+S z;2cBZM-P?>CeIA0kxS zbNo*7{OHd!*0^v%xBe?+GS$*?&Gi*H(&^ZO_-fOdWPjKw%l1|q`0p*t1ZQSyTpDBP z=ZICxSoPJJ2i$%Hh{)rk=O7rWg8RPyU;fO^%7nebQ%U04PrHkP!XlWq<7?+03cp?R z6K1$ezqOK+3b{has%}wxO*ZjCVLL?#Kvy0Up#n@zkNVc3nP@qog3f&p!@5|kxZFGP zom$xyFgT(BW$*r3gD?!;-LjGXTV=^wI-r{}p}9pJJlCvr%^4#p9@oF+k{UU+fDk7< z?)E73-Ls$FdzV$7s=xAq8)Lr8w+RdWO-q}8zzvifvWs`6ja@#zQXxNfJAYrLLWXKg zHwYd_n?B<&kw~y?;dI2P=v2;AT~EirNMDVSpz#*6-5*huN8xBC^L(rd8VNLIynMe~ov_ABgi2uv7yJ z?A%c2EzvVDf@X!Q|Nh-g!n;kx3<8Qye{!a2TJ;K1tLAniNT3`I~@cj0pQp?CdFxb`GY!B7`wQy2$?IO+ibQzRcnGHiW|8 z`oHc4nt5a|E*!4kZyv6DDG|2I;bpC|9)H_5A~$av_$O@`*dFF=oz!E9?1aUCP1T$= zkhgiBaS0uG%Xtvcou}McXZ*?d8sTQuHRwZ-SVU=-0_zi%l$;}kBv(gGUV_>tWzvxq zkwKzLl4i1TchS`$EO`c0EU!mGm=1oPvI~4}`1Y!ln`-)bT|Cfii&~4ObaHbuF_xY@b8m>)LN26K|DZJ1sM<4cH$D2Jk=ev=%Vz3Fl*syI zIZ4WGMF5?T*2Xfo;h^u^dCS^|z6FWCd!z9kDloigU+|fw=;13EHP1>`78f$!1wS+z zoa~N|t({F<{I^F-Y;@+;J0LoGsv}J@N22cTy&@Z=D|n*v4*f% zXMT|bV5lYuU=0RcCbY2ut!5dtxK}u-+{?M13_L>?87IN(x5O5A>PLH5Y|nKrssi~4 zWx>Vx$D?9dzt+X=?To>-?xH0LK>eUulb>K@L-wtcC(EmSXjw@@xmCB{^o->UB_hA^ zT6Y(#u#y#4W?F?y*KAf1q=6DYfK+)sRC8-$Gc6ND&e1#)oqsk}eahX~<2 zPqtbv$((Qu-_fyaX+5I;P+(iPx>N`sulIHRG710k25-|~0);n{9|vW!$$ZwZrElE6 zS<2*>$UpBzb&25XUVZ!@UVp_m!bu$zY~<{XZ)-*dk&9C5)6W|ad1s)Jc^aFU((Vr) z0oXbkHc~CJ^A&6JUXA~P&D@s)(4=Encx1mI%uC$eZiM?!_4rC{p}ulXo(PFQN9~Vb z2J-Uq70)olh%)8)-?h1TRZfL;v=wW1*qV!> z?DUKymp2fw!aZ(_`g^a5G71D58QlGfVwpw2c*mvmxz9?_NBLN8rlKLF>GBu^I--@`SyYrH0fgPJ`|dAQlg> zeJM&?m)`%-<#fGGqF%tMN#R`JQb?8x=^+^z?7kGC0r1)Ni-WaB2)lP@ZnFm!Lyir0kaA#@b5&XVv? zaeUa{=?%W58|-BzCGx1?cxo(0>aAP8d%yF2$jj^|l_-?cJb;{^=sK#K=Aw~HtO0l&E|n}IKAf=gN}xpQAr%o!;DWA zj3UHjz~^gx0MfsKJuzuXl^C+QNw-`w<4j+?TxQo!4$9@@6^0e6UO4rO^gFV-3`bg$=%R1Jy1j0p3U%^hfQiE*S**uz05zYXX3uNgQ zn}3pKV0l4K+qGL;8}LQL84s1G=CMRr9(8PG!Q#3_ota~u7 z>F>#9@=o?<9go#yR${4Or zYkXw?$cZpwxCCY^&G+-V@}-!5F8})+0M~#O0B1_Xaqb#@xxxtRv_J00Z(aXdsTU4P z>g8%C6_cxa9zGc2w9MoLEov(vjDMQ2JtsOWj#wjCI4&#Ep)%d zKOaD=0f_|tN%q0h%<1^S{~vd6*%W8jHGzgeaDqF*3GM`U3j}utcXxMpcNpAV!r<=i z5FofiaCbYy{k%Wn)cJ5Is-|iR=9=wmukO_i`KFEZI-(^05Kf22)EE)7yJ|dK>a4jltFf3SW*LZkT*{*TocP~{qs*o*qNz8Dvmy$ zx-L&<3awKs8;99v1Vms)cL+OeNfFee_ma)Zmy(4t&1$N(^}>J_gd5NaveDNa>QKWj zSySRsj|i$Zr4-*Iz1O3wQEh?uyzu{^Z-gPb%Rh7*Q0g5y#OFhrGD_^a?J$ctH)N&- zwmCM!E^5rSju(F@S|6{A>dl_*)!4O(Z$}v1l7y>h`N~ptHGB(et+&UuVe{;m|xisM1d#bohd`sBa`UL z@3&l?y!>}=yy8nlFZ_e?RE7a`c_2s)wY;SaXXMR)KSB=!{o^%0uUQJL@(O(vn9^hl zFh*zAPVlyJKnn=fbRVU*ZJdASvkoSU@_WzOb$u^ObcPu|hG%2^)J^C<4F%|hDLhcU zx>vBPF|Bpm&D5JRxn|~)l{@R=X{WttY?r;8Q;UFWv%IX= zrcK}S@_em3zHjn(w84Q@p(M^_SA>bCT2hcx$8y4Ra@5jjYT|KU6Bfz?qC{YvPLAJT55w@+Gz4@{kR^dmBbyfTsR26Q-OW0~3TV-h=*-e!}n+`hVZ z`(rsi%$$6yzX--B*r$HJ^p~(ut0VX3^ToF2^Gdm*`Y~t_J*SUBn-)uhoRKFpVr<4c z+m`3}iyM(FhrlyW3y4=-)t-JGNxT$j|dh zfOwqbL)Gt^OMq%c;;9~e{G`s8*-SILHj+~FeG4qLV>08b;Q&Cdd3wk+`LYkef-W(&Hy>d& z*Vx=Um2$so>=l?+a+9!eB@DCCMY10z0dm&vqWg^ZpKt?2c0#}b>FzG*71YAe6(-NM zxAS@>6K3ehnX@9o|Ch*>M-@x6|_P zGXzkZ@mr&5a#;l6G)z{`aCyV#bPNfG}Zj z=Fd^VMT$?|B;dp%5?uf%431n<8$JGAm(1Oo06r8Df^v*Nv~}@B5$iN?%v(5ULq(ti zOI^iY?F?pDT#al>S?_0DktCN0_3t+N=n*}43$p9oQ-Mf%1jiorm#79McE*ZB1Khi) zzTs3K8?qBFlJlybPXv#A+UN7Z0Gzi+Gx3uv=#Rc~XSU_jOxjU-q7iXVfKv1U%O{G5q-ILM4cjx_i?OM#}{o$$M74-@-wQ!zoc% zAA|i8hjEGWJ2{2YHU`k5@b-7jpY?Kz%=-pAGO+++7P_wAjs4VTTPAFHvvoIv?SMan zo@1~I!spxX-*`nQWV3QAIW7Ug|EmVKH3U@Lt_ARK(>TXG;s#?DjJTz8cI#rzmU$;Hbk_isfki2(j$ z=fKcSJ1Q7<2vvp5I|BcV#o(N@gyXM_hnJS@3A908gBD#=?;+`5^!c?LyX~5Hg-n)$ z=Cmzb9tLCtUHOFpnGbCTzgRAEb^&Zc9)#*21`u*rO?>u0+F(3^CUNu+M4vu6APJe9 zo11<45ODKUL2EujDw#VS*5|5@=(2+@0hyy}(T(M)*+QWQ?z@j0dX; zHVn{E(dJkFu5{E{;sO)ktg$228ijB%*gqPt0L@#N3*t$-Ra}q+m?MvI6Az1;r*=3n_g_YQD)4viVP$Qw5lVMG@P{ zhb!%X$fNvjy3x}oAD=IZJ561DqGW6-ab7;YQ*b@@tWkBsTK1o&DeMOiem%BogD_C$XICUy#RYc1qgBHAiG6XD!v(#Cm%)L}a8W zs%0&yM?S$x>>@tHbC^RxcF1pBQY?nC%I&yRitvYHvgZsdG?P41^?Xs$D{f{7M8^|Y z{PoTX94^$rY%31&Wvk{tz{2Xl5v&Ys+V{sk>43jsOOf&S+NbsY?(Z+z9oaKj`gja` zUsD@D+4u?ip3DDQicK2PoBhyq`AgAeF8^%tM;NZ&(?E50vf#kW8Bxdqk$0z?Ia6^{ z>Vq|Hg~~hecWl%of!}YyR+12$Q_7hFi)+B4^%Id0Cdns0z%{s;lkP(27-@jNcJ$_} zIx2qPi2cR01S%t)poRLVqiCt59?o_@ikiLAwGRLW59gM-Rqf|+>;CIt#K4%Vq+%1N z6yRm)qWsogUe2{qs$NO9nJ$ubegZ{~tjMOe_|%ZznoYca8D;Fv{Sn96XNNrHV!1^= zhh&%+Tvc%14SX6idYXFrMZ?FfkF<90%?nm7N=xZl1$u}n-|X2Z#T!BpPj6;?p)}1V z;h^TVGZENt22n-IlPE2MWl8T7;w1@i@=4M&hoW)wd**G%@koV93uE$%x#P{3Bw(Id z`sM1wuqsfD;<3MvWhG-u#qfEZ*_hh)Tap*u>xhrox1j}^o(K$1x-uJW1mcE{5#`gh znH5!baUf*Y8xT3;w8VYQYL!TYZYYfJz*n^UJtgjRU(k(L`pNIEPN6Z?DV9;-bxKJU zbz++%KT1sMv!_xLMFcUExN^wc?WIu&6{|t+c){na=&#ZkmuND$v7~H6iM1S-U$r-! zac$7laFh3jSyPQrJshQnjQ;9TejZsnO(1}!B_kZ?lvV4qCTN846s12_Ple>@nKRmV zPhCA}tOOLpI#(*u^hFQSugUb;l#5J>&gXkmGR~@9yF6~YHEU#EG}6k_!xBFX&1Bv% zJZL66$7P@h7>)nDHbPjA2Jjk)S0)2~1Al4_0-%Dna6#*R)h$1>kF zvCRWuTSb2nZDyOHiBATJC!i}B!?KIe-P#jpvY+>s`2f#wYf?uyTr|77mAurb`k92P<0p2%%5*!b{epI!U2L4i2o_ zp;7lqMfu@gL-D)2oZ+;r?Oe533WH+>V#;Z@M}fw`4x`_6pF_f@?Y=`jg~=18^t@;O zz**Db&`L-$jGkjrw8Qbg1}~o+<7!3$f}nW%uk;bKLngS-NUp>$ylayl((x|KvzSrr zI98_bgDt|Y6rw=g%>}cu4E&U$9u8%2*_)iwF*1vfo2`5vj<<&^It>AubXVoygIRuI zguQ~Y*rp<93nIDq#u!D#SzbQ&&e~fSQ%FWA%jc+76ss&L$wd4e_}Ml#Kw5{4M=CFZ zpQ9ORP6F|1Hq}~6h+ZUS50=a#Ofvo@;4UoweXZxKXof$@QRYAju68LLR*xxtXz;KR z>VtSk)R}@vDH8T&om6#~DCo=V5HM&NB{40s;l!1EDHcZR%8uuni%GN)719LOz|-2m zjVby%&ddVR(F&*_P9zm40OplrJ&cru^57#Lmb$jdDSx)S%~q0K{PwpI9-O$LrYI>? z%t^y!Grd+wy;CSx_p#nJIlf>5vt5FqV|2yT_|Q$7Mwqk52QBNU4wY0d+2l==wFit- zX-CMm%R4hxI&x3YXMdVFw5GE6U_QvOb>Lb zK{Me6%|Q}!#LQq$DSqcO9{g7lGkQc_A$$mve*s}fe2--uIgCZNg?f?nczQkxf4{=0 zrW(m2z;sxjlv=g9T&JJ@j0Q!V_RM0LE$DCBJl}9{7kZRLN%bKx;z~6A{e~A^x zq4qClKDv@>t1it^5m&FtXI~G|bw^(TSKS4>KJ{r}js^d{K}V+|yDESr^ZO@14%?V+ zZw=b9gQL+8c>_f;VJaUvG>Q|K)xA!zP?E*NVCHd(8of%`9f9kH;hkwOL~FU|5@Vpo z>;%%-%z12mKEI*rbnqB;HCDV_jB^b3N=ye~S6p^yw`P*^9qQpBGNyr>*e#obpb#`)v-lPnlF3>EAUIoKc_G>=gEA`#*n3;7;+JQNgs z_`k2#dgt)$^2)>pwh|atuo6_Wp63)!!ZLpHA|t+CKvp9Vk7ixQ#P}x9^(DQtJ za@@!9tm7a_?GCo9M#=*=M)|P??2|o!p0mkS#S3sZqkQ!>UiHlmbqJ3^EIGB+mP0=a zpB>C_AI-5$D79Tx{MF_ZTx}_zUCg_>Fz1l(?Y3$|*|Aa^oa2L?)RuXS8bBoS&~5zE zlCh#EFOdJ#)e~@natN8Uai`ywkkm19j*5(Ap7m>FiUMqC3+kR8woaDszz|zREZH%g zrSchoh^5tNIS69!MBEu?TCda*oAN|2spb)Fiq#Z8V9+V9z8#(2h;1k_2wrtbV85AR z7UB5Axch#oJJ6gRy32-SVL{s#v(cy2))#F}9H*MmD6$IN-_6;qt)cP^-)K@{k93Ny zBK~-`RdI0}?bkgfoDGI$k%L(VPc78#D19&7L7+-Bm2hOJYaV}9xtrEx6jJEnU9Hr= zN(&LN401A)hxSP}yP$AtI+*g> z_&v`5ZGB5MrqFX)t)%yhu({GK^^rzbr3ql~IM~xnJ+}2mVo@W>?F2Cz*pQg6#wbQK zz&>N*-rCo>TL%`;WVX<4WBXC6o(ZOm?pfVdj(7HRW`vKf!i(Q5R3VkRHz=m7*`0PK zc0OeFHop}YPOYN{1h!EbMlGm2F!G@V^cw`gkUkRCx`lZFmIOxMu0%YCsHAopb^3Y{ zneXpLhamVC>e1GD+Mkai zBCz&>awRQ@2|3BkdgpP3Pz&_X-fa>5opsa`zSXRJKg_?$q;;)ehnC?r?Q98VQu)jB zVHW!TioWzakjQa9{F<5tTkV;QM8T)=Xf{ihp?hPWf%@gO9mFV^6aPrW@ME^G;Xex# z1h%dku2OfOuQW4GLw_lb>;;aO(9>1vC5Z;v^GJXBk)Y5^aJy%(zpQjnq1di3Tv#|< zH@z=y%i1jm=&(01A5!xXDAwyy1qYj)2@$=mcuds6+N;)pt035YIv9N-NKOXSi9}0~ z+j%G+__Tm9*Tcqvf87Sr5x-jzTnhoIOi>QEe!TtkNOjSjWfgr$uuayMzvDYJWR7?L zOju{_z<~iaNe8|Q8rh{17T%j$%|Sn@(Wpp7F2n-j09*bsKmHZ)%hWULyUM7`&T$aj znLWGO+KS4#);OxfbzCl*xZcm>>kv~yKF7n{tgR!JsS6F25GOP}OC;^>+}(`z9AH3~ zl1<_biZp;Y!9XhUDoigQ@#KoXmWMT;fyX;Ac2qRMtne~m@sxem@VrWqJubF{QOK36 zl_ehWTlH1TXf?&XVI^EZTxdLa2HKBiCC9;f^?G^xbulB%;WItFt~_g6Xy;nq=M?^P z-JcdXUc+`HArU2_VK#*YslBg?)_}dgN}eqs+j(nauoh@ElfYvP$M-acSAKuh%p8p~i;N`nI!k4td9Dl#?4ts8i#q()+K?-Oo_^3!*j|A09T>$TqGN`dS!@ z-<)mbWzos974t+%=n)6As>;D!Sr_>x`H@l1FN4}aiS$j3}5B>2a%%`7s79g; z6=glTQV-1xu$`Kca@RpjxM9f)0arMCeZ2-rr^+dlIf=DVwZE(vLGwbLy)F`VvlL-m+S+!wiS8dx1pM&O*^4yBW~l9jU{ooOY8yteif zM36=VE2N`2*Y2d6%{=l!1R$m|NF*dy-3M%uc+nA9PqTvsJxO1R-P#L;u7k8BWXoDv-c*AnrX z5B3MZV);%`-MjFuz=PDWxZy^h(#|MrysJk5>dQbd|N$HKv|N3kyH4S zQOEbbh>VnX>Dn;O0wEa3huIawpV2Xw;l1{6>q%mIb#O+QAQUb5YEBKob%oyZwq_#9 zX`3KRF#y5edJF@pAnWH;GloeQt$xUjLhVk3%d#H2wOj^oX z{5F+?E{OsPbJFz~a*$KaZaT%WR^Fx&4v*?&$iG}|L5^zkf3 zx-~mtTd)?g(Is|Y0ur}1c{|f+u2#U+KsKM~6$$$tH^E0Wjlt|KY{K|EB~ncx;An@4 z&_N|ERGB|943b9}SodobMoX|pvV;|LCYHL05;2&ze~C~#Wn+C&F)}_x`ZMxtbNcq%^;6d# z>3Id^AIEy)a&gWEMRuF)W0=tmwQq&bod6-*wS_nzLIN2IcpiR2(`2UO*GDukDTZnQ z*<6N$qvD^+GYEp*)puYCUZSYsB)D3GhK|uK*egSjpXV{)=8O+=JR$0$U`-MTo`_~M z#SHwVFwY8^12{n&{i{BX$^o>Q!K$lU^=z6`Nn745v5=9*J?L`4A+v$MR)%lRxeBom3Yu2*)6qq!N~aso5mH%b{K@W42CRP2^39u{!|qk<0bK|G9uf{-pIAppZf% zjL~ph4a2ixyw|!YIF&A#Wzc?L#maO*g26Wdf15g3Y*kOEDK_#J-Hi|ThS3NYS81Ow zO?$p)Em;oi-1fT7r{O^!mRJ-%;&M#<$hqw>vEdW-eHC2{A(_e3Ya8#$CjOb3VewR; zY~r`5YZ;|JE5WABuXIvX-4M*-pRY-O5tRbAFMe{k&!<_|P?vlgdgl2<{F9nTWd1W$ zA-!59v31?oT2(f|gRxsx9Xcnqi4!^kzE8;%xj3)m$(QO_GmaN3h~9 z({4AqZGG?*zIkm)P(keOeMji^wl z#{AH0C=wexjZMrpZwwyIQuGng<-${Mt=Ta}#enKiK*|h^$s8kcV=g2!!Jb1o>?FwyRb*rgv^bf9-kd` z9U%{EN11r;a27kbk=O8l$R&v_76JMZ_eVa}(rKtI!?G7hO{*H=8rU!`xdK|zj8VKV z(xQnE45tm$cX8KQ+!kAT00IN;8v)?`o#{m3j&Z|p&EUF6Ilb+a%DGA{Mf~2nJlfx3 z@LuXpaX>NnUr)@B2Ah@{R#&5gH~kG4&)TfM{*7~)4e`kAbK!X72*uuFG6saB#a0^c zg)ZFJ2KI2mSNCZ4m08sHW1Ud(^>qpSHW-NGphO5xHKxnFlGD^CwhB@Fq;8fermPn` ze2s)OX-4TK32ertgRQ~-kPKA#-5D3Q*YG=y`?D);mv?WzmdSeJ_G;ox6k_Z=8bake z?n5E=!4z!>47bWp-IFzcgV@NrJVsUU0K z8vyvUA@;gVuI5@TM#Og$_;)-SzYXNz={K_Soflisj9u$1rFYIP&QuMq4s1#*WMFYv zJxj2h7J{*DbU#g^?>f{Uvx{-C52BwAoC;t|^3!DZml|=rF z{kc3N5ZhFeF-QkG{mMA%%z)Hu2`@QJN#z-GbLl&*@TiS7Ryhzbp0k#`Y%b+-Z-%q@ zMW`|PiZJ|pp3#qLIt4g(!(!v4=x&w;BK>Pz(e#DbCKL~GY?FYrqQnF(^f0yV?uGB z!NGaT^X*xebO6apNJR?UJ{_o6jAkvfkya%32*^-t0K2g=(?*EWj zY5P3zBRN88Vphz2`Dt9c7R5*pd@=fEwNMb_JT|?iTb)}_2FwyO<-&m7u6un|=V=uS zuOHw^v_96tD_q2E$C0az^XP}kM?}W4{JUd6DrbE*b=q%);5O5?w=VPK@vt%q>9lY|4FyUmOR0D$5S-}MPL_M}9M%$IC!qeP)a!>>Vm;g^=rrKtL4oyQ2ky$hsxr-!*3)s~ zm_-D>BlF{q%hZ*Tc~i&d&u$k9ak@Bfz>6?~aV3%OBzMwK3N#~CDxbF;mtfm3XfMt6| zYoai>v3j-aT0Rb7-{46IZ8~iUWVFK{m{M5z06Et}4dcj}=XaX|wfDcf3sF);38T*m zD#dY$OEUJ?=!a!z4L`OXuVNZq~q5C!O$We_e*As2AjvGugaGvi;Wa zc=Nt<2yTJNl@`@b%`)d5c5l8O2Sly-fV`WLtcg+?BPgV_-zP`pp)j2jFDS8o?X1~m zHNgr(-P-7;fiLO3eP4M^8YGc#B3849GAnHhtA(5BO{^Pt1=h5EtjK~ke$qj)|Hj_? zz54aXOoJjE18l`5@0bI5=a^WVnKWIPF$A@CYJhL{=9ikk2b&|4WGDo;H^EYWj;{x9 zws)hK=!c^ym38}r10L*g5)JNW>e#IN^gYg=S~XIOmMl_ff7xHVC}gCgvh7F?>2ETz z&WH%P(D~(CHJxHhxqP==`zt|dJU}l)YhGi$o>dUdSeLIdVP_4!Z_z*i`OavRUDZN4 zTtj^_Zu-JM9(|0ks7E^*mWHg*7;zK!^!5qD^k*%xNONR0>F`MqfB?ZTY#y`4>R$E2 zNB@0$cM;1g*lpBnXsR%l;!-2iTJl%XzorAI@>lzIk|Ua(A%C<7@I1VRfv7=jSi2(@ftfl={zelK%-)#nPY# zoBM*Qv7=X0|Ft?}d}^|;f~A)Qq6?)+v=~k^8?3+f2O!S8+Um#eMaU)7lXy33$#gPo ziM0VU`)962E#vrq6A|)8QS(R!5QC$82ZDo#!B~jB=zzir{N{*kMP24!ZI8umjuixw-;oXtJ#6evjiHiXt>=Y2E?tk!?sTrO zo5-f4DENpiiVsZ;_fHB12+b>sW?Ae~p3%bhJkOIQP3!J%MWm7CJ}r* zyg~ZYc*;*^0t4Bd@9T(JCH8mh$TRLQnHDoL17n`Yb`4a?9dw1=oS*IZDYAIa%^y9R zV^#-q3S;MkO6YnaMaEeip|+8C8_8jXWyN`o-@s=y6F#~SQv6hn=vR~oi7Q^}jN{;; z@&XXi65!2>;ycU}cGaA`CX3;|^Q z7j3IfS${|Wv5u7Ekr8R*yx$uz#(7aOS|&O$=0FstMkL?Cv`MU_=g+C|A0Kjo3OgCh zX~Gf5FEU5ef}^nSR1N7oF)H+otTwG#7>X!lktqeBJ4Z{M3mfYoAU}ZUhs>XRPYGs0 zsYAGIA|Ht4H~+$FEtN<}j}`z#^$ zK)&Xf8v+l+C}6y^MC?l!*gvT0+Qqp!^P7+xp&m=`w?fYeAIf{uN!?xNt#57GOC&9s zY!-3r+Tm>aX^*@#FgefQ1(Y%@_}(2T5P!eaD@lYL%#bQhS3Me+%}|U}J5BBG&^0%B zn?R)d(b5+QelDnwmJ`GJQ+5#q5Qs?{TPHUtFUSLAjFXd-6;-1axvEZrK!KxZ$=1q^ z!b=9mlzS-PdHB&;Jv`;q#|4#5Ah0GI!vf==YVaaQbEOp!tlajUdWAMr_2Ur%Fo&Ip z1X;d$65Vut{FKJj0GR!?kU-$ba39Y8>!IJ81%J$GH^k^MrI|zvS3b&EW7C zJd7Vhk*lPz6g#?4b(|J`>$1!3yUYIHV1aK9Q)m@db)Yv0E6AhuUTf6<4ILmmKNln? zN#v%>0#jcC)wIWIlkr~*!Mivgir`!lUjpRH-ERmVp=i2{^$R`n((K% z)znT1cd8*zkWkxlk@@6Ymf1L1Az{4mmQZD(QiHm+N!z)#Me<8Io&xzC$a}=}u*Ny` z-^zfe*=;s@_8H8bemv;)D)E0K1Jc_?H!k8`%1uX80;je2BHD-;D#52F81#W#TPml? zYOw>F*ns6TOiyzIDJLz*Xp?C~!EP^kp3ABwp>3kGjAQq6iCvXNJ0)|gRrwg_Qnrth z{~Ha!Z`6Xy)GpdGwOY>CS2Lb+c@RnmhatW=}Y-5ioGrzaiRsC2mHpzW4m{;$`2`YYb5bHRVi_Ii1jB)~?b&0)b$zYaWc@(ycA z_1%zouawJ|6j`1Id%-EJxE{>T{6WY*Nd!;4^B|te=FWeFMe*LL4{U3 zNMjzhqz3!6m{x6;m7XWfD+SuA%DQQSjDvkT1=!O_1!RT{+0Li}N;iB7q&t+!b6U(=UScUc z|2?J5m)e9gO>nc7mwKBHJW8q6FHU=rWV4YZ-Os1$b+4Eh%f+83mGq=PCq8;ljl7=$USpffuau|bZU7Xj({u($98-C%#c7GoX3Q*v*a4^3#&QY#xW@Se{2x=~5hj!sZDpQ8<|D1mpe>B>ZAe9T%7y!rW z&xBdzZI4JA5i&EzF<;_SRYAk-qJwUf46e|a9q9cB2EhNV`8G}i5mMe=OWz@lU-#-U z+l}fa<9f7TK_I#0rLUXP3XRdh%e13}N_VX+{f$DYl*NK$8(#zfzp~})}_r}^KV0=})U?Rq4WXyytNnAjU z_BN)xvO`wKy?cw>nHHnKJk~Y$5Fc6LdeKy2cH~+uRo`nBzlkkZtglURN)Bt*Kgm&5 zEccsX68+@eHHqJ&AVpV+9L{(EeD}(-$Pzb4V_P>eg!(|G2(9Yn;!F0OfxX`LMH`X`5@D4ti`mO*!ZG2!Zx#$<+A=i2eRGrns7Dyg+JU z4QMtcBV=cjH--sQ#Nw&G3GC?+x|(xpxdCBHJKzqSGh;zK>MeSz4|1>Dz`bV|sF$9m z^wECAJ{xwk=n8j&p?GYqwo0e30pOb4479KIu1&ee_(z8SKET+)@pVarQ0E!woj@$x z$$TUjme3l%=Jd|3-|Qx*VidwUowfYm_`Ln^D02z|em$tr0n&OSF>=9_4L0jneUHQY z==zy!6dcv(BkK4<$TkI(TD4WUQlUEtxx zV~hEX4P69}{rkDP5KR$9C4`u@v+gr##o|F^*`(C_Y=J;cp1=b63^=n?&qbZ=qt%)k z^71>P94Vu?Y6nti|FV+>XZIwr=k+zeVzx90Q7)%N>T3(X8h6y;slKt&R`P73f*(| z&4Y2Sz$2wMI3gE{aT{%iJMIr|Rj*#uDamv`fb2c+Djj^P# z#G*#-p4ajYnBXS`BH{)&zvS#PA$*)*$8H!^p4Di2^Pw_hH)|Qb)(hj(daHi+(=4FoM>%yE&O5+e~g+? zRiqC%5dX9LR87fuUb4xvd`UZa`D$LvyY5egKVG96`1r2KzOLN)ae-kWStDAnRlJ)g zkr>-eG&(Jr)Smq=tfv^%Gfk~oPkwTdQYAOei<_^%hnD2_$K0w}{z`k9%2vo{(zgl< z*CZdWPJu6%CRI(0K`KWvRrj8j$EubfpEfuc(43KvXyafgF7=J8KY;izDVS?4Xcj!C zx@|ZUvs2IbSb1mR-Yp_hs$Dg!Ow9J%14qbsWpP#{OdsS2$&h%UPkzL$soo)tTCUAb zb_1wodc|nJOLtg^u$zKwEzx$yW41n?KPMhs?`WgwxYyk0v~z8!{$+WeH9ZQpiDNr$ z820Nv)x^u~i@6|8{02v5%Bnz{L?zlVhFK(ac&PCUjiSs_8>*0y=xj>g) z@V~$t6t*gq%pFMdUMzwbOc!#;P86a0-x5w3_yx1_B~2S}9E|&wqu;6*wF7@I?HgBu zhd;O!dKma{<8)^nRPZJ1C?#(Mxv2qR2V(uqIBVxyS$Q`2h9aZm?brBiw&~gV(#FGE zP|Cygt+V2|p$t1@hQ}>?##S<;MDQ{-Y zsF?4+bI<15swoC=`=A(_2)X{GIElQeb+`R~iaZi{vNB#gReOPz=@?@0km~JlI!ZIA?WdWHi>PLTrO^$yFtegg+x5 zR3^1&aMNdaS~hxt>tx$@^rt}K%af;dLhWHUF@`bhr9Yq$kQI$5gbR7^NIXGT;Qi*EK(qkiYVjT7sU!dCOm~r=x2G$)N=neeApX6O6M1mM+s}05TL%z(2GiJ#jAtMT&R` z@+Dp-zbn#XQw+Z%2!P(w057~Q3bu_f{CXI;wXzR-?d6}ib=XW5zkW9%I=} zhD;XB|C4GR$p}v~zBMyVp;oF-U34Y$Ce?adeK7?;Xcw2KzgAX+(3{aB{k8Nxq z_3DI_DNiaKsW=gqB3ICJ&=p_ynQ8C=q_Y(^xW~PzFnQLS^}HyTc-2<0%A)2V`EJ(U zlKvZijAXm_d*eg{H zPjg{$plst!#9}2W z1LG4OxrRtN=l$v4l;AM7&AKZaGuP09!|t2m&iAUn=XT$ZHYa}^f?;g)a%wF&Fx>di zHF-0SxV8l2&+}X6#}S`P`02jbF6ah#BjIeRw;2>FfgFG7m*Ly~uoDtm#o;@MGtqY4 z&D?hz3+#?*4@EJiO(vF5_&lM$u|_;!>(w<8b9k)qRTPLCX;U;2h`rn>43H9luRB@w z1*fd1uLOL`;gPRiyQ6m{iIP~uSEb)xhmHc%jnTWH{xvU8NI0{h--4b%I>Fl*U0wow zf4CB|PjoWGr&jZ-LLaQ6$;Qld>OMbSE39^7eL#|JOF)cf+~SsaCoIMH_;q?j|M~D6 z;3A6EPr61S93<%z!BtMfZlXaJ7suZ|Hjvs4wHIO3Tgm3zflmwx1CuCoi`l%>;`?#l zLB#mxB;u6u-beJhXw<1jXX4OL&(Nh2Lc4$_aoHCzjNBQX69g!eno?=H-`)A7Ir8&gb!5^-jpcF&p-ZR1O#zx>&VObWkqrvo5TRoc~NCyc17bkUTga zUs0bo_0%QQr&*!u!$$sdiPZ~tunw=JO-ofky8^%;G3d%X6{!9DWAR5~7unAt)$m=^ ztNW}v6gl9zVEgANE_Ysu6@ifZ9&D{$fhlB%={N7;Q+Oy@O6cn?0h95ZOz~(d+kFi z-kA5A;In<&Ir<4q^m)%aVP{-{j<>G@l_YgYdq{Jx3TXZYK%j}k zh8ASZiu?7ic$w}&;7ySZo!H}zbU}_XwOfW4@2U2V-tqJ${z&-ZM4k%6tVA36Okm8d z7RJ(wS4-3<^DL0KLUdlZruw{T^={a#<*42F(3ZkJG;;L!1JAvo^}5_x{xm3|*Pb>rXfDeL7R|l;z9}f7)0u{E84vRY#nBj3BP~&C8a@yfERg zBN`VN+LAGs#Lf`hCyO`-P~9 zQodW{p7Id&_y-d@rs2rA@>fP_Ytprx@FTsDLtPBc*xasWBYR#*xK`Go-*8x^0?(op zy~L!5H5ixA7-#EFV(mHU3$r);5iFi%`MfB`WK?}*mT|oXl=1iT@t>j%Yw>mpUfKH3 zBw&V^*)w9Qz!COOhlHH|;sin`7RtJaoIAOvGB2$cf%E~1PY=|gt3iVqv4Qi_f6S0g z^Q+fA1HO+pMP4v7VCyLT>wHlMKwuf^{>|*$uf*Gb(1ES-x9RgLb`Cy)+&1Kez85Ks zH-+4M{oy%tp*QfPw}Dur#<}DPeyN zMtOUnkj4K!i8e8t6rPch@Pu|;^O*oC6V0w8^O=NdprHq)_0)hb% z<}D;?s@y0F;aCAP_&r8eb3;9Mq`d*KK<`6=Y3-2V)dDKhXj;hw_S@W(5y)_=5N^6Yu3HsS9&^+e1-ev(_#fHFznH>vBoHpKq;S_Os2FG~tdIKg$6?8{ zdrw(UV?<7ex$#}MPwq%ln@n4WWfV($6<}0KxgO(|i z&bsKIgiJokiM3gk674mWWM(}7KfL{AP+U#h28sfK;F93MAy{w-?(XicLvVt-gdoA) z-QC?S*x&?rcX#J3p7*QT=lA}xt5P);Y}T6Y)qVGU*{98CWTM1}kBN9?5>-n&A=IY0 z&1fH~>G@(My97+a3?LJXKKlr3{K5HsuIS>DdJ;a)vVin!TN1AFxRcvS(wzbTTaZH^HifV4zH;|B)%x*OY(X8^#h|r0Nun(Iz)^fP%jl60 zKvkNxXC=kE!+yR_!VuZ(E(9mUuI@}shn~#E@C6%5(l=3f8#rL6F)%2J{e3pTGVa&@ z%UwEn_7=aC2hi8iYp|b_jc&;@NS|U(1uYU`enHvQ{AouXyhuvxy(5A`aAVsb5iI)i zn&-mX^e;aGa_Q$5*)oif4LjQVZA#}^ive!s=)kDgxKbsarKEj&{#dNq1Ob-6(_cGyNT zNs(A>ys6=ouVbT^UNn-0=KliRLb4Q>e}(6Y@b5frj_Hvxh@dy`mz!u+#e>bR^%<2KSoO89&@rewC+R z(X>8r6Qi$;=3nZcS6Dc#_>K=yrC*;- zBp!Y%Q0xNfF9Q4{0aU^x4FY*Ee!d|$cFA;ZZ$BQht^NHAg6F||+yC3Su$r)j+Wf-6L~dX1~= zb6%ETD|%7$6N_``*^Aky;pA4vg%~2-MhVT>oxeu~o3m)xEY{jBV$p&Rg=~8o%_@4m z`u*ng0d5i2m=L90Fk`9BAO{x1MqG2MJtJZbMl4Rqwo_0lG`61lxrb+_nHK6=V;%LJ zg=fkGw`=WVR7O9NwRDwvuZ%ar*inB~Q^@yVI&o`OiH#aq?c+uO5`X`UpM{VRBcWl3 zkrhAwVxBU^E3FugF1YdC_*4oavmxGht}*zsDd?e0)yth|<}SZHMpZ#G`E~Qp5w7{; zYDu|i*o7k#n-iQH{z1n(uJJ6I7w%e39-Wxn%4n>KPtJkHVp3~^zu=LIWE;l-J3Ub2 zD^>TvxB8VLy?$myDs_tt?#m`M`ulGN%sTA>M?{FtA)I?a>8myNH>}xH98?%(+iNaT zli!M#wJr4LGwAd)CeR;!|6tZ8|H1;~$xo*JR)00HKpWeyWy2Wu$JUnvuH~+%(7Dpp zQp_1LRe~)H?+~1iq2rBcGnyJ2_it)4Hq9JZQtE_bUb&4pCe5y8tkSM>CcFk_LZ%pRAvLy&h$J?XIF$z8zuPtr74bJ*2v=GHmSOeCGgESa zEcAlQk>GV!D9hiRke^s`fdeDwZOASPV{oy)AzMyA7UKwnakrMkvMQ-j4yCffe&Saw zTCA$)F8h)+Gl>2-i`}H-x|g7BKO4m(+mV7V5whmBxfTv`KC+|rK7~u0gB7T3^ zzw-v7Z1imsaY8jlUhhHb^0K5FQt;R}?($;}{&g$W2HgsR|3Ek1Z`2+t3%t*KrPD@u zCA5+Y>|j1sX9bk{r~%)^2UG9CU^TVr-`3+)+Wn{;KGCPaSkQulSeHX2gU%(?p<9$! zdtP4$t%?UhXKJ@FbJTFn$#9@IOusDRbCqrdUE?xZ(*11zh5s1TtTkB%HbTk)7+!4o0v{%F40GT&zzp{QR& zOy_~D+vBclI+{dS7Ow`ZiEDmGAChFMsI2zm#CIq^L3gYFL0t9e*`oyM!7!C*)Sx+) zs0V&gp%nyRnp`DO1O?Y%O?Mu~ciWy# zgiv5n(a_^oMl(NwHzh&((W~uA1ZAqTk_#_jvDi~qyj*|W{%qbTU^^6jNCrk2;q&C0 z@G_h;{EdISyStLj4YTNe#q3Pcy9PtHFYE$LE#(UUEE!4+I#Ybu3`v>bc&a=Rt-x5s zO{=Mpm+P09_PV=!fWCP^gcWH%rWQk-EaY23>5Ch^&v)FNId|3j7t8k44O~IC@(%`e z-ijerFLP=755K%JR%t~n%Vp_1Ly7jsbMSiL8}C6a!Ag!@e9ZUbz!pbw6%ZKva}Io2 z=N#oE0OOg>WS~2KpK-4-S=fXr29%uB&3d>k#de~ygSv{HJC!u36N3j!W-qU?8OO7c z;E!Ba9Kgm4^%Wd){#*D*?L7%^M$*7cG@;Ie*gu!^I$nWQw%H6uMKtV>$#JD zx+GfpQXLG0ytj&ja1K5c0_zj!jynSAlM|v(|A%p6d!EoK%v_1H%Q_gQ7co~&Q%Edl zmy13A_#3skP!kwnr2-;0-$WKKVrz!Guij-qXJ@vOs$?M(+p4f;^V`UEdq7{NViK9F z#)a%~C5QP$nos&eryHfvt6N2AR&}bAR;P{lr`fpivCzP8s}5ul~NE4 zSfr%ZEdwj$Na#eE3bEf?taavY99#(?IfaAA(rdo{8~m+ggM|AUzdvUjO2Az1%JlEW>?VuQRMcw6v){KziL&Kv*sk-tiy zc2iZEcTnC#7|VZwcB_slZU1)-QENncHb5E8 zuEky^!n$&<44lq(Hve+F^syzsn7&~5j6Rk-uR&vB|pHOIVA?DGaL4SGxx1p3L8+_)3!a#TyC>39?#{YG?TG& zv)R<8s8jp?C+eL(FO{R;U6vHxw`M=40Oy8juRZMHx`r^ki5|+Q1Y}gCjfwi_Z>VU^ zM9@ywy=Nq*5x^%?OM7h4c=h9l0WA)X<6c~T)LkqB@qMJS*q`u*L&N;m=eqxtvJ46$ z?djzcg{qi`T9ve391h&&x5Td+C-!}2Ju7r(1JVD!-#@9EL}=MR*mJG$8V1a!2Um<< zk|Vb0(l7cpIF{{^cl-dmnbaoS+GVJx{q z_l71b*Fs+!PcKAp6juOXP`QYS728eyz1p`|HC|eHlWLR(MA}bP7OtxkC-Xh>t+Rf^ ziN*2VqIRJ2`6SN)A78p3n){977yy-+|f@)H?fy^8yM? zDt!sKm+Hr?e?p|gm^a!VbpOyjdd&!yhntlmYCRT7!b$or|0aB4!W=ofpw_;VV0A%t^%>}U$9B(d^IHMwP$K|1_fd{)VZXdQ8Ll2;4E4sALA&yZak zUa8Is9syXTw1_@22pw0&F{&p;xjFpEjqtwpd)2WF*0>iTTtgN{yt^PP8yY3175T>z zIsb6;Tz}0@0L((+&>+HvMvKUW;~$ZY&D8#n%RxR>Y*eZgqjoBrT^D+*n|SjLs}LZ+ zD+`lz@nxn;47(KGx7pD|pDD$^{7jUv&@2CXL(nOMSZTPsnNL$E6f9OZ1H)Q7kN^D3 zdq*Zpl}=YA6`3o`NmbVO9c41L;wc;b%GN4o<) z_mj%ey0fOfohDw%t(tkYN^^r{Ce$K z`QQiuUCgDCa=m^s!hLDD^j*RnTXm0H9x2P~WA?D$)Oy#@0ehdAwBEjyaECrfeQj2_ zc)G*cynGa!AkwQeDPT)QYC!~KsD>ykEL?XCJ-(u#ezn-1EiyZYc*l|6=Btx+S6?X? z>0DawHX|mpBt=$en+uTq%GFSf$HiC}-r53=y#^OH*9mVDfZErLYy@U=fkexvCGjS^ zO$Get{*0O<(Po1!yQ~IWKz(sj;O-?1&$JY3&XW0?b*B&ux*M0dV1%0#pROoNMEKQ{ zr0(fHSw`rDg*>98y^PC>sUZY@4CW0e2$Z1CM{x-po- zA1Ue)-dZ#@U4aL20NzJqrW`8^@op~Ly6)@A8pEnIvfgVVKt!>m5L7D?psJ4u%c_FH zEu>B`<}Hgn(d*2Ie7RM?E9ZgDdTrc^8=Z{Xm|J06>ka1)6~&QTZU;w6+pAzf;|g%) zd&HLy3E>v``XmIkL_+4DdGGKcmfbIlzTS({2oa}8&kV;buA}< z6If0KJ76D-v%(guJIvjgy7sHJ>@SunXX7|kDEEUj&-sv#6xA)ob3O-Tj;#(^wIv*kF}pYX zq$PSWN2UYRcs=)-M z4fRVs#gP5hg$wH(G_Dysu3+vH+f0jr^{*`M@`xLT-`bWte7CXrS07GXf7NjM{vbxL zgVpT0*`(M26*P|ac5~~+dHG*&Z=d>UxUkkV@q7Ju9?zkD5?IRv@q{|yw|BZ`hY5$; zi2R|1whH($n9h?_D3dex3H7Zhg)h0jcgJ0}G$9Z5)J#YeF>opm^ND2{eYqdtu;`wY z78>BEfIG=uMLII!%b3=3}j~5w!geTzZ9V`M;5EA`2?ueS~3IoXr*I zd6SylqY>G4w)CS7Hc37-P%+ABt-8c}EuK8ixwAjMiLqBgtIb2!a6BR_zW?sFGwhMO ze;2egr5rmu2{6QXO91VIFDD3HNVm+M9+_0t`k#^u?9?wu3*y6g3%6l zDW6gY8vPD5_qT}tI@2}yFH9?3L{vtNKw&6>XoJV@lSl#Pdvs}Su#)LCT`U_RD?Fwg z&2C#tQCHfmt#)ps`}m4iY{NHVxHnaw=W)>zbAvR)1z!AyR|MEzI!N5%jDkUP=*vU- zRvkW(*Yq;JO-wGa8Bwd525cZq`}G~COFW|~-%t2I<3=w(Yc?eS=RV;e)aS%T2TY{vxm&`ghI)e;0A4eVSf<^s=K;M=ShbnJO?e?3}JP6+suD$sa4`u7NQ z&9d`g$Yl5x61tM1uP~OmFdP`Kgq$}p6oemvXr99v35V>D{v%?Z+2L4Y+BGx~N#;Ld z9tTAd7pT2^o&eq_6Ym}$!qXZ?%@<1!@KDTa zwP717cFiyyk+H@g_v9U>en6Ol*3}v4b4BT!GQx@nooExhWF8IP+C4h~OCgyl*clJR z%~XONb=%^u6W8RW0Iw!Bc;-?&TPLeq<^Sd%>cX}ai76smh0@d%dZ4Spcz77ZN0Or~PyVw&NIHUMccu&Wv70JmF_6mIfsiU5#rXq}Szm7;|-oqh4q~ z<~TRfUzGE+ky+KF@x)K#-H-j=C&WOf3y}8@Xnw;=XiOsycam2N4Q5>eppT0Y{FLS{N{tQIAzKamegN>|f zE2gyK%L$)3L{}A+eojX}SgHw`1!@@h`GEjJENjlOVz$WYC1)ztR0BqH2}=uY8o$-# z2GLYbbJl*Vn^pAdW!s~Ab#6uH1B7>BL%X--2loOGT?=IvKcfMz~3NtTT20##$vhg=az^~b^NN-tSHxQBsv8l2bCU_5NplkepD;DwW6)t z%d^yxqlB%RR@j4^x@kv#A@%&+=cu0#q!zDGApUB`kdfVn&Fl}xizw7bm4D~)v5#E7 zulz^^mjlxh;N`-~_n{12y*uLgl<`Wq)D@NG!`LUVQ4ybhnJGw3Rmsy=Czx0~^q*;~ z%ux7yDDBAZx6NXHJ%a31e=V07U*rn-I*g9s^EqWKc5sWMhv)t{P367x`_5b34TgWwCRgGa$5EfqlBTU}E7-kuG;BO6YmbObmrb)zSvm!TeN{O(6F zlSB1x4C&CV6Gu1bq+ODib|L>qgxdJ8Er>yOXu1}^*GUGY=g1u9fC-$n+!}L~w}K`V z9?weN{=~-JJtBpquOa5%^jTeJxN^QT{{L1HpZniwNHv7q?24hXx6@8ebxbB169D(- zP^B>}L2YP(_?fbGZnlM=srDcGL_yW_LmgX7btK;gsYef^v&CI??ehxeqxpdzmj{!> z9J#4MMs4s&WEA1~;X;A`w>+@$Jkn1A_*AF|r#;Xjc@Qi;FW|-@y^ESe;x4~*IK8Xu zAsBe^2QC4T?_e%2;Y6-r6xIoqn8IrL@qtu}qYRNw8EUj3^l^t66NIgyV>o+yl2@o| zf5R<^217~!BS<-`X9rv!rA=&fH^_&RYw2NGs=hSEVoeO7MCJZ?w{UpB9(~# z$dc&0F^AAqfI^}>=%BUF!Vv|`k^s>hOWsrd?c z9N)`+>S)c1Ci+FCu{^hFKK_3(*SLv~nNGhvzn93Pmsyth|cvP}y}ui{fjYJ%>(FMlidBaV}#Pe08^rW8B{0R4F&ajIH&!Dmd()etQ9 zEr~z#@#>m3esv#U5U<`EU+-EY7kd$SOwIsYak{8)Mj7o_<5-d4SB;lwY$cyyV!;q7J z+v}INJ8=p)xnD6}1<;?}5VX8L_R-ab?(HDeZS+%M?$>e#)5oT_F0x}A%|z&mkDIMH z&drV|MI*=)Kppbk9l1-{WvF&V0Lm=0`)%aKThmDW#zzqA8Tz3^*DORDaQuSYmozjMNIok|a}HGnWqAUosH!bte(VgVus3}nB>I`d^|du(2MIcl?TE6&nO zRFWgLJ!h{lZjcJyj+2&Z>VIjJURs5yp0iOUg}LFF zvd2i$P)zRe?@DbnE2RG#t!B|(H8u_SA*8hKB%Kg>6pX)>@ypbMOKvicgx*CB0o)P# zvWurh6~tQ~K=*=7vrZaV!#%M`{l(c!=jQB<2g2?R&|#{>7Js4*+lb~f?{?JwH+;V* z_Zhgno;zJNuguaVTl4y+ORQtPhj4+U^_kBuy{#C!EILPk$LGwx=F&mr%xTb~Kzh*= zKv!}E+FHyz}JfkWrsftVkDl%Gs@Z?hx4QkPu2 zKelqN=A?wkY5sOTeHqc-%YVl|xRm~tkgw2tZeN#Q52XB#1BULs zXZ6vyb>pA~;ZP{O2+vwznFiZHzrf@o>94j|v(1{MwLT!I(3ge*^#!wF7ys0tlEwe* z#R~Qb7J}JNBq^tElfcQ(Xhhlgbs2b9R2bj6(M27(7>{fMp81np`7z)!$fDcO5-GF7 ztsklOK6kF{beP2q@Q6G~Lr~lk(J0a_YBR`Gd?~3>;WIU^{TbXIZLn|$ljW=XWUYI{Pm@ zjeK#?6M7w~_{d2f(6dbUU$wK%}OH^(Ut#qe}|y>Jf6vMn?hSUM}_pm){p zL=}tLvnKp{ZgD%~q_F9VMirommM4>dHbp^)K5e~>M1;KpA=v9tJ!nJxd=I~mq}PSk{3IQ$ z%>O_^@>?f=9F$$Q0zNhT6&R<&ALGP)bpifz{xm>sdGR+;S?qL9ea4pRfgY$=@Pd_h z@fhU}Bs-e9O*U?~rcZvmVer?nzHrqc_l+*)!$9!bjXe;%gf%|8Y#BD<{r` zW$}3Wny|RXwG(QdseZ<3NIl4Rwx)BmdBSg)oN&DYY20?>eZT+Qlp<;HaB5aG_2pqFsdSQAZ~fYx>gO5H)F!RtDU#v~bA5(@(ML^K@Rb8(Tgx9^p!Xv0AP8##pD z9CX$|cgB^JvKT~i*iP9eN6ITuG)14Q|Qnq745VnBR{bXiR()B@zC$pDN{N>~2 zS$gj~8?kHj`G-2qhCB|W@Fx_=9P^bUrbQeYSok_#s10_)ZDvKbLjheIgqlpW;G>)may6N`zzu(@=(XYaIhy+^NHwvCMybM1p+Ky@_R?L7aw>O50_>8*V* zL2Z}zw*R4z`6_5_j$%^Ry2RW(p(|T?uef)xd9h6TTxi@~r8w?XvR6jh^J7wgTkk$h z3UO~<283iltILzD>ITq-=p{F*WqHj@?3iX%AUh*m)(-vcd6-KB2IMk@Npjzq@ zF8Jg$6#xYDdA#Kvzt;{eO>3Z0!3%oQrk%LN)uiXSqzn5SP7R^)B@$1Yg7wP)HLXKn z6rN;|e0rm4nxq*5jruU4Zk%?`L{AT%|gB@%PBtk0|=)d~|K2 zm@M^8@$o6;x7-neQC1IZ3?I`6@M~1cRl+}E6Bnq}K!7hJKTlw(61v?J$PYw35KfdQ!i_(KI&kO4?)=Z3R?>XU`;X+Y| zY@Jgza)T%?Rq4guyKdEnxCrv)CSiz|s z$!3|rG1vV-0l8jgsQOuzEF<%rFfVM{017Ja>HP}?D2a?MsdZ#V#q zY4Ga|lg!(xuw=HHd2)64#lq`8sqQ+3*)M}|5)EDZt%844H%#reg;y8N9lAEvz6qfS z_QySBygWOy2x}6k(-=>@%1hsw2mV^FR#e?zd<2=B?WHVsIsMR)lrOA*lAD5kvnjlf zf1(@EX*R%aoY7Z2wfoQ|VClG~+27q2HgZZdT9^?|GvUBKov-MXGPU2~4mf>FIg(uR z@(9h4hM3hdF_~@g-SfTJRFyCN21Ryl|eM0Dwe}dxfSsMe*Jh-H)_fHD12Lc82@k(3q;tD|lM#ncfswZRH_%#&9HR$uh6(bgPzw5W9 z(@tnC8#^r0f&JaE4f`!wC?6c3xtJs7Mnjy+ACB!`phnPS`nk3qRwZ@RzBaN%AAN_; z=Qi#(YHlBk`J_#kI<$1dbaLcs^CW?K2e7XaN`K9pkF#4fI(!mR!R$u~bb9`ANcHs>MU}xH;n{jU zO*(p9e;g$tk``WjCmRk|snC@M{)aT~8^WE`-D-S$xv(8P53jAzcT?D-Mz)E~O5TTI zEo+&yXy4bTJ`YwFU%pP>5@s*YAIfyAsn&_~2gwNiyHiI8PPZS!OdK&gQ>gJM?LO*EM*epX@2k2NAhVEhJ(7+(Gee_4FQ6db%yrhlk}Rgwcj zNp_Ls)2v+m zqKF_nNdF?dmyEapt*0lP5o^^KuZ#GGGR6WEeHhi?mSk#9h7vn^ilk}8=&v;K_sYU9 zkuw))BlRxJM&D~YnG^_*ojch&M|I}*xmKojM`N!?yCFWUwkwVkem6Np5a6{d7*g>` z@WY}?KGegd`PN=RMg0|;5yFf>1z96h_iw(3O3AylZZcmR7yqjHqdwc}(P3wmtp*%U zF_Obm<+-V^%{vd<9VRqfVohk|!4&eb8%|Oi<4kONWJ@hZ1aao3mC&$4PK=FYeW5Sd0Qbp4?kX0JJ|^;^m@A6->))9Pf`zYxNQ}u@ zto+UOH^#iu_epzysSa`Qo%s(Gk1B6vg-u51efd(uTYo@ zzN)jZMQDHAGfiosANnSy%az#7gQ_FX;ey7AyILWZN9i6k?-LX-WzIjV8wRs}^-O5h z)m#9*VA?zbqcSM?9hoVZx%an4Sn8$8ZjND8pWJa&XW5d0w-crG^MPRmsazzs+K={}g^3me0lIHyr)G1Bl zsX%~~Vd~zMo+2By6tFT3OQJle#n^8p{0rK}WUFZkLh}fN`MhduHE-528*yLNVgIZU z5QIw>fZ0Ox$!JHEd~hsgUBZmxGc_7g$05`o<7yLEuO8W)k)qtl-;c}Y!U!P3TFkzi z4ajVAP*{NWkdQU`*^`0&=?+V5*O7S47L#5e`-EyLnd|`nGVBwB2@CTR^OJ!3mzHT8 zO0Q>m=jwQd{Uhoh&{zQm?%})yu~bLRRFywD!<&~4aQ0t$L;sZ_)vWY^JTqY{^J@W@ z#6ph5&ff;^u>t(d?AK&xE&c+~wr`Y)cLkDBqdV?z;;WJ3!-!@pL4Z7m+0A!)?~S_EH-^C(dx<3FH29 zuntJcy`{J}dke4v+>aKPPa5THq+{AUeq<$XY^yz_)B zvHa1eb_o4cx6&F(o8vFk_WaQtP#Z?R58~UT_3DHWER3y}nPZIJ0e2UsZ2p}BN|&n7 zKmF`XaE^j)ER=Cs~E1*3^6LnCLal|$){ThVtVMd@FeFZU;W<%e@a|5Obk6SK32SCwqHR+<~%Om zO9~00e!WJ?zWWT<{w2jvLJ~rhmU!lNp$n{Ejn?NUCHYqmEyphe242=3eoD}Pg8S?B zXNk)d7Kb1iHf>X9_Jx)0my5KZ(bJK1Zjj3==iRac$7)5O97a`@LFK%bl0(M}5|il+ zO)POIKbfQ~w6-i^FVIHguvaqW~mY zYzCNciV0d6?U>`B2AP=W_F%gSHpJZ1I8L2nx)DBe6 zexgsare7T1dL46UqHD$tSX7&hHI?EzE{9u-X$ggTW6-`?iq2<27jHpKVPFiwFlHd7t2A|-S1 zE4?Osg}4w9+h1@xpdldEKQVe9e8(@#+&=8(3S=Mwzvp_r2ZjCrzW{&X{lEYB0)Ynl z@0RxLn?KzFQEvV}B zZzs2cK_Pz+MzdAYT>bhH&XSI{tNXGq@5234%iTZ!a_rk!&l3JHVMJdjRB5?SY)VO; zr(WJgnqRGItH^qkw(qDk_|RBC&8ohR_ondXztA4rc>-ZxXdt&Bxy$1AMo1Dro#dmLYjSobqv1D;01xP>|j#jY4)7 z>ZNf;^~2c8t1OVV9*t-QiW~&Qk^kf=2gl$n&prwk1QFSDWH?klKbafKZ&dx?-w=jhl-au+p}TNtCE{vkB(c-nHthb2xC3!VLMhV>HRTgy~d$h_7t)bI#-=DqS zgfxtmu2O;b6iH6(8lrN$HEvqKM1+M=IDQ!|)+d|v@8qYOcMmbGkjS}_95T^FmNsLx zAi$D}bS{_tkfNT&Kx8G?{v|&5V$GUqlXa``IbSHrDUlEc!jm9lc}lLsJAGP`o)a0> z(EfQ*J5AF7|91KL4roz+IR}?Vqh4Q14A>BxWcAf#mDA8O3X$eLy8Me)ou)a;f z-`~`Mv)0-yaeO|EX<%#`fl^exyjPalFP}_D`11;ot5RLDKncD<9rC8@XUks80&V?*(Dk=pcLvp&wf>UWF_!XR*f0@VU!i>dOgbwB>d3QEV$2X$O<) zpJIzw;xOxurdbbh)cgw8mPYnVMnRdse?Iy~_L|d6#cE-au_iW-{(60O91cz=8YqSU z9$L4Iy8tH#)4m`smE8S=_u^_-W9Bc%5A|1vC+e1?TviOs#$WV0?FWvOV>&H@ zz5Ht;FbEh~Ns!@GRlXblhP@*D&7r%@JL29P;Oo>l@F5_62xN60{hU1KQ2)YVx6xvB zY9OqH;MI9SCCXYUa3`jc%`k`0++smn%)}{fC-n=vNBB66s0^}L^YOtpgLj0Lmffw} z>4~Peo~1eG!az)C$0K3+Vti$scslVh0-r1jy|a+ z(=}3dS{!_S6fX^ld>U=zH?6&#tkw5jSn>N^3p9?mF&ngy1lt`i;mSxn5TT_E+qUTA zc_xu_G(B?Knztz!=2pr9E0PxGweESQOZsva_*z=@H@c-!ihrgx8eI)pB*NXpd;Bg3=Ll?zKhaf;bbx{ zwL%xzY4s3@Rf*v&`8mS;Aw(A%;ewAERArU7LDA5OHZo8tTf~Ni>fV`gl}N=ij2s#n z#&v<<&e1MEvxF*G34%>pnqwpS6BKofb@wFi$6?udMhf&{#MBb^9@$ zLWu^N*NuYo&drPd*C|_V`93XZypd^G!3U!MCh)^Mlt_MXG`CHYU>U23B|#x3!fr*sUHFU$S%O3UNq zth{}l&zNLRe=gc|`cu*qhtr~t&Rf=o&xCz{Sv!y}G)ks3_FmWw?>wb}f47^}|15b= z7(WGNwWEH3dNwl~mWoR`mA8Fsp4&?2^}6_ooYX8wy#YK)c3&2%TZW(ZKOV+v4JO-q zXCmN{mgW3*`Uc+Ni$C(BUV`k9)usL`p@-htGOzcEdbg9Dm6~}Veujj#Q}d79M4?pm zxU=eA6dGw_IoTWm?UEGnlQ}2t0$pD+8%dGha-$K)4g`cY;U@!>*GU^o+h2bUNicLK zGO?`qg%d0BXp&VbLSD`qh&m62srgc&i{&g3 z5l_s*;2v5ji1XJOlbjwRZH%6?um=xQ7GiNm1$zLHvq2e_8fUw2kk8P5= zd@F+PwZU-o)ljFzn7KF>ZJvgMu#n(=0p`LVv2?*9E0bX&ah)=sv)kIB&E!Lq3yQ5& z+ODXe8DYA6=7E`Q!qF|v{pO>3G1<_pT({wSv zLJgyW%ib`=?m#%U?V1iN8BPw>@gXwblDy+yi+eMWEokt~ZP2bZ)>YuBycP7Wm0F~hx{8HpURA60m2*--Rq9XTKQc%cJ`npV&eiWB&f&R)^j}mKt zL(%@-hmyQ~W_aQ<4Yu5)eQG+-zAE~@KEVb96r1<3GvQ{KJ-}pE8N;RHZ{F7d=@9`Q zo?*+?v@=tCsaM!$GM?~`(e$QA-;>7!Fc%BcrRC> z`7Mr@_bPVoXHxl7Pkm}!ihC>=i@~f(k+8x

r}N5)7cv>a>Bp3@c5djZHzYCA8*@+Zo<#) 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 K#C^Mid~KgifC7 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

mWnCT_8{Z7=!0P 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

_vwu&e-p0_Yiddlm_ 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

TUTam2Z(?YUt4 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 ZsBZR$nRkMC!(Mfb`zL^rc1r*N literal 474238 zcmce-WmsI#vgl0`0tA8whrr+tgS)%CI}Gmb7BpCJm*DR1E`z%T2n3hlZtw8ld!KvG zea>?~zI^Ff&1$Qzma6)#a0NMWM0i|yC@3gINeK}pD5&>(P*CV$a4?V@gHz)PNP^=m zs^P3`XX@-`=m>%mG_f-R5lPw@nt_x+h9({kBOo3qs1HFFDjLojvNBx8b~f~eZ|~5% z+t@=&LqYNIyW1NYTY;R3j6h}a4Pivi8Cta|;PiN073ooQkoh zl`*FYF+U#>k2@En0vnLCA(6X{wXGAEJ1_A+^>RUezhyHJ6aDjwvlTD#zdEHMt3V`d z=LjNVrDvlv1_FUZ?40yKRt{z+R$3w^Mj$H#BPRopk&Y3_1!Ux6VkG+aA2FmgM-x*n zB@wZIw*`6PB{p|Wolw<0^(o<(Q&eIGSM-zvM|$eFtM@Gv2Yj}axj}R z85sjj{!`EYR$hovlvNNY#3TX~g3N{}n;;7diztT>GaIK6Bdee&^MA@p+B!KK+8TrY z)3ybq?SGdA{y)od2|I!eo$VY|?Ch-nqXi1)cFuNA=63c(!ovT|IuWJ1g{_I5n-kUB zH2rJTA|OW#SCEOAqn!=WKXT@>_+R<}GGSq6H|8{?<1l44qyqt2Ky-%e?51=k%xrAN z#>Omc?52=0{Hwglf0N(8^c0c<8HfFUy2AxzHf9Ae8$a zh9Hn3lM$mS2QdSriwtk7^WRkIKUom{eEa!d3j^}-UrP&Q3t3N&kcBfff^-T6%ke`} zL{P-nk=n0Z)UoW#b>$tsclTy7-|E{;SckSITjdm~>jg56&PH=AA zcLp6FTLXengx~-lp{|C#(eBYvy- z-wEK0-aqa9&m^cf;;r%jBns}RZ%_X-`Tw;;`TkTR!YDY#A@os4H!=8&NffbXkA0`e zfczi7!~Pki1fU1Cs<$Y&Rt~&EV^vcAvvvhcO(hLn#aB!!u@0?81glYMmmhP3U_IbI z{Uc7a6fSV3x@$viL;_jJ65jy!&C$O5Yh>+5FgbO4jx_=@-M<7(+e+mnp{b8$G>S-> zS65S%D64!^UdzcdNBY&_h=kR2f97&NTRp*rD!0(L>{xDoJ=MwUCto0}h!F|Gtb{CBSfYmSq z_8lGTEc#Hgkd*Kh0*gW)E@?m%3D1>q>5g3%eJ6#oZ`z_NLQ3`6RC{hzp+Rd&oz|Em zJHo?DI)MXvc`@E@Zp4cyMJ@f?U=(G_y($6+(T(6I7CpV^)Y9WDZ0oNpSBbS?9%WLw zE`5^u?9qO$4sI@(G?tb69j5ulNB0moz~+x1nVI8xDC@F6(=^K9R|njc{gf8Om)D`> zFL+W(F}w6Z^VuLUE)`yGh1m{ZR(?b6Pp7L7w zQmr^JsnmD~2%(;?jqPiE`5&`Dn;EU;Wbp6g-rr@Uww(>CI<4~hDA;#YSrnq?)Ed(tvn#`Yim11IFEH76s(>$${qt3aUK|<5=d5$89_PHj z)*Vwa(r*aG#J!kFXO4t~wlYfNFOlu3A)lMrMxLvw@y7^~m#h(O5o$flZw^})> zGuq9HqqJ^I$%|?yz;o(s;ALhrgnR%QnzTe0H{N0EuKX`l%ge076SvDRaoBsn%iE7+ zmTIC3NWb3kIfc>tf6btf_=k_zepzU zI7AfR`NASpskV(>OVDO4?9<9$Ui|U-evfCC`i{aoj<7c5%hg>}-U<>FBe>++V&xz+ zoH@r~Z>xfaM>y1%y-*XJf@{SIa*u#RX2Zt@d)gu*PZCMjFY?PgAS}vhj-;X(h)gg# zC>+WSTEXLu6<%uSBKsOo1Ge%m85QA+mEAM^KEmi>Y*PZ{glbplQ;chDV z*=ML44V0omgM5m|S!vVkV0%dAwffX(*m~iqTsRJ_5fZ}3r0G6`W=B?eCxCYf+(Bmc zA%bkSRg}NMi}@nq&<9-kjph1jR5)#N&GhYJ-)d)`3tKt)w9F<*6v)$^%Lva*!(_~WovD#t7O(W!siOo2&U zo3hDbcr0^rj{KT?h~#JQA>WD@qWfz;kY998F+X+NaQjRA_Vvld&WD;U`+y#>ZA6Y< zy$An8&VwWRBqe|pTW20SEmX&*AS>DHmySAH6$hyo8zFkrqYhtvK)#AxoTTx>PNW*> zmv2YE>tpADa+Tc>Bg5DzYHxKoY&40hlCs zy-m~AT`X-X)Q(73mt%Eh-1<_Yh{EH9asEBs?gr1Ecba@&+4cK6%h!|(xg~9v^#dQ( zQ~1!7R5ohV=dzK&m^5A_y<5K(VhnoN!`j4=%Y6mC+ad-W>tljy3Xut9vfqv|n$L_j zzb#eH0{_mN47HNf`ZTnqMDEZ~j0}96F&SkD-F_T-8Cc0cZaj=Fm$oY=DTou!F10B` z9-X)rchS~Snz^cBtYnsXXL!#$(`6vZFUBT^y=u4qIBe~NS~cz@wsl;YnjzkRv#S02QfH+uU$JS<6`r2vEr&!+(L1NjIUwGQDBTo zR-ERkZDNBo6WL?=Yp7HI-ox?0^-PYcD8a`K#E7E5aWtnkq*3(cq(^?k&Z|S!**D*0 zk4n;!w}K6EKLwB*FkZwpopZf`m6CcajHg@EAsV+C2G+SSx6nr(Zy3g=&+!{Xk{hsbm z!qd|@UlX5pt>LoZ8fN_nS*DDBp2u-1rI%z!5E=o7kn_jf%4IiRuuy6{b;SHFLhiOD z$ers>7$;HL}O}u zu`3t~j^#idYkzYd-ggCbExqnokVEb%EkpA&&1!39lDk>)wXTX{-8Nt~+5(@}T*=f6 zvI6U1C0~B+I!0lnzr0ixp3OJcmV_UBRA)Fa{3zA%3(UVU@e2?HJI|7R4C3+&i&#`G zhr3|#T0$Q6?NYgEtxYA5QWp#mDBnoA@v#+2(bi+}IkJ3^f&*}#!C;Cg2e0Iq_BqZp z+mNN+-(Yfjv7OngSLx5kbB!yTJfx?C*5by(@D|PjzjJ*afT)+rOv;ll$b58$!A&|w z`|#j*c^iB1XS->pUOWp;l4h7~s(LGolYRXT-{tDj^_rV7+Vl?jstcBGoHit}F0p7U zugGMJU*Yt3&uhjn5pdT$SC0FOl=~&xv7n&@Ptx^ou3ZCRt(SZ4~mjgcLtft{{OfW7# zm6sGwh;tE@SML-56nsMbJH5w8UJ=eSPH9G?BUI3&hYjgNVWoUN39iwDH?utN+v?_M z2=vitQM2GYjiY9A>vipTV8pg}ef?dc>X}fwhQXTe`K^}8=2(o=m!ry*qy97>Us(uA zIl0rovgWipM5#&CW4Zn*$NN5eT#(>$GJ}hTUuJ_wx3Z$(c~U5!@w*8aW|sPc&xXj1 zZDhNwpH+Jjs8DNp;{xYioCe^NxMtg3QZP=+VXsueUMn-0 zx+oGhBwuvRN%~in`FtpXGXB{2(=bv6@KI`a=GXt#l*ROJRF=ye%Ulzntx^b(+f2Uh zyIPxRlt;wz_A~Zynu8zV@+JR$GXg@pb{#%wHu~$!S$!GAVvEJoHgZs2$5sC^&Q|!z z8DBve)3;MP8Wz)Pr;mg0%+CY(gOWGRLn@-*fHX;Ih?<*wI}A`rebiu1e?nhnTk&-q zVTF;TTLLy5b?~$9cSeMcgbLN0Dxy`@OLtzQe)KXpU}C6ZSqXRo{dJ_~S#cDOu1)SP zA_|y0A=`CEAsk*#_Kr*!_MOFz32hN=aAI~l`%?eM5G0yv#f-V~8{S3F{andi6r&RElf+Ll61IH2=b`L-j`6b#wdc9CeG4`G*#X zPwf53k4C==bC7PZeJoeo(ryq&mwcGEZ-@FEdcykYI_->lpwz7Cvl?mk;lU9J9DPOs z@}bz-uQvnzc;)DA$X_H)%eG#+szJ9e6Vin@2eSTfAk~BMcCTIy$nn$NYOq|z^h zmkTIFl>)VM*?nqnzuXWB_hSoLf!ag_tJ0FuF_hptw^_Q34oAhXCBy8g{}5Gn9Vwcu z8l`9z2reDr0{avkj@}&7@V?%7fS@tvm^MVM)m<(;zyhrbEZP&_6Rh*+c{2 zk-o<|lOD4kpETw~xQzP=wdL9^g$b{tBvWcYgKV@3jGw1aF``U*qw4z#%S>;dD&rMQ z>0AVMo$|;>d6em$m_gI*Q?fv8D_|HMk64MZGDEL%#C$|b(a9;cY%61TF`Agj25^_* z{j*SA6+u`-(YEdmwk_TfXArb#avN$wQD))#p>fbKDZpKf7S>5Vh zVP?;V&H%+OasnmL1njCe!Nz5PqEP15YG{G}Nv!I|4veI%ovz~TG!}GDaF-U%D}c$f z|HuBJt?fQR{pl*5%k_R3UfbS0!p;od;Sw}R*5Srq zhB?z_w3m&XUJTt&7>Z0AQEiUKt@gG;0H*wHk>^`}X?UlGxL5wmwjC|>8K0fn?UEPi z$7)G?*{)o#7MJ%z2_6}craE2uhD=(sPikce{>*a@vxO**I1k<9*exC{netSbBgnDB z49+LOiX|}e!fkG%>+*&k*x62(9xQF{Lu-aIEc+3DDo;#vl}UtGjr%21-lTc_^MOZS zsJ!{u)rVlY{`g1vE5MJ7G>k$*CJYY36ckpwb-vv#&6RaqxLl!N~K(;dLzIC;DXPo@5DGoU^^)mQ*SdPSx-B5Nt6b0r~lIaG2{<4YrW?N*XK30 z&=awQa5qY`KgPfl|NfOgh6*u)4~}5O(^pb`rZzs$s^be65o+4iRb4joS+85!fk#^^ zQeE$C&64-Z_qZ7E1W5&1sR{5hBo=+yd;Z$2#je+O4x(>8<1s44~b*fS` zr+U!kWT?q1wL0JB{vWrmr4#7PdBU%_j=L(2W4;?*!n{w@FuxM%wNdia1GZJpjmlreOy7Y1e(@?lau? zV=&?5FVNDVXKSaM9pWH-VJwJ*K5pBX+2R~Y2q)~Cci=m0m?c$yt*cF*J6bsGP^OQe zi|(7>?Mev|h1v+z82LU;CBwTCdkmYZSY@4j((k;BeYt^^QZyYug}X(k@w{QGlerk6+4>A2bd@?72oCb&IK3y>rU=^UV8U0%i~8(`1+3W5Za7d zX{5i`r`=te;WLs9<%p@o0q?A>mY zsk!SN0pG*stHpmQStB(wwE0fOU4!l2^i|o7re*X$c$Oh`zFXq}!4Pvr%2YnF{&5*%f$~^)mG|A@4M*tI60)-}LUu zFKpRQ*q_NObcsK%ws&o^sZ08)e%yC$Vz2oDJqlgudKOUWd5N|grk?LzUM^i6#W)Z` zRDAL{pMc0u;H+LdgRLpdqU?upwDUWf`WoLKAT&^Nt@{a}2> z092eH4~+}aN?{+%D3cDyX-rABu;!SYl4166MFxBZGsp84S+K=9==R+%g7@~ZZ^eUc zSF{Oo(aW_o^JPOtSa-d8^f!Jr10m>1cPpo_(=N*d*A4rD{vu(qrIzVsf9+_|vvp}G zq6CDqMnA^8O3;w~YOET^nHOGe3g2-jJT(w0ZmS(iFz`|T^hG^(cixp*=-02@Pn{`M zUSBqv?Fs9|+wRa05%=IZm|KJK?ls!gvUSaZQlQ}&47>J@=1$shnbv@4m=~H08m>Pk zpBn(UAko%rEbDh{nd*RGb;S>UaemF5a@dAK&0#C!O5R0XPlR_$Wc43h%B0J{cdyzf z>^4ZYGd_N+0u+OT!-~}wTng%+@U|tN9Dk8FJ#*VUV6PA4J@_-?noVvu5?J^XVWN8r z?XLDH0XUxNM3zdUaUPQ6((?PH?*>JL2_72>Z>tQ91w}O+T3`097eGzyKal5JTn2U8 zt_Hbgp0>bTW8y7RWDSgcQj1wlbF(Es2V?Z&Nvb#d7JmB4mbiTt`mtU9eqe4G4{gt( zGr|8sg@9QmTaRXeWzc3|oBcx<*09e5>cepMRG0`h^eptBJ=QU*q+_ZIs4YN3&dTql z^(cnZAgDa!Eyq{$1dMSuXm0Yw@K=LwoOa?o*dp9-8~8V2(xIjtLf@i&#Vntwv&!o{ zF$}IBK#5RgM{em6u%+p?qwp6UXv9B7u*~fa^)R|eHjwqx_&fna4xa-w0r+XU8F+FZ zP%rtP7rE}Yv#p#yw@{6$QWuCj5y79J;zP#;zY7|@J3B1{-45n?_J0O2-&k`Ns)KqJ zDwQo+PEDf7@1a9^b%K%+)V}TpMK+rYq?JF}b{((St2{a_C#d(Lm2q|XdPzqU2@5P~ zp4ucT6`&`kG&BzId14&pXLd?X;7J2DcPLw4SevL(7dY3s^B$o57*{{N0$u{e5R39! zPr7y(+WQ$VHH%TFaiULraJIzHmfqWh#CT+?AvBenHv;B>2PZ{H-BTzKw?3G;vQdeB zMDx^oUg(n%7_s>sNzi*C5|%bfJKE|8$o&cFdDdk1LU<*V`iuQm2*cc%TcbM;f(Loz zpV&W?k$2kIi3dE*YF`~T^EW?YfTnz+u2ufD`Dvz-CGi8X;qD(`YS0a`rphU-)YH3U@xb)j8!J_r`e^jW8@89KbL{~Z-`0lUDONJJJN&V z^fMcE5ebQx)yQIX+Tst|<|{9O2cu=BcIkJs2bs8%lE{xs?j#{uu91O;7#k2-*%|+d z`hok`$eFw^%-5QK<=8GX$sFtVCR8@Bbt9hX3%^V|NE7ZK=`8_q=v&GNLb3bK&#{zx z8&a6}P&fGpFW`&L9KDsI;Hjp1c8amOhlc_PDDoF8u1Q%d>RG9kI3>kP_#KHx z)7YE=`Nv%9-gO%`^ZT>xhWK$jWrvId@P<(Oq+QfDeTw%_iHM#%S?P-0GA%~eBx2yk z@-u#a7s1KHRykTrxP?X`a)Iht{wy*R z3iegGX@WcYYWi@Nd4T>YW|}Vq?}d`A*-?!USNtzu93GcptH+x71$UA(6yT;F6<2ud z#hA>_9U4!jr-7Y#%aBA$jC*|pB_AnVNi(()Koa!3)??g3XNVhmiIRVa%tY6e`pzQM z{f~3OAB&ivT?dEFDTGk-{MrLY8yf<0B8@|QJQ+?o#op}@@pNf3bd>8jD`23Cka#n{ z1B>%<6-XaFAwG&ldkbA?29#uKEdN+f_~>(Hp4AxA<81d_?6D5 z8S48FokkJ~QCv+G6HVh=#O-2fOC;XaZZAf`G5*NEwt+_tuWB*rht!51YL9OBBo&IB zIPTeGt$e<&ve60y#T1Szy#PW%2MpPW<=Z1s67p<(X6FNUGM$@H&1j#WE-E+jpxdCO z7vwm+tSyt~DE5+wEa$6W_kOrC#jlOofWKQeAD!O&$UZ&F@)8)Zn7d45m=J_&=4;fg0EM9_98MeHsU$vg^`^Ot0-kCD>(uS_wkfRGAVrZgWxG9-|(t$|o z^ST-V&IaPYLL1)1n^m7jvCbUtkA0LNRy-0NDm+IL$xH{so?999o~{zv_RH{ISZmTA z;R)n)7ZO3fHD1964j&JoX$*K=pQdXl-pz9!x>)&0+Qsu9!xfUkK3CT8-JYHF`Yyiw zw3q;j4t@x&Qnv&?`Wgldk%Hvjp(EK**Ac9sI&Os!t-3lzIs&-6H%Rac1Xn3iJ0YRs zVD&G}ljkA?D3SI=70CD#K+rzsos`ehu~sH2?!>{%%;DV!mmK=J13Qq3zhb~6F$Yq! zq>WSOyP;c1@M*zU)>R@*z+m2}>F97fyz66EGvu5|lwyth_BWzE1;wUVntOHcqm7oz z9F}BBKAIyqmhDsQ9ia7CH8bFA7rNB;>*v$^kR8gwr{yOCHb_L))i5c5q5C8*-Rq0| z{rIzWsE3CPa4X-y8Ih)?wzou~0VD5&TgvOjNY-0$X`smQ*HUQP^34#ASN#X~)zLDq z(htgJmwf9#g~gji_rg`!&C2neN9^@Cw^56~yLoRs30}9TIDX3fN`XDx5axT+($R?- zMU^OJ;l~#F7Z54J$ha25rI1Xx4z!`6zQQMZn&9GgH1AD)SsPNMYvqMfB7ksT>8lGo&Z=F%wmSIQi!75h3$i;lp5cSS&(6Xzf%6cw(J4No>K77Mg&FpV2PZPV% zFI^;Fb`mCe?$b~-m(EGwKy^1IH-#gG*~o{Ayd2|xkJGNaXot|@-874|6@MUSSkcZN zgUt_`Q^{l&vIU|>g@xOA*M|jF9S_ZN^Ygr+&$E8w=p-_7WxqRAn0xgZWb*9U%cq6 zAC&B>i_^~zq1TKdolIUtZSyx^`*jVLoGz*w4NyNu)WVWbB9WM5rNNSIz{1J^v%+(% z!`NiheWTeflVc$ZMzxwf^!aetKgTP~a)W%z6-6YVm-q`Yif%`gKsY%i^62%3TW8Dm zDDRt>vjKpq&RAYDFop150ke=KmS+|D7DHg8_Z`XiqkfSpagk@+#l`7&3YoLr;!L&q zJ{xJCJGq%^pL$f=kV-1V+a}WNZ%}ma?zRLiJQMRj%mJHH{06cZdyn|8dA*c5AFz&)4S^S`7CeLfp6P1`O%e^};!DzRI zbno$(FH@k+cl5%ufIP5_*y7IYRWDmS)JQ*JlVn|SXxZpxtrxt!IR4ErKfDm20^FL{ zhunmWa-LBPQyEekJ1SRN6S_izP#7RCbBOy3a4oW~-r+4*-Yi%H{UrDG2i$w%R%jAA z3)3%x->%rlxeBFj(+?kXd-j5_5NN>B4dTwJd@^dTc98^^O$j|CTCha@)ct%-^NS@> zj_+4X`I$G?sl&s`>hF3}u+*I8JbiVuVu7S+UG4^HGJZ6Zfo)`k(N6EYvwz3T3;PU( z6rZjH!GU|-h_q(w!nW6hmrJpqCeVc_+b2GqeONM1Dp4=yDocAkDxt6O0b!(m5 z{I#YO`v@qmu7)aOrQq$-qd;*B^r=2YidWDnx2ThNj@vr;xtqY1WdDOO?^yHN^SkG1 zO7;nSg={Gz)!}5kpYe3CKejnjbxn$zwh4(tmT_xZ-%Q-OQK?iPk-${c&MZH(r?#+67zOZ zVAx2#>}hlb_fo;|>89xMn33d`{o%k0lrC2hNZG|x5RnyJ3;X=}{Fcsd>kaX#8NoNc z?#FEqpsk2DDxmuWdv|LvuqaYPJY`39hy-(16DZI+8~OQ{alf!ljHn$J4dPUUQDEL+ z9DlO(w7-RT#_4K*8o3jmtXqeMWco&&QD@*Z8Meh?L3tNf*0ShQG+i9`Ap}`1VH{w&l@g1Kl^L!3kyndd9a7{!$PA&;Lo z5%7*F>1y%(fT2;88b9)4?8~Si?_beSH2wWPJSj#25yQiKDNtq{q|xF13gbm1RnE*SbP|DWml z@5#ThJBj074n4m9$BP?@-!tz2rs;ZN3HZw2=2t?4Lm8&w3k?Y60{cN4r(Sp&21G;3 zrwoItq(K^%h~7|g&zE?4&qshk^GY$J1PI3Zv;S7^J8)Rq9U|yjhPWxoTIEQ?uIT97 zSW-L-w;!Zlf&Bt;)^X3_8I(WK_A<7>& z_xL>sqd(2F+?uwh-7R2w*P(6_s0<^PM5xxNw7h2&C50{|5zviVwI5e_ObE86-}Y?# z&T11_?U(`6tGlLa+ z;G2ttSZvrbmm-P3`!h7)uRqQT(NUv68j_;~?pW14^|nKuhuUMDF|=?Y8!<=U;jjZ>^vP=A)zFNB8Z%I(`x2ii#%fo>SkW>~Uyxz%M-wV8 zHISe;){LTDqgVq`HVX8N24+d#c2^-NK3#O)aQcGm8Ey3hq-QG#__yOccC3pR13vtS zQ)_&J`W7d~pBM(?No$`d^RY@&7bPZX$tvZqd+Zd*P9Dw_s=IWY=2Eqp^vT1n4Q{-_ zeKbwA?(mY4(;~}eV$KBWuHR}$43kvH6B2jbtA0`;&xVTkQlh^{AsHl0Vat7@Hxlik zcsqsACezHHq*kRehwm92j#_V_?HDaXXc|f>1p>Yw1vZ!8g)i2Ma>a)k zwH8{%Sz9i$#A=P#P*blVQ6mUWlU{hmV$+pg^rIg|HBpv5@IWRg7op~49hHVYnE|f- zyJDHWI)OZ!O}hEY_vsd-UMg>)Fmbfny42b+$*}wmxLL;awO9-bKT*U3XH_~*FD`9N z*)=id5hzZhC?dHN8sFrII=zTkaqzU2Tn)37)VGlo`zr+c>R2tF~C*^~3#^ zwW-(qcSqEAoR#HKNq-aJqbMXCPeYxHkdqOt?0VqnR?eAwgyXDltXqXJ2!oAElwaL4 z31}S@p=?!{$U~aGPWi(Ojq$SF?yJ{(Htx(QM_c6AHWAAc^(NoIcMd^9gBMisN=gtj zp~N*SlyIScZ=ppmR-+5_ku29zGShTN*Cxi1;>9VmvPiHDzIA76P-lLG(dvlz>qLyKuwldSKHY4%aC6$>TJ znq4W4CPjJZ6|-4w!L7|TS%ay?A}EJ%F5=;FV|i+vZpR@@P3cP{PV1MN(@NG?AI@Z{*A1FaZI|%U?>E2yaOUl79h(Hz{7ua2V=H(&3p6r96{KFOfnp9*+HCL%>;GbXEt zeUP=my_TFo?69@5wkws&{w|P~8^B@jgI2_>f_;{sHtH6*iYlHGr zE*1A%r0T-E@!ybP^yH#V~hH|9d1yxd21}PS@R6Jc5e%vX= z=|$W48(w%Nki4!iWK#@>xDs%aqie2@B9+F6Ip_kzpP>lmL!+sj@vX^7kWX109W%=t zYiwtWcw^oNI2%5s$l*ia!e6k2tUf8`FJ9jcjfo*t9qC+DGW2em0-iJe5AvayjD;S> z4tvtegfUOIvU1%x9Q%aN_jvqX4jnhkT!}j;o8AZNUe2C?db_?DSmEpQ`}bVFVOXwB zEz1jtwFFPj)Df)D#)Ov@Z|FI-86Lxck)YW~6yR15c!>4jn8(DSMqI-dZ;mb$7%hVG zYEWFPT#fkS43`GYFRf+K$zCO_V#n#`fJI2~qt+mmRdD{$(o#{P!lT84-Wp#$Gu#_G zD2YLmvJk-)`@fL%3K=~xCBJ>_u!(^KNFHRh z)>U-1;lZ70DzhF?S}CGQOQ6zM0;|FK>I<|@bzZRnzBxC=2*oqv2B=UIe#aPNTFDth zmLbR>j$w{GRffIXxc}-ppm9oi*;=Ln?4qafC%?g>349sYeJ!4i=<8f7Lb|#nhNw%h zc$opAT5%dFMj6>?Qevnu|L$vP)~}02%$a80f?}4>=e@qqO-VC*H=cl|wTn^1H8l+s zEwLriF_3SrwFn?18MUyowq4}UcQJQ8#wx#yW(IF);7O#%y(PFX9OIQ{>2z@fs_L1S zF;eX&RbzG;MH{Zp@!JsF3RMs|r4vm^qMMKaO<)81v0Ch#;{!vSO6XRbyqm-;gfV^% zbJo1ru}x)n2ra5cXZu8kmOq=raxhg@h`*9ec1iIUu4VG3LELc#&%~tCFlce=5eyTw zf+B>G7u0~87!UE?ceLR~3-m7>%%Z)U;v9 z=N#mrRjx>u;U>e*_wyJH)I_<8Cji%RMDpFc#0Gq1$zK%4n)&R5{jB|Gc9E552Xb^U z*v-M;7+NCI7~BM8QV3xN5fu{hG)Tcp+qj7$maONL%iy&sMiWky;UJxGQwu7R@Dh(gO%Mzk}yI8F}VN5{ptMJ_5KQ1_xVmy zmvSM28UGr%6IL>0^&D29ESB)`z0r|zjo1{FcPol9txo9p$-6gP^ot(-CoTq!pO&>q zxAq);y2q9ALleVqlwSl){)p&@+3i7o_GBssyB}-m(L2^3fEN$nMlVky62m|IwI$u5 zPMnE7N3~~N-SNj+33W|E=9~Wq_L~ma4B!jWICin(wQx2h8(DG@GVSV8U7!UIQ*dOi zl5n~o>CNwyKH`l&5Hh(yzY46Tx9+7VBA~4le!atH$`)$z#? zj;Ihp zFg=Hs=Xt)xClFdz-wR~FbA2N8DI4BUeRE~Mg9>n2L7l6&Tw`)vBTV<8?#nV-ZFw>8 zwxKSYtRdj&vQo9Nb-z7NpO+xfa-WYhXwg0>6?u3- zZiLPwYN7TQ2uGly)?b1sa4ca}6_7I_K&t&`c}$ijx`a1CZ7^O*L^)bCwXZg1J6|So zpZ4OsHja@S{(5sXyGLK>ty5S2XmA{d!Tu#=@s6ihC?8Q!CT`ycJVip>{i3k)16M|j zH+K9#Kgy&g#Bp)G6z;$ZCuO^AS$~ZUWXnYQ`uq9~>Dx)@I=_8ahya`kW|PP65Q`=N zcM%i*WPOM-Pho~%{5R8gVUu3-m``s!TwK^XcKg!GG*$nH01QF;oLItTk9WE{XCc9a zhXFXoCIhb1+c<8i;93gLrB@P?g%b$&hHUoC{Ppnd0M~9C_ zY9@s&cPe;_X}KCvDHD&GSvI`+L33q@W{D;5--O>hpB~mtW#wy^L9G`dLp|~dkH=PI zdU~!l%JQlm3NUD*`-)hs^(nlvKkk#3^QQaBnxjnB9IZZ?!^skQYJU&i5e5ztEHTixms8p`Avkx2B_2$9d|4CC9z;x*cC0_y{53)KM?#QOiD zXXsCO!4<&Q4=)lHc2Od!B@&$LEG60U#Ey7nj%8%!^FJ}Y3%SXYHBX&&Kg&cNV0{3l zEh}D9Jj0+3e5x&6j*t1?=5IkgH!lu)?3v3ptJLD4l;3_F`1`Paq2U5qr7@4_XgNT}`-e0Y}J0?!hqNlt znmxEhh8+PG;79Pt*x@^{EMfO)J_$wT=l7OchSi=UIpAZsnt{$qRbxoWm;HXIvzkzu7!u$dzJtN+md)x*8=J39& z%<{E$Y+lWWA_YKG35f}i(xuli{GJF~WWCI+@DLI$*G{8yqOgu9Ne%Gp|FMV$%8Q1Y zi~TjcU-Nz|4=~o_7Z^tG$HMmL%@8}F5ka=Vt;c@d%wU^z8<98xn>!kPG_U+VwD7;U zG{)9>^=192?qGKzt=!PQW>i)MbAs3nk37DAa4H)n3US9lVikgqx1;UP zYBP3(Nxlu@YCdj6x9YVnqH9ALon=glY=>tQGKjoJ`ws`UVyce)M3_>}xEbV&{4+8k zynX?$(Or)_Y>r3Ddy=R6i^=3C$^{}ufmOqzIBVa-&$#}gi0Zk^FY^!J4hUsb(2%jm z`4Gi@XutUwc*G#)FBrBQd%SVEB-SQBMAiOFk%Y=3g;Nb#I=U~UzAhUlF-q07yWOw* zX=4!!B^&Yb*6G0Aubs1KtJtjl@_w#}zD-sxuptpe-o6ybDEKUg^6@L`!chYy!-fx9 zd(Qtw&b`+6CSoacT!N1pLxw3@mV~c;{j5=9zm99RahwVe zD?ru4&RW3*`jN5w&%kc_j*`m!rjp{|G{Tjk;f8M|H2FExmy`_&cW)o0l&Ce8m+Pef zocNZ=VQ(|$5KyM{Y1xYB^E1%&61Tr^uuY{RVakuDJ`aGW4~#xWJ~Qcc$w--G;Xop_ z#3aNWq@W>S`%3#D9MMxXybc*CnF}saj*jxG15sO|5A)TtP7_gVb`TX!$t~@#leoVh^M|o z_(N5DTkM1d=bwsk!RO5>JzC;orM7zS%gsifTXH}%I(*8CF? zYyHxL!BT_jT&NayN*t8PeD(gpEbPf&bj5f>CwAt;6wxU=Mxi8MZ*XK0;%q)+U zlqlZX`C&jcQ5boOV$n1jslAhbsJXVe?AiUXA;}>wXJZXvt9ZJr4cv^H5KkY3S;PNK zCZT3zDZ`6yoM=RwyP9aQf`fepoE5I|o&Bj&o>eZQ=o|VlPJ=X(kF_AJN>=#BsYT1! z)yaJ-a}m=?tWc1W?@=vN7EAK3(S{simEuR%WwYh&Ss}uAQQrfKa3i=>5k$CpN%ntd z5Iig<>}Hnk2cts#{KKfa8YAIXiYZzmW6ZS0-CGFu?tV!!eol4ex@lD3#MovOUlFMa zkNf|TgkS9M_L$IT6r$Um_n5kDMUmZ)3w?Y(q;4OtXkVN?O+zMMH{o8>wqxRx4A%+K z23kY0fxB%wE12dT!u5$LlW*1}A$OL^WevpJm3dL*5@V@F%kiN!gtP}f?0d70IMe$L zd3#~oa@$S_c6Pgs7eZBzpwc!4F?>V_JASi+dAHn7AiU3BP`kT59RXM0Cr2$}bLtCO zqd5dYFiZr9 zh_8;8dMURTNbLtrsjtsU$aCM%n;w!!-Kp{Vsj4ecCtj%duJX+nlv`r0U zN#(Yac2;9^R?=n3th2s$c#cgK%x^uz_Fnbe2zq6|=qdt)-&YBJCI|O^%+vOHk6ncE zDOerwVXrs`X&mK)gxfdNG?hySMFyHR+cQG?IaRgyT62AK?pv+Tu8ry6q<7P&gj6K?DxJJXBN+`l z?q8{2g7xys(v$ZI&B}AHpT2b-!aZK|__5|v1_n#L#xXqmrR?0y^q^;hTsDwnT)PM1 z$h6qJ%QzLGfLR)D=Euk4$7XTV1JomlrTyDS4+(ma?|952)VhD#e|>H(a>|@M$}$iR zEBp-jqhbN#bo8Z4_G2l51(JlaNE3`8+Q7v*Z(y*RC+vq~*k>5|a$HfER-fEQ9 zeX@@2gVns5({fV_T@(iX3xchvk7y9$gOrk!8!%8`POz}2re9PCJB;g1o3HvgrVAR` zNy87P-}N{}yxvaR8}Q>zf@Yd^j}xqn@DjU-OICpYviw^SKVeg~wem7uBa6}L+K)#z zSRXX=Sh&~ujiwacD6SLDx}NNL@GsxP23$CCnIP?xPN1s>tIvn5l8%?2tkEKWB|UEz zOuX#5iDx~VHKN_cTXwS8jo7!U2i|$b)CT+c-ssbQrFrA4C1gpx-oR2U;IWDG{~aYv zV0&lF&$#Z_qQdJ>rtlMs`4X(~TEB6AhVJimk<>0ZLH_H|cY1!29SRS*LSf4mf|Lr; z)`0W!!!(WOijtM)%_7wbH3`Mm$BwrLI=t%JJF&=QVIVhi zSzT%;P)g`N^3=Lashvzljx=~V9~hGhd{fxi<^XNCT?kf#y1ei#-zrw|7}ojlLp&L- znkrqxuRsY5?zFUCd_6TMK_mqI;WrrJf>LL*8^eH9_xD;jhj?p3JmA5xp3~T}4n;V3 z{LM#Hda)EfB*m7v1ew+N$E2I=nA_slmhD=E=oaF(lN5v7Cp?k&1@KSv+6$7+pE>%7 zg45}XU(CDiJ6$wd94mSwoc}{^9V-z!4A<9_SDSt$*nI6%x~uMFb_%AEC?nVX%)Udt zgl0qt_w28?{X{8Z?b2Ei{n<8)R&adel=pvuThn=>C4?1==O$f;GyUT3QJ;r#po=r< zQ@^U7jTP6jdW?CVcFt`Vw8&^?&b{ircIABkey5dlyluX)13UM^8!elt?NNjNIclG2 z1~7{z1A6JTi8H|}+5Gi(j1gu?ols~qyXMmB-uJB^9{`pKmK?I+#S3!P!ekjyKsf83 z?J#OpOAEW)lOgmTm+`DeA~L=$*YJ1T=;_~ijI#1TcVPT?CS;SjVWeCu4o6*fa_p-@ zzzvAT3qdBhh%6PT^0Q9l^}!|_>f|j@H`)5LZx6C~B2n=^q?=3;x2?K_A`rQJj@DcPp<~j34onAk0V`$&QBL`Q|heWFMRh$TyC^?oaj6PL%qs_l5UVBFa|k z93OwE>M)dX`UAo}c1BufI{9`=^y>)QP;*!d0KwKlr3~ZIXU+$S1?v zmKa2+Y0f&W64?}0S@&h5MYYRmHzm7Al_w(HQ6zsyh93V?k!Mr|{KW(t_Q87z znG)jF276V9d8yN$4{$hBd&zE?Tt!>zD8+3SNGvLIHgeU;vzvU4mnImQN)0 zXj1vC=;N9z2XxqQj^v7hfZ-IlGwCcN9n6*0Jm;J!3H7Q@8q%4SCt8E%iZW+1e>%C3 z;6r%H7qSU=`6ja@-uwM-u)$Fc5!=8-%by0Cg#?9hVo&o_lRu+n@DpXCCpIOxsgZ#1 z63RXs;wgF_z9Wx_$H*k@Z}|)7ZIxbYaMH?vLJ~F*zv`F$e`v17pm&-pn-CU(YyK&K z^$X^R*b>+ft1Yd}{4&$69d8BM`Ehnq{72UR#c~yah3%~ zxtFRLCj$c5`!`2FJL&4ApBqS@9iXZILWuk=rMvE?+oB$Q*ZQk-Xz*SPayQquAq(kJ ze9h`n=)G5lf=#NNM65@7c8NW>f9b54z9<5EDA_ajNAHY~N!d0gszs!yT>OL(CnW(1 z@fy*$XFro=LIh@Gj)`@c&}w$eF&_Ro4pUW?PBMdcY408LQrOX=ny{GKweKf0Hp+%i z2x9%w2l5mp#p{oN=041SXD<$I%ZgPakGd^iS7I7QW7sZ(V%5k038EqTa$k_-@s0c@w<`DHV*tPSzv zqk7f&h-H4h`cEgG*b)WA^0mQ^h__bp`BJ>L(JyGD{n{c~82#JlDK*E5Y8MOUecL@! zlka9<@xjX_ud7f|$PAyC?`8q%+?o&jkd`jmu9cL4QMtSy2Y5Qc{By4X9!yV8=@wbP z>}~V6uA7$+zjjE_hsw1(l?e-Sr_WpIJ~w+`+y8vX^@WXHxxK`l&QURA$YYs%J{mIf zR7JK-s%n=`vSq7J@hL=xhNMHQ4u$&ug$fr8L%}MKOoH6Vr8L{azR-h7H#?B#Pj&pU zTuej7mLkbJRdC)lPIzIA{Ln5xR9@@IHZdD4b;H1;G5=kh7jcLHD5F-2(ac?3?sizi zc*2|6wz$0mebbvI)h7gzY436br{-4bxR(b%j2^Bdk#ns-9m||vuW#?Qc#3Z+vfUlU z;jJKz|I!{)Gr?Z!IZyyJ%o_`=Xsm!JXq-dv{{hMp*n?wrKif9m%8JUd?xUZhP*knl zl^2U!1V~$iZItMR%+BZPnMd&i9rQea0C$&G0;fOYQHllULK)a9&sH z)hh?Tt0r4}x@v`%Ht&e2jj)Tbw{RfAS{4P2TgD#}pecm2uKL7j(Z|X2MQHGY3eze@ zR}KU$rCgfPoG~z#%72n~1zdK=N7sVbyS1W>#LwUowHZYsy&J14#mG!Bn1dJds(Rm4x#!L`=isUjnVEk=>2#F5=T^vvMixO`{ z?;YJzpr-$yu`l3g#f}^dyx8;#$v=lj&Z4T1HyO;x`oi7I2@YXmY|12WnLW)%Yg6s* z6Z`s5J$KMd^fjlr4OmSTLYAit`C*nT*&*Yf3xO4ftc@(|Vu{W0HS~=A?ZZ3jO0R z^rgG|c@PI>fxCY;6~kl!9KX@eEKp?Rc207qHkpI^Voqv*rOy~nj>I_6`cWs%HJ!1K zG41-$T4)}NK1Xq&ZmdF85QE9IPvCv695_{r%NQt0t`+|mx zSt{!!MaY>ASHl~BWl}``^AKZP*ImCPS;MUDRI~^%J-Nl zO@7x}O)>-6<;DEiqm06nN#!~kX9Zw}%%QW?nWz@!^zbxRH2CD`Kp=-^{R^HGgnr*L zPS7d;-k~cpx#4QcD$m5{+dL@qkn&?HbPXQ24)a3hnhM~vmvxvLOvCIVj1kN^(0{3-!K1wcM0*zjHl&>#EqNPmERGsemX*f;rj%RXq-b5ekPBWpn%Q0i<<#l!VBXMUVfDVxeF z7&*GX##*UhA;Sx8g@n1;LgoPT=?Y!dF_z~iLsT^*jI{@)Djt@Ms5xD;s`-TpEeeu5|fq2eI6-5;0%KEt^I1T<#5 zP{7U)OgvFU?umP0@PN_=>mr)X?2Bx*GBgP&y)!{r%CSbc4BzP@g*Eg&bPjMQAzq^D zSDsjzVbRFKSGQ-FBR;vhw8cETNVT#lEkRa0O`xDM5oc|kj-0U~5#&c05hS# z(~NzThQ0VcaRVjGSshPkk4h)(W{#CZhaFY`pHSbO;6sDN7KS!;V_^1%LZ{?;XuLc* zUEue|@*=-cO!bax^R4#F1oKHQ`NQ_BGou98n5VV0Tvh$V-a|C&M71t?<}n+VNI>Tl z?X2K@5%aU(|Ih!zw;Wkh;*ix^5GiXcExsa{ffg~2LfHd3R2K}_hFc0wRbE8Dt_`aw zzHb@W!PGj%Cwrtez2gN4qV7CWky9hjFW2~oAo46U|c0Ck%{t!|7^zoAEO4|BrT`rrU>7FVEZVeWtK^ax^0+v24->| zh1(}80!vfDoGx~+s=^^(h9L)FS!xriKpdNXCM#<0XP36%AD(c-86^>v;|V^+Wg-cq z;zOY{GRpzX<2kq@ z6^-ed1MJ&Ge_N$qLi^GC&o|{zGDVGm z6SpYSLtaw7g*PB94gM^Hfu7 z&HH{Ie`*epf2A2Ul;0QVhUYDTSw)dB$l@;)G&^np$La*gqNXPTG&2Ks328+3o9gaM zKF$`3~&8z5zsD zp4>ycjJpS%&C3<%Q=LaPAo%EY4qn9w2pDt?qLiBRhSp1Ew`+E@qGa}FS_S-M&q*{n zd@(kwbvQ`K*rm|45nj$@?XNNz3l z;CHGb8Oe4-t1MLjGvQpMjah7@Q%h@=c!h$lw5%*~JH=k@wnDSCr{O}G9@DUXxZN1) z(pEY0DGVkwxnFzOBe*aFSR;24$$QRrTnp_5*GLGWvl2@QEl7cxJ8j(n;W!^fDHdVu z0~$YEyFx+bl-zGU@v_9>XQ$*-e5li#c&a`8wXc^G7N^{D2l)#j)ZVK&{8Y3>Nk zh%ToiWhJnuf-w9#)o-CX7=fqKp(YTt^Ok_1&Y@d21$@{Pvy+eEM1H>GX)gJe0ZUJj z6<8gLnXlo|288G{%j|ReVCeG+u-w_q2=d~**n1qk|A=Q6u824FW`R%1YPUc*5iZm? ztcr$~evV_m#~!F~U&@avwUfd9zyEZoqXj%y5k!agCG?cQ@Mvd9?Y6?pIZ?h2%zRp`<)WC{}!Nc=2l6Ri^&X9vETN0w&dj9W8fq1Z60a;egRs+$x}o%1Tn zQrlLQoQFp)Jnj;8`qyM66QaOKcb0Xid@=LFZcC>%3bj0!<^x^*_dZk&4sqyP*4cIP z2YlNUlCc=czj4UsyQsi>Dn)&3$DdicMypf7;QA|{dULlU5-@E11d_1a>Q7?~Kyln4 z`=9coy@>sZ7y|-|VOet#?;xO=vJCA-vkW59Q25A&7^QzlFRqN!QatN+xwi+kV{EKT zvs3|o1Z#*H%ZPN?BHctkJ>I9H%q)t>T)lskBSo}SO0NDpy^EKuMQX9%k{hqfsHD!s zwNV_&G-x}$7sN9@DmkseL>#tb|LpUjI+T3VtwRQu^1dBP1~oI*zv$`pCFT@zL#p%h z9QlVkvbHXO0jRKnV_Io~eD$m+Kmr?6bwK>`K3sfco8Lc$Hwo19CEn$YW-<)+EWK0> zo`O{OIO#j>{b(}KCv%oGR?oZkcvd{dh@SfUugl|4Iv zv*S2U7}vOMu4z_&-qPJf{AoINXZHic9}n0neiHbQy-IWXRbF}6ht?d9P~Lm*VV(%; z_oThbyVgYj<)#R9^EW;wTOvWvD0sppsmJw1#*Y-ACQkvc_ni$lBT#gs&HqRau|)~k zNfILJfuRGSOojxZBJxeUpWn&Anuy*QsVru)$Zt`txBr`ogY-5)JVeM!dh(XgPSH=L zbT4C8o`}H8IlDDMEZHgT;9Ut5>9&+>#9RsIPMr>H_~|uDT9TE#8T>x#lmd+$gil9F zh~1EfHCkTz>!AmfA43jWPNE;PA+-r+8lYHQbgOwlqBD$4Lcd=m={xI>`7^ULcU`M7 zMTj%d3mPK4Mt&#bzfi7u$ZPSEbrJWSpiE5}M_CB#8s)hMqkP4=t*v~}#a~Ev-Wh9t zgI1ZG@jU|BHrSfK+AnP5r^>q~B;)>WQzaujx@B0_ObupP$GY3* z&NIAN=cs-;=2b{>b8g z1{mrTo#0mY5cjcF(jMoZ(3+{_yHgD})Y5v>KKP`BdQoC;&aJ@W>ZtPDLdvx~cvtT{ zn)2I4xoOEp7U7;QP7b?YtvO_QF7uA0*$LDJ8QBZ&MsXUCM5~x9{>VwE zkZ_UbT!~~oo!%{)oKC#Qo%nan#>3pR3;l!*wpb^kavqE+Z7P8MTtFgv-)uzS=UZ1_IEHkvy5 zYOb&UA zO}t#{eVhTo{=)LrKzu~;Ic)`*N41bw7EG6F*4yNHm7o39w;%UNEL(KT%;CXtHAc~Q zxXsk|VLQrxACx=vhFYi!P4CADZfw6j|U;ooJlvDheElgqB79Jahxt}UL_$LPc2(wBv9 zxi?$skepjPa!ubos`0-Y@!B^wW~J>T&>Ru;+_hYrPokkO_lmMk8b&k zCGm@VUJJ!v!Ls_n!Wr?I*svh&C7Ab?Xb)N3!&jMN!DxNm%WkyS%V(^keSDu=K>sUV zXq8Z|wyZl2umf4Q6`m03N2|<4C!JS`YjkcRP&DfrZlb^j<`jLQxVA}TP+)b-O0bkj zcSqJQlqbp!-sjTSE0L)*ki;LP!xY-S>_efeoLCQUeyTrcxkZxS%{8CjSur`NEx%+C zS*+hI^1i>DySz&Gna<9##})ON@etke6DRI5PoN9##0d=>yjGh+(d(eYwe_PZ6jZlQ z-d$RGc>E5HTaHWl@X`^?CH8yeG8jiG(Fk%L@@m!ATx<^V>E^7gj8CLeLV4Qa6VsLDl+St_x>@RxewX-9fs#0s`YNnF=gkNMp$8L|V3S;y9CfQ&&VKo0sR9|qT)zwITI#I6_g(Nf^BmlK z@~gLoWAmunZffd~$oX(|goz|wLom1xW;TiA=v}T^8XQ5V7b)cbq1B*FExn(nn45$g zoNH@0da&QDM;#LR)Zw{I_eKbfMx$6YoBiBkk4CHg+#i*yLNX;2wzh<#J5U2<@IqTR za6t-foinGcWJ-F5>lty??iG<~FK5)ZNcijvHyhIjiLkn3td_as(Uv?BcdT=V`x z!Iou=$}T96=qptF?{JRjg)&mUf(K(TjINRaf7gDn2F-N0=;yC;Q6_P6Ko1%I@eGZQ zLO!1hBw27M+e93Mu*dqcXH5^7=PYJ&G=Cl zvFQ$6jQkswJOa)j-MOZM6rW0Ojp2F5-<}(*0*YFP;M8~v>-^7Q*@Z%xyPU^4{@|$DVkEL-+gj|9#6^y9$F(x@FOYz5(eESDHR1bDfz?IGyH3@! zZb(Q>z&9&3>^k_A)Y}`^s+L}dbETz`)*u-%n4rfbkc$C$!F6jCb_!7G1G)5{68Ui< z2HnGJLelL4J~n}IVLnL$OMQB4W+vm=rU6kB)lhAF*7!DK`QV;WxUY;J=*)k!u zlW*LAbcm8`+lSy;RRaN~`U+z#-;9V^Vzy z{bkkhN&djX#V7l=^sHjO9M?V!3=czpqVhp1 zLA`sGy*oM>`aDt6iV9J@gEC8pB2R>1jea4JDLsAq{mZAokIY!pWl03x(vkVdk^EDC zc4T+KnDgOxW_`ajWJxHMo}sCGYwpGZjrZ#mAFwgg>v!TCtkV?c63t>a%SG&q`GrB| z6Vl7Sm2Ol*fvfUe3$R{1`0}NDlZlZe@T8&&;ar$*8>~s)sYT=f;gpe8r-Gf{B z65)(&s)P-36S=ws14quWA^r{C)K1*Y1xmGq9W%kQLRsLDtM_AsZS^%$E+1RJ(-%P< z_zC_;|EZY9KHStcWi3EqRT<~Nk+1=p48Tb-+n)_eaocUo`seUOhb?4^%%Bqzqi1%j z2mn+!7C;2qrv}W!E}}q;JRrcqA8h~sPwJpHtPfsTrQLF=7P^Fup4k+rDdUh#i>hJil{tQdcU^?QyJ^~z63&B90;6j_2_czD(% z<8AU*Q;Tc@G`Wf2&%FRfB`>Tk-z-9QmB)PAfu!sp+0ktC$Ei8kAkUEs7ZWYB5;<>1L&iPqQg6j5uj2nLVC40_>wME+Mkc;{D3OETUhmIBm(pNgr)@cAO^Nhg`cVb>WYbX zWZ_TXyC?pFXSw}W{bTe1|0#P4{pz$=e2#WIQo>7DiqZ-@B zAef8vIUt+bg|>YZ^V5ZurjRH(p#6M{WCDV2i*YY+?ISdPORZjr^g$DG39~b>Ik6v@ zKwTNdfDLBMAQ@_C`zPJKDQTQEmB{-19e}&Z^48O5j2B6-j0x>->0PWJP;XkZuOR&- z8g%Z-|Fz63#f%8UOX^kDC#vg-$dY@*$pkKHm1?s;3XuGRG{B3p-y&NJg>){E-b|$J zPH;%{1$3eZi=!5+^^vs^T=4qlQ5Nnr%&Vyqh`X7cRNy~udodW;#NhB*-SlUIc{D6u zm{7mLSNFmQ{CWI$!@`IQ;6BQkBy|<)KEM}i=jP0o8Aw~rmy)L@jt;hr?^~p?c|3&1 zbkia_tIC1(8QZcoXhY#ZqM?4$V40UX$?Kae)pR;@?&D;fyOY_%dl3akwur%rLF-3s z%gR}a^F#U=p>sYB3@)I49JgNuE?y94_N#RdiyV7Ukd6f=(Vs3k*}muMTqfm*pe za=zSxcqmsE2$ODPZ%2RG-;P|EKuy&>q1ryJwgvWubd3fXIhM`)BaQG5KyPm6fXIlj zj63HKj>~Cl3}I6`WllDQ`+P_W7mkg+s*sPH_{1`pa9TxdCSB>OllOc6Y#W+%vfsvr zcP<$ttyJ!ry?eeWFyT%9?(TjFEgSWl?tv}GO^RJk@{-cdQcnL0I-WXO@5mEfKw?~Lvx4b5P$X@v&KfwmG$4qF? z7}Yi@XrE(0;AFDx42b%6SkfMGTsWZsn;t5JFFK_=f6?7dRG!%aZjF_G=4Y#)6sKNu zHEmj>UqMNgYwMIxZb`AHB%*mM{*O-Gu>(oi&SHy~++I5o!)ZI`-_hc(x1nBOCW(-@ zV3-2|A7+bPY)*EE>wx~XCLyG*fk|T+flEvng&+D#?TwE~n%)!XIu`ihBnGcu|2o8o zr%F&N892+2<}7psTU3!ybL?#l0YzEJ?+rI;8gUR_m%F|D3nPtLXLSvUm9ZoQkF!ZD zZs2P565{Nz4)BEos-)s`*B)VLgw~muScxBS;Q2JlC zeiyoPOV{8C+JFr#7+|byLov-TFiv40P#>F_n9Ia{!&)nOF!t*CJGL-5K{DdGzWAlO z-Au~yBHW>Y?0q3RGrZs8QIt%n+*@1VNPuQ2)$R>me=_4ebTsqfZhLELdsvitaNpw5 z;&LuDohzfpT3ZzJ{ao?$`bFQQSatWh>#G#{XHQK8$zCh9VxmIjyU>C;pV!t&{J(sO)vFt8uB5|A!Y2=dWZs-~~ zx+bDimmb7lF9DbzNmnb2m>ORUs7CSjphd&2u}+f#;##&}X4kZL8shSZY}9Nf93rXd z_?z>L)Z;ZW6P+~Xb_jzI^NYzN>V-;7Uo}r4EHRgF#NvhSc}>*(o!b!*>miUE$ofZp z5HAF~hRp-xBS~BrcI9+8mYV?+%ymaWw#%W0W}c%YN|hC(k9)DXuJw=z2S-_e;x*|DZ%9O* zg2MKs;N$23yPrdujyT7s;;;x|C6EcpGWY4}mwcRq%Z?gL?1|&2a=2E$B>m8en zwFk~pE*#00#iSI45#mMZkvD`Oa1LwIj2I#j&QJEOArF$x^;Pyy5Cr$PqEx-1R8j+{ zBH>%nr+Pl_;$o_mXe7Kgvj2qecwoJOvdtJckGuj%F?lvcBUcJ-nw@B7X_Sbm4X zvsfsE>6DBlY)9BfH=C3)j`*y!6CG+UYv0p8CA=n{726~! z|0mW7iN4JH7GTq?#pe$7`d9Bp ziWW@oHa(7VK5G6-E8=>*3;{5>TBefrrmvHvbo1T+FU_BYGS@NPsQO~u@-|B?LV9i_j9Xx;K zw*M7o97eq-Mmh_d18bNP1>(nUm~l1rw}Pa4T^WP>lzY6L=+cTw19>MMp0 zAb@f6Y_ZMRm4+T&tJB>tJ#axF^|pq9FUFI&?w4x~0gToXMtRx2W+0wu+|Vf$NV7J2 zu3dGCW`uIf;B93+O!9_XS-k5iDD-=n@gM9CCdgqR2oM&eFk^8($Zu? z1nPH^*1yHJ$kXW@bNLE*)b0>*)9`W<#^yOCy7yTym|E`bN^MyM2%VtJ||95RF zegm4Gdm}jJ?cT7c#{o%s=dUGYi8*2w2z?6Yk8~ym2m262XIXfyDp^0?4o!4sI%V2M z0%INgK1&Z93{lW6IN>PQzT!AtihZXbjSZnAR4ug)ktK;c+PAk$8uj}t!q}P{gg?g1 zNc3!0U+*0Yu{E}QGnVAE%a*rcs@dF!D>+qX9*KZ>L&@h9wQM?EAumZ^i9eqf_@!L6 znHu^u1tsFWUUH4N9S*O&EW4raHLRNFk8iY+`J*3hOquprq*s3Jm>XW!8P*=W6QlQJ zg9#L<2gN#DkA&iHn3t^o#@2;jxp+w`F~L_xHK>{RVK`!!-d0hQ2WG7dCyfKCO07F{ zkV|MLE8x^(Bd7%FO_4VFkQ(wl>A{Z?h!-%ASNkt#sZLM}R|DAQ?E z{MykVeS6CHHB8mL!)m^goWH`tkO9;86(P#(VoZ;9f0bd=9a-s4uDaczZ@mdCyTkFh z3d#?gzk0=ysBRQRzx4Xa!K>>DR1CXS2EcUL#H>+()>%$Rs+-X=wk1ZYbv_FP|tTX?)Gj{cJ}xPa%YN zbm?}(U#~kE*RiP~V1WiyMJ_(jdtvQ1v1$7vp^OevCp(?Lp_y1n$ng&@!cpB@yLt|J zql$_cHKHwO=GOkw!wD>*;N2waO@)?AOgBi%TYLPrFF1__mIiH7DA|v$2YNbtZSCv_ z=YNN{jgY(~;uSv%50jWPHJrvVV688!BA)UyzI3e5YKvY1WtL3)*TnKWV&b?bo4w<- zvc5_fxBb!SrPh4k2-?f6kR<81m0zQ-g4T3Iin`|Q1|vw1Wbt_2FX+Dj~$WvKgp8rA+ys>c@Z~(sU(=dbTOE6if zcA~k10Wlbj*;iM|_)Gc%JH`03rGY#n(Y(l>U!5N1t8rZ0`ApE|>x?x$NvI3fx&MpF zn6b6edFhykNE`0f_B_+FeV~RK9pmYbeW$3Qzjlcb-?ct{vq%f|b98F4Wp2W_==ZieBxYfzL1YLs5@EtnPU{2^|iz7BzYiH z>PyyzIhr-g>y)PRDs&9!r?Hnph9Jq1SbJkS?|!GG z8;?J0ug6v^KgCvEi13kYet}%Cpz{kd2ML4;3<1B9&GF#iY(lnR0m! zyDVChbF9zp2y`h?J2WSCd6ABfr(mx9`A|8!7ikxhn){qarEGz~V8fGZR-&gIkB>lx zSUzCrIf0H_QasskaqoCFKGCb5;p$VlH>RX#o$cI0)%&1zGAQLZ$)ws*>u{@v>X}sQ zTzj^!QNYxdyoO9vU&zb!5lBwRsy8Z4`YW2W=vXMFX%7iyoahw!LF=+JC-Sx(nmx8* z|Lf>`b2Z~`c+uGxuIPPGHR@H51v?D~kn=t`Q7IcIldp+x@M6tI%O>)YJ6n(U{jT#l^Y86I@B(w>JqRXw=xMTyrU4(h zO^eyRAt1b?-YxWFz%)yn$M^xqyyAF^c;>4=(?u1CB74okM*)GZ!sZZbEm?ub^B|Ai zw6!-qEucq)Y|ADtXc)>|PkABSjJNh%`E+>mqU0SCACGe``j34p9IS#RA{^O3+>3e@ zag_NjF$HwFkG{eub?`rAso^4&O@;~Gkx&XT=$WwXi2JO&dxKmtGE!mT)OJ>}g3o)9 z&(VE+RbuZ}B=7fwLfO$_;t(p${d@u&tzxRHN%$nMT!c<^SZ#=SF^NH}0=5UJc8L>=j%cL1hMJDp(Lcb8xYw`Si z3MfX1`QpNJ&^_;W*1DH{h-7W%%gS;ES(6Lz_dgOcnm0&pIO$3)eNaqb^Fo%@Y{%Og zMC~EsZluJ+Ge4ntnR=~%DX!xC()q`B2;>$`7=n|qV9l?hEBKqbG_ML=(%m(2ragur z<4sc=@j{}(v(Ukh4Dkr8y~1P`9O_HO;-~_*tfIWLN8`EAX<0tEa2D^=F7#hnuCMXv zMDZs?=k0=Gqu&-%OILy+4|}m~-)l;<>7P`|{|h3vbgE<~k+zoBU>Bi4dd0VX zw6TaVC(cRLcm0H0KUxOihdl?74Z{pQ#)R60!VBHH_OVCb+Nk<}++_rnn77doqsrz6R|D>9Posb7Nn223dc;Q*a z%VR5GyPAcg-H?DxxC+pYoYfw2M9y?=~vmQ&T+FoT)mc3%=? zc$6#>tIckNk72y_gUQqzzU9>lJ${1xo6A5bM0Dr5*lF~|%&?CbwZZL3XHX{eh+<$A zOkd!-5_4-;PV1ap;X$Y3rnb?3frTy@F|+FVj~S=jB|k*mtNq6zt)LEgzns#<<8lx} zl<7FvYx~qMd=#Oiq*a~p`A>4}0xFw9hBrzi zx2YwWOt2+g(nLt52g|vHu;fa;=R2jeixqA!srQvYLMCAe0;Jj9?0#0l^jG&@X7qL7 z7$E~mcO%w8`3m2-p;Y{H9?9@vyr)uRT&%4o2k=9J%{hZCB&E1HJ#qaCfh^=N=FD-Q zg@bh7h_@KAqq}ksNCD3AQoX4Mt{VhsZVkbB$$rg)GLOyng{Q+pC-G^AZ%Y>W+Wubx zLY=-6iMS9q;eUOhs9f(^=I}U?0rDWPk7%)QNHmIN3T9byY?snk)phu8r{IKZ|MF^G zmd=$}e1zTE9JwRzh!p`}6A1;*;reKSQe-d;%M;pU67m_(Z@8yaJ06t0LM|nzu}%_Y z_8q17&C9tKWgsYN5RTNl7G-kYW=;*ptkmPRSMoHjG>y=P3B=zn0URpJ(2hIOp?A{t zq`Cu9J>y$PC}<;$m$8Z+De_TZW*&#fQ&l|qAS)Q<=*6jxtaF-Z<_o-PoVQ$%zNL45 z51eRTD3h1e33fHSMyHgwg9u)MxROM4X_+pD4n&?slVi=Na{S~$d2;ur;b(sz`pBYR z1|m;a0im+W!A6l9!y8#Hi^Ek_3S?gidsKqNvRgTcxaD2A4XKfH=v7Bx;6>{}i43Lt z`-#*o$llRQfye@(KSj>ykkSDtD2gojYg@xVX?p$bGi`_y{BNeQ1xb#=$_g&isS11|~Ef z<#WdwZ$ha0mxkt-!`!szzMGF{d~z`wx{i=_Xtfv?n***qgcT&TfljLMH_18o73uyw zt;xiY&b?)KV5{G>U&h94^c8?iPaf>rC$7I4B(bpq;KQnMrK1Etb}@E(MK*jadxLFT z%(5;~cAlL@!$=umiL8m*kw1ryUdrJ7i1ohNG*f?GMi8|3vO2(EQFyVlq~+vyFSu^* zh@+sb%KLNbcSO!GSz=^X8zR+Dy8OYCTz!1SS}fw_DJ-y7fk1yHiJ1ASO8z&xs9ghs zEaK2rZbxl!;zj5jjQ+!mGFc1lP%O-{4qW*U*N8jWUJf<0i4`5w?P-YlYGHD9Jn1Q| zXh1UiL3eBG!|e_9YZM-T>B0yqZ>TT?Ms-0@1?f$_H{L0WwdhyZFi66WLuee@P*?$1 zOwJyIe~D3;oJx$K$-kxik_8K*@tx|=V5%o6g zt&WCDUi`=8VkeJxt@jvka3(sDs{5!k1gjPolp`aa?~xF{MhTX4B`THy0?c%Sjy#>w zkrviMeem3`x>8Cu{Z;BWPlqsel5QunruaTmEbUwltt3e#k2bdi2Syod9q=Yv2hm!@ zxjcoRBkDvkL=06)U!0P>MEuqtuVm;JUt6;3s{?5sVeCmNtXIFP(Tn12&L)aH>k-Ap zqC0Zh_D4VQOfDkbWTs~e+SSgQY>W}Qv`r=-2_TDwrg;qPJ~(+*X_xr-R1vezm}tJJ z&}h4EQamw5xWW@&)ki+iF8)cv%X2r@*tvadKfYmm4v(a3LXs%ja14ev3I$8U?4wI8 z6)9;wn;D@f(1wC#+IN)lkNs3OgJS;EWd)XoP}6{P#6+b9AH|i3HjzDLpQvIV%kNu{(h!Y-c z0hlAIV+b~de(#MO;AjyHxIi&|%SbpuD91H^BE)dFZ)xCX6bD;1`1LxruVJd1Lz{kz zrrN}1NsJG6>z|&PX%u+2zw>tl?mQhzAPe6#t#-B8`4@VA1vYX2cKv0~VJ?b6Gvft& zdUA(N@5bY~yHs0qlG%VYUU^EX{tvv7@lJjf0T0U;OKS#b2+>Gn9L;T%V+`nA$0vGg z98!48iHsVxy*9MC+s_kuymww0B zhjP?hW;tu|Ti;Ul6_ANZ2)HIu{B?+gXcKd9-zrspGo6s#;-BVlfPkc`Fp(BA^t;^h zY~IaAtTEdqk+qmFQjuQs^v=higH<#_Ud{(fMefFce(?;|3qAvcC;FrE<41)d$V#Jb+!id0bC&)`mh z4$80(HF`l^uWya#zAFn%epYBA+HSZAZnFl8IJ1eIb)yUpkVLjUqx!|qV%Y(#ccLpY z18{7JeeTdwr{frP*3GRvmy+i4LHdMnS`U(6vY=AbC3zQr4}Nb<aGpP~k_m*I*N^oI4|8;X=z`NEd_p zkSSJ%Yh)31iNJ0g(RI|76aQ6<+`}l}(t55co04eTm6le45l{1RH#SD(AgfdIJX+tl zFLTwPMv8n3l!c8!iupr5(n;ROjYHFOPZVD1JA9VwZhtvxb_f#P&19ID`{DS)_dm-w zyxX}cQ%2?%CkGKWuxQO?($Nq?EZhRXY@gA?MjiYb{9GFhxq5~?-MpXW#I<2nZHCIw zz8zd=^0uq7zjdYeaiM=`zR45r%+PoBJ^ZC$Q^eckIO5(o@#-%$tjmg~UxGgXbU~9P zu%2}Zs6Dd7-4$_^P75yeJ@SKoS+oZi4T8Cz)069+u^|rHAPUBvo>zM;40smGvYo%b zd9IWVQ`b4B0_4fv%Y9XQtWYBabii`z=V}=XY7C%+hd}$i=@jV=a2{-P( zIt#oLwur{spRZmATYpM7ki=yVn7#^#|J^q3O*}k?Q|NxmFUJH*l@g96Lh*7D8OvDQ7jsKc=X{6g2p$YXQTwkuWy!~D}UKa+}I1h^I zEFDh#W2QZAY=K4Zs1$cJ{_3OhQJ5R0~X{{Z0XR&%M#nkXqNiIuj(qWy&t( zO}KnbBX@^VlDa=?WU6$C0-nzy?ct5;H3|OYf6RRlOx0|jM(?w zw4}bRfAnRa_o4k{Q(QUq1*$uwb1J(b!=~4{P>T2&?D8>P$|OB%!?&Z;2f;=jE#|fa zKOVemX6CTv&FLiPY#vw4{X#xAjHhgw*z1R4A>BspVt{?|4g}!^I7gW56dqjxy|*QI z99&HJgF)Br9b2Hcw)FX#PsJd$v&;5|1TQ*&K+oq*g^NnO*xPfZuDRnS)IM0drN=1s zJ-1|je0$oNro&7d5nML@Sa}5qE{V_V=knt#ify-mED%}bb6>ekqM3f2N%>BDZt?To%hOD`#AxW*tIjK^cl4CB53(`QJj* zUHM;6Zr%$W!Mpt;6rk4&@8xaj;uV4N%kTSrige!-;ir4^1US4v7TV%>@`yZm;$?Rr zTiM1r|DBlBG;Ow6#zyyvKmIyV1RGiPMt6?4*E|Yq91)`VC7GIe9y?6H8r*Hh8Q; zLU=Ao5zI*IN>MJe68ttEtFyULz`}BiB3o6ZY@rhDRsO3zW+c$*Q{#fvx#~=%TpcvS z23K7{iaaQ<7KEEJK`$p`bI5d5l`l)@iz_p0S~IG6kAt@H;hFz)Dz!OHD0o8fj4crt z9}}SFvE!avkl)u!I4=IWFuTnYntPf!6<~@ZZGICXelr;boQKuS^1!8%1gg%~qfDEl zF|l~Ve?6HmV$d6f);j2}NNU;tG48vD;6(^rlcTMukt+ecC$NgaMCzwzrOZu8XT+-1 zlNnKl>r^4>m>1pcwB9RKKRYoaEB^76okLxqj^UJ694Q!N^XI0*k#W|?K-r&|ISC={ zlkQF>(56`*=;VUevFg1j8^dWB3(Q}}R8N+~70uVrxO?u~nM6vo!ttA9U!W{RpgrbV zV&r=1V}N4D=n8ny69s2E0>4dXU(tqp!zu|@|CVNEoZycvtsBeFH?J`^D3=ay`NAA{ zTEig2v4=zhl|%KO6lab1@&|?T&we7xK!F%x*t3#>#$DH`-3|jmoY7|N`Uh>l5z9QPIy1a6K}zWItvqebIU+Q)I=iZw@3 zonOj5*?-7~s%W1$z0v$d7bd@#IA1N4)}?ay^5UfkrIg**i0Y z9&ybDP?~2vY1cx_Fk^1gvv0uQtsK987gH^FoAr%Q6M5d}XTUiN1jlcV+B>=$0BxKA ziVy1}@NZx5#R8K=Q3WOvKGhqL`c1r($n(~I^g`noo@=5PZSvy|HhQwv%+s5_ph5A<(nx0@q98&6KvQe z05|$(0bd_C7*OzhFL!YK0zHy&W_YU;^w#kmG`HOflodzQwCc09rV4&;ssFaDS&$;Y z8MtY|zq6RauF?J5>7Vxc(cBn&3g=iKfKLaxnOWM3_M5lXaG-=HCGU#+674$>GS&2+ zzmh>MJCPaTg{{}75-Fgg=|QOhUVQWSPxcrQ`v}5KbZ};|c^lVc6F~|V`QAnv^2|%d z0#n3&QkF{kyjD%k#ldt1bP>#0Qr0!3KM%E*__?I!Sc7{s^ zBsNQc=1b$Fikq&Ty0T-Gf63#lDH?{noTOxNUH0Xe20y?_yllj8;4{VDfn6$4Xe(Dc#g~_CcB@u>nUlw*3{p=WiB^jV{Kr&HX z6>1j`MODT#DYX4ESUp*1f1UxNGj|oI16c!OiXRe}p6J7f%x?w`Q({jA5XoW=hH;V@FEC znmmo`w~aqORX`;&?FG!`$|X!60#YJEH=P6vTtr#Ne% zdOV;@k?rIdLpXZE0IDj__uCUKXoKxHs1l1BxYLt5JH|n0Z~arCe=Gwg34TyRdl@4# z8uz=zCA(g)Tp>yd^xmCiyl#&HFcQzFW0-m8{Imc^)z5FrjHZJ zk>?*+d;VA*Sg%R16+3dv(?pUwShK%G@_OrFf_=VWY*rXk@dIhm17H0m@Ql!B$@dK+ zZpk^fZ?%&ICz~Lfp9JY77bq4Gp4tv(@1=!!>KYvMf?^@Dfgd-ajzq?(mw0()s3{W( zZs=v7bdsE8{4movfbz-5e(SOt6|sW=C3e>K4d~cxVjkF+>M19DQuxru(HXgjP5pOK z9OjK1$ZiBT^W=xd8WCDk6&pHyt50Rc;Sn4gotdjP|J*Y>Y-hh%b4*FeS`DKv_=~L|Tk5O~+nY|@w+YiS+ST%Yb`+CJw6|EI)f=AU`aV89wOf4nS-JK}w8cJe-_;#W(m&cOu^{X4^5 z8;iQ2*~r$;t|#H|86;}Q{}JB`|3`{Yv4YlXOiP1bb@*e!VeZy~ONz6{`qYaGG_s9b z4z~r7?wQZ(UO1Cy9$sBYw}FPZAzMfLPwkhVE|BPt^E;(_U>ohWpcB45x@8P22#^|< z?(l2nU1d0)f1F+cEI?{eh`!)~t85dwL9(`{h4on*svE6PsJHAlVMiib zkVk0FxVY4qM|F;bwulsp<>NnvGebHxI)m{0drL3UNuq{?cMrgX{{h0Ph<}E%?4bU1 zR{&;OvQu%@gb<9VXiH8Gc2L7zNMn`3Vii1}onoIvT?DH{g*D)soJ%geaC!97*>PEZ zX7e4WGN52^C6!oT=|W#Cif}J6>h>{eMtlv6&we$TvVA74^iDmAHq`uU%)1{J4Ni(^ z$5T zaO_H>jmcS?_`{ks5jk637a1W`x)xJ_Zg_+{ck>Z<;*afq!HKdK_sV0r zcYwA1m_OAs)ozlo;~J)jm05nHf474IGOD7gIe*vR@bok(3n=~^6OD*D5*&?b_}(wr zn(*D6f>_2}ACjMEh!nN`aYfy_Am=Q_(P)WmSXvxFDOUqsb6YWotWRf>ObGV*&ZHC- z_EXczrs(BdSFLG^4Gcp%-HU{_mvxYZdqW6{nc<@l=UdeBU(r(-HtPn}grn-C9y5BC z35Pc~453k{u83xXsa2v*{DUj3m3FfAng+Cd<$lb9W+6JE`$Z@8EU`BsUhY0`nES!_ zAEq4QRD`Vd@8+fYvia)AqbJ?PL>a_d|8i{C$isay@p4t5qMkb^=nLhMfqZOK#bRR^;GG-Cl>T zpiWLpt)+h+;f046|6(uWYH%^_u52BXIMm{`xxYNE^GHj@^gjnHY39&X(`>6#r`||~ zWfJ87F1B~oR6)l0;HH`Og3c($GW!K8+CMCtUO0M?v6FRVz3e3(tpp#Nx=tFQ=^eC> ze*Q~ealJOKk^JxZ^~9fozBaSv2=O<6@C;kh*Ml%TLDs77l>Ff(PMtK>5ycq&?ML+n z6EdE))IKaP|F{GjqlSNrE_$rP!OixU8^Z3=a9}7i%el0@t53O+hR5&+cg^kk$=B}E zIXhGQedm4aZDuBth7E<3V&1JmBFT0FW%O$7j7%23Kcy!aiE8m3 zP6w^F7zRR+%!|&ZLM-YTkuSWK-xf8{e(XX;$_4gyQZj62lG4q#e-w7`;H6Ea`X*YH z+98refIVUlGc>cfoXif%qZH5$$$K8^DSVkO+u4P^_ZzgHjLYS{dS5p6`e3G0cIi1d z8}w{n06{)Y10wm4UX`5331&`Ci%nZe{I({Iupo=E1=;LQ)%0w16_8E^(Ye^$zaR4R z*?n#A^1VENIEW=`WfbjDrI@zlo(=!KoFmWpNye8$0qoHT&B8&h$s zv0Y3-i2&_Iws|loU-l}98YYfm%`RsrerM}4Bd+9>9>OPmf;Fc?!@h-x`XEG+diM~w zoK^&CMFH-zZMX+sOVh%J}k^2HlkN4X5Y!V;xh& z)jj*9_%j3;8K!?=VcC}E665Tre8!+fQAq(o29!l{l|^dIRi5mf&38RdjFi&Z^a$Ca z!)tviB?I@wlMLof$@w0mN_E^!Q+C>Yq2>v5PXS(D@yH+UxX-iV1z^ro)C*rf)ZocZ zCU07wOhUVJdhndXBDnuJZkgF)>%x%VArrXqdPljgs`}wvxgDZQ-sXd-5Z44rZtt$l zr>!QYW_96&>lc7+;|zitLnoA{JB8L0P-H zap-=pFI9^IRe9nSXc{5mfNS!6M%n1o*%K&g1(nBlG)qW0u5`*j;-<;(&4y#+IvC)N z3X-8TI}Y)O(ONe(u~g@RMGaIwP9pSEX7jcNSW@4r%w|7^70L2`tBo{Y+r+r=r2DW! zH5WdIRFDwLdz%%@T$;$I5rXK6n)wfwIN|sGuw@B{#b15c?<9%0{pHJFTDpebUFAUo zAl_qUf`XdTAnK9Dpx1T#dUez?KVl4A95aserc;|A$*27U&Gwm9um~2X!V9|A?uY&& z{recp@6R2!AC~o>(?m(#>oeL{vGv76e!;R?r3t!G4Q)Edk5HoC(?sQ}9WjbEsrs?1 z0G5i8O_VJRH)4J@dVwhN%*XCg{#GB*G;C2>?qd%WRK7Qyo#wxGd>4ZL#l`&9zX*C@ z1UDc;M-m#@zmA7xQUEx1M~a;d4f+Kn!{hshAGRuuAlpsCN0xc zge3Ac35W6u?nA2@D@|B@A9(m-S_k)94q}we@`<}FcD(IE{+7)OBfZD*PAcl@UxTTq zfh+gD7EE9l(_rF39-2e;=JY)n6{+~bocN(d9q*u%oNmjH&Jbi6C5WysLBCY|D zCMmQ#r^;e);+J2**JqvLXLxlDq9 z=}9wd)0c3lB(lCASZC%VS=%%z@x6Ef5HJ)6`Jtr(T(=k-V1Br+$QR!_R>NW$^kSv5 zW*RDm4dKjrZ-L7I&yW3F3mgzHZe1Bfxi2-p(O8{-*6?p&n{{-3e3bw^3`&k(*&H$3 zqPvI)Y{aGMA+3R(>OnhH$&?&rFu~s=Pm7^I~ZftJka1AZoA-M@K zTA|S?Mevv=hk(k?<8_omn&^eup4cs5rq-l@0E^fgrk&HX1cE6Y#_$DWgTYtpOhza-KG4ED(o2vGnwgWQV7A9F(w$7T@> z(b2R5=y6o>-E)kx%)b)~ZgJdBPS2sjV*aW%NU5MuLRCo}qV<-n-SSih~^==+(xCRGkgUOzoI^yv0({g70gU3A zE9KP?hCZA?=SptryPVQQ+!R*VGN@-z>J}tGB!}vg$%s(0>)LN#g=cC=2nUb&j%{U- z7#k_?=Uje!3bC5q3_#6w_BH*qva=KJ#=<3_#7lAlP@qFk5dO2@oG(+71tDSIx_V&> z1A=6tmX)t!B4RK+7hf!IWB&nYDcqEVlff!0&S)PLH@GchTjDl(fHKW+COywMu4q5X zfjgL>Z%jZ?`GZFsz_xruNd9Yay)Stu#`hNH^ncF6=)oTGxq2}>7;=8%-qjg18O>IP zy{rDxidpZdYbKWRqLfo8H#U#<8F*MRRq*3upk;%a3d8+*XeU}LA3^^-nsLHxXd*CgLIaRO%_Bq@>Cu{3;CrSKOZ@PnB@}&?9^!Q z@t3ok+|K;90=REV`&8Dd1K!GqI@ep(9}i8_0vsAIpB%MZXv{|-CL0W{psdJ9HOqGT zT?ZqsP}Cy8CDU5+vag}ok4ZFEfwTv6$?3oVY9pR99Zt;#)W}Kb7*7&>Ptv>q(&_U0 z0w9A5{*pm^|B^v+8%F=JXZ#RgL8k*`OZF5g~A@Nt;DJv=t|Bn>@SVP8jQ@pnP-U zjFWiW8$S3u=gfBxP_rsq#Kv7RUoQnnAWhI2_?VvDSq-l}j)#_=Bn*nEG#c_y*(1w9 zK<&4?IEuNDOM8X7?w8l=xnhPmmSVMD8?Ev-Z^Kh*?*>>uLJK8fZvHv4*c& zr42+s%gI~|x4IOZkbgQ>!rG$+hF-)7zqcLP?miaI-GCL`oH<#iGn6VU_)J!oPBj2H;HKwrL( zuKsV5#GVdkY|&ercnrq)YwN((Wo(*v4PC!G@r4q>R>g^%>|9{xD}16i03=J?X@asA zEv;1MynArJfYDW7orrO*dhvS!yB{JMLGneHN`HD*hsl!Gi>{8AhaW+H9hF86k{S=P zazJp084GdxfQ2r2WPunZitnx&S}=rB!V=UVZ%fsD+n=$BrgQETt0M&Fz(yYY)e!K*qw-Y^U=*|~I zK&!n?5ZuX}47reg&3ilepU-SoLJzqZ712&@&ezwmL^|=63Jm|p`WL77syH3XD8R%l z-DYJ)9ZRf3C>fv$4Qjj;&#ZZLz&e2$E`YQ+A3DF4*c^-T(4o=a(EHA9@^8w zGI1?PMQjTqz!VWfrxI^5Qfk`HHst5`9_wpI79n9&;BC$G=)GUqho49=`nzKBnY7}J znG4T7bL9!Cy95pAUI&ROVZ?GqQDO1HeWGjD#^wt5)t6(yiW528Ygu zgB6f(7zkqj{hUPd0M?as;DM<9$@{t{=ku#Q)T+Yf`ofS(#d2AX@hc|=S4ti2V>&ip zg3j90RTFYrIcgR$_ylC2jMlwfSH|Qn{YBjB%*WsO7S5JBsKBbu^V^Pyd1k88?5@$p zRH|-fK;m%f2sFDqI6S7I%DFR|$f)%6H2qUiDJbXN9UkKWpOo~Vt*{lS;NQE*Fz|=c zi7paO)%;|~$h(Tpf#m4ilRd$0C<-q)?&K?@1hHvss=kjAm#BhpO97Q+3SyU?J|^aT zU^752r}e#Ox2^c9@wxR$*{nu7-qR-10QMg6T2mK0aeSFUO-h4UMa17!g~Ryhf}FIz z0FdaLeMF%3S~?+j+bLT#eQn@TT2+cg!VzMXpPa^9bN798V}rgJib|1=cK*CIJdl@3 zS~=&t8I_?~<40sS3vF!|4f1N}r)!?+(%gI-GnJzBcTN8pQ4=5k5%akKYOmBE;N zx{#?TTsW9d;v|E;MfI|0n3#&ERe~wS*A$OQQ*tTy6QKdt#ot;MFH!^r&;Dnvn5N)p zIGv$4+Fs*-Nb#I=+mcuWVZmcfU_@g z+~xq=PjaA?h}vuPeL2kYJScaiOHFR>qfmMxkbn~J#qKm{lAVBvHZUZX$slVRWZEW= z!Jn^TiU|0p-I!Y3q{xdft#F)-7};gVe?<}4p@##NY!N{Uhr;z?7ushP29$D{GF;%r zlnKe{`6-+2du!-iAg1yP9Gqg(rMdHouTQxOYO(uAJz!)`WQdgv*vGP9i1_XjjyP{Sw}BBvzmJA(7w;{W@dJe6TQIa|2>CE2Qpbz2RnwW z+Oc?7S3aOu`gCD*5i8-EVB<=EcZmpZ-oSew#+yGWf_--{@!`u8A!6zl09R@U{mprc zMMjl@=+F2!zzelZlsga(mvZg|2*K#H#@E` z3T}*}TOemyT*lmbCUTiQF1;7q*L|}pOF#tvsU!^b7 zwW@P<1^q3CQlOP8%nV^LX$Q7zN7RUhO|v)hM*kPij3bS0dL8r$=&dnvJw4KSDAJ0W z1t;`jX#%AG4G8~+>nq`2{2$tbze)sP_lE#*xQ{*mpNLX_f_!-A0yp3$Cu4w|qQZ_{ z@y5bOI9U0<%D2Ys-ouhf0Wd#V4 zm~U(H;JfgjH)UnOHKf_j2cgKb0U@(DF--uCgScmQqqyMVxaE{S!KET6(w#3R`rP}3k%?)&sPOcA9?U=KA@&gN}AQ}VC; z;Ik8=s1EFUltb6r6XU$pLYngaBQOA(iZ~erP||?7-;{(uAD;8g1N zHY;*s`p@6LnwZs}Qqp9M5rQ60|!mE2$WhIwW=^ZI>I0gl?K z`@dK{XwworSE3R8H?ZaJE#Q(ob0vrG(wXW44F*BAS6P^efLcDq(U_0eq@dk%4j}_( zhb@|An;<)KbGUvf=7)AxvC*}xuH3D1{wJ5*0W7k-OpoAsH^hU08H=y!Fx z6A~}hCHAckkiahF?-u~5Qnui{4F7yI6?^ppxU6Rw0HRvx(#hLg6oQH&fxN13q&sW> zpA`iHP0`Kth`)Jf8a`pJvAbejkl(=w$F!Z(?QW2F#L=BX8~Se{0nmr{5YSCxU??*r zC}XZuHD1F{Mu&MOTEmZ2%PT{qbr43;E-)2orM9ptizTgC1S|pkJP+~`4Od@tgfztZ zd)J;asV;K4QY3UkLl%KlrbO#=|31Y&$aK{w6)em=WG$ z!zhA0W(%ChP*3|bvA-#EfIY$bTtv<PSH-jgu%hWU=C_)LBaGZ6U z;_Sm)5di2hhIZw!Bv}M3{y#+suZobS!d+g%ZSpXHhOXl1*^;Lhb_yn}!+^{NRq1Th zzcPf|d|;-sMg~p`F+GW}IE6!yT)+Xf8=+2v$jKelO})dhh5KWcrP?i#deOKkXgjAE zZ{F0Prqz6)BVsH0%~D0Z=0FD@eml3bF4~7fL8=aCuU|0zQQ=G4dP{FhJ z&?+rx%?!QJvt6pZQ>n$th}L!!C1mz(fB^uJV+-Kp{viCJz$j5q(h=HMk*JswL7AF` z9a4@9jDbspPy-bJoBVumFiqnlwi5x++1DL_raXV*UO%L0hU2^Rs0y_SOIMy#sV^D) zMn9;ptD8Y7=F5GsU9f6Z7=0PW%^X=`W7{Hp zqf2o!J6H@vyZG{6vdh53UNp}}my-(+J-FKk$je7~ww8U)nd#D1>QQNU(-oq6 zKHt)R(`q7Tk*(e(`QNw|0?YSJV(a#(+svp9rv2XA_@d8yz#VTQru5zQra}m^4aXgM znnwrP&r~LiP1stf*0VE{@kA7{aU59C#e|Z97`R6J`v`N@mlq3yk|FoDX5;}-tKG2J|CEp5Y#*bdKmb%;xzN}%<=16l*BXBVn*D2IBWRMO}i44=o|8>bTh7dMpp^5BZc4w?ppNUAAbmO zC7XzN2?j(yyp1DpmRkeq``MtNk|bPY47w;b-_qOteY#r_uD&1{WtK!l^~fS$LCRfO z9bf@}E3)fx%CK4uZ1ZQbnTZ{h%aH`&Z>>R?+6muF99`B1%W#GJv5;D0SKl zQQS4lW+XN7*EJlR-P@+{{v(^t7xsZl))QrMydxg>S5M(Uir=vQFIS%xASQp>MaRI| zf9Jw?Co`ytbt}H@;dJ$M0T2ko7ZkXB@rkyvtHGo8Ba&H32WT@Xfn7^4q%2!G+o91p zUUnubVUa3QQiXw6yQ*221D`ERwGPNqxXwN){fsj28R~eRSS3cO5>-<;SYc%q58 zQT)Oy_FWK*W^3pC$E}EH)DAf(r6GvrnYbxqz0AS8t%}}xzwO&kXSc_(HgCUfL^sWX z0ehd-{$4MSgMNjx+*oe#O4ow&A}$ibaQN<@-35sb(;rwX10%f!oQl4!?WQybG(9r2 z^7|iuBr+)x43tF;xkZ;dKBTVQ&%3_mwtPYVWV3DG&9C}FnPE`pS0IrGgYPYRc;=%o zyYZS1zTV36b%T>>1Pv7u30g#P(MhlvaW{_9$&Yfx-?JeOD6_zo4^iSd#tpJYl2*nj2o4#P;+>1KyVk46WJy*HHI>`32o z1>OCi7WNaPcbOwucv(})JuAGFi;3ykv^n|x&Oo3|`YXgZx$mx6?W-s?EZ1!BT=Ops zW^gaQ(B{U~Vkq{+(Xk7bp-DOsw*u%}#^lK2?{5yHeQ18s60xP%cVZ{dG}?$qoSBBd z-(Zx*ke+zDnzvCGJhvOISut16Y|zMR z*u&c<#h7)sqB`HYr}&kH_cPNe^$*o41fT@ISGa~Hmy#BrE{bWOkqmIkHO=cX*>9#m zdDk4B;M++yjt7WOIhtG3AGIX;s zQhbAHpOpkX*{27U%;)7N-uX(5BLf8>#*mqVJF+&ukJ1uZwTuQp8Tk&EW1PHAjoz3T zwPkEftSh2n=cCs`!1q6o^TUhn#91{?$}cLU(YY?rsU>Z!-`7ffU_9%IY6q{5I9YzatrUSk;)2bCY!2j= zf>djk2dFQ)h5vkmJ#?>J1Nj;m!oV!cQFa38fO%n=J&`Q%tnRewFP~k$nyv6WNJhkO z33LXt?%tig;9LE3Y<1uT=|t2T07b&;Aazz+^3B5mA+E_o<0w=D^@=orRs-xwPxNcq+71Y-=5A*Xamq{7f?HPbb>rYJcA0 zj=~9G;ed*}vC>EuKY;v(oy~RAfa-7`JCapjp8i6Dio`Dt$r}ef(XQ-JLW+v5a3a1$ z5e&_P`X_3%njiQtc4<;0Z@m5z?$6;AZ9idVam$DGO%HDl{<#LbRokTfDZo~BeO%%5 zt{ES@86J>VW-<8c@uy{_4(&sYS1}=AH@+JZ#a{f?jzQJiy80UEf4U zwi@}o*YQO5Fh=I4ts$79kyG;NF^%QE<=Tx%nf04D%{aq5(aYRpk(aghQHRknjW35- z>RWk0@d06G8VD?RVHE+Z|9TrO&Q6?YzVn2G!izR|+B5%x3hC;wY2cfk1*NNp<^YHK;HxKNxV4cz9>ltyN5r* zv;ZYAfVTc0%mpb@|38`wfC)>5pC29r-5uamH18m>&8@Me`1=jl(r2-Fnnqw8N{+o8 z3lVhflz&09o=A$_fgL!tFAw^`(cac*;-V0N?RgSw!@1{{QI}*b{r}miO(MT?=HJ0^?%9gbtpHno zNwhkr4^SR4fiT=InMA#7bGm)>Q|7P7SLDOlqCC0{^WXeBCnQ;ohS-3cq zq=M|&dtp_8!3A#gx48g9^cABV@5vmW_gH9R%s)=>$){eoW@J(BgidM_8cP~B<4H#y z1G_xWq_74TF}CaV(b3sQZy(o(9G|AXHZw@0OTBOOzZ^xEYj8W;w}XCQwWe70}ZjaRy5{MfPLYmmn;e9!HM~TQnUAP*_kawzA zb!t1EJG37D^1jZ}IqyI}SZHOA1_1O(Pach-Oe`1Nv#JLdlscCWG6RAXMs|*QKv(J% z)ct0Z^q01oUyJZ1UU_WVlA4m|x7C@cbIzP=4m|*-XNeU^T;|FDWCid=)mvltb6oi0 zG~jXa#Xh6ts1Ejtc*~le)r2-<>jO-1emqT+`A=ZNOE}d=j73cxcGhK4({P;D(#8gn zwg{qMjka5=2B$iC2P=Vn{xv`X(9cf2CeN0#YQ_;(y$af6$@&+jZ+5F7%Ot(Lg)evr zJU_^GMo@<>JOxf76IGZx?la9!Op}T$=t+5{FI)skYF;c`c0Q0IGJDPS7cTSMlCsex zhOPktbs~VnWF^49@nFff7reB`%$&@P^&8e2NG|!Ovxu0( zk}m`@T!SWtN8$r3t5pV{k@Y;zPjH}-<=r;^IIC{&ogH2@kzieYFJbK*dzmQ7`@~Uv z9H2#d*aV`6r@sOLllrFYzOA9roG*QkP3p(rbO~#TTvl-aDS2An&QU5OdWocHTuUn7 zk0g0j=blO*d4U00oWlXK%VYzI$%%iEZRIEE=D-oZw7qUW&V1Z5)SBU$futpZtl8XqT0hI} z!jFJ61UlZ2jloqxIpq*jQhXL(EPlzyH~1kE3IvDniBXdzZehKQfHz>DN=RfsjoSnj zaGHUuNnBRY5G+#OU?=CJ8zyk_(^jcdq|LSn!w1@8Zkbav9M1G5mn$V*Z@HG!mo`I) z(8XJhFN#2dHG8jzqs+QC&`lpNSMd#+ZM!xF-d_(nyWWC0toj}&VPm>vrjn9?Ho@qV zFcir5Vw#KNyv^(OaEwj)uP8tZB-h^=w{KgU;mOD>1a}&@gqP-6Ns(qw_x*w6x&2~~VV{}=%)fc?38k1Y)J?Y5y zf*)HA6R0HYsycSqQy|`t{uwB}9g1+&@l8ZvkP={?R`ctGA2A!^e3hzT&CtV=KE8$q z)lhWZRqm@IJYrPGfcA9c2Q5FH8P3j@VQea$?Ed} zjf1a^6ym1&o~sVfIjg>H7r8X++?vG44Lv~i)-(KzeU?Vtzm8~)zMI7rZdbq^WjD@**6P%sr$i` zx+{T>B?4IJyle{X4Zrbm?&QTp59(-|lRn%0kqoeTLL&$H^T>qULq@w)sw^aaLK_uI z8`({O)6ku7Y2?77K5oCC*w967&sEe>*=Vm^^++ri9iu>$%=}~pzg?XZ{Uv^Nn9&oZ zKfi3Y$au3xj>ZngfPX};^y^ovooBb%Ijp}ggPjZBm>uCTx=U(%$Ja4RL6V9- zy!$3obS!`gSb-;?9ny zxwtf+rJ3-@@ws~bS~n|no{2CqYoU9PkcF-30Nfy;2WQE6=vga19B|#%Mum)IdXqxf zQw7uX_j2rZ6C0}rYHgth!*gI;IWI4=qt`y>0IOE*@|hvhfjp|Z;%Kk*Ifc8}?0K-U zO61i`Q`4mInG~C*i5#;Uk)~qP%S~#3tvdNDB^e>>f}TZBB1$ zWvfY@mIn&|+vbX$icKBusxcCZ$I-=W@fD^Bi@`#P79URSrguFfw^oz=b5&k#Z~495 zVSY%)1Jc$cC6o16#k*p86f(jj!fY}IMc?z*jcvJ z#j{IWR-@1>jgdZMWN<89MA@nfUzk(#Ms>mYAd_voKs~|0mVuol zhB+6c%jv|%9bFxsac&<~G048ouD4*e^Xk{QkF3_{E1IR3OA$6oiOU#}#D=o2syait_Wru!*MD9a=RO;!-Zoeh zAnvMgOs;btT6$Zvz1z!`dh~vat6c^;bnNxb*|Cv^i3y8kju7>#*YENxi5^rjzc`u*bKzV)ghOm7$!<%@=y2^17#lIdqWCcu}UY8&})UJ#JD# z<~q5YDng+uY)?E0!r?`}-Tr-Dj*WLAan;|qz5Q*Cij+GgHHMW`A9c?5pV|y;Kju~} znAXL*S!dDzMc!Ms#nDAw!Z-wX3GNQTT@u{gEeSLdEO-OKg1b9`;1CGXxDzyZaCdia z9HzLRnYrfu4KH7+sj5C*b#$M#*4{e;BecXPb;od6uco|&gYl+%u=ja6zqCi+YJ%9b z)_jxb;q4JA;&S4*v8wMIxz%BBYz!=Bre|!RD?ors!3FvGbeppyr{|=aEyrw`3z{aS zi%j-@VhOf>CJ_uun}E>Z57pGo%Gwcg%W7k!KUQLYod{8+V*D9Lw&YKzp# zi>4z|1*}#zov7UDNrl*&tyK>`Y7fpWoc}0*}B1P(L5lR*3c{QPa zR2qi}iwa!tTUt;kS7OytH#FH`u)a@M=-9lVUW9&jqT=hrcF3LkAjY^F%sK&4wkA}P zcbB=?)+OU2^bbb8llonU-+AEn#u>`PdsTsX>F_*m_A#g8$bgQu>NWE3uiGsiyr*Bk*2P{$ik@zW7a)`;@JE{Z8E`F{4zJ)0$W$hbn3dX!_Y2 z{xG_pK2qsNM8%=6xcpFqe zg9s7~%Vln``xF)87ZeisO1*QWmKX)Qh13-^Vsk5^M~#@2j?W*s=L9a6w6*m}nQ3cD zqP}#{;GlZau(6bi%eNZ`X`~NqnzPT&`4v6dBlM3^SxE)q!Dn3WKF=SYgewcRb9}#3wF5OW zBDQs|979C;sF)f4H`4Tyb@z@tl4GSWFA}fvqTOk2g(-G36q+F~^25hQfZcydp4{n# zV0nKSP1u%)t0iknaj1Pv!JI^uuw{S9C!@G*x0By>n*6C2me#zUveH)QDxt#Ap$3Hw zh?urvefz6;c+O%RaK$%0Th)3NyuJ0tB*yNv+FPVaa;U{IdCYwYM#=u+WCtI~2_h=UYq&jNp}@@#JDvtq-i`Wp)m7X*sR7h~Ywd2R zaVz`&wh{+z(a4?TlzCfsY2caYxffFtxlK#Y&eS3E2K0Wukmz_!_+oolTNoF$-ut@@ ztK?>8Jnr1Y`c}uwJq&7+DWdYLnJN56zNc^D4J5J+deUUT3V^~P{u@@zMH05 zurJQ)i*Gv2IH>b;gcP!%`U@S7*$#cx!p0^h49xmAmII^5T?JWW<+736IjGa`vR*K} zf@NQ+_N>;o9}V-eiaN50NZK|1Q~aM4oAl)d(6ul7`=dCtmM_`dpsy%E9!z#$%*rAQB zG-{u08{-^_o#PVtZ?~3^F8p$%*&d5+hi$uw7r&9#}AJy#lF6l-GDd3FYU1`v5us81Vj&S+WYZj zc)Hflqb|j86WNbUdDZV@6;!}6^WlLnV{OOhj(F6;OkMDwh6(KVNvT#vudD?Y91{Ws z-0x&PW8IUYfx%*C%Wq&{s9L`vA~TBPVx9L6p`I^9i3pHid<&<>i&gjW2eFAN-)ler zJ1DPL9U7|h-1a>f@2DfppKkI{k_&d>)?ew6Y9Q2p9xzo&n+nb;F<=K6ifCQvj;IN{ zp@0}iGg#xwamsC*>;;69zZgIerm+uz+-Npd_P>iqy;f1QY0Ocgl?e;#jwTKd&7DU zgQ2q{x$gQ6tq}`b78*5#=~E9|_1Z4wx_Fc=^}bR<%NdgtiJ@biVYY|PAC!*M$_Z6? z&%3_6u2xhDpE^a1MD8NCUTFrVS7yy@Ml9ZI27i%==yWWc+u{zxK{$B2nI}DQ}-M*+hxj*^B*gR(3IP!OcN6@l+_CaAZY!ap;gS z`n-y6EGX-Gb8J7d!NYb3d*ysrT(G~Asb#S>0B?TB)$#pU@@O)`8XyoYiF+8jB52Md>w0PMs5>v%uLY@ zB+|3uub3;wkT6^mPC+_LU*}hg>u3rLWj{@2ly~I{5r~vxKe7zF=oJcz6@q~YO6^!P z(9iOZpA8^A+~gD)ooi!M-Ih?fk1H!vK(Y1+x2y0}9q7UDIz+D&GC#^o{J>SPi+s$Li3iHh)XCpBTn+_AoiAL*}Bs z=_rMfOs)&zqXoNr8@4zcj`2dU?B31gP9|*4F&ng)FxXhw#+0OwBVKRlC8`!H#75}r>R)c;_3FqVY@CdlLqAj2IQS=Mka zXH3IeY3Pu44<1EEQ^J+o&<4gVSNtPsV2xssqrS%98Ujy^Ys4C|@QN?YE;?@|%tTxN zR!5N4{7p0*X5~y8;QTqUwJFOQ_h2`N;qsl%zlcxRCY| zz5KoHs%6JPvx9$qDj0p`dwj3#_I{yk!E+EBmoT4Z-?HWoLTR^SmB&Ho;5`egW<6g7 zcl}_sPhq(UZ0oZqub}e$P4aISrzK$_OX9+tv(I$rby-*Cm%y|6clx{HhJQ+gNQBkV z`Us1tc~G*!{Yr#D2Z5N6qOIEWpUuVgt67JnU5_!;JA@Q0b0InLCr#^|e?=!!t@c6t zoTo!Wf2&eMt%}dT&(<-2J#NCvGI)72A(oh>`zZ)Tkv3GjFzmNSa+~t~J2!TU%&Ma} z@Be0MNqv36Hii_As<2y0Hj{OiDrs~W7|DzT4ZTqM0iaD`U~pkSxBmBm>i=_q2_pLM z?EgKe0?h?{^|K@eCmNQjL3X`QhxrWl(tjt(0{YQjKTy5z+)M@!D~I)>qC-3!Z?YL_rQ7oTBJAH%iUZiS)IJ{Xr$Tn_U+OJ zd>qvB_@#|d<{4f@m>xJ$)04Xzh!d>cji8Ol>klU&0H@Y?F$DTGC3T0Ch3&N&4_su8 z4yJ18>#Qe}V#t2w4j!-m3n6&ei!5x}liVH$*X1mZDwynUXnyzqlPJx=+>&QNUOJ2%Y)1eKg4CzA z>idfKy6vyurIB(H6k5;<2zz4z6-=!<)Nk-ab7m0OM#%g0w9DLU8s0E@Ya6hulD{^{ z+*i|b=r~#0Ja6EIqi8(Rk1{KF!P*-ppYu_N1ykQROkHxFuCh{Glizzum%^GYqa!wZ z^vfmQtNd3NQipqg*WVteF{l99WoPiH`+RO$_tD(p*Q``Ep)@a+@h_Kj@j?Y-3@g9N z3nA|d`Z-kTeKhVu0lmh3-j%l#DlE`ge=N!&;o}sdmd>Y}d54n%9up#C_J#R!Z=b1F zueQYvpA7VOmS!ISdq%XJTq~P#-h5m=jKu{VrrL!&0BOB{*>NV|!X} z|N1sc;Hyo5+P>VqFpvs(rNAx%5}e|L$z;UPw^Cuo@?Zuc3K!hmg<|ic4Y_z`soyGr zPUFOtfj)w5D!$!rjWsM*^Mi1*xAozX|9)@!nED13I|I2}Ed8}X+U)8@dBDeHRI^FM zTK47#ZzKB;S3{$F_2kQyRv;blJ_QQrnig3891+JPCy`>7VBd0g4se@wB%PRL6I1FT zN*(WoaC#5<<{p^|PQ&<12O31juhSLK<_kBea9dx!T+KW`|0-uG-{ZcVzF;wYzQ;Uv z#B4Qtydv~EXxF)#Fq<8p;X9D?MH;UfY92S(Z0VV(jGqvIdAya{)dq?*T2RI_4V#eH}HGh+I9J5V=3V>%}Ml&-NfLK-HdePo5+C3((`xdFas9C`w9{BQrE6Y zpsLVA_X#cKDBf@m%Nz)0A_bc4g@9-WjDHX;z-v}`xW#aXsR|adV-ROZEkD#3L6epV-XPwwZ7XpBAE*ODZZNtC#fx~^*9-=-p1<#cagJ+3Q;m^8}^)vzk;z* zg^eQsk+4mnDyU@%MP6ycwm2CT;fpTcsN(D}X4GH8Yi0Z2OECBlU+{unlI+XmbB_N~ zG$ zL5r<^?*i-%Sh|M%@gRip*%=#*4DXR(V6y#z0A*h?~0e32EQ6+l#3s=?e4*Q%S@!oO&Aprjuvw9Cc((UIbl~ zaThFmHybfaX|~dj0YA1cnO}J*!@k(qf**=Smf!1A|L*_`$~!k|4+hd+?uU4*>$zk>KdEN(FUD zb6lGb%YLfvMRTaxy`cbM#fc-_`+y!ls&#L}!+>E$O>_70Y(k$sg%%DoVp;Mre^Po# zInL%qt^@d)$S;!UkYUc?zBvUK$rX?b zmi(B%0$uIXKnxG^iLstPdTt5nGj#kRe<23qfQaz>R;wvN7Jx8VjP%f`b;nfu6?sVy!e$7#qWk$ba93)oB<6lCPQC1Fon`(u(u*0-uC!U}$qu=G>D*V44 ziGf`hw0BT{F}d()3Ha9~lHi#3_+Rr6-+Rnc2|{msx0Msy+ES3MTxz3z((m>ZGW0)L zp6`i-UlvRa(HFWH`6ntyuARP$;;el?&HnkOX4sMhhz724uu{oKE~2T#nsPEjh=tW% z3$)5EK8(xPmU{{c)2$?GU~Zeuzo01C+k7)W=^hFxra9`bu|Z4vA$kALoQs1VhKdkC zO*8m$dPiVQmTDbVhdrVN7F?}!^0f))HMIXQ(>@d0Fvjqhs}V(3Se=?pO1g4oIohpI z&QA0Jw!szG51XE8Ad&JXK$~rF zcP}CEZ=4ny{?|5Udc4cezF^=cs~khX8R4Q+28p#5U6o7TLN3aiSK}%MZqx zbI(?x&qa;$Y}HNWUo2$!iq15NrUX9P4m1_tbPW2cdHn)b(6BdPz>%J60<%nF$_gJU zRwm|lG~OkEar&OutWzePaC>OMc)vYqYux1v;_kPyf*uexYhAW{7+5=|Kg$ zdubj@cXZimWkGJL>txVqkkS3bQhHfi_)P>X6yL`cK6V+mS4E@_{g7<#g>%%gNlXGlN+a@0>thBlj$*j2*xuR+OewNu;EWWj3;&m*}S(rO{x4 z<1obsU%?NQIX}vicoLb$aRbZyTMAqfLXB!WL1}Qvy*E>I^eokB@>i=@hNE4pz;oC z7v8p;AnI`F2@4n7J5p*Hudl@Xm&Yj3QYt~0Odw~ylG8rnN1ihk(PzAx3FKiYuIJc6 z=Jc^&sY|Ur4zyU|-Dxa)9lVd$WAZIaof|=^zt$W1RPkF@v@O+hiUqcmptvAb_!%gx zirH2tZL=k4JFJQY?+?g*tftuZR~RQWgg{n9rd7}% z)s#<}^^=u%-733iPv1UX#j}$i&{AJ_P&3~#Rs-A(}PLd1M`jmf*@* znN393m$;liQqFkMG#^QGj74n;k2bZ6xQXX##6YTjn>>>w-{zZ&M}2TLkU0tcReq_p z=IOQYuc&}?91q`6kzU4CoRnjHe!Mv~9CF zO-t^#*2znD{rRUVlw1bCtUII&l*zH;POnb=TOpUTKFolxy=W6NTnJ&(-}!9Tg2ikP z&Evnizm>I5`Ai3%`+Al(YS-Y-0VV9AjrW z^nSfhkIDv?l6qC0VGc%k7?=6_`rVa?g*c&lgq{00YvJx^n5g(biE}m+rQso zB-8*qv7@gH^NekZ61iacCSKfWlK_;nW+HLf2Tdq08v-OlYh^F=zLcKMzS?MZR>r!-c3Vn=4Hl5hP%to?Jd zODm-lrupQulrDvw!71XT-)rRuM+CyNXq3ccQZ6+=(xwp(+UC}-GI6FJxd`tpBvmV$ zM)PkgbX?etY8A9+J{VZKm^|E{_l2IJVjv4&3g)tI_jL6~--h$ichWZazO|KT`j3tN zx!h+8zxeMJUxz(FV9ZnUR-6`Zt)y-x&ffpqogR|Pskw;D*4&6Owh&$cOq&&j{kLZw zW|O2ZD+MZ|f-c5Z&Cl71`^lk0b@a*Lw6wMq!t+6pSlQqX*5Nd)ZxJ~Cr%Tdusa-y# zVJ1OKAF2_=MCXCjQk%nptJ6}hcWc!qh+zM>2$o7!@ z*PWK|_b^>t*EO|Sk7Q|SJMJXbgZeh{F;hKChUWZp+M_)bpHO2nw~Z{age~5l$HFY1 zqGpf#z`*+a-3YeR)U0;)cx*ZYH9<_erj?o2qEb&vx^(_xd#bLsUaWxUpGNW{*deXO zp-1;kDR8i5B}zj4o2NH>+?Qkb9_&}Uy1H*iVM>()qna)dw@7G}#+MlWF9A=|JRQ6=Yo<9BN6R(O+ z5;N{`#-1-Ya=!cbO51U>te+eO|@PpNQr8^9>=IRI1!Q(j|`Fi z<3|1^tC?10KrgJL#NNDlwDl*CPrbDj{5Ytp)}oBzmuK~Lk%7wIFOi3FPraK00V{#~ zid~2!o!FUp$=MciOs{$6n#YzDbal{F8`{L}ZZ9h$_su44_u779(sS-l&cCdK&+qmF zu9i4V!;;&aS7|(?&O3$r-f7Xne!vuE4!IqCbDpg+)`bGvG87f6<_QvCi( zmjBmwTIlo80lXp2{1K)>Oekr7@Zp}&yUZCMd{XSfg3rmofENtp33a1szZDL;_#z}^w%$|i^whf7Qu(L6 z@9eDd6p?wU193u5V2;7)slXK(WNB$V^k~695@rHoUq|8m725y9`#PEaPB^SR1LdwAOBqU0GJ zP9Zn1xw+L=cZLp!=TLcrO0NAXT9BfJ%#=sjY(l7r^Rnw*c8U#6wsXl!V2a#zzz%)U z(@sP~$sFB>IfnVL6q1P(xG#H6BZ>D>bBr}US#nR(vyeV+7W zsme;FDQ%f>6}OrT>;53bI8@N;td-tmLD?e1584{Kt{?rvi#*)F;DJ)y=}S62laL~P4Q%{oHqxOdq95w`;yY+5b8y7%-*S@lgnvHN z)}U;M{8;h+WK;r(25@#>&Jq+(MLYP)_cknA+*!%bj{aH6e7r6J^4R zokjDMON+v>kJ9@`NTx=w*h|aPz43-C;nxDJoFA(YlNCm>^+LLQkQG8>UmPS)(!$-j)y#DH%-9-r$veH}###{KS%X?A#-qHb zr2IWfdG|}ne(P>p&q4wAZu`W}i#rJ4NV;aST}~Le9p4(;bhI%PcWXiUW7KS$21UQX z3t#Rx?9-7&SzC!;1w4IjGmwKE-o_t{Qn4c$0=WcA9^=K1bI2uV1L)sR9G}$y2uizJ z{P7=6B!>v~CjwZ4ZRENOW%N$kH)Fb}8mgn4kHd!ovWX3qQ|nHuH>?F`2G{27{R8Lj zwuTvqQ6^L!26S(02!4Zx(W$eRdMp;|Mr=r8Moj=ITuA0I05t}rili6YeU7-YGDZL3 ztWiL&PwbSiC&Mutm#7c+V^(!_7(vBWC6-FXb=q z_5-9hW#h|454HGv{k#C7J;joF-0eG(0(1+c!M%LF1})u7WqbA!(?Cca+jSO2mmSj4 zu{qY7%FS%(D4*kUlBytmCd04ICNd6AZId-YvP~VLu9S_dg6J?}PJaC2ZXDUc$o3+a zS!$W~({FEHp=-$@t^ze7ESlK3hy8!<04uD?VqnS_C4;=X`}xDj7a#{_EpvJ~z1U{c z%Fk{-UXPtGZ+&&JUNO-x^9)z{mb=H9k7e%-xu=s)PjYX}mSp8(dH*HZo-s8eahZx2 zKy(l_a<`aG-&ImrcpqJ2ehoDqZRZB0NARcjL%1~68?P^-{31@x2-0*y#zg?)$ z#_nkuY55zHsmU|+eP7`DS=+=_@mr?B*U=^q0&;P{b<^Z07Z6+jb@xy8h!>rTvo3k^ zC;OSA(xtjm1k9XL#(ZC>f3#MT$x0oud&z26>9~XGT@fxkPpd zlM?p%dwayy(c1Z%%|xhiB0Cv6&o6x2GAYsiu48*hwg3 zl1lOIND)h-Fi;EvenDawxh|sUR^MdW&Al|bDlRpc4))qcKsrRb(`N1l(BC(W?4LA*n1$IDL*rt*n z|L_>hOC&vI;5Jl2MFxG}514R=24iE@w9&(rC-!fj()j4RsKT7UL!X`O$aj@(@xByW z{rElPDG7uX6E&@GOvkbl2VlPhxRAG-@R3-f%)B92|A$62mtJGPP*@dO%f8GKQ(Qqu z)KxNIL!=izrVFGgj@3Zi$InH|b!H`7pOZzGmCW@5J-iGK;rSKQMov$onQ)5c_ z-U8`QUl)E)Q;Tb>0&j;t<{>S9|0|jLk*94R&!gxzQOAV#H8++5l{N9NmQRfGH_E0J zc0nkEWb?(EJu@wXrVL`b*vzzDm-u&#$tVEn2fiaFRILmzL}Q~7$5zt2C1b;Z*Vv$Y z0RJKXCVUb4C9aBPt5uH0gy5LzXzE0|1SUEL$KC=SL2A|`iHs#wNi@hSL114 zX|*uUGw^>z8XXF_6*ty%;HQ>?8FvZeJSR!5ia`^ElPT^0$2=lXt81t+`x^*F?+xe9 z*lb(~IVfK%a-D$gx!leeW>HLa0njnQ_|pZ@2QK}wdFz1r^`YrFYs!s-gI*p1AZ;o3 zpsQTAC>%5}omy+>&X}AQCS*0vnOu@Qm4F+Dc|j%Yf8-_td~B+VAgAtwKHC0xM|AOG zp8vy{-UQJRQs*gK@~j4hJ;0@+RKmQ|o$tXvz`6;Z{MZ_xg!XMzKDGfCMpE;SdOpvI z(jW2Vz#&xNdFWF9r;Fh6|LM#Ma&@ZR#>o8lLzQwd+_1rR$I}SwSWGdetu9g=e0OLa zN&MR`{5(fKpyxemlB{~IV-8~jF{L^Qg?+aV0*pM%tGMz+UwRgRs`_PIxqfRm?V8S; zlrfI`z<0v?mLA#S$mb5T<+aXP*0B#hV*%tw9252?K{m%AM-22M)RpTMQTqL2SGgN~ z=;9^Pya8=D6r+3=V5yw#o#-cjgL`L{NWm$fO`;cqH!Rz zaLFiHEN~GI80y#o03t)11oARrLhf>r{KlHv9cb^IF@6>~pR7SAwRi zM2oEAP3m3kQ~)Ig(8_Sg?X4d+y(pTdhb#mL#1{M?|AMX)UC*VFe@K7y*(lAU7; zaeLfpRBjvnQeQp|yC3a1HT50!nyul(1J(YhKzTLI<)`H?gS+4pJcXf&d}-H@j&EOSlA4x-brGX;UVEZYk$w$d)00!n92B`c- zcN3vE6|qEINV8UQo@D*QjoEE!%haqJs~qb+Wm%8T!VX4pwK=cT;W{FjCV4LxBhy2B z?ETk7$SU(<(qF~Irmx^m!mkvdyAH}WQ*5Kxfko%+pLgbk*jVYXPPHAT#U@1`$rl-- z?kA`C);2f2cE7mM4VWb*!HBUe4PC6Af36=)bo;9V1f&-RH*&mu~*$FYH zrw=|aVbxSEM$&Vq$ztnTI3yTs4089a(U#Q@{CpG?h%1T3cDauxY~Le;^#c^5qSXR? zo&9!jLuz1y^z>&~Nq2VqVUTAlJ(^ww8AW6=*`VP3Jf*iHGjd&#m-%9}pZ{U7{d-op zw+OJ!Zxp8@kudXT{SRW@Vg!dvygiTV2S<2laWr!4!l?3aPJRRosED zr!#bsd&18~x&~%AmPmb776FeY%nt;HgC&X1#R(^T<`EVhrJ5cU3R~$eIB!qY5}TvO zS~TZ%9TrZjv2Rp<92v1~RChYBrpiC)`|l_S?RcTG{wf>#8d<>b7YGW~xO9blLosba zUEJW}mR0>iEwo~u(zNvIBO;A!g5ELq(Ax>PgNP8Z7)h?M;jbvP!V#^#ThXTaD2P{FVYk_$F5%P>+LSuL55>4yW!K1v1I3Pods#*@D5 zf4SbYf4=ih(2oz}$UhF59V6B?0rs(}Y%;H7o@~!JpKbEII4p4OevI%qZ(YxA_H%09 zdQF4-yhAK?WA?*s_K;;zRN5|GN$!OcNgnG`71K?(Y8J`UVn=ZX#mg#zMjiY6sxxn0 zgOpH^r9%26V%6JN26-H3nK?mFQ5ebdSvl{MOjzXy zC7+$A!2;3zYy}R#9#S|+k1SaVfYfCUvFha6s^MSz`@;Y(hEQ2*d77^G8>bz&b+%&! z#kyd}75@7*5c2z-6C~wV+^z+Odz~echEUgZw}E>w3Xl!ev%^-&zr-f;6C2$BuKZ+8 z3$jAG^8B#l^-(S+(#L?8Kx^~U0D!x_p^ZF)pi+sPYZ2y=(*sd`Zc0w?G#xdZi3raN0u)HjU+W8@`sI-dU1YLMZFl?{ZAcg$;rK|G&9^vT2^!Q11W`t_~QOt^8 zSR?V5rJMqn0kbLU#0E@2tMbEJ<_4*|L^h|qQuL31u;;vOy@5DbaLWnRG@BD)7M}Ge zK7(b0RXZyc2U(Xng*2EclCXvQhl2}?Xu5hL8jDjTu$`e5k;h7CXUhl#JVLanzkd8y z%S_O<{=V}GZa?3s9h1J5BBwepzUmB)h@!1B(X}#54G8i&{>qd{blfHY-~w*-&-x#b zy~Ud!xQgKG#Ad?Ha|GDpxC1TOs0N(3cNf_>wmLKqMpp0Mav9Q7G{g?Ep;99ZTxB?x zwsZ!cO~q7}RPgr~k-WcQ0)JXk}zB+u%&9-^!k9XBywcL`_=!(<~0frs(1(Q zQf9ge4;i4&SgrW-C1aXS(*)a;>K{|JMkzuc9gZGZt%K^%3`blcdWKxfVK~5D(X-JZ z1f}{zY^HTV3lm>>3z?Rf?7!A{)I3d7w63sn5@)hg9+e}m0UOJ!$vrI%vK~4>!G(|| z5niL;GTJ;6a7995(W0A6)Mz~PZ*URc$ARg2t+DR}gA$#OLutZ?yK6sYc4;}s3&W1g zZ>;MmJV#iulwZ_;42OFb9+g@?B;p@aoZco+-`_xxI`hM5!97V#?gcnL@I`JxT;YIg z!J;7L9abbJ!Me4>4H(BfIc02^=9ik02Hi%Det3oRyhB09+KUTCCCw5Aw(0(`*c3P< zincu9D#ZUC){kBYJJLz?`kYMe3W~tg-)beYO?(@agqxa;ys^jx*VwBDf;|3xJ}->F zMaX_ttr|&**R5wSQYa&^V7g7rjW%34AwFezoEXJlH~39$zP*IhL^dtdsI+zc4hpm_ zpJF~h&Ig$TwhJf#8Hjspu3a`HoOvS0a~xG6pr#bS6>JS49-}rp_e|^jK1l^YII_tB zY!wV?9V8)Cb}U+c7dY@3btA>A6=durvVRCu|3A1zbtgyZ{1$i7_f*)3Ps~(|!wfm> zEaV)yc643fR!tIjEEn9RH-pcIpPKNt+(iD{>Qa4lL~Uuv2`|JRWpR8mAs?z|N@MT| zPYz99mife8+b>);xm`Z;#YPLVMjcu)6J1Zi85(pBF1+BqluKGJKH3&c!IBgN&sF0W z!vdQYcuZfi{G-ru!jBC}YHW*nw-f1yx!6Ank9O2Wz*XW;Vz^1;kQr5Q@4#jq zLvT*DS>p5M_nc}6ij)?elb6*E^I-|VC+4Br;ISLYh76Dz$KJ+65@q}m!|5m7IqwP~ zw#?G1mHJk0&1rQ_M)PBd-+Vpy3uSAdN1~=noFZ7njskdno7bih66QDIuP;gTFQgU_ z&K))Vfwj5Z9jr*H_kM$xZInFnrY>;#LY_?+T?6O9F?ETU)VL5+5nVjr4f^Q&iju6YxwV4p&AB(D1^@bB(>s3B$xi8~poIPxj>dTBTC-mR z2v1ukeH)^q8R9W^|MvTI1g93CUg zJj6hpXcXIlT+(1e>An1|5%rICNp9T1>F@VxcM>U#JURm*nDPdf=dWAWAfl>W_KDdd zQYkMsP0{bUwuN>TftPaZ7xO|NPw^T5Y#o)#6kzQ)g38Di^#&IRetP={Pt4;R(e!aM z!{-4aT1^Cm+5Xht&x~>6+C5FRA^b;MsejAHOlMKD?LqYPuV!q3Xm2;Msv zNf=Zm6xDwkGaV*Ml(4*%`k zc>NJ4fHah_fa~wrw@rj{pCmULpL6>fl=a^7`RjZUC_+i_uMvqDmreJ=dX188)=cM{*G_}Kzv~Q{d4(gbrFR#{X4G z7pu-+UFa`}kc5sm-+KSJZtEGU*{UP_R{aJQ$ zqy}t6g~WH}#tjd~D=|!bjm*5D&wSO|5}Nn*2&u$$k$^tq#)tGYjSqnc03OzpB~N1X z{s6MMV?|f4IzBh)gE(FLOs{DHxh_@|v$)$l1mK6(3GAAgS_CN&cU^7Yw;_WjU;Veo za=xj`Va^6E=Y$egK59rDtTgZ)FM9^W)>t#S@JsJo*S1GT)q z%~=sUD*fOOQEj>h#b7#o|vGWGH!wK;x}a%*3<^}){q`T? zP;Q6jAhU);l+gb5kqLAu^X<6b1{Q`6b@&T91}BS{C6r+NyRh<7jKwhlrBIb3xgX7&REd1~*AdB5 zh7AT5!Nt2=qB72J`A4E4PG-_*Ei@Q;1i~~n4lJ`?r2f6IxNL;^kMaGggN7UwUr&WIO<3quzFubK<28* z>p;n3=7Lbi!3z1V>!uF}Nc-IlTi5f%gJ7NccN1EvUyWxivvglal7uzoK{TMxc%RR3 zJ(2Jea=vP1w!m)piEUVwG9Qb_7hv*-qc6cg8g2~=kKYg*(;Tol@pJ&A;{pJ^nuQwi zv9D!0rp9G29tRWW9C9j*F*gtt6Trk-V;7KR@aL`&i#9tQ-KO6Gu9iI%F{qYU$+JC; zzUJ=u{a?L88^Kv%;yS?H-xcI8;dRbwW;6fP-D%HMxEGo&`EKo-5qmPbZoOEDv#Or1 zoct)zp16Qf^4_urU2YLq1sx#Zcuwv}BgT$;L%K^mp!wxz*`lhg_qI#P%xVFx;-uz6 ze6Rj97Jwqr8qADiR5_c0#kya6N%|$`KVHamuBdFDfn=&&22a?zWL;CzlgO>GhVxL? zNcXt-<+)9C2gw;%mm=kGsti~5EPpfbb$K?PBIvT-VX;%b98e)pv;nZ#F_6v+>l_ky_$cvwprVo!nLPN zK6R}TNSH&pll|^92*$PGR$udA(&d7q5PcR>F9p4WxthXy^a-t--*!o3%0~E)qrQd^ zgOS7=M!9TJhsl?CztDJat7}$Rm`n0?;r$yjor~b^ra~|xtf^8JQtX;jYuX6PH`&?p zaxxq}&|sg@iX{%e-h32sj~2%$_Ze*%AZEUo7pYovW@$zj_tuJq-Ialu4|Kc^oI{f% zZ~opmAyI&9dh2c=aD1}|NQ*2orFHR=6J%v_1W6wF=sY>)esHl+m*rz6MX?eq5z~8}bkP3Ga0Vnr#G)jJHA$*HkQ~9P&KcKFlt)XFc`uah!d?#Z(sTuDj}B{hbyY$ zoCU<5P!s9{VITf&J2A36ghFzd9w_#+t0XtxqmxcPbCZ&1B>J~EJXS&a6=N~|%NzpVuB?6g}G=HNvT=?~ZbaKO}HmA=xfTz`H z0%8R0jm3>so-?fL(t(r?gWS6?iwtC3=qU*t@2N7`b%}sU|;henA)8d zJDyOJZn+PV(rJJYeV;=9kn{KatBAY+kn=CX$X|~7d0d7QUI)_|i*M0uM3QEhlP?Je zA6;0xVG3=L8v;^}bypQd0KWyVNzy9-C@v?$(D_w#t6rvUd)UeNyQvA*4=*ot@;QIj z%I)S&h8M9lu z`68L?zi+Ttv=avL%{1=bFSw2;Cv5|!n##BLgUMhujYf{IqnhYp^LLU&K6iaNnz*c+ z&83=2-?+>whP#K-5d~v**Lq6cU!u#QhEUA0)ZgV;;)NGG+jbOJ+0W_F^QY`iS}6C} z0T%A-(_}F6D!{d9@|VieJuJmn9hyq4^Sf5u)=`iCLelx=>g(DbcSljLUh|4j7+I2- zY>aXLLp1%#=qjaD>Vrpjry~u!0HD8W-+cAz*Ne|`5AJG3t7>BP-chgzCPW_7*-5D1 zhuO==>1?mS)2r;FoNUdaAo7N%VHTwm6>IyQ9+v4GXNBNBIg0Whxbz$7!k@I zCAR|6=SSzb#1b^#N@%C%s)l{G2sj_d%(neectY96`jFT8BMC~#tBjfIZQ=d;UcCMD z7~n=iHovx4!F1E&gciLUdf`b%C^; z!E`07l=c~?G1nh#@ws9bMjljd^O+G8pC+?mR^FG%T){14+IlTz(MDSLp@W&!^8;DI zqzaxg8jTgwyMs;1&n8fMfpFb}2La?^vb{PC1G8&2VSpjC!`JQsn<2pXVv&N45)gfA z2Uv!i#XO`@TzEz32(r(5B25?^*ZcZp;cgRFb+g zHmm=o(l$uj%$dcd0^sD_A~}zCky4dXJB4TVjKS+E<(7F4+kYFyRcC>)_ zY+kO3tJYuFGs1zCKi4jI)v>9HyVHe*YKRGzi+7dks_zqD2>kxjMEaihwJ~~=cgsq+2=m7YX^x6a=b6#uwj#20 zAA6%)hCBG-I+2Vnc!nS%9xkTd4%K-X?Yzk6Ep1c~3F5Q^oIGn?;s;?zvtw*n;1ijNgk)M{NteQ6&F3~*5H7!Xo#WB| zx@fdnYr;}Gw`<7m77z{@IJvH-CUPqtE+OGPPqdG5&Wy?Yt;NIOh~sy|kQY|PqVhrG zlSlh?)SjIWSuqm9pFcZOAoCllr?}ov)BSx4Kl*V3ZwUJuz^`I84J0$wCjQgKcTr~o z_@Bk?p)|@P)v~2bLncwap;W6RIhGsl`D%*pV{K=Rz3~kP5K)E!QSE>&;f`mDQBUAr#!^V`*Y7Iy&GnRDV0Pr}mT4ISO#B?VL_U%wv$<}L zLYTR~hV~5nPWxlydrGk^-ufkmj^=naJ0+sjefD?(%~lZnv*RZ%Vn#S^_}+Vp zs^qm>Zd_y%i?ylJiEho=6m8)HjyAwN_-T51^Xx>#huv<0Jj}(>M&z}vGW{|rk!*Mw zB5Lw{jBZ~cB3&g{)Fb=TCb8OC82rXRHQHs4P>K+K}lI zK0>_3hwofo9%VV>ry;^qrFQF|lCn2^)Uu&l7gzo91AJMhnyk_nNJcPNY$LDfmeP#EZXO>gM~kwJX$3 z3Su{ZAZl~YO3$TV=m(B#OQ7Qk z=(;}ryg8qb>(vik=ruA0)98}}-NNo;|8_0;2^rH2>x0rW?iKFaPlUa-He;-jg*F>P zv#Ef}(wD0D>ISA0({%H%Wk?J+W;!&dsu4^c-4#YjFJ3rr>C7??WWNC+94&wB=TNv( zbm-dwAj{Xo*2)-=UKoI{eh&&03}q&Ll6vr=CPpO}G?qvS$IN{gX+Z=?T4RHGmQKT7bd8ezCn#4n|v*j({c%RnXRO}Zcta&Z%(lK&qZEm+R+|DD!D zN_(a4|C`oBp=|^hn5tgJ#_kACb~sy^4TkDJsf3jjRaZTJ!`U~WLOlH=#xj@2hJP3* zjtP@W05}Co&rpY%RE&w(O!hQ@U_Iu<;(cn6i$Wft3qGe{*sSu)$@A$KKm~%@aJB+! z4-}1VR;gjx`wDvk2!W_a&PdUKj`8vu|7j)kZ85N<0o3>yjaDT4DiaJrXt=-tp$}5_ ze0%ynn8*=vz}4ybBo&*jM{0v0dK&hBTI2ca^0R+EpkT23hXV)eQ9Y?UAUEIty;Nw9 z{F(n?5W)SAINi^*u|^EIxC>90>00AM^0fRT8xX3!PWDIR0reDn(X8Bg!olR^SJ z!&8Hm4ZVKmEaD@@xpm&cSkd?Dx@XO%g#QC=l`yl4)LIUQuNruCML+vp=%2OrnD;P7 z((s?OIs8%UBaKTWb~d1+c!A}UNDKyQa*|QBVIacKA4kIE3v9Uv5`h4y$L&7Q76@Rh zY8FeW*N~X%mL~y_AHc5w8ZA!*B4SWtq?On=V)gwSpoIB!kOy7Xp4J^1Uy9fR9k9p6 zU(Ob(X%d&)BJAu4zK6k)Q|xs5-`TyO+T6ugH+;0idFq_fawd?yKAObx&7~O zCMTRvZ|dFbhe^Su%6$b8Hp_gVA@0mir4Kr5ya)(^F9Y|adZHAu)q?!67>@oQkjm#v zq%6sxRqcP6_-MGa?>Cp-a9IHFjQ{Rup=jD3m`3|v=Jr(DgcX`Y2W%nJtBo(|X9~T_ z!TbUQPfKJusTKiyWEvD3;(6YvR`zK#Q~L7DcVy6U?F9`qS7V9^%Wj=JFI9+BI(HFL zRXKA0$UF-~8E{OVSvbDFxcFa~% zN@Wap{@Y6Vfw0zE(^K_C#p`CdE}B#>+h>ejImhDi%>G~NCEZ@iUdr-s^}pGaP!Fd^ z-Ed$GosB}|K_YvEms4Iu6(3}KTue6y11$m(0+XbAA{yq3G)xy91HnfFn$)FZ$MIRo z_o}lc(s|9FQ+w;!W$+KcLi!WH^#i+XL^&^>3EcSbQ3~|StZaTT+Q)$;3TCF@(;PMiHZf zg;VTkMMDo!K?BE({ANWvuqf%DhkaJ4gvRw?XKB}zsOECsc4O96o9gg-@GB9-mS*$` z{Fl>V7BUUUuLIUZvMu;r)IE7O=2EPxc@#SU3`u}Pwc67cda!}q-fCg)>xPY)2H&Rq zD4j;m0Oev~6eYAq-WkG}Xg5q^Er5M(f9K0q5Ow9RJWGMQ=)L|Zm}-90?t^PDo7)t^ zZ#J;wNBi6{1Jo%36LUMrvhosNIuH6t&o}aJtHEC@rAlk{ODI^VPUNp95JzIzHPsir zZHm}!|CGW)Nw0dczQT_@-FduK18KF8@^yVw)@YQT{YeZZW&|mBt)Xb*Tz*bTJUl^@ zX^}~0#Xr$x9QDq>^UsJ8;CiW@pYEwYdEh5Y9_nrn+0b`^H=D}5VT_WYW#jd&QBLfP z+BiDVIOmYt&7p=<5wc4F_7(3@B86qr&b8L3egwJaj1#sEJJ>n6IzcT)m$WU}T!X$o zqs7F>EPhs`$hVIRJA6@`b>GT-B+gz2${p(mz6uNp$|5e!cq1@_u4{$IZPYL1xs*ND zlKi?qtnM=ykW&FK8O=H*ZV2=g@-a!n6?-vOw5@hsT8ba-;RCO9wDqK15itOUVf}P5 z)d})p(oYx43Zwm{g@N`fsrl>a9Vyk2)*HTV9bb7U5>?8eQ=LP=9ZDURlCGw&GO&#pzMk5y^TPbRJdqHT%q`TM{CymdK+PYLiofGD#u=r316{_Tpy3rTP$IO z`HpNn%!+lG4B3-%w4c9}IZhN4yT!l1@V&V0uq88od{BuRZ4hSFf{Mw^iiu=WA%2L9 z%R)HI=3FhFC=PcC!ZoSm?7#F}?2O#q<^C%R=n?e;lqFP>WhHDX z9Gnm{=l@i+(*NlKo0j+q81Or9JP9b2a9o+oD_CT- z>m0cP2hgQI)h@qhEGX@z{mm@Xt4#2YN9Vzm>1ZHG5!Xnz4eh&FSA}44@VM9^3yEr zEV)}pO=eCGB<0%Cz*4U>Cayd)#10K4p`6mSvQ^FziRES;Kk zz7eU|DRv6)_oTL%)&TNO@7Wx`%pMTUU8X+v5De>_nZ1WA|Acd~$*yQu*z(W5^m?7k z*cSYaOyZC?b!fz8bNPC9qVZE5M?fHo=aW1bK-^mXFvL~Ffr>9pks#I!?E(CkRM3@0 zECe7M~9qGIQC56agqp32F!sB1%OcX(tmafmUfUK=CHRl zF}2_%fSfJktC|RR_a?g~#N>$2Rp|)O1hZ2TFzNn!y=0MOl=61Chvq-WB0UjkIvfXX z8)B3cMx8tUOIdKQf%YQqY~~tNr9dd{PXjA@K|v2uusTB~5{`1`!DcyiqKhJpXz0XE zMSqU)^=F_fUR_r`j6HuH*=_#BeWIT3D8fZ_-^q&!^?psr;mO@&ot$6Qf8Z~p89a_e z{c`GVjN&aEdof4SR|ha20GYpZnj-9$lT34O-#17tY)$g>tC#~Z#-+A?&*9gRzYPxR zy#s0K(1Y(ziYWYjaev2IGUo-)cjvmAB(Jp9HNbONA;9R+<G zJ*(9h;Vyp?<{OY#JQNDC5LnI?^^Z$@D;4lZlMs+%l(<4bemGl?;^RuL1Kc$^G!c9n zW3)_+xL+#mG$*)Ea))U2fZ&_@l-%qBbg^(|)!(`(x~+H^RWob}AlO)59aU7y&rUHy zXP5^rQ^0PB$G4po``RFJ^~Ui&C(?~{t)gh{Rr0t?RK<1#gfWDoB>De1YjaGb)wYZ~ zsQLyHUo@w3cU>f$TE8;mlI|&t_We+n){76U5X=%O)w|9B*DFwB{nF}>61)VTr(J=L z)HA?u6-I?cg9RV;PXB`OaI%)|D?+Nb9E#<{=YM3!lzHx zip{+e?-Sq6C#SH$0|Q$=;XIuH5F^H_QSzt)SES?=vhs94{13*=J_bkI83c^?U;c=M z#7}i|A3@Vu7?eN0L*fzzxqyW%LlY@YhaD8xZw1(UKvxqPT+mcT!%ADpXfu{!oJdo1vp!yUxO@8Kpi`YaVOC{2$^8*k1#4AR_GFxZ7c}{~l^{=p}u>srP z8v`hXCV$%bQ(fkqhLHK+WNA-6)YoH00&q%u`Mxe?W6b<{D;TR;`Kg;=y|Eo-FQY$* zKwak1av!a^C(9RDg%aI8o;6G`bP2;z^~SGvTo_N^1NTwSQJIK=6LX>)P~Oj~cLXvA zo?26#Sc2A`&m1~U{1X%eyujzGla4N5=SS`Gf?>ek033QlZZg;^fOvcIf0AUF#;^~2 zOq~Ru27toR$^Bo6G8@m0fRH@`RUL01lVh*1y&DBDl7Ic zPgx|5Uv)xrXBTg^ADjq)7_K7Re?Ha#kXcRm40nwK1DbUI=~=u>L0+y^@WU_Ul;7oc zJVIBIhrcUZ+*SLYoWMuOrRyr(`}5A+`^6#ms@l!+s zS9R3Fvzh~$syRO4hs6MBq4tAS%H}P=yzO=Jv=jcMQIk|(rjUg3+SMLe$hkH&RiwTz zszVUZ*fsgBb3%68PBWl|ZRkAQdNrcmWPcpZ(#PoHE#H$U7$4U_!?3-g zF}&ea(!(_G8+@M(6avlFxy%4BKs#{f+2(Uod`G(40cs5u0RZfaOnYbyb{PL@I5s7< z^1gZZ+WDg%plTP@nmrQsgWqWAXizFIK|oqHfb5$J>Iy(*nkVB4v%-Sb)@+z4d1a|3*H|IYg7xMBA%bFXUujmcrz3>n6gJUh^&X zuY3S;PWF}+-sSrivq@rDU#aOW3VBTTr6!SHaNcV-3cDn~D6r}&uJINXaVJ;ELlp`s zFr`ckdF|bKsL8K13qViNPpjcEubt;vO$GDxV_K0yrl)=8$e9F_mQsFk$a9c7Gu7Ce zpvcHq1S=00%-a`UEm(SvvKmFYGKeIR1>BR8J3q%JQu8s$Ck5>$EUYJnd;HsNYI63o z_j%~H)-injeLG4Sy!E}S+OKBeqD!|^O^lG$ctL2Qr1AFniCNO*T+ta?pTYrIm1xRnH#)a?`^*-rkI=wNK*R$ZHEsNv!UhYwc^ zuS-dXxZsrP?|xaVz1F3Gg9=dP>y^og+)QYH7yQT7z4;uRZ?}jwL#Rz6Qnpw@*Dvx_ zto)=K^hRdl?-+XwAT=@dm%5BZ!AtbBm2H~4Np<}0>884ll?6&L(IMTZt4==UQcTH1 zF3?$uuZ{t!gT{aQ?>Tp*{8m*grMOh~C-fDrrK!dnL76h+y_JnXPv>=sLZ4>#qIUbq z+ZOR#@s)`80tnNH-B@+z)66!@c8X8MC|SgaNe^F8_1p9&v$D0~*yd$S^N^MQXpzc{ zZL$hLdKOw#i9o@%e|A_-Gd`yKS1JxGej9A?IW|JV$E)LCRldGwJ>5Evl4gMzdFf20 zCi=AIrIt#X;1t39daWWLQ7HCEsNt+xTaQ;^t&X4V=RR?b)(A)P?*>{yyDpqrco!Er zGU4;kEAu6IiZMmNo=c11WfepRD6OXM(I?jOk*PsI$HGXHHE9%jl&OkBQT1Ye7c|gs z%~ldSeNIuOuSX}Oc=htig?Kf6sbEL`@sYsH)H+ zbAR;>R<5$y*3N{K6~Yf_yZBI%rZqJj%YHk4gT*anKnyWr$VuYh;UF)UNh;C$^f)Et zX$cD1zpquDGZgko4G=K}3CG#2AaXlvO6s&%itPs_<6g;ieUT*BWftx>OpQ-B%f5MJ zkK4duXNmSGi>>3|5S)`i3DGMW98{SKI3sQkZ)R6Fm@3+G`PfkpoZW3-7s88A zUBDsU=0}yUL^4hp?{NXg%V!^uANe>W$fS_%STnG6P5ncI^=Q0ZM3i=Mxq)>NRUxr5 z@q`3?3|n*cA(SR+C3xGZ&8~Lu6PEj2K8n4#4-b-_ZbioR1E+*IFreg?pJ~ZgMAMGE zcpqKEwMxukR~jY4cb~mqWPm%o*4WImM=0i(qiq;FjJX~Hz029synIfxyU%^>nJ~aV zbA&p;f85dHSx4xZd=Z>x?lm=Pk1Y5ue*h-TH!*rBODo)0H0Acd_7!53{)$u!d6vsW zOv7|Cc0_e(SS6K9`!RqOukS0Gwp?g zy;gh{K1r{<1fJ%u zCMSEt4Bsnyq62jZ8!6eP0f|LfN1II{C4(A4;I5{v|Lyf+`SjP=6g1Qo_Ro8 z{-Y0v@@3rtVt{SKMGUjTCX^CqY5C2v!V8c5 zm}s0{AosC5NvE;i1e=#Q*n@9?hR8+Vf~aUva2g}6u5^8H-QdQHN)l%{I`Ir3PnY&( zF1K|`H0Q&gqnewpPbc;Y{@FxE@114?c*rAR;pLY&3Osir^Ld=}Gbj4R{n_12V_@5{ z++v?m9MV|pbFAk%^J-t+3St~y*4?jvKnvU2YgtNxc3{U24Kf)xpAgByqLrfP*lgl? z-!|?={Irw0Vw$jpbZ&lMB*G6v9$IG<$ot-tM2%<6&r~uzboV|HKNy106!hI-9qgNn zYwz}VN|C1fuPnY8AU# zI`NFa)jy`<_<};0zEEsn{jj+HJ<9Ta-}#6u@8GMqaQtGuAB*yRYUZh(hJfndwMmqa zY1Cg!zNj2UZW0m#fm^t*7H7xHczzd>{_36F+fZfTJ9R29qF0nM9&O3-Wpl9M1JQgwci}D!J|TQ zCGUQ<>Z}#&BF@@2Xlv=+%&#!2jYlNdo8fYg76(2|vB#dvi8W`x`m9z~=;to9TdMWm zQF<*xLDFA#u8)QyV=&=r<=fi;uLXa#@l_b1QH`jlx_d^xunIcGcaAT9Z$-TIk>`70 zE}H{k<#saGaSel!;s@i;Unpo;nhGjAm}o7saEru`HMrx^~>xH0y8%LC%t8C(~L3lEyN_L z%L-D=K*yP2Wx*?;uDYYNyZf8f?)`6Ywi=2Qy~jpV4)o`rmet4yqYq=x0wW!Wj+kg9 z5j9nmHK&G#FM@IKyvNoyNKx=!@|tcoa(8~Jt@QX@Lnu~iEFisUDz3SBZJAMI$pAa` zZnUbI{5^Z)+*K;4AZJ+mKv{q`Z|VgjZaL;D{Pc$gzA?cOo5B}I9&dc~doaaaIsVLn ztW54)MT|u)Q48-2NxBJ2jT=hJAM5!ShI_8nwQ7EL1tK?V2Z?$j`is|k8T;^Ws_1Q@ zbNq%^H>)y+u87YPs|e38f;TbAE9YOt5k21_wKgn%AEAOWvNrJkf_qp-(884c z$nBvOWszm8HKKY5=T9D4iD+7SF~SZP)f6%vLo?b$sJY#HUK$Vz5@|DM7n#i$jE8vY z7cXT50Sm8gIIbO)10p@2(rj(B^Lrs+o4tqICsYpINoiYFNl`IAX_O@y8WbZ`jcV(0 zTWfT=;p8>3-`}e1>HY`zK+yXH+uK#$)7mTXR@~U+VNZ;07%h3ZTo<$gGSZtZfcajG z-*X?HlVyl?s#8`J*GVB)&L`QGGCf22xK?V{<@}wa8~vcmD8v*>zLQxO%K=| z#wA!jf-Vxm?~<%8cm~er{wQl-+r6j$@+c{;jqUG)?his^OH(f8sFBEa%+rTVv;$lf zioZF!FDR5<4dR5^}%cG!>y#NfbQMG95eSWRwoM-RRuc zdS0M{#F9|AU9BMW@w0^q7;<^VP2#DUs#;M0+_2hmA?S=c#>dX-2 zqWIRHJ=w%1Erwo}%2Q6p$MPu$-_ta->esuoWcTzdOG4cYPDQ7TlwWnKSW`?OqzerY`wmGBUQ`JVAwJeRd$Zl+*oe(Vr#`J zKMQdQ>n%r(l`hALGq@SzwyREYX~1^Tu#a9AeFtnP81qBjW z8v8Wg%OH>%6THZU+RT~i)iHROje@l-2>;8nuvtayp~G(uLk~dOlx3*$K1`5AgU{bV+s5)qzko=ku8 zpvd51XP=6baDA-uy!)n2X+Pm4ghN99E9dkw5-me$V3%H6Z#}yr)J9E5#WSh$?o3RS zZUh~6xot05r2CbT#kWniKPQvssA|{mCRWFvC{A^HF(GM`E!oNiy+LoCQhc6T?vigi zy(Vdk;PZ>4Dxq?d#cHQBz7jTHM6DSz9Pu;0H{Zzw+ummix#}^`MZZHfKx9f>wqu~1 z!kG^qPes%BJqeF{ z`X=c-i@8TToUTjU8Ru8)$QHtg;DV;u8jj-hJiD z$NVmGJPY15wbwFF_)JT`J`pg<_Kb7O{$1F0j{fi7#KtW8`ZijUprD` z^zN6D@QNCkv!1(x+;|K5k=|IXVL~4^!DMy8am=I}b$1NV4w6Cl3>-Xz?GrRCl++t& z$E(5%|DRdgXo*YdL<)+@4HbRAnG*Mp=^$uwB}21$j0qZ(;NtU~*W@oeKIGr;qqRFh`2hk*5`|SvFY{qQ*@8^~8 zPqKHzkS@HS9s6c|CMsH&m0-i-t8Cv+-T`;~G*uklM{<|_*ECqBZ}U3sa}_=d*MGy8 zTp@733j>$Qe(l4vQC^VhdUm$_=$zbe5Lcp_(Ch0}_Hx`4#;GCDYJhvC*Lc=UQ2LhH z7%!1*hxWI4uir;nRwU|cLEXyJKwN76=D2vImo#eZ$2cb2%y(HZ-#Z7I>{`GMH9k)4 z!oMgPXvFzgn(j?G+keChm#n2$x}lJ3UlwdrtxRV&^q~HXXPk#(->Ftf%%ZH1b);KG z)V2OfPn@8_5QoXik4@Jnb*sItZ1C$ z{ibKRq{GYs>>5SbWn5Rp5X&VO+aPXny2H9pPw&*`XB=?EO}!H|wL1mOx#L`R%6FJFJf zI1}`6$zN**#9HNt9KpCeAKGD!d&O7b8f{s)xo=-C00nd`&nBOtaUiG>oNjhWxhI4j z3mJO3YnU6J^F8L_7G9#PCmBIy5gyIWHtwu93p1Wx0Z4^;IIeKDI$2>^8jpA8y;{xA z@Z|vUrIjzlpHm~f5u9ni;z)db1and%4{V389R1>G|66)Y^{2&X2~Iv*&N|TYKv`$j zx-TH*aPu}BKULMm2Wwq8pymB|OayVI-Y~fH^$KDSBUFMxQ0(&qhm%zyL-Mu(ow@7fPwK&Pe?>9 zyv*ADH=wZW@6rBTMcQ`y4-d;RrLpuHm)LvM{Np!^0k!YaNH<5MrlnMa_kzOsWi8n# zzpYV+ZU~)8-p(M9pBcCer!uw?&HaL1vteuCpzZeUURuYU9Koa}c$z5+(M@;@&;z#9 z1g5BScO9@+0>?v%Q#`=9CKnbYr*1J9&XDoV$F)si>p11?br~|_k5D6yg_9508Y^T1 zAHB)yC{A=ACQN6Z<3sl94%514SS3{%@jTHak%C9GBW$OM%s!Q1eA@zs?YfWJ z%r)4+(JG^uUkiJIm-1$b5Mq-Kul*C=?u1oe!zPP6g8D6n_+I$8&jSx-3V_HZj0Jo= zk@pEtule%A!|3JR8^5zTxZfWQ z!}NPlHuADYI z)>k!5RAER*)-^_6VoPRTE$x;o$$-+FXKfOge|+1J4p!eRCDj4Eci=ff6yj`nuU_L%EMcMKNpChD#=!y6M@>D*sH!e~DGHhahxX4egRvAf=h5Y4K{ z!I@7q9$p@2KMSOipC2mn?S#cQ^&I0G6G^0jOXPuavx~CIrJkIRL)3%Bo`<7uB=_vI=9 zT=LI7lriCfmUy#&wuo^pwxY}V&Cs=eir7J@$ek|9(@6^K@=|iUZupNBn$nnYa(OrV zk)Qo`FC5@M3lg|gMO_-ylLWSg6NK&^L~{l-9NfJ=QLBvzSF9;w;g8Foeg)%9B)#;8 z;sMw=;Fp>Z8>v100Sw^3e=tJ+{r5jVJkb9AkA$>&a=P4+^)|28&T@nf=zj7<8eqJLYZL08_9;c;v(D)`&j`^~9coy##wE;c)!(8z`yLbVNl;&4Qo3a5Sgzl-e(7A`F zWh|Jsi9ka{vyKBqpV25rS*V;9(8Gw;r@2G5|{+@aY+MHuu$-P_92z#^mw7AWlc|lM<@AQa? z$Bz|9Z)3|tZha%v)68k*4xEa}{ykav7kI(bEPSF0Bh5wnvMRq4lN)HuL?>7uAO5hn z+iy2xWcY4y3PRw`kQ42UA5wvXOj`s)>-DF!Y{CY+%!Z%(@-F3lzu4$y%p9E~N&y&K zX2TD+LGK!h1nenYH**mAd z_mJo=t?Wd+K?@zIZe$9KqbL~&c)bChe#QcN^_7&|B-W^-Oj;mlC@QTnJt^uEA1%bB zG&kQ`N+IHDlArCrCjX;Ss~q~8&RxD7&mjmXe)wAu(RqAJRw(tup9Ex+@+DVdi4UT_l{KoAQiWo+6qRCZCbstY0dGH-W#NTXwR$6KxUXe6 z!P@8PM@yeip_t*-Dk7M`8h8k>v6iMH9qA~Lj;hW)weSQmwW7uX1Mf1QX9+JC4GgIF zaz$p$jji7&4tM$m6B-+uh%%GriWZ463@&4^B=}8yd)ac0Zr-pxcPpC$xjB+b%oUYK z|8e&*2z05_v;Ide@b;MrMQ@|J*IOj5>n(pD@ZCw)QJ9_gi`{cmJYRg9wf}^M9K`Qp z-o^X&gmV_Dd&sLsM|9_yrY2Keshpk)&TN^UA{;6O5^VGT&T|nUE`QRKJr|y-|Y|+oALZGH9Nq8V3ph z?8MU`voBh1nU6<17f}p!pa5_TR48WU?70ac;7yV|cWa@gH;61NW^&x>m8;Pka=}i9 zcG+EMa*)bnTjuC6l=()?f$DTn0+; z2Tn6*!`gwc&w}__irsc8vB+eylRcSF9w!}vS@R+B^4f!Bnc*qK1gyvV7&f_7zQRn;pjd7;C8dGRm zZ=YV)>0iy!unud@CM``3-s~9YVoOt*WRYiCuMg$fru`_XaGH6^QdDU>;I#AkC>fF; zv~eC4`dN(_!-V}SmG8?j^ZUvWDLQJdcN6tV8-M$BDSrD>B9VfNDK!HCYGY*IQs&=_ zSwnaZET@2Z=AfOENAZxnm%N?$jha%vr=Stu+7d%{(#tbvQu%7$M}M=gao!154wa@& zjuGthG(Y}kS8Vj#CakMm&nz;o9~&|)yt^V2%$>a=KH*zL;YjvQo3#iqu%z_2@>GJE zfmmW@2mHr=C&b715OW++jghd^b~@42JQga4sto_`-r3B{E0DomZSX06EpXI|D}+@E z;K=T5fzEW_C3@;~J=gNW03<7H2tan@1p)9oWE#0f2U;F>rDWq0R_VF_mGyf6v*>&0 zDUcK$lVF|ql79-~q-w)S3{_*^zMag_b@Vq?N8(m02DvWZAR!T^t^wwoH+{*dA6sHf ze~H~UD~FGr;CrA#(7ub%M2noHBzqR$_=n(XU$_0PGm8Ek$a|=T=-8f@*eYsY3Cdr za?`Yuw|6P;?;k@`Z!6Zvj~r6W<$_+niQz}$dD+=JkJg(pOC=ggIF#HuCLK3z;Ff1)ymXbh-eaP&_dfw*!M34j&v(wmaTne~hIxK%o3s90wjXnnWBnhF znVIAJyEo(9-NFVx;(VQVcF21%D>l=LiIbOdjC5VNpVf;7iQ~fx=R;VnO-o~v_-R&q zQ=7d(ey+)XI?}S?A^a&eV;N*>x~!LYfGfUTXo4IP9%my~h`kCsOeM3t40A{0GT~7% z_%o4H-iL3Pyt77BS~Pt8%2a<-Lrzi>4Y=TUngfjj_NG}@=K84oeA1Mf3eqn;JmJGM zgo6?R2#qaDX7%vh=VyU;t!YF|5aR7QPmV!nQ(Tr<^qXl}T{r zl?@T*l{p9Albc`7VVT>zDt@TrT}*^Nzy`#^entJAcK=pWd0K~6y}fjXyQ}J{r1Zr} z5sF7si&Fy{c+bYY$>u)&h9){yD0uu$SbDvGwnTP5`l$)cnC)mfTk}`34%7nET^!@v z>+du*uK-720)}%n!y~?6y_(24m`X8o1eO_ad7x@;VAHLO9v&FZ{M8;ts*Xia- zEWLxI*JxaJBT!!P)k$J*-=M@@zps|YhUi?$H-*_G;Tq>kLguK;ZPotd#QN@Q<6JiK zsI<)VADS3hUpCdXgMdh7CaN)^tiUN6E?UiCo$Ra-D(4hSsJ`VKAuG!I=^SOKCk@Br zu7~GU3e6MA$@f+Ifb*)d2;2>}omBq?tUqjSU}}y@nBL?OtSmsI$KR<UZi;!sbwu^Vr*jH>e5zhOT73{{n>r%68jsJFw2Qc=pk|WQ9$inNdVy*VdA@ciU_1GE z=_H;PP-|YYCI17@s79>SG^(UzO|)G*Oo_Cp6=ERfwx=)ZPxtfjs9LBXSg$4bIcl^p zpWLF?Wo_=cHxO355J@4K^|Q2?CGI*C9Dj&U$ojkH;~}ipWgC=jheehQ1Tk4DOpK4u^5u*J%mDCuht@`s z;LYiji|!)$PaOGJglWygXax6}xzq(X#ecCvW{z(un^vZ9VtohhzT@okRj8c+lcCx1 z)B8bK@BYgtBbTz@0};z)Kb*)zq<_AyH_Z_Z!L{wf^__9GO$z_q@i4U=|FQ1<;idb< zma)V1;C)laf_Yl#+>}Y3ays!{Ugr#nayv!ppc^W6Ns$La96`+}&8G*sH-8mDluS0x zm2xAMwr4FQO|fa*B~g3`FG03v;2cct(^qwnaN?CV9Y|?>z-=EdFOBjnC18d|;YdCY zrKnl{IhciP*8G4Sesw3%_4VsoDx=Um^9?-v(CGhN+XUG>y$g?cGtylv$FG*w7I@r#lDVF5J7)0>6~U%Q%WV$2ta zX@!1TtM2)Qg}1k5bZ=9LB9Q6F5BMmTUxz&Imok)cI80J6bYnR7ua6=hi;Z#RyRCR8F$~svl+~H z`7Nl2@S1U=q4V3S-XE#*z{)rG>^uVSBmgXdJ%r^o9oA_l)M`1M&PJbn1IrU+eD?^>!BmqJptHgg*IY zXH`)h9Yo^ViqV)YOz5*gDU3==H1>b=z6p{mTD5DfFxx&h4z%4^qE?5{Hm<2W_!v`e zSgmcwqHQ3$ga4us9qh`Os^Q$3RJc`t4lH>b=)HAhST`#{>eP*gn)s>@UWXkBO$Mt< z>wZOrTHYdU@$ciYMyp9QafEAuD|WZq&EPwy70N>-s;%C+v;lJHS6`S@$5J7R>n5?U zZ>4@z80YU3+q_>kdt6b1(|eubc_hIxr+2zDV>KiT z?aa%|`@r%vRO$zMvF1W*#f*XKOm5T|vD>^^)uu!BKP%Tc5tnx@ODr8))(N2^Qvlv! zvkuGLa+n|>!O)(T8Fq0o{*PeXy&lys>0?YPhLQQ9}H!6yxPZ7*|kT<@d8S@xbXR4?bx#1L_}Te-2Y;{hH)6GPFm zd!%v4;sJ;6ft&1Xj|=CHXJ)yU<2Na}S+_E`R|;rfPtRDTfo_PWb@r!2r2JDHfYUC` zCg|lHxetU}<#Y`p`AwXO6C#VFdaxN1;zMJW>n#wY! z++it`JtALaUbRPgx|0xvqKMtiyVjcFP~uiO=2=e{#rGHYjx9BOy%(ZSQ=ZgsY93$y znCQ4RKcC#;SL^QnNK9Obzup;0$P^KpCZJzE7kF$KYI7^qVoj>O|3m>GRLBH(AKR46 zV^vns=+8ku-X9y&+1dfD-69Izx|8pk@{+7|*7bw`cFw#DnD)>DN#Dm2nJj7#(HO*o znxJQvt&QQc9BxArf+Y#h%sop;hJ?GV>1s7=(MvPT&O(&B6+8aYgf7+^X&55CutTy$>V9#X_LHyZ@6!8{)I*V?{U=*lX+Y)6fgnCu!u$j_zjxq;2RO(CTwP~!Cy8R zL2}kN1VLy!QNUu(uXiUw*HY%tg!hAzGO4 zPd7^_UuQTtXU^bchrYBc*Jv$F(=h~L$9uBh34S%Q3iG??9GL%rkko9KeQ8K;^)*3H zA9UKqaUkB)1eStIeE-0MPGl;1M@FEsgc1DC%~AFN&$%f-pasBvu^S-+rny#9f2XFd zDI;`dxPOlS7+pZ~P+vpci&u^F)m~mtx%jg_(Z7(T{-EkjM$IBHSpA%ogIu_!0v8Ru z5L(63i0iN=wH8v4C&JK8rgBTEr+4p;pkNqan$_*SCCeXDkGLYGm|VG zP;9oH&K`_G*_YN}CuTCsxBrX0_Thx?|CMSI$L`gzu`5Nw&152{GKT>5LR?n-Qa#aO zmPd{P%Bdicd^G^f`p9b|GL!z>Z2Cvh`FFVtEIgbl_Q3_RznhS7xk%MysZ6C6V?A^| z0d2Y|b|DNsxOWQI>E-=@{TCvMLQk@oin6G`h26Wc8K68Ybd_)UfTVQUy80Y_0ALvB z?L=5kQmV7muCxF`30$rPET%T|u`TJD7P1PNB~bF>7BN(PQdgbuq;9a~U7-SWIu0EkEfWWOh#TE_sDigF#a^mZQv!krBsy~vfOhQ9alyV)MwFq8BvfJ1Hw13m%iSbSM*YA?2 zlgqi{>UyAXtS@}r)6(zwb)1ss{QuzbP^$H3X3+yT9>HE3+?FTW(5_8+Y@PX3F|qtX z|F!=HY1a8s6gWKS003aPmD}~t;lI7gxEwSh9yKUH^Ph-`;wM}zw_O#=PNL-1H;~Q^ z$cxQ@O&V$n0hAESkjtS8mx=S^$d{kj@y$inmabv{Y1%q|E)5J(sf&ijAmCtlRV1NU zRmGRqP_?0)>r-yBn_ksf;d0TcMSm9;WaeJulp7-W0BLwf0X}JUa~RhB^wwduBpm#3vl1n+P$rbuq0 z7WVg+wj0~uEdoNsq}22!^32}UWaPy61-WxyuptK{NPcJCZGlJ6jluiw!h-@uR_!%a zbe5Zp|C&F%Q-~nlYx95iBIz;t-JRmYIE3+K4 zfGo3jPR+q|kfu=Yaj#^j-#N3Mh}BSK>i^^=5!EwPwa-Js&n6`=GKKuHOa0==(~7=q z@%39Wfb9}G8Z>M+9eG!AC7kPV^*mIcK0%nGJFlCU2p%+6fT9Bc_l&cbVzMkKe<`;9 zl2$Ze5ub2~1BQ%#XCCJ|36BPnCde&^^!0kt_Xf`YpHJkUi|8>8uK86CHtonmY;GZ` zL31>yt`hl1pVpJuTBdpZ_ZOI0rr)pVi za7uLWOLZQ7rRJXog%(xRt0_es(}EAmbe!-IC}bHI-E^Y}tx?3S0@IQNk1nD2r6BM~ zbiQ*CW?Y6IYS8bWU$s@)Dq9af;yxeJ={U-#|9?#(oj3Q9K>TjBc+c7c7erF(@lAT!sZvNEkB_-jM=XD?f>_$ZU4X`~lAcMV0l-8N~+7_dejYC8kmizumfoJS)u$t~3N@uvl%-k^ojF2?d%UY)Ot2w+;;# z>LMh?sg`;KyCBzq;?bB30al@)gepjoyAog1IX~*Y7h1Z7Z>6S0CYGJwz4=EztJ&}X~vDh zlT<<2xR~Va{O=HYKeS-6`dHR$bB#(k&cA)X!XnS!FcsSHG3ppAwWDl=D_nsv>w9RG zof$rXL(#lhMoEY{&*^COy&u5ze6YP2mEouy|`$+^pQWSyH*>LAqMMd*{)MYRj2w1|&KI02$#scdrL~>A zNe93fp*(vfu-%I9_&76IqU~;PDSsc(!K#WbY67^|WK@T4yuZuaW~(KXZf2@Z!pW#> z=O3-)CAl~sIKD??xSnRLaZrm?%;7z$BM^X~+8Hg*Xzr^-r#M?|4D-v3NKZI$lU0{G zKgf?xWKqGK5La1G$6J!i35rLda>3f^o58e@+D8*EsjO1AznTYlsN_~FW62-zoLnpc z21!6~0tfWTrMWNQx+aX>VcKo6?48!DbHroU7^D3ov!-&IsJ~Dr z{7KojJKO?oFXEYLHrHu)^^@wWIGzAQ@}RBuA{0Zig6*XxHffK}GEN(q2Qt$w9dG9& zbBarxi5PqrnnsR^B%tpj&Wq@`}ockGnmEp+9%RBuIW=>;(RxM{RAJd81}EQE2j zqxZU{66^(k;trkm7w&ELb2-!kg%er$I%hQ)hGP6kjpKIwWfPBCR}X+wzq&2$KP++o zx2HuOe#rXqTihqZV6i!vD?TP)>kCh--Fbn1r9DFde&btL*I!9EN{LnWTy6y6Kz;e9 zgwx-&a#7Y5)L{KHsnLKgIj|Q-VBHB|`Y2Ep6K*vKr@ME-hmsb|C`pZt&fmr~zwD4O zM#T_Z2Z225Zr_Vqf0vAtPl=@uaVAPemKCqB|I!RD8ljIV4N$n)=|J6oidDWY4_uRIn18P@%t*=fPb4AC3?F#$;8Wl+h?rElT7@jcX-JC&~rV% z7w)|D>G!HS5ktz8PEN#a^U9}4A0NY*7biJKT?UUrs(}$~z7nkh5JBSTV{UeGNoI;G_uFX;hVUq#egN;+PbH6+Wb0ro7Wb)EKvQ(c14S%h}2gov+Ke zLxdtX{8S%x-7Gp|IQgWhjIYpTcrHLPhmq@HEA^N(Cn>Gt)NZO{fncomxiQ6w-Ypd& zNb~GbVP0uz6w|mBs1Rp2;PvrMGeXR1Nl8V*s<@UTQ?dkp4kQR^%{qeh5J?*o-d72! zQxUgolmyLyC3@Dpmp3HsQJo|NGmACy?UkenWl!23u1-a&=G@ExJ=Kbl6+hTjgdH5a`=tW4uFyz zbW}3WCL3k}e-7i|9P|@4^v)?W{eyV{o!ZKTs$NE1O)sf) z5})`)rX)WjYRz10gvBE0hM9AFnM?qB*=~tC;uaD${>9X)dec^?w}Qh-cMDBzI?6ty zTEFoVq-4ihiU#aoEL!fnGqj|ig%hO7CMf2Syw+DjYdfPC+`3XZey* zFBbL66zbXyxTXU1K-MCo05>*+vEan+sIga$hn`?tcdKu4oB25c zunhJ@F9*)TS<+umal85%*OAp!n3!(PT&uhDlKi^wd%t`f8XLYR7(nA6@~wwGI0D8j%;pM}MG1vIDd55%`6NuL)1fpgv*EHwQU&6vx#={5)5 z0R-4jPE!N4;81L~NKHh9pxD2CI)Ub*9G^A9suDMRIBFVOm=ag=-&-q9VF-a>?U!2l zVRQ_J&ZmQ6R%$-z7jO?|*D3NFx2=uan@smSvk6zWyXKjAy)&LE?%ypwHi7c*HSy^f;$sCo=pCKu zCIbw)Lw18dIdFNVA@iK_2q*;`-=SAn3n1`uk?8!{m|hi+-}MTKPBx$FR)6u8h11oCRz%VNlCohI$V)t|V$}b`zfFA6Fr2Qo!<=spC7 z{BQNH6W=+i-fof4NQCLRQe5uP)%ts8OMfK`M;|_(0PaG51A5j@C_B$h#i8ka@$Z5e zB^-ZjD4Hdb?R=so6lqwxoeH9_rLiwVYoz)h@Jg?1L0lVbOWCv~99yZ#uW|-mAGr1~ zulWqf{kN5PI;01xw~-YR#hJk%&VKqd0*#Pv{790{-Hiu~j-6hkKz`VbDa75o_v1LhjbLnrKx zDU?aal&s(KH0cXv18;$=Rf}RnI1Y2~9%+T-n}Hvkk6|%t2}bTg=Di@6aCClY5`cej zO3$?%K`|5uZ}1N^+&zkccBRMG?BVm2!nV5vW#(-YGJ!p(GF(0d&WTpT=Ez_F91?>F z?z#p)N7pR!dnc^(-FWTeKDKGLw8D%>3yy{gys4VH-f>`onl(_p@u-fweO{ijuDE9+ z8Q*n@T*Eu9UbO{eqrd}s$8zP`?l#v)hAMq~w*TxKax>dIR`-dJsksSl7iJ6#X4cQz zN!4Jo6tnmy9!srQx~3=j?C)B=tiZyDYD=kG6PQE8%quMI$JkHPu+Z<{qUkRxb)K$h zk(2!yIT$kW2yY(C^gnFU%E}eJ6oR<+*|kOCvg&N0o#J$!DeY&m9fdZJWh@Glbd_yo zX#UbKUvqX1jLrWRQDfUW#XiE&(U!ftEkoXfA>X#P4H!+3C4Jp7?HnrrE$>J6$B_GX z{6hT)ZT(XMAJ%61-@11kS>}_=8g>S-TifJv5ZT5HoKDk?t5*r=jVK)F9);fLUyX%h zzXvNa7p~e@5b}=UQSoOxOta7uWmeYyT_ib%1@<+P>i7#dLsX5#{is{@k}}N#k*MHb znzfx1QLFt4%scEuD-CdZls6qgnlum6<&Fdmd;U$L&r~q!{udZ@Tqtg zkGIA=H@G6hQ=@%!Gsun4I%WV7_kr~Qv)Wq3v0f0nXO(yu`r}?_lz{O_>fanOSI&pI zXGBSUD42Mkk?P7W259V0N%@DUD|N?3N8BS9jsskiy%$NjWi?+~THUK0tS;5aTi)<1 zOIP00lK-%|YLc?cU1tm~!_=>;y4v*Ar_=C#Vi8*8#ET7Ma-&cz8h9;fQ{KM1LZF<# zAca=GD;mueglpu{H#^xVt57osp^`U-&rOShH^BPl65yXGn zDtPGw+6yLl8rKFiIanp;7VPng-C^_Fyl}La1hFQbu5*@dv~$oN7Pygk_wrUyT(h`Y zbIs0UB6Ln1P(%PPgF4-C0A>f-So8$%My^L;pe@e5$xcu+h3K&kol%A*oAg;+>i{^# z!*Bjw6tU%WEj&q6JF%Vht+Xi|`W3dTyO}G)B^S^3GLesu(!7@-Wc23F+dY3Ol&seu znRTcLA1d&TORozl7KX^p3uTfy-EYrTBWygCq)nR1OFrkR^LfTx+MR39<&5Z;gMoW_ zXYJtebRRBJ`$lw~6f;Ox8Tv{kGajoXJg(v0VX+Sh&8-Q>eWwlg+0YXig3k$&YsNF7 z-_3f;zm5`DnT_|kLA^hLxDM3u`ricPNnL|}t^7we%!}QYTf-yHAvFxdAiiSPvt-j7 z;t7G|^~niBJJ(XJYQr@+GkjO)%o14}40?+d+LK_91fhlV`4RGm;7t!`bnb>|ApYAc z3a1AZy&%$e_9Ho+TBO#p_2{O;&ZE)QcGdkI6@Xf6eC0yj=@ayBMy)oA&0Uw0&6c0 z|JdTN3-L-_^f2pE%>uiF04ch^USzIGvs)+G;LTt7X{d7zgJi#KhL$c@1aHRmQ)ls< zYt8(-zUpas14ohKK;WItfu93&A=nAPxDn~$)f$TfsxgnfFs@kx7XrW%wC|Zcjjt_ih z{mw&2rxjxKWsm;BLl(OClb1e4`d{yv$Ls@hk1fp2pOQcYu<;h22uVz;lV1190dB9U zD%GGNHiHdLbWa0Rg$Jd9vvGmW?$CONuoI23_9SMtjJe^{ZR|6JKYs0*;VHEi)G`UW zXBP~_e!IM`5Ilf*p3vi!L0_Qex&Ti}fqWf-5b&vc5OP?s`%^p}c}I8E45nSjh0C}H z61i-1a{J*jzw;6fp*N{}xL0P-%j&Z0AtWe-};0!XS1o3X=jbtz5m` zfc}k$9vc1uIushwsnI6HP2^F0{($BipLbUkNB8CBgijSJSipy)`@#Zg8M=wf9M5(j zLNLiMg~^e*KcINX;5~v)2AF)AD4pt3s0GG{O2hY4r*!Xi6x*sxLckb&LPuZdYJ7xY zZSlE?p+F1Y`Z17NPa!UGd#p$?<89YO4JUxNemk+M`$@ge_ghj|ra4$^j`){cMz+U2GS!5)eKB8mt zaNJ36MAw9kckD}#tJ;mk*Vgkmu|KD%k-KY>#QN`T2{@P|9w;wL@mx!l_Wf^p6$t-6rE}-jxj0_P;gCbdBD$w+~3(7UGz} z#sDw5G`SE(ZkWRW1RX{B+WM`U$=!9NR($GCGLIyCt`15yb7~Z}R3th}>j<-TL{g9R z&jp-s+%S`Rl8&7Z0iW<(eONZE0;N1qahQ9kF6p2C<4_q1N7Eb2X30Vi{l#CaP>-$y zAL_jT?w$WA{uXNa0X1dp?AwzzIHH{Lm8keB{He|GNF0jHxb2GIopYX_!>@iE(%cP$ zet1$=QBiYq>an+^6bwr)mu6XkG`mqC^D~P7a-?ARu=vrvQgVQ&<$wMFyl1Z;{^tkJ zx)BjGs^ZrADS?I}z&QkB19J7(!(rjw!LUTTfFs2hTMgETNUV`I0MeT_bqgIfLL2bU zA?uuLhWg!>eQ6XA4Cg{J&PA+8+(Xp_@unsVgz|B1x}Tt!fN#Q3`&GsY&Y+(u81U## zBk@ptlQ)DdQ-qYD{tY4+U7Y$)TX^stCcrIE?GP~Jw+)0UcwJcEZPU@d1UnR9^@jFa95t!b^+EC3W@ouL;=#7&_3yS zlLLQV01yRE13bxd(IlX{Ud9S?63f(AO&S{#2mS*vxA00B_o?gQ^f~qZglNj^y`C1R zX5w@BPTzspjdLoC={!{O^6~$r4#`A-_k)5ZvM>x;iQ7qWeVZIO8ej&(3}{+OU=O|g zO8#MdfluBRe7&(&;pvQQ-wNzk>ytgf1m2mzR5!NUgY~$S1d?Oxt5WpQK>-MT@AbI?7tk7NH9(7)T$(!4w@2=1e1d*J!$>*2pwhM zfd|7Vqhca%@`oWHup=&EY4SWpJ%&tdz-+M20dc#>De=_>UsCq1`iI)~@xxjQ!Dmt1 zgN&6)7Ey4d$|1?z!XodJ`jhHp|9ky!|B|s2y2OJ#5QtJNpc-tgZ(ovt zL>!A`txJce@qUBgdwx;vEZP~8pi~G|SYj4=PkD&PNlwi%gzE<<+>Q=}*A=lJ^>!JI zYk)yIs(eEWy4F7_B)iOCH-RW(S(3RjRB1G*m;YYR=Dhvfx~M4!=)IUU zc8=xZimWPX#+Iv(BJ#oRuU*$~{Xm$D4kvbp&X<>u7xWNJS0b>m^u#enKml;ICz_5t ze%uw!xe6KrH63!D>O@uvndxQQ5#iw;)j(u zlhmgiP>(^aMF!pF=D=)*%X&Ip07fj)?J$xPL)HCxKP#>Bz$pCd=?eSr9&IN!NA8yy znN^!z{-B9+Ps+}g$5gI;#^7&tlBY7H;i?FVcgYT#&bbStpKK zhZ58~b=aI$Hr@$cRI&iW1ez?pZW1rF#rkg7wRuGx~ zU12dfqwI(MvBiT$K!t{CTk%yYWa*~U&v5qrekiC>YJN;NX*XV0D%J^s3G#>06_gqNIp_#Dtwl&76`u-NjZgq zSXfy)?WE(#3EMS{mci`GL8N@sbgmePmvEoL1KT=ig6djQbT;T(|NWyDh(KEDKuR3?V#B^l%$HJ}j?cU#8} zU6}X!Ag#NBJzsC*89Ucne9G2}%iQ=1yQgUkh8_ZfSCz6T5a(3cKYFA1)pj4gRPo8W z42Tbl{xMC-uFSwOP_Rqy{AqdYFLxs0g;tUgjG7sI6e>20;7tB(d9k^d$^nI9;8heXJ51_0}IOrMiDvNX%_?%?)a-tFu zpgyndcG6vTBdt6DB;UUyZ_Df2bo6<{?1bU=xNKrmOC1p>7zuTQ0J%EK6ZBtI61X>9ile~&7~27ftB)vtnC0A%{A{9Jmw3-4ive*;QR>u9hZ zj|8p06thMW=Q}k|IpVZP72_b4?|)-~AU`%1zo)j)ErKLgF6zRLDTYX!4!v$=RM)mM z%fgY(XIqTZ`xXpfN)d$-&|fJ*brc&8-;=aaDNT_79swi*-=EdX^3-j*{z;s#-A*~0 z(^`I_Qtr0C+hUM$Is6vrawKe`wQz8T=Sljba(Y)GQ~GM7Dq4V3n03a0q-H_S+qdWp z10Cp^WO52Q_{M*U7R$Ep`EX^FGULt3)1NF~KK*PZgof(6gL9c0I(%U`TtBA6;nM2& zkm+~-JUyUetj;|3kA-VIafEMviZ-n)kyo?a>fkVe5Xl zX$U1amnfv5F@$?I{H*pXmMA;|I^b$lOohRj3qQK@5c(Nk;&9F@G4C=Hrb_l2-fOaNg3TC4a*MeE_*5`HW^KGylZmR)1c-K+KMPd1jIgCTAU@{d8Q<(jk|3|Mld|E4*M}zVWmNW-@s8Xx8KUi zW-MD2wS2I*mjENxU5Q}6^&8N(xDPLep8Ur4?vMf!aN^I+w`5;+Sh5WSF=!T{_=`Zy z(vf$gM)K)Zx}pCu5GQAGnyO%KUaZJC4lqW2Uv%W8epw?Yu(u&hbfpGt#W6=Dk(#i5 z7Ff7$wy-=*NG4t=Yjb`>=5R6Z_BUe-!1zW{=p|8>e_B-Oow80kY(3&jI@cpV5YBy} zrvI#cBfd@q5Xm~k61Qj<`2scvACb^3Qg&eNEN5Zeyz&wSHu#_)=ZzJ<9fO-rLlez5 zCeWs#CZVsT3GG%#(&OJY2}<34LZaUU?9f5jP^WS^4$#hDShcRzTb+KuWzN#)%2CV2 zeVG9;e<8j}*WAOir+O);B~1;HA6f43hq2D0W9NHum-H$Kyz&xt7t9atp=FAcHzZ4I zlwz~yF`j6>4cM+aDr`(*l8Pe@surf&jWbD_(U4r#AtPVcy8GGam@sya8#)kn(OwtA ztB~zr0A=se-cTo#K;uCnZMyB)qJAVsWnYhMH0Uy4+I57xW8;DS4V1rO01)_G5q5rx zDM_lkX(CWbsM|j}9+?QqV%fF-4u9ZVbK}O)6WSLYa`qtdHs=#yVRKXp_Ks$Ki2a&X z%Bwe=DVdTR{>)Ts<2UaeeD4vj-8f+vsx#a!$KRm$H7T)Ws#r4>=oR#C^?>`jvzj&~ zlGGpN^h75bhTl~B1x@-rycMF+G@RXbc%+CGA7K9i?0Ozsj6IH$rxk*EK{Q|kAjzpb zdC#8BNzo5W&yq+eXKdG_EXtxfG0n`WultZwp0Fq6>_-yMHIv3oT_BZV>mP7V49iU) z&aE{&vSVA6-`v0>8@hC=M(>e}B)K?>^8Tay zQWyma9~K-U6g|SaB(!tZ-ofo^=(cL?ee?= z2oq;_7@cX{+$qX^*ylh;nAv5DPW;O!V;vyuW~+VT#8Z?$vB+y$>N5JYr-5p)?U5@m zh&^Ol_1;K)%u#CF1Fzt3%*QPu<8MjwJbbIR>(nERG1fr%W8>kVpQHf1(OvIJ!nb$r z)VSFM?{1L~&I$sZ6Lf#jVlszYv;Ot+hr{irqIP3MLrB#e!$t;^OxQt<9(wk^Gjb#ap4@Ag&Gs4m})3#At-~l3O z(RAh%W2m)Wi?E|iUcHzIRO-|sfBhn>W&n(Y-SQRa6yC)QA~BwTd?%_(R8`IK)>_+3 z{2L@4RDeN%;}vStDNeZ#0XX3bTaD{IDh8tX$~J+sqa(LfS$rcz8pp9rd+*$5;_gzQ z%v&)~n6mD>j>kAiQ*`V z#j~_)y`<96Om~??=0Isp5mEOLk0?h9VDLiQ_enf6t#U8(RKgvG;>T)Nu(lI9aPULrnM)>PB0{QFZ zdq*NB7Ek*k-Lrj_h4_HGU$s>QhRX%i89vM&J?(vlJtl6lNzfji{G!ny` zeVh!|pGttQPLRF}ZUPP((oT!jA??Dz2mQ1ceLs)HeZ6d~@No;_?Pk^I8(%Gb7K41L zoSWG84fJZN&j!ae$UDYQwBCz%C6hg+C)c86e#ObZQMz3aq35@%BRlLbGZukt-z&Pw z>WHoviUJ^{FujBJA*|!F?s+w&z)(DGSjFGsQf}Mc(9$beir(paoadE$VY$!FFDylD zZ?gn>z{lLsu3y+UyD$5hG{*ZF6Rx1JM63wt+VP{bF+bV{oI1TXNHFDJcH7)5`}0)x z?dOyG0mT|_jip1Rd|GO;P{(~0+x&}4CYCAoGRGH1AaC|C>na_#WTcMu5hgYj!b(zi zTd*;nzW$!`Vdf1194n2_huK_gm9a%g7Wz>5QN^<>DOt>4y8To=A_BBBz6&MeLe$hM ztDpDY8;@dz#OgO`TGhsuo{wwdEm5o+0weDr0gXo>LD+m)J`(TX@Vm72>c~s)(wpkx zsLQl<+V)?=a;d-)HwZoAm+0*vsGSR-EnE8j2*96j$-np-+QDRI+nuAeA@d7KQ~HI~ zvlc3k#(dUpd^FUYC6RnrcdPL)mU z+b|_+q)t1k6qAamE?^j^^_F0WPHMz|yIkKC%d#z2k!-!f28%kcMc$4v(iV|i&~em7 z^Driv;ntcPr=Y#^?~K=p5gfjvxY@%@ICgmyA(G8zs6w5J1DqcgvK2}zDqZNks63?X0y=3xnK7BF9DyP;N^ATgSLsGgW+`R@HW zOrFzANRqcGSkqf(%+Ot^+A@U9HTz0d#&DMmKOrN> z+BX%Z)HLW(jfGm1dnonI|t~2VxDV) zl)PoA++|*I^&|tr(AclU@CFRuNRK3WXQ@D75;eSihjfdYL^(?~Gsf+kyS}2OkCMM~ zhf@{p%qJw8l74^22qdZ+v}?SxqBDeRm_B{DDMPz+K*9gngPL~F(BpVyy@?T;c9s4Q89F+y4u6H_6 zerMf&d#d06C*2Xwu72_T)-11eS4`!2_`d9SVdYBiD_@%dOCO=1ffjK$FwNCoV)d1L zVBs^8EPL-*qU!nW6^oNS43PdDPM3#i-mZUMY?6i5H;ZJzr)M$l1w;faY;Ge+HYf@; zD(|w;dlgH1wEwxuQ~7E$kk(s85r%oDOL%(2H!~*49ze5t+CZgpAg_-CfM)_Eoj0`S zvAySm?XYg%Ur$r@NVu%fe72jBTj03clq*M&djkX>bWW=?(P&d-;jmzoWL7t^G~9Ij zcxZ0R+(}ybTa?$I0tSjqMS}^JG^&DVi)7Ncs+6flhZBc&Ew?CPwi~Y1c>_8G2>$@K zgckbIEGz{5?waH4zn)ixHqgRV!@s_!&dee%x1)`odAhluWgw|+AZ9TQ4Z2#sh?y6t$>8S;e2_u>AI0!V;xF=zUV=XVpXAm5rm<+@om;#fVhwCK^&)khPtN(JOpECcd$R4?XYF<`>iY@a;FtC4XQKcXD}cdv+R>otb&4Z zV{gZNw|l2uP33T6JW%vappi<_!Z}T53QEeedO?UrfwktwKwsusXj6zRG3&oUQP|7H+5VEDAS&v);O;Q_&c!}s(WDe|TE z#hyP6?Qfzt6zxo_26FtZ@!dmANau*ot!-FsaO(HXx2S-$e%KE7y$vEGam`wE?LqpB zU+Cv(qUK@Kgi%gmlFGSlFD45|1b(dI<@*6xxOUf3HQ91wy)|<$8V=bF_^j`sZi=*6 zf3ymS&wjXG6K>}MaZ*k)56_@0vE?ex^}l+H)-Es@9*mc z8$JYR5lKdvO2iGtLY^5lG+tl^E|Gc0E=H<}IbX&wEd7tHLiW-OqqvpkCyN;1yL?KW zCWHP38lIr{w}pz1%#BAxuoWIP%HQ1W05N_<#TcMu)b9^x#*g0;GA~1VFMb8mqi<3< zM5Js2lh2X~3`!vKM9rf#Evf-Kj&zPb+RdW3^eS9uPr~Z2K{fS$z*{#!#+3&@63w-iTlrXA7nQ#^m8UmBz6P z!jJ$hY8HdMK6Oq0o>G()eJHgdM`f-r)0V}R^hHzdn!^b7#TSQBXc$O9s3!qDz9Y!+ z+m8#HpJOU|$vWL6EpImZD?c}Uim>)nBd!&MoV;^1*CS`z2zd(w(yxd{ANsI&N@y-) zxXvlgz3Ix@YGpK8PqJuoKPqaqu7frHj;>C)`!jO@!#3xhiSzV~+_3myU((@}NO)86 zQJ!45gw-WC$o#?*I6nh$exkjT&c~3w?j|}>Ct*#<80BNU1Ub#VF$mStR)R)kcE{Qt z>_N9M_cQ2}9s}%%f88=1Y4?mI@_A?fp-BUgJTxzafedju^f!~ZOD2|%42u89Y8`sU zL*9c2$LvD+^l)Oj=?UJ32*6(L57?{UcCo7sS0<<%@t=GHVb-tFM=39o2L2g=Rhn8y zOYqTZ1a>&U(sN#WY8Ch2yf2*sG1@?nDdl1DMu+dWmCnrmRT*jy{N$lCTq!lcL+?XT zG~iMzp)B%9G$Hg}8HHc#%!V;xbEO9ZWSQW#o2#8kQnYG550V<-}>Y2j+nfrI85 z{bmhOl*B&$dgyL!!kt31Kt!2?O%ec#Lok|V;j)mo_FL%1{h1OrEDOB5P;YCIdL45; zShM)`ZpMF%?ugcC2Vzt4JZTI!F*~hY}pmf!Hl!tG+ATa^2~aX zQ}%vDpQT(Cp|aVyADKzxWo&Y6mH}i^cSac)ljDUD_XkQOFlTAyi*H3@r?F$2Bd*IH zTd`#7UJbM#V36@j9GPZTF_G58?63nM~21I)0XjR(` zltT7qgms?G>u|&TjHR$z4fHd{NFrAq7!Ho~lCt{6M+iKE2bg++gS+dj%b^$s*%s?b zMSTQF`P9rG6$QlL5y%i28IcTrZLmP-KCBIS)}@fI27iMJqKFB#{ynic7cVJlMKX&P zyjC@tM{f%Cc(9FGdg%|OYzXb41l_{vi7yi@geSAMgsyFCQ<iD z(I>;-ihM<7VV*WdT-L*}ZiJ*agw$pN{ME8-ji7u=5}vdm z@;_co=@i3=|HVW8hn4)_bY$)sUD31Xv`OCo1l*X29PQVVReD4i7G&C64S|%M8(CgH+%nfI@q1TV#q-??yT#9;c-olz8#D z)`c0IN&}mC6+{W`KL~8aWnaagv$x8*HyDgU($(?J&SU{zk2Ka#FLEUytbA9h4ipKex-5Pdp{8JS6F)rTy=5gP>TVHtikA+5Rb=LD~3C{ZuQ*pV}ft0ezu z@e6I0P>q7>gcX|#!Y@F*Z~H@3hw8ir1LK2iedof@BXm$e;xbJUoKVgcnl7y737r|G_z97~cNH9W zt+|gap<91kXlf8wOrH`F)UiJcbg~2z3|F5dd}#lIbdju;+REsB4G^XHVOmbj6|PrfSVb*?`5+?OHp7g9G&dJOP7veo!Bki zUnieF>7)?Jc(MJXhs`xZv+G995g&on?=mulJi9_@=0~DHNqGoJyRb&v7dT1ZLc5lSiE@pfbavwa{u=wb90*X{G)fQt=dsEWz){$ z%pM}P4zQ;R82JpUHv&Vq{YIe1a9p^Z!I$16o4_{lb6|fXZ1iS+Jo?1gcvDC6BC|P) z*5$C(=`(lhhjLxmj9B7*F0zRiCFA}U&z~;?=YO93$Ms4U-e1)WU2_p1cs&;kkx*#d z$-l&;7;4|N)Zk$+R$;RvzuREkJ-sMdgAkW7$)w_(CIcm;>3N`x~1G1Oeqs_R+j>GwQ|v1bC{qybTj<5Mzd&T)UpE?;uyLWf=%^F$ zu83mcrvXXV9cru^fx4PZxIQ-`cH|uW$i9CdoFxkM%LOtOJ`NOG@)-Gg zQ=f`*uX-)mNaquzh1zOStg%I#UeCCo-e|TXXgV0r-{eY53hCY0)be5vpt&HsZgyB-XUNTx<&ba$olHID7v?A z3j{%0QW~ULxmq;u(|ySrPuyZary@8|c#``5Dj8D?ka%$&K- zw=U^AMnk0*Wmt<~OEJ5Y?_79)_ zk61JG8iBF1GMlv`=?pXqS+Vf?IBx-Ed1``RmYDLCq{ndlI>kK>l?J2i{8<){^dehl zT--U8zIc(8tHzFT)-R!uySPQv4c^0V{9z|(SP^Dl3j-62?bICOXr?YX#98Bs^EuFW!~6QI@<}#q}5Gs;nLf;a!8hG1_#fn0XEn+%%)0c=*-T$Ikff<%ZP!g+|hu0K1yp&uJlN zFNd>fnEoa<{)*Wx&N_>&3P1oiX8%Bc66Gobbq)gUws zs?vfH_PA7zFQukRFOYRW%6d+0?Hz%TMqb@TH~Vk&_fw2gvei=7-#(L1TFi%9pWNTd z#h(>s1yxTx@8`WFSEEDS%jGbbgby>LdVCn*JUP!N?{t%vlZm}!H0yMOU7-5C9a4|H zO0P&oiing{UO#GE6I{`nA{8ZInaSjBcqvZ>@ZDBlS>y@EKeP3AqRJqDeU5H-GVKh# zUR5F=UQi>MuJTl(wa{6lD$t#$qkF8Dm~3+R$Z{G@xkL*0YNao-OrVL0UEQka$nG{d zwsvpMzv}?F$MMKc>WR-;W?2rY2#oIMUa!SH&Y2@ie=Nj@kw@v$BT($}h_T`_e>KyO zq;QC13GK}t1N!xNe6)#a?gDMlC{4;gqE4-GF>l)L?TO&|V2%;ozfP4CUIC&qVDK%f zL@F&NGN`?gcKhorFy!Ss)MUU zx4oppE7+q%L+j3)A0KFFirK~aQTWO~=0{Xv z`%Dw3R%lXUhlJ$6FK}&^DD$q&2@_DSkbs@_vBB`8I$z+OdAuEnD^VqiS9_>Z>C~PT z6W5uRg8w-or^Fhwwm{|b%Dq8>%5i{AVmTstH}-z?gv>chf#8I5A>Fbd@$|C*VZc7= z;@9SzuDE5jF=`0Hn~(PTt_=@q36MXvcL9thSF1TO^n)F+?0z51;d%hny@vtWQwbQ$NG$31Hrsx1l&p3VP|muJZ)uHt>S z;Z2?}RfpuuF_7+oaZCP@7@XK~TFq-wP#uZ|qACu&Jjh7C#kI4r;co4KcH{`_yhudy}-R`R+m`m&t3l{h>EdXcda2frpwNG&>4fyXmnu%gihC5W3SRTKhExn>{plMtssIayrP<#nxS8A zK3*vx3cM;6afEB;A+91kkZB2W>+6+|cLtAvtxt~$Zo|S8$3D0qv%$jfyX80FdF({+Go1-b&FDEL%Yyt^`B4aAqiXOUhj99!81G%hS}7qK22Ao7zLn$ zvzXk{&9C~1|FGE&Fn8k^&1A3IpeA6-rTa<@4MYu?_O}pNd%Woo@DPr+sUBT!;s67+y1f5LB@xT zZLhs9nDU{Fq~y~>YF*$>v^ty>{i*)#U?b5VpnNy<&*Y82@A7=qGctYV7=BbMN*=}W z$KSu==!R6o`kB!-)XI}>)i>ZqpyyPd7=hgp)R=*cxW-hZfWxq6kmOLgl~f>x@oLol zUc|7t?WD&&trjIsEQGNvsI2GaQA{&;Uu(yzj|TTk4S^4Bxr&IFBw`@CZvL=xmEjyOIo9q)OR0b8=ppVW4z z?~hgLmA{Tz@o_CVs79zz;wBPjnGwpZ&Bp|0di_@-)dZ_GUSY5>(w7b*WTy{}45^00 zOdp?Taz~|-!wWgif_{FN{weng(FM~Ik;PM*>bhmV#lA=W_SzwZyOmG(*dJ)zmCAsO z)H$CIcs@UA$Px&+oK{XlT{PsJ(G;DB-nA$2>sSU?gufG!4klX+q)1`v?Bkd04ItSL z0rD>ow>WNIL>IX)5GSUXvo`L37XT%&f(|T=%OB6D#1EJyn0BBmwhd9C*mF0`tz~4s zn;60JKWS-#dIol-AzR%0>&YsVouWIq$J_?e>33I;fxVc5x1$NGXJcKO=!Td09}Y!% z;9U3r9C(O?ben@N8Wj3RzJTNQhXt{TP`}y=s5R9)G~6i~H^6tdaOlhr{VG-KAIYPu zKzJq+w~+tXg)m9Auoro_Oc`Q<_NFvUg$cBV;DAUS@m0-d_!9X1iTFeg|5yKWBXCg zD|f_~ETSXnI{-$fi|-7O~)hBz=ftae?kMorTUk-ISo~cfpn2R$MHd ztx+P=YtLkCt||BFLpDfB&+#-zJ2xp3pYIF5xV|^aC-n@*fo?X}+PZ$);HGk~=}Qsj zmn*1d>BcxH8btmHTO5X;S9RM%&u=oJOI0I>8%hj~2jgVsQ98z(?%W5@wP?HQP!Fr= z%WYizL}tdWcgUYW-_#b+xQg9$vC4|BHFcW!1mU7Gxl~^8sD)`bv#f%lSNZa_T?bIZ zD>?rfl>Fe)Cn%TT;4{r?4Ry)0i zDDM~LfMQ15SYR0fwJ`UNNg|5#RJa9hvl%*8Fz#F+ro z!l&%+SJb-C#vy#~jG7~o`+~1zBPYScR4Ui`%J|aM0dNxxp(Oc?$ogY6@I4Inb21dxL#{pRe)+Phy>VtocdS2 zE58UKFouVdG8|AMrux;K&3X@SBa1=u;+;g4a!TwowJdDoQ2 z(*BOQ^7wX)slYKVQ{=Bk7_$lG%KRQ1XXO*Fk~I~n9dSLl^2!nKVTvrp`;QU9nZ#o^ znfk*)27OQ!Z{_`Ph~ZrIeQ+DAK9#Bo!Zd>wX4gCzxHvk{J=WTv^{cPJ`}oJe)mUQR zl#_25RJ=S^scM?E8f08+_;GblG-{EHL17j=Iy!HV1+o3T@3=q~&{d2OI_jTLviavd zo};l)fzw3`JgYbNM<5C6g@7vZkqNf|^w60q6}4RyqF%gDinIR8kb(}DoKJr)d^y4M z+HZ=0yJB!fO@AD*L~P|gYxU`9aD(2t(g*H7CcZME4V74TRf}4xe_UFCZcuW@xZ|iu z2@Cs@)?g1T(4QLHFkRRQHxw&V%&bhPB1(ctqoeg>?8YKoeog|5z??%OCYXv%nh#9d zHFJ*UileKg+WX1r(Kj?+1U1fXb}5DaFChKN7dyCgtUJ{D5Si=<&L{cJQav!SRDGs zE_i&!4I>)~kFbu3vX$qqKeD$Teaz7f5U{G{AJ1Tk+y%k|a*)TN4xVglL`d@0Avd%oH<o`{n;7!*U|nnzFKG90C#b~n&fMS!=2 z9xI^t`75dP`;Ua)0P{CpkfLOv%g6zbLNaMJRV@MO|6Nq43A&aN#IqIu`Z<1_pvMS& zq?*Dfa~P83McBL=Fph9Uao-Oe@KaP6f@kIjPtKbiz;iVlnw-b4zj^Xvz`X+KJfu^% z(4gWTQZy;*!%17VXJv}=3&+1bD^G&X1kU|kruUc8zUTnVo~o|%7X*=3b-EJ1nhAue zF8|rYrcp$$&ewKl^fNJ6!nXJAWX;W8D|4m|3NDY_bW1;$Ipltee1*0Dq}k5KWPo020TA}RATAAPt^MF`FoXhtie(E1Uryf2%vz3Xciq8(_gbzb1p zn7tN2=`tpKcS*ye5b;v;^SzcP6|uP5gV_!5A2Np0_m@SH ztBbT>t|WII!B_R_pCX8%TP_%v%tr4tJ@t*Y1Qs@2Qzk>v-hfu(#cujgW2SW8rStF= z>}_H^^kf`|+#2jxA~+SZ)@Ru$XB3c1ANqx9e$;!h8cXth4iC1c{=0bq27lkLokKqm z!1eOd)B*m4YhgbfzEw#ysv;u*s7}!bHVb+n-E3l`kT|OZ794eETex80=F0< z(|)D|C;gkz!j8bzduJi2Snsa;u6X^lk*WHvA6ciVozrKe?zB_7n8>Qv{5t8&UXayx zK7IDx1?|{AV#lgrshmu6)npZpLEq%Cdu!A>IzmR@k;nNsTo-cdH zf4w4f1X-_19e+?#(mh%e@{FY&}i*3m=t z`Y&6L$Q|mik8$sg-pCV@QeX_Pz9T}Tzr(Q#V#O zNWK8%CwQHC+}dLgsUGR*;TJE~V%kG5jJpD7&cIZlp0BSRSs~(E1>(RB>PPRgBW%Vw_FK*PGO>3Uj zqlHP}*dNV+H2wGQ0F%FApcKeVoj`i^lSbr!y#To(Papp0#u2YH8fFb8=yr%-Zc3L{w={_n0@>GlBg9^F$^8Zv|fb86s6KE;rA?(Rq6NCEJ##ux?^ z?*pNFgvL8OpElQ@h(CZji^2lTejYmg=pj)b)TZE^q}SK~CDj5fAvQF1>~D4hd4N*= zO9GIm{={23@dV+ivD19t4N{EjbNrv?Ju66?;a~Hf#DAOj1peE+H}yZwdrdUSxPIrU zxw}s`NZ{xapPAuXhcDk`93|~n&v=M2bce*@yx#vv@G#i- z#8U!G3_8qMFuugT&|j(v*bGZ&q?`Z$diS~j@7`b12WSQMiQ*W`buFCB2Hha1vgJDxeO_M-SKF70xFr+zhca$aFw^1f2sJ8A-R z?#;S5{>(i^h=(g3uxapXAioX&6D>dNZG}U{E1wtp&YDbC${byOTlQiu4Tl_HRo=zu ze}*c7x!2O_*H4axNxiQ$!5rVY`4yP}FV(*^#^3M#ES4g61|2dO?~? z-s>qx><3=^XD6ZQR=GufFXshCX8L-qkww5Z<6XUf{wqUrYoN*Os%ypK8fljJZXHmr+r6(%8b2SMS0~6C|tn2s5a>4D>y4|Qb_l21yS7W2t z{q4wZ2lTiN!$HWmTa5D}Y958=w+7dwCbHZ3&2H|ZGZlb& z$?RsD^F;NZ#LC+>w^_a3LLDU~ZMw&l(+TFNmjD@Q->AuX6U`VM8%>?oH37fDh^D*xX zwtGa=!WlZCvboEYys#|f()W@T%Ph!VyK)Oh+w&HARe~PgApGg@FYUhkuFc48_7}iY zXq=o4s%9Vo+)fWp9}3XQ+9mFOt{@cR^=)0sTR;EUr%NYEseV9vFlIdy@GmqTzS#k;G5$?49z|)3on()W?J_% z`N#*7J29HMf5r!SN(IbB*(g8=maGJ-@R{*^i`54 za8xLbf!h@K%eP*+^O4mI1R}PtG*w=z8x`{s);II(%xMiSnI->%`jiqQmC}<=HxR5P zd0Ve=W#=epdF;7ze92TC?OeWP7?d;COK*|Eznv2RL(usj0DRg4eANH5Af9184w#{$ z^wSa@-d4e(T$M7++pBq0rZWh^r)rQ;g>}b-^RrO!Q)yse%pbm_0*7Iwzjjd}&}o(> zjw2#i-+n&6J@rqUDsYaNzM$G6u@#z;iz)gA6+|A1>J1e|3Nj9>aV#*SB0N)@%;gwY zwZYpCBiWy36=AGttX|uG4!8J1KRzm%z9Db}pW~!eZn3k_Y0T-C`uiZ=N#?!$R38q> za4Ht7_5K^;64Za@<~2GqUWb?7`)yU2{8qzGALF%I>e86IpN&tj^<02@e>?j8WaF%L z`2!3sWs`FL6A7j?W)(e0s?vBH@^G@ETUD|1!>Pre8bfC_jv=}kp5)_Sh!{e5Eg8*a z1clyqoUwg9@7<8JC>cBNJ^0L_Yl9@dWp#QE-M)DwYgo_*g|n&&W-`)zl4`j)rN2$r zaX=ZLD%t!^j-}I*!@#e;>pAUQQy13_a$Y`fhzKqoNQ>=-KJKx=!(F}TZE1!JeI=%$ zY_m=N#0Yhgz;T8KMW4E*LZ>LXV*EvF7|>bu_jo<&rRsl)zHJ{p)x7I33!z>-3pqy4QQH_W}5?GVv3FO zS>%(ag#^4EnwFf9Fmv0GgfPI)N{&fr@yS=F(OhU?H2EWn7G8*KYyD?XTFxV=vM`yB z${l)g?x2q&6mkaTJ+A_e3>w6E>wH@A%wheUrTqtn`s96lJ}kl1j?+&q`s(GTxua}t zgfE4v5J8{kbYpp4+T<9ASms2c6pKEDJV44Z4dG`(uJQ~*2-RfgxBikG&a-tp^a7}yqX6!}27H*BICu-IuT&&m6 z#IKkB?JQnrx+bKAyM$HfoO3*#*4Os$U8eiAFt%fH{!*^|k1CV6UHcZ}R>(Z5qvBV7 z3^b%ahA3%q!ubpw&dLyiA>ZG>3TGWzr3rkKVIKTIyb!l#PanB@tezUaDtrG2op&lY z><=ZygD@b&h}_0{K7i91o6_e2_94>@r&XcKK@K+nrBj;=czebUbir~Uq#F4J3Fkt!? zl5YzgbVUDKNdH_QSm#sAd&4mCBhLFHT&EpC&#oPK7 zuMrKvVMqQXA_ve^5&N*HU%Ewndk5-3riQViLH1`vTm<}ArCNp!B(Q9YsLwm;xOGQm zueUd~E~=ID0|>**+wD`f<5z16miYM5^rFPZXI@_797|)oDH;B9Csjc4V9=l%?DLcX zXB|`!r%NwLkt4UK7izi3%_YHjWe3uzvaKFhy`D4-al}Y;z<_+oKY_pYoFTQ@!KUft z(n2U9o_)^bvbiaPDlPK!RNFW)=5$<&(CDn=C!}>^A*>$4$QPJ-tqxr2x*@T-Le&fR z_Vs;e25mkub)bG&PopbKQ+jeE^6gmY6;w82U;_ZtN_@3{BA4Rx=w zC#XFEY4JdATz1q|L)z^!(yqN4-SU9j>G8h(w*0`We5$bi1mOIHO11T&OiC&H-M-4N zS`&RD#J%JO_$Mj9(fBR8R&*<)fJzyCH%}={kiMnqQU?bko*WZ&oCM!~##PdtGqN-+ zr|iZX;~}_hJY7RENxs-5ms%0^T=tkyt{?Zb6Sx^+%ujJkeIF3jwVDf~xY7^=>TTg> zk6s;BXS0-w&Gl#gYxeR4dvi)OLyu-L+O{G#J%_Qz2-N*ETd2QpEy8I0Q1*)vr5A)H z8_NS0;Ej`GGC}-nPC`d}VK;In+XB>cIflUM0;tKUtZ^Kqf7An^a!J-9O?q#V`B(G- zN&WADrh8TRlqAqg@pqEnQt_gr_80a6SH9`11e;sr7^4J9cCCx(tE}BJ-9YkjHhqHJ2H?cU4JyFC*<6!x#lr|>LXgZ{(?rL|tyNyNRvlreCUDm9V*j%kdHp_=um+#@K;N> zU)8Nv!VEJ<*OkkliUGXX<+&~DGVB1&0haZ+HROyPwEguWkgTC0hgkM!Y(u_fE>w`F zZmR7fQC2S=dPu#?cwq8wI(N?i(xk$n+;4rXLCWWHWJ&((y|Ox(#`tcv>H3`2B#-I01d3)iQwAIy}-97BrvqUUF{mXK*!l<-q z;Al)MZkInLc#_JXTQdhfnW;87ss*|=xpaJbh9qR009A|C&owDWB7J2CXEW+`(}kjh zLL%A2qqNM7D){WpnY(KV+8n}AQh9qqHBH^eeyPdiz5B)bH42} zXS_hP+q6gz79w1z*h<`Qvy-W?y^VtE^bXpQ)kh`_rg}f)PJYO@^b;UzpJD?O^P-xL zR0<(gWa{&{1nu*R%rFvP@Kba-7(Gd|41W0C$h>cwr4ltGJoarAZSoXuaWHVMT|`U2 zSpI$Y1Q9aa{BCHTkw(ay0*FG~E})|~Z&0)D9$xF?M!=T6Q3SR)D(!7*L@SaWg}ujp z(`vK-XUGt>%$V;U5i@_A;J9F6Hf^2Q47t09(b><8$44-(Xu|otmo;}470DX_k7EPM z!(;eHN6>Inq)jjsb}!QZ>U^}zZC=+c7X zkFp_n7m_H_NdA1Ki0OuI9#Gf2;)tvh#}B*k8VGBWUbOh>&tsk?IMk>Y zS!Q5+cA%T{`lG>S{sh12*eY&=d2x!DZ9)CeO@fLFkcBnkV1*sb50>+p9oVoPCbVT? zkoT27R;$rHy}oy^J@cll6C4a<*+~qA(e-!a_ZQow@x8%1EC{ZyQD~1ruEm@cuDh#x zliNw&#cBI#7G>-&?9ilwdk>0h6iAK$2V}L zeA2VwUp$bjefT6(zqo@ZNrLYXq;)%{B<)gR&03SYEZAKwtY2f15s;UD!=WE6&@y;x z<4uxJng=}yeYI{PBntN{p4JWKj^c$a;7rQ-aV9| zAYI7r6T8OMJ59&2`YKTr^BZN;ZF_ZG$&6YkiuoA9p6_t3&qqtW? z$(TX&+|`HrY4o%EiuMfzakb`5w$DqLz)ZSf-D(qr*A7mf!(Nzf{1o@f?xe_D72fPP z;G>)C+(U7-26d5%y{WB3=xzt{(Km!2IRR5W2H~Zm#bv2Pv%VaMQ-Zy=f>|LhF+Z0K z(GMF_c=P|~X`8a9XxId3n_1I;MmOcR zrX}gj`mTX<5qsBmx$WnWUO{;E!Ox(8!ydW#%_}$1Cik`75t7y7N&S_em0IZ_A+VY+ zkbS;7|NY~imNmew z^!MHWK{#7Oa=!d;;PXiH38-v$NvvIj1D^V9pEv93pfT+!Jg-lS^ob-srH17Bvz$98 zW}@I7FjvnNk0Z~8(+D1TNpwWrB=un*w8pZ8wG`vBhW?|~KW;Va?X=+4;*$>#sa@l- z(Es2xA$zhTqD46pe`Irh%+E|U8{jpl`~+42IBQH_oR``R7Pp-*IL*x391scPShP{h zCLSKcK|m*;pY}O|x*90l#s(>3E7ahw5d8OpAj0cQZ1w`MUKV(-;L(wPB+ z46awdi4)-yvIw9MQ`*0Q6**lTrNo~ru8m7aLgN$rr{50Dvy%DHCOQxCet=Z)70!R9 znZae5)o=&y`ousB-2Q`qww(FA)!0TP3p*cB@~U{Q{1V_dyTi|L7Jxe7FZRiBNlS;U zvRwHtEIK}k0$9h%$dun`PhbJT*|~F1+e9+8NkJQ4(vTOwHU7%LP>OA4ZW^_bZM@CQ zB@y^@PLT&tj$5V0^=%#!#`^IVJc$J{VlZM6WDv5^M6{Sj?U+GN<_+L1THSphiJF)< za4q|htQBf4N}Zdv_NweRg(MDTg&ckqXyNs`q-M4({!a45CLhh-Ptv+Z9@;qpPzXp=|&%*S~B+M5CZ$ST?(b+H678TV5BFGa{Y*JoUF-qD72*0ypMWy6q zV=F=_R&C_Iecqk~$?%-_#isaTN%fRUgvwFP>Yl4n{hm2jDsw*qZgyhE?o*ZfC zI;=`%Uy7U=3Sc$ge`nNVl}2_QU>030(Du^Uk&`ycD2VNRCLUQ{J!5=INS&PyovL&5 zf}bTzWC)oXJdpt{6q3H2>K$o2SNi=>l4r`sr@vK2&rlpgOWAKJrK5sFaNn%8d=Btq zh8w7>3X!8Q5?J@uM-o{1r$JFgM=Q9^BpqG&bw*m7QaWSctW;=^l*y+@(4`lE z8l{2WU)2-*^3`_aAV4GjG=^qOQ~Jg79uc5I%BS+>lLVVc%(F_{F*`g!6nz8B@ z(P6~#xX0S--*$eBL^yJrsi!&;$1+HnakQ}qc#*dLq466w&*f!YR4{g*JYK!|SZr;W z3v`kh3jfR@G=l)Sk8@Iq&zn-CnJcg?hdKc?#H}c@Aj#ivpTPbyx8<33Db3`!m5i@- z)-A>idr)GvG_REuv5Fz>)|2?YYqXRtJ)`>>;z%m|sU@UxclQlIpD6B#eo>!&6IU);j@XMiK_VnxJa*~Bvvdw1+$@$s;X(@{;i~m7NRM_KySgjancE37ZhILp zuhnA~3~kDli+^xPK!1$OZ-3X0Yfyp4b@+xH;{SWMG(B4i0GuO#>JqXWwD6n{#sZ4= z=nBhrU(yMGD0~ykVrJM&U+Q|}pzYu0#91dK^VXB=i?qfM%)sxZ_@KYxK81X_>kp6- zg{MJnt+}GE#b{TlDv=as8XSO@8qc>+?dvO{*N50JdPO-^Z)ntyjM^S7GjaFeAI7U! z%jN}`=#Pom;`<`D{0bWmH@J5#Pn1$C-5~CtDa6X)s0bt)qR=l_o!CGJdzM#f4$8K) zlheawcy2vF+bBx}-k>5FKC3f*%SHkalymhbF9-B$~iPogzoIAL6 zQ%-|EY0!@rOX5bT9LCrg|Ey9iX2i*i)ps}fN53T!2W5SJAAVMT`|etvkXgY7I%JH@ z)+>A4Fy@Lv9`GDhZCUWkKKdl+Nc=5T#lr=8NlhE`D}-oeb_bpZ_Wn8F0o43TqXXzc zUxy2OTXQ>6z^whEh2o{^A+f~8tS~OSJKIVXy8tM`-;gxGS{806dh8ze>^XH*gaSp1s-23$k)4uu~lQkYg z$|*|Er4Y&na+dI1a+)<)(I{yDR1>mRmmF*Lvq4XtaERrp{0RHPRq~QIKbEOi?U4$< z42;LkL9-QY++VTDfKK9XE}ElfHt2b z<$%hg)N)DTz=o3^qhyh88FA0$0|}XPT8E}*43FAwMfYKDi5Alrh2+8k_d<;G&0kPj zr&RGHt-pPo@AdEr9$^HSm}^G|=6S`Y(R+8IhKmGR1{r7XQ!I>rUnXRKVD>%pK+YKTotZIKK6#343}u_lm$VoFcz+0Q$tC z@D=|YnFvxZVZ3Jv`{im>dRd@V`nw~ss|;L?Y-Y{k;H>{6y+OK=g5uS@s&0*x1~exO z_O_d2Wfpo84RrJBIJ#P|a7gVYBD1`@CVcDny2MDg=yTizfiexL;7qElHJk;scnp+z z<=y%YKWC2&ViG(v@V`g~l8Zdl*$-PB;=O2V{#w@DIFA?(jq>f-I{Ae!o3j7Tb|Ph0 zNqtCUx#{T|&Yl{KeuL&F^>)el$&_^@VmD#k2@$#rRNLG=-dKgSY_v;~cq7xM8^{F$ zv(&te0y{Pe4V6VYebNv$kMiXjJn%ws*SJ)7J1VM99b=b>2g%@jxY_bc_mnOIr<+RA zrS@4a-6=E0>7fpefLW66gJH5g`QFs{DrQA4CDC65_LbN_EsndnZnx7dlQ{Z~nKVN* zQmWB!-UD+0fNMZ`e^px<_{JWTuzqMh;2`PiHctEHuXLDR3pJAs{v1C+pt02uY~dT( z_5gluB$LpXG&*W2*BItn!kENfax(B<9R8$s8<^&jG z4*Z}ax2BFsm51>k?uVXE@e-)VY()i!6h=$BCP$>KXH>w+GEViKZJfQQYDhZl{JDEQ z$4%+JXvtD2u2Yg_>bFV|j?8t7rXi7x$w&Vd0p-V>tPj%R7`ldxyJShVJ>uLtETrH4 zr(7W+6s6lSB+~-etcrWRT&~$DJP0N5f?^5Eu?Td^D+L`rz!6fI>k)yb3Q>(rwrKi` zfJm$cE!wbRu}_C%x&B>%9V*MA>66Gux0fF}4merl-P58o{bgd<=m?{ueo~0(#`d-R zWRH%GMH{SgCnR|b`e_$4gRus#aSnr zgt4K0Qv_UB9|cAj4yU)efl;?S@+VhP^97v4)G0fgBge02g%nc9%oA|prrE}`nsJ!@ zumH62WjHp{AV~HW%j@fUnV z-zx0)c*qPGYZ_5bnh7J#yKL{v=h#UCOil9c_o)TSoi35yZKqjsh|FCi9*#1?kv}=o z{m!`Ar$Tq7zfe(2p&aDK1I`*27z?J=a~Iae%()!~osjS39_Hcqy3>8tYgd#19?Xj7 zF-s&-na#b#dS6HREuPQu43ffy6Z73CZf7%-?}sl@=k2mn5;u$*0EQn6u)1E>7wuU? zYP}PN4V<|TmUI{h7I`U5bmlu!n##&Ly4eITPOPO}*$I;7#>!(T6dQcd+XDFXaz2^b zI5Kl^RN%HEKR*NNSE%)|H+hrFkAzIJ1%=`{T#R93^5Ie6Q0=S6gf0cKwK@7vMgMLlt|P6%Invuyz*D>?q;rbXL4w`O`HEhimWBFJTsCHL`?{G%r} zjF?Ji4D6ov!_c*oqz2zSc|4@1Av91DQ#nf?i#)p6yXx#$6fr$JzupKX%!_0Ol-g2`KUvv88 zRObbVAsmVI0?qXW_lWaha7oMus$}7)$F68Yb&UemvG6ku zuiV@xdY}b<3J2^uM1W2Oz;D0Y`l=`ZHF_*@e!}|W0s}zE{a6T3G{|k#h>rV3yBA~D z-)1WR{YUns;mH;%_WlGoMu^~*b4l9mHCAD$Bi@z{yTbl^_R5&Ptg^%-kG1i^F3%8x z3GdWVD=vTwy6l!ZP>m;MmN4GHs!5~m6;O%x^1wNZn0Re=;j1rsSURhJe7@2#pH}P& zRBj5V;W1SulTW!vz*_HBYPt{H?<{QQ>^HOw#Zi|J4ShjV!o%$C2;$7GV*%3)t`dM< z_hh2C4SF)Opp+wu!)Gk?Chwv8YIFZZpVz|kJWzgbzqa<4^Lw^VH+f1J?!FmC={=zC z7SX9Di9WQ3n3ds~kEfdi&I$9Jb(>Z;2zGscp6YlND#dRCuds+3>vU#|{C65=KEQBb zS!%9Kz>ufG%ii2=c-)IGQH#UPBaJLaTKIHiF62*2guD>_wsN2op(g%M5aXxxljLU? zU056fkeA;QMLF|+Dt~Z{EWR(-wDMDokSwv=BQf_N&VGXd&dDWg0f4EG5kd#7I(m)L zyBBu74!sw=^tTPr&$>wNPZjOWOa)Yz_;1Xz0q!S?`$u055PF&_ssnSdwP z)p01Q+Aaj33R4V9HBLkN=2Y6ct`(7*t#|Q)tZ>wIfV0 zq$Rp>L`GO z4Sdm?oPOo@N>(dq7<`bBl|(RaNVwisw1tPAV_(5A+q-5HE_+gCv#*4iybhHe!kWa> z&ABJ5*>3k1J*3G5@t|E%CCLJe?BXEjofuN8w>E^?6S`iEdvW@}JoS}`ZZ@ew5BEli zkiR?c=G#|JaQL>nRu?z(V;W=fUo7mEXPz!CRe1j!T-WO1i6GHDhL!=DaF|ZUE)l(V z!Cp`aFDYSXKF&o?{CQCaoB-giyhYeKN~W#>EuK|87dIudMn&dr%5>Z|kqhx}%1N_v zuPa>)iAu5Q=qW$bh0qbkzg50K1zmV)&(NUssqV1+t*HjT^ljwh9`hAWIK6dNbwNng zx}QNODsr+RjGO=+u!@6LKmxZw%Zln-@@FE?bZ&^oaIkC&qTe18v%pll2DU!5@cfkdZ- zZJvWSir2W@97BhgR|AS}`^#3Hx`Iidk=5m9q(^TXj`nfIpl!daoe27K4%SZ8zJ_OA zrs0{J2*M}ERDDq<)>SdHZqjzEiR(g5YtU;D5U>AQZ;#5Y@$f4VJc~F>QuDB4RQD}*>xQ!_ z9D%g#*`_)2`z&0EggJbOPdw(gDhXlaMbhQdSNfvMalJYU&VVfYI$OZlD|P`Xar3qE z6iJ$Td`{T%_G!!9x2yVsbLJIvS7@Ztiqg0B?n4Oi_7y+XZA0NDkgk*X1;`qDp6-zS za886Mq)-y!mF?ej`&KH4G5#5h&`U4Xn_Ep{+pAP@CX{69<=;%ByE`^B{c~81(~<)z ztaSg<7=%0d)NEmS;)9UEs6`z3!-iz5ZTkw_t|2%(qJbBXM5lb@{JtH`^WOJFaYN+> z_pPEgu^vyhUKm-?KeQfQ~d_%6*`E2 zQ+?s#>sxxnatg;h#lNsjbiWQ0JywS>lhwq990AYI|0D#(VzO4Aayy{ir(;Rb=@ST8Z%kvHD5m3t*C* zPrB&#ls}jMOBWqM{*Nwtx!wub3J{?FM;5Jcfx}ECQ3a=vDx2^X`rUD6^9W$Vo>sb6 zNyi3qf%U>O!*OH*C=Lt{?@W5C2f$wQ}=Ygr4m1Ly%Rul@kof0~+P)7`4h z^dn5_XBW3Q0%3}OPa=_&;zcQRv*Udku9>|PSRv=L4j?Xnx|4OfRWIV9TA8KRxnp&` zZ(Ng}&JY0V=lCVssl;T|gyX8zewvE=hhbnwgq<#`a`3_LxaUJ%D0pB(Pd^*5C}0L{ z3%?js|1o{!2;Te~+W)lg_^bb$5`-9;y}W^2EVv`!mkahZ1U{VN&= zmd;N-P2B$WGM8dE;gFPr}cdjaj|LPK-9qOdP|6GgLaj0%P~q z`&Lu_{oboAhPPn^=>9DKkFvK8s-x+?g&zoV&;UV$OK>N+1=k=UL4$K}cPF^J26qX5 zaQEOANN{&|J;)vMyubU_{pzb*b*uP?nKRQpJ>9!!@3r>Y6IPEYkY_pzQa`@jk)2Dn zS&5hV@e<3N51QxW>3rn)H##|eCFxa$x||C@h&U1bDwODZV7HW;UBN*BCjP1#6%{9=Kd`JS1X#cI?Sz zB}rD}y-UrMm#}-ey3ptCA73qaRk^%AQ`iVs_Z)dw?C*Vu%Gv>S9dnDHzFnJT=)LrQ z0p_rE*yNL15-SQPd>ic-f7)sFk7Gz<=%~hSjoMW+1tgc=yQ*YTFGOGXU!qU0+KCb; z(ew9eCHFc{6A>o8jdnsSIr>ld?jAO#Xd&Y+&ZhIiy#L_YYwHts^z0bq*f)7w+O z*HYjX*99yre(Xa0lBauG!V1eaNUr*iXMp#rBMvNb@u6NZmpqO#5|;kiGM}+KdZR?A zE#HecWYX6z@sLg6CWFli9TDqLI*~aZFdiMhoQ5#?&Rx3%Qa<#D)Vtog%;#WRHVG4QbcrV@8 zuxpRU%jly+YGR#@XuEy($%?%baJU1=`~a3%=K89+_(CO0I7G_dwfDLYDlC3uv!! zw7nBJC}hWW+=iB8S0nB%D|KOaE@G+d;OtN51Qjo?o}I^M9KFUVC!W4qNw|Oi!n$Q) z2e-y473D%);qvLa3BBJ1`-^i9r__RNn|ykRh(%k3S7IY1nS16}6v6!Vx&0f4Lvu$o z*o?Gb$eSEX zpxw3{4tHt`>3=w_l-JDsCOIVka#|4xJwhZ(kEM>P0nsvskO#H7tc_a%&V8=9&aR0w z+f7Wdhd~uUU4Tl64g$)!V(wK`hC2wfmNeO8mUY_$47@E5t#Qnygx!3*izA^I4B-1q zn0e4sxLQUCIHnd2vy}(cAdQp{3*=Ai7Ddg9HPA`epg- z{iT$W(EaX4@ICya&Jw~LVd}VLXD=CxD=T-^e$nS+^Sw>y!m%v^pEW}kHjjR1=&Z4- zz=A;Frs&$1AVXq#+->-kX2HTX1O69oD%l0>K};XRujRJX*^8rld+>j` zpl`HP$@GA_m6Y&DY+nwxdiMeZkXT!kG-+szf3RFBA({*ybsu^23XNh4jVpKWtIxR` zZG7d;Ope&20>tV_7nx%1Y=YxfpiQLhoy<4JVm38XP{`P;0}59mMdXd@dtgGJeM>WQ zI`ulBV_Esj+tifQr5S!B;OX43nC70NeeJ0S*!sJ{|C70C!(B#i1Cqu1lJMrRIq;jO z4SX>J=3bBZ&YdR}5OU=LD!rXFX?qU4;FKrq0aVGts=1BPARrGI3>StddNqjvEb0## zLTgsCKu{$Wm_r@_wQ{8MFSXK@A^qz_nPraanq+@*E6rE9kYF;0M^WttXD;XuVim4}7+<l&NaP_KtWwmeg{)wK01#?TuEM&%Ywz_uxqrwt-B?;#`w6PWVkH&C+ z%-?2^Pb)mtMm`+puzfPQywNWF*Y!gV^<@7|IrNe-eESjX!lPB)Q7p@MHF#OVdbknP zU~rV9Oo25+w=_J;ajCn>&~quBacL64?l3ZIqg}5y;;Cq(Azs=*@brc#Gr3)8x~4A& z6}t158+wdg)AID?v1z{FVdG0nLW<(58rKVQ`;QKV^hof(iomI52SkSswxtl07e!#P z2`-;+Qg)?0gF4S0!q)cG;;ow7a6}va_@2hu0xDjMCcYAmZenU}ig?2NGX|In8D1En z$F^!eKY+*ShE-JY@;6=xfa`DN>l~s066D7apaLqqS12S7BQYAU-<8+SJlfWmNNAFM zhDvAg<^a!!wu>#*@YIcM|8Up$jEpM-sThtWd5&&sow}>1uIAUW{t`7)f@j|p+f*%n z`PA@_x(`>)mX3<04zufri&&z$Zwli<5qU$*F$0Ls{2QbO#_r5WXLhT0?o6;pJ#04N z5QnGQ0ItvjcP~^d9nn4Iy0CWYOmoq7QukI^#17TTt)QlhOr<13cmvxcqAYI4X)^0W zS@8eC(PJ62=pCU+!r27aFWSThEG8{3Khc0{;B+PFeGYC|EKv(vO|w7oEcN*W=dAZ- zY;ei#U+5mU}x1-h2{>SJp=Pe|BTr(EO)0y=b`&V=xJ7cH?JC|2~sy4|(6 ze{!7?)rs#mVsiz=RDFn6v!zqzQjs5@X~Sv{ty5!Yk)z-Tqko!SDL(W9zm_}T`L1WH zK4Lv;Vz?@#&S-2&Y+ne!4~W&~TG$B)kO}>Cbz=zf!`%3d1;1V@s)61ii4)7(Z~rxwXOE2&OF0iS3&+g72g<}wjBismvvcs9jO;|ZdZT%8jA zIj!?2;IIVZA))qqef;uAYlKKq+LJ)~f6`k&dqtSOTBb9)kz&qoGT2r-PyBCs>m(|At$)rEeCm3x*lmhe*eljqD~{Khh^2cA)QFt`sL4A&Em!>p(t6o1WY!9q?Iq_1Y^ z+Q~TXGa0lBog9)3`Th+D7J12j7roj=F2|!pK0NZsV0&G&NJ7mGwT^IZGnVRH&A{E7 znx3$ttOH_=e$-c=f{dt>2{u3|=I-yRlOl}Kcs64bj9*dal0+HuZ2MS(t7VbUR$=)i zy>>}9k<_Z24ATPki%swS75Z>Y@B5gN@+u!I(3n(Y@c4_Dfkj1@zWnEpYA4Fge^O!R z=ZSzIh{cY<9nvtPo$kQI%A9_knp-R5mh*M4`>}u~f%oA_WH4h-^hP6J0}=iQY1G(> zU!o^}2_(`y|L>x*--4Sq*58`&Ccbz{SOU9ef6HMay}5J^Bt1wF@$XA#FD~WDVh1_= zeo>V*a2O(cakBsdKk@%fRhDX-DCWh_3B{cKjjuU|>+oxX*gzph@F&XT7J3@E!J@*Ah6|M<;s$UgRrvVHZL_CjF! z>yNGB9O+RU+}TY;xfzVXytqbyzf}zHR(%fWiJ11RxbgmVJu6MYeh|5hVnNekDjn6A zvF>Jg+eCxD;K=%(ZAv=`{AugCB(aEJo`v(LTEXK6s`M>!)62MQ- z{%Luu?JrXx)!^$Km9(muy`+FrXf?F$ilJSxTX6$$QqB9d;{FcW1H0t+a*YkZniNq(fES78IGgU?WR*}04WQp*74$6e$zAW z2ah9hUPAIfO6h`m7P=t2(eB*Qiw>p?K)eDZc!Qda0lv~Zxy)rcfTS0fJG943B?T~a zVp>JNIO{;FM+%23%B|xvbQ6aG;6ko1*4^hvWMgTcNMmx$((_LY?da>FOcgGjIjfsimES3<^SW_-R{;SJs_+AlYpUUJ;qs!C{e0S3&VHDrnVGdR zcs74nM#Df(R;gPKm7II+$8lVym%-fJQG%=3+$+cypeLDssFzXsn}le!X-Mf>7_8D` zt4(%@!H;mF#%ZJScl6IhYhk;WbACdoM%hLcwTh{dn`rv}4k(gl(^HOd$Inl!_1x^=>2iDDsYN4C;3 zbf%)J_P70OK|<AyMHS|AUYx$?NCC^(N0t(WZEX3X4@@N|7O7)#n1<~ zvA0#hN4po!o;*x!pHE=tM7%;UX(UpUS2k=|ABTq-oV(Y@s~tSe4n(psfp@8lKlBc zGOIUh#briWH?A3E-$rzt+GaR_x%apk6@jE!!6faHYyTY-ohm^>hWyKKbh8+W+laj0 zTyK`V{&msS{^lQJF#u`esb$}=%dtMl3?hBf^>}bF^grgZoGiR`9>v__r0PFay%Ksi z6EY==x0U2n@FGn4Nz2VZQPUuop8uV4;*yc4f>PGeGAmS=riOok0Y&a4Bt-om zWo&HBGW@K!tkuGXRlTOE$`_v^2IV?iTk&$KeY4rB{U>{aXzBITI+@9;E+Mr?R`qQs z&r1$2CyQ+y{2cuJkrz`vV~b5UEh|hM7g-KtF73TyqLEJ}p?{)c4gv#ieV+9>%Dv5# znJInq@4P7?W{U)UXRc-biCzp*6~CPpX+$vKL@?G8vpIw4@>D%T6G%(zD$0|o(4L3+bP|Cw z(?d#j(g&T&#Q=)d^|10G>cHmMG%1|ChDJef;WOdl!X$`!fsL#<$zm2*Way82S3FG0s3Pt8|a z-wGUGA^-YB)gkYU;!lsg{PV`3Z5_)(O;eDNJGf))8FutzdGk*^xUXpD{&n?twUJy0 zpZReR-}dnSVG&h#aVOHP;ny?Aw(!G|H_BqM??ZX8$ zmAL*iDDCy*+|Mf0;_BMPv+PUtr>n}(!JFML9^OL2GNBs)u$y+5C04BVj5^eHO<)e4 zH=aLNe%IFIm|UTa`z_SY{v^Hp&@F6)Y7N7>GESM*+0Cy#S(Scx(__bB;e0&d zAyH6Lve7y7h|?1K4dO!&bq9HglD7%Rvq|@+9=H<`Wo5Go#B%T)b6YWwvY#;kF56A8SQCjat*hm4_a(-JUoEq~gL?hrKVq^M1F z_&#uP1!pn&*FVsd&VJMDmBpX;f`&mdJND3Rcka{nvIUmhF;46wF9$x{EQg8;5hyRq zh5JeES3(D$8m1kOc1@F##U_eY_c)i^7i@kL9cpHdqiD{y&%2@sP{g4fr$Xb{$j!_)*GM9_1v2V3j7)ola!kD6uY8Z^E>W_Eb4K8gzREGDER znOAzEUeg9LI_rRam4?PoRuA-%5j^i$^vNBHBtEq6li3bXvv2c)64sLX<=QiS{D2Y4q4mhqQkt+Q})cdTOEbj z9DVz?!@Q>+V~Ml$YTf4TTRbRC{rQ!?nkKoLQr*SCfJDgRQmMo}@YqGfQvztBGCYI}o9-pbyZ>IVd2E^tZD?IkCEOR=R%y^_&`?r2S3#!g=QqC_Q zwO^58>_r0#R%R^}!3&uq2E3TOiG5?D!riD>v&?EqqoT;K(9&D0FElJ4mFC>pCH=c8 zuN`!rP}mE*L>Gy5x)*LAEy1aM3ui717LDFMn_jvBI6v zmIqCGAG^$$)hrR`v-j!n09~P||9DNKYZ&i*!ya+6E~Y^PTW_Vu?YVHrvP43j7panf z(X#AO+x(5Dg28B}W%N$)-BS%q19D@Xr%kynhO>i}D0;44fW$y~-QvcD6|7>G14mP) zpsoWGkocw2W}TUgW1dk!(M;i=5Dyv=-ood{gcN_9`B7K*F_;+Bc=2305S>?nrzoJJ zc?X|w%i@uiVdmN9AJ_Jn{=$Z6+ZBotPHcAyFWT%Qi#L}-3!}PGw^+Ler}v79k0}vf zs~T<*$5E!;5JGFzW5{(6R~Tnc3zRMIBs$`C7y4#4g@PZya}0`oh;+LBDxS9OS?*%@ z{Nq**WBrEnSPRI1m>3l{nplpwaYMD&6t z+^v++X8lJK7-v)#;mqjgmP3LTra@u<;DuIh=Q9!XJFkVlUm+*(J{86C7sN72YmyLlCBh_9>r#(DR{cs;$zS!Za^oYdzmW8o-TbGy7{ z7X!BS)W`bqk$=a|vPtTpn2Z9Jy-m;5=R`s;<-TS?f^r8nORPX$T+9b^Ou%*cz!Yhnx1Lp$y(* zR?oo#Q`{@Rr29EUOK)1VM7OqrA>;EqR*6}xDd@Y9(|xn!M8k`m1*Cq7M~>agVT50y z9MB1wotpv?sU6ek*|nvsB`dz9!HFH3y>^PwI|fn;1QMo$Lqz6aC*R*_=IH9Q$W_tF zuB0ciYmdn9iE;0JW&TK=dBCi1TMHi;t4PuQ!1KX$GNH8#Ef5STeXZfjr%xR5jiO6< z%OP0EXQ-Q1gYBYWo3E8CnNJdD{<};&(vCvP8g~dOM^k$`;L2rM94vU&Bf;F;99smA z%AeuUO>+81ceQ5`kgufw3{e5GQZ2H8F(t8ki=A^UsG8a>l!OOIcx9-Ub5G61y5emu zvvGjR7sUm0+{mAGmllO&TvKTRf2M1S?`ixzLOhwV@L8!SlD97^P}2U$!O2-WTW@2Z z32t>*G3YB%Kp9WtkGPKaAuM`aW>^~;MYL7A}nviy!3IZ zl1Sdaf7|?o)V!(O(}2e6xpk;yZV<_HrAx(sF+XcINo`I*MFMv`;g0u;hTXp2TSgK+ z`O%&7bFe)|<*EB>Az7;^hMr7*zPZK&+02j*Ez9&c{8V1>Lq&WKkI(Lb&qea% z5@Rn$^VgL8td6b2NOq|?CI~2d?l6+>re;ZgA4EFls6LMRC3O%QxT!VN6{Ue?z*VVh zJ!dR|_ozE?z+6`graqO*74OOLOt&aDtj(QkSW9|BplrUh`_aL{xG-9WBqI`_7VY4I zwQSpg>cH=*uKm_Du;Xd9Mxi|%(dI-wh#d>X20Cr0HBALQxbf2U4>_1Ff{5a*iuAIGr=vNmW{nrc6y(Pjy`UBEsC^r{@hlQ8mJk*X0ulg zW$wR-#K<3j!PJ?ArA%QB+g+#P%`|Btr`l+Wb76#Tjqo*oqXdI0Z?}gCpgN6SOR}KZcXY25+4eW34b?LT+|zEbx1`nFXn}U)kg{he zYcwgC?rE@JKgw|tH~%!%@ZiQ_nvH@zM@e@*eBjws0(y>v{Z%MoSR^I_bb9|un1se> z#y|oiD}z~h;UlUczt3>SSnQs53wfsy(RkCN<|*iBC{@U57#sd_iz-3r#MpW_nnBlFDGb!*<$3o0m9rN_qKPv0$G*TDp z2l-=`gO&cK_+odJd)CnK4`^=ifVk&`P2SLHmV#MQJ@XlnVDJ_MC0?BwNjVgFq6p-9 zOnBx)VxiileDHsu4ZxgHk&4noZkX#FSAKvlP57qBFh2&Y|Hsb%eaV^Q(s3MgE z(5~w{sy6h44_|EbYCeJA*co|rh{Aa@lJ@(NbstE>oZXpi9_%YpJ;^@>3kJhV=0AR; z;Ac{BVU-%}i~Fe1U3#9aHvXlgBj-S~SXMB&Gu8QyOuLIz^sv0hMMe9|o8O<`D~r{w z;digXS{?*fZkE%6{=KmqjbX9jP^`E<=ZzrNDjrWY%O*kFe4LDz2VxXz!9yz}T^iI{L|kuAgO5%0u$k5GsPj1}pN* zkAP=On;)gN+ll5|@;5zK1}9kk174-T9MsEG+tg~Wir-jKXPH~U185T zgP-LqN*Hdbk`8>Zs}#uV&5M_f6UgE*%_9@=HGI6WGT42UXb}ss-^C&w)cIQ(3t_fD z4e7qU>$6CpwkL_cED@?f_1I2Gv#4>OivWqNWE+zJbA4HG*ty2TY)|EDXVZnZSYta^ zG2f!YPK)mLW{_Ij2JIf&Q@asFyg7!LeNg;cP+nkvAc(w9*1+g)+sGf7#$PHZQ(MvKGsaN6iq2Lw2I#C`%%*RTsBfA5YD zbAL-yy;`S<3S0*d2TVVfX2^#V3*Y4M_1W zgf?Q)7(FTJklPlwgW!Ckvu~LNs#AXLI4@YhTb^3xpwIZ6oqxDs6#a}wNf{7YB`hh8 zz6DM}w4)4fvV6ic2r?awjs0U!i-vxbhvquV>Nhj8;~84{Dl9+u8(rb@P)xM22oS&M zL-^d@?&s6ifz$WcKH71~QWUknFo|%nwj>=y^MfYnfpl}DB{qF$Ih8Z=^wQw-2RPh<7@IsUS;ei6K zk!c4WOQ{i?Gs8+eNKAGR>2KpHiAE#v+>sGg>WWli4fYGOh@#YIahuUpTWk+tpuR

j*!Mt!3qVa|r=^1pSZht4o>(g*g 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%0AgO8x? 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 f&&Wi3gLdu^LK^4el7O}6d1LODj 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 resourceTypes; private List excludeResourceCategory; + private List excludeResourceType; private Map deploymentResourceArtifacts; private Map deploymentResourceInstanceArtifacts; private Map toscaArtifacts; @@ -361,6 +362,15 @@ public class Configuration extends BasicConfiguration { public void setExcludeResourceCategory(List excludeResourceCategory) { this.excludeResourceCategory = excludeResourceCategory; } + + public List getExcludeResourceType() { + return excludeResourceType; + } + + public void setExcludeResourceType(List excludeResourceType) { + this.excludeResourceType = excludeResourceType; + } + public Map getToscaArtifacts() { return toscaArtifacts; @@ -842,6 +852,7 @@ public class Configuration extends BasicConfiguration { String host; Integer port; String downloadCsarUri; + String healthCheckUri; public String getProtocol() { return protocol; @@ -875,6 +886,14 @@ public class Configuration extends BasicConfiguration { this.downloadCsarUri = downloadCsarUri; } + public String getHealthCheckUri() { + return healthCheckUri; + } + + public void setHealthCheckUri(String healthCheckUri) { + this.healthCheckUri = healthCheckUri; + } + @Override public String toString() { return "OnboardingConfig [protocol=" + protocol + ", host=" + host + ", port=" + port + ", downloadCsarUri=" diff --git a/common-app-api/src/main/java/org/openecomp/sdc/common/api/Constants.java b/common-app-api/src/main/java/org/openecomp/sdc/common/api/Constants.java index 04640e7fc7..fcde7f13ac 100644 --- a/common-app-api/src/main/java/org/openecomp/sdc/common/api/Constants.java +++ b/common-app-api/src/main/java/org/openecomp/sdc/common/api/Constants.java @@ -125,5 +125,6 @@ public interface Constants { public static final String VF_LICENSE_DESCRIPTION = "VF license file"; public static final String GET_INPUT = "get_input"; public static final String SERVICE_TEMPLATE_FILE_POSTFIX = "ServiceTemplate.yaml"; + public static final String SERVICE_TEMPLATES_CONTAINING_FOLDER = "Definitions/"; public static final String UNBOUNDED = "unbounded"; } diff --git a/common-app-api/src/main/java/org/openecomp/sdc/common/api/HealthCheckInfo.java b/common-app-api/src/main/java/org/openecomp/sdc/common/api/HealthCheckInfo.java index 653b8b0866..2e4f54f153 100644 --- a/common-app-api/src/main/java/org/openecomp/sdc/common/api/HealthCheckInfo.java +++ b/common-app-api/src/main/java/org/openecomp/sdc/common/api/HealthCheckInfo.java @@ -20,12 +20,19 @@ package org.openecomp.sdc.common.api; +import java.lang.reflect.Type; +import java.util.List; + +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; + public class HealthCheckInfo { private HealthCheckComponent healthCheckComponent; private HealthCheckStatus healthCheckStatus; private String version; private String description; + private List componentsInfo; public HealthCheckInfo(HealthCheckComponent healthCheckComponent, HealthCheckStatus healthCheckStatus, String version, String description) { @@ -36,6 +43,16 @@ public class HealthCheckInfo { this.description = description; } + public HealthCheckInfo(HealthCheckComponent healthCheckComponent, HealthCheckStatus healthCheckStatus, + String version, String description, List componentsInfo) { + super(); + this.healthCheckComponent = healthCheckComponent; + this.healthCheckStatus = healthCheckStatus; + this.version = version; + this.description = description; + this.componentsInfo = componentsInfo; + } + public HealthCheckInfo() { super(); } @@ -48,6 +65,14 @@ public class HealthCheckInfo { return healthCheckStatus; } + public List getComponentsInfo() { + return componentsInfo; + } + + public void setComponentsInfo(List componentsInfo) { + this.componentsInfo = componentsInfo; + } + public String getVersion() { return version; } @@ -61,7 +86,8 @@ public class HealthCheckInfo { } public enum HealthCheckComponent { - FE, BE, TITAN, ES, DE; + FE, BE, TITAN, DE, ON_BOARDING, CASSANDRA, + CAS, ZU;//Amdocs components } public enum HealthCheckStatus { @@ -71,6 +97,14 @@ public class HealthCheckInfo { @Override public String toString() { return "HealthCheckInfo [healthCheckComponent=" + healthCheckComponent + ", healthCheckStatus=" - + healthCheckStatus + ", version=" + version + ", description=" + description + "]"; + + healthCheckStatus + ", version=" + version + ", description=" + description + ", componentsInfo=" + + componentsInfo + "]"; + } + + public static void main(String[] args) { + String des = "[{healthCheckComponent=BE4, healthCheckStatus=UP, version=0.0.1-SNAPSHOT, description=OK}, {healthCheckComponent=BE, healthCheckStatus=UP, version=1710.0.0-SNAPSHOT, description=OK}, {healthCheckComponent=BE5, healthCheckStatus=UP, version=2.1.9, description=OK}]"; + Type listType = new TypeToken>(){}.getType(); + List componentsInfo = new Gson().fromJson(des.toString(), listType); + System.out.println(componentsInfo.toString()); } } diff --git a/common-app-api/src/main/java/org/openecomp/sdc/common/config/EcompErrorCode.java b/common-app-api/src/main/java/org/openecomp/sdc/common/config/EcompErrorCode.java index 0f45d34886..aaee26004f 100644 --- a/common-app-api/src/main/java/org/openecomp/sdc/common/config/EcompErrorCode.java +++ b/common-app-api/src/main/java/org/openecomp/sdc/common/config/EcompErrorCode.java @@ -26,7 +26,7 @@ public enum EcompErrorCode { "An Authentication failure occured during access to UEB server. Please check that UEB keys are configured correctly in ASDC BE distribution configuration."), E_199( "Internal authentication problem. Description: %s"), - E_200("ASDC Backend probably lost connectivity to either one of the following components: Titan DB, Elasticsearch, UEB Cluster. Please check the logs for more information."), E_201( + E_200("ASDC Backend probably lost connectivity to either one of the following components: Titan DB, Cassandra, Onboarding, UEB Cluster. Please check the logs for more information."), E_201( "ASDC Backend probably lost connectivity to Titan DB. Please check the logs for more information."), E_202( "ASDC Backend probably lost connectivity to ElasticSearch. Please check the logs for more information."), E_203( "ASDC Backend probably lost connectivity to UEB Cluster. Please check the logs for more information.", @@ -34,7 +34,7 @@ public enum EcompErrorCode { "Unable to connect to a valid ASDC Backend Server", "Please check connectivity from this FE instance towards BE or BE Load Balancer. Please check that parameters in FE configuration.yaml: beHost, beHttpPort and beSslPort point to a valid host and port values."), - E_205("ASDC Backend Recovery to either one of the following components: Titan DB, Elasticsearch, UEB Cluster."), E_206( + E_205("ASDC Backend Recovery to either one of the following components: Titan DB, Cassandra, Onboarding, UEB Cluster."), E_206( "ASDC Backend connection recovery to Titan DB."), E_207( "ASDC Backend connection recovery to ElasticSearch."), E_208( "ASDC Backend connection recovery to UEB Cluster."), E_209( diff --git a/common-app-api/src/main/java/org/openecomp/sdc/common/util/GeneralUtility.java b/common-app-api/src/main/java/org/openecomp/sdc/common/util/GeneralUtility.java index c89eeaf535..0b55fd1845 100644 --- a/common-app-api/src/main/java/org/openecomp/sdc/common/util/GeneralUtility.java +++ b/common-app-api/src/main/java/org/openecomp/sdc/common/util/GeneralUtility.java @@ -153,4 +153,14 @@ public class GeneralUtility { byte[] encodeBase64 = Base64.encodeBase64(calculatedMd5.getBytes()); return new String(encodeBase64); } + + + /** + * + * @param String + * @return String is null or Empty + */ + public static boolean isEmptyString(String str) { + return str == null || str.trim().isEmpty(); + } } diff --git a/common-app-api/src/main/java/org/openecomp/sdc/common/util/ValidationUtils.java b/common-app-api/src/main/java/org/openecomp/sdc/common/util/ValidationUtils.java index 3ea780a7f9..6c47659dad 100644 --- a/common-app-api/src/main/java/org/openecomp/sdc/common/util/ValidationUtils.java +++ b/common-app-api/src/main/java/org/openecomp/sdc/common/util/ValidationUtils.java @@ -66,14 +66,18 @@ public class ValidationUtils { public final static Pattern ENGLISH_PATTERN = Pattern.compile("^[\\p{Graph}\\x20]+$"); public final static Integer COMPONENT_DESCRIPTION_MAX_LENGTH = 1024; + public final static Integer SERVICE_TYPE_MAX_LENGTH = 400; + public final static Integer SERVICE_ROLE_MAX_LENGTH = 400; + public final static Integer TAG_MAX_LENGTH = 1024; public final static Integer TAG_LIST_MAX_LENGTH = 1024; - public final static Integer VENDOR_NAME_MAX_LENGTH = 25; + public final static Integer VENDOR_NAME_MAX_LENGTH = 60; public final static Pattern VENDOR_NAME_PATTERN = Pattern .compile("^[\\x20-\\x21\\x23-\\x29\\x2B-\\x2E\\x30-\\x39\\x3B\\x3D\\x40-\\x5B\\x5D-\\x7B\\x7D-\\xFF]+$"); public final static Integer VENDOR_RELEASE_MAX_LENGTH = 25; public final static Pattern VENDOR_RELEASE_PATTERN = Pattern .compile("^[\\x20-\\x21\\x23-\\x29\\x2B-\\x2E\\x30-\\x39\\x3B\\x3D\\x40-\\x5B\\x5D-\\x7B\\x7D-\\xFF]+$"); + public final static Integer RESOURCE_VENDOR_MODEL_NUMBER_MAX_LENGTH = 65; public final static Pattern CLEAN_FILENAME_PATTERN = Pattern.compile("[\\x00-\\x1f\\x80-\\x9f\\x5c/\\*:|\"/]+"); @@ -318,14 +322,18 @@ public class ValidationUtils { return true; } - public static boolean validateVendorName(String ventorName) { - return VENDOR_NAME_PATTERN.matcher(ventorName).matches(); + public static boolean validateVendorName(String vendorName) { + return VENDOR_NAME_PATTERN.matcher(vendorName).matches(); } - public static boolean validateVendorNameLength(String ventorName) { - return ventorName.length() <= VENDOR_NAME_MAX_LENGTH; + public static boolean validateVendorNameLength(String vendorName) { + return vendorName.length() <= VENDOR_NAME_MAX_LENGTH; } + public static boolean validateResourceVendorModelNumberLength(String resourceVendorModelNumber) { + return resourceVendorModelNumber.length() <= RESOURCE_VENDOR_MODEL_NUMBER_MAX_LENGTH; + } + public static boolean validateVendorRelease(String vendorRelease) { return VENDOR_RELEASE_PATTERN.matcher(vendorRelease).matches(); } @@ -333,6 +341,16 @@ public class ValidationUtils { public static boolean validateVendorReleaseLength(String vendorRelease) { return vendorRelease.length() <= VENDOR_RELEASE_MAX_LENGTH; } + + public static boolean validateServiceTypeLength(String serviceType) { + return serviceType.length() <= SERVICE_TYPE_MAX_LENGTH; + } + + public static boolean validateServiceRoleLength(String serviceRole) { + return serviceRole.length() <= SERVICE_ROLE_MAX_LENGTH; + } + + public static boolean hasBeenCertified(String version) { return NumberUtils.toDouble(version) >= 1; @@ -509,5 +527,5 @@ public class ValidationUtils { String stripped = HtmlCleaner.stripHtml(htmlText, false); return stripped; } - + } diff --git a/common-app-api/src/test/java/org/openecomp/sdc/common/test/CommonUtilsTest.java b/common-app-api/src/test/java/org/openecomp/sdc/common/test/CommonUtilsTest.java index 50c2b79d63..ae882d8a92 100644 --- a/common-app-api/src/test/java/org/openecomp/sdc/common/test/CommonUtilsTest.java +++ b/common-app-api/src/test/java/org/openecomp/sdc/common/test/CommonUtilsTest.java @@ -257,7 +257,7 @@ public class CommonUtilsTest { @Test public void validateVendorNameLengthTest() { assertTrue(ValidationUtils.validateVendorNameLength("fsdlfsdlk.sdsd;")); - assertFalse(ValidationUtils.validateVendorNameLength("ddddddddddddddddddddddsdfs")); + assertFalse(ValidationUtils.validateVendorNameLength("ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddsdfs")); } @Test @@ -271,8 +271,8 @@ public class CommonUtilsTest { @Test public void validateVendorReleaseLengthTest() { - assertTrue(ValidationUtils.validateVendorNameLength("fsdlfsdlk.sdsd;")); - assertFalse(ValidationUtils.validateVendorNameLength("ddddddddddddddddddddddsdfs")); + assertTrue(ValidationUtils.validateVendorReleaseLength("fsdlfsdlk.sdsd;")); + assertFalse(ValidationUtils.validateVendorReleaseLength("ddddddddddddddddddddddsdfs")); } @Test diff --git a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/components/ComponentMetadataDataDefinition.java b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/components/ComponentMetadataDataDefinition.java index 24d801262c..5fecac429a 100644 --- a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/components/ComponentMetadataDataDefinition.java +++ b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/components/ComponentMetadataDataDefinition.java @@ -28,6 +28,8 @@ import java.util.Map; import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; import org.openecomp.sdc.be.datatypes.tosca.ToscaDataDefinition; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public abstract class ComponentMetadataDataDefinition extends ToscaDataDefinition implements Serializable { @@ -35,7 +37,8 @@ public abstract class ComponentMetadataDataDefinition extends ToscaDataDefinitio * */ private static final long serialVersionUID = -9114770126086263552L; - + private static final Logger log = LoggerFactory.getLogger(ComponentMetadataDataDefinition.class.getName()); + private String uniqueId; private String name; // archiveName @@ -156,13 +159,13 @@ public abstract class ComponentMetadataDataDefinition extends ToscaDataDefinitio this.lastUpdateDate = other.getLastUpdateDate(); this.description = other.getDescription(); this.state = other.getState(); - this.tags = new ArrayList(other.getTags()); + this.tags = new ArrayList<>(other.getTags()); this.icon = other.getIcon(); this.contactId = other.getContactId(); this.UUID = other.getUUID(); this.normalizedName = other.getNormalizedName(); this.systemName = other.getSystemName(); - this.allVersions = new HashMap(other.getAllVersions()); + this.allVersions = new HashMap<>(other.getAllVersions()); this.isDeleted = other.isDeleted(); this.projectCode = other.getProjectCode(); this.csarUUID = other.getCsarUUID(); @@ -177,6 +180,8 @@ public abstract class ComponentMetadataDataDefinition extends ToscaDataDefinitio } public void setUniqueId(String uniqueId) { + if ( this.uniqueId != null && !this.uniqueId.equals( uniqueId ) ) + log.warn("uniqueId changed more then once -> OLD : {} , NEW: {} ", this.uniqueId ,uniqueId ); this.uniqueId = uniqueId; } @@ -264,8 +269,10 @@ public abstract class ComponentMetadataDataDefinition extends ToscaDataDefinitio return UUID; } - public void setUUID(String uUID) { - UUID = uUID; + public void setUUID(String UUID) { + if ( this.UUID != null && !this.UUID.equals( UUID ) ) + log.warn("UUID changed more then once -> OLD : {} , NEW: {} ", this.UUID, UUID ); + this.UUID = UUID; } public String getNormalizedName() { @@ -297,6 +304,8 @@ public abstract class ComponentMetadataDataDefinition extends ToscaDataDefinitio } public void setInvariantUUID(String invariantUUID) { + if ( this.invariantUUID != null && !this.invariantUUID.equals( invariantUUID ) ) + log.warn("InvariantUUID changed more then once -> OLD : {} , NEW: {} ", this.invariantUUID ,invariantUUID ); this.invariantUUID = invariantUUID; } diff --git a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/components/ResourceMetadataDataDefinition.java b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/components/ResourceMetadataDataDefinition.java index 7b112ce129..9675cd37fb 100644 --- a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/components/ResourceMetadataDataDefinition.java +++ b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/components/ResourceMetadataDataDefinition.java @@ -34,6 +34,7 @@ public class ResourceMetadataDataDefinition extends ComponentMetadataDataDefinit private String vendorName; private String vendorRelease; + private String resourceVendorModelNumber; private ResourceTypeEnum resourceType = ResourceTypeEnum.VFC; // ResourceType.VFC // is // default @@ -44,12 +45,14 @@ public class ResourceMetadataDataDefinition extends ComponentMetadataDataDefinit public ResourceMetadataDataDefinition() { super(); + resourceVendorModelNumber = ""; } public ResourceMetadataDataDefinition(ResourceMetadataDataDefinition other) { super(other); this.vendorName = other.getVendorName(); this.vendorRelease = other.getVendorRelease(); + this.resourceVendorModelNumber = other.getResourceVendorModelNumber(); this.isAbstract = other.isHighestVersion(); this.resourceType = other.getResourceType(); this.toscaResourceName = other.getToscaResourceName(); @@ -70,6 +73,15 @@ public class ResourceMetadataDataDefinition extends ComponentMetadataDataDefinit public void setVendorRelease(String vendorRelease) { this.vendorRelease = vendorRelease; } + + public String getResourceVendorModelNumber() { + return resourceVendorModelNumber; + } + + public void setResourceVendorModelNumber(String resourceVendorModelNumber) { + this.resourceVendorModelNumber = resourceVendorModelNumber; + } + public ResourceTypeEnum getResourceType() { return resourceType; @@ -114,7 +126,8 @@ public class ResourceMetadataDataDefinition extends ComponentMetadataDataDefinit @Override public String toString() { return "ResourceMetadataDataDefinition [vendorName=" + vendorName + ", vendorRelease=" + vendorRelease - + ", resourceType=" + resourceType + ", isAbstract=" + isAbstract + super.toString() + "]"; + + ", resourceVendorModelNumber=" + resourceVendorModelNumber + ", resourceType=" + resourceType + + ", isAbstract=" + isAbstract + super.toString() + "]"; } @Override @@ -127,6 +140,7 @@ public class ResourceMetadataDataDefinition extends ComponentMetadataDataDefinit result = prime * result + ((resourceType == null) ? 0 : resourceType.hashCode()); result = prime * result + ((vendorName == null) ? 0 : vendorName.hashCode()); result = prime * result + ((vendorRelease == null) ? 0 : vendorRelease.hashCode()); + result = prime * result + ((resourceVendorModelNumber == null)? 0 : resourceVendorModelNumber.hashCode()); return result; } @@ -170,6 +184,11 @@ public class ResourceMetadataDataDefinition extends ComponentMetadataDataDefinit return false; } else if (!vendorRelease.equals(other.vendorRelease)) return false; + if (resourceVendorModelNumber == null) { + if (other.resourceVendorModelNumber != null) + return false; + } else if (!resourceVendorModelNumber.equals(other.resourceVendorModelNumber)) + return false; return super.equals(obj); } diff --git a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/components/ServiceMetadataDataDefinition.java b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/components/ServiceMetadataDataDefinition.java index 4f3486e457..4a42436583 100644 --- a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/components/ServiceMetadataDataDefinition.java +++ b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/components/ServiceMetadataDataDefinition.java @@ -33,6 +33,8 @@ public class ServiceMetadataDataDefinition extends ComponentMetadataDataDefiniti public static final String EMPTY_STR = ""; private String distributionStatus; + private String serviceType; + private String serviceRole; private Boolean ecompGeneratedNaming = true; @@ -40,10 +42,14 @@ public class ServiceMetadataDataDefinition extends ComponentMetadataDataDefiniti public ServiceMetadataDataDefinition() { super(); + serviceType = ""; + serviceRole = ""; } public ServiceMetadataDataDefinition(ServiceMetadataDataDefinition other) { super(other); + serviceType = other.getServiceType(); + serviceRole = other.getServiceRole(); } public String getDistributionStatus() { @@ -53,6 +59,22 @@ public class ServiceMetadataDataDefinition extends ComponentMetadataDataDefiniti public void setDistributionStatus(String distributionStatus) { this.distributionStatus = distributionStatus; } + + public String getServiceType(){ + return serviceType; + } + + public void setServiceType(String serviceType){ + this.serviceType = serviceType; + } + + public String getServiceRole(){ + return serviceRole; + } + + public void setServiceRole(String serviceRole){ + this.serviceRole = serviceRole; + } public Boolean isEcompGeneratedNaming() { return ecompGeneratedNaming; @@ -73,8 +95,8 @@ public class ServiceMetadataDataDefinition extends ComponentMetadataDataDefiniti @Override public String toString() { return "ServiceMetadataDataDefinition [ distributionStatus=" + distributionStatus - + ", ecompGeneratedNaming=" + ecompGeneratedNaming + ", namingPolicy=" + namingPolicy - + ", parent=" + super.toString() + "]"; + + ", serviceType=" + serviceType + ", serviceRole=" + serviceRole + ", ecompGeneratedNaming=" + + ecompGeneratedNaming + ", namingPolicy=" + namingPolicy + ", parent=" + super.toString() + "]"; } @Override @@ -84,6 +106,8 @@ public class ServiceMetadataDataDefinition extends ComponentMetadataDataDefiniti result = prime * result + ((distributionStatus == null) ? 0 : distributionStatus.hashCode()); result = prime * result + ((ecompGeneratedNaming == null) ? 0 : ecompGeneratedNaming.hashCode()); result = prime * result + ((namingPolicy == null) ? 0 : namingPolicy.hashCode()); + result = prime * result + ((serviceType == null) ? 0 : serviceType.hashCode()); + result = prime * result + ((serviceRole == null) ? 0 : serviceRole.hashCode()); return result; } @@ -117,6 +141,16 @@ public class ServiceMetadataDataDefinition extends ComponentMetadataDataDefiniti return false; } else if (!namingPolicy.equals(other.namingPolicy)) return false; + if (serviceType == null){ + if (other.serviceType != null) + return false; + } else if (!serviceType.equals(other.serviceType)) + return false; + if (serviceRole == null){ + if (other.serviceRole != null) + return false; + } else if (!serviceRole.equals(other.serviceRole)) + return false; return super.equals(obj); } diff --git a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/ListDataDefinition.java b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/ListDataDefinition.java index 424b15059e..6d11c51596 100644 --- a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/ListDataDefinition.java +++ b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/ListDataDefinition.java @@ -25,6 +25,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.function.Predicate; import java.util.stream.Collectors; import org.codehaus.jackson.annotate.JsonCreator; @@ -86,6 +87,11 @@ public class ListDataDefinition extends ToscaData ((ListDataDefinition)other).listToscaDataDefinition = mapByName.values().stream().collect(Collectors.toList()); return other; } - + + @Override + public boolean findUidMatch(String uid){ + return listToscaDataDefinition.stream() + .anyMatch(p -> p.findUidMatch(uid)); + } } diff --git a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/MapDataDefinition.java b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/MapDataDefinition.java index 537d9502cd..741aa39230 100644 --- a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/MapDataDefinition.java +++ b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/MapDataDefinition.java @@ -76,5 +76,17 @@ public class MapDataDefinition extends ToscaDa mapToscaDataDefinition.entrySet().forEach(e -> e.getValue().setOwnerIdIfEmpty(ownerId)); } } + + + public String findKeyByItemUidMatch(String uid){ + if(null == mapToscaDataDefinition) + return null; + Map.Entry entry = mapToscaDataDefinition.entrySet().stream().filter(e -> + e.getValue().findUidMatch(uid)) + .findAny().orElse(null); + if(null == entry) + return null; + return entry.getKey(); + } } diff --git a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/RelationshipInstDataDefinition.java b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/RelationshipInstDataDefinition.java index de9127d08c..0017567031 100644 --- a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/RelationshipInstDataDefinition.java +++ b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/RelationshipInstDataDefinition.java @@ -44,12 +44,12 @@ public class RelationshipInstDataDefinition extends ToscaDataDefinition implemen this.setModificationTime(cdt.getModificationTime()); this.setCapabilityOwnerId(cdt.getCapabilityOwnerId()); this.setRequirementOwnerId(cdt.getRequirementOwnerId()); - this.setCapabiltyId(cdt.getCapabiltyId()); + this.setCapabilityId(cdt.getCapabilityId()); this.setRequirementId(cdt.getRequirementId()); this.setFromId(cdt.getFromId()); this.setToId(cdt.getToId()); this.setRequirement(cdt.getRequirement()); - this.setCapability(cdt.getCapabilty()); + this.setCapability(cdt.getCapability()); } @@ -60,11 +60,11 @@ public class RelationshipInstDataDefinition extends ToscaDataDefinition implemen public String getRequirement() { return (String) getToscaPresentationValue(JsonPresentationFields.REQUIREMENT); } - public void setCapability(String capabilty) { - setToscaPresentationValue(JsonPresentationFields.CAPAPILITY, capabilty); + public void setCapability(String capability) { + setToscaPresentationValue(JsonPresentationFields.CAPAPILITY, capability); } - public String getCapabilty() { + public String getCapability() { return (String) getToscaPresentationValue(JsonPresentationFields.CAPAPILITY); } public void setToId(Object toId) { @@ -87,15 +87,15 @@ public class RelationshipInstDataDefinition extends ToscaDataDefinition implemen setToscaPresentationValue(JsonPresentationFields.REQUIREMENT_ID, requirementId); } - public void setCapabiltyId(Object capabiltyId) { - setToscaPresentationValue(JsonPresentationFields.CAPABILITY_ID, capabiltyId); + public void setCapabilityId(Object capabilityId) { + setToscaPresentationValue(JsonPresentationFields.CAPABILITY_ID, capabilityId); } public String getRequirementId() { return (String) getToscaPresentationValue(JsonPresentationFields.REQUIREMENT_ID); } - public String getCapabiltyId() { + public String getCapabilityId() { return (String) getToscaPresentationValue(JsonPresentationFields.CAPABILITY_ID); } diff --git a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/RequirementDataDefinition.java b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/RequirementDataDefinition.java index 59b14b3060..b32f65f9d3 100644 --- a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/RequirementDataDefinition.java +++ b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/RequirementDataDefinition.java @@ -191,7 +191,7 @@ public class RequirementDataDefinition extends ToscaDataDefinition implements Se public int hashCode() { final int prime = 31; int result = 1; - String name = getUniqueId(); + String name = getName(); String uniqueId = getUniqueId(); String capability = getCapability(); String node = getNode(); @@ -230,7 +230,7 @@ public class RequirementDataDefinition extends ToscaDataDefinition implements Se return false; RequirementDataDefinition other = (RequirementDataDefinition) obj; - String name = getUniqueId(); + String name = getName(); String uniqueId = getUniqueId(); String capability = getCapability(); String node = getNode(); @@ -308,7 +308,7 @@ public class RequirementDataDefinition extends ToscaDataDefinition implements Se @Override public String toString() { - String name = getUniqueId(); + String name = getName(); String uniqueId = getUniqueId(); String capability = getCapability(); String node = getNode(); diff --git a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/enums/JsonPresentationFields.java b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/enums/JsonPresentationFields.java index 9dfc3b602a..d5592995e6 100644 --- a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/enums/JsonPresentationFields.java +++ b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/enums/JsonPresentationFields.java @@ -48,6 +48,9 @@ public enum JsonPresentationFields { DERIVED_FROM ("derivedFrom", null), VENDOR_NAME ("vendorName", null), VENDOR_RELEASE ("vendorRelease", null), + RESOURCE_VENDOR_MODEL_NUMBER ("reourceVendorModelNumber",null), + SERVICE_TYPE ("serviceType", null), + SERVICE_ROLE ("serviceRole", null), CONFORMANCE_LEVEL ("conformanceLevel", null), ICON ("icon", null), TAGS ("tags", null), diff --git a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/enums/OriginTypeEnum.java b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/enums/OriginTypeEnum.java index 0d837762e2..36756e9225 100644 --- a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/enums/OriginTypeEnum.java +++ b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/enums/OriginTypeEnum.java @@ -27,7 +27,9 @@ public enum OriginTypeEnum { VFC("VFC", "VFC (Virtual Function Component)", "resource instance", ComponentTypeEnum.RESOURCE), CP("CP", "CP (Connection Point)", "resource instance", ComponentTypeEnum.RESOURCE), VL("VL", "VL (Virtual Link)", "resource instance", ComponentTypeEnum.RESOURCE), - VFCMT("VFCMT", "VFCMT (VFC Monitoring Template)", "resource instance", ComponentTypeEnum.RESOURCE); + VFCMT("VFCMT", "VFCMT (VFC Monitoring Template)", "resource instance", ComponentTypeEnum.RESOURCE), + CVFC("CVFC", "CVFC (Complex Virtual Function Component)", "resource instance", ComponentTypeEnum.RESOURCE), + PNF("PNF", "PNF (Physical Network Function)", "resource instance", ComponentTypeEnum.RESOURCE); private String value; private String displayValue; diff --git a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/enums/ResourceTypeEnum.java b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/enums/ResourceTypeEnum.java index d3652c238f..182657e125 100644 --- a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/enums/ResourceTypeEnum.java +++ b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/enums/ResourceTypeEnum.java @@ -27,8 +27,14 @@ package org.openecomp.sdc.be.datatypes.enums; */ public enum ResourceTypeEnum { - VFC("VFC (Virtual Function Component)"), VF("VF"/* (Virtual Function)" */), CP("CP (Connection Point)"), - VL( "VL (Virtual Link)"), VFCMT("VFCMT (VFC Monitoring Template)"), ABSTRACT("Abstract (Generic VFC/VF/Service Type)"); + VFC("VFC (Virtual Function Component)"), + VF("VF"/* (Virtual Function)" */), + CP("CP (Connection Point)"), + PNF("PNF"/* (Physical Network Function)" */), + CVFC("CVFC"/*Complex Virtual Function Component*/), + VL( "VL (Virtual Link)"), + VFCMT("VFCMT (VFC Monitoring Template)"), + ABSTRACT("Abstract (Generic VFC/VF/PNF/Service Type)"); private String value; @@ -85,7 +91,7 @@ public enum ResourceTypeEnum { return false; } /** - * Checks if enum exist with given type ignare case + * Checks if enum exist with given type ignore case * @param type * @return */ diff --git a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/tosca/ToscaDataDefinition.java b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/tosca/ToscaDataDefinition.java index eba27fb48b..df73adaa4a 100644 --- a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/tosca/ToscaDataDefinition.java +++ b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/tosca/ToscaDataDefinition.java @@ -100,4 +100,8 @@ public abstract class ToscaDataDefinition { return null == dataList? new HashMap<>() : dataList.stream() .collect(Collectors.toMap(p -> (String)p.getToscaPresentationValue(JsonPresentationFields.NAME), p -> p)); } + + public boolean findUidMatch(String uid){ + return uid.equals(getToscaPresentationValue(JsonPresentationFields.UNIQUE_ID)); + } } diff --git a/pom.xml b/pom.xml index b1dfc96bcd..22ff9bbed8 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ -SNAPSHOT UTF-8 - 73 + 74 3.3.2 diff --git a/sdc-os-chef/sdc-backend/chef-repo/cookbooks/sdc-catalog-be/templates/default/BE-configuration.yaml.erb b/sdc-os-chef/sdc-backend/chef-repo/cookbooks/sdc-catalog-be/templates/default/BE-configuration.yaml.erb index 7cf8d6b7b8..e687804556 100644 --- a/sdc-os-chef/sdc-backend/chef-repo/cookbooks/sdc-catalog-be/templates/default/BE-configuration.yaml.erb +++ b/sdc-os-chef/sdc-backend/chef-repo/cookbooks/sdc-catalog-be/templates/default/BE-configuration.yaml.erb @@ -22,7 +22,7 @@ beProtocol: http beSslPort: <%= @ssl_port %> version: 1.0 released: 2012-11-30 -toscaConformanceLevel: 3.0 +toscaConformanceLevel: 4.0 minToscaConformanceLevel: 3.0 titanCfgFile: /var/lib/jetty/config/catalog-be/titan.properties @@ -80,6 +80,7 @@ cassandraConfig: - { name: sdcaudit, replicationStrategy: NetworkTopologyStrategy, replicationInfo: ['<%= @DC_NAME %>','<%= @rep_factor %>']} - { name: sdcartifact, replicationStrategy: NetworkTopologyStrategy, replicationInfo: ['<%= @DC_NAME %>','<%= @rep_factor %>']} - { name: sdccomponent, replicationStrategy: NetworkTopologyStrategy, replicationInfo: ['<%= @DC_NAME %>','<%= @rep_factor %>']} + - { name: sdcrepository, replicationStrategy: NetworkTopologyStrategy, replicationInfo: ['<%= @DC_NAME %>','<%= @rep_factor %>']} #Application-specific settings of ES elasticSearch: @@ -525,6 +526,7 @@ onboarding: host: <%= @host_ip %> port: <%= @catalog_port %> downloadCsarUri: "/onboarding-api/v1.0/vendor-software-products/packages" + healthCheckUri: "/onboarding-api/v1.0/healthcheck" # #GSS IDNS diff --git a/sdc-os-chef/sdc-cassandra/chef-repo/cookbooks/cassandra-actions/templates/default/configuration.yaml.erb b/sdc-os-chef/sdc-cassandra/chef-repo/cookbooks/cassandra-actions/templates/default/configuration.yaml.erb index 4d5f979f56..bc96582615 100644 --- a/sdc-os-chef/sdc-cassandra/chef-repo/cookbooks/cassandra-actions/templates/default/configuration.yaml.erb +++ b/sdc-os-chef/sdc-cassandra/chef-repo/cookbooks/cassandra-actions/templates/default/configuration.yaml.erb @@ -22,7 +22,8 @@ beProtocol: http beSslPort: <%= @ssl_port %> version: 1.0 released: 2012-11-30 -toscaConformanceLevel: 3.0 +toscaConformanceLevel: 4.0 +minToscaConformanceLevel: 3.0 titanCfgFile: <%= @titan_Path %>/titan.properties titanInMemoryGraph: false @@ -80,6 +81,7 @@ cassandraConfig: - { name: sdcaudit, replicationStrategy: NetworkTopologyStrategy, replicationInfo: ['<%= @DC_NAME %>','<%= @rep_factor %>']} - { name: sdcartifact, replicationStrategy: NetworkTopologyStrategy, replicationInfo: ['<%= @DC_NAME %>','<%= @rep_factor %>']} - { name: sdccomponent, replicationStrategy: NetworkTopologyStrategy, replicationInfo: ['<%= @DC_NAME %>','<%= @rep_factor %>']} + - { name: sdcrepository, replicationStrategy: NetworkTopologyStrategy, replicationInfo: ['<%= @dc1 %>','<%= @rep_factor %>']} #Application-specific settings of ES elasticSearch: @@ -519,6 +521,7 @@ onboarding: host: <%= @host_ip %> port: <%= @catalog_port %> downloadCsarUri: "/onboarding-api/v1.0/vendor-software-products/packages" + healthCheckUri: "/onboarding-api/v1.0/healthcheck" # #GSS IDNS diff --git a/sdc-os-chef/sdc-os-common/templates/default/BE-configuration.yaml.erb b/sdc-os-chef/sdc-os-common/templates/default/BE-configuration.yaml.erb index b26cd9019c..1fa30f8c49 100644 --- a/sdc-os-chef/sdc-os-common/templates/default/BE-configuration.yaml.erb +++ b/sdc-os-chef/sdc-os-common/templates/default/BE-configuration.yaml.erb @@ -22,7 +22,7 @@ beProtocol: http beSslPort: <%= @ssl_port %> version: 1.0 released: 2012-11-30 -toscaConformanceLevel: 3.0 +toscaConformanceLevel: 4.0 minToscaConformanceLevel: 3.0 titanCfgFile: <%= @titan_Path %>/titan.properties @@ -67,7 +67,7 @@ users: cassandraConfig: cassandraHosts: [<%= @cassandra_ip %>] - localDataCenter: + localDataCenter: <%= @dc1 %> reconnectTimeout : 30000 authenticate: true username: asdc_user @@ -80,6 +80,8 @@ cassandraConfig: - { name: sdcaudit, replicationStrategy: NetworkTopologyStrategy, replicationInfo: ['<%= @DC_NAME %>','<%= @rep_factor %>']} - { name: sdcartifact, replicationStrategy: NetworkTopologyStrategy, replicationInfo: ['<%= @DC_NAME %>','<%= @rep_factor %>']} - { name: sdccomponent, replicationStrategy: NetworkTopologyStrategy, replicationInfo: ['<%= @DC_NAME %>','<%= @rep_factor %>']} + - { name: sdcrepository, replicationStrategy: NetworkTopologyStrategy, replicationInfo: ['<%= @dc1 %>', '<%= @rep_factor %>']} + - { name: sdcrepository, replicationStrategy: NetworkTopologyStrategy, replicationInfo: ['<%= @dc1 %>', '<%= @rep_factor %>', '<%= @dc2 %>', '<%= @rep_factor %>']} #Application-specific settings of ES elasticSearch: @@ -140,6 +142,7 @@ resourceTypes: &allResourceTypes - VF - VFCMT - Abstract + - CVFC # validForResourceTypes usage # validForResourceTypes: @@ -176,6 +179,8 @@ toscaArtifacts: #Informational artifacts placeHolder excludeResourceCategory: - Generic +excludeResourceType: + - PNF informationalResourceArtifacts: features: displayName: Features @@ -484,7 +489,15 @@ resourceInformationalArtifacts: validForResourceTypes: *allResourceTypes OTHER: acceptedTypes: - validForResourceTypes: *allResourceTypes + validForResourceTypes: + - VFC + - CVFC + - CP + - VL + - VF + - VFCMT + - Abstract + - PNF SNMP_POLL: acceptedTypes: validForResourceTypes: *allResourceTypes @@ -496,6 +509,7 @@ resourceInformationalArtifacts: validForResourceTypes: - VF - VFC + - CVFC resourceInformationalDeployedArtifacts: @@ -525,6 +539,7 @@ onboarding: host: <%= @host_ip %> port: <%= @catalog_port %> downloadCsarUri: "/onboarding-api/v1.0/vendor-software-products/packages" + healthCheckUri: "/onboarding-api/v1.0/healthcheck" # #GSS IDNS @@ -584,6 +599,8 @@ vfModuleProperties: genericAssetNodeTypes: VFC: org.openecomp.resource.abstract.nodes.VFC + CVFC: org.openecomp.resource.abstract.nodes.VFC VF : org.openecomp.resource.abstract.nodes.VF + PNF: org.openecomp.resource.abstract.nodes.PNF Service: org.openecomp.resource.abstract.nodes.service diff --git a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/api/Urls.java b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/api/Urls.java index 3977f16d5a..ea1c9eff8d 100644 --- a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/api/Urls.java +++ b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/api/Urls.java @@ -117,19 +117,19 @@ public interface Urls { // *****************************************ECOMP User // URL's***************************************************** - final String ECOMP_PUSH_USER = "http://%s:%s/api/user"; + final String ECOMP_PUSH_USER = "http://%s:%s/api/v2/user"; - final String ECOMP_EDIT_USER = "http://%s:%s/api/user/%s"; + final String ECOMP_EDIT_USER = "http://%s:%s/api/v2/user/%s"; - final String ECOMP_GET_USER = "http://%s:%s/api/user/%s"; + final String ECOMP_GET_USER = "http://%s:%s/api/v2/user/%s"; - final String ECOMP_GET_ALL_USERS = "http://%s:%s/api/users"; + final String ECOMP_GET_ALL_USERS = "http://%s:%s/api/v2/users"; - final String ECOMP_GET_ALL_AVAILABLE_ROLES = "http://%s:%s/api/roles"; + final String ECOMP_GET_ALL_AVAILABLE_ROLES = "http://%s:%s/api/v2/roles"; - final String ECOMP_PUSH_USER_ROLES = "http://%s:%s/api/user/%s/roles"; + final String ECOMP_PUSH_USER_ROLES = "http://%s:%s/api/v2/user/%s/roles"; - final String ECOMP_GET_USER_ROLES = "http://%s:%s/api/user/%s/roles"; + final String ECOMP_GET_USER_ROLES = "http://%s:%s/api/v2/user/%s/roles"; // *****************************************Elements************************************************************* final String GET_TAGS_LIST = "http://%s:%s/sdc2/rest/v1/tags"; diff --git a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/execute/attribute/ComponentInstanceAttributeTest.java b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/execute/attribute/ComponentInstanceAttributeTest.java index b1d04ba88d..537a70984e 100644 --- a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/execute/attribute/ComponentInstanceAttributeTest.java +++ b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/execute/attribute/ComponentInstanceAttributeTest.java @@ -74,7 +74,7 @@ public class ComponentInstanceAttributeTest extends ComponentBaseTest { .filter(att -> att.getName().equals("private_address")).findAny().get(); // update attribute on vfc instance final Resource vfWithInsatncePreUpdate = swallowException( - () -> (Resource) AtomicOperationUtils.getCompoenntObject(vf, UserRoleEnum.DESIGNER)); + () -> (Resource) AtomicOperationUtils.getComponentObject(vf, UserRoleEnum.DESIGNER)); ComponentInstanceProperty attributeOfRI = attributeGetter.apply(vfWithInsatncePreUpdate); final String newAttValue = "NewValue"; attributeOfRI.setValue(newAttValue); @@ -86,7 +86,7 @@ public class ComponentInstanceAttributeTest extends ComponentBaseTest { BaseRestUtils.acceptHeaderData)); // Retrieve updated vf and verify attribute was updated final Resource vfWithInsatncePostUpdate = swallowException( - () -> (Resource) AtomicOperationUtils.getCompoenntObject(vf, UserRoleEnum.DESIGNER)); + () -> (Resource) AtomicOperationUtils.getComponentObject(vf, UserRoleEnum.DESIGNER)); ComponentInstanceProperty updatedAttribute = attributeGetter.apply(vfWithInsatncePostUpdate); assertEquals(updatedAttribute.getValue(), newAttValue); diff --git a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/execute/devCI/AndreyTest.java b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/execute/devCI/AndreyTest.java index 6e36e1b675..45c6b18b59 100644 --- a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/execute/devCI/AndreyTest.java +++ b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/execute/devCI/AndreyTest.java @@ -45,26 +45,33 @@ import org.testng.annotations.Test; public class AndreyTest { + private static ToscaDefinition parseToscaYamlToJavaObject; + + public static void main(String[] args) throws Exception { ToscaDefinition toscaDefinition; System.out.println("start " + new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format(new Date())); // File path = new File("C:/Data/D2.0/TOSCA_Ex/Definitions/tosca_definition_version.yaml"); // File path = new File("C:/Data/D2.0/TOSCA_Ex/resource-Vl11Vl10-template.yml"); - File path = new File("C:/Data/D2.0/TOSCA_Ex/service-Servicepxtc-template US822998.yml"); - File csarPath = new File("C:/Data/D2.0/TOSCA_Ex/Nested.csar"); +// File path = new File("C:/Data/D2.0/TOSCA_Ex/service-Servicepxtc-template US822998.yml"); +// File path = new File("C:/Data/FileToParse/Definitions/service-Ciservice513e6fa67d07-template.yml"); + toscaDefinition = ToscaParserUtils.parseToscaMainYamlToJavaObjectByCsarLocation(new File("C:/Data/FileToParse/LDSA/LDSA_amdocs.csar")); +// File path = new File("C:/Data/FileToParse/Definitions/resource-Civfonboarded2016006VvmVvm301607E2100a9b04-template.yml"); +// File csarPath = new File("C:/Data/D2.0/TOSCA_Ex/Nested.csar"); - toscaDefinition = ToscaParserUtils.parseToscaYamlToJavaObject(path); + +// toscaDefinition = ToscaParserUtils.parseToscaYamlToJavaObject(path); System.out.println("listTypeHeatMetaDefinition start " + new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format(new Date())); - List listTypeHeatMetaDefinition = CsarParserUtils.getListTypeHeatMetaDefinition(csarPath); +// List listTypeHeatMetaDefinition = CsarParserUtils.getListTypeHeatMetaDefinition(csarPath); System.out.println("get service start " + new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format(new Date())); - System.out.println(listTypeHeatMetaDefinition); - for(TypeHeatMetaDefinition typeHeatMetaDefinition : listTypeHeatMetaDefinition){ - for(GroupHeatMetaDefinition groupHeatMetaDefinition : typeHeatMetaDefinition.getGroupHeatMetaDefinition()){ - List artifactList = groupHeatMetaDefinition.getArtifactList(); - boolean isBase = groupHeatMetaDefinition.getPropertyHeatMetaDefinition().getValue(); - } - - } +// System.out.println(listTypeHeatMetaDefinition); +// for(TypeHeatMetaDefinition typeHeatMetaDefinition : listTypeHeatMetaDefinition){ +// for(GroupHeatMetaDefinition groupHeatMetaDefinition : typeHeatMetaDefinition.getGroupHeatMetaDefinition()){ +// List artifactList = groupHeatMetaDefinition.getArtifactList(); +// boolean isBase = groupHeatMetaDefinition.getPropertyHeatMetaDefinition().getValue(); +// } +// +// } System.out.println("Finished"); System.out.println("get service start " + new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format(new Date())); } diff --git a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/execute/general/BasicHttpAuthenticationTest.java b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/execute/general/BasicHttpAuthenticationTest.java index c52ee470cf..66bc153e70 100644 --- a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/execute/general/BasicHttpAuthenticationTest.java +++ b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/execute/general/BasicHttpAuthenticationTest.java @@ -238,7 +238,7 @@ public class BasicHttpAuthenticationTest extends ComponentBaseTest { assertTrue(restResponse.getHeaderFields().containsKey(WWW_AUTHENTICATE)); List getAuthenticateHeader = restResponse.getHeaderFields().get(WWW_AUTHENTICATE); assertEquals("www-authenticate header contains more then one value", 1, getAuthenticateHeader.size()); - assertTrue(getAuthenticateHeader.get(0).equals("Basic realm=" + "\"ASDC\"")); + assertTrue(getAuthenticateHeader.get(0).equals("Basic realm=" + "\"SDC\"")); validateAuditAuthentication("", AUTH_REQUIRED, ComponentTypeEnum.SERVICE); } diff --git a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/execute/imports/ImportToscaResourceTest.java b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/execute/imports/ImportToscaResourceTest.java index 8ce8dc5433..b460b9fce0 100644 --- a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/execute/imports/ImportToscaResourceTest.java +++ b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/execute/imports/ImportToscaResourceTest.java @@ -1816,8 +1816,8 @@ public class ImportToscaResourceTest extends ComponentBaseTest { importReqDetailsFather.compareRequirementsOrCapabilities(capabilities, capabilitiesFromResponse); } - // DE202329 - @Test(enabled = false) + // DE202329 - TDP -154379 + @Test(enabled = true) public void requirementWithMissingTypeTest() throws Exception { String fatherName = "father"; String fatherFileName = "DerivedFromWebApplication_HasNoReqType.yml"; diff --git a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/sanity/MultipleResourceUpdate.java b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/sanity/MultipleResourceUpdate.java index 0a7b4a98aa..a33ee71f9e 100644 --- a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/sanity/MultipleResourceUpdate.java +++ b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/sanity/MultipleResourceUpdate.java @@ -86,7 +86,7 @@ public class MultipleResourceUpdate extends ComponentBaseTest { ComponentInstance instanceCP2 = AtomicOperationUtils .addComponentInstanceToComponentContainer(cp2, vf, UserRoleEnum.DESIGNER, true).left().value(); - vf = (Resource) AtomicOperationUtils.getCompoenntObject(vf, UserRoleEnum.DESIGNER); + vf = (Resource) AtomicOperationUtils.getComponentObject(vf, UserRoleEnum.DESIGNER); // Create Vertex(Link/Associate 2 Resource Instances on Canvas) AtomicOperationUtils.associate2ResourceInstances(vf, instanceCP1, instanceVL, AssocType.LINKABLE.getAssocType(), diff --git a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/tosca/datatypes/ToscaDefinition.java b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/tosca/datatypes/ToscaDefinition.java index 5a89a6766c..18b2329663 100644 --- a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/tosca/datatypes/ToscaDefinition.java +++ b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/tosca/datatypes/ToscaDefinition.java @@ -111,7 +111,7 @@ public class ToscaDefinition { typeDescription.putMapPropertyType("metadata", String.class, String.class); // TODO Andrey imports format typeDescription.putMapPropertyType("imports", String.class, ToscaImportsDefinition.class); - typeDescription.putListPropertyType("imports", List.class); +// typeDescription.putListPropertyType("imports", List.class); typeDescription.putMapPropertyType("node_types", String.class, ToscaNodeTypesDefinition.class); return typeDescription; } diff --git a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/tosca/datatypes/ToscaParameterConstants.java b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/tosca/datatypes/ToscaParameterConstants.java new file mode 100644 index 0000000000..18d7d7d97b --- /dev/null +++ b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/tosca/datatypes/ToscaParameterConstants.java @@ -0,0 +1,9 @@ +package org.openecomp.sdc.ci.tests.tosca.datatypes; + +public interface ToscaParameterConstants { + + public static final String ENTRY_DEFINITION = "Entry-Definitions"; + public static final String TOSCA_META_PATH = "TOSCA-Metadata/TOSCA.meta"; + public static final String HEAT_META_PATH = "Artifacts/HEAT.meta"; + public static final String IMPORT_STRUCTURE = "importStructure"; +} diff --git a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/CsarParserUtils.java b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/CsarParserUtils.java index 69c8b2fe2f..cd6687be0e 100644 --- a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/CsarParserUtils.java +++ b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/CsarParserUtils.java @@ -30,11 +30,13 @@ import java.util.Set; import org.json.simple.JSONArray; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; import org.openecomp.sdc.ci.tests.datatypes.GroupHeatMetaDefinition; import org.openecomp.sdc.ci.tests.datatypes.HeatMetaFirstLevelDefinition; import org.openecomp.sdc.ci.tests.datatypes.PropertyHeatMetaDefinition; import org.openecomp.sdc.ci.tests.datatypes.TypeHeatMetaDefinition; import org.openecomp.sdc.ci.tests.datatypes.enums.ArtifactTypeEnum; +import org.openecomp.sdc.ci.tests.tosca.datatypes.ToscaParameterConstants; import org.openecomp.sdc.ci.tests.utils.validation.CsarValidationUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -42,40 +44,34 @@ import org.slf4j.LoggerFactory; public class CsarParserUtils { private static Logger log = LoggerFactory.getLogger(CsarValidationUtils.class.getName()); - public static List getListTypeHeatMetaDefinition(File csarUUID) throws Exception { - - String artifactHeatMetaLocation = "Artifacts/HEAT.meta"; - JSONParser parser = new JSONParser(); - String csarPayload = CsarValidationUtils.getCsarPayload(csarUUID, artifactHeatMetaLocation); - if (csarPayload != null) { - Object parse = parser.parse(csarPayload); - JSONObject jsonObject = (JSONObject) parse; - JSONObject jsonObjectImportStructure = (JSONObject) jsonObject.get("importStructure"); - List listHeatMetaDefenition = new ArrayList(); - listHeatMetaDefenition = getArtifactsByGroup(jsonObjectImportStructure, listHeatMetaDefenition); - return listHeatMetaDefenition; - } - return null; + public static List getListTypeHeatMetaDefinition(File csarFileLocation) throws Exception { + String artifactHeatMetaLocation = ToscaParameterConstants.HEAT_META_PATH; + String csarPayload = ToscaParserUtils.getYamlPayloadFromCsar(csarFileLocation, artifactHeatMetaLocation); + return getListTypeHeatMetaDefinitionByPayload(csarPayload); } - + public static List getListTypeHeatMetaDefinition(String csarUUID) throws Exception { + + String artifactHeatMetaLocation = ToscaParameterConstants.HEAT_META_PATH; + String csarPayload = ToscaParserUtils.getCsarPayload(csarUUID, artifactHeatMetaLocation); + return getListTypeHeatMetaDefinitionByPayload(csarPayload); + } - String artifactHeatMetaLocation = "Artifacts/HEAT.meta"; + public static List getListTypeHeatMetaDefinitionByPayload(String csarPayload) throws ParseException { JSONParser parser = new JSONParser(); - String csarPayload = CsarValidationUtils.getCsarPayload(csarUUID, artifactHeatMetaLocation); if (csarPayload != null) { Object parse = parser.parse(csarPayload); JSONObject jsonObject = (JSONObject) parse; - JSONObject jsonObjectImportStructure = (JSONObject) jsonObject.get("importStructure"); + JSONObject jsonObjectImportStructure = (JSONObject) jsonObject.get(ToscaParameterConstants.IMPORT_STRUCTURE); List listHeatMetaDefenition = new ArrayList(); listHeatMetaDefenition = getArtifactsByGroup(jsonObjectImportStructure, listHeatMetaDefenition); return listHeatMetaDefenition; } return null; - } + protected static List getArtifactsByGroup(JSONObject jsonObjectImportStructure, List listHeatMetaDefenition) { @SuppressWarnings("unchecked") diff --git a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/ToscaParserUtils.java b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/ToscaParserUtils.java index 26fac7fd6e..3bae41fc57 100644 --- a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/ToscaParserUtils.java +++ b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/ToscaParserUtils.java @@ -21,19 +21,30 @@ package org.openecomp.sdc.ci.tests.utils; import static org.testng.AssertJUnit.assertNotNull; +import static org.testng.AssertJUnit.assertTrue; import java.io.File; import java.io.FileInputStream; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.Map; import java.util.Set; import org.openecomp.sdc.ci.tests.datatypes.enums.ToscaKeysEnum; +import org.openecomp.sdc.ci.tests.datatypes.enums.UserRoleEnum; import org.openecomp.sdc.ci.tests.tosca.datatypes.ToscaDefinition; import org.openecomp.sdc.ci.tests.tosca.datatypes.ToscaGroupsTopologyTemplateDefinition; import org.openecomp.sdc.ci.tests.tosca.datatypes.ToscaNodeTemplatesTopologyTemplateDefinition; +import org.openecomp.sdc.ci.tests.tosca.datatypes.ToscaParameterConstants; import org.openecomp.sdc.ci.tests.tosca.datatypes.ToscaSubstitutionMappingsDefinition; import org.openecomp.sdc.ci.tests.tosca.datatypes.ToscaTopologyTemplateDefinition; +import org.openecomp.sdc.ci.tests.utils.general.ElementFactory; +import org.openecomp.sdc.ci.tests.utils.rest.BaseRestUtils; +import org.openecomp.sdc.ci.tests.utils.rest.ImportRestUtils; import org.openecomp.sdc.ci.tests.utils.validation.CsarValidationUtils; +import org.openecomp.sdc.common.rest.api.RestResponseAsByteArray; +import org.openecomp.sdc.common.util.ZipUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.yaml.snakeyaml.TypeDescription; @@ -45,20 +56,56 @@ public class ToscaParserUtils { private static Logger log = LoggerFactory.getLogger(ToscaParserUtils.class.getName()); - public static ToscaDefinition parseToscaYamlToJavaObject(String csarUUID) throws Exception { + + /**method get csarUUID and send GET API request toward BE + * @param csarUUID + * @return + * @throws Exception + */ + public static ToscaDefinition parseToscaYamlToJavaObjectByCsarUuid(String csarUUID) throws Exception { ToscaDefinition toscaDefinition = null; - String TOSCAMetaLocation = "TOSCA-Metadata/TOSCA.meta"; + String TOSCAMetaLocation = ToscaParameterConstants.TOSCA_META_PATH; Map map = getToscaYamlMap(csarUUID, TOSCAMetaLocation); assertNotNull("Tosca Entry-Definitions is null", map); if (map != null) { - File definitionYamlLocation = (File) map.get("Entry-Definitions"); + File definitionYamlLocation = (File) map.get(ToscaParameterConstants.ENTRY_DEFINITION); toscaDefinition = parseToscaYamlToJavaObject(definitionYamlLocation); } return toscaDefinition; } + /**method read csar from location + * @param csarNameLocation - full path with csar name + * @return + * @throws Exception + */ + public static ToscaDefinition parseToscaMainYamlToJavaObjectByCsarLocation(File csarNameLocation) throws Exception { + + ToscaDefinition toscaDefinition = null; + String TOSCAMetaLocation = ToscaParameterConstants.TOSCA_META_PATH; +// read file location of main yaml file(location+name) from TOSCA.meta file by + Map map = getToscaYamlMap(csarNameLocation, TOSCAMetaLocation); + + assertNotNull("Tosca Entry-Definitions is null", map); + + String definitionYamlLocation = (String) map.get(ToscaParameterConstants.ENTRY_DEFINITION); + String csarPayload = getYamlPayloadFromCsar(csarNameLocation, definitionYamlLocation); + toscaDefinition = parseToscaYamlPayloadToJavaObject(csarPayload); + return toscaDefinition; + + } + + public static ToscaDefinition parseToscaAnyYamlToJavaObjectByCsarLocation(File csarNameLocation, String yamlLocation) throws Exception { + + ToscaDefinition toscaDefinition = null; + String csarPayload = getYamlPayloadFromCsar(csarNameLocation, yamlLocation); + toscaDefinition = parseToscaYamlPayloadToJavaObject(csarPayload); + return toscaDefinition; + + } + public static ToscaDefinition parseToscaYamlToJavaObject(File path) throws Exception { ToscaDefinition toscaDefinition = null; @@ -72,7 +119,7 @@ public class ToscaParserUtils { System.out.println("Exception: " + e); } - Constructor constructor = getConstructor(); + Constructor constructor = initToscaDefinitionObject(); Yaml yaml = new Yaml(constructor); try { @@ -90,7 +137,7 @@ public class ToscaParserUtils { public static ToscaDefinition parseToscaYamlPayloadToJavaObject(String payload){ ToscaDefinition toscaDefinition = null; - Constructor constructor = getConstructor(); + Constructor constructor = initToscaDefinitionObject(); Yaml yaml = new Yaml(constructor); try { @@ -104,23 +151,33 @@ public class ToscaParserUtils { } - public static Constructor getConstructor() { - Constructor constructor = new Constructor(ToscaDefinition.class); - constructor.addTypeDescription(ToscaDefinition.getTypeDescription()); - constructor.addTypeDescription(ToscaTopologyTemplateDefinition.getTypeDescription()); - constructor.addTypeDescription(ToscaNodeTemplatesTopologyTemplateDefinition.getTypeDescription()); - constructor.addTypeDescription(ToscaGroupsTopologyTemplateDefinition.getTypeDescription()); - constructor.addTypeDescription(ToscaSubstitutionMappingsDefinition.getTypeDescription()); + public static Constructor initToscaDefinitionObject() { + Constructor toscaStructure = new Constructor(ToscaDefinition.class); + toscaStructure.addTypeDescription(ToscaDefinition.getTypeDescription()); + toscaStructure.addTypeDescription(ToscaTopologyTemplateDefinition.getTypeDescription()); + toscaStructure.addTypeDescription(ToscaNodeTemplatesTopologyTemplateDefinition.getTypeDescription()); + toscaStructure.addTypeDescription(ToscaGroupsTopologyTemplateDefinition.getTypeDescription()); + toscaStructure.addTypeDescription(ToscaSubstitutionMappingsDefinition.getTypeDescription()); // Skip properties which are found in YAML, but not found in POJO PropertyUtils propertyUtils = new PropertyUtils(); propertyUtils.setSkipMissingProperties(true); - constructor.setPropertyUtils(propertyUtils); - return constructor; + toscaStructure.setPropertyUtils(propertyUtils); + return toscaStructure; } - public static Map getToscaYamlMap(String csarUUID, String fileLocation) throws Exception { - String csarPayload = CsarValidationUtils.getCsarPayload(csarUUID, fileLocation); + public static Map getToscaYamlMap(String csarUUID, String yamlFileLocation) throws Exception { + String csarPayload = getCsarPayload(csarUUID, yamlFileLocation); + if (csarPayload != null) { + Yaml yaml = new Yaml(); + Map map = (Map) yaml.load(csarPayload); + return map; + } + return null; + } + + public static Map getToscaYamlMap(File csarPath, String yamlFileLocation) throws Exception { + String csarPayload = getYamlPayloadFromCsar(csarPath, yamlFileLocation); if (csarPayload != null) { Yaml yaml = new Yaml(); Map map = (Map) yaml.load(csarPayload); @@ -129,6 +186,39 @@ public class ToscaParserUtils { return null; } + + public static String getCsarPayload(String csarName, String yamlFileLocation) throws Exception { + + RestResponseAsByteArray csar = ImportRestUtils.getCsar(csarName, ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER)); + assertTrue("Return response code different from 200", csar.getHttpStatusCode() == BaseRestUtils.STATUS_CODE_SUCCESS); + byte[] data = csar.getResponse(); + return getDataFromZipFileByBytes(yamlFileLocation, data); + + } + + public static String getYamlPayloadFromCsar(File csarName, String fileLocation) throws Exception { + + Path path = csarName.toPath(); + byte[] data = Files.readAllBytes(path); + return getDataFromZipFileByBytes(fileLocation, data); + + } + + /** method get file data from zip data by file location in the zip structure + * @param fileLocation + * @param data + * @return + */ + public static String getDataFromZipFileByBytes(String fileLocation, byte[] data) { + Map readZip = null; + if (data != null && data.length > 0) { + readZip = ZipUtil.readZip(data); + + } + byte[] artifactsBs = readZip.get(fileLocation); + String str = new String(artifactsBs, StandardCharsets.UTF_8); + return str; + } /* public static Map getToscaYamlMap(String csarUUID, String fileLocation) throws Exception { String csarPayload = CsarValidationUtils.getCsarPayload(csarUUID, fileLocation); if (csarPayload != null) { diff --git a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/general/AtomicOperationUtils.java b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/general/AtomicOperationUtils.java index 207c4bbe02..17148ce8a9 100644 --- a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/general/AtomicOperationUtils.java +++ b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/general/AtomicOperationUtils.java @@ -261,7 +261,7 @@ public final class AtomicOperationUtils { LifeCycleStatesEnum curentCompState = LifeCycleStatesEnum.findByCompState(component.getLifecycleState().toString()); if (curentCompState == targetState) { - component = getCompoenntObject(component, userRole); + component = getComponentObject(component, userRole); return Pair.of(component, null); } // List lifeCycleStatesEnumOrigList = new @@ -299,7 +299,7 @@ public final class AtomicOperationUtils { } } - Component componentJavaObject = getCompoenntObject(component, userRole); + Component componentJavaObject = getComponentObject(component, userRole); if (validateState == true && isValidationFailed == true) { assertTrue("change state failed" + lifeCycleStatesResponse.getResponse(), false); @@ -431,6 +431,12 @@ public final class AtomicOperationUtils { Service container = ResponseParser.convertServiceResponseToJavaObject(serviceResponse.getResponse()); return container; } + + public static Service getServiceObject(String uniqueId) throws Exception { + RestResponse serviceResponse = ServiceRestUtils.getService(uniqueId); + Service container = ResponseParser.convertServiceResponseToJavaObject(serviceResponse.getResponse()); + return container; + } public static Product getProductObject(Component containerDetails, UserRoleEnum userRole) throws Exception { User defaultUser = ElementFactory.getDefaultUser(userRole); @@ -439,7 +445,7 @@ public final class AtomicOperationUtils { return container; } - public static Component getCompoenntObject(Component containerDetails, UserRoleEnum userRole) throws Exception { + public static Component getComponentObject(Component containerDetails, UserRoleEnum userRole) throws Exception { User defaultUser = ElementFactory.getDefaultUser(userRole); switch (containerDetails.getComponentType()) { @@ -521,7 +527,7 @@ public final class AtomicOperationUtils { if (changeComponentInstanceVersionResp.getErrorCode() == BaseRestUtils.STATUS_CODE_SUCCESS) { - Component compoenntObject = AtomicOperationUtils.getCompoenntObject(containerDetails, userRole); + Component compoenntObject = AtomicOperationUtils.getComponentObject(containerDetails, userRole); ComponentInstance componentInstanceJavaObject = ResponseParser.convertComponentInstanceResponseToJavaObject(changeComponentInstanceVersionResp.getResponse()); return Either.left(Pair.of(compoenntObject, componentInstanceJavaObject)); diff --git a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/rest/CatalogRestUtils.java b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/rest/CatalogRestUtils.java index 25fce34a75..e387cd2544 100644 --- a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/rest/CatalogRestUtils.java +++ b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/rest/CatalogRestUtils.java @@ -21,8 +21,7 @@ package org.openecomp.sdc.ci.tests.utils.rest; import java.io.IOException; -import java.util.HashMap; -import java.util.Map; +import java.util.*; import org.openecomp.sdc.ci.tests.api.Urls; import org.openecomp.sdc.ci.tests.config.Config; diff --git a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/rest/LifecycleRestUtils.java b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/rest/LifecycleRestUtils.java index d53d2da91b..22a352cbfe 100644 --- a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/rest/LifecycleRestUtils.java +++ b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/rest/LifecycleRestUtils.java @@ -262,19 +262,14 @@ public class LifecycleRestUtils extends BaseRestUtils { LifeCycleStatesEnum LifeCycleStatesEnum) throws Exception { Config config = Utils.getConfig(); String url = String.format(Urls.CHANGE_COMPONENT_LIFECYCLE_STATE, config.getCatalogBeHost(), - config.getCatalogBePort(), ComponentTypeEnum.findParamByType(component.getComponentType()), - component.getUniqueId(), LifeCycleStatesEnum); - RestResponse LifeCycleStatesEnumServiceResponse = sendPost(url, createLifecycleCommentJson(COMMENT), - sdncModifierDetails.getUserId(), acceptHeaderData); + config.getCatalogBePort(), ComponentTypeEnum.findParamByType(component.getComponentType()), component.getUniqueId(), LifeCycleStatesEnum); + RestResponse LifeCycleStatesEnumServiceResponse = sendPost(url, createLifecycleCommentJson(COMMENT), sdncModifierDetails.getUserId(), acceptHeaderData); if (LifeCycleStatesEnumServiceResponse.getErrorCode() == STATUS_CODE_SUCCESS) { - String productUniqueId = ResponseParser - .getValueFromJsonResponse(LifeCycleStatesEnumServiceResponse.getResponse(), "uniqueId"); + String productUniqueId = ResponseParser.getValueFromJsonResponse(LifeCycleStatesEnumServiceResponse.getResponse(), "uniqueId"); component.setUniqueId(productUniqueId); - String productVersion = ResponseParser - .getValueFromJsonResponse(LifeCycleStatesEnumServiceResponse.getResponse(), "version"); + String productVersion = ResponseParser.getValueFromJsonResponse(LifeCycleStatesEnumServiceResponse.getResponse(), "version"); component.setVersion(productVersion); - String newLifecycleState = ResponseParser - .getValueFromJsonResponse(LifeCycleStatesEnumServiceResponse.getResponse(), "lifecycleState"); + String newLifecycleState = ResponseParser.getValueFromJsonResponse(LifeCycleStatesEnumServiceResponse.getResponse(), "lifecycleState"); component.setLifecycleState(LifecycleStateEnum.valueOf(newLifecycleState)); } return LifeCycleStatesEnumServiceResponse; diff --git a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/rest/ResponseParser.java b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/rest/ResponseParser.java index ad9f482bc1..95953838c9 100644 --- a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/rest/ResponseParser.java +++ b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/rest/ResponseParser.java @@ -60,6 +60,7 @@ import org.openecomp.sdc.ci.tests.datatypes.ResourceRespJavaObject; import org.openecomp.sdc.ci.tests.datatypes.ServiceDistributionStatus; import org.openecomp.sdc.ci.tests.datatypes.http.RestResponse; import org.openecomp.sdc.ci.tests.utils.Utils; +import org.openecomp.sdc.ci.tests.utils.general.AtomicOperationUtils; import com.fasterxml.jackson.databind.DeserializationFeature; import com.google.gson.Gson; diff --git a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/rest/ServiceRestUtils.java b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/rest/ServiceRestUtils.java index a93587dbbc..9ba4a906c6 100644 --- a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/rest/ServiceRestUtils.java +++ b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/rest/ServiceRestUtils.java @@ -94,6 +94,7 @@ public class ServiceRestUtils extends BaseRestUtils { } public static RestResponse createService(ServiceReqDetails service, User user) throws Exception { + Config config = Utils.getConfig(); String url = String.format(Urls.CREATE_SERVICE, config.getCatalogBeHost(), config.getCatalogBePort()); String serviceBodyJson = gson.toJson(service); @@ -256,6 +257,7 @@ public class ServiceRestUtils extends BaseRestUtils { config.getCatalogBePort(), serviceName, serviceVersion); RestResponse deleteResponse = http.httpSendDelete(url, headersMap); + deleteMarkedServices(sdncModifierDetails.getUserId()); return deleteResponse; } diff --git a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/validation/CsarValidationUtils.java b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/validation/CsarValidationUtils.java index 0fe11537e4..7423dbc808 100644 --- a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/validation/CsarValidationUtils.java +++ b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/validation/CsarValidationUtils.java @@ -44,39 +44,6 @@ import org.openecomp.sdc.common.util.ZipUtil; public class CsarValidationUtils { - public static String getCsarPayload(String csarName, String fileLocation) throws Exception { - - RestResponseAsByteArray csar = ImportRestUtils.getCsar(csarName, ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER)); - assertTrue("Return response code different from 200", csar.getHttpStatusCode() == BaseRestUtils.STATUS_CODE_SUCCESS); - Map readZip = null; - byte[] data = csar.getResponse(); - if (data != null && data.length > 0) { - readZip = ZipUtil.readZip(data); - - } - byte[] artifactsBs = readZip.get(fileLocation); - String str = new String(artifactsBs, StandardCharsets.UTF_8); - return str; - - } - - public static String getCsarPayload(File csarName, String fileLocation) throws Exception { - -// RestResponseAsByteArray csar = ImportRestUtils.getCsar(csarName, ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER)); -// assertTrue("Return response code different from 200", csar.getHttpStatusCode() == BaseRestUtils.STATUS_CODE_SUCCESS); - Map readZip = null; - Path path = csarName.toPath(); - - byte[] data = Files.readAllBytes(path); - if (data != null && data.length > 0) { - readZip = ZipUtil.readZip(data); - } - byte[] artifactsBs = readZip.get(fileLocation); - String str = new String(artifactsBs, StandardCharsets.UTF_8); - return str; - - } - public static void validateCsarVfArtifact(String csarUUID, Resource resource) throws Exception { List listTypeHeatMetaDefinition = CsarParserUtils.getListTypeHeatMetaDefinition(csarUUID); diff --git a/test-apis-ci/src/main/java/org/openecomp/sdc/externalApis/CRUDExternalAPI.java b/test-apis-ci/src/main/java/org/openecomp/sdc/externalApis/CRUDExternalAPI.java index a680990af8..127ae54784 100644 --- a/test-apis-ci/src/main/java/org/openecomp/sdc/externalApis/CRUDExternalAPI.java +++ b/test-apis-ci/src/main/java/org/openecomp/sdc/externalApis/CRUDExternalAPI.java @@ -80,7 +80,6 @@ import org.openecomp.sdc.ci.tests.datatypes.http.RestResponse; import org.openecomp.sdc.ci.tests.utils.general.AtomicOperationUtils; import org.openecomp.sdc.ci.tests.utils.general.ElementFactory; import org.openecomp.sdc.ci.tests.utils.rest.ArtifactRestUtils; -import org.openecomp.sdc.ci.tests.utils.rest.AutomationUtils; import org.openecomp.sdc.ci.tests.utils.rest.BaseRestUtils; import org.openecomp.sdc.ci.tests.utils.validation.AuditValidationUtils; import org.openecomp.sdc.ci.tests.utils.validation.DistributionValidationUtils; @@ -356,42 +355,45 @@ public class CRUDExternalAPI extends ComponentBaseTest { // create component/s & upload artifact via external api if(ComponentTypeEnum.RESOURCE_INSTANCE == componentTypeEnum) { component = getComponentWithResourceInstanceInTargetLifeCycleState(chosenLifeCycleState, resourceTypeEnum); - restResponse = uploadArtifactOfRIIncludingValiditionOfAuditAndResponseCode(component, component.getComponentInstances().get(0), ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER), artifactReqDetails, 200); - component =AtomicOperationUtils.getCompoenntObject(component, UserRoleEnum.DESIGNER); - - if((LifeCycleStatesEnum.CERTIFICATIONREQUEST == chosenLifeCycleState) && (!component.getComponentType().toString().equals(ComponentTypeEnum.RESOURCE.toString()))) { -// numberOfArtifact = component.getComponentInstances().get(0).getDeploymentArtifacts().size(); - numberOfArtifact = (component.getComponentInstances().get(0).getDeploymentArtifacts() == null ? 0 : component.getComponentInstances().get(0).getDeploymentArtifacts().size()); - } else { -// numberOfArtifact = component.getComponentInstances().get(0).getDeploymentArtifacts().size() + 1; - numberOfArtifact = (component.getComponentInstances().get(0).getDeploymentArtifacts() == null ? 0 : component.getComponentInstances().get(0).getDeploymentArtifacts().size()); - } + component = getNewerVersionOfComponent(component, chosenLifeCycleState); + numberOfArtifact = (component.getComponentInstances().get(0).getDeploymentArtifacts() == null ? 0 : component.getComponentInstances().get(0).getDeploymentArtifacts().size()); } else { component = getComponentInTargetLifeCycleState(componentTypeEnum.toString(), UserRoleEnum.DESIGNER, chosenLifeCycleState, resourceTypeEnum); - restResponse = uploadArtifactOfAssetIncludingValiditionOfAuditAndResponseCode(component, ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER), artifactReqDetails, 200); - numberOfArtifact = component.getDeploymentArtifacts().size() + 1; + component = updateComponentDetailsByLifeCycleState(chosenLifeCycleState, component); + numberOfArtifact = component.getDeploymentArtifacts().size(); } - - ArtifactDefinition responseArtifact = getArtifactDataFromJson(restResponse.getResponse()); - component = getNewerVersionOfComponent(component, chosenLifeCycleState); - // Get list of deployment artifact + download them via external API Map deploymentArtifacts = getDeploymentArtifactsOfAsset(component, componentTypeEnum); - Assert.assertEquals(numberOfArtifact, deploymentArtifacts.keySet().size(), "Expected that number of deployment artifact will be increase by one."); + Assert.assertEquals(numberOfArtifact, deploymentArtifacts.keySet().size(), "Expected that number of deployment artifacts will be increase by one."); // Download the uploaded artifact via external API downloadResourceDeploymentArtifactExternalAPI(component, deploymentArtifacts.get(responseArtifact.getArtifactLabel()), ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER), artifactReqDetails, componentTypeEnum); - + return component; + } + + /** + * according lifecycle state of component get updated component details + * @param chosenLifeCycleState + * @param component + * @return + * @throws Exception + */ + public Component updateComponentDetailsByLifeCycleState(LifeCycleStatesEnum chosenLifeCycleState, Component component) throws Exception { + if(LifeCycleStatesEnum.CHECKOUT.equals(chosenLifeCycleState)){ + component = AtomicOperationUtils.getComponentObject(component, UserRoleEnum.DESIGNER); + }else{ + component = getNewerVersionOfComponent(component, chosenLifeCycleState); + } return component; } // Upload artifact via external API + Check auditing for upload operation + Check response of external API - public RestResponse uploadArtifactOfRIIncludingValiditionOfAuditAndResponseCode(Component resourceDetails, ComponentInstance componentInstance, User sdncModifierDetails, ArtifactReqDetails artifactReqDetails, Integer expectedResponseCode) throws Exception { - RestResponse restResponse = ArtifactRestUtils.externalAPIUploadArtifactOfComponentInstanceOnAsset(resourceDetails, ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER), artifactReqDetails, resourceDetails.getComponentInstances().get(0)); + public RestResponse uploadArtifactOfRIIncludingValiditionOfAuditAndResponseCode(Component component, ComponentInstance componentInstance, User sdncModifierDetails, ArtifactReqDetails artifactReqDetails, Integer expectedResponseCode) throws Exception { + RestResponse restResponse = ArtifactRestUtils.externalAPIUploadArtifactOfComponentInstanceOnAsset(component, ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER), artifactReqDetails, component.getComponentInstances().get(0)); // Check response of external API Integer responseCode = restResponse.getErrorCode(); @@ -406,18 +408,16 @@ public class CRUDExternalAPI extends ComponentBaseTest { Map body = new HashMap<>(); body.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_NAME, componentInstance.getNormalizedName()); - AssetTypeEnum assetTypeEnum = AssetTypeEnum.valueOf((resourceDetails.getComponentType().getValue() + "s").toUpperCase()); - ExpectedExternalAudit expectedExternalAudit = ElementFactory.getDefaultExternalArtifactAuditSuccess(assetTypeEnum, action, responseArtifact, resourceDetails); + AssetTypeEnum assetTypeEnum = AssetTypeEnum.valueOf((component.getComponentType().getValue() + "s").toUpperCase()); + ExpectedExternalAudit expectedExternalAudit = ElementFactory.getDefaultExternalArtifactAuditSuccess(assetTypeEnum, action, responseArtifact, component); expectedExternalAudit.setRESOURCE_NAME(componentInstance.getNormalizedName()); - expectedExternalAudit.setRESOURCE_URL("/sdc/v1/catalog/" + assetTypeEnum.getValue() + "/" + resourceDetails.getUUID() + "/resourceInstances/" + componentInstance.getNormalizedName() + "/artifacts"); + expectedExternalAudit.setRESOURCE_URL("/sdc/v1/catalog/" + assetTypeEnum.getValue() + "/" + component.getUUID() + "/resourceInstances/" + componentInstance.getNormalizedName() + "/artifacts"); AuditValidationUtils.validateExternalAudit(expectedExternalAudit, AuditingActionEnum.ARTIFACT_UPLOAD_BY_API.getName(), body); return restResponse; } - - protected Component getComponentWithResourceInstanceInTargetLifeCycleState(LifeCycleStatesEnum lifeCycleStatesEnum, ResourceTypeEnum resourceTypeEnum) throws Exception { Component component; if(resourceTypeEnum == ResourceTypeEnum.VF) { @@ -426,9 +426,9 @@ public class CRUDExternalAPI extends ComponentBaseTest { Component resourceInstanceDetails = getComponentInTargetLifeCycleState(ComponentTypeEnum.RESOURCE.getValue(), UserRoleEnum.DESIGNER, LifeCycleStatesEnum.CERTIFY, null); AtomicOperationUtils.addComponentInstanceToComponentContainer(resourceInstanceDetails, component, UserRoleEnum.DESIGNER, true).left().value(); - // Add artifact to service if asked for certifcationrequest - must be at least one artifact for the flow - if((LifeCycleStatesEnum.CERTIFICATIONREQUEST == lifeCycleStatesEnum) || (LifeCycleStatesEnum.STARTCERTIFICATION == lifeCycleStatesEnum)) { - } + // Add artifact to service if asked for certification request - must be at least one artifact for the flow +// if((LifeCycleStatesEnum.CERTIFICATIONREQUEST == lifeCycleStatesEnum) || (LifeCycleStatesEnum.STARTCERTIFICATION == lifeCycleStatesEnum)) { +// } AtomicOperationUtils.uploadArtifactByType(ArtifactTypeEnum.OTHER, component, UserRoleEnum.DESIGNER, true, true).left().value(); component = AtomicOperationUtils.changeComponentState(component, UserRoleEnum.DESIGNER, lifeCycleStatesEnum, true).getLeft(); } else { @@ -446,8 +446,8 @@ public class CRUDExternalAPI extends ComponentBaseTest { // Upload artifact via external API + Check auditing for upload operation + Check response of external API - protected RestResponse uploadArtifactOfAssetIncludingValiditionOfAuditAndResponseCode(Component resourceDetails, User sdncModifierDetails, ArtifactReqDetails artifactReqDetails, Integer expectedResponseCode) throws Exception { - RestResponse restResponse = ArtifactRestUtils.externalAPIUploadArtifactOfTheAsset(resourceDetails, sdncModifierDetails, artifactReqDetails); + protected RestResponse uploadArtifactOfAssetIncludingValiditionOfAuditAndResponseCode(Component component, User sdncModifierDetails, ArtifactReqDetails artifactReqDetails, Integer expectedResponseCode) throws Exception { + RestResponse restResponse = ArtifactRestUtils.externalAPIUploadArtifactOfTheAsset(component, sdncModifierDetails, artifactReqDetails); // Check response of external API Integer responseCode = restResponse.getErrorCode(); @@ -460,10 +460,10 @@ public class CRUDExternalAPI extends ComponentBaseTest { AuditingActionEnum action = AuditingActionEnum.ARTIFACT_UPLOAD_BY_API; Map body = new HashMap<>(); - body.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_NAME, resourceDetails.getName()); + body.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_NAME, component.getName()); - AssetTypeEnum assetTypeEnum = AssetTypeEnum.valueOf((resourceDetails.getComponentType().getValue() + "s").toUpperCase()); - ExpectedExternalAudit expectedExternalAudit = ElementFactory.getDefaultExternalArtifactAuditSuccess(assetTypeEnum, action, responseArtifact, resourceDetails); + AssetTypeEnum assetTypeEnum = AssetTypeEnum.valueOf((component.getComponentType().getValue() + "s").toUpperCase()); + ExpectedExternalAudit expectedExternalAudit = ElementFactory.getDefaultExternalArtifactAuditSuccess(assetTypeEnum, action, responseArtifact, component); AuditValidationUtils.validateExternalAudit(expectedExternalAudit, AuditingActionEnum.ARTIFACT_UPLOAD_BY_API.getName(), body); return restResponse; @@ -478,7 +478,7 @@ public class CRUDExternalAPI extends ComponentBaseTest { // check that this version different for input version // check that this component uniqueID different from input uniqueID // Return: that version - protected Component getNewerVersionOfComponent(Component component, LifeCycleStatesEnum lifeCycleStatesEnum) throws Exception { + protected synchronized Component getNewerVersionOfComponent(Component component, LifeCycleStatesEnum lifeCycleStatesEnum) throws Exception { Component resourceDetails = null; if((!lifeCycleStatesEnum.equals(LifeCycleStatesEnum.CHECKOUT)) && (!lifeCycleStatesEnum.equals(LifeCycleStatesEnum.STARTCERTIFICATION))) { @@ -501,7 +501,7 @@ public class CRUDExternalAPI extends ComponentBaseTest { System.out.println("Service UniqueID: " + resourceDetails.getUniqueId()); // Checking that new version exist + different from old one by unique id - Assert.assertNotEquals(resourceVersion, resourceNewVersion, "Expected for diffrent resource version."); + Assert.assertNotEquals(resourceVersion, resourceNewVersion, "Expected for different resource version."); Assert.assertNotEquals(resourceUniqueID, resourceNewUniqueID, "Expected that resource will have new unique ID."); } else { if(component.getComponentType().equals(ComponentTypeEnum.SERVICE)) { @@ -518,13 +518,13 @@ public class CRUDExternalAPI extends ComponentBaseTest { // download deployment via external api + check response code for success (200) + get artifactReqDetails and verify payload + verify audit - protected RestResponse downloadResourceDeploymentArtifactExternalAPI(Component resourceDetails, ArtifactDefinition artifactDefinition, User sdncModifierDetails, ArtifactReqDetails artifactReqDetails, ComponentTypeEnum componentTypeEnum) throws Exception { + protected RestResponse downloadResourceDeploymentArtifactExternalAPI(Component component, ArtifactDefinition artifactDefinition, User sdncModifierDetails, ArtifactReqDetails artifactReqDetails, ComponentTypeEnum componentTypeEnum) throws Exception { RestResponse restResponse; if(componentTypeEnum == ComponentTypeEnum.RESOURCE_INSTANCE) { - restResponse = ArtifactRestUtils.getComponentInstanceDeploymentArtifactExternalAPI(resourceDetails.getUUID(), resourceDetails.getComponentInstances().get(0).getNormalizedName(), artifactDefinition.getArtifactUUID(), ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER), resourceDetails.getComponentType().toString()); + restResponse = ArtifactRestUtils.getComponentInstanceDeploymentArtifactExternalAPI(component.getUUID(), component.getComponentInstances().get(0).getNormalizedName(), artifactDefinition.getArtifactUUID(), ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER), component.getComponentType().toString()); } else { - restResponse = ArtifactRestUtils.getResourceDeploymentArtifactExternalAPI(resourceDetails.getUUID(), artifactDefinition.getArtifactUUID(), ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER), resourceDetails.getComponentType().toString()); + restResponse = ArtifactRestUtils.getResourceDeploymentArtifactExternalAPI(component.getUUID(), artifactDefinition.getArtifactUUID(), ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER), component.getComponentType().toString()); } Integer responseCode = restResponse.getErrorCode(); @@ -532,7 +532,7 @@ public class CRUDExternalAPI extends ComponentBaseTest { Assert.assertEquals(responseCode,expectedCode, "Response code is not correct."); - // For known artifact/payload - verify payload of downloaded artfaict + // For known artifact/payload - verify payload of downloaded artifact if (artifactReqDetails != null) { String response = restResponse.getResponse(); String payloadData = artifactReqDetails.getPayload(); @@ -575,8 +575,8 @@ public class CRUDExternalAPI extends ComponentBaseTest { } // download deployment via external api + check response code for success (200) + verify audit - protected void downloadResourceDeploymentArtifactExternalAPI(Component resourceDetails, ArtifactDefinition artifactDefinition, User sdncModifierDetails) throws Exception { - downloadResourceDeploymentArtifactExternalAPI(resourceDetails, artifactDefinition, sdncModifierDetails, null, resourceDetails.getComponentType()); + protected void downloadResourceDeploymentArtifactExternalAPI(Component component, ArtifactDefinition artifactDefinition, User sdncModifierDetails) throws Exception { + downloadResourceDeploymentArtifactExternalAPI(component, artifactDefinition, sdncModifierDetails, null, component.getComponentType()); } @@ -821,13 +821,13 @@ public class CRUDExternalAPI extends ComponentBaseTest { {LifeCycleStatesEnum.CHECKOUT, ComponentTypeEnum.RESOURCE, "uploadArtifactWithSameLabel"}, {LifeCycleStatesEnum.CHECKOUT, ComponentTypeEnum.SERVICE, "uploadArtifactWithSameLabel"}, -// DE306360 {LifeCycleStatesEnum.CHECKOUT, ComponentTypeEnum.RESOURCE_INSTANCE, "uploadArtifactWithSameLabel"}, + {LifeCycleStatesEnum.CHECKOUT, ComponentTypeEnum.RESOURCE_INSTANCE, "uploadArtifactWithSameLabel"}, {LifeCycleStatesEnum.CHECKIN, ComponentTypeEnum.RESOURCE, "uploadArtifactWithSameLabel"}, {LifeCycleStatesEnum.CHECKIN, ComponentTypeEnum.SERVICE, "uploadArtifactWithSameLabel"}, -// DE306360 {LifeCycleStatesEnum.CHECKIN, ComponentTypeEnum.RESOURCE_INSTANCE, "uploadArtifactWithSameLabel"}, + {LifeCycleStatesEnum.CHECKIN, ComponentTypeEnum.RESOURCE_INSTANCE, "uploadArtifactWithSameLabel"}, {LifeCycleStatesEnum.CERTIFICATIONREQUEST, ComponentTypeEnum.RESOURCE, "uploadArtifactWithSameLabel"}, {LifeCycleStatesEnum.CERTIFICATIONREQUEST, ComponentTypeEnum.SERVICE, "uploadArtifactWithSameLabel"}, -// DE306360 {LifeCycleStatesEnum.CERTIFICATIONREQUEST, ComponentTypeEnum.RESOURCE_INSTANCE, "uploadArtifactWithSameLabel"}, + {LifeCycleStatesEnum.CERTIFICATIONREQUEST, ComponentTypeEnum.RESOURCE_INSTANCE, "uploadArtifactWithSameLabel"}, {LifeCycleStatesEnum.CHECKOUT, ComponentTypeEnum.RESOURCE, "uploadArtifactWithInvalidCheckSum"}, {LifeCycleStatesEnum.CHECKOUT, ComponentTypeEnum.SERVICE, "uploadArtifactWithInvalidCheckSum"}, @@ -902,104 +902,104 @@ public class CRUDExternalAPI extends ComponentBaseTest { } // Upload artifact with invalid type via external API - to long type - protected void uploadArtifactWithInvalidTypeToLong(Component resourceDetails, User sdncModifierDetails, ArtifactReqDetails artifactReqDetails, + protected void uploadArtifactWithInvalidTypeToLong(Component component, User sdncModifierDetails, ArtifactReqDetails artifactReqDetails, ComponentInstance componentResourceInstanceDetails) throws Exception { artifactReqDetails.setArtifactType("dsfdsfdsdsfdsfdsdsfdsfdsdsfdsfdsdsfdsfdsdsfdsfdsdsfdsfdsdsfdsfdsdsfdsfdsdsfdsfdsdsfdsfdsdsfdsfdsdsfdsfdsdsfdsfdsdsfdsfdsdsfdsfdsdsfdsfdsdsfdsfdsdsfdsfdsdsfdsfdsdsfdsfdsdsfdsfdsdsfdsfdsdsfdsfdsdsfdsfdsdsfdsfdsdsfdsfdsdsfdsfdsdsfdsfdsdsfdsfdsdsfdsfdsdsfdsfdsdsfdsfdsdsfdsfdsdsfdsfdsdsfdsfdsdsfdsfdsdsfdsfdsdsfdsfdsdsfdsfdsdsfdsfdsdsfdsfdsdsfdsfdsdsfdsfdsdsfdsfdsdsfdsfdsdsfdsfdsdsfdsfdsdsfdsfdsdsfdsfdsdsfdsfdsdsfdsfdsdsfdsfdsdsfdsfdsdsfdsfdsdsfdsfdsdsfdsfdsdsfdsfdsdsfdsfdsdsfdsfdsdsfdsfdsdsfdsfdsdsfdsfdsdsfdsfdsdsfdsfds"); ErrorInfo errorInfo = ErrorValidationUtils.parseErrorConfigYaml(ActionStatus.ARTIFACT_TYPE_NOT_SUPPORTED.name()); List variables = asList(artifactReqDetails.getArtifactType()); - uploadArtifactOfAssetIncludingValiditionOfAuditAndResponseCode(resourceDetails, ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER), + uploadArtifactOfAssetIncludingValiditionOfAuditAndResponseCode(component, ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER), artifactReqDetails, 400, componentResourceInstanceDetails, errorInfo, variables, null, false); } // Upload artifact with invalid type via external API - empty type - protected void uploadArtifactWithInvalidTypeEmpty(Component resourceDetails, User sdncModifierDetails, ArtifactReqDetails artifactReqDetails, + protected void uploadArtifactWithInvalidTypeEmpty(Component component, User sdncModifierDetails, ArtifactReqDetails artifactReqDetails, ComponentInstance componentResourceInstanceDetails) throws Exception { artifactReqDetails.setArtifactType(""); ErrorInfo errorInfo = ErrorValidationUtils.parseErrorConfigYaml(ActionStatus.ARTIFACT_TYPE_NOT_SUPPORTED.name()); List variables = asList(artifactReqDetails.getArtifactType()); - uploadArtifactOfAssetIncludingValiditionOfAuditAndResponseCode(resourceDetails, ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER), + uploadArtifactOfAssetIncludingValiditionOfAuditAndResponseCode(component, ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER), artifactReqDetails, 400, componentResourceInstanceDetails, errorInfo, variables, null, false); } // Upload artifact with invalid checksum via external API - protected void uploadArtifactWithInvalidCheckSum(Component resourceDetails, User sdncModifierDetails, ArtifactReqDetails artifactReqDetails, + protected void uploadArtifactWithInvalidCheckSum(Component component, User sdncModifierDetails, ArtifactReqDetails artifactReqDetails, ComponentInstance componentResourceInstanceDetails) throws Exception { ErrorInfo errorInfo = ErrorValidationUtils.parseErrorConfigYaml(ActionStatus.ARTIFACT_INVALID_MD5.name()); List variables = asList(); - uploadArtifactWithInvalidCheckSumOfAssetIncludingValiditionOfAuditAndResponseCode(resourceDetails, ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER), + uploadArtifactWithInvalidCheckSumOfAssetIncludingValiditionOfAuditAndResponseCode(component, ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER), artifactReqDetails, 400, componentResourceInstanceDetails, errorInfo, variables); } // Upload artifact with valid type & invalid name via external API - name to long - protected void uploadArtifactWithInvalidNameToLong(Component resourceDetails, User sdncModifierDetails, ArtifactReqDetails artifactReqDetails, + protected void uploadArtifactWithInvalidNameToLong(Component component, User sdncModifierDetails, ArtifactReqDetails artifactReqDetails, ComponentInstance componentResourceInstanceDetails) throws Exception { ErrorInfo errorInfo = ErrorValidationUtils.parseErrorConfigYaml(ActionStatus.EXCEEDS_LIMIT.name()); List variables = asList("artifact name", "255"); artifactReqDetails.setArtifactName("invalGGfdsiofhdsouhfoidshfoidshoifhsdoifhdsouihfdsofhiufdsinvalGGfdsiofhdsouhfoidshfoidshoifhsdoifhdsouihfdsofhiufdsghiufghodhfioudsgafodsgaiofudsghifudsiugfhiufawsouipfhgawseiupfsadiughdfsoiuhgfaighfpasdghfdsaqgfdsgdfgidTypeinvalGGfdsiofhdsouhfoidshfoidshoifhsdoifhdsouihfdsofhiufdsghiufghodhfioudsgafodsgaiofudsghifudsiugfhiufawsouipfhgawseiupfsadiughdfsoiuhgfaighfpasdghfdsaqgfdsgdfgidTypeghiufghodhfioudsgafodsgaiofudsghifudsiugfhiufawsouipfhgawseiupfsadiughdfsoiuhgfaighfpasdghfdsaqgfdsgdfgidType"); - uploadArtifactOfAssetIncludingValiditionOfAuditAndResponseCode(resourceDetails, ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER), + uploadArtifactOfAssetIncludingValiditionOfAuditAndResponseCode(component, ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER), artifactReqDetails, 400, componentResourceInstanceDetails, errorInfo, variables, null, false); } // Upload artifact with valid type & invalid name via external API - name is empty - protected void uploadArtifactWithInvalidNameEmpty(Component resourceDetails, User sdncModifierDetails, ArtifactReqDetails artifactReqDetails, + protected void uploadArtifactWithInvalidNameEmpty(Component component, User sdncModifierDetails, ArtifactReqDetails artifactReqDetails, ComponentInstance componentResourceInstanceDetails) throws Exception { ErrorInfo errorInfo = ErrorValidationUtils.parseErrorConfigYaml(ActionStatus.MISSING_ARTIFACT_NAME.name()); List variables = asList(); artifactReqDetails.setArtifactName(""); - uploadArtifactOfAssetIncludingValiditionOfAuditAndResponseCode(resourceDetails, ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER), + uploadArtifactOfAssetIncludingValiditionOfAuditAndResponseCode(component, ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER), artifactReqDetails, 400, componentResourceInstanceDetails, errorInfo, variables, null, false); } // Upload artifact with valid type & invalid label via external API - label to long - protected void uploadArtifactWithInvalidLabelToLong(Component resourceDetails, User sdncModifierDetails, ArtifactReqDetails artifactReqDetails, + protected void uploadArtifactWithInvalidLabelToLong(Component component, User sdncModifierDetails, ArtifactReqDetails artifactReqDetails, ComponentInstance componentResourceInstanceDetails) throws Exception { ErrorInfo errorInfo = ErrorValidationUtils.parseErrorConfigYaml(ActionStatus.EXCEEDS_LIMIT.name()); List variables = asList("artifact label", "255"); artifactReqDetails.setArtifactLabel("invalGGfdsiofhdsouhfoidshfoidshoifhsdoifhdsouihfdsofhiufdsghiufghodhfioudsgafodsgaiofudsghifudsiugfhiufawsouipfhgawseiupfsadiughdfsoiuhgfaighfpasdghfdsaqgfdsgdfgidTypeinvalGGfdsiofhdsouhfoidshfoidshoifhsdoifhdsouihfdsofhiufdsghiufghodhfioudsgafodsgaiofudsghifudsiugfhiufawsouipfhgawseiupfsadiughdfsoiuhgfaighfpasdghfdsaqgfdsgdfgidTypeinvalGGfdsiofhdsouhfoidshfoidshoifhsdoifhdsouihfdsofhiufdsghiufghodhfioudsgafodsgaiofudsghifudsiugfhiufawsouipfhgawseiupfsadiughdfsoiuhgfaighfpasdghfdsaqgfdsgdfgidTypeinvalGGfdsiofhdsouhfoidshfoidshoifhsdoifhdsouihfdsofhiufdsghiufghodhfioudsgafodsgaiofudsghifudsiugfhiufawsouipfhgawseiupfsadiughdfsoiuhgfaighfpasdghfdsaqgfdsgdfgidType"); - uploadArtifactOfAssetIncludingValiditionOfAuditAndResponseCode(resourceDetails, ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER), + uploadArtifactOfAssetIncludingValiditionOfAuditAndResponseCode(component, ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER), artifactReqDetails, 400, componentResourceInstanceDetails, errorInfo, variables, null, false); } // Upload artifact with valid type & invalid label via external API - label is empty - protected void uploadArtifactWithInvalidLabelEmpty(Component resourceDetails, User sdncModifierDetails, ArtifactReqDetails artifactReqDetails, + protected void uploadArtifactWithInvalidLabelEmpty(Component component, User sdncModifierDetails, ArtifactReqDetails artifactReqDetails, ComponentInstance componentResourceInstanceDetails) throws Exception { ErrorInfo errorInfo = ErrorValidationUtils.parseErrorConfigYaml(ActionStatus.MISSING_DATA.name()); List variables = asList("artifact label"); artifactReqDetails.setArtifactLabel(""); - uploadArtifactOfAssetIncludingValiditionOfAuditAndResponseCode(resourceDetails, ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER), + uploadArtifactOfAssetIncludingValiditionOfAuditAndResponseCode(component, ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER), artifactReqDetails, 400, componentResourceInstanceDetails, errorInfo, variables, null, false); } // Upload artifact with invalid description via external API - to long description - protected void uploadArtifactWithInvalidDescriptionToLong(Component resourceDetails, User sdncModifierDetails, ArtifactReqDetails artifactReqDetails, + protected void uploadArtifactWithInvalidDescriptionToLong(Component component, User sdncModifierDetails, ArtifactReqDetails artifactReqDetails, ComponentInstance componentResourceInstanceDetails) throws Exception { ErrorInfo errorInfo = ErrorValidationUtils.parseErrorConfigYaml(ActionStatus.EXCEEDS_LIMIT.name()); List variables = asList("artifact description", "256"); artifactReqDetails.setDescription("invalGGfdsiofhdsouhfoidshfoidshoifhsdoifhdsouihfdsofhiufdsinvalGGfdsiofhdsouhfoidshfoidshoifhsdoifhdsouihfdsofhiufdsghiufghodhfioudsgafodsgaiofudsghifudsiugfhiufawsouipfhgawseiupfsadiughdfsoiuhgfaighfpasdghfdsaqgfdsgdfgidTypeinvalGGfdsiofhdsouhfoidshfoidshoifhsdoifhdsouihfdsofhiufdsghiufghodhfioudsgafodsgaiofudsghifudsiugfhiufawsouipfhgawseiupfsadiughdfsoiuhgfaighfpasdghfdsaqgfdsgdfgidTypeghiufghodhfioudsgafodsgaiofudsghifudsiugfhiufawsouipfhgawseiupfsadiughdfsoiuhgfaighfpasdghfdsaqgfdsgdfgidType"); - uploadArtifactOfAssetIncludingValiditionOfAuditAndResponseCode(resourceDetails, ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER), + uploadArtifactOfAssetIncludingValiditionOfAuditAndResponseCode(component, ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER), artifactReqDetails, 400, componentResourceInstanceDetails, errorInfo, variables, null, false); } // Upload artifact with invalid description via external API - empty description - protected void uploadArtifactWithInvalidDescriptionEmpty(Component resourceDetails, User sdncModifierDetails, ArtifactReqDetails artifactReqDetails, + protected void uploadArtifactWithInvalidDescriptionEmpty(Component component, User sdncModifierDetails, ArtifactReqDetails artifactReqDetails, ComponentInstance componentResourceInstanceDetails) throws Exception { ErrorInfo errorInfo = ErrorValidationUtils.parseErrorConfigYaml(ActionStatus.MISSING_DATA.name()); List variables = asList("artifact description"); artifactReqDetails.setDescription(""); - uploadArtifactOfAssetIncludingValiditionOfAuditAndResponseCode(resourceDetails, ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER), + uploadArtifactOfAssetIncludingValiditionOfAuditAndResponseCode(component, ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER), artifactReqDetails, 400, componentResourceInstanceDetails, errorInfo, variables, null, false); } @@ -1007,14 +1007,14 @@ public class CRUDExternalAPI extends ComponentBaseTest { // Upload artifact with same label via external API - protected void uploadArtifactWithSameLabel(Component resourceDetails, User sdncModifierDetails, ArtifactReqDetails artifactReqDetails, + protected void uploadArtifactWithSameLabel(Component component, User sdncModifierDetails, ArtifactReqDetails artifactReqDetails, ComponentInstance componentResourceInstanceDetails) throws Exception { RestResponse restResponse = null; if(componentResourceInstanceDetails != null) { - restResponse = ArtifactRestUtils.externalAPIUploadArtifactOfComponentInstanceOnAsset(resourceDetails, ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER), artifactReqDetails, componentResourceInstanceDetails); + restResponse = ArtifactRestUtils.externalAPIUploadArtifactOfComponentInstanceOnAsset(component, ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER), artifactReqDetails, componentResourceInstanceDetails); } else { - restResponse = ArtifactRestUtils.externalAPIUploadArtifactOfTheAsset(resourceDetails, ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER), artifactReqDetails); + restResponse = ArtifactRestUtils.externalAPIUploadArtifactOfTheAsset(component, ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER), artifactReqDetails); } @@ -1022,18 +1022,18 @@ public class CRUDExternalAPI extends ComponentBaseTest { ErrorInfo errorInfo = ErrorValidationUtils.parseErrorConfigYaml(ActionStatus.ARTIFACT_EXIST.name()); List variables = asList(artifactDefinition.getArtifactDisplayName()); - uploadArtifactOfAssetIncludingValiditionOfAuditAndResponseCode(resourceDetails, ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER), + uploadArtifactOfAssetIncludingValiditionOfAuditAndResponseCode(component, ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER), artifactReqDetails, 400, componentResourceInstanceDetails, errorInfo, variables, null, false); } - protected RestResponse uploadArtifactOfAssetIncludingValiditionOfAuditAndResponseCode(Component resourceDetails, User sdncModifierDetails, ArtifactReqDetails artifactReqDetails, + protected RestResponse uploadArtifactOfAssetIncludingValiditionOfAuditAndResponseCode(Component component, User sdncModifierDetails, ArtifactReqDetails artifactReqDetails, Integer expectedResponseCode, ComponentInstance componentResourceInstanceDetails, ErrorInfo errorInfo, List variables, LifeCycleStatesEnum lifeCycleStatesEnum, Boolean includeResourceNameInAudit) throws Exception { RestResponse restResponse; if(componentResourceInstanceDetails != null) { - restResponse = ArtifactRestUtils.externalAPIUploadArtifactOfComponentInstanceOnAsset(resourceDetails, sdncModifierDetails, artifactReqDetails, componentResourceInstanceDetails); + restResponse = ArtifactRestUtils.externalAPIUploadArtifactOfComponentInstanceOnAsset(component, sdncModifierDetails, artifactReqDetails, componentResourceInstanceDetails); } else { - restResponse = ArtifactRestUtils.externalAPIUploadArtifactOfTheAsset(resourceDetails, sdncModifierDetails, artifactReqDetails); + restResponse = ArtifactRestUtils.externalAPIUploadArtifactOfTheAsset(component, sdncModifierDetails, artifactReqDetails); } @@ -1046,30 +1046,30 @@ public class CRUDExternalAPI extends ComponentBaseTest { AuditingActionEnum action = AuditingActionEnum.ARTIFACT_UPLOAD_BY_API; - AssetTypeEnum assetTypeEnum = AssetTypeEnum.valueOf((resourceDetails.getComponentType().getValue() + "s").toUpperCase()); + AssetTypeEnum assetTypeEnum = AssetTypeEnum.valueOf((component.getComponentType().getValue() + "s").toUpperCase()); // ExpectedExternalAudit expectedExternalAudit = ElementFactory.getDefaultExternalArtifactAuditSuccess(assetTypeEnum, action, responseArtifact, resourceDetails); responseArtifact.setUpdaterFullName(""); responseArtifact.setUserIdLastUpdater(sdncModifierDetails.getUserId()); - ExpectedExternalAudit expectedExternalAudit = ElementFactory.getDefaultExternalArtifactAuditFailure(assetTypeEnum, action, responseArtifact, resourceDetails.getUUID(), errorInfo, variables); - expectedExternalAudit.setRESOURCE_NAME(resourceDetails.getName()); - expectedExternalAudit.setRESOURCE_TYPE(resourceDetails.getComponentType().getValue()); + ExpectedExternalAudit expectedExternalAudit = ElementFactory.getDefaultExternalArtifactAuditFailure(assetTypeEnum, action, responseArtifact, component.getUUID(), errorInfo, variables); + expectedExternalAudit.setRESOURCE_NAME(component.getName()); + expectedExternalAudit.setRESOURCE_TYPE(component.getComponentType().getValue()); expectedExternalAudit.setARTIFACT_DATA(null); Map body = new HashMap<>(); body.put(AuditingFieldsKeysEnum.AUDIT_STATUS, responseCode.toString()); if(componentResourceInstanceDetails != null) { - body.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_NAME, resourceDetails.getComponentInstances().get(0).getNormalizedName()); - expectedExternalAudit.setRESOURCE_URL("/sdc/v1/catalog/" + assetTypeEnum.getValue() + "/" + resourceDetails.getUUID() + "/resourceInstances/" + resourceDetails.getComponentInstances().get(0).getNormalizedName() + "/artifacts"); - expectedExternalAudit.setRESOURCE_NAME(resourceDetails.getComponentInstances().get(0).getNormalizedName()); + body.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_NAME, component.getComponentInstances().get(0).getNormalizedName()); + expectedExternalAudit.setRESOURCE_URL("/sdc/v1/catalog/" + assetTypeEnum.getValue() + "/" + component.getUUID() + "/resourceInstances/" + component.getComponentInstances().get(0).getNormalizedName() + "/artifacts"); + expectedExternalAudit.setRESOURCE_NAME(component.getComponentInstances().get(0).getNormalizedName()); } else { if(includeResourceNameInAudit) { - body.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_NAME, resourceDetails.getName()); + body.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_NAME, component.getName()); } else { if((lifeCycleStatesEnum == LifeCycleStatesEnum.CHECKIN) || (lifeCycleStatesEnum == LifeCycleStatesEnum.STARTCERTIFICATION)) { expectedExternalAudit.setRESOURCE_NAME(""); body.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_NAME, ""); } else { - body.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_NAME, resourceDetails.getName()); + body.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_NAME, component.getName()); } } } @@ -1085,14 +1085,14 @@ public class CRUDExternalAPI extends ComponentBaseTest { - protected RestResponse uploadArtifactWithInvalidCheckSumOfAssetIncludingValiditionOfAuditAndResponseCode(Component resourceDetails, User sdncModifierDetails, ArtifactReqDetails artifactReqDetails, + protected RestResponse uploadArtifactWithInvalidCheckSumOfAssetIncludingValiditionOfAuditAndResponseCode(Component component, User sdncModifierDetails, ArtifactReqDetails artifactReqDetails, Integer expectedResponseCode, ComponentInstance componentResourceInstanceDetails, ErrorInfo errorInfo, List variables) throws Exception { RestResponse restResponse; if(componentResourceInstanceDetails != null) { - restResponse = ArtifactRestUtils.externalAPIUploadArtifactWithInvalidCheckSumOfComponentInstanceOnAsset(resourceDetails, ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER), artifactReqDetails, componentResourceInstanceDetails); + restResponse = ArtifactRestUtils.externalAPIUploadArtifactWithInvalidCheckSumOfComponentInstanceOnAsset(component, ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER), artifactReqDetails, componentResourceInstanceDetails); } else { - restResponse = ArtifactRestUtils.externalAPIUploadArtifactWithInvalidCheckSumOfTheAsset(resourceDetails, ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER), artifactReqDetails); + restResponse = ArtifactRestUtils.externalAPIUploadArtifactWithInvalidCheckSumOfTheAsset(component, ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER), artifactReqDetails); } @@ -1109,23 +1109,23 @@ public class CRUDExternalAPI extends ComponentBaseTest { AuditingActionEnum action = AuditingActionEnum.ARTIFACT_UPLOAD_BY_API; - AssetTypeEnum assetTypeEnum = AssetTypeEnum.valueOf((resourceDetails.getComponentType().getValue() + "s").toUpperCase()); + AssetTypeEnum assetTypeEnum = AssetTypeEnum.valueOf((component.getComponentType().getValue() + "s").toUpperCase()); // ExpectedExternalAudit expectedExternalAudit = ElementFactory.getDefaultExternalArtifactAuditSuccess(assetTypeEnum, action, responseArtifact, resourceDetails); responseArtifact.setUpdaterFullName(""); responseArtifact.setUserIdLastUpdater(sdncModifierDetails.getUserId()); - ExpectedExternalAudit expectedExternalAudit = ElementFactory.getDefaultExternalArtifactAuditFailure(assetTypeEnum, action, responseArtifact, resourceDetails.getUUID(), errorInfo, variables); - expectedExternalAudit.setRESOURCE_NAME(resourceDetails.getName()); - expectedExternalAudit.setRESOURCE_TYPE(resourceDetails.getComponentType().getValue()); + ExpectedExternalAudit expectedExternalAudit = ElementFactory.getDefaultExternalArtifactAuditFailure(assetTypeEnum, action, responseArtifact, component.getUUID(), errorInfo, variables); + expectedExternalAudit.setRESOURCE_NAME(component.getName()); + expectedExternalAudit.setRESOURCE_TYPE(component.getComponentType().getValue()); expectedExternalAudit.setARTIFACT_DATA(null); Map body = new HashMap<>(); body.put(AuditingFieldsKeysEnum.AUDIT_STATUS, responseCode.toString()); if(componentResourceInstanceDetails != null) { - body.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_NAME, resourceDetails.getComponentInstances().get(0).getNormalizedName()); - expectedExternalAudit.setRESOURCE_URL("/sdc/v1/catalog/" + assetTypeEnum.getValue() + "/" + resourceDetails.getUUID() + "/resourceInstances/" + resourceDetails.getComponentInstances().get(0).getNormalizedName() + "/artifacts"); - expectedExternalAudit.setRESOURCE_NAME(resourceDetails.getComponentInstances().get(0).getNormalizedName()); + body.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_NAME, component.getComponentInstances().get(0).getNormalizedName()); + expectedExternalAudit.setRESOURCE_URL("/sdc/v1/catalog/" + assetTypeEnum.getValue() + "/" + component.getUUID() + "/resourceInstances/" + component.getComponentInstances().get(0).getNormalizedName() + "/artifacts"); + expectedExternalAudit.setRESOURCE_NAME(component.getComponentInstances().get(0).getNormalizedName()); } else { - body.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_NAME, resourceDetails.getName()); + body.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_NAME, component.getName()); } AuditValidationUtils.validateExternalAudit(expectedExternalAudit, AuditingActionEnum.ARTIFACT_UPLOAD_BY_API.getName(), body); @@ -1542,7 +1542,6 @@ public class CRUDExternalAPI extends ComponentBaseTest { }; } - // Verify that it cannot update VFC/VL/CP artifact on VFCi/VLi/CPi - Failure flow @Test(dataProvider="updateArtifactOfVfcVlCpForVfciVliCpiViaExternalAPI") public void updateArtifactOfVfcVlCpForVfciVliCpiViaExternalAPI(ResourceTypeEnum resourceTypeEnum) throws Exception { @@ -1571,10 +1570,6 @@ public class CRUDExternalAPI extends ComponentBaseTest { } - - - - @DataProvider(name="updateArtifactOnRIViaExternalAPI", parallel=true) public static Object[][] dataProviderUpdateArtifactOnRIViaExternalAPI() { return new Object[][] { @@ -1602,10 +1597,6 @@ public class CRUDExternalAPI extends ComponentBaseTest { }; } - - - - @Test(dataProvider="updateArtifactOnRIViaExternalAPI") public void updateArtifactOnRIViaExternalAPI(LifeCycleStatesEnum chosenLifeCycleState, String artifactType, ResourceTypeEnum resourceTypeEnum) throws Exception { getExtendTest().log(Status.INFO, String.format("chosenLifeCycleState: %s, artifactType: %s", chosenLifeCycleState, artifactType)); @@ -1619,12 +1610,6 @@ public class CRUDExternalAPI extends ComponentBaseTest { } } - - - - - - @DataProvider(name="updateArtifactOnVfcVlCpRIViaExternalAPI", parallel=true) public static Object[][] dataProviderUpdateArtifactOnVfcVlCpRIViaExternalAPI() { return new Object[][] { @@ -1714,10 +1699,6 @@ public class CRUDExternalAPI extends ComponentBaseTest { }; } - - - - @Test(dataProvider="updateArtifactOnVfcVlCpRIViaExternalAPI") public void updateArtifactOnVfcVlCpRIViaExternalAPI(LifeCycleStatesEnum chosenLifeCycleState, String artifactType, ResourceTypeEnum resourceTypeEnum) throws Exception { getExtendTest().log(Status.INFO, String.format("chosenLifeCycleState: %s, artifactType: %s", chosenLifeCycleState, artifactType)); @@ -1732,15 +1713,6 @@ public class CRUDExternalAPI extends ComponentBaseTest { } } - - - - - - - - - @DataProvider(name="updateArtifactOnVFViaExternalAPIByDiffrentUserThenCreatorOfAsset", parallel=true) public static Object[][] dataProviderUpdateArtifactOnVFViaExternalAPIByDiffrentUserThenCreatorOfAsset() { return new Object[][] { @@ -1789,8 +1761,6 @@ public class CRUDExternalAPI extends ComponentBaseTest { }; } - - // External API // Update artifact by diffrent user then creator of asset - Fail @Test(dataProvider="updateArtifactOnVFViaExternalAPIByDiffrentUserThenCreatorOfAsset") @@ -1812,8 +1782,6 @@ public class CRUDExternalAPI extends ComponentBaseTest { }; } - - // External API // Upload artifact on VF via external API - happy flow @Test(dataProvider="updateArtifactOnAssetWhichNotExist") @@ -1875,7 +1843,6 @@ public class CRUDExternalAPI extends ComponentBaseTest { }; } - @Test(dataProvider="updateArtifactOnAssetWhichInInvalidStateForUploading") public void updateArtifactOnAssetWhichInInvalidStateForUploading(ComponentTypeEnum componentTypeEnum, String artifactType) throws Exception { getExtendTest().log(Status.INFO, String.format("componentTypeEnum: %s, artifactType: %s", componentTypeEnum, artifactType)); @@ -2065,10 +2032,10 @@ public class CRUDExternalAPI extends ComponentBaseTest { if(componentInstance != null) { updateArtifactOfAssetIncludingValiditionOfAuditAndResponseCode(component, ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER), - 400, component.getComponentInstances().get(0), artifactReqDetails, artifactUUID, errorInfo, variables, null, true); + errorInfo.getCode(), component.getComponentInstances().get(0), artifactReqDetails, artifactUUID, errorInfo, variables, null, true); } else { updateArtifactOfAssetIncludingValiditionOfAuditAndResponseCode(component, ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER), - 400, null, artifactReqDetails, artifactUUID, errorInfo, variables, null, true); + errorInfo.getCode(), null, artifactReqDetails, artifactUUID, errorInfo, variables, null, true); } } @@ -2100,10 +2067,10 @@ public class CRUDExternalAPI extends ComponentBaseTest { if(componentInstance != null) { updateArtifactOfAssetIncludingValiditionOfAuditAndResponseCode(component, ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER), - 400, component.getComponentInstances().get(0), artifactReqDetails, artifactUUID, errorInfo, variables, null, true); + errorInfo.getCode(), component.getComponentInstances().get(0), artifactReqDetails, artifactUUID, errorInfo, variables, null, true); } else { updateArtifactOfAssetIncludingValiditionOfAuditAndResponseCode(component, ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER), - 400, null, artifactReqDetails, artifactUUID, errorInfo, variables, null, true); + errorInfo.getCode(), null, artifactReqDetails, artifactUUID, errorInfo, variables, null, true); } } @@ -2135,10 +2102,10 @@ public class CRUDExternalAPI extends ComponentBaseTest { if(componentInstance != null) { updateArtifactOfAssetIncludingValiditionOfAuditAndResponseCode(component, ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER), - 400, component.getComponentInstances().get(0), artifactReqDetails, artifactUUID, errorInfo, variables, null, true); + errorInfo.getCode(), component.getComponentInstances().get(0), artifactReqDetails, artifactUUID, errorInfo, variables, null, true); } else { updateArtifactOfAssetIncludingValiditionOfAuditAndResponseCode(component, ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER), - 400, null, artifactReqDetails, artifactUUID, errorInfo, variables, null, true); + errorInfo.getCode(), null, artifactReqDetails, artifactUUID, errorInfo, variables, null, true); } } @@ -2170,10 +2137,10 @@ public class CRUDExternalAPI extends ComponentBaseTest { if(componentInstance != null) { updateArtifactOfAssetIncludingValiditionOfAuditAndResponseCode(component, ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER), - 400, component.getComponentInstances().get(0), artifactReqDetails, artifactUUID, errorInfo, variables, null, true); + errorInfo.getCode(), component.getComponentInstances().get(0), artifactReqDetails, artifactUUID, errorInfo, variables, null, true); } else { updateArtifactOfAssetIncludingValiditionOfAuditAndResponseCode(component, ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER), - 400, null, artifactReqDetails, artifactUUID, errorInfo, variables, null, true); + errorInfo.getCode(), null, artifactReqDetails, artifactUUID, errorInfo, variables, null, true); } } @@ -2205,10 +2172,10 @@ public class CRUDExternalAPI extends ComponentBaseTest { if(componentInstance != null) { updateArtifactOfAssetIncludingValiditionOfAuditAndResponseCode(component, ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER), - 400, component.getComponentInstances().get(0), artifactReqDetails, artifactUUID, errorInfo, variables, null, true); + errorInfo.getCode(), component.getComponentInstances().get(0), artifactReqDetails, artifactUUID, errorInfo, variables, null, true); } else { updateArtifactOfAssetIncludingValiditionOfAuditAndResponseCode(component, ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER), - 400, null, artifactReqDetails, artifactUUID, errorInfo, variables, null, true); + errorInfo.getCode(), null, artifactReqDetails, artifactUUID, errorInfo, variables, null, true); } } @@ -2241,21 +2208,14 @@ public class CRUDExternalAPI extends ComponentBaseTest { if(componentInstance != null) { updateArtifactOfAssetIncludingValiditionOfAuditAndResponseCode(component, ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER), - 400, component.getComponentInstances().get(0), artifactReqDetails, artifactUUID, errorInfo, variables, null, true); + errorInfo.getCode(), component.getComponentInstances().get(0), artifactReqDetails, artifactUUID, errorInfo, variables, null, true); } else { updateArtifactOfAssetIncludingValiditionOfAuditAndResponseCode(component, ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER), - 400, null, artifactReqDetails, artifactUUID, errorInfo, variables, null, true); + errorInfo.getCode(), null, artifactReqDetails, artifactUUID, errorInfo, variables, null, true); } } - - - - - - - // Unhappy flow - get chosen life cycle state, artifact type and asset type // update artifact via external API + check audit & response code @@ -2305,14 +2265,14 @@ public class CRUDExternalAPI extends ComponentBaseTest { return component; } - protected RestResponse updateArtifactOfAssetIncludingValiditionOfAuditAndResponseCode(Component resourceDetails, User sdncModifierDetails, + protected RestResponse updateArtifactOfAssetIncludingValiditionOfAuditAndResponseCode(Component component, User sdncModifierDetails, Integer expectedResponseCode, ComponentInstance componentInstance, ArtifactReqDetails artifactReqDetails, String artifactUUID, ErrorInfo errorInfo, List variables, LifeCycleStatesEnum lifeCycleStatesEnum, Boolean resourceNameInAudit) throws Exception { RestResponse restResponse; if(componentInstance != null) { - restResponse = ArtifactRestUtils.externalAPIUpdateArtifactOfComponentInstanceOnAsset(resourceDetails, sdncModifierDetails, artifactReqDetails, componentInstance, artifactUUID); + restResponse = ArtifactRestUtils.externalAPIUpdateArtifactOfComponentInstanceOnAsset(component, sdncModifierDetails, artifactReqDetails, componentInstance, artifactUUID); } else { - restResponse = ArtifactRestUtils.externalAPIUpdateArtifactOfTheAsset(resourceDetails, sdncModifierDetails, artifactReqDetails, artifactUUID); + restResponse = ArtifactRestUtils.externalAPIUpdateArtifactOfTheAsset(component, sdncModifierDetails, artifactReqDetails, artifactUUID); } @@ -2326,35 +2286,35 @@ public class CRUDExternalAPI extends ComponentBaseTest { AuditingActionEnum action = AuditingActionEnum.ARTIFACT_UPDATE_BY_API; - AssetTypeEnum assetTypeEnum = AssetTypeEnum.valueOf((resourceDetails.getComponentType().getValue() + "s").toUpperCase()); + AssetTypeEnum assetTypeEnum = AssetTypeEnum.valueOf((component.getComponentType().getValue() + "s").toUpperCase()); // ExpectedExternalAudit expectedExternalAudit = ElementFactory.getDefaultExternalArtifactAuditSuccess(assetTypeEnum, action, responseArtifact, resourceDetails); responseArtifact.setUpdaterFullName(""); responseArtifact.setUserIdLastUpdater(sdncModifierDetails.getUserId()); - ExpectedExternalAudit expectedExternalAudit = ElementFactory.getDefaultExternalArtifactAuditFailure(assetTypeEnum, action, responseArtifact, resourceDetails.getUUID(), errorInfo, variables); - expectedExternalAudit.setRESOURCE_NAME(resourceDetails.getName()); - expectedExternalAudit.setRESOURCE_TYPE(resourceDetails.getComponentType().getValue()); + ExpectedExternalAudit expectedExternalAudit = ElementFactory.getDefaultExternalArtifactAuditFailure(assetTypeEnum, action, responseArtifact, component.getUUID(), errorInfo, variables); + expectedExternalAudit.setRESOURCE_NAME(component.getName()); + expectedExternalAudit.setRESOURCE_TYPE(component.getComponentType().getValue()); expectedExternalAudit.setARTIFACT_DATA(""); expectedExternalAudit.setCURR_ARTIFACT_UUID(artifactUUID); Map body = new HashMap<>(); body.put(AuditingFieldsKeysEnum.AUDIT_STATUS, responseCode.toString()); if(componentInstance != null) { - body.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_NAME, resourceDetails.getComponentInstances().get(0).getNormalizedName()); - expectedExternalAudit.setRESOURCE_URL("/sdc/v1/catalog/" + assetTypeEnum.getValue() + "/" + resourceDetails.getUUID() + "/resourceInstances/" + resourceDetails.getComponentInstances().get(0).getNormalizedName() + "/artifacts/" + artifactUUID); - expectedExternalAudit.setRESOURCE_NAME(resourceDetails.getComponentInstances().get(0).getNormalizedName()); + body.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_NAME, component.getComponentInstances().get(0).getNormalizedName()); + expectedExternalAudit.setRESOURCE_URL("/sdc/v1/catalog/" + assetTypeEnum.getValue() + "/" + component.getUUID() + "/resourceInstances/" + component.getComponentInstances().get(0).getNormalizedName() + "/artifacts/" + artifactUUID); + expectedExternalAudit.setRESOURCE_NAME(component.getComponentInstances().get(0).getNormalizedName()); } else { expectedExternalAudit.setRESOURCE_URL(expectedExternalAudit.getRESOURCE_URL() + "/" + artifactUUID); if((lifeCycleStatesEnum == LifeCycleStatesEnum.CHECKIN) || (lifeCycleStatesEnum == LifeCycleStatesEnum.STARTCERTIFICATION)) { if(resourceNameInAudit) { - expectedExternalAudit.setRESOURCE_NAME(resourceDetails.getName()); - body.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_NAME, resourceDetails.getName()); + expectedExternalAudit.setRESOURCE_NAME(component.getName()); + body.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_NAME, component.getName()); } else { body.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_URL, expectedExternalAudit.getRESOURCE_URL()); // body.put(AuditingFieldsKeysEnum.AUDIT_CURR_ARTIFACT_UUID, artifactUUID); expectedExternalAudit.setRESOURCE_NAME(""); } } else { - body.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_NAME, resourceDetails.getName()); + body.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_NAME, component.getName()); } } @@ -2381,7 +2341,7 @@ public class CRUDExternalAPI extends ComponentBaseTest { return downloadResourceDeploymentArtifactExternalAPI(component, component.getDeploymentArtifacts().get(artifactName), sdncModifierDetails, artifactReqDetails, componentTypeEnum); } - // Get deployment artifact of asset + // Get deployment artifact of RI protected Map getDeploymentArtifactsOfAsset(Component component, ComponentTypeEnum componentTypeEnum) { Map deploymentArtifacts = null; if(ComponentTypeEnum.RESOURCE_INSTANCE == componentTypeEnum) { @@ -2447,20 +2407,13 @@ public class CRUDExternalAPI extends ComponentBaseTest { deploymentArtifacts = getDeploymentArtifactsOfAsset(component, componentTypeEnum); numberOfArtifact = deploymentArtifacts.size(); - // create component/s & upload artifact via external api if(ComponentTypeEnum.RESOURCE_INSTANCE == componentTypeEnum) { - if((chosenLifeCycleState == LifeCycleStatesEnum.CERTIFICATIONREQUEST) && (!component.getComponentType().toString().equals(ComponentTypeEnum.RESOURCE.toString()))) { - numberOfArtifact = numberOfArtifact - 1; - } restResponse = updateArtifactOfRIIncludingValiditionOfAuditAndResponseCode(component, component.getComponentInstances().get(0), ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER), artifactReqDetails, artifactUUID, 200); } else { - restResponse = updateArtifactOfAssetIncludingValiditionOfAuditAndResponseCode(component, ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER), artifactReqDetails, artifactUUID, 200); } - - ArtifactDefinition responseArtifact = getArtifactDataFromJson(restResponse.getResponse()); component = getNewerVersionOfComponent(component, chosenLifeCycleState); @@ -2483,8 +2436,8 @@ public class CRUDExternalAPI extends ComponentBaseTest { // Update artifact via external API + Check auditing for upload operation + Check response of external API - protected RestResponse updateArtifactOfRIIncludingValiditionOfAuditAndResponseCode(Component resourceDetails, ComponentInstance componentInstance, User sdncModifierDetails, ArtifactReqDetails artifactReqDetails, String artifactUUID, Integer expectedResponseCode) throws Exception { - RestResponse restResponse = ArtifactRestUtils.externalAPIUpdateArtifactOfComponentInstanceOnAsset(resourceDetails, ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER), artifactReqDetails, resourceDetails.getComponentInstances().get(0), artifactUUID); + protected RestResponse updateArtifactOfRIIncludingValiditionOfAuditAndResponseCode(Component component, ComponentInstance componentInstance, User sdncModifierDetails, ArtifactReqDetails artifactReqDetails, String artifactUUID, Integer expectedResponseCode) throws Exception { + RestResponse restResponse = ArtifactRestUtils.externalAPIUpdateArtifactOfComponentInstanceOnAsset(component, ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER), artifactReqDetails, component.getComponentInstances().get(0), artifactUUID); // Check response of external API Integer responseCode = restResponse.getErrorCode(); @@ -2499,11 +2452,11 @@ public class CRUDExternalAPI extends ComponentBaseTest { Map body = new HashMap<>(); body.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_NAME, componentInstance.getNormalizedName()); - AssetTypeEnum assetTypeEnum = AssetTypeEnum.valueOf((resourceDetails.getComponentType().getValue() + "s").toUpperCase()); - ExpectedExternalAudit expectedExternalAudit = ElementFactory.getDefaultExternalArtifactAuditSuccess(assetTypeEnum, action, responseArtifact, resourceDetails); + AssetTypeEnum assetTypeEnum = AssetTypeEnum.valueOf((component.getComponentType().getValue() + "s").toUpperCase()); + ExpectedExternalAudit expectedExternalAudit = ElementFactory.getDefaultExternalArtifactAuditSuccess(assetTypeEnum, action, responseArtifact, component); // expectedExternalAudit.setRESOURCE_URL(expectedExternalAudit.getRESOURCE_URL()+ "/" + artifactUUID); expectedExternalAudit.setRESOURCE_NAME(componentInstance.getNormalizedName()); - expectedExternalAudit.setRESOURCE_URL("/sdc/v1/catalog/" + assetTypeEnum.getValue() + "/" + resourceDetails.getUUID() + "/resourceInstances/" + componentInstance.getNormalizedName() + "/artifacts/" + artifactUUID); + expectedExternalAudit.setRESOURCE_URL("/sdc/v1/catalog/" + assetTypeEnum.getValue() + "/" + component.getUUID() + "/resourceInstances/" + componentInstance.getNormalizedName() + "/artifacts/" + artifactUUID); AuditValidationUtils.validateExternalAudit(expectedExternalAudit, AuditingActionEnum.ARTIFACT_UPDATE_BY_API.getName(), body); return restResponse; @@ -2511,8 +2464,8 @@ public class CRUDExternalAPI extends ComponentBaseTest { // Update artifact via external API + Check auditing for upload operation + Check response of external API - protected RestResponse updateArtifactOfAssetIncludingValiditionOfAuditAndResponseCode(Component resourceDetails, User sdncModifierDetails, ArtifactReqDetails artifactReqDetails, String artifactUUID, Integer expectedResponseCode) throws Exception { - RestResponse restResponse = ArtifactRestUtils.externalAPIUpdateArtifactOfTheAsset(resourceDetails, ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER), artifactReqDetails, artifactUUID); + protected RestResponse updateArtifactOfAssetIncludingValiditionOfAuditAndResponseCode(Component component, User sdncModifierDetails, ArtifactReqDetails artifactReqDetails, String artifactUUID, Integer expectedResponseCode) throws Exception { + RestResponse restResponse = ArtifactRestUtils.externalAPIUpdateArtifactOfTheAsset(component, ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER), artifactReqDetails, artifactUUID); // Check response of external API Integer responseCode = restResponse.getErrorCode(); @@ -2525,10 +2478,10 @@ public class CRUDExternalAPI extends ComponentBaseTest { AuditingActionEnum action = AuditingActionEnum.ARTIFACT_UPDATE_BY_API; Map body = new HashMap<>(); - body.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_NAME, resourceDetails.getName()); + body.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_NAME, component.getName()); - AssetTypeEnum assetTypeEnum = AssetTypeEnum.valueOf((resourceDetails.getComponentType().getValue() + "s").toUpperCase()); - ExpectedExternalAudit expectedExternalAudit = ElementFactory.getDefaultExternalArtifactAuditSuccess(assetTypeEnum, action, responseArtifact, resourceDetails); + AssetTypeEnum assetTypeEnum = AssetTypeEnum.valueOf((component.getComponentType().getValue() + "s").toUpperCase()); + ExpectedExternalAudit expectedExternalAudit = ElementFactory.getDefaultExternalArtifactAuditSuccess(assetTypeEnum, action, responseArtifact, component); expectedExternalAudit.setRESOURCE_URL(expectedExternalAudit.getRESOURCE_URL()+ "/" + artifactUUID); AuditValidationUtils.validateExternalAudit(expectedExternalAudit, AuditingActionEnum.ARTIFACT_UPDATE_BY_API.getName(), body); @@ -2571,9 +2524,6 @@ public class CRUDExternalAPI extends ComponentBaseTest { }; } - - - // Delete artifact for Service - Success @Test(dataProvider="deleteArtifactForServiceViaExternalAPI") public void deleteArtifactForServiceViaExternalAPI(LifeCycleStatesEnum lifeCycleStatesEnum, String artifactType) throws Exception { @@ -2935,7 +2885,7 @@ public class CRUDExternalAPI extends ComponentBaseTest { // External API - // Delete artifact by diffrent user then creator of asset - Fail + // Delete artifact by different user then creator of asset - Fail @Test(dataProvider="deleteArtifactOnVFViaExternalAPIByDiffrentUserThenCreatorOfAsset") public void deleteArtifactOnVFViaExternalAPIByDiffrentUserThenCreatorOfAsset(ComponentTypeEnum componentTypeEnum, UserRoleEnum userRoleEnum, LifeCycleStatesEnum lifeCycleStatesEnum, String artifactType) throws Exception { getExtendTest().log(Status.INFO, String.format("componentTypeEnum: %s, userRoleEnum %s, lifeCycleStatesEnum %s, artifactType: %s", componentTypeEnum, userRoleEnum, lifeCycleStatesEnum, artifactType)); @@ -2955,10 +2905,10 @@ public class CRUDExternalAPI extends ComponentBaseTest { if(componentTypeEnum.equals(ComponentTypeEnum.RESOURCE_INSTANCE)) { deleteArtifactOfAssetIncludingValiditionOfAuditAndResponseCode(component, ElementFactory.getDefaultUser(userRoleEnum), - 409, component.getComponentInstances().get(0), artifactUUID, errorInfo, variables, lifeCycleStatesEnum, true); + errorInfo.getCode(), component.getComponentInstances().get(0), artifactUUID, errorInfo, variables, lifeCycleStatesEnum, true); } else { deleteArtifactOfAssetIncludingValiditionOfAuditAndResponseCode(component, ElementFactory.getDefaultUser(userRoleEnum), - 409, null, artifactUUID, errorInfo, variables, lifeCycleStatesEnum, true); + errorInfo.getCode(), null, artifactUUID, errorInfo, variables, lifeCycleStatesEnum, true); } //TODO @@ -3000,10 +2950,10 @@ public class CRUDExternalAPI extends ComponentBaseTest { if(componentTypeEnum.equals(ComponentTypeEnum.RESOURCE_INSTANCE)) { deleteArtifactOfAssetIncludingValiditionOfAuditAndResponseCode(component, ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER), - 404, component.getComponentInstances().get(0), invalidArtifactUUID, errorInfo, variables, null, true); + errorInfo.getCode(), component.getComponentInstances().get(0), invalidArtifactUUID, errorInfo, variables, null, true); } else { deleteArtifactOfAssetIncludingValiditionOfAuditAndResponseCode(component, ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER), - 404, null, invalidArtifactUUID, errorInfo, variables, null, true); + errorInfo.getCode(), null, invalidArtifactUUID, errorInfo, variables, null, true); } @@ -3014,7 +2964,7 @@ public class CRUDExternalAPI extends ComponentBaseTest { errorInfo = ErrorValidationUtils.parseErrorConfigYaml(ActionStatus.COMPONENT_INSTANCE_NOT_FOUND_ON_CONTAINER.name()); variables = asList("invalidNormalizedName", ComponentTypeEnum.RESOURCE_INSTANCE.getValue().toLowerCase(), ComponentTypeEnum.SERVICE.getValue(), component.getName()); deleteArtifactOfAssetIncludingValiditionOfAuditAndResponseCode(component, ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER), - 404, component.getComponentInstances().get(0), artifactUUID, errorInfo, variables, LifeCycleStatesEnum.CHECKIN, true); + errorInfo.getCode(), component.getComponentInstances().get(0), artifactUUID, errorInfo, variables, LifeCycleStatesEnum.CHECKIN, true); } else { component.setUUID("invalidComponentUUID"); if(componentTypeEnum.equals(ComponentTypeEnum.RESOURCE)) { @@ -3024,7 +2974,7 @@ public class CRUDExternalAPI extends ComponentBaseTest { } variables = asList("invalidComponentUUID"); deleteArtifactOfAssetIncludingValiditionOfAuditAndResponseCode(component, ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER), - 404, null, artifactUUID, errorInfo, variables, LifeCycleStatesEnum.CHECKIN, false); + errorInfo.getCode(), null, artifactUUID, errorInfo, variables, LifeCycleStatesEnum.CHECKIN, false); } @@ -3065,10 +3015,10 @@ public class CRUDExternalAPI extends ComponentBaseTest { if(componentTypeEnum.equals(ComponentTypeEnum.RESOURCE_INSTANCE)) { deleteArtifactOfAssetIncludingValiditionOfAuditAndResponseCode(component, ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER), - 403, component.getComponentInstances().get(0), artifactUUID, errorInfo, variables, null, true); + errorInfo.getCode(), component.getComponentInstances().get(0), artifactUUID, errorInfo, variables, null, true); } else { deleteArtifactOfAssetIncludingValiditionOfAuditAndResponseCode(component, ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER), - 403, null, artifactUUID, errorInfo, variables, null, true); + errorInfo.getCode(), null, artifactUUID, errorInfo, variables, null, true); } @@ -3110,17 +3060,17 @@ public class CRUDExternalAPI extends ComponentBaseTest { } List variables = asList(artifactUUID); deleteArtifactOfAssetIncludingValiditionOfAuditAndResponseCode(component, ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER), - 404, component.getComponentInstances().get(0), artifactUUID, errorInfo, variables, null, true); + errorInfo.getCode(), component.getComponentInstances().get(0), artifactUUID, errorInfo, variables, null, true); } - protected RestResponse deleteArtifactOfAssetIncludingValiditionOfAuditAndResponseCode(Component resourceDetails, User sdncModifierDetails, + protected RestResponse deleteArtifactOfAssetIncludingValiditionOfAuditAndResponseCode(Component component, User sdncModifierDetails, Integer expectedResponseCode, ComponentInstance componentInstance, String artifactUUID, ErrorInfo errorInfo, List variables, LifeCycleStatesEnum lifeCycleStatesEnum, Boolean resourceNameInAudit) throws Exception { RestResponse restResponse; if(componentInstance != null) { - restResponse = ArtifactRestUtils.externalAPIDeleteArtifactOfComponentInstanceOnAsset(resourceDetails, sdncModifierDetails, componentInstance, artifactUUID); + restResponse = ArtifactRestUtils.externalAPIDeleteArtifactOfComponentInstanceOnAsset(component, sdncModifierDetails, componentInstance, artifactUUID); } else { - restResponse = ArtifactRestUtils.externalAPIDeleteArtifactOfTheAsset(resourceDetails, sdncModifierDetails, artifactUUID); + restResponse = ArtifactRestUtils.externalAPIDeleteArtifactOfTheAsset(component, sdncModifierDetails, artifactUUID); } @@ -3133,37 +3083,37 @@ public class CRUDExternalAPI extends ComponentBaseTest { AuditingActionEnum action = AuditingActionEnum.ARTIFACT_DELETE_BY_API; - AssetTypeEnum assetTypeEnum = AssetTypeEnum.valueOf((resourceDetails.getComponentType().getValue() + "s").toUpperCase()); + AssetTypeEnum assetTypeEnum = AssetTypeEnum.valueOf((component.getComponentType().getValue() + "s").toUpperCase()); // ExpectedExternalAudit expectedExternalAudit = ElementFactory.getDefaultExternalArtifactAuditSuccess(assetTypeEnum, action, responseArtifact, resourceDetails); responseArtifact.setUpdaterFullName(""); responseArtifact.setUserIdLastUpdater(sdncModifierDetails.getUserId()); - ExpectedExternalAudit expectedExternalAudit = ElementFactory.getDefaultExternalArtifactAuditFailure(assetTypeEnum, action, responseArtifact, resourceDetails.getUUID(), errorInfo, variables); - expectedExternalAudit.setRESOURCE_NAME(resourceDetails.getName()); - expectedExternalAudit.setRESOURCE_TYPE(resourceDetails.getComponentType().getValue()); + ExpectedExternalAudit expectedExternalAudit = ElementFactory.getDefaultExternalArtifactAuditFailure(assetTypeEnum, action, responseArtifact, component.getUUID(), errorInfo, variables); + expectedExternalAudit.setRESOURCE_NAME(component.getName()); + expectedExternalAudit.setRESOURCE_TYPE(component.getComponentType().getValue()); expectedExternalAudit.setARTIFACT_DATA(null); expectedExternalAudit.setCURR_ARTIFACT_UUID(artifactUUID); Map body = new HashMap<>(); body.put(AuditingFieldsKeysEnum.AUDIT_STATUS, responseCode.toString()); if(componentInstance != null) { - body.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_NAME, resourceDetails.getComponentInstances().get(0).getNormalizedName()); - expectedExternalAudit.setRESOURCE_URL("/sdc/v1/catalog/" + assetTypeEnum.getValue() + "/" + resourceDetails.getUUID() + "/resourceInstances/" + resourceDetails.getComponentInstances().get(0).getNormalizedName() + "/artifacts/" + artifactUUID); - expectedExternalAudit.setRESOURCE_NAME(resourceDetails.getComponentInstances().get(0).getNormalizedName()); + body.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_NAME, component.getComponentInstances().get(0).getNormalizedName()); + expectedExternalAudit.setRESOURCE_URL("/sdc/v1/catalog/" + assetTypeEnum.getValue() + "/" + component.getUUID() + "/resourceInstances/" + component.getComponentInstances().get(0).getNormalizedName() + "/artifacts/" + artifactUUID); + expectedExternalAudit.setRESOURCE_NAME(component.getComponentInstances().get(0).getNormalizedName()); } else { expectedExternalAudit.setRESOURCE_URL(expectedExternalAudit.getRESOURCE_URL() + "/" + artifactUUID); if((errorInfo.getMessageId().equals(ErrorValidationUtils.parseErrorConfigYaml(ActionStatus.RESOURCE_NOT_FOUND.name()).getMessageId())) || errorInfo.getMessageId().equals(ErrorValidationUtils.parseErrorConfigYaml(ActionStatus.COMPONENT_IN_CERT_IN_PROGRESS_STATE.name()).getMessageId()) || (lifeCycleStatesEnum == LifeCycleStatesEnum.STARTCERTIFICATION)) { if(resourceNameInAudit) { - expectedExternalAudit.setRESOURCE_NAME(resourceDetails.getName()); - body.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_NAME, resourceDetails.getName()); + expectedExternalAudit.setRESOURCE_NAME(component.getName()); + body.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_NAME, component.getName()); } else { expectedExternalAudit.setRESOURCE_NAME(""); body.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_URL, expectedExternalAudit.getRESOURCE_URL()); } } else { if(resourceNameInAudit) { - body.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_NAME, resourceDetails.getName()); + body.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_NAME, component.getName()); } else { expectedExternalAudit.setRESOURCE_NAME(""); body.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_URL, expectedExternalAudit.getRESOURCE_URL()); @@ -3185,7 +3135,11 @@ public class CRUDExternalAPI extends ComponentBaseTest { protected Component deleteArtifactOnAssetViaExternalAPI(Component component, ComponentTypeEnum componentTypeEnum, LifeCycleStatesEnum chosenLifeCycleState) throws Exception { String artifactName = null; component = AtomicOperationUtils.changeComponentState(component, UserRoleEnum.DESIGNER, chosenLifeCycleState, true).getLeft(); - + if(!LifeCycleStatesEnum.CHECKOUT.equals(chosenLifeCycleState)){ + component = AtomicOperationUtils.getComponentObject(component, UserRoleEnum.DESIGNER); + }else{ + component = getNewerVersionOfComponent(component, chosenLifeCycleState); + } // get updated artifact data String artifactUUID = null; int moduleTypeArtifact = 0; @@ -3202,12 +3156,9 @@ public class CRUDExternalAPI extends ComponentBaseTest { break; } } - String componentVersionBeforeDelete = component.getVersion(); int numberOfArtifact = deploymentArtifacts.size(); - - // create component/s & upload artifact via external api if(ComponentTypeEnum.RESOURCE_INSTANCE == componentTypeEnum) { @@ -3215,8 +3166,8 @@ public class CRUDExternalAPI extends ComponentBaseTest { } else { deleteArtifactOfAssetIncludingValiditionOfAuditAndResponseCode(component, ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER), artifactUUID, 200); } - - component = getNewerVersionOfComponent(component, chosenLifeCycleState); + + component = updateComponentDetailsByLifeCycleState(chosenLifeCycleState, component); // Get list of deployment artifact + download them via external API deploymentArtifacts = getDeploymentArtifactsOfAsset(component, componentTypeEnum); @@ -3228,7 +3179,6 @@ public class CRUDExternalAPI extends ComponentBaseTest { } else { Assert.assertEquals(numberOfArtifact - 1, deploymentArtifacts.keySet().size(), "Expected that number of deployment artifact will decrease by one."); } - if(chosenLifeCycleState == LifeCycleStatesEnum.CHECKOUT) { Assert.assertEquals(componentVersionBeforeDelete, component.getVersion(), "Expected that check-out component will not change version number."); @@ -3242,8 +3192,8 @@ public class CRUDExternalAPI extends ComponentBaseTest { } // Delete artifact via external API + Check auditing for upload operation + Check response of external API - protected RestResponse deleteArtifactOfRIIncludingValiditionOfAuditAndResponseCode(Component resourceDetails, ComponentInstance componentInstance, User sdncModifierDetails, String artifactUUID, Integer expectedResponseCode) throws Exception { - RestResponse restResponse = ArtifactRestUtils.externalAPIDeleteArtifactOfComponentInstanceOnAsset(resourceDetails, ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER), resourceDetails.getComponentInstances().get(0), artifactUUID); + protected RestResponse deleteArtifactOfRIIncludingValiditionOfAuditAndResponseCode(Component component, ComponentInstance componentInstance, User sdncModifierDetails, String artifactUUID, Integer expectedResponseCode) throws Exception { + RestResponse restResponse = ArtifactRestUtils.externalAPIDeleteArtifactOfComponentInstanceOnAsset(component, ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER), component.getComponentInstances().get(0), artifactUUID); // Check response of external API Integer responseCode = restResponse.getErrorCode(); @@ -3258,20 +3208,20 @@ public class CRUDExternalAPI extends ComponentBaseTest { Map body = new HashMap<>(); body.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_NAME, componentInstance.getNormalizedName()); - AssetTypeEnum assetTypeEnum = AssetTypeEnum.valueOf((resourceDetails.getComponentType().getValue() + "s").toUpperCase()); - ExpectedExternalAudit expectedExternalAudit = ElementFactory.getDefaultExternalArtifactAuditSuccess(assetTypeEnum, action, responseArtifact, resourceDetails); + AssetTypeEnum assetTypeEnum = AssetTypeEnum.valueOf((component.getComponentType().getValue() + "s").toUpperCase()); + ExpectedExternalAudit expectedExternalAudit = ElementFactory.getDefaultExternalArtifactAuditSuccess(assetTypeEnum, action, responseArtifact, component); // expectedExternalAudit.setRESOURCE_URL(expectedExternalAudit.getRESOURCE_URL()+ "/" + artifactUUID); expectedExternalAudit.setRESOURCE_NAME(componentInstance.getNormalizedName()); - expectedExternalAudit.setRESOURCE_URL("/sdc/v1/catalog/" + assetTypeEnum.getValue() + "/" + resourceDetails.getUUID() + "/resourceInstances/" + componentInstance.getNormalizedName() + "/artifacts/" + artifactUUID); + expectedExternalAudit.setRESOURCE_URL("/sdc/v1/catalog/" + assetTypeEnum.getValue() + "/" + component.getUUID() + "/resourceInstances/" + componentInstance.getNormalizedName() + "/artifacts/" + artifactUUID); AuditValidationUtils.validateExternalAudit(expectedExternalAudit, AuditingActionEnum.ARTIFACT_DELETE_BY_API.getName(), body); - + component = AtomicOperationUtils.getComponentObject(component, UserRoleEnum.DESIGNER); return restResponse; } // Delete artifact via external API + Check auditing for upload operation + Check response of external API - protected RestResponse deleteArtifactOfAssetIncludingValiditionOfAuditAndResponseCode(Component resourceDetails, User sdncModifierDetails, String artifactUUID, Integer expectedResponseCode) throws Exception { - RestResponse restResponse = ArtifactRestUtils.externalAPIDeleteArtifactOfTheAsset(resourceDetails, ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER), artifactUUID); + protected RestResponse deleteArtifactOfAssetIncludingValiditionOfAuditAndResponseCode(Component component, User sdncModifierDetails, String artifactUUID, Integer expectedResponseCode) throws Exception { + RestResponse restResponse = ArtifactRestUtils.externalAPIDeleteArtifactOfTheAsset(component, ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER), artifactUUID); // Check response of external API Integer responseCode = restResponse.getErrorCode(); @@ -3284,26 +3234,26 @@ public class CRUDExternalAPI extends ComponentBaseTest { AuditingActionEnum action = AuditingActionEnum.ARTIFACT_DELETE_BY_API; Map body = new HashMap<>(); - body.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_NAME, resourceDetails.getName()); + body.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_NAME, component.getName()); - AssetTypeEnum assetTypeEnum = AssetTypeEnum.valueOf((resourceDetails.getComponentType().getValue() + "s").toUpperCase()); - ExpectedExternalAudit expectedExternalAudit = ElementFactory.getDefaultExternalArtifactAuditSuccess(assetTypeEnum, action, responseArtifact, resourceDetails); + AssetTypeEnum assetTypeEnum = AssetTypeEnum.valueOf((component.getComponentType().getValue() + "s").toUpperCase()); + ExpectedExternalAudit expectedExternalAudit = ElementFactory.getDefaultExternalArtifactAuditSuccess(assetTypeEnum, action, responseArtifact, component); expectedExternalAudit.setRESOURCE_URL(expectedExternalAudit.getRESOURCE_URL()+ "/" + artifactUUID); AuditValidationUtils.validateExternalAudit(expectedExternalAudit, AuditingActionEnum.ARTIFACT_DELETE_BY_API.getName(), body); - + component = AtomicOperationUtils.getComponentObject(component, UserRoleEnum.DESIGNER); return restResponse; } // download deployment via external api + check response code for success (200) + get artifactReqDetails and verify payload + verify audit - protected RestResponse downloadResourceDeploymentArtifactExternalAPI(Component resourceDetails, User sdncModifierDetails, String artifactUUID, ComponentTypeEnum componentTypeEnum) throws Exception { + protected RestResponse downloadResourceDeploymentArtifactExternalAPI(Component component, User sdncModifierDetails, String artifactUUID, ComponentTypeEnum componentTypeEnum) throws Exception { RestResponse restResponse; if(componentTypeEnum == ComponentTypeEnum.RESOURCE_INSTANCE) { - restResponse = ArtifactRestUtils.getComponentInstanceDeploymentArtifactExternalAPI(resourceDetails.getUUID(), resourceDetails.getComponentInstances().get(0).getNormalizedName(), artifactUUID, ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER), resourceDetails.getComponentType().toString()); + restResponse = ArtifactRestUtils.getComponentInstanceDeploymentArtifactExternalAPI(component.getUUID(), component.getComponentInstances().get(0).getNormalizedName(), artifactUUID, ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER), component.getComponentType().toString()); } else { - restResponse = ArtifactRestUtils.getResourceDeploymentArtifactExternalAPI(resourceDetails.getUUID(), artifactUUID, ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER), resourceDetails.getComponentType().toString()); + restResponse = ArtifactRestUtils.getResourceDeploymentArtifactExternalAPI(component.getUUID(), artifactUUID, ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER), component.getComponentType().toString()); } Integer responseCode = restResponse.getErrorCode(); diff --git a/test-apis-ci/src/main/java/org/openecomp/sdc/externalApis/GetCSARofVF.java b/test-apis-ci/src/main/java/org/openecomp/sdc/externalApis/GetCSARofVF.java index 6acc54b54c..9d56316b18 100644 --- a/test-apis-ci/src/main/java/org/openecomp/sdc/externalApis/GetCSARofVF.java +++ b/test-apis-ci/src/main/java/org/openecomp/sdc/externalApis/GetCSARofVF.java @@ -20,11 +20,10 @@ package org.openecomp.sdc.externalApis; -import static org.testng.AssertJUnit.assertEquals; +import static org.testng.AssertJUnit.assertTrue; import java.io.File; import java.io.IOException; -import java.io.InputStream; import java.util.ArrayList; import java.util.Enumeration; import java.util.HashMap; @@ -34,58 +33,27 @@ import java.util.zip.ZipEntry; import java.util.zip.ZipException; import java.util.zip.ZipFile; -import org.apache.commons.codec.binary.Base64; -import org.apache.commons.io.IOUtils; -import org.apache.http.HttpResponse; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClients; -import org.codehaus.jackson.map.ObjectMapper; import org.junit.Rule; import org.junit.rules.TestName; -import org.openecomp.sdc.be.datatypes.elements.ConsumerDataDefinition; import org.openecomp.sdc.be.datatypes.enums.AssetTypeEnum; import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum; -import org.openecomp.sdc.be.model.ArtifactUiDownloadData; import org.openecomp.sdc.be.model.Component; import org.openecomp.sdc.be.model.Resource; import org.openecomp.sdc.be.model.Service; -import org.openecomp.sdc.be.model.User; import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum; import org.openecomp.sdc.ci.tests.api.ComponentBaseTest; -import org.openecomp.sdc.ci.tests.api.Urls; -import org.openecomp.sdc.ci.tests.datatypes.ArtifactReqDetails; -import org.openecomp.sdc.ci.tests.datatypes.ResourceAssetStructure; -import org.openecomp.sdc.ci.tests.datatypes.ResourceReqDetails; -import org.openecomp.sdc.ci.tests.datatypes.ServiceAssetStructure; -import org.openecomp.sdc.ci.tests.datatypes.ServiceReqDetails; import org.openecomp.sdc.ci.tests.datatypes.enums.ArtifactTypeEnum; import org.openecomp.sdc.ci.tests.datatypes.enums.LifeCycleStatesEnum; import org.openecomp.sdc.ci.tests.datatypes.enums.UserRoleEnum; import org.openecomp.sdc.ci.tests.datatypes.expected.ExpectedExternalAudit; -import org.openecomp.sdc.ci.tests.datatypes.http.HttpHeaderEnum; -import org.openecomp.sdc.ci.tests.datatypes.http.RestResponse; -import org.openecomp.sdc.ci.tests.utils.Utils; -import org.openecomp.sdc.ci.tests.utils.cassandra.CassandraUtils; import org.openecomp.sdc.ci.tests.utils.general.AtomicOperationUtils; import org.openecomp.sdc.ci.tests.utils.general.ElementFactory; -import org.openecomp.sdc.ci.tests.utils.rest.ArtifactRestUtils; import org.openecomp.sdc.ci.tests.utils.rest.AssetRestUtils; -import org.openecomp.sdc.ci.tests.utils.rest.BaseRestUtils; -import org.openecomp.sdc.ci.tests.utils.rest.ResourceRestUtils; -import org.openecomp.sdc.ci.tests.utils.rest.ResponseParser; -import org.openecomp.sdc.ci.tests.utils.rest.ServiceRestUtils; import org.openecomp.sdc.ci.tests.utils.validation.AuditValidationUtils; -import org.openecomp.sdc.common.api.Constants; import org.openecomp.sdc.common.datastructure.AuditingFieldsKeysEnum; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; -import static org.testng.AssertJUnit.assertTrue; - -import com.google.gson.Gson; - -import fj.data.Either; public class GetCSARofVF extends ComponentBaseTest { @@ -224,22 +192,42 @@ public class GetCSARofVF extends ComponentBaseTest { } - - - - + /** + * all files in list(expectedDefinitionFolderFileList) must be found in csar file + * @param resource + * @param toscaModelCsarFile + * @throws ZipException + * @throws IOException + */ public void validateCsarContent(Component resource, File toscaModelCsarFile) throws ZipException, IOException { ZipFile zipFile = new ZipFile(toscaModelCsarFile); + List expectedDefinitionFolderFileList = new ArrayList(); + expectedDefinitionFolderFileList.add("Definitions/"+ resource.getComponentType().getValue().toLowerCase()+"-"+ resource.getSystemName()+"-template.yml"); + expectedDefinitionFolderFileList.add("Definitions/"+ resource.getComponentType().getValue().toLowerCase()+"-"+ resource.getSystemName()+"-template-interface.yml"); + expectedDefinitionFolderFileList.add("Definitions/relationships.yml"); + expectedDefinitionFolderFileList.add("Definitions/policies.yml"); + expectedDefinitionFolderFileList.add("Definitions/nodes.yml"); + expectedDefinitionFolderFileList.add("Definitions/interfaces.yml"); + expectedDefinitionFolderFileList.add("Definitions/groups.yml"); + expectedDefinitionFolderFileList.add("Definitions/data.yml"); + expectedDefinitionFolderFileList.add("Definitions/capabilities.yml"); + expectedDefinitionFolderFileList.add("Definitions/artifacts.yml"); + Enumeration entries = zipFile.entries(); while(entries.hasMoreElements()){ ZipEntry nextElement = entries.nextElement(); if (!(nextElement.getName().contains("Artifacts")||nextElement.getName().contains("csar.meta"))){ - assertTrue("missing file in csar template", (nextElement.getName().equals("TOSCA-Metadata/TOSCA.meta") || - nextElement.getName().equals("Definitions/"+ resource.getComponentType().getValue().toLowerCase()+"-"+ resource.getSystemName()+"-template.yml")) || - nextElement.getName().equals("Definitions/"+ resource.getComponentType().getValue().toLowerCase()+"-"+ resource.getSystemName()+"-template-interface.yml")); +// assertTrue("missing file in csar template", (nextElement.getName().equals("TOSCA-Metadata/TOSCA.meta") || +// nextElement.getName().equals("Definitions/"+ resource.getComponentType().getValue().toLowerCase()+"-"+ resource.getSystemName()+"-template.yml")) || +// nextElement.getName().equals("Definitions/"+ resource.getComponentType().getValue().toLowerCase()+"-"+ resource.getSystemName()+"-template-interface.yml")); + if(expectedDefinitionFolderFileList.contains(nextElement.getName())){ + expectedDefinitionFolderFileList.remove(nextElement.getName()); } } + } + zipFile.close(); + assertTrue("missing files in csar template definitions folder", expectedDefinitionFolderFileList.size() == 0); } public void validateAudit(Component resource) throws Exception { diff --git a/test-apis-ci/src/main/java/org/openecomp/sdc/externalApis/VFCMTExternalAPI.java b/test-apis-ci/src/main/java/org/openecomp/sdc/externalApis/VFCMTExternalAPI.java index f93958542d..6e212d3155 100644 --- a/test-apis-ci/src/main/java/org/openecomp/sdc/externalApis/VFCMTExternalAPI.java +++ b/test-apis-ci/src/main/java/org/openecomp/sdc/externalApis/VFCMTExternalAPI.java @@ -216,10 +216,10 @@ public class VFCMTExternalAPI extends ComponentBaseTest { // Various failure flows @Test(dataProvider="createVfcmtVariousFailureFlows") public void createVfcmtVariousFailureFlows(String flow) throws Exception { - + //TODO: check what happens now, test will prbably fail if(flow.equals("resource_type_missing") || flow.equals("resource_type_invalid")) { throw new SkipException("TC require repairs"); - } + } User defaultUser = ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER); ResourceExternalReqDetails defaultResource = ElementFactory.getDefaultResourceByType("ci", ResourceCategoryEnum.TEMPLATE_MONITORING_TEMPLATE, defaultUser.getUserId(), ResourceTypeEnum.VFCMT.toString()); @@ -272,21 +272,21 @@ public class VFCMTExternalAPI extends ComponentBaseTest { case "description_with_invalid_char": defaultResource.setDescription("\uC2B5"); expectedResourceAuditJavaObject.setDesc("t"); - errorInfo = ErrorValidationUtils.parseErrorConfigYaml(ActionStatus.COMPONENT_INVALID_DESCRIPTION.name()); + errorInfo = ErrorValidationUtils.parseErrorConfigYaml(ActionStatus.INVALID_RESOURCE_TYPE.name()); variables = asList(ComponentTypeEnum.RESOURCE.getValue()); break; // TODO: defect on the flow - need to get error instead create VFC case "resource_type_missing": defaultResource.setResourceType(""); expectedResourceAuditJavaObject.setResourceType(""); - errorInfo = ErrorValidationUtils.parseErrorConfigYaml(ActionStatus.COMPONENT_MISSING_DESCRIPTION.name()); + errorInfo = ErrorValidationUtils.parseErrorConfigYaml(ActionStatus.INVALID_CONTENT.name()); variables = asList(ComponentTypeEnum.RESOURCE.getValue()); break; // TODO: in audit RESOURCE_NAME is empty case "resource_type_invalid": defaultResource.setResourceType("invalid"); expectedResourceAuditJavaObject.setResourceType(ComponentTypeEnum.RESOURCE.getValue()); - errorInfo = ErrorValidationUtils.parseErrorConfigYaml(ActionStatus.INVALID_CONTENT.name()); + errorInfo = ErrorValidationUtils.parseErrorConfigYaml(ActionStatus.INVALID_RESOURCE_TYPE.name()); variables = asList(ComponentTypeEnum.RESOURCE.getValue()); break; case "category_type_missing": @@ -377,7 +377,7 @@ public class VFCMTExternalAPI extends ComponentBaseTest { // create vfcmt RestResponse restResponse = ResourceRestUtilsExternalAPI.createResource(defaultResource, defaultUser); - expectedResourceAuditJavaObject.setStatus("400"); + expectedResourceAuditJavaObject.setStatus(errorInfo.getCode().toString()); expectedResourceAuditJavaObject.setDesc(AuditValidationUtils.buildAuditDescription(errorInfo, variables)); AuditValidationUtils.validateAuditExternalCreateResource(expectedResourceAuditJavaObject, action.getName(), body); diff --git a/test-apis-ci/src/main/resources/ci/conf/attsdc.yaml b/test-apis-ci/src/main/resources/ci/conf/attsdc.yaml index 7273344672..10402eb2b0 100644 --- a/test-apis-ci/src/main/resources/ci/conf/attsdc.yaml +++ b/test-apis-ci/src/main/resources/ci/conf/attsdc.yaml @@ -1,6 +1,6 @@ outputFolder: target reportName: index.html -catalogBeHost: behost +catalogBeHost: localhost catalogFeHost: fehost esHost: eshost disributionClientHost: disClient diff --git a/test-apis-ci/src/test/resources/CI/error-configuration.yaml b/test-apis-ci/src/test/resources/CI/error-configuration.yaml index ef7a885678..899a225152 100644 --- a/test-apis-ci/src/test/resources/CI/error-configuration.yaml +++ b/test-apis-ci/src/test/resources/CI/error-configuration.yaml @@ -1776,3 +1776,9 @@ errors: message: "Creation of %1 failed. Generic type %2 was not found", messageId: "SVC4660" } + #---------SVC4669----------------------------- + INVALID_RESOURCE_TYPE: { + code: 400, + message: "Error: Invalid resource type.", + messageId: "SVC4669" + } \ No newline at end of file diff --git a/ui-ci/src/main/java/org/openecomp/sdc/ci/tests/US/MIBsArtifactsOnResourceInstance.java b/ui-ci/src/main/java/org/openecomp/sdc/ci/tests/US/MIBsArtifactsOnResourceInstance.java index 949a20b4a9..4e4192fe7e 100644 --- a/ui-ci/src/main/java/org/openecomp/sdc/ci/tests/US/MIBsArtifactsOnResourceInstance.java +++ b/ui-ci/src/main/java/org/openecomp/sdc/ci/tests/US/MIBsArtifactsOnResourceInstance.java @@ -78,10 +78,6 @@ public class MIBsArtifactsOnResourceInstance extends SetupCDTest { setLog("mibsArtifactCRUDUi"); String filePath = FileHandling.getFilePath(folder); - if(true){ - throw new SkipException("Open bug 197101"); - } - // import Resource ResourceReqDetails resourceMetaData = ElementFactory.getDefaultResourceByType(resourceTypeEnum, getUser()); ResourceUIUtils.importVfc(resourceMetaData, filePath, fileName, getUser()); diff --git a/ui-ci/src/main/java/org/openecomp/sdc/ci/tests/datatypes/DataTestIdEnum.java b/ui-ci/src/main/java/org/openecomp/sdc/ci/tests/datatypes/DataTestIdEnum.java index ef510b8a12..5bbc8ad9e0 100644 --- a/ui-ci/src/main/java/org/openecomp/sdc/ci/tests/datatypes/DataTestIdEnum.java +++ b/ui-ci/src/main/java/org/openecomp/sdc/ci/tests/datatypes/DataTestIdEnum.java @@ -433,19 +433,19 @@ public final class DataTestIdEnum { } public enum StepsEnum { - GENERAL("Generalstep"), + GENERAL("General"), ICON("Iconstep"), - DEPLOYMENT_ARTIFACT("Deployment Artifactstep"), - INFORMATION_ARTIFACT("Information Artifactstep"), - PROPERTIES("Propertiesstep"), - COMPOSITION("Compositionstep"), - ACTIVITY_LOG("Activity Logstep"), - DEPLOYMENT_VIEW("Deploymentstep"), - TOSCA_ARTIFACTS("TOSCA Artifactsstep"), + DEPLOYMENT_ARTIFACT("Deployment Artifact"), + INFORMATION_ARTIFACT("Information Artifact"), + PROPERTIES("Properties"), + COMPOSITION("Composition"), + ACTIVITY_LOG("Activity Log"), + DEPLOYMENT_VIEW("Deployment"), + TOSCA_ARTIFACTS("TOSCA Artifacts"), MONITOR("Monitor step"), - MANAGEMENT_WORKFLOW("Management Workflowstep"), - INPUTS("Inputsstep"), - HIERARCHY("Hierarchystep"); + MANAGEMENT_WORKFLOW("Management Workflow"), + INPUTS("Inputs"), + HIERARCHY("Hierarchy"); private String value; diff --git a/ui-ci/src/main/java/org/openecomp/sdc/ci/tests/execute/sanity/Onboard.java b/ui-ci/src/main/java/org/openecomp/sdc/ci/tests/execute/sanity/Onboard.java index fddb97ace3..76723bba11 100644 --- a/ui-ci/src/main/java/org/openecomp/sdc/ci/tests/execute/sanity/Onboard.java +++ b/ui-ci/src/main/java/org/openecomp/sdc/ci/tests/execute/sanity/Onboard.java @@ -27,9 +27,11 @@ import java.awt.AWTException; import java.io.File; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Random; import java.util.stream.Collectors; import org.openecomp.sdc.ci.tests.datatypes.CanvasElement; @@ -94,6 +96,36 @@ public class Onboard extends SetupCDTest { return provideData(fileNamesFromFolder, filepath); } + + @DataProvider(name = "randomVNF_List", parallel = false) + private static final Object[][] randomVnfList() throws Exception { + int randomElementNumber = 3; //how many VNFs to onboard randomly + String filepath = getFilePath(); + Object[] fileNamesFromFolder = FileHandling.getZipFileNamesFromFolder(filepath); + Object[] newRandomFileNamesFromFolder = getRandomElements(randomElementNumber, fileNamesFromFolder); + System.out.println(String.format("There are %s zip file(s) to test", newRandomFileNamesFromFolder.length)); + return provideData(newRandomFileNamesFromFolder, filepath); + } + + + private static Object[] getRandomElements(int randomElementNumber, Object[] fileNamesFromFolder) { + if(fileNamesFromFolder.length == 0 || fileNamesFromFolder.length < randomElementNumber){ + return null; + }else{ + List indexList = new ArrayList<>(); + Object[] newRandomFileNamesFromFolder = new Object[randomElementNumber]; + for(int i = 0; i < fileNamesFromFolder.length; i++){ + indexList.add(i); + } + Collections.shuffle(indexList); + Integer[] randomArray = indexList.subList(0, randomElementNumber).toArray(new Integer[randomElementNumber]); + for(int i = 0; i < randomArray.length; i++){ + newRandomFileNamesFromFolder[i] = fileNamesFromFolder[randomArray[i]]; + } + return newRandomFileNamesFromFolder; + } + } + public static String getFilePath() { String filepath = System.getProperty("filepath"); if (filepath == null && System.getProperty("os.name").contains("Windows")) { @@ -116,6 +148,7 @@ public class Onboard extends SetupCDTest { runOnboardToDistributionFlow(filepath, vnfFile); } + public void runOnboardToDistributionFlow(String filepath, String vnfFile) throws Exception, AWTException { Pair> onboardAndValidate = OnboardingUtils.onboardAndValidate(filepath, vnfFile, getUser()); String vspName = onboardAndValidate.left; @@ -193,6 +226,14 @@ public class Onboard extends SetupCDTest { runOnboardToDistributionFlow(filepath, vnfFile); } + @Test(dataProvider = "randomVNF_List") + public void onboardRandomVNFsTest(String filepath, String vnfFile) throws Exception, Throwable { + setLog(vnfFile); + System.out.println("printttttttttttttt - >" + makeDistributionValue); + System.out.println("vnf File name is: " + vnfFile); + runOnboardToDistributionFlow(filepath, vnfFile); + } + @Test public void onboardUpdateVNFTest() throws Exception, Throwable { diff --git a/ui-ci/src/main/java/org/openecomp/sdc/ci/tests/execute/sanity/OnboardViaApis.java b/ui-ci/src/main/java/org/openecomp/sdc/ci/tests/execute/sanity/OnboardViaApis.java index cb647aec6d..0dc6740c30 100644 --- a/ui-ci/src/main/java/org/openecomp/sdc/ci/tests/execute/sanity/OnboardViaApis.java +++ b/ui-ci/src/main/java/org/openecomp/sdc/ci/tests/execute/sanity/OnboardViaApis.java @@ -25,6 +25,7 @@ import static org.testng.AssertJUnit.assertEquals; import java.awt.AWTException; import java.io.File; import java.io.FileOutputStream; +import java.io.IOException; import java.nio.charset.StandardCharsets; import java.sql.Timestamp; import java.util.ArrayList; @@ -40,6 +41,7 @@ import org.openecomp.sdc.be.model.Resource; import org.openecomp.sdc.be.model.Service; import org.openecomp.sdc.be.model.User; import org.openecomp.sdc.ci.tests.datatypes.ResourceReqDetails; +import org.openecomp.sdc.ci.tests.datatypes.ServiceDistributionStatus; import org.openecomp.sdc.ci.tests.datatypes.enums.LifeCycleStatesEnum; import org.openecomp.sdc.ci.tests.datatypes.enums.UserRoleEnum; import org.openecomp.sdc.ci.tests.datatypes.http.RestResponse; @@ -49,6 +51,8 @@ import org.openecomp.sdc.ci.tests.utils.general.AtomicOperationUtils; import org.openecomp.sdc.ci.tests.utils.general.ElementFactory; import org.openecomp.sdc.ci.tests.utils.rest.ResourceRestUtils; import org.openecomp.sdc.ci.tests.utils.rest.ResponseParser; +import org.openecomp.sdc.tosca.parser.exceptions.SdcToscaParserException; +import org.openecomp.sdc.toscaparser.api.common.JToscaException; import org.slf4j.LoggerFactory; import org.testng.annotations.BeforeMethod; import org.testng.annotations.DataProvider; @@ -125,6 +129,34 @@ public class OnboardViaApis{ } + + @Test + public void onboardingAndParser() throws Exception { + Service service = null; + String filepath = getFilePath(); + Object[] fileNamesFromFolder = FileHandling.getZipFileNamesFromFolder(filepath); + String vnfFile = fileNamesFromFolder[7].toString(); + System.err.println(timestamp + " Starting test with VNF: " + vnfFile); + service = runOnboardViaApisOnly(filepath, vnfFile); + +// AtomicOperationUtils.getServiceObjectByNameAndVersion(sdncModifierDetails, serviceName, serviceVersion); +// RestResponse distributeService = AtomicOperationUtils.distributeService(service, true); +// Map convertServiceDistributionStatusToObject = ResponseParser.convertServiceDistributionStatusToObject(distributeService.getResponse()); +// convertServiceDistributionStatusToObject. + } + + public static String getFilePath() { + String filepath = System.getProperty("filepath"); + if (filepath == null && System.getProperty("os.name").contains("Windows")) { + filepath = FileHandling.getResourcesFilesPath() +"VNFs"; + } + + else if(filepath.isEmpty() && !System.getProperty("os.name").contains("Windows")){ + filepath = FileHandling.getBasePath() + File.separator + "Files" + File.separator +"VNFs"; + } + return filepath; + } + public static void downloadToscaCsarToDirectory(Service service, File file) { try { Either serviceToscaArtifactPayload = AtomicOperationUtils.getServiceToscaArtifactPayload(service, "assettoscacsar"); diff --git a/ui-ci/src/main/java/org/openecomp/sdc/ci/tests/execute/sanity/Service.java b/ui-ci/src/main/java/org/openecomp/sdc/ci/tests/execute/sanity/Service.java index d5920a22ca..3a42d22d0e 100644 --- a/ui-ci/src/main/java/org/openecomp/sdc/ci/tests/execute/sanity/Service.java +++ b/ui-ci/src/main/java/org/openecomp/sdc/ci/tests/execute/sanity/Service.java @@ -387,10 +387,6 @@ public class Service extends SetupCDTest { @Test public void deleteDeploymentArtifactFromVFInstanceTest() throws Exception{ - if(true){ - throw new SkipException("Open bug 300513"); - } - ResourceReqDetails atomicResourceMetaData = ElementFactory.getDefaultResourceByTypeNormTypeAndCatregory(ResourceTypeEnum.VF, NormativeTypesEnum.ROOT, ResourceCategoryEnum.NETWORK_L2_3_ROUTERS, getUser()); ServiceReqDetails serviceMetadata = ElementFactory.getDefaultService(); ArtifactInfo artifact = new ArtifactInfo(filePath, HEAT_FILE_YAML_NAME, DESCRIPTION, ARTIFACT_LABEL,ArtifactTypeEnum.SNMP_POLL.getType()); @@ -405,10 +401,6 @@ public class Service extends SetupCDTest { @Test public void deleteDeploymentArtifactFromVFInstanceNextVersionTest() throws Exception{ - if(true){ - throw new SkipException("Open bug 300513"); - } - ResourceReqDetails atomicResourceMetaData = ElementFactory.getDefaultResourceByTypeNormTypeAndCatregory(ResourceTypeEnum.VF, NormativeTypesEnum.ROOT, ResourceCategoryEnum.NETWORK_L2_3_ROUTERS, getUser()); ServiceReqDetails serviceMetadata = ElementFactory.getDefaultService(); ArtifactInfo artifact = new ArtifactInfo(filePath, HEAT_FILE_YAML_NAME, DESCRIPTION, ARTIFACT_LABEL,ArtifactTypeEnum.SNMP_POLL.getType()); @@ -434,10 +426,6 @@ public class Service extends SetupCDTest { @Test public void updateDeploymentArtifactOnVFInstanceNextVersionTest() throws Exception{ - if(true){ - throw new SkipException("Open bug 300513"); - } - ResourceReqDetails atomicResourceMetaData = ElementFactory.getDefaultResourceByTypeNormTypeAndCatregory(ResourceTypeEnum.VF, NormativeTypesEnum.ROOT, ResourceCategoryEnum.NETWORK_L2_3_ROUTERS, getUser()); ServiceReqDetails serviceMetadata = ElementFactory.getDefaultService(); ArtifactInfo artifact = new ArtifactInfo(filePath, HEAT_FILE_YAML_NAME, DESCRIPTION, ARTIFACT_LABEL,ArtifactTypeEnum.SNMP_POLL.getType()); diff --git a/ui-ci/src/main/java/org/openecomp/sdc/ci/tests/execute/sanity/Vf.java b/ui-ci/src/main/java/org/openecomp/sdc/ci/tests/execute/sanity/Vf.java index a94a63500d..ef7a534ee9 100644 --- a/ui-ci/src/main/java/org/openecomp/sdc/ci/tests/execute/sanity/Vf.java +++ b/ui-ci/src/main/java/org/openecomp/sdc/ci/tests/execute/sanity/Vf.java @@ -231,10 +231,6 @@ public class Vf extends SetupCDTest { @Test public void addPropertiesToVfcInstanceInVfTest() throws Exception { - if(true){ - throw new SkipException("Open bug 292047"); - } - String fileName = "vFW_VFC.yml"; ResourceReqDetails atomicResourceMetaData = ElementFactory.getDefaultResourceByTypeNormTypeAndCatregory(ResourceTypeEnum.VFC, NormativeTypesEnum.ROOT, ResourceCategoryEnum.NETWORK_L2_3_ROUTERS, getUser()); diff --git a/ui-ci/src/main/java/org/openecomp/sdc/ci/tests/utilities/OnboardingUtils.java b/ui-ci/src/main/java/org/openecomp/sdc/ci/tests/utilities/OnboardingUtils.java index 621cc26a12..ae05e77aff 100644 --- a/ui-ci/src/main/java/org/openecomp/sdc/ci/tests/utilities/OnboardingUtils.java +++ b/ui-ci/src/main/java/org/openecomp/sdc/ci/tests/utilities/OnboardingUtils.java @@ -506,6 +506,7 @@ public class OnboardingUtils { jObject.put("description", "new VSP description"); jObject.put("category", "resourceNewCategory.generic"); jObject.put("subCategory", "resourceNewCategory.generic.database"); + jObject.put("onboardingMethod", "HEAT"); jObject.put("licensingVersion", jlicensingVersionObj); jObject.put("vendorName", vendorName); jObject.put("vendorId", vendorId); @@ -669,7 +670,7 @@ public class OnboardingUtils { boolean vspFound = HomePage.searchForVSP(vspName); if (vspFound){ - + List elemenetsFromTable = HomePage.getElemenetsFromTable(); // WebDriverWait wait = new WebDriverWait(GeneralUIUtils.getDriver(), 30); // WebElement findElement = wait.until(ExpectedConditions.visibilityOf(elemenetsFromTable.get(1))); @@ -767,24 +768,36 @@ public class OnboardingUtils { LinkedList deploymentArtifacts = ((LinkedList) combinedMap.get("Deployment")); ArtifactsCorrelationManager.addVNFartifactDetails(vspName, deploymentArtifacts); - validateDeploymentArtifactsVersion(deploymentArtifacts); + List heatEnvFilesFromCSAR = deploymentArtifacts.stream().filter(e -> e.getType().equals("HEAT_ENV")). + map(e -> e.getFileName()). + collect(Collectors.toList()); + + validateDeploymentArtifactsVersion(deploymentArtifacts, heatEnvFilesFromCSAR); + DeploymentArtifactPage.verifyArtifactsExistInTable(filepath, vnfFile); return createVendorSoftwareProduct; } - public static void validateDeploymentArtifactsVersion(LinkedList deploymentArtifacts) { - String artifactVersion = "1"; + public static void validateDeploymentArtifactsVersion(LinkedList deploymentArtifacts, + List heatEnvFilesFromCSAR) { + String artifactVersion; String artifactName; - + for(HeatMetaFirstLevelDefinition deploymentArtifact: deploymentArtifacts) { + artifactVersion = "1"; + if(deploymentArtifact.getType().equals("HEAT_ENV")) { continue; } else if(deploymentArtifact.getFileName().contains(".")) { - artifactName = deploymentArtifact.getFileName().trim().substring(0, deploymentArtifact.getFileName().lastIndexOf(".")); + artifactName = deploymentArtifact.getFileName().trim().substring(0, deploymentArtifact.getFileName().lastIndexOf(".")); } else { - artifactName = deploymentArtifact.getFileName().trim(); + artifactName = deploymentArtifact.getFileName().trim(); + } + + if (heatEnvFilesFromCSAR.contains(artifactName + ".env")){ + artifactVersion = "2"; } - ArtifactUIUtils.validateArtifactNameVersionType(artifactName, artifactVersion, deploymentArtifact.getType()); + ArtifactUIUtils.validateArtifactNameVersionType(artifactName, artifactVersion, deploymentArtifact.getType()); } } -- 2.16.6