summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.vscode/settings.json8
-rw-r--r--cds-ui/designer-client/angular.json24
-rw-r--r--cds-ui/designer-client/package.json10
-rw-r--r--cds-ui/designer-client/proxy.conf.json6
-rw-r--r--cds-ui/designer-client/src/app/common/constants/app-constants.ts4
-rw-r--r--cds-ui/designer-client/src/app/common/core/services/api.typed.service.ts10
-rw-r--r--cds-ui/designer-client/src/app/common/core/stores/Store.ts6
-rw-r--r--cds-ui/designer-client/src/app/modules/feature-modules/packages/configuration-dashboard/configuration-dashboard.component.html136
-rw-r--r--cds-ui/designer-client/src/app/modules/feature-modules/packages/configuration-dashboard/configuration-dashboard.component.ts202
-rw-r--r--cds-ui/designer-client/src/app/modules/feature-modules/packages/configuration-dashboard/configuration-dashboard.service.ts15
-rw-r--r--cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/designer.component.css37
-rw-r--r--cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/designer.component.html40
-rw-r--r--cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/designer.component.ts335
-rw-r--r--cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/designer.service.ts2
-rw-r--r--cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/designer.store.ts119
-rw-r--r--cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/functions.store.ts (renamed from cds-ui/designer-client/src/app/modules/feature-modules/packages/configuration-dashboard/package.store.ts)32
-rw-r--r--cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/functions/functions.component.css0
-rw-r--r--cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/functions/functions.component.html21
-rw-r--r--cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/functions/functions.component.spec.ts25
-rw-r--r--cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/functions/functions.component.ts28
-rw-r--r--cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/graph.generator.util.ts113
-rw-r--r--cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/graph.util.ts228
-rw-r--r--cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/jointjs/elements/action.element.ts3
-rw-r--r--cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/model/ModelType.model.ts (renamed from cds-ui/designer-client/src/app/modules/feature-modules/packages/model/ModelType.model.ts)0
-rw-r--r--cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/model/designer.dashboard.state.ts33
-rw-r--r--cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/model/designer.topologyTemplate.model.ts13
-rw-r--r--cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/model/designer.workflow.ts14
-rw-r--r--cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/model/desinger.nodeTemplate.model.ts15
-rw-r--r--cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/model/functions.state.ts (renamed from cds-ui/designer-client/src/app/modules/feature-modules/packages/model/designer-dashboard.state.ts)8
-rw-r--r--cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/source-view/source-view.component.css580
-rw-r--r--cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/source-view/source-view.component.html80
-rw-r--r--cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/source-view/source-view.component.ts45
-rw-r--r--cds-ui/designer-client/src/app/modules/feature-modules/packages/model/package-dashboard.state.ts16
-rw-r--r--cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/creationModes/DesignerCreationMode.ts32
-rw-r--r--cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/creationModes/PackageCreationModes.ts14
-rw-r--r--cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/dsl-definitions-tab/dsl-definitions-tab.component.html4
-rw-r--r--cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/dsl-definitions-tab/dsl-definitions-tab.component.ts14
-rw-r--r--cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/imports-tab/imports-tab.component.html10
-rw-r--r--cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/imports-tab/imports-tab.component.ts10
-rw-r--r--cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/mapping-models/CBAPacakge.model.ts40
-rw-r--r--cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/mapping-models/ResourceDictionary.model.ts23
-rw-r--r--cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/mapping-models/definitions/VlbDefinition.ts11
-rw-r--r--cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/mapping-models/mappingAdapter.model.ts45
-rw-r--r--cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/mapping-models/metadata/MetaDataTab.model.ts7
-rw-r--r--cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/metadata-tab/metadata-tab.component.css4
-rw-r--r--cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/metadata-tab/metadata-tab.component.html120
-rw-r--r--cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/metadata-tab/metadata-tab.component.ts96
-rw-r--r--cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/package-creation.component.html126
-rw-r--r--cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/package-creation.component.ts65
-rw-r--r--cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/package-creation.service.ts6
-rw-r--r--cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/package-creation.store.ts38
-rw-r--r--cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/scripts-tab/scripts-tab.component.html13
-rw-r--r--cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/scripts-tab/scripts-tab.component.ts46
-rw-r--r--cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/TemplateAndMapping.ts7
-rw-r--r--cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/templ-mapp-creation/templ-mapp-creation.component.html159
-rw-r--r--cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/templ-mapp-creation/templ-mapp-creation.component.ts266
-rw-r--r--cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/templ-mapp-listing/templ-mapp-listing.component.css3
-rw-r--r--cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/templ-mapp-listing/templ-mapp-listing.component.html147
-rw-r--r--cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/templ-mapp-listing/templ-mapp-listing.component.ts90
-rw-r--r--cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/template-mapping.component.html12
-rw-r--r--cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/template-mapping.component.ts37
-rw-r--r--cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template.store.ts58
-rw-r--r--cds-ui/designer-client/src/app/modules/feature-modules/packages/packages-dashboard/package-list/package-list.component.html21
-rw-r--r--cds-ui/designer-client/src/app/modules/feature-modules/packages/packages.module.ts62
-rw-r--r--cds-ui/designer-client/src/app/modules/feature-modules/packages/packages.routing.module.ts2
-rw-r--r--cds-ui/designer-client/src/app/modules/shared-modules/header/header.component.html4
-rw-r--r--cds-ui/designer-client/tslint.json7
-rw-r--r--cds-ui/pom.xml2
-rw-r--r--components/model-catalog/blueprint-model/test-blueprint/baseconfiguration/Definitions/activation-blueprint.json4
-rw-r--r--components/model-catalog/blueprint-model/test-blueprint/baseconfiguration/Definitions/notemplate-mapping.json36
-rw-r--r--components/model-catalog/blueprint-model/test-blueprint/pom.xml5
-rw-r--r--components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Definitions/PNF_CDS_RESTCONF.json424
-rw-r--r--components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Definitions/artifact_types.json (renamed from components/model-catalog/blueprint-model/uat-blueprints/pnf_config_aai/Definitions/artifact_types.json)0
-rw-r--r--components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Definitions/config-assign-pnf-mapping.json (renamed from components/model-catalog/blueprint-model/uat-blueprints/pnf_config_aai/Definitions/config-assign-pnf-mapping.json)0
-rw-r--r--components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Definitions/config-deploy-pnf-mapping.json (renamed from components/model-catalog/blueprint-model/uat-blueprints/pnf_config_aai/Definitions/config-deploy-pnf-mapping.json)0
-rw-r--r--components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Definitions/data_types.json75
-rw-r--r--components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Definitions/node_types.json (renamed from components/model-catalog/blueprint-model/uat-blueprints/pnf_config_aai/Definitions/node_types.json)0
-rw-r--r--components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Definitions/pnf-software-upgrade-mapping.json36
-rw-r--r--components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Definitions/policy_types.json (renamed from components/model-catalog/blueprint-model/uat-blueprints/pnf_config_aai/Definitions/policy_types.json)0
-rw-r--r--components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Definitions/relationship_types.json (renamed from components/model-catalog/blueprint-model/uat-blueprints/pnf_config_aai/Definitions/relationship_types.json)0
-rw-r--r--components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Definitions/resources_definition_types.json (renamed from components/model-catalog/blueprint-model/uat-blueprints/pnf_config_aai/Definitions/resources_definition_types.json)0
-rw-r--r--components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Environments/source-db.properties (renamed from components/model-catalog/blueprint-model/uat-blueprints/pnf_config_aai/Environments/source-db.properties)0
-rw-r--r--components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Environments/source-rest.properties (renamed from components/model-catalog/blueprint-model/uat-blueprints/pnf_config_aai/Environments/source-rest.properties)0
-rw-r--r--components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Plans/CONFIG_configAssign.xml (renamed from components/model-catalog/blueprint-model/uat-blueprints/pnf_config_aai/Plans/CONFIG_configAssign.xml)0
-rw-r--r--components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Plans/CONFIG_configDeploy.xml (renamed from components/model-catalog/blueprint-model/uat-blueprints/pnf_config_aai/Plans/CONFIG_configDeploy.xml)0
-rw-r--r--components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Plans/CONFIG_upgradeSoftware.xml15
-rw-r--r--components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Scripts/kotlin/RestconfConfigDeploy.kt (renamed from components/model-catalog/blueprint-model/uat-blueprints/pnf_config_aai/Scripts/kotlin/RestconfConfigDeploy.kt)17
-rw-r--r--components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Scripts/kotlin/RestconfSoftwareUpgrade.kt205
-rw-r--r--components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/TOSCA-Metadata/TOSCA.meta7
-rw-r--r--components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Templates/config-assign-restconf-configlet-template.vtl (renamed from components/model-catalog/blueprint-model/uat-blueprints/pnf_config_aai/Templates/config-assign-restconf-configlet-template.vtl)0
-rw-r--r--components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Templates/pnf-swug-config-template.vtl22
-rw-r--r--components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Templates/pnf-swug-download-ne-sw-template.vtl28
-rw-r--r--components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Templates/restconf-mount-template.vtl (renamed from components/model-catalog/blueprint-model/uat-blueprints/pnf_config_aai/Templates/config-deploy-restconf-mount-template.vtl)0
-rw-r--r--components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Tests/uat.yaml374
-rw-r--r--components/model-catalog/blueprint-model/uat-blueprints/README.md3
-rw-r--r--components/model-catalog/blueprint-model/uat-blueprints/pnf_config/Tests/uat.yaml4
-rw-r--r--components/model-catalog/blueprint-model/uat-blueprints/pnf_config_aai/Definitions/data_types.json23
-rw-r--r--components/model-catalog/blueprint-model/uat-blueprints/pnf_config_aai/Definitions/pnf_config_aai.json152
-rw-r--r--components/model-catalog/blueprint-model/uat-blueprints/pnf_config_aai/TOSCA-Metadata/TOSCA.meta7
-rw-r--r--components/model-catalog/blueprint-model/uat-blueprints/pnf_config_aai/Tests/uat.yaml130
-rw-r--r--components/model-catalog/definition-type/starter-type/node_type/component-resource-resolution.json5
-rwxr-xr-xms/blueprintsprocessor/application/pom.xml23
-rw-r--r--ms/blueprintsprocessor/application/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/BlueprintDatabaseConfiguration.kt6
-rw-r--r--ms/blueprintsprocessor/application/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/BlueprintProcessorApplication.kt5
-rw-r--r--ms/blueprintsprocessor/application/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/BlueprintProcessorExceptionHandler.kt25
-rw-r--r--ms/blueprintsprocessor/application/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/logging/ColorMarker.kt (renamed from ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/logging/ColorMarker.kt)0
-rw-r--r--ms/blueprintsprocessor/application/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/logging/LogColor.kt (renamed from ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/logging/LogColor.kt)0
-rw-r--r--ms/blueprintsprocessor/application/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/logging/MockInvocationLogger.kt (renamed from ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/logging/MockInvocationLogger.kt)0
-rw-r--r--ms/blueprintsprocessor/application/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/InvalidUatDefinition.kt22
-rw-r--r--ms/blueprintsprocessor/application/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/JsonNormalizer.kt (renamed from ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/JsonNormalizer.kt)0
-rw-r--r--ms/blueprintsprocessor/application/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/PathDeserializer.kt (renamed from ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/PathDeserializer.kt)0
-rw-r--r--ms/blueprintsprocessor/application/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/RequiredMapEntriesMatcher.kt (renamed from ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/RequiredMapEntriesMatcher.kt)0
-rw-r--r--ms/blueprintsprocessor/application/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/UatDefinition.kt (renamed from ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/UatDefinition.kt)24
-rw-r--r--ms/blueprintsprocessor/application/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/UatExecutor.kt (renamed from ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/UatExecutor.kt)159
-rw-r--r--ms/blueprintsprocessor/application/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/UatServices.kt (renamed from ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/UatServices.kt)0
-rwxr-xr-xms/blueprintsprocessor/application/src/main/resources/application-dev.properties7
-rw-r--r--ms/blueprintsprocessor/application/src/main/resources/application-local.yml4
-rwxr-xr-xms/blueprintsprocessor/application/src/main/resources/application.properties8
-rw-r--r--ms/blueprintsprocessor/application/src/main/resources/error-messages_en.properties91
-rw-r--r--ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/ErrorCatalogTestConfiguration.kt28
-rw-r--r--ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/UatServicesTest.kt23
-rw-r--r--ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/error/ErrorCatalogServiceTest.kt97
-rw-r--r--ms/blueprintsprocessor/application/src/test/resources/application-test.properties6
-rw-r--r--ms/blueprintsprocessor/application/src/test/resources/application.properties5
-rw-r--r--ms/blueprintsprocessor/application/src/test/resources/error-messages_en.properties91
-rw-r--r--ms/blueprintsprocessor/functions/message-prioritizaion/pom.xml1
-rw-r--r--ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/ComponentNetconfExecutor.kt3
-rwxr-xr-xms/blueprintsprocessor/functions/pom.xml2
-rw-r--r--ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionComponent.kt4
-rw-r--r--ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionComponentDSL.kt11
-rw-r--r--ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionConstants.kt1
-rw-r--r--ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionService.kt30
-rw-r--r--ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionDBService.kt23
-rw-r--r--ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionRepository.kt9
-rw-r--r--ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/CapabilityResourceResolutionProcessor.kt2
-rw-r--r--ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/DatabaseResourceAssignmentProcessor.kt6
-rw-r--r--ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/RestResourceResolutionProcessor.kt7
-rw-r--r--ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/utils/ResourceAssignmentUtils.kt77
-rw-r--r--ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionComponentDSLTest.kt1
-rw-r--r--ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionServiceTest.kt98
-rw-r--r--ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionDBServiceTest.kt12
-rw-r--r--ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/CapabilityResourceResolutionProcessorTest.kt8
-rw-r--r--ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/utils/ResourceAssignmentUtilsTest.kt70
-rw-r--r--ms/blueprintsprocessor/functions/restconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/restconf/executor/RestconfExecutorExtensions.kt17
-rw-r--r--ms/blueprintsprocessor/functions/restful-executor/pom.xml (renamed from ms/blueprintsprocessor/functions/nrm-restful/pom.xml)12
-rw-r--r--ms/blueprintsprocessor/functions/restful-executor/src/main/kotlin/internal/scripts/TestRestfulConfigure.kt42
-rw-r--r--ms/blueprintsprocessor/functions/restful-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/restful/executor/ComponentRestfulExecutor.kt69
-rw-r--r--ms/blueprintsprocessor/functions/restful-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/restful/executor/RestfulCMComponentFunction.kt126
-rw-r--r--ms/blueprintsprocessor/functions/restful-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/restful/executor/nrmfunction/RestfulNRMServiceClient.kt (renamed from ms/blueprintsprocessor/functions/nrm-restful/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/nrm/restful/RestfulNRMServiceClient.kt)2
-rw-r--r--ms/blueprintsprocessor/functions/restful-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/restful/executor/ComponentRestfulExecutorTest.kt105
-rw-r--r--ms/blueprintsprocessor/functions/restful-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/restful/executor/nrmfunction/RestfulNRMServiceClientTest.kt (renamed from ms/blueprintsprocessor/functions/nrm-restful/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/nrm/restful/RestfulNRMServiceClientTest.kt)2
-rw-r--r--ms/blueprintsprocessor/modules/blueprints/blueprint-core/pom.xml10
-rw-r--r--ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/BluePrintConstants.kt5
-rw-r--r--ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/BluePrintException.kt27
-rw-r--r--ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/BluePrintProcessorException.kt110
-rw-r--r--ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/interfaces/BluePrintScriptsService.kt2
-rw-r--r--ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/scripts/BluePrintCompileService.kt13
-rw-r--r--ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/scripts/BluePrintScriptsServiceImpl.kt7
-rw-r--r--ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/service/BluePrintTemplateService.kt8
-rwxr-xr-xms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/utils/BluePrintArchiveUtils.kt186
-rw-r--r--ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/utils/JacksonUtils.kt8
-rw-r--r--ms/blueprintsprocessor/modules/blueprints/blueprint-proto/pom.xml4
-rw-r--r--ms/blueprintsprocessor/modules/blueprints/pom.xml1
-rw-r--r--ms/blueprintsprocessor/modules/blueprints/resource-dict/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/resource/dict/ResourceDefinition.kt31
-rw-r--r--ms/blueprintsprocessor/modules/commons/nats-lib/pom.xml1
-rw-r--r--ms/blueprintsprocessor/modules/commons/processor-core/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/cluster/HazlecastClusterService.kt7
-rw-r--r--ms/blueprintsprocessor/modules/commons/processor-core/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/cluster/HazlecastClusterServiceTest.kt4
-rw-r--r--ms/blueprintsprocessor/modules/commons/processor-core/src/test/resources/hazelcast/hazelcast-5679.yaml21
-rw-r--r--ms/blueprintsprocessor/modules/commons/processor-core/src/test/resources/hazelcast/hazelcast-5680.yaml21
-rw-r--r--ms/blueprintsprocessor/modules/commons/processor-core/src/test/resources/hazelcast/hazelcast-5681.yaml21
-rw-r--r--ms/blueprintsprocessor/modules/commons/processor-core/src/test/resources/hazelcast/hazelcast-5682.yaml9
-rw-r--r--ms/blueprintsprocessor/modules/commons/processor-core/src/test/resources/hazelcast/hazelcast-cluster.yaml23
-rw-r--r--ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/service/BasicAuthRestClientService.kt4
-rw-r--r--ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/BlueprintModelController.kt39
-rw-r--r--ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/DesignerApiData.kt32
-rw-r--r--ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/ErrorHandling.kt40
-rw-r--r--ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/handler/BluePrintModelHandler.kt69
-rw-r--r--ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/ErrorHandling.kt36
-rw-r--r--ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/ResourceController.kt22
-rw-r--r--ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/ErrorHandling.kt44
-rw-r--r--ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/ExecutionServiceController.kt6
-rw-r--r--ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/ComponentFunctionScriptingService.kt6
-rw-r--r--ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/ComponentScriptExecutor.kt2
-rw-r--r--ms/blueprintsprocessor/modules/services/workflow-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/workflow/BlueprintSvcLogicService.kt4
-rwxr-xr-xms/blueprintsprocessor/parent/pom.xml108
-rwxr-xr-xms/error-catalog/README.md40
-rw-r--r--ms/error-catalog/application/pom.xml30
-rw-r--r--ms/error-catalog/core/pom.xml30
-rw-r--r--ms/error-catalog/core/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/core/ErrorCatalogException.kt112
-rw-r--r--ms/error-catalog/core/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/core/ErrorCatalogExtensions.kt32
-rw-r--r--ms/error-catalog/core/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/core/ErrorCodes.kt88
-rw-r--r--ms/error-catalog/core/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/core/ErrorLibData.kt94
-rw-r--r--ms/error-catalog/core/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/core/ErrorMessageLibConstants.kt31
-rw-r--r--ms/error-catalog/pom.xml157
-rw-r--r--ms/error-catalog/services/pom.xml37
-rw-r--r--ms/error-catalog/services/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/services/ErrorCatalogConfiguration.kt34
-rw-r--r--ms/error-catalog/services/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/services/ErrorCatalogDBService.kt98
-rw-r--r--ms/error-catalog/services/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/services/ErrorCatalogExceptionHandler.kt31
-rw-r--r--ms/error-catalog/services/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/services/ErrorCatalogLoadService.kt147
-rw-r--r--ms/error-catalog/services/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/services/ErrorCatalogService.kt91
-rw-r--r--ms/error-catalog/services/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/services/ErrorCatalogServiceExtensions.kt25
-rwxr-xr-xms/error-catalog/services/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/services/domain/Domain.kt76
-rw-r--r--ms/error-catalog/services/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/services/domain/ErrorMessageModel.kt69
-rw-r--r--ms/error-catalog/services/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/services/repository/DomainRepository.kt45
-rw-r--r--ms/error-catalog/services/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/services/repository/ErrorMessageModelRepository.kt36
-rw-r--r--ms/error-catalog/services/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/services/utils/ErrorCatalogUtils.kt39
-rw-r--r--ms/pom.xml20
-rw-r--r--ms/py-executor/pom.xml1
-rw-r--r--ms/py-executor/resource_resolution/README63
-rw-r--r--ms/py-executor/resource_resolution/authorization.py64
-rw-r--r--ms/py-executor/resource_resolution/client.py31
-rw-r--r--ms/py-executor/resource_resolution/resource_resolution.py294
-rw-r--r--ms/py-executor/resource_resolution/tests/authorization_interceptor_test.py50
-rw-r--r--ms/py-executor/resource_resolution/tests/resource_resolution_test.py105
-rw-r--r--ms/sdclistener/application/pom.xml6
-rw-r--r--ms/sdclistener/application/src/main/resources/application.yaml2
-rw-r--r--ms/sdclistener/application/src/test/java/org/onap/ccsdk/cds/sdclistener/SdcListenerConfigurationTest.java2
-rwxr-xr-xms/sdclistener/parent/pom.xml2
-rw-r--r--pom.xml8
219 files changed, 8082 insertions, 1584 deletions
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 000000000..2421e386c
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,8 @@
+{
+ "files.exclude": {
+ "**/.classpath": true,
+ "**/.project": true,
+ "**/.settings": true,
+ "**/.factorypath": true
+ }
+} \ No newline at end of file
diff --git a/cds-ui/designer-client/angular.json b/cds-ui/designer-client/angular.json
index 6219bf68a..a84b95e39 100644
--- a/cds-ui/designer-client/angular.json
+++ b/cds-ui/designer-client/angular.json
@@ -25,21 +25,23 @@
],
"styles": [
"src/styles.css",
+ "./node_modules/datatables.net-dt/css/jquery.dataTables.css",
"./node_modules/bootstrap/dist/css/bootstrap.min.css",
"./node_modules/@angular/material/prebuilt-themes/purple-green.css",
"./node_modules/font-awesome/css/font-awesome.css",
"./node_modules/jointjs/css/layout.css",
"./node_modules/jointjs/css/themes/material.css",
"./node_modules/jointjs/css/themes/default.css"
-
],
"scripts": [
+ "./node_modules/jquery/dist/jquery.js",
+ "./node_modules/datatables.net/js/jquery.dataTables.js",
+ "./node_modules/bootstrap/dist/js/bootstrap.js",
"./node_modules/ace-builds/src-min/ace.js",
"./node_modules/ace-builds/src-min/theme-eclipse.js",
"./node_modules/ace-builds/src-min/theme-tomorrow_night_bright.js",
"./node_modules/ace-builds/src-min/mode-json.js",
"./node_modules/ace-builds/src-min/mode-javascript.js",
- "./node_modules/ace-builds/src-min/mode-python.js",
"./node_modules/ace-builds/src-min/mode-xml.js",
"./node_modules/ace-builds/src-min/mode-kotlin.js",
"./node_modules/ace-builds/src-min/mode-text.js",
@@ -52,7 +54,6 @@
"./node_modules/ace-builds/src-min/ext-language_tools.js",
"./node_modules/ace-builds/src-min/worker-json.js",
"./node_modules/ace-builds/src-min/worker-javascript.js",
- "./node_modules/jquery/dist/jquery.js",
"./node_modules/lodash/index.js",
"./node_modules/backbone/backbone.js",
"./node_modules/jointjs/dist/joint.js"
@@ -60,12 +61,10 @@
},
"configurations": {
"production": {
- "fileReplacements": [
- {
- "replace": "src/environments/environment.ts",
- "with": "src/environments/environment.prod.ts"
- }
- ],
+ "fileReplacements": [{
+ "replace": "src/environments/environment.ts",
+ "with": "src/environments/environment.prod.ts"
+ }],
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
@@ -75,8 +74,7 @@
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
- "budgets": [
- {
+ "budgets": [{
"type": "initial",
"maximumWarning": "2mb",
"maximumError": "5mb"
@@ -126,7 +124,7 @@
],
"scripts": [
-
+
]
}
},
@@ -159,4 +157,4 @@
}
},
"defaultProject": "designer-client"
-}
+} \ No newline at end of file
diff --git a/cds-ui/designer-client/package.json b/cds-ui/designer-client/package.json
index 22defe502..89e107fec 100644
--- a/cds-ui/designer-client/package.json
+++ b/cds-ui/designer-client/package.json
@@ -24,14 +24,19 @@
"@angular/router": "~8.2.9",
"@ng-bootstrap/ng-bootstrap": "^5.1.1",
"angular-animations": "0.0.10",
+ "angular-datatables": "^8.0.0",
"angular-font-awesome": "^3.1.2",
"angular-material-expansion-panel": "^0.7.2",
"backbone": "^1.4.0",
"bootstrap": "^4.3.1",
+ "dagre": "^0.8.5",
+ "datatables.net": "^1.10.20",
+ "datatables.net-dt": "^1.10.20",
"file-saver": "^2.0.2",
"font-awesome": "^4.7.0",
+ "graphlib": "^2.1.8",
"jointjs": "^3.0.4",
- "jquery": "^3.1.1",
+ "jquery": "^3.4.1",
"json2typescript": "^1.2.3",
"lodash": "^4.17.15",
"ng-sidebar": "^9.1.1",
@@ -48,10 +53,11 @@
"@angular/compiler-cli": "~8.2.9",
"@angular/language-service": "~8.2.9",
"@types/backbone": "^1.4.1",
+ "@types/datatables.net": "^1.10.18",
"@types/jasmine": "~3.3.8",
"@types/jasminewd2": "~2.0.3",
"@types/jointjs": "^2.0.0",
- "@types/jquery": "^3.3.31",
+ "@types/jquery": "^3.3.33",
"@types/lodash": "^3.10.1",
"@types/node": "~8.9.4",
"codelyzer": "^5.0.0",
diff --git a/cds-ui/designer-client/proxy.conf.json b/cds-ui/designer-client/proxy.conf.json
index 11ed26767..6b81a884a 100644
--- a/cds-ui/designer-client/proxy.conf.json
+++ b/cds-ui/designer-client/proxy.conf.json
@@ -4,5 +4,11 @@
"secure": false,
"logLevel": "debug",
"changeOrigin": true
+ },
+ "/resourcedictionary/*": {
+ "target": "https://localhost:3000",
+ "secure": false,
+ "logLevel": "debug",
+ "changeOrigin": true
}
}
diff --git a/cds-ui/designer-client/src/app/common/constants/app-constants.ts b/cds-ui/designer-client/src/app/common/constants/app-constants.ts
index 387c35342..14cb001c8 100644
--- a/cds-ui/designer-client/src/app/common/constants/app-constants.ts
+++ b/cds-ui/designer-client/src/app/common/constants/app-constants.ts
@@ -106,6 +106,7 @@ export const ResourceDictionaryURLs = {
saveResourceDictionary: '/resourcedictionary/save',
searchResourceDictionaryByTags: '/resourcedictionary/search',
searchResourceDictionaryByName: '',
+ searchResourceDictionaryByNames: '/resourcedictionary/search/by-names',
getSources: '/resourcedictionary/source-mapping',
getModelType: '/resourcedictionary/model-type',
getResourceDictionary: '/resourcedictionary/model-type/by-definition'
@@ -117,3 +118,6 @@ export const ControllerCatalogURLs = {
getDefinition: '/controllercatalog/model-type/by-definition',
getDerivedFrom: '/controllercatalog/model-type/by-derivedfrom'
};
+
+
+export const ActionElementTypeName = 'app.ActionElement';
diff --git a/cds-ui/designer-client/src/app/common/core/services/api.typed.service.ts b/cds-ui/designer-client/src/app/common/core/services/api.typed.service.ts
index 9c9477f33..d4851ded5 100644
--- a/cds-ui/designer-client/src/app/common/core/services/api.typed.service.ts
+++ b/cds-ui/designer-client/src/app/common/core/services/api.typed.service.ts
@@ -22,9 +22,9 @@ limitations under the License.
============LICENSE_END============================================
*/
-import { Injectable } from '@angular/core';
-import { HttpClient, HttpHeaders, HttpResponse, HttpHeaderResponse, HttpParams } from '@angular/common/http';
-import { Observable, of } from 'rxjs';
+import {Injectable} from '@angular/core';
+import {HttpClient, HttpParams} from '@angular/common/http';
+import {Observable} from 'rxjs';
@Injectable()
export class ApiService<T> {
@@ -60,4 +60,8 @@ export class ApiService<T> {
const options = {params: httpParams};
return this.httpClient.get<T>(url, options);
}
+
+ getCustomized(url: string, params?: any): Observable<any> {
+ return this.httpClient.get(url, params);
+ }
}
diff --git a/cds-ui/designer-client/src/app/common/core/stores/Store.ts b/cds-ui/designer-client/src/app/common/core/stores/Store.ts
index 1d5b0afc1..0be804270 100644
--- a/cds-ui/designer-client/src/app/common/core/stores/Store.ts
+++ b/cds-ui/designer-client/src/app/common/core/stores/Store.ts
@@ -1,4 +1,4 @@
-import {Observable, BehaviorSubject} from 'rxjs';
+import { Observable, BehaviorSubject } from 'rxjs';
import { Injectable } from '@angular/core';
export class Store<T> {
@@ -19,4 +19,8 @@ export class Store<T> {
this.subject.next(nextState);
}
+ public unsubscribe() {
+ this.subject.unsubscribe();
+ }
+
}
diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/configuration-dashboard/configuration-dashboard.component.html b/cds-ui/designer-client/src/app/modules/feature-modules/packages/configuration-dashboard/configuration-dashboard.component.html
index 804aad057..df1911a7d 100644
--- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/configuration-dashboard/configuration-dashboard.component.html
+++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/configuration-dashboard/configuration-dashboard.component.html
@@ -1,7 +1,133 @@
-<app-header>
-</app-header>
-<p>package-viewing works!
+<app-header></app-header>
+<div class="new-wrapper">
+ <div class="container-fluid main-container">
+ <header class="page-title">
+ <div class="row">
+ <h2 class="col m-0">
+ <ul class="breadcrumb-header">
+ <li><a routerLink="/packages">CBA Packages</a></li>
+ <li>Package Name</li>
+ </ul>
+ </h2>
+ <div class="col d-flex justify-content-end header-button-save">
+ <button class="float btn btn-sm btn-outline-secondary" (click)="goBacktoDashboard()">Discard
+ Changes</button>
+ <button class="float btn btn-sm btn-primary" (click)="editBluePrint()">Apply Changes</button>
+ </div>
+ </div>
+ </header>
- {{viewedPackage!.artifactName}}}
-</p>
+
+
+ <div class="container-fluid body-container">
+
+ <div class="container">
+ <!-- <div class="creat-action-container">
+ <a href="#" class="action-button">
+ <i class="icon-clone" aria-hidden="true"></i>
+ <span>Clone</span>
+ </a>
+
+ <a href="#" class="action-button">
+ <i class="icon-archive" aria-hidden="true"></i>
+ <span>Archive</span>
+ </a>
+
+ <a href="#" class="action-button delete">
+ <i class="icon-delete" aria-hidden="true"></i>
+ <span>Delete</span>
+ </a>
+ </div>-->
+
+ <div class="card creat-card view-package-container">
+ <div class="row">
+ <div class="col-8">
+ <div class="row">
+ <div class="col d-flex">
+ <i class="package-type-icon icon-designer-mode"></i>
+ <div class="package-name-container">
+ <div class="row">
+ <div class="col-12 package-name deployed">
+ {{viewedPackage.artifactName}}
+ <span>.vLB.CDS</span>
+ <i class="icon-deploy"></i>
+ </div>
+ <div class="col-12 package-description">
+ Last modified {{ viewedPackage.createdDate | date:'short' }} By
+ {{viewedPackage.updatedBy}}
+ </div>
+ </div>
+
+ </div>
+ </div>
+ </div>
+ </div>
+ <div class="col-4 package-view-button">
+ <button class="btn btn-sm btn-outline-secondary" (click)="deployCurrentPackage()"><i
+ class="fa fa-play-circle"></i> Deploy</button>
+ <button class="btn btn-sm btn-outline-secondary"
+ (click)="downloadPackage(viewedPackage.artifactName,viewedPackage.artifactVersion)"><i
+ class="fa"></i> Download</button>
+
+ <button class="btn btn-sm btn-primary" (click)="goToDesignerMode()">Designer Mode</button>
+ </div>
+ </div>
+
+ </div>
+
+ <nav class="row">
+ <!--Nav Tabs-->
+ <div class="col">
+ <div class="nav nav-tabs " id="nav-tab" role="tablist">
+ <a class="nav-item nav-link active" id="nav-metadata-tab" data-toggle="tab"
+ href="#nav-metadata" role="tab" aria-controls="nav-metadata" aria-selected="true"
+ autofocus #nameit (focusout)="saveMetaData()">METADATA</a>
+ <a class="nav-item nav-link" id="nav-template-tab" data-toggle="tab" href="#nav-template"
+ role="tab" aria-controls="nav-template" aria-selected="false">TEMPLATE & MAPPING</a>
+ <a class="nav-item nav-link" id="nav-scripts-tab" data-toggle="tab" href="#nav-scripts"
+ role="tab" aria-controls="nav-scripts" aria-selected="false">SCRIPTS</a>
+ <a class="nav-item nav-link" id="nav-imports-tab" data-toggle="tab" href="#nav-imports"
+ role="tab" aria-controls="nav-imports" aria-selected="false">IMPORTS</a>
+ <a class="nav-item nav-link" id="nav-authentication-tab" data-toggle="tab"
+ href="#nav-authentication" role="tab" aria-controls="nav-authentication"
+ aria-selected="false">EXTERNAL SYSTEM AUTHENTICATION PROPERTIES</a>
+ </div>
+ </div>
+
+ </nav>
+ <div class="row mt-4">
+ <div class="col">
+ <div class="tab-content" id="nav-tabContent">
+ <div class="tab-pane fade show active" id="nav-metadata" role="tabpanel"
+ aria-labelledby="nav-metadata-tab">
+ <app-metadata-tab></app-metadata-tab>
+ </div>
+ <div class="tab-pane fade" id="nav-template" role="tabpanel"
+ aria-labelledby="nav-template-tab">
+ <app-template-mapping></app-template-mapping>
+ </div>
+ <div class="tab-pane fade" id="nav-scripts" role="tabpanel"
+ aria-labelledby="nav-scripts-tab">
+ <app-scripts-tab></app-scripts-tab>
+ </div>
+ <div class="tab-pane fade" id="nav-imports" role="tabpanel"
+ aria-labelledby="nav-imports-tab">
+ <app-imports-tab></app-imports-tab>
+
+ </div>
+ <div class="tab-pane fade" id="nav-authentication" role="tabpanel"
+ aria-labelledby="nav-authentication-tab">
+ <div class="card creat-card">
+ <div class="editor-container">
+ <app-dsl-definitions-tab></app-dsl-definitions-tab>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+</div>
diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/configuration-dashboard/configuration-dashboard.component.ts b/cds-ui/designer-client/src/app/modules/feature-modules/packages/configuration-dashboard/configuration-dashboard.component.ts
index 84fdafb36..6de76f949 100644
--- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/configuration-dashboard/configuration-dashboard.component.ts
+++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/configuration-dashboard/configuration-dashboard.component.ts
@@ -1,8 +1,18 @@
-import {Component, OnInit} from '@angular/core';
-import {ActivatedRoute} from '@angular/router';
-import {PackageStore} from './package.store';
+import {Component, ElementRef, OnInit, ViewChild} from '@angular/core';
+import {ActivatedRoute, Router} from '@angular/router';
import {BluePrintDetailModel} from '../model/BluePrint.detail.model';
-
+import {PackageCreationStore} from '../package-creation/package-creation.store';
+import {FilesContent, FolderNodeElement, MetaDataTabModel} from '../package-creation/mapping-models/metadata/MetaDataTab.model';
+import {MetadataTabComponent} from '../package-creation/metadata-tab/metadata-tab.component';
+import * as JSZip from 'jszip';
+import {ConfigurationDashboardService} from './configuration-dashboard.service';
+import {VlbDefinition} from '../package-creation/mapping-models/definitions/VlbDefinition';
+import {DslDefinition} from '../package-creation/mapping-models/CBAPacakge.model';
+import {PackageCreationUtils} from '../package-creation/package-creation.utils';
+import {PackageCreationModes} from '../package-creation/creationModes/PackageCreationModes';
+import {PackageCreationBuilder} from '../package-creation/creationModes/PackageCreationBuilder';
+import {saveAs} from 'file-saver';
+import {DesignerStore} from '../designer/designer.store';
@Component({
selector: 'app-configuration-dashboard',
@@ -11,24 +21,192 @@ import {BluePrintDetailModel} from '../model/BluePrint.detail.model';
})
export class ConfigurationDashboardComponent implements OnInit {
viewedPackage: BluePrintDetailModel = new BluePrintDetailModel();
+ @ViewChild(MetadataTabComponent, {static: false})
+ private metadataTabComponent: MetadataTabComponent;
+
+ entryDefinitionKeys: string[] = ['template_tags', 'user-groups',
+ 'author-email', 'template_version', 'template_name', 'template_author'];
+ @ViewChild('nameit', {static: true})
+ private elementRef: ElementRef;
+
+ private zipFile: JSZip = new JSZip();
+ private filesData: any = [];
+ private folder: FolderNodeElement = new FolderNodeElement();
- constructor(private route: ActivatedRoute, private configurationStore: PackageStore) {
+ private currentBlob = new Blob();
+
+ constructor(private route: ActivatedRoute, private configurationDashboardService: ConfigurationDashboardService,
+ private packageCreationStore: PackageCreationStore,
+ private packageCreationUtils: PackageCreationUtils,
+ private router: Router,
+ private designerStore: DesignerStore) {
+ }
+ ngOnInit() {
+ this.elementRef.nativeElement.focus();
const id = this.route.snapshot.paramMap.get('id');
- this.configurationStore.getPagedPackages(id);
- this.configurationStore.state$.subscribe(
- el => {
- if (el && el.configuration) {
- this.viewedPackage = el.configuration;
+ this.configurationDashboardService.getPagedPackages(id).subscribe(
+ (bluePrintDetailModels) => {
+ if (bluePrintDetailModels) {
+ this.viewedPackage = bluePrintDetailModels[0];
+ this.downloadCBAPackage(bluePrintDetailModels);
}
+ });
+ }
+
+
+ private downloadCBAPackage(bluePrintDetailModels: BluePrintDetailModel) {
+ this.configurationDashboardService.downloadResource(
+ bluePrintDetailModels[0].artifactName + '/' + bluePrintDetailModels[0].artifactVersion).subscribe(response => {
+ const blob = new Blob([response], {type: 'application/octet-stream'});
+ this.currentBlob = blob;
+ this.zipFile.loadAsync(blob).then((zip) => {
+ Object.keys(zip.files).forEach((filename) => {
+ console.log(filename);
+ zip.files[filename].async('string').then((fileData) => {
+ if (fileData) {
+ if (filename.includes('Scripts/')) {
+ this.setScripts(filename, fileData);
+ } else if (filename.includes('Templates/')) {
+ if (filename.includes('-mapping.')) {
+ this.setMapping(filename, fileData);
+ } else if (filename.includes('-template.')) {
+ this.setTemplates(filename, fileData);
+ }
+ } else if (filename.includes('Definitions/')) {
+ this.setImports(filename, fileData);
+ } else if (filename.includes('TOSCA-Metadata/')) {
+ const metaDataTabInfo: MetaDataTabModel = this.getMetaDataTabInfo(fileData);
+ // console.log(metaDataTabInfo);
+ this.setMetaData(metaDataTabInfo, bluePrintDetailModels[0]);
+ }
+ }
+ });
+ });
+ });
+ });
+ }
+
+ private setScripts(filename: string, fileData: any) {
+ this.packageCreationStore.addScripts(filename, fileData);
+ }
+
+ private setImports(filename: string, fileData: any) {
+ if (filename.includes('blueprint.json') || filename.includes('vLB_CDS.json')) {
+ let definition = new VlbDefinition();
+ definition = fileData as VlbDefinition;
+ definition = JSON.parse(fileData);
+ const dslDefinition = new DslDefinition();
+ dslDefinition.content = this.packageCreationUtils.transformToJson(definition.dsl_definitions);
+ const mapOfCustomKeys = new Map<string, string>();
+ for (const metadataKey in definition.metadata) {
+ if (!this.entryDefinitionKeys.includes(metadataKey + '')) {
+ mapOfCustomKeys.set(metadataKey + '', definition.metadata[metadataKey + '']);
+ }
+ }
+ this.packageCreationStore.changeDslDefinition(dslDefinition);
+ this.packageCreationStore.setCustomKeys(mapOfCustomKeys);
+ // console.log(definition.topology_template.content);
+ if (definition.topology_template.content) {
+ this.designerStore.saveSourceContent(definition.topology_template.content);
}
- );
+ } else {
+ this.packageCreationStore.addDefinition(filename, fileData);
+ }
+ }
+ private setTemplates(filename: string, fileData: any) {
+ this.packageCreationStore.addTemplate(filename, fileData);
}
- ngOnInit() {
+ private setMapping(fileName: string, fileData: string) {
+ this.packageCreationStore.addMapping(fileName, fileData);
+ }
+
+ editBluePrint() {
+ this.packageCreationStore.state$.subscribe(
+ cbaPackage => {
+ console.log(cbaPackage);
+ FilesContent.clear();
+ let packageCreationModes: PackageCreationModes;
+ cbaPackage = PackageCreationModes.mapModeType(cbaPackage);
+ cbaPackage.metaData = PackageCreationModes.setEntryPoint(cbaPackage.metaData);
+ packageCreationModes = PackageCreationBuilder.getCreationMode(cbaPackage);
+ packageCreationModes.execute(cbaPackage, this.packageCreationUtils);
+ this.filesData.push(this.folder.TREE_DATA);
+ this.saveBluePrintToDataBase();
+ });
+ }
+
+ private setMetaData(metaDataObject: MetaDataTabModel, bluePrintDetailModel: BluePrintDetailModel) {
+ metaDataObject.description = bluePrintDetailModel.artifactDescription;
+ this.packageCreationStore.changeMetaData(metaDataObject);
+
+ }
+
+ saveMetaData() {
+ this.metadataTabComponent.saveMetaDataToStore();
+ }
+
+ getMetaDataTabInfo(fileData: string) {
+ const metaDataTabModel = new MetaDataTabModel();
+ const arrayOfLines = fileData.split('\n');
+ metaDataTabModel.entryFileName = arrayOfLines[3].split(':')[1];
+ metaDataTabModel.name = arrayOfLines[4].split(':')[1];
+ metaDataTabModel.version = arrayOfLines[5].split(':')[1];
+ metaDataTabModel.mode = arrayOfLines[6].split(':')[1];
+ metaDataTabModel.templateTags = new Set<string>(arrayOfLines[7].split(':')[1].split(','));
+ console.log(metaDataTabModel.mode);
+ return metaDataTabModel;
+ }
+ saveBluePrintToDataBase() {
+ this.create();
+ this.zipFile.generateAsync({type: 'blob'})
+ .then(blob => {
+ this.packageCreationStore.saveBluePrint(blob);
+ this.router.navigate(['/packages']);
+ });
}
+
+ create() {
+ FilesContent.getMapOfFilesNamesAndContent().forEach((value, key) => {
+ this.zipFile.folder(key.split('/')[0]);
+ this.zipFile.file(key, value);
+ });
+
+ }
+
+ goBacktoDashboard() {
+ this.router.navigate(['/packages']);
+ }
+
+ downloadPackage(artifactName: string, artifactVersion: string) {
+ this.configurationDashboardService.downloadResource(artifactName + '/' + artifactVersion).subscribe(response => {
+ const blob = new Blob([response], {type: 'application/octet-stream'});
+ saveAs(blob, artifactName + '-' + artifactVersion + '-CBA.zip');
+ });
+ }
+
+ deployCurrentPackage() {
+ console.log('happened');
+ /* this.zipFile.generateAsync({type: 'blob'})
+ .then(blob => {
+ const formData = new FormData();
+ formData.append('file', this.currentBlob);
+ this.configurationDashboardService.deployPost(formData)
+ .subscribe(data => {
+ }, error => {
+ });
+ this.router.navigate(['/packages']);
+ });
+ */
+ this.router.navigate(['/packages']);
+ }
+
+ goToDesignerMode() {
+ this.router.navigate(['/packages/designer']);
+ }
}
diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/configuration-dashboard/configuration-dashboard.service.ts b/cds-ui/designer-client/src/app/modules/feature-modules/packages/configuration-dashboard/configuration-dashboard.service.ts
index 51d0e9db1..164d76601 100644
--- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/configuration-dashboard/configuration-dashboard.service.ts
+++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/configuration-dashboard/configuration-dashboard.service.ts
@@ -9,14 +9,23 @@ import {BluePrintDetailModel} from '../model/BluePrint.detail.model';
providedIn: 'root'
})
export class ConfigurationDashboardService {
-
-
constructor(private api: ApiService<BluePrintDetailModel>) {
}
- getBluePrintModel(id: string): Observable<BluePrintDetailModel> {
+ private getBluePrintModel(id: string): Observable<BluePrintDetailModel> {
return this.api.getOne(BlueprintURLs.getOneBlueprint + '/' + id);
+ }
+
+ getPagedPackages(id: string) {
+ return this.getBluePrintModel(id);
+ }
+
+ public downloadResource(path: string) {
+ return this.api.getCustomized(BlueprintURLs.download + path, {responseType: 'blob'});
+ }
+ deployPost(body: any | null): Observable<any> {
+ return this.api.post(BlueprintURLs.deploy, body, {responseType: 'text'});
}
}
diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/designer.component.css b/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/designer.component.css
index 799407093..37a6f9235 100644
--- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/designer.component.css
+++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/designer.component.css
@@ -268,7 +268,7 @@ p.compType-4{
color: #fff;
}
.actionBtns .btn:last-child{
- padding-left: 34px;
+ padding-left: 34px !important;
background: url(src/assets/img/icon-import-blue.svg) 12px center #fff no-repeat;
border: solid 1px #D0DFF1;
color: #1B3E6F;
@@ -279,6 +279,8 @@ p.compType-4{
}
.componentsList{
padding-bottom: 0;
+ height: calc( 100vh - 218px)!important;
+ overflow: scroll;
}
.custom-control.custom-checkbox:hover,
.custom-control-label:hover{
@@ -342,11 +344,11 @@ p.compType-4{
/*CANVAS*/
.editBar{
- width: 350px;
+ width: 200px;
margin: 0 auto 0;
padding: 6px 10px;
background:#F4F9FE;
- border: solid 1px #E8EFF8;
+ /* border: solid 1px #E8EFF8; */
box-shadow: 0 2px 6px rgba(47, 83, 151, .1);
}
.editBar .btn-group{
@@ -366,7 +368,7 @@ p.compType-4{
}
.viewBtns .btn{
background-position: 10px center;
- padding-left: 30px;
+ padding-left: 30px!important;
}
.viewBtns .topologySource{
background-image: url(src/assets/img/icon-topologyView-active.svg);
@@ -548,3 +550,30 @@ p.compType-4{
font-size: 10px;
}
+.source-button{
+ position: absolute;
+ z-index: 9999999;
+ top: 69px;
+ left: 50%;
+}
+/*jointjs paper*/
+/* #board-paper {
+ position: relative;
+ border: 1px solid gray;
+ display: inline-block;
+ background: transparent;
+ overflow: hidden;
+}
+#board-paper svg {
+ background: transparent;
+}
+#board-paper svg .link {
+ z-index: 2;
+}
+.html-element {
+ position: absolute;
+ background: #F4F9FE;
+ pointer-events: none;
+ -webkit-user-select: none;
+ z-index: 2;
+} */
diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/designer.component.html b/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/designer.component.html
index 8ec735aec..1a2219bab 100644
--- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/designer.component.html
+++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/designer.component.html
@@ -55,26 +55,27 @@
</div>
</div>
</header>
+<div class="source-button editBar">
+ <div class="btn-group viewBtns" role="group">
+ <button type="button" class="btn btn-secondary topologySource active">Designer</button>
+ <button [routerLink]="['/designer/source']" type="button" class="btn btn-secondary topologyView">Scripting</button>
+ </div>
+</div>
<ng-sidebar-container class="sidebar-container">
<!-- Controller SideBar -->
<ng-sidebar [(opened)]="controllerSideBar" [sidebarClass]="'demo-sidebar controllerSidebar container-fluid'"
[mode]="'push'"
#sidebarLeft>
<div class="row">
- <div class="col-12 p-0">
- <form>
- <input type="text" class="form-control input-search-controller"
- placeholder="Search actions and functions">
- </form>
- </div>
+
<h1 class="col-12">Actions</h1>
<div class="col-12 text-center p-0">
<div class="btn-group actionBtns" role="group">
<button (click)="insertCustomActionIntoBoard()" type="button" class="btn">Insert Custom</button>
- <button type="button" class="btn">Import Action</button>
+ <!-- <button type="button" class="btn">Import Action</button> -->
</div>
</div>
- <div class="col-12 actionsList">
+ <!-- <div class="col-12 actionsList">
<b>Select from other packages:</b>
<div class="actions-scroll">
<div class="custom-control custom-checkbox">
@@ -106,32 +107,16 @@
<button type="button" class="btn btn-secondary mr-3">Insert</button>
<button type="button" class="btn btn-secondary">Cancel</button>
</div>
- </div>
+ </div> -->
<h1 class="col-12">Functions</h1>
+ <b>Drag and drop function to Action’s box</b>
<div id="palette-paper" class="col-12 componentsList">
- <b>Drag and drop function to Action’s box</b>
- <ul class="list-group actions-scroll">
- <!-- <li class="list-group-item" *ngFor="let function of viewedFunctions">
- <p class="compType-1">{{function.modelName}}</p>
- </li> -->
- <li class="list-group-item">
- <p class="compType-2">component-netconf-executor</p>
- </li>
- <li class="list-group-item">
- <p class="compType-3">component-remote-ansible-executor</p>
- </li>
- <li class="list-group-item">
- <p class="compType-4">dg-generic</p>
- </li>
- <li class="list-group-item">
- <p class="compType-1">component-resource-resolution</p>
- </li>
- </ul>
</div>
</div>
</ng-sidebar>
<!-- Page content -->
+
<div ng-sidebar-content id="board-paper">
<button class="rotate" (click)="_toggleSidebar1()">
<span>
@@ -139,6 +124,7 @@
<i class="fa fa-angle-double-left"></i>
</span>
</button>
+
<!-- Canvas -->
<div class="editBar text-center">
<div class="btn-group mr-2" role="group" aria-label="First group">
diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/designer.component.ts b/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/designer.component.ts
index b19f5699b..5adce7ea0 100644
--- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/designer.component.ts
+++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/designer.component.ts
@@ -1,9 +1,39 @@
-import { Component, OnInit, ViewEncapsulation } from '@angular/core';
+/*
+============LICENSE_START==========================================
+===================================================================
+Copyright (C) 2019 Orange. All rights reserved.
+===================================================================
+
+Unless otherwise specified, all software contained herein is licensed
+under the Apache License, Version 2.0 (the License);
+you may not use this software 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============================================
+*/
+
+import dagre from 'dagre';
+import graphlib from 'graphlib';
+import { Component, OnInit, ViewEncapsulation, OnDestroy } from '@angular/core';
import * as joint from 'jointjs';
import './jointjs/elements/palette.function.element';
import './jointjs/elements/action.element';
import './jointjs/elements/board.function.element';
-
+import { DesignerStore } from './designer.store';
+import { ActionElementTypeName } from 'src/app/common/constants/app-constants';
+import { GraphUtil } from './graph.util';
+import { GraphGenerator } from './graph.generator.util';
+import { FunctionsStore } from './functions.store';
+import { Subject } from 'rxjs';
+import { takeUntil } from 'rxjs/operators';
+import { distinctUntilChanged } from 'rxjs/operators';
@Component({
@@ -12,23 +42,26 @@ import './jointjs/elements/board.function.element';
styleUrls: ['./designer.component.css'],
encapsulation: ViewEncapsulation.None
})
-export class DesignerComponent implements OnInit {
+export class DesignerComponent implements OnInit, OnDestroy {
private controllerSideBar: boolean;
private attributesSideBar: boolean;
- //to generate Ids for dragged function elements
- private fuctionIdCounter=0;
- private actionIdCounter=0;
boardGraph: joint.dia.Graph;
boardPaper: joint.dia.Paper;
paletteGraph: joint.dia.Graph;
palettePaper: joint.dia.Paper;
+ private ngUnsubscribe = new Subject();
+ private opt = { tx: 100, ty: 100 };
- constructor() {
+ constructor(private designerStore: DesignerStore,
+ private functionStore: FunctionsStore,
+ private graphUtil: GraphUtil,
+ private graphGenerator: GraphGenerator) {
this.controllerSideBar = true;
this.attributesSideBar = false;
+
}
private _toggleSidebar1() {
this.controllerSideBar = !this.controllerSideBar;
@@ -53,23 +86,66 @@ export class DesignerComponent implements OnInit {
ngOnInit() {
this.initializeBoard();
this.initializePalette();
- // this.createEditBarOverThePaper();
- const list = [
- { modelName: 'component-netconf-executor'},
- { modelName: 'component-remote-ansible-executor' },
- { modelName: 'dg-generic' },
- { modelName: 'component-resource-resolution' }];
+ this.stencilPaperEventListeners();
- const cells = this.buildPaletteGraphFromList(list);
- this.paletteGraph.resetCells(cells);
+ /**
+ * the code to retrieve from server is commented
+ */
+ this.functionStore.state$
+ .pipe(
+ distinctUntilChanged((a: any, b: any) => JSON.stringify(a) === JSON.stringify(b)),
+ takeUntil(this.ngUnsubscribe))
+ .subscribe(state => {
+
+ if (state.serverFunctions) {
+ console.log('inside subscriotn on functions store -->', state.serverFunctions);
+ console.log(state);
+ // this.viewedFunctions = state.functions;
+ const list = state.serverFunctions;
+
+ const cells = this.graphUtil.buildPaletteGraphFromList(list);
+ this.paletteGraph.resetCells(cells);
+
+ let idx = 0;
+ cells.forEach(cell => {
+ cell.translate(5, (cell.attributes.size.height + 5) * idx++);
+ });
+ }
+ });
- let idx = 0;
- cells.forEach(cell => {
- console.log(cell);
- cell.translate(5, (cell.attributes.size.height + 5) * idx++);
+ this.designerStore.state$
+ .pipe(
+ distinctUntilChanged((a: any, b: any) => JSON.stringify(a) === JSON.stringify(b)),
+ takeUntil(this.ngUnsubscribe))
+ .subscribe(state => {
+ if (state.sourceContent) {
+ console.log('inside desinger.component---> ', state);
+ // generate graph from store objects if exist
+ const topologtTemplate = JSON.parse(state.sourceContent);
+ console.log(topologtTemplate);
+ delete state.sourceContent;
+ this.graphGenerator.populate(topologtTemplate, this.boardGraph);
+
+ console.log('all cells', this.boardGraph.getCells());
+ /**
+ * auto arrange elements in graph
+ * https://resources.jointjs.com/docs/jointjs/v3.1/joint.html#layout.DirectedGraph
+ */
+ joint.layout.DirectedGraph.layout( this.boardGraph.getCells(), {
+ dagre,
+ graphlib,
+ setLinkVertices: false,
+ marginX: 10,
+ marginY: 10,
+ clusterPadding: { top: 100, left: 30, right: 10, bottom: 100 },
+ rankDir: 'TB'
+ });
+ }
+ });
+
+ // action triggering
+ this.functionStore.retrieveFuntions();
- });
- this.stencilPaperEventListeners();
}
initializePalette() {
@@ -78,22 +154,26 @@ export class DesignerComponent implements OnInit {
this.palettePaper = new joint.dia.Paper({
el: $('#palette-paper'),
model: this.paletteGraph,
- height: 300,
width: 300,
- gridSize: 1,
+ height: $('#palette-paper').height(),
+ // background: {
+ // color: 'rgba(0, 255, 0, 0.3)'
+ // },
interactive: false
+ // elements in paletter need to be fixed, please refer to flying paper concept
});
}
}
initializeBoard() {
if (!this.boardGraph) {
+ console.log('initializeBoard...');
this.boardGraph = new joint.dia.Graph();
this.boardPaper = new joint.dia.Paper({
el: $('#board-paper'),
model: this.boardGraph,
height: 720,
- width: 1200,
+ width: 1100,
gridSize: 10,
drawGrid: true,
// background: {
@@ -120,22 +200,21 @@ export class DesignerComponent implements OnInit {
this.boardGraph.on('change:position', (cell) => {
- var parentId = cell.get('parent');
- if (!parentId) return;
+ const parentId = cell.get('parent');
+ if (!parentId) {
+ // this is action
+ return;
+ }
- var parent = this.boardGraph.getCell(parentId);
-
- var parentBbox = parent.getBBox();
- var cellBbox = cell.getBBox();
+ const parent = this.boardGraph.getCell(parentId);
- console.log("parent ", parentBbox);
- console.log("cell ", cellBbox);
+ const parentBbox = parent.getBBox();
+ const cellBbox = cell.getBBox();
if (parentBbox.containsPoint(cellBbox.origin()) &&
parentBbox.containsPoint(cellBbox.topRight()) &&
parentBbox.containsPoint(cellBbox.corner()) &&
parentBbox.containsPoint(cellBbox.bottomLeft())) {
-
// All the four corners of the child are inside
// the parent area.
return;
@@ -145,54 +224,18 @@ export class DesignerComponent implements OnInit {
cell.set('position', cell.previous('position'));
});
}
+ console.log('done initializing Board...');
}
insertCustomActionIntoBoard() {
- this.actionIdCounter++;
- const element = this.createCustomAction("action_"+ this.actionIdCounter, 'Action' + this.actionIdCounter);
- this.boardGraph.addCell(element);
- }
-
- createCustomAction(id: string, label: string) {
- const element = new joint.shapes.app.ActionElement({
- id: id
- });
- element.attr('#label/text', label);
- return element;
- }
-
- buildPaletteGraphFromList(list: any) {
- const elements = [];
-
- console.log(list);
- list.forEach(element => {
- elements.push(this.createFuctionElementForPalette(element.modelName));
- });
-
- return elements;
- }
-
- createFuctionElementForPalette(label: string) {
- const element = new joint.shapes.palette.FunctionElement({
- id: label
- });
- element.attr('#label/text', label);
- element.attr('type', label);
- return element;
- }
-
- createFuctionElementForBoard(id :String, label :string, type :string) {
- const boardElement = new joint.shapes.board.FunctionElement({
- id: id
- });
- boardElement.attr('#label/text', label);
- boardElement.attr('#type/text', type);
- return boardElement;
+ console.log('saving action to store action workflow....');
+ const actionName = this.graphUtil.generateNewActionName();
+ this.graphUtil.createCustomActionWithName(actionName, this.boardGraph);
+ this.designerStore.addDeclarativeWorkFlow(actionName);
}
stencilPaperEventListeners() {
this.palettePaper.on('cell:pointerdown', (draggedCell, pointerDownEvent, x, y) => {
- console.log('pointerdown 2');
$('body').append(`
<div id="flyPaper"
@@ -232,116 +275,62 @@ export class DesignerComponent implements OnInit {
if (mouseupX > target.left &&
mouseupX < target.left + this.boardPaper.$el.width() &&
mouseupY > target.top && y < target.top + this.boardPaper.$el.height()) {
- // const clonedShape = flyShape.clone();
- const type = flyShape.attributes.attrs.type;
- console.log(type);
-
- //create board function element of the same type of palette function
- //board function element is different in design from the palette function element
- this.fuctionIdCounter++;
- console.log(this.fuctionIdCounter);
- const functionElementForBoard =
- this.createFuctionElementForBoard("fucntion_" + this.fuctionIdCounter, 'execute', type);
-
- functionElementForBoard.position(mouseupX - target.left - offset.x, mouseupY - target.top - offset.y);
- this.boardGraph.addCell(functionElementForBoard);
- const cellViewsBelow =
- this.boardPaper.findViewsFromPoint(functionElementForBoard.getBBox().center());
- console.log(cellViewsBelow);
- if (cellViewsBelow.length) {
- let cellViewBelow;
- cellViewsBelow.forEach( cellItem => {
- if (cellItem.model.id !== functionElementForBoard.id) {
- cellViewBelow = cellItem;
+ const functionType = this.graphUtil.getFunctionTypeFromPaletteFunction(flyShape);
+ // step name is CDS realted terminology, please refer to tosca types
+ const stepName = functionType;
+ const functionElementForBoard = this.graphUtil.dropFunctionOverActionWithPosition(
+ stepName, functionType,
+ mouseupX, mouseupY,
+ target, offset,
+ this.boardGraph);
+
+ const parentCell = this.graphUtil.getParent(functionElementForBoard, this.boardPaper);
+
+ if (parentCell &&
+ parentCell.model.attributes.type === ActionElementTypeName &&
+ this.graphUtil.canEmpedMoreChildern(parentCell.model, this.boardGraph)) {
+
+ if (this.graphUtil.isEmptyParent(parentCell.model)) {
+ // first function in action
+ const actionName = parentCell.model.attributes.attrs['#label'].text;
+ this.designerStore.addStepToDeclarativeWorkFlow(actionName, stepName, functionType);
+ if (functionType === 'dg-generic') {
+ this.designerStore.addDgGenericNodeTemplate(stepName);
+ } else {
+ this.designerStore.addNodeTemplate(stepName, functionType);
}
- });
+ } else {
+ // second action means there was a dg-generic node before
+ this.designerStore.addNodeTemplate(stepName, functionType);
+ // this will fail if multiple dg-generic were added
+ // TODO prevent multi functions of the same type inside the same action
+ const dgGenericNode = this.graphUtil.getDgGenericChild(parentCell.model, this.boardGraph)[0];
+ const dgGenericNodeName = this.graphUtil.getFunctionNameFromBoardFunction(dgGenericNode);
+ this.designerStore.addDgGenericDependency(dgGenericNodeName, stepName);
+ }
+
// Prevent recursive embedding.
- if (cellViewBelow && cellViewBelow.model.get('parent') !== functionElementForBoard.id) {
- console.log(cellViewBelow);
- cellViewBelow.model.embed(functionElementForBoard);
+ if (parentCell &&
+ parentCell.model.get('parent') !== functionElementForBoard.id) {
+ parentCell.model.embed(functionElementForBoard);
}
- console.log(this.boardGraph);
+ } else {
+ console.log('function dropped outside action or not allowed, rolling back...');
+ alert('function dropped outside action or not allowed, rolling back...');
+ functionElementForBoard.remove();
}
-
}
$('body').off('mousemove.fly').off('mouseup.fly');
// flyShape.remove();
$('#flyPaper').remove();
});
});
+ console.log('done stencilPaperEventListeners()...');
}
- /**
- * this is a way to add the button like zoom in , zoom out , and source over jointjs paper
- * may be used if no other way is found
- */
- // createEditBarOverThePaper() {
- // joint.shapes["html"] = {};
- // joint.shapes["html"].Element = joint.shapes.basic.Rect.extend({
- // defaults: joint.util.deepSupplement({
- // type: 'html.Element'
- // }, joint.shapes.basic.Rect.prototype.defaults)
- // });
- // joint.shapes["html"].ElementView = joint.dia.ElementView.extend({
-
- // template: [
- // '<div>',
- // '<div id="editbar" class="editBar text-center">',
- // '<div class="btn-group mr-2" role="group" aria-label="First group">',
- // '<button type="button" class="btn btn-secondary tooltip-bottom" data-tooltip="Undo">',
- // '<img src="/assets/img/icon-undoActive.svg">',
- // '</button>',
- // '<button type="button" class="btn btn-secondary tooltip-bottom" data-tooltip="Redo">',
- // '<img src="/assets/img/icon-redo.svg">',
- // '</button>',
- // '</div>',
- // '<div class="btn-group mr-2" role="group" aria-label="Second group">',
- // '<button type="button" class="btn btn-secondary tooltip-bottom" data-tooltip="Zoom Out">',
- // '<img src="/assets/img/icon-zoomOut.svg">',
- // '</button>',
- // '<button type="button" class="btn btn-secondary pl-0 pr-0">100%</button>',
- // '<button type="button" class="btn btn-secondary tooltip-bottom" data-tooltip="Zoom In">',
- // '<img src="/assets/img/icon-zoomIn.svg">',
- // '</button>',
- // '</div>',
- // '<div class="btn-group viewBtns" role="group" aria-label="Third group">',
- // '<button type="button" class="btn btn-secondary topologySource active">View</button>',
- // '<button type="button" class="btn btn-secondary topologyView">Source</button>',
- // '</div>',
- // '</div>',
- // '</div>'
- // ].join(''),
- // initialize: function () {
- // _.bindAll(this, 'updateBox');
- // joint.dia.ElementView.prototype.initialize.apply(this, arguments);
-
- // this.$box = $(_.template(this.template)());
- // // Prevent paper from handling pointerdown.
- // this.$box.find('input,select').on('mousedown click', function (evt) {
- // evt.stopPropagation();
- // });
- // this.model.on('change', this.updateBox, this);
- // this.updateBox();
- // },
- // render: function () {
- // joint.dia.ElementView.prototype.render.apply(this, arguments);
- // this.paper.$el.prepend(this.$box);
- // this.updateBox();
- // return this;
- // },
- // updateBox: function () {
- // // Set the position and dimension of the box so that it covers the JointJS element.
- // var bbox = this.model.getBBox();
- // this.$box.css({
- // width: bbox.width,
- // height: bbox.height,
- // left: bbox.x,
- // top: bbox.y,
- // transform: 'rotate(' + (this.model.get('angle') || 0) + 'deg)'
- // });
- // }
- // });
-
- // }
+ ngOnDestroy() {
+ this.ngUnsubscribe.next();
+ this.ngUnsubscribe.complete();
+ }
}
diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/designer.service.ts b/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/designer.service.ts
index c4564254f..aa3a6a668 100644
--- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/designer.service.ts
+++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/designer.service.ts
@@ -23,7 +23,7 @@ import {Injectable} from '@angular/core';
import {Observable} from 'rxjs';
import {ApiService} from '../../../../common/core/services/api.typed.service';
import {ResourceDictionaryURLs} from '../../../../common/constants/app-constants';
-import {ModelType} from '../model/ModelType.model';
+import {ModelType} from './model/ModelType.model';
@Injectable({
diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/designer.store.ts b/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/designer.store.ts
index be98eec88..ba8b2f0f1 100644
--- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/designer.store.ts
+++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/designer.store.ts
@@ -22,8 +22,9 @@ limitations under the License.
import {Injectable} from '@angular/core';
import {Store} from '../../../../common/core/stores/Store';
import {DesignerService} from './designer.service';
-import {ModelType} from '../model/ModelType.model';
-import {DesignerDashboardState} from '../model/designer-dashboard.state';
+import {DesignerDashboardState} from './model/designer.dashboard.state';
+import { DeclarativeWorkflow } from './model/designer.workflow';
+import { NodeTemplate } from './model/desinger.nodeTemplate.model';
@Injectable({
@@ -35,15 +36,109 @@ export class DesignerStore extends Store<DesignerDashboardState> {
super(new DesignerDashboardState());
}
- public getFuntions() {
- const modelDefinitionType = 'node_type';
- this.designerService.getFunctions(modelDefinitionType).subscribe(
- (modelType: ModelType[]) => {
- console.log(modelType);
- this.setState({
- ...this.state,
- functions: modelType,
- });
- });
+ /**
+ * adds empty workflow with name only.
+ * called when blank action is added to the board
+ * declarative workflow just contain the steps but its order is determind by dg-graph
+ */
+ addDeclarativeWorkFlow(workflowName: string) {
+ this.setState({
+ ...this.state,
+ template: {
+ ...this.state.template,
+ workflows: {
+ ...this.state.template.workflows,
+ [workflowName]: new DeclarativeWorkflow()
+ }
+ }
+ });
+ }
+
+ addStepToDeclarativeWorkFlow(workflowName: string, stepName: string, stepType: string) {
+ this.setState({
+ ...this.state,
+ template: {
+ ...this.state.template,
+ workflows: {
+ ...this.state.template.workflows,
+ [workflowName]: {
+ ...this.state.template.workflows[workflowName],
+ steps: {
+ [stepName]: {
+ target: stepType,
+ description: ''
+ }
+ }
+ }
+ }
+ }
+ });
+ }
+
+ saveSourceContent(code: string) {
+ const topologyTemplate = JSON.parse(code);
+ this.setState({
+ ...this.state,
+ sourceContent: code,
+ template: topologyTemplate
+ });
+ }
+
+
+ /**
+ * adding node tempates is a separate action of adding the steps to the workflow
+ * you can add node template and don't add workflow step when you add dependencies for the
+ * dg-generic function for example
+ */
+ addNodeTemplate(nodeTemplateName: string, type: string) {
+ this.setState({
+ ...this.state,
+ template: {
+ ...this.state.template,
+ node_templates: {
+ ...this.state.template.node_templates,
+ [nodeTemplateName]: new NodeTemplate(type)
+ }
+ }
+ });
+ }
+
+ addDgGenericNodeTemplate(nodeTemplateName: string) {
+ const node = new NodeTemplate('dg-generic');
+ node.properties = {
+ 'dependency-node-templates': []
+ };
+ this.setState({
+ ...this.state,
+ template: {
+ ...this.state.template,
+ node_templates: {
+ ...this.state.template.node_templates,
+ [nodeTemplateName]: node
+ }
+ }
+ });
+ }
+
+ addDgGenericDependency(dgGenericNodeName: string, dependency: string) {
+ const props = this.state.template.node_templates[dgGenericNodeName].properties;
+ this.setState({
+ ...this.state,
+ template: {
+ ...this.state.template,
+ node_templates: {
+ ...this.state.template.node_templates,
+ [dgGenericNodeName]: {
+ ...this.state.template.node_templates[dgGenericNodeName],
+ properties: {
+ 'dependency-node-templates': [
+ ...props['dependency-node-templates'],
+ dependency
+ ]
+ }
+ }
+ }
+ }
+ });
}
}
diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/configuration-dashboard/package.store.ts b/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/functions.store.ts
index efbaef8bd..86814179d 100644
--- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/configuration-dashboard/package.store.ts
+++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/functions.store.ts
@@ -21,38 +21,28 @@ limitations under the License.
import {Injectable} from '@angular/core';
import {Store} from '../../../../common/core/stores/Store';
-import {BluePrintDetailModel} from '../model/BluePrint.detail.model';
-import {ConfigurationDashboardService} from './configuration-dashboard.service';
-import {PackageDashboardState} from '../model/package-dashboard.state';
+import {DesignerService} from './designer.service';
+import {ModelType} from './model/ModelType.model';
+import { FunctionsState } from './model/functions.state';
@Injectable({
providedIn: 'root'
})
-export class PackageStore extends Store<PackageDashboardState> {
+export class FunctionsStore extends Store<FunctionsState> {
-
- constructor(private configurationDashboardService: ConfigurationDashboardService) {
- super(new PackageDashboardState());
+ constructor(private designerService: DesignerService) {
+ super(new FunctionsState());
}
- getPagedPackages(id: string) {
- this.configurationDashboardService.getBluePrintModel(id).subscribe(
- (bluePrintDetailModels) => {
+ public retrieveFuntions() {
+ const modelDefinitionType = 'node_type';
+ this.designerService.getFunctions(modelDefinitionType).subscribe(
+ (modelTypeList: ModelType[]) => {
this.setState({
...this.state,
- configuration: bluePrintDetailModels[0]
+ serverFunctions: modelTypeList,
});
});
- /* bluePrintDetailModels.forEach(
- bluePrintDetailModel => {
- this.setState({
- ...this.state,
- configuration: bluePrintDetailModel
- });
- });*/
-
-
}
-
}
diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/functions/functions.component.css b/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/functions/functions.component.css
deleted file mode 100644
index e69de29bb..000000000
--- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/functions/functions.component.css
+++ /dev/null
diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/functions/functions.component.html b/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/functions/functions.component.html
deleted file mode 100644
index b27f91f49..000000000
--- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/functions/functions.component.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<h1 class="col-12">Functions</h1>
-<div class="col-12 componentsList">
- <b>Drag and drop function to Action’s box</b>
- <ul class="list-group actions-scroll" >
- <li class="list-group-item" *ngFor="let function of viewedFunctions">
- <p class="compType-1">{{function.modelName}}</p>
- </li>
- <!--<li class="list-group-item">
- <p class="compType-2">component-netconf-executor</p>
- </li>
- <li class="list-group-item">
- <p class="compType-3">component-remote-ansible-executor</p>
- </li>
- <li class="list-group-item">
- <p class="compType-4">dg-generic</p>
- </li>
- <li class="list-group-item">
- <p class="compType-1">component-resource-resolution</p>
- </li>-->
- </ul>
-</div>
diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/functions/functions.component.spec.ts b/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/functions/functions.component.spec.ts
deleted file mode 100644
index eec909b01..000000000
--- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/functions/functions.component.spec.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-import { async, ComponentFixture, TestBed } from '@angular/core/testing';
-
-import { FunctionsComponent } from './functions.component';
-
-describe('FunctionsComponent', () => {
- let component: FunctionsComponent;
- let fixture: ComponentFixture<FunctionsComponent>;
-
- beforeEach(async(() => {
- TestBed.configureTestingModule({
- declarations: [ FunctionsComponent ]
- })
- .compileComponents();
- }));
-
- beforeEach(() => {
- fixture = TestBed.createComponent(FunctionsComponent);
- component = fixture.componentInstance;
- fixture.detectChanges();
- });
-
- it('should create', () => {
- expect(component).toBeTruthy();
- });
-});
diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/functions/functions.component.ts b/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/functions/functions.component.ts
deleted file mode 100644
index 5a86150e8..000000000
--- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/functions/functions.component.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-import {Component, OnInit} from '@angular/core';
-import {DesignerStore} from '../designer.store';
-import {ModelType} from '../../model/ModelType.model';
-
-
-@Component({
- selector: 'app-functions',
- templateUrl: './functions.component.html',
- styleUrls: ['./functions.component.css']
-})
-export class FunctionsComponent implements OnInit {
- viewedFunctions: ModelType[] = [];
-
- constructor(private designerStore: DesignerStore) {
-
- this.designerStore.state$.subscribe(state => {
- console.log(state);
- if (state.functions) {
- this.viewedFunctions = state.functions;
- }
- });
- }
-
- ngOnInit() {
- this.designerStore.getFuntions();
- }
-
-}
diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/graph.generator.util.ts b/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/graph.generator.util.ts
new file mode 100644
index 000000000..8e1d88907
--- /dev/null
+++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/graph.generator.util.ts
@@ -0,0 +1,113 @@
+/*
+============LICENSE_START==========================================
+===================================================================
+Copyright (C) 2019 Orange. All rights reserved.
+===================================================================
+
+Unless otherwise specified, all software contained herein is licensed
+under the Apache License, Version 2.0 (the License);
+you may not use this software 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============================================
+*/
+import { TopologyTemplate } from './model/designer.topologyTemplate.model';
+import { Injectable } from '@angular/core';
+import { GraphUtil } from './graph.util';
+import { NodeTemplate } from './model/desinger.nodeTemplate.model';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class GraphGenerator {
+
+ constructor(private graphUtil: GraphUtil) {
+ }
+
+ /**
+ * loops over workflows
+ * create action element
+ * from steps --> create function element
+ * add function element to action element
+ * example toplogyTemplate
+ *
+ * {
+ * "workflows": {
+ * "Action1": {
+ * "steps": {
+ * "STEP_NAME": {
+ * "target": "NODE_TEMPLATE_NAME",
+ * "description": ""
+ * }
+ * }
+ * }
+ * },
+ * "node_templates": {
+ * "NODE_TEMPLATE_NAME": {
+ * "type": "dg-generic",
+ * "properties": {
+ * "dependency-node-templates": [
+ * "component-config-snapshots-executor",
+ * "component-jython-executor"
+ * ]
+ * }
+ * },
+ * "component-config-snapshots-executor": {
+ * "type": "component-config-snapshots-executor",
+ * "properties": { }
+ * },
+ * "component-jython-executor": {
+ * "type": "component-jython-executor",
+ * "properties": { }
+ * }
+ * }
+ * }
+ */
+
+ public populate(topologyTempalte: TopologyTemplate,
+ boardGraph: joint.dia.Graph) {
+
+ Object.keys(topologyTempalte.workflows).forEach(workFlowName => {
+ console.log('drawing workflow item --> ', workFlowName);
+
+ // create action element
+ const actionElement =
+ this.graphUtil.createCustomActionWithName(workFlowName, boardGraph);
+
+ // create board function elements
+ const workflow = topologyTempalte.workflows[workFlowName].steps;
+ const stepName = Object.keys(workflow)[0];
+ if (stepName) {
+ const nodeTemplateName = workflow[stepName].target;
+ const functionType = topologyTempalte.node_templates[nodeTemplateName].type;
+ console.log('draw function with ', stepName, functionType);
+
+ this.graphUtil.dropFunctionOverActionRelativeToParent(
+ actionElement,
+ stepName , functionType, boardGraph);
+
+ // TODO handle dg-generic case (multi-step in the same action)
+ if (functionType === 'dg-generic') {
+ const props = topologyTempalte.node_templates[nodeTemplateName].properties;
+ console.log('dg props', props);
+ props['dependency-node-templates'].forEach(dependencyStepName => {
+ const dependencyType = topologyTempalte.node_templates[dependencyStepName].type;
+ console.log('dependencyType', dependencyType);
+ this.graphUtil.dropFunctionOverActionRelativeToParent(
+ actionElement,
+ dependencyStepName, dependencyType, boardGraph);
+
+ });
+ }
+ }
+ });
+
+ }
+}
diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/graph.util.ts b/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/graph.util.ts
new file mode 100644
index 000000000..fd4dd35e4
--- /dev/null
+++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/graph.util.ts
@@ -0,0 +1,228 @@
+/*
+============LICENSE_START==========================================
+===================================================================
+Copyright (C) 2019 Orange. All rights reserved.
+===================================================================
+
+Unless otherwise specified, all software contained herein is licensed
+under the Apache License, Version 2.0 (the License);
+you may not use this software 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============================================
+*/
+
+import * as joint from 'jointjs';
+import { Injectable } from '@angular/core';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class GraphUtil {
+
+ actionIdCounter = 0;
+ // to generate Ids for dragged function elements
+ private fuctionIdCounter = 0;
+
+ createCustomAction(boardGraph: joint.dia.Graph) {
+ const actionName = this.generateNewActionName();
+ const actionId = this.generateNewActionId();
+ const element = new joint.shapes.app.ActionElement({
+ id: actionId
+ });
+ element.attr('#label/text', actionName);
+ boardGraph.addCell(element);
+ return element;
+ }
+
+ generateNewActionName() {
+ this.actionIdCounter++;
+ const actionName = 'Action' + this.actionIdCounter;
+ return actionName;
+ }
+
+ private generateNewActionId() {
+ const actionName =
+ (Date.now().toString(36) + Math.random().toString(36).substr(2, 5))
+ .toUpperCase();
+ return actionName;
+ }
+
+ createCustomActionWithName(actionName: string, boardGraph: joint.dia.Graph) {
+ const actionId = this.generateNewActionId();
+ const element = new joint.shapes.app.ActionElement({
+ id: actionId
+ });
+ element.attr('#label/text', actionName);
+ boardGraph.addCell(element);
+ return element;
+ }
+
+ buildPaletteGraphFromList(list: any) {
+ const elements = [];
+ list.forEach(element => {
+ elements.push(this.createFuctionElementForPalette(element.modelName));
+ });
+
+ return elements;
+ }
+
+ createFuctionElementForPalette(label: string) {
+ const element = new joint.shapes.palette.FunctionElement({
+ id: label
+ });
+ element.attr('#label/text', label);
+ element.attr('type', label);
+ return element;
+ }
+
+ createFuctionElementForBoard( label: string, type: string) {
+ this.fuctionIdCounter++;
+ const id = 'fucntion_' + this.fuctionIdCounter;
+ const boardElement = new joint.shapes.board.FunctionElement({
+ id
+ });
+ boardElement.attr('#label/text', label);
+ boardElement.attr('#type/text', type);
+ return boardElement;
+ }
+
+ getParent(functionElementForBoard: joint.shapes.board.FunctionElement, boardPaper: joint.dia.Paper) {
+ const cellViewsBelow = boardPaper.findViewsFromPoint(functionElementForBoard.getBBox().center());
+ let cellViewBelow;
+ if (cellViewsBelow.length) {
+ cellViewsBelow.forEach(cellItem => {
+ if (cellItem.model.id !== functionElementForBoard.id) {
+ cellViewBelow = cellItem;
+ }
+ });
+ }
+ return cellViewBelow;
+ }
+
+ /**
+ * trigger actions related to Function dropped over the board:
+ * - create board function element of the same type of palette function
+ * as board function element is different from the palette function element
+ * - save function to parent action in store
+ */
+ dropFunctionOverActionWithPosition(
+ label: string, type: string,
+ mouseupX: number, mouseupY: number,
+ target: JQuery.Coordinates, offset: { x: number; y: number; },
+ boardGraph: joint.dia.Graph) {
+
+ const functionElementForBoard = this.dropFunctionOverAction(label, type, boardGraph);
+ functionElementForBoard.position(mouseupX - target.left - offset.x, mouseupY - target.top - offset.y);
+
+ return functionElementForBoard;
+ }
+
+
+ dropFunctionOverActionRelativeToParent(
+ parent: joint.shapes.app.ActionElement,
+ label: string, type: string,
+ boardGraph: joint.dia.Graph) {
+
+ const functionElementForBoard = this.dropFunctionOverAction(label, type, boardGraph);
+ parent.embed(functionElementForBoard);
+ functionElementForBoard.position({ parentRelative: true });
+
+ return functionElementForBoard;
+ }
+
+
+ dropFunctionOverAction(
+ label: string, type: string,
+ boardGraph: joint.dia.Graph) {
+
+ // function name is the same as function type
+ // actually functionName here refers step name in CDS tosca model
+ // and function type is the nodeTempalteName
+ const functionElementForBoard =
+ this.createFuctionElementForBoard(label, type);
+ boardGraph.addCell(functionElementForBoard);
+ return functionElementForBoard;
+ }
+
+ getFunctionTypeFromPaletteFunction(cell: joint.shapes.palette.FunctionElement) {
+ return cell.attributes.attrs.type;
+ }
+
+ getFunctionTypeFromBoardFunction(cell: joint.shapes.board.FunctionElement) {
+ return cell.attributes.attrs['#type'].text;
+ }
+
+ getFunctionNameFromBoardFunction(cell: joint.shapes.board.FunctionElement) {
+ return cell.attributes.attrs['#label'].text;
+ }
+
+ canEmpedMoreChildern(parentCell: joint.shapes.app.ActionElement, boardGraph: joint.dia.Graph): boolean {
+ if (!parentCell.get('embeds')) {
+ return true;
+ }
+ const types = this.getChildernTypes(parentCell, boardGraph);
+ return parentCell.get('embeds').length < 1 ||
+ types.includes('dg-generic');
+ }
+
+
+ getChildernTypes(parentCell: joint.shapes.app.ActionElement,
+ boardGraph: joint.dia.Graph): string[] {
+ if (parentCell.get('embeds')) {
+ return parentCell.get('embeds').map((cellName) => {
+ const child = boardGraph.getCell(cellName) as joint.shapes.board.FunctionElement;
+ const functionType = this.getFunctionTypeFromBoardFunction(child);
+ console.log('functionType', functionType);
+ return functionType;
+ });
+ } else {
+ return [];
+ }
+ }
+
+ getDgGenericChild(parentCell: joint.shapes.app.ActionElement,
+ boardGraph: joint.dia.Graph):
+ joint.shapes.board.FunctionElement[] {
+ if (parentCell.get('embeds')) {
+ return parentCell.get('embeds')
+ .filter((cellName) => {
+ const child = boardGraph.getCell(cellName) as joint.shapes.board.FunctionElement;
+ const functionType = this.getFunctionTypeFromBoardFunction(child);
+ return functionType === 'dg-generic';
+ })
+ .map((cellName) => {
+ const child = boardGraph.getCell(cellName) as joint.shapes.board.FunctionElement;
+ return child;
+ });
+ } else {
+ return [];
+ }
+ }
+
+ isEmptyParent(parentCell: joint.shapes.app.ActionElement): boolean {
+ return !parentCell.get('embeds') || parentCell.get('embeds').length < 1;
+ }
+
+ getActionSiblings(actionCell: joint.shapes.app.ActionElement,
+ boardGraph: joint.dia.Graph
+ ): joint.shapes.app.ActionElement[] {
+ const cellId = actionCell.id;
+ const siblings = boardGraph.getCells().filter(elem => {
+ const type = elem.attributes.type;
+ const elemId = elem.id;
+ return (type !== undefined && type === 'app.ActionElement'
+ && elemId !== cellId);
+ }) as joint.shapes.app.ActionElement[];
+ console.log('siblings', siblings);
+ return siblings;
+ }
+
+}
diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/jointjs/elements/action.element.ts b/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/jointjs/elements/action.element.ts
index 212905814..7960e83d1 100644
--- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/jointjs/elements/action.element.ts
+++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/jointjs/elements/action.element.ts
@@ -1,4 +1,5 @@
import * as joint from 'jointjs';
+import { ActionElementTypeName } from 'src/app/common/constants/app-constants';
/**
* please refer to documentation in file palette.function.element.ts to get more details
* about how to create new element type and define it in typescript
@@ -18,7 +19,7 @@ const rectWidth = 616;
const rectHeight = 381;
// custom element implementation
// https://resources.jointjs.com/tutorials/joint/tutorials/custom-elements.html#markup
-const ActionElement = joint.shapes.standard.Rectangle.define('app.ActionElement', {
+const ActionElement = joint.shapes.standard.Rectangle.define(ActionElementTypeName, {
size: {width: rectWidth, height: rectHeight}
},
{
diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/model/ModelType.model.ts b/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/model/ModelType.model.ts
index c8498fa36..c8498fa36 100644
--- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/model/ModelType.model.ts
+++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/model/ModelType.model.ts
diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/model/designer.dashboard.state.ts b/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/model/designer.dashboard.state.ts
new file mode 100644
index 000000000..1a14021f4
--- /dev/null
+++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/model/designer.dashboard.state.ts
@@ -0,0 +1,33 @@
+/*
+============LICENSE_START==========================================
+===================================================================
+Copyright (C) 2019 Orange. All rights reserved.
+===================================================================
+
+Unless otherwise specified, all software contained herein is licensed
+under the Apache License, Version 2.0 (the License);
+you may not use this software 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============================================
+*/
+
+import {ModelType} from './ModelType.model';
+import { TopologyTemplate } from './designer.topologyTemplate.model';
+
+export class DesignerDashboardState {
+
+ template: TopologyTemplate;
+ sourceContent: string;
+
+ constructor() {
+ this.template = new TopologyTemplate();
+ }
+}
diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/model/designer.topologyTemplate.model.ts b/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/model/designer.topologyTemplate.model.ts
new file mode 100644
index 000000000..b85a6139a
--- /dev/null
+++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/model/designer.topologyTemplate.model.ts
@@ -0,0 +1,13 @@
+import { DeclarativeWorkflow } from './designer.workflow';
+import { NodeTemplate } from './desinger.nodeTemplate.model';
+
+export class TopologyTemplate {
+
+ workflows: {};
+ 'node_templates': {};
+
+ constructor() {
+ this.workflows = {};
+ this.node_templates = {};
+ }
+}
diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/model/designer.workflow.ts b/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/model/designer.workflow.ts
new file mode 100644
index 000000000..0687c1f47
--- /dev/null
+++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/model/designer.workflow.ts
@@ -0,0 +1,14 @@
+export class Workflow {
+ inputs: {};
+ outputs?: {};
+}
+
+export class DeclarativeWorkflow implements Workflow {
+ steps: {};
+ inputs: {};
+ outputs?: {};
+
+ constructor() {
+ this.steps = {};
+ }
+}
diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/model/desinger.nodeTemplate.model.ts b/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/model/desinger.nodeTemplate.model.ts
new file mode 100644
index 000000000..8715e44c2
--- /dev/null
+++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/model/desinger.nodeTemplate.model.ts
@@ -0,0 +1,15 @@
+export class NodeTemplate {
+ type: string;
+ properties?: {
+ 'dependency-node-templates'?: string[]
+ };
+ interfaces?: {};
+ artifacts?: {};
+ cabapilities?: {};
+ requirements?: {};
+
+ constructor(type) {
+ this.type = type;
+ this.properties = {};
+ }
+}
diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/model/designer-dashboard.state.ts b/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/model/functions.state.ts
index dc65c009f..329c38deb 100644
--- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/model/designer-dashboard.state.ts
+++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/model/functions.state.ts
@@ -21,9 +21,11 @@ limitations under the License.
import {ModelType} from './ModelType.model';
-export class DesignerDashboardState {
+export class FunctionsState {
- functions: ModelType[];
- actions: string[];
+ serverFunctions: ModelType[];
+ constructor() {
+ this.serverFunctions = [];
+ }
}
diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/source-view/source-view.component.css b/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/source-view/source-view.component.css
new file mode 100644
index 000000000..01ae599a4
--- /dev/null
+++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/source-view/source-view.component.css
@@ -0,0 +1,580 @@
+.dsl-editor {
+ height: 500px;
+}
+
+body{
+ background-image: linear-gradient(-45deg, #000 9%, #fff 0) !important;
+ background-size: 6px 6px !important;
+}
+
+
+/*Header*/
+header{
+ height: 60px;
+ background-color: #1B3E6F;
+ box-shadow: 0 4px 10px rgba(238, 240, 245, 1.0);
+}
+.logo{
+ float: left;
+ width: 50px;
+ height: 60px;
+ background: url(/assets/img/logo-icon.svg) center center #fff no-repeat;
+}
+
+/**Bread Crumb**/
+.breadcrumb{
+ padding: 9px 20px;
+ background: transparent;
+ line-height: 40px;
+}
+.breadcrumb a,
+.breadcrumb a:hover{
+ color: #fff;
+}
+.breadcrumb .breadcrumb-item{
+ font-size: 12px;
+ font-weight: bold;
+}
+.breadcrumb .breadcrumb-item:first-child{
+ font-size: 16px;
+}
+.breadcrumb-item + .breadcrumb-item::before{
+ color: #fff;
+}
+.breadcrumb .breadcrumb-item.active p{
+ display: inline;
+ padding: 4px 10px;
+ background: #F4F9FE;
+ border-radius: 10px;
+ color: #C3CDDB;
+ font-size: 10px;
+}
+.sidebar-container{
+ height: calc(100vh - 60px) !important;
+}
+/**Topology Actions**/
+.topology-actions{
+ margin: 0;
+ height: 60px;
+}
+.topology-actions > li{
+ height: 59px;
+ display: inline-block;
+ padding: 0 20px;
+}
+.topology-actions > li:first-child{
+ border-right: solid 1px #16396A;
+}
+.topology-actions .btn-group{
+ margin-top: 11px;
+}
+.btn-topology-action,
+.btn-topology-action:hover{
+ margin: 0 6px;
+ padding: 6px 10px;
+ color: #fff;
+ border-radius: 50%;
+ border: solid .5px #fff;
+}
+.btn-topology-action:last-child{
+ margin-right: 0;
+}
+.btn-topology-action .fa{
+ width: 16px;
+ height: 16px;
+ text-align: center;
+}
+.topology-actions .dropdown-text,
+.dropdown-toggle:hover ~ .dropdown-text,
+.dropdown-toggle:focus ~ .dropdown-text{
+ top: 7px;
+ text-indent: 15px;
+ background: #1273EB;
+ border-radius: 15px;
+ border: 0;
+ box-shadow: none;
+ color: #fff;
+ font-weight: bold;
+ font-size: 13px;
+}
+.topology-actions .dropdown-text::after{
+ right: 15px;
+ top: 13px;
+ border-width: 6px 6px 0 6px;
+ border-color: #fff transparent transparent transparent;
+}
+.topology-actions .dropdown-toggle:focus ~ .dropdown-text::after{
+ top: 13px;
+ border-width: 0 6px 6px 6px;
+ border-color: transparent transparent #fff transparent
+}
+.topology-actions .dropdown-content:hover,
+.topology-actions .dropdown-toggle:focus ~ .dropdown-content{
+ padding: 12px 0;
+ text-indent: 0;
+ background: #fff;
+ border: 0;
+ border-radius: 2px;
+ box-shadow: 0 2px 6px rgba(47, 83, 151, .15)
+}
+.topology-actions .dropdown-content a{
+ padding: 0 20px;
+ color: #1B3E6F;
+ font-size: 13px;
+}
+.topology-actions .dropdown-content a:hover{
+ background: #F4F9FE;
+ text-decoration: none;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/*Rotated Text*/
+button.rotate{
+ position: absolute;
+ margin-top: 1px;
+ padding: 0;
+ background: transparent;
+ border: 0;
+}
+.rotate{
+ vertical-align: bottom;
+ /* text-align: center; */
+}
+.rotate span{
+ display: inline-table !important;
+ -ms-writing-mode: tb-rl;
+ -webkit-writing-mode: vertical-rl;
+ writing-mode: vertical-rl !important;
+ transform: rotate(180deg);
+ white-space: nowrap;
+ background: #1B3E6F;
+ padding: 15px 12px;
+ font-weight: bold;
+ font-size: 12px;
+ color:#fff;
+ /* border-bottom-left-radius: 2px; */
+ border-top-left-radius: 2px;
+}
+.rotate i{
+ margin-right: 3px;
+ margin-top: 9px;
+ font-size: 15px;
+}
+.rotate span:first-child{
+ margin-bottom: 0;
+}
+.rotate a:hover{
+ text-decoration: none;
+}
+
+/*ACTIONS & COMPONENTS MENU*/
+.input-search-controller{
+ height: 50px;
+ padding-left: 30px;
+ background: url(src/assets/img/icon-search-light.svg) #fff 10px center no-repeat;
+ border-radius: 0;
+ border: 0;
+ border-bottom: solid 1px #D7E7F9;
+ color: #1B3E6F;
+ font-size: 13px;
+}
+.input-search-controller::placeholder{
+ color: #D0D7E4;
+ font-size: 11px;
+}
+.input-search-controller:focus{
+
+ box-shadow: 0 2px 6px 0 rgba(47, 83, 151, .15);
+ border-color: #DEE8F3;
+}
+.actions-scroll{
+ max-height: 29vh;
+ overflow-y: auto;
+ margin-top: 12px;
+ margin-bottom: 20px;
+}
+.componentsList p{
+ margin-bottom: 0;
+ padding-left: 30px;
+ background-position: left center;
+ background-repeat: no-repeat;
+}
+p.compType-1{
+ background-image: url(/assets/img/icon-comType1-sm.svg);
+}
+p.compType-2{
+ background-image: url(/assets/img/icon-comType2-sm.svg);
+}
+p.compType-3{
+ background-image: url(/assets/img/icon-comType3-sm.svg);
+}
+p.compType-4{
+ background-image: url(/assets/img/icon-comType4-sm.svg);
+}
+/*Actions Wrapper*/
+.actions-wrapper{
+ position: absolute;
+ width: 100%;
+ top: 0;
+}
+.actions-container{
+ width: 92%;
+ margin: 0 auto;
+ background: red;
+}
+
+.controllerSidebar{
+ width: 320px;
+ background: #F4F9FE;
+ border: solid 1px #C1CDDD;
+ box-shadow: 0 2px 6px rgba(47, 83, 151, .10);
+}
+.controllerSidebar h1{
+ margin-bottom: 15px;
+ padding: 12px 0 12px 12px;
+ background: #fff;
+ font-size: 12px;
+ font-weight: bold;
+ text-transform: uppercase;
+ color: #C3CDDB;
+}
+.controllerSidebar b{
+ font-size: 12px;
+ color: #C3CDDB;
+}
+.actionBtns .btn{
+ margin: 0 15px 12px;
+ padding: 9px 20px;
+ border-radius: 2px !important;
+ font-size: 12px;
+ font-weight: bold;
+}
+.actionBtns .btn:first-child{
+ background: #1B3E6F;
+ border: solid 1px #1B3E6F;
+ color: #fff;
+}
+.actionBtns .btn:last-child{
+ padding-left: 34px !important;
+ background: url(src/assets/img/icon-import-blue.svg) 12px center #fff no-repeat;
+ border: solid 1px #D0DFF1;
+ color: #1B3E6F;
+}
+.actionsList,
+.componentsList{
+ padding: 0 12px 20px;
+}
+.componentsList{
+ padding-bottom: 0;
+}
+.custom-control.custom-checkbox:hover,
+.custom-control-label:hover{
+ cursor: pointer;
+}
+.actionsList .custom-checkbox,
+.componentsList .list-group-item{
+ margin-bottom: 10px;
+ padding-left: 40px;
+ background: #fff;
+ box-shadow: 0 2px 6px rgba(47, 83, 151, .15);
+ border-radius: 2px;
+}
+.actionsList .custom-control-label{
+ width: 100%;
+ padding: 6px;
+ vertical-align: unset;
+ color: #1B3E6F;
+ font-size: 14px;
+ line-height: 20px;
+ border-top-right-radius: 2px;
+ border-bottom-right-radius: 2px;
+}
+.actionsList .custom-control-label::before,
+.actionsList .custom-control-label::after{
+ top: 1.25rem;
+}
+.actionsList .custom-control-label p{
+ color: #C7D0DD;
+ font-size: 12px;
+}
+.custom-control-input:checked ~ .custom-control-label{
+ background-color: #1B3E6F !important;
+ color: #fff;
+}
+.inserActionBtns .btn{
+ border-radius: 15px !important;
+ padding: 6px 20px;
+ font-size: 12px;
+ font-weight: bold;
+ border: 0;
+
+}
+.inserActionBtns .btn:first-child{
+ background: #1273EB;
+ border: solid 1px #1273EB;
+ color: #fff;
+}
+.inserActionBtns .btn:last-child{
+ background: #fff;
+ border: solid 1px #D9E6F2;
+ color: #C3CDDB;
+}
+/*Components List*/
+.componentsList .list-group-item{
+ padding-left: 36px;
+ border: 0;
+ font-size: 14px;
+ background: url(src/assets/img/icon-drag.svg) #fff 20px center no-repeat;
+}
+
+/*CANVAS*/
+.editBar{
+ width: 200px;
+ margin: 0 auto 0;
+ padding: 6px 10px;
+ background:#F4F9FE;
+ /* border: solid 1px #E8EFF8; */
+ box-shadow: 0 2px 6px rgba(47, 83, 151, .1);
+}
+.editBar .btn-group{
+ box-shadow: 0 2px 6px rgba(47, 83, 151, .15);
+}
+.editBar .btn{
+ background-color: #fff;
+ background-repeat: no-repeat;
+ background-position: left center;
+ border: 0;
+ color: #1B3E6F;
+ font-size: 10px;
+}
+.editBar .btn.active{
+ background-color: #1B3E6F !important;
+ color: #fff;
+}
+.viewBtns .btn{
+ background-position: 10px center;
+ padding-left: 30px!important;
+}
+.viewBtns .topologySource{
+ background-image: url(src/assets/img/icon-topologyView-active.svg);
+}
+.viewBtns .topologyView{
+ background-image: url(src/assets/img/icon-topologySource.svg);
+}
+.card.actionContainer{
+ margin: 20px 20px 40px 60px;
+ background: transparent;
+ border: 0;
+}
+.actionContainer .card-header{
+ padding: 0;
+ background: transparent;
+ border: 0;
+}
+.actionContainer .card-header span{
+ padding: 12px 20px;
+ border-top-left-radius: 2px;
+ border-top-right-radius: 2px;
+ font-size: 12px;
+ line-height: 38px;
+ font-weight: bold;
+ color: #1B3E6F;
+ background: #C3CDDB;
+}
+.actionContainer .card-body{
+ min-height: 170px;
+ padding: 15px 20px !important;
+ border: solid 1px #C3CDDB;
+ background: #fff;
+ box-shadow: 0 2px 6px rgba(18, 115, 235, .1);
+}
+.actionContainer a{
+ display: inline-block;
+ width: 230px;
+ height: 130px;
+ margin: 20px;
+ padding: 24px;
+ background: #1B3E6F;
+ color: #fff !important;
+ text-align: center;
+ border-radius: 2px;
+ border: solid 1px #1B3E6F;
+}
+.actionContainer a:hover{
+ cursor: pointer;
+ border: dashed 1px #E9FCC6;
+}.componentContainer img{
+ height: 38px;
+}
+.componentContainer h2{
+ margin-top: 9px;
+ font-size: 14px;
+ font-weight: bold;
+}
+.componentContainer p{
+ font-size: 12px;
+}
+
+/*ATTRIBUTES SIDE BAR*/
+.attributesSideBar{
+ width: 396px;
+ padding: 0;
+}
+.attributesSideBar .attributesContainer{
+ background: #fff;
+ border: solid 1px #C1CDDD;
+ box-shadow: 0 2px 6px rgba(47, 83, 151, .1);
+}
+.closeBar{
+ float: right;
+ width: 90%;
+ height: 40px;
+ background: url(/assets/img/icon-close.svg) center center #DCE8F4 no-repeat ;
+ border: 0;
+ outline: 0;
+}
+.closeBar:focus{
+ outline: none;
+}
+.attributesContainer h1{
+ margin-bottom: 10px;
+ padding: 12px 0 12px 15px;
+ background: #DEE8F3;
+ font-size: 12px;
+ font-weight: bold;
+ text-transform: uppercase;
+ color: #1B3E6F;
+}
+.actionName{
+ margin-bottom: 21px;
+}
+.attributesContainer label{
+ color: #1B3E6F;
+ text-transform: uppercase;
+ font-size: 11px;
+ font-weight: bold;
+}
+.attributesContainer .form-group{
+ margin-bottom: 9px;
+}
+.attributesContainer .form-control{
+ border-color: #F0F5FC;
+ border-radius: 2px;
+ box-shadow: 0 2px 6px rgba(47, 83, 151, .1);
+ color: #103D73;
+ font-size: 13px;
+}
+.attributesContainer .form-control:focus{
+ border-color: #66bfff;
+ box-shadow: 0 0 0 4px rgba(0,149,255,0.15);
+}
+.attributesContainer .form-control::placeholder{
+ color: #CFD7E5;
+}
+.scrolll{
+ max-height: 88.75vh;
+ overflow-y: auto;
+}
+.accordion > .card{
+ margin-bottom: 0 !important;
+ border: 0;
+}
+.accordion > .card .card-header{
+ margin: 0;
+ padding: 0;
+ background-color: #F4F9FE;
+ border: 0;
+ border-radius: 0;
+}
+.accordion > .card .card-body{
+ padding-bottom: 10px !important;
+}
+.accordion .btn-link{
+ padding: 0;
+ color: #C3CDDB;
+ font-weight: bold;
+ font-size: 13px;
+ text-transform: uppercase;
+ line-height: 38px;
+}
+.accordion .btn-link:hover{
+ color: #103D73;
+ text-decoration: unset;
+}
+.accordion .card-header .btn-link[aria-expanded="true"]:after,
+.accordion .card-header .btn-link[aria-expanded="false"]:after{
+ margin-right: 9px;
+ font-family: 'FontAwesome';
+ float: left;
+ font-weight: normal;
+ font-size: 12px;
+}
+.accordion .card-header .btn-link[aria-expanded="true"]:after{
+ content: "\f078";
+}
+.accordion .card-header .btn-link[aria-expanded="false"]:after{
+ content: "\f054";
+}
+.btn-addAttribute{
+ width: 20px;
+ height: 20px;
+ background-image: url(/assets/img/icon-add.svg);
+ background-position: center center;
+ background-repeat: no-repeat;
+ vertical-align: sub;
+}
+.btn-addAttribute:hover{
+ background-image: url(/assets/img/icon-add-hover.svg);
+}
+.btn-deleteAttribute{
+ padding: 5px 10px;
+ background: #FFE6E7;
+ border: solid .5px #FFC9CB;
+ border-radius: 2px;
+ color: #FF6469;
+ font-size: 10px;
+
+}
+.source-button{
+ position: absolute;
+ z-index: 9999999;
+ top: 69px;
+ left: 50%;
+}
+/*jointjs paper*/
+/* #board-paper {
+ position: relative;
+ border: 1px solid gray;
+ display: inline-block;
+ background: transparent;
+ overflow: hidden;
+}
+#board-paper svg {
+ background: transparent;
+}
+#board-paper svg .link {
+ z-index: 2;
+}
+.html-element {
+ position: absolute;
+ background: #F4F9FE;
+ pointer-events: none;
+ -webkit-user-select: none;
+ z-index: 2;
+} */
diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/source-view/source-view.component.html b/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/source-view/source-view.component.html
new file mode 100644
index 000000000..2a558517c
--- /dev/null
+++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/source-view/source-view.component.html
@@ -0,0 +1,80 @@
+<header>
+ <div class="row m-0">
+ <div class="col pl-0">
+ <p class="logo mb-0"></p>
+ <nav aria-label="breadcrumb">
+ <ol class="breadcrumb mb-0">
+ <li class="breadcrumb-item">
+ <a href="#">CBA Packages</a>
+ </li>
+ <li class="breadcrumb-item">
+ <a href="#">Package Name</a>
+ </li>
+ <li class="breadcrumb-item active" aria-current="page">
+ <p class="mb-0">Topology View</p>
+ </li>
+ </ol>
+ </nav>
+ </div>
+ <div class="col pr-0 text-right">
+ <ul class="topology-actions">
+ <li>
+ <div class="btn-group" role="group" aria-label="Basic example">
+ <a href="#" role="button" aria-pressed="true" class="btn-topology-action float tooltip-bottom"
+ data-tooltip="Preview">
+ <i class="fa fa-eye"></i>
+ </a>
+ <a href="#" role="button" aria-pressed="true" class="btn-topology-action float tooltip-bottom"
+ data-tooltip="Download">
+ <i class="fa fa-download"></i>
+ </a>
+ <a href="#" role="button" aria-pressed="true" class="btn-topology-action float tooltip-bottom"
+ data-tooltip="Share">
+ <i class="fa fa-share-square"></i>
+ </a>
+ </div>
+ </li>
+ <li>
+ <div class="dropdown">
+ <input class="dropdown-toggle" type="text">
+ <div class="dropdown-text">Save</div>
+ <ul class="dropdown-content">
+ <li>
+ <a href="">Save</a>
+ </li>
+ <li>
+ <a href="">Save &amp; Deploy</a>
+ </li>
+ </ul>
+ </div>
+ </li>
+ </ul>
+
+
+ </div>
+ </div>
+</header>
+<div class="source-button editBar">
+ <div class="btn-group viewBtns" role="group">
+ <button (click)="convertAndOpenInDesingerView()" type="button" class="btn btn-secondary topologySource">Designer</button>
+ <button type="button"
+ class="btn btn-secondary topologyView active">Scripting</button>
+ </div>
+</div>
+<ng-sidebar-container class="sidebar-container">
+ <!-- Controller SideBar -->
+ <ng-sidebar [(opened)]="controllerSideBar" [sidebarClass]="'demo-sidebar controllerSidebar container-fluid'"
+ [mode]="'push'" #sidebarLeft>
+ <div class="row">
+
+ <h1 class="col-12">Actions</h1>
+
+
+ </div>
+ </ng-sidebar>
+<div ng-sidebar-content id="board-paper">
+ <ace-editor [(text)]="content" [mode]="'json'" [autoUpdateContent]="true" [durationBeforeCallback]="1000"
+ [theme]="'tomorrow_night_bright'" #editor style="height:500px">
+ </ace-editor>
+
+ </div>
diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/source-view/source-view.component.ts b/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/source-view/source-view.component.ts
new file mode 100644
index 000000000..34194e42f
--- /dev/null
+++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/source-view/source-view.component.ts
@@ -0,0 +1,45 @@
+import { Component, OnInit, OnDestroy } from '@angular/core';
+import { DesignerStore } from '../designer.store';
+import { PackageCreationUtils } from '../../package-creation/package-creation.utils';
+import { RouterLink, Router } from '@angular/router';
+import { Subject } from 'rxjs';
+
+@Component({
+ selector: 'app-designer-source-view',
+ templateUrl: './source-view.component.html',
+ styleUrls: ['./source-view.component.css']
+})
+export class DesignerSourceViewComponent implements OnInit, OnDestroy {
+
+ content = '';
+ lang = 'json';
+ private controllerSideBar: boolean;
+ private ngUnsubscribe = new Subject();
+
+ constructor(private store: DesignerStore,
+ private packageCreationUtils: PackageCreationUtils,
+ private router: Router) {
+ this.controllerSideBar = true;
+ }
+
+ ngOnInit() {
+ this.store.state$.subscribe(
+ state => {
+ console.log(state);
+ this.content = this.packageCreationUtils.transformToJson(state.template);
+ });
+
+ }
+
+ convertAndOpenInDesingerView() {
+ // TODO validate json against scheme
+ console.log('convertAndOpenInDesingerView ...', this.content);
+ this.store.saveSourceContent(this.content);
+ this.router.navigateByUrl('/packages/designer');
+ }
+
+ ngOnDestroy() {
+ this.ngUnsubscribe.next();
+ this.ngUnsubscribe.complete();
+ }
+}
diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/model/package-dashboard.state.ts b/cds-ui/designer-client/src/app/modules/feature-modules/packages/model/package-dashboard.state.ts
index 638e68c06..b010f7a69 100644
--- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/model/package-dashboard.state.ts
+++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/model/package-dashboard.state.ts
@@ -20,9 +20,21 @@ limitations under the License.
*/
-import {BluePrintDetailModel} from './BluePrint.detail.model';
+import { BluePrintDetailModel } from './BluePrint.detail.model';
+import { Mapping, Scripts, Template } from '../package-creation/mapping-models/CBAPacakge.model';
-export class PackageDashboardState {
+export class PackageDashboardState {
configuration: BluePrintDetailModel;
+ public scripts: Scripts;
+ public templates: Template;
+ public mapping: Mapping;
+ public imports: Map<string, string>;
+
+ constructor() {
+ this.scripts = new Scripts();
+ this.templates = new Template();
+ this.mapping = new Mapping();
+ this.imports = new Map<string, string>();
+ }
}
diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/creationModes/DesignerCreationMode.ts b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/creationModes/DesignerCreationMode.ts
index b44e844be..e1efc3c22 100644
--- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/creationModes/DesignerCreationMode.ts
+++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/creationModes/DesignerCreationMode.ts
@@ -7,6 +7,7 @@ import { PackageCreationUtils } from '../package-creation.utils';
export class DesignerCreationMode extends PackageCreationModes {
+ // Refactor methods params to be in constructor level
constructor() {
super();
}
@@ -15,6 +16,7 @@ export class DesignerCreationMode extends PackageCreationModes {
this.addToscaMetaDataFile(cbaPackage.metaData);
this.createDefinitionsFolder(cbaPackage, packageCreationUtils);
this.addScriptsFolder(cbaPackage.scripts);
+ this.addTemplateFolder(cbaPackage);
}
private addScriptsFolder(scripts: Scripts) {
@@ -23,28 +25,50 @@ export class DesignerCreationMode extends PackageCreationModes {
});
}
+ private addTemplateFolder(cbaPackage: CBAPackage) {
+ // Create Template Files Folder
+ cbaPackage.templates.files.forEach((value, key) => {
+ FilesContent.putData(key, value);
+ });
+ // Create Mapping Files Folder
+ cbaPackage.mapping.files.forEach((value, key) => {
+ FilesContent.putData(key, value);
+ });
+ }
+
private createDefinitionsFolder(cbaPackage: CBAPackage, packageCreationUtils: PackageCreationUtils) {
cbaPackage.definitions.imports.forEach((valueOfFile, key) => {
FilesContent.putData(key, valueOfFile);
});
- const filenameEntry = 'Definitions/vLB_CDS.json';
+ const filenameEntry = 'Definitions/blueprint.json';
const vlbDefinition: VlbDefinition = new VlbDefinition();
const metadata: Metadata = new Metadata();
metadata.template_author = 'Shaaban Ebrahim';
metadata.template_name = cbaPackage.metaData.name;
- metadata.template_tags = cbaPackage.metaData.tags;
metadata.template_version = cbaPackage.metaData.version;
metadata['author-email'] = 'shaaban.eltanany.ext@orange.com';
metadata['user-groups'] = 'test';
- cbaPackage.definitions.metaDataTab.mapOfCustomKey.forEach((customKeyValue, key) => {
+ cbaPackage.metaData.mapOfCustomKey.forEach((customKeyValue, key) => {
metadata[key] = customKeyValue;
});
+ // create Tags
+ let fullTags = '';
+ let setCount = 0;
+ cbaPackage.metaData.templateTags.forEach(val => {
+ setCount++;
+ if (setCount === cbaPackage.metaData.templateTags.size) {
+ fullTags += val;
+ } else {
+ fullTags += val + ', ';
+ }
+ });
+ metadata.template_tags = fullTags;
vlbDefinition.metadata = metadata;
const files: Import[] = [];
cbaPackage.definitions.imports.forEach((valueOfFile, key) => {
- files.push({ file: valueOfFile });
+ files.push({ file: key });
});
console.log(vlbDefinition);
vlbDefinition.imports = files;
diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/creationModes/PackageCreationModes.ts b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/creationModes/PackageCreationModes.ts
index 2d234958c..8ccf0c39e 100644
--- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/creationModes/PackageCreationModes.ts
+++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/creationModes/PackageCreationModes.ts
@@ -11,7 +11,7 @@ export abstract class PackageCreationModes {
public static setEntryPoint(metaDataTab: MetaDataTabModel) {
if (metaDataTab.mode.startsWith(ModeType.Designer)) {
- metaDataTab.entryFileName = 'Definitions/vLB_CDS.json';
+ metaDataTab.entryFileName = 'Definitions/blueprint.json';
} else {
// TODO Not implemented
metaDataTab.entryFileName = '';
@@ -31,6 +31,16 @@ export abstract class PackageCreationModes {
}
getValueOfMetaData(metaDataTab: MetaDataTabModel): string {
+ let tags = '';
+ let count = 0;
+ for (const tag of metaDataTab.templateTags) {
+ count++;
+ if (count === metaDataTab.templateTags.size) {
+ tags += tag;
+ } else {
+ tags += tag + ', ';
+ }
+ }
return 'TOSCA-Meta-File-Version: 1.0.0\n' +
'CSAR-Version: 1.0\n' +
'Created-By: Shaaban Ebrahim <shaaban.eltanany.ext@orange.con>\n' +
@@ -38,7 +48,7 @@ export abstract class PackageCreationModes {
'Template-Name:' + metaDataTab.name + '\n' +
'Template-Version:' + metaDataTab.version + '\n' +
'Template-Type: ' + metaDataTab.mode + '\n' +
- 'Template-Tags:' + metaDataTab.tags;
+ 'Template-Tags:' + tags;
}
diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/dsl-definitions-tab/dsl-definitions-tab.component.html b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/dsl-definitions-tab/dsl-definitions-tab.component.html
index 6fb1dcfd8..a67d12bcf 100644
--- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/dsl-definitions-tab/dsl-definitions-tab.component.html
+++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/dsl-definitions-tab/dsl-definitions-tab.component.html
@@ -1,5 +1,5 @@
<ace-editor [(text)]="dslDefinition.content" [mode]="'javascript'" [autoUpdateContent]="true"
- [durationBeforeCallback]="1000" [theme]="'tomorrow_night_bright'" #editor style="height:300px;">
+ [durationBeforeCallback]="1000" (textChanged)="textChanged($event)" [theme]="'tomorrow_night_bright'" #editor style="height:300px;">
</ace-editor>
-<!-- <app-source-editor [lang]="'javascript'" (textChanged)="textChanged($event)" [(text)]="dslDefinition.content"></app-source-editor> --> \ No newline at end of file
+<!-- <app-source-editor [lang]="'javascript'" (textChanged)="textChanged($event)" [(text)]="dslDefinition.content"></app-source-editor> -->
diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/dsl-definitions-tab/dsl-definitions-tab.component.ts b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/dsl-definitions-tab/dsl-definitions-tab.component.ts
index 7171e730e..1297bc14e 100644
--- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/dsl-definitions-tab/dsl-definitions-tab.component.ts
+++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/dsl-definitions-tab/dsl-definitions-tab.component.ts
@@ -1,6 +1,6 @@
-import { Component, OnInit } from '@angular/core';
-import { DslDefinition } from '../mapping-models/CBAPacakge.model';
-import { PackageCreationStore } from '../package-creation.store';
+import {Component, OnInit} from '@angular/core';
+import {DslDefinition} from '../mapping-models/CBAPacakge.model';
+import {PackageCreationStore} from '../package-creation.store';
@Component({
selector: 'app-dsl-definitions-tab',
@@ -16,11 +16,15 @@ export class DslDefinitionsTabComponent implements OnInit {
}
ngOnInit() {
- this.packageCreationStore.changeDslDefinition(this.dslDefinition);
+ this.packageCreationStore.state$.subscribe(cbaPackage => {
+ if (cbaPackage && cbaPackage.definitions && cbaPackage.definitions.dslDefinition) {
+ this.dslDefinition.content = cbaPackage.definitions.dslDefinition.content;
+ }
+ });
}
textChanged(event) {
- console.log('event changed');
+ this.packageCreationStore.changeDslDefinition(this.dslDefinition);
}
}
diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/imports-tab/imports-tab.component.html b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/imports-tab/imports-tab.component.html
index 344e7f599..d80ed16b2 100644
--- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/imports-tab/imports-tab.component.html
+++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/imports-tab/imports-tab.component.html
@@ -5,7 +5,7 @@
<a class="enter-link" href="#"><i class="icon-enter"></i></a>
</div>
<span class="import-container-span">Or you can also <a href="#" data-toggle="modal"
- data-target="#exampleModal">Import File</a></span>
+ data-target="#importModal">Import File</a></span>
</div>
@@ -47,7 +47,7 @@
<div [id]="'id-'+mapIndex" class="collapse" [attr.aria-labelledby]="'head-'+mapIndex"
data-parent="#accordion">
<div class="card-body">
- <ace-editor [(text)]="file.value" [mode]="'json'" [autoUpdateContent]="true"
+ <ace-editor [(text)]="file.value" (textChange)="textChanges($event,file.key)" [mode]="'json'" [autoUpdateContent]="true"
[durationBeforeCallback]="1000" [theme]="'tomorrow_night_bright'" #editor
style="height:300px;">
</ace-editor>
@@ -82,12 +82,12 @@
</div>
-<div class="modal fade" id="exampleModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel"
+<div class="modal fade" id="importModal" tabindex="-1" role="dialog" aria-labelledby="importModalLabel"
aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
- <h5 class="modal-title" id="exampleModalLabel">Import File</h5>
+ <h5 class="modal-title" id="importModalLabel">Import File</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
@@ -130,4 +130,4 @@
</div>
</div>
</div>
-</div> \ No newline at end of file
+</div>
diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/imports-tab/imports-tab.component.ts b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/imports-tab/imports-tab.component.ts
index 106fe3090..dc0cf7f3b 100644
--- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/imports-tab/imports-tab.component.ts
+++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/imports-tab/imports-tab.component.ts
@@ -18,6 +18,8 @@ export class ImportsTabComponent implements OnInit {
public files: NgxFileDropEntry[] = [];
constructor(private packageCreationStore: PackageCreationStore, private packageCreationUtils: PackageCreationUtils) {
+ }
+ ngOnInit(): void {
this.packageCreationStore.state$.subscribe(cbaPackage => {
if (cbaPackage.definitions && cbaPackage.definitions.imports && cbaPackage.definitions.imports.size > 0) {
this.definitionFiles = cbaPackage.definitions.imports;
@@ -25,10 +27,6 @@ export class ImportsTabComponent implements OnInit {
});
}
- ngOnInit(): void {
- // TODO
- }
-
public dropped(files: NgxFileDropEntry[]) {
this.files = files;
for (const droppedFile of files) {
@@ -74,4 +72,8 @@ export class ImportsTabComponent implements OnInit {
resetTheUploadedFiles() {
this.uploadedFiles = [];
}
+
+ textChanges(code: any, key: string) {
+ this.packageCreationStore.addDefinition(key, code);
+ }
}
diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/mapping-models/CBAPacakge.model.ts b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/mapping-models/CBAPacakge.model.ts
index d94a64ca3..a37339d90 100644
--- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/mapping-models/CBAPacakge.model.ts
+++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/mapping-models/CBAPacakge.model.ts
@@ -1,8 +1,10 @@
import {MetaDataTabModel} from './metadata/MetaDataTab.model';
+
+
export class Definition {
- public metaDataTab: MetaDataTabModel;
+ // public metaDataTab: MetaDataTabModel;
public imports: Map<string, string>;
public dslDefinition: DslDefinition;
@@ -10,7 +12,7 @@ export class Definition {
constructor() {
this.imports = new Map<string, string>();
- this.metaDataTab = new MetaDataTabModel();
+ // this.metaDataTab = new MetaDataTabModel();
this.dslDefinition = new DslDefinition();
}
@@ -19,10 +21,10 @@ export class Definition {
return this;
}
- public setMetaData(metaDataTab: MetaDataTabModel) {
- this.metaDataTab = metaDataTab;
- return this;
- }
+ // public setMetaData(metaDataTab: MetaDataTabModel) {
+ // this.metaDataTab = metaDataTab;
+ // return this;
+ // }
public setDslDefinition(dslDefinition: DslDefinition): Definition {
this.dslDefinition = dslDefinition;
@@ -34,6 +36,23 @@ export class DslDefinition {
content: string;
}
+export class Base {
+ public files: Map<string, string>;
+
+ constructor() {
+ this.files = new Map<string, string>();
+ }
+
+ public setContent(key: string, value: string) {
+ this.files.set(key, value);
+ return this;
+ }
+
+ public getValue(key: string): string {
+ return this.files.get(key);
+ }
+}
+
export class Scripts {
public files: Map<string, string>;
@@ -59,6 +78,13 @@ export class Template {
this.files.set(key, value);
return this;
}
+
+ public getValue(key: string): string {
+ return this.files.get(key);
+ }
+}
+
+export class Mapping extends Base {
}
export class CBAPackage {
@@ -67,6 +93,7 @@ export class CBAPackage {
public definitions: Definition;
public scripts: Scripts;
public templates: Template;
+ public mapping: Mapping;
constructor() {
@@ -74,6 +101,7 @@ export class CBAPackage {
this.scripts = new Scripts();
this.metaData = new MetaDataTabModel();
this.templates = new Template();
+ this.mapping = new Mapping();
}
diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/mapping-models/ResourceDictionary.model.ts b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/mapping-models/ResourceDictionary.model.ts
new file mode 100644
index 000000000..558d1c7d0
--- /dev/null
+++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/mapping-models/ResourceDictionary.model.ts
@@ -0,0 +1,23 @@
+import { JsonObject, JsonProperty } from 'json2typescript';
+
+@JsonObject('ResourceDictionary')
+export class ResourceDictionary {
+ @JsonProperty()
+ name: string;
+ @JsonProperty('creation_date')
+ creationDate: string;
+ @JsonProperty('data_type')
+ dataType: string;
+ @JsonObject('definition')
+ definition?: any | null;
+ @JsonProperty('description')
+ description: string;
+ @JsonProperty('entry_schema')
+ entrySchema: string;
+ @JsonProperty('esource_dictionary_group')
+ resourceDictionaryGroup: string;
+ @JsonProperty('tags')
+ tags: string;
+ @JsonProperty('upadted_by')
+ updatedBy: string;
+}
diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/mapping-models/definitions/VlbDefinition.ts b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/mapping-models/definitions/VlbDefinition.ts
index c4f3ee8bd..630baa1ac 100644
--- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/mapping-models/definitions/VlbDefinition.ts
+++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/mapping-models/definitions/VlbDefinition.ts
@@ -1,5 +1,9 @@
import { Any, JsonObject, JsonProperty } from 'json2typescript';
+@JsonObject('topology_template')
+export class TemplateTopology {
+ public content: string;
+}
@JsonObject
export class VlbDefinition {
@@ -10,14 +14,15 @@ export class VlbDefinition {
imports: Import[];
// tslint:disable-next-line: variable-name
dsl_definitions: DslContent;
- // topology_template: TopologyTemplate;
+ // tslint:disable-next-line: variable-name
+ topology_template: TemplateTopology;
}
@JsonObject('dsl_definitions')
export class DslContent {
}
-
+// Refactor varaibles name and use JsonConverteri
@JsonObject('metadata')
export class Metadata {
@JsonProperty('template_author')
@@ -38,6 +43,8 @@ export class Metadata {
@JsonProperty('dictionary_group')
// tslint:disable-next-line:variable-name
dictionary_group: string;
+ @JsonProperty('template_tags')
+ templateTags: string;
/* @JsonProperty('custom_keys', {String}, false)
diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/mapping-models/mappingAdapter.model.ts b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/mapping-models/mappingAdapter.model.ts
new file mode 100644
index 000000000..b4de578b9
--- /dev/null
+++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/mapping-models/mappingAdapter.model.ts
@@ -0,0 +1,45 @@
+import { ResourceDictionary } from './ResourceDictionary.model';
+import { JsonObject, JsonProperty, JsonConvert } from 'json2typescript';
+
+// Convert ResourceDictionary object to store Mapping.
+export class MappingAdapter {
+
+ constructor(
+ private resourceDictionary: ResourceDictionary,
+ private dependancies: Map<string, Array<string>>,
+ private dependanciesSource: Map<string, string>) { }
+
+ ToMapping(): Mapping {
+ const mapping = new Mapping();
+ mapping.name = this.resourceDictionary.name;
+ mapping.dictionaryName = this.resourceDictionary.name;
+ mapping.property = this.resourceDictionary.definition.property;
+ mapping.inputParam = false;
+ mapping.dictionarySource = this.dependanciesSource.get(mapping.name);
+ if (this.dependancies.get(mapping.name)) {
+ mapping.dependencies = this.dependancies.get(mapping.name);
+ } else {
+ mapping.dependencies = [];
+ }
+ mapping.version = 0;
+ return mapping;
+ }
+}
+
+@JsonObject('Mapping')
+export class Mapping {
+ @JsonProperty('name')
+ name: string;
+ @JsonProperty()
+ property: any;
+ @JsonProperty('input-param', Boolean)
+ inputParam: boolean;
+ @JsonProperty('dictionary-name')
+ dictionaryName: string;
+ @JsonProperty('dictionary-source')
+ dictionarySource: string;
+ @JsonProperty()
+ dependencies: string[];
+ @JsonProperty()
+ version: number;
+}
diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/mapping-models/metadata/MetaDataTab.model.ts b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/mapping-models/metadata/MetaDataTab.model.ts
index df723d58f..7200e1210 100644
--- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/mapping-models/metadata/MetaDataTab.model.ts
+++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/mapping-models/metadata/MetaDataTab.model.ts
@@ -26,10 +26,15 @@ export class MetaDataTabModel {
name: string;
description: string;
version: string;
- tags: string;
mapOfCustomKey: Map<string, string> = new Map<string, string>();
entryFileName: string;
templateName: string;
+ templateTags: Set<string> = new Set<string>();
+
+ setCustomKey(mapOfCustomKey: Map<string, string>) {
+ this.mapOfCustomKey = mapOfCustomKey;
+ return this;
+ }
}
diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/metadata-tab/metadata-tab.component.css b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/metadata-tab/metadata-tab.component.css
index e69de29bb..856f458f0 100644
--- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/metadata-tab/metadata-tab.component.css
+++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/metadata-tab/metadata-tab.component.css
@@ -0,0 +1,4 @@
+.fa-times-circle:hover {
+ cursor: pointer;
+ color: #1f64c3
+} \ No newline at end of file
diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/metadata-tab/metadata-tab.component.html b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/metadata-tab/metadata-tab.component.html
index 09393c403..89724be79 100644
--- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/metadata-tab/metadata-tab.component.html
+++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/metadata-tab/metadata-tab.component.html
@@ -2,13 +2,13 @@
<div class="single-line">
<label class="label-name">Mode</label>
<label name="trst" *ngFor="let mode of modes; let i = index">
- <input class="form-check-input" [(ngModel)]="metaDataTab.mode" type="radio"
- name="exampleRadios" id="exampleRadios1" value={{mode.name}}>
+ <input class="form-check-input" [(ngModel)]="modeType" type="radio" name="radioMode" id="radioMode"
+ [value]="mode.name">
<span>
- <i [className]="mode.style" aria-hidden="true" [id]="mode.name"></i>
+ <i [className]="mode.style" aria-hidden="true" [id]="mode.name"></i>
{{mode.name}}
- </span>
+ </span>
</label>
</div>
<div class="single-line">
@@ -20,53 +20,50 @@
<option>Library Instance 3</option>
<option>Library Instance 4</option>
<option>Library Instance 5</option>
- </select>
+ </select>
</div>
</div>
</div>
<div class="card creat-card">
- <div class="single-line-model error">
+ <div class="single-line-model">
<label class="label-name">Name <span>*</span></label>
<div class="label-input">
- <input type="input"
- [(ngModel)]="metaDataTab.name" placeholder="Topology name.vLB.CDS">
+ <input type="input" [readOnly]="!packageNameAndVersionEnables" [(ngModel)]="metaDataTab.name"
+ placeholder="Topology name.vLB.CDS">
</div>
- <div class="model-note-container error-message">
- Package name already exists with this version. Please enter a different name or enter different version number.
- </div>
+ <!--<div class="model-note-container error-message">
+ Package name already exists with this version. Please enter a different name or enter different version
+ number.
+ </div>-->
</div>
-
+
<div class="single-line-model">
<label class="label-name">Version <span>*</span></label>
<div class="label-input">
- <input type="input" [(ngModel)]="metaDataTab.version"
- (input)="validatePackageNameAndVersion()"
- placeholder="Example: 1.0.0">
+ <input type="input" [readOnly]="!packageNameAndVersionEnables" [(ngModel)]="metaDataTab.version"
+ (input)="validatePackageNameAndVersion()" placeholder="Example: 1.0.0">
</div>
<div class="model-note-container error-message">{{errorMessage}}</div>
</div>
<div class="single-line-model">
<label class="label-name">Description</label>
<div class="label-input">
- <input type="input" [(ngModel)]="metaDataTab.description"
- placeholder="Descripe the package">
+ <input type="input" [(ngModel)]="metaDataTab.description" placeholder="Descripe the package">
</div>
</div>
-
+
<div class="single-line-model">
<label class="label-name">tags</label>
<div class="label-input">
- <input type="input" [(ngModel)]="metaDataTab.tags"
- placeholder="Ex., vDNS-CDS">
-
+ <input type="input" (keyup.enter)="addTag($event)" [(ngModel)]="metaDataTab.tags"
+ placeholder="Ex., vDNS-CDS">
+
</div>
<div class="model-note-container tag-notes">Seprate tags with comma or space</div>
<div class="model-note-container tages-container">
- <span class="single-tage">vDNS-CDS <a href="#"> <i class="fa fa-times-circle"></i></a></span>
- <span class="single-tage">vDNS-CDS <a href="#"> <i class="fa fa-times-circle"></i></a></span>
- <span class="single-tage">vDNS-CDS <a href="#"> <i class="fa fa-times-circle"></i></a></span>
- <span class="single-tage">vDNS-CDS <a href="#"> <i class="fa fa-times-circle"></i></a></span>
+ <span *ngFor="let tag of tags" class="single-tage">{{tag}} <i (click)="removeTag(tag)"
+ class="fa fa-times-circle"></i></span>
</div>
</div>
</div>
@@ -75,59 +72,48 @@
<div class="card creat-card">
<div class="single-line">
<h5 class="label-name">
- Custom key
+ Custom key
</h5>
</div>
- <div class="single-custom-key">
- <div class="single-line-custom-key">
- <label class="label-name"><span>1-</span> Name</label>
- <div class="label-input">
- <input name="key" type="input" placeholder="Enter name">
+ <div *ngFor="let map of customKeysMap | keyvalue; let i=index" class="single-custom-key">
+ <div class="single-line-custom-key">
+ <label class="label-name"><span>{{i + 1}}-</span> Name</label>
+ <div class="label-input">
+ <input value="{{map.key}}" name="key" type="input" placeholder="Enter name">
+ </div>
</div>
- </div>
- <div class="single-line-custom-key">
- <label class="label-name">Value</label>
- <div class="label-input">
- <input name="value" type="input"
- placeholder="Enter value">
+ <div class="single-line-custom-key">
+ <label class="label-name">Value</label>
+ <div class="label-input">
+ <input value="{{map.value}}" name="value" type="input" placeholder="Enter value">
+ </div>
</div>
- </div>
- <div class="single-line-custom-key-delete"><button class="custom-key-delete"><i aria-hidden="true" class="icon-delete"></i></button></div>
- </div>
- <div class="single-custom-key">
- <div class="single-line-custom-key">
- <label class="label-name"><span>2-</span> Name</label>
- <div class="label-input">
- <input name="key" type="input" placeholder="Enter name">
- </div>
- </div>
- <div class="single-line-custom-key">
- <label class="label-name">Value</label>
- <div class="label-input">
- <input name="value" type="input"
- placeholder="Enter value">
+ <div class="single-line-custom-key-delete">
+ <button (click)="removeKey($event,map.key)" class="custom-key-delete"><i aria-hidden="true"
+ class="icon-delete"></i></button>
</div>
</div>
- <div class="single-line-custom-key-delete"><button class="custom-key-delete"><i aria-hidden="true" class="icon-delete"></i></button></div>
- </div>
- <div class="single-custom-key">
- <div class="single-line-custom-key">
- <label class="label-name"><span>3-</span> Name</label>
- <div class="label-input">
- <input name="key" type="input" placeholder="Enter name">
+ <div class="single-custom-key">
+ <div class="single-line-custom-key">
+ <label class="label-name"><span>{{customKeysMap.size + 1}}.</span> Name</label>
+ <div class="label-input">
+ <input (keyup.enter)="addCustomKey()" name="key" type="input" class="mapKey"
+ placeholder="Enter name">
+ </div>
</div>
- </div>
- <div class="single-line-custom-key">
- <label class="label-name">Value</label>
- <div class="label-input">
- <input name="value" type="input"
- placeholder="Enter value">
+ <div class="single-line-custom-key">
+ <label class="label-name">Value</label>
+ <div class="label-input">
+ <input (keyup.enter)="addCustomKey()" class="mapValue" name="value" type="input"
+ placeholder="Enter value">
+ </div>
</div>
+ <!-- <div class="single-line-custom-key-delete"><button (click)="removeKey($event)"
+ class="custom-key-delete"><i aria-hidden="true" class="icon-delete"></i></button></div> -->
</div>
- </div>
</div>
</div>
-</div>
+</div> \ No newline at end of file
diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/metadata-tab/metadata-tab.component.ts b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/metadata-tab/metadata-tab.component.ts
index 97040ee90..3a9b7b880 100644
--- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/metadata-tab/metadata-tab.component.ts
+++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/metadata-tab/metadata-tab.component.ts
@@ -1,7 +1,8 @@
-import {Component, OnInit} from '@angular/core';
-import {PackageCreationService} from '../package-creation.service';
-import {MetaDataTabModel} from '../mapping-models/metadata/MetaDataTab.model';
-import {PackageCreationStore} from '../package-creation.store';
+import { Component, OnInit } from '@angular/core';
+import { PackageCreationService } from '../package-creation.service';
+import { MetaDataTabModel } from '../mapping-models/metadata/MetaDataTab.model';
+import { PackageCreationStore } from '../package-creation.store';
+import { ActivatedRoute } from '@angular/router';
@Component({
@@ -10,21 +11,90 @@ import {PackageCreationStore} from '../package-creation.store';
styleUrls: ['./metadata-tab.component.css']
})
export class MetadataTabComponent implements OnInit {
-
+ packageNameAndVersionEnables = true;
counter = 0;
- modes: object[] = [
- {name: 'Designer Mode', style: 'mode-icon icon-designer-mode'},
- {name: 'Scripting Mode', style: 'mode-icon icon-scripting-mode'},
- {name: 'Generic Script Mode', style: 'mode-icon icon-generic-script-mode'}];
+ tags = new Set<string>();
+ customKeysMap = new Map();
+ modes: any[] = [
+ { name: 'Designer Mode', style: 'mode-icon icon-designer-mode' }];
+ /* {name: 'Scripting Mode', style: 'mode-icon icon-scripting-mode'},
+ {name: 'Generic Script Mode', style: 'mode-icon icon-generic-script-mode'}];*/
+ modeType = this.modes[0].name;
private metaDataTab: MetaDataTabModel = new MetaDataTabModel();
private errorMessage: string;
- constructor(private packageCreationService: PackageCreationService, private packageCreationStore: PackageCreationStore) {
+ constructor(
+ private route: ActivatedRoute,
+ private packageCreationService: PackageCreationService,
+ private packageCreationStore: PackageCreationStore
+ ) {
}
ngOnInit() {
- this.packageCreationStore.changeMetaData(this.metaDataTab);
+ this.metaDataTab.templateTags = this.tags;
+ this.metaDataTab.mapOfCustomKey = this.customKeysMap;
+ this.metaDataTab.mode = this.modeType;
+
+ const id = this.route.snapshot.paramMap.get('id');
+ id ? this.packageNameAndVersionEnables = false :
+ this.packageNameAndVersionEnables = true;
+ this.packageCreationStore.state$.subscribe(element => {
+
+ if (element && element.metaData) {
+
+ this.metaDataTab.name = element.metaData.name;
+ this.metaDataTab.version = element.metaData.version;
+ this.metaDataTab.description = element.metaData.description;
+ this.tags = element.metaData.templateTags;
+ this.metaDataTab.templateTags = this.tags;
+ console.log(element);
+ if (element.metaData.mode && element.metaData.mode.includes('DEFAULT')) {
+ this.metaDataTab.mode = 'Designer Mode';
+ this.modeType = this.metaDataTab.mode;
+ }
+
+ this.customKeysMap = element.metaData.mapOfCustomKey;
+ // this.tags = element.metaData.templateTags;
+
+ }
+ });
+ }
+
+ removeTag(value) {
+ // console.log(event);
+ this.tags.delete(value);
+ }
+
+ addTag(event) {
+ const value = event.target.value;
+ console.log(value);
+ if (value && value.trim().length > 0) {
+ event.target.value = '';
+ this.tags.add(value);
+ }
+ }
+
+ removeKey(event, key) {
+ console.log(event);
+ this.customKeysMap.delete(key);
+ }
+
+ addCustomKey() {
+ // tslint:disable-next-line: no-string-literal
+ const key = document.getElementsByClassName('mapKey')[0];
+ // tslint:disable-next-line: no-string-literal
+ const value = document.getElementsByClassName('mapValue')[0];
+
+ // tslint:disable-next-line: no-string-literal
+ if (key['value'] && value['value']) {
+ // tslint:disable-next-line: no-string-literal
+ this.customKeysMap.set(key['value'], value['value']);
+ // tslint:disable-next-line: no-string-literal
+ key['value'] = '';
+ // tslint:disable-next-line: no-string-literal
+ value['value'] = '';
+ }
}
validatePackageNameAndVersion() {
@@ -39,4 +109,8 @@ export class MetadataTabComponent implements OnInit {
}
}
+
+ saveMetaDataToStore() {
+ this.packageCreationStore.changeMetaData(this.metaDataTab);
+ }
}
diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/package-creation.component.html b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/package-creation.component.html
index 906904855..67beca2a1 100644
--- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/package-creation.component.html
+++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/package-creation.component.html
@@ -2,21 +2,21 @@
<div class="new-wrapper">
<div class="container-fluid main-container">
- <header class="page-title">
- <div class="row">
- <h2 class="col m-0">
- <ul class="breadcrumb-header">
- <li>CBA Packages</li>
- <li>Package Name</li>
- </ul>
- </h2>
- <div class="col d-flex justify-content-end header-button-save">
- <button class="float btn btn-sm btn-outline-secondary" disabled>Discard Changes</button>
- <button class="float btn btn-sm btn-primary" (click)="saveBluePrint()">Save</button>
+ <header class="page-title">
+ <div class="row">
+ <h2 class="col m-0">
+ <ul class="breadcrumb-header">
+ <li><a routerLink="/packages">CBA Packages</a></li>
+ <li>Package Name</li>
+ </ul>
+ </h2>
+ <div class="col d-flex justify-content-end header-button-save">
+ <button class="float btn btn-sm btn-outline-secondary" (click)="goBackToDashBorad()">Discard
+ Changes</button>
+ <button class="float btn btn-sm btn-primary" (click)="saveBluePrint()">Save</button>
+ </div>
</div>
- </div>
- </header>
-
+ </header>
<div class="container-fluid body-container">
@@ -39,93 +39,23 @@
</a>
</div>
- <div class="card creat-card view-package-container">
- <div class="row">
- <div class="col-8">
- <div class="row">
- <div class="col d-flex">
- <i class="package-type-icon icon-designer-mode"></i>
- <div class="package-name-container">
- <div class="row">
- <div class="col-12 package-name deployed">
- Package Name
- <span>.vLB.CDS</span>
- <i class="icon-deploy"></i>
- </div>
- <div class="col-12 package-description">
- Last modified Oct 4, 2019 03:48 PM By Ahmed Abbas
- </div>
- </div>
- <!-- <div class="row">
- <div class="col-4">
- <div class="package-view-title">Author Name</div>
- <p>Abdelmuhaimen Seaudi</p>
- </div>
- <div class="col-4">
- <div class="package-view-title">Author Email</div>
- <p>abdelmuhaimen.seaudi@orange.com</p>
- </div>
- <div class="col-4">
- <div class="package-view-title">Contributions</div>
- <ul class="package-contributers">
- <li>
- <button type="button" class="border-fade" data-toggle="tooltip"
- data-placement="bottom"
- title="User name">
- <img src="/assets/img/img-user1.jpeg">
- </button>
- </li>
- <li>
- <button type="button" data-toggle="tooltip" data-placement="bottom"
- title="User name">
- <img src="/assets/img/img-user2.jpg">
- </button>
- </li>
- <li>
- <button type="button" data-toggle="tooltip" data-placement="bottom"
- title="User name">
- <img src="/assets/img/img-user3.jpg">
- </button>
- </li>
- <li>
- <a href="">5 contributors</a>
- </li>
- </ul>
- </div>
- </div> -->
- </div>
- </div>
- </div>
- </div>
- <div class="col-4 package-view-button">
- <button class="btn btn-sm btn-outline-secondary"><i class="fa fa-play-circle"></i> Deploy</button>
- <button class="btn btn-sm btn-primary">Designer Mode</button>
- </div>
- </div>
-
- </div>
<nav class="row">
<!--Nav Tabs-->
<div class="col">
<div class="nav nav-tabs " id="nav-tab" role="tablist">
<a class="nav-item nav-link active" id="nav-metadata-tab" data-toggle="tab"
- href="#nav-metadata"
- role="tab" aria-controls="nav-metadata"
- aria-selected="true">METADATA</a>
+ href="#nav-metadata" role="tab" aria-controls="nav-metadata" aria-selected="false"
+ autofocus #nameit (focusout)="test()">METADATA</a>
<a class="nav-item nav-link" id="nav-template-tab" data-toggle="tab" href="#nav-template"
- role="tab" aria-controls="nav-template"
- aria-selected="false">TEMPLATE & MAPPING</a>
+ role="tab" aria-controls="nav-template" aria-selected="false">TEMPLATE & MAPPING</a>
<a class="nav-item nav-link" id="nav-scripts-tab" data-toggle="tab" href="#nav-scripts"
- role="tab" aria-controls="nav-scripts"
- aria-selected="false">SCRIPTS</a>
+ role="tab" aria-controls="nav-scripts" aria-selected="false">SCRIPTS</a>
<a class="nav-item nav-link" id="nav-imports-tab" data-toggle="tab" href="#nav-imports"
- role="tab" aria-controls="nav-imports"
- aria-selected="false">IMPORTS</a>
+ role="tab" aria-controls="nav-imports" aria-selected="false">IMPORTS</a>
<a class="nav-item nav-link" id="nav-authentication-tab" data-toggle="tab"
- href="#nav-authentication"
- role="tab" aria-controls="nav-authentication"
- aria-selected="false">EXTERNAL SYSTEM AUTHENTICATION PROPERTIES</a>
+ href="#nav-authentication" role="tab" aria-controls="nav-authentication"
+ aria-selected="false">EXTERNAL SYSTEM AUTHENTICATION PROPERTIES</a>
</div>
</div>
@@ -134,24 +64,24 @@
<div class="col">
<div class="tab-content" id="nav-tabContent">
<div class="tab-pane fade show active" id="nav-metadata" role="tabpanel"
- aria-labelledby="nav-metadata-tab">
+ aria-labelledby="nav-metadata-tab">
<app-metadata-tab></app-metadata-tab>
</div>
<div class="tab-pane fade" id="nav-template" role="tabpanel"
- aria-labelledby="nav-template-tab">
+ aria-labelledby="nav-template-tab">
<app-template-mapping></app-template-mapping>
</div>
<div class="tab-pane fade" id="nav-scripts" role="tabpanel"
- aria-labelledby="nav-scripts-tab">
+ aria-labelledby="nav-scripts-tab">
<app-scripts-tab></app-scripts-tab>
</div>
<div class="tab-pane fade" id="nav-imports" role="tabpanel"
- aria-labelledby="nav-imports-tab">
+ aria-labelledby="nav-imports-tab">
<app-imports-tab></app-imports-tab>
</div>
<div class="tab-pane fade" id="nav-authentication" role="tabpanel"
- aria-labelledby="nav-authentication-tab">
+ aria-labelledby="nav-authentication-tab">
<div class="card creat-card">
<div class="editor-container">
<app-dsl-definitions-tab></app-dsl-definitions-tab>
@@ -163,5 +93,5 @@
</div>
</div>
</div>
-</div>
-</div>
+ </div>
+</div> \ No newline at end of file
diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/package-creation.component.ts b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/package-creation.component.ts
index 58c04e83e..42db2688e 100644
--- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/package-creation.component.ts
+++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/package-creation.component.ts
@@ -19,15 +19,17 @@ limitations under the License.
============LICENSE_END============================================
*/
-import { Component, OnInit } from '@angular/core';
-import { FilesContent, FolderNodeElement, MetaDataTabModel } from './mapping-models/metadata/MetaDataTab.model';
+import {Component, ElementRef, OnInit, ViewChild} from '@angular/core';
+import {FilesContent, FolderNodeElement, MetaDataTabModel} from './mapping-models/metadata/MetaDataTab.model';
import * as JSZip from 'jszip';
-import { PackageCreationStore } from './package-creation.store';
-import { Definition } from './mapping-models/CBAPacakge.model';
-import { PackageCreationModes } from './creationModes/PackageCreationModes';
-import { PackageCreationBuilder } from './creationModes/PackageCreationBuilder';
-import { PackageCreationUtils } from './package-creation.utils';
+import {PackageCreationStore} from './package-creation.store';
+import {Definition} from './mapping-models/CBAPacakge.model';
+import {PackageCreationModes} from './creationModes/PackageCreationModes';
+import {PackageCreationBuilder} from './creationModes/PackageCreationBuilder';
+import {PackageCreationUtils} from './package-creation.utils';
+import {MetadataTabComponent} from './metadata-tab/metadata-tab.component';
+import {Router} from '@angular/router';
@Component({
@@ -36,24 +38,33 @@ import { PackageCreationUtils } from './package-creation.utils';
styleUrls: ['./package-creation.component.css']
})
export class PackageCreationComponent implements OnInit {
+
+ // adding initial referencing to designer mode
+
+
+ constructor(private packageCreationStore: PackageCreationStore,
+ private packageCreationUtils: PackageCreationUtils,
+ private router: Router) {
+ }
+
counter = 0;
modes: object[] = [
- { name: 'Designer Mode', style: 'mode-icon icon-designer-mode' },
- { name: 'Scripting Mode', style: 'mode-icon icon-scripting-mode' }];
+ {name: 'Designer Mode', style: 'mode-icon icon-designer-mode'},
+ {name: 'Scripting Mode', style: 'mode-icon icon-scripting-mode'}];
private metaDataTab: MetaDataTabModel = new MetaDataTabModel();
private folder: FolderNodeElement = new FolderNodeElement();
private zipFile: JSZip = new JSZip();
private filesData: any = [];
private definition: Definition = new Definition();
- // adding initial referencing to designer mode
+ @ViewChild(MetadataTabComponent, {static: false})
+ private metadataTabComponent: MetadataTabComponent;
-
- constructor(private packageCreationStore: PackageCreationStore, private packageCreationUtils: PackageCreationUtils) {
- }
+ @ViewChild('nameit', {static: true})
+ private elementRef: ElementRef;
ngOnInit() {
-
+ this.elementRef.nativeElement.focus();
}
saveBluePrint() {
@@ -76,9 +87,10 @@ export class PackageCreationComponent implements OnInit {
saveBluePrintToDataBase() {
this.create();
- this.zipFile.generateAsync({ type: 'blob' })
+ this.zipFile.generateAsync({type: 'blob'})
.then(blob => {
this.packageCreationStore.saveBluePrint(blob);
+ this.router.navigate(['/packages']);
});
}
@@ -88,23 +100,14 @@ export class PackageCreationComponent implements OnInit {
this.zipFile.folder(key.split('/')[0]);
this.zipFile.file(key, value);
});
- /*this.folder.TREE_DATA.forEach((path) => {
- const name = path.name;
- if (path.children) {
- this.zipFile.folder(name);
- path.children.forEach(children => {
- const name2 = children.name;
- if (FilesContent.getMapOfFilesNamesAndContent().has(name2)) {
- this.zipFile.file(name + '/' + name2, FilesContent.getMapOfFilesNamesAndContent().get(name2));
- } else {
- // this.zipFile.file(name2, FilesContent.getMapOfFilesNamesAndContent().get(name2));
- }
-
- });
-
- }
- });*/
+
}
+ test() {
+ this.metadataTabComponent.saveMetaDataToStore();
+ }
+ goBackToDashBorad() {
+ this.router.navigate(['/packages']);
+ }
}
diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/package-creation.service.ts b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/package-creation.service.ts
index 36da6a42f..494c9e555 100644
--- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/package-creation.service.ts
+++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/package-creation.service.ts
@@ -23,9 +23,10 @@ import {Injectable} from '@angular/core';
import {Observable} from 'rxjs';
import {ApiService} from '../../../../common/core/services/api.service';
-import {BlueprintURLs} from '../../../../common/constants/app-constants';
+import {BlueprintURLs, ResourceDictionaryURLs} from '../../../../common/constants/app-constants';
import {PackagesApiService} from '../packages-api.service';
import {PackagesStore} from '../packages.store';
+import { ResourceDictionary } from './mapping-models/ResourceDictionary.model';
@Injectable({
providedIn: 'root'
@@ -62,4 +63,7 @@ export class PackageCreationService {
});
}
+ getTemplateAndMapping(variables: string[]): Observable<ResourceDictionary[]> {
+ return this.api.post(ResourceDictionaryURLs.searchResourceDictionaryByNames, variables);
+ }
}
diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/package-creation.store.ts b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/package-creation.store.ts
index 3dae2e570..0808223cd 100644
--- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/package-creation.store.ts
+++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/package-creation.store.ts
@@ -19,14 +19,15 @@ limitations under the License.
============LICENSE_END============================================
*/
-import {Injectable} from '@angular/core';
+import { Injectable } from '@angular/core';
-import {Store} from '../../../../common/core/stores/Store';
+import { Store } from '../../../../common/core/stores/Store';
-import {CBAPackage, DslDefinition} from './mapping-models/CBAPacakge.model';
-import {PackageCreationService} from './package-creation.service';
-import {FolderNodeElement, MetaDataTabModel} from './mapping-models/metadata/MetaDataTab.model';
-import * as JSZip from 'jszip';
+import { CBAPackage, DslDefinition } from './mapping-models/CBAPacakge.model';
+import { PackageCreationService } from './package-creation.service';
+import { MetaDataTabModel } from './mapping-models/metadata/MetaDataTab.model';
+import { Observable } from 'rxjs';
+import { ResourceDictionary } from './mapping-models/ResourceDictionary.model';
@Injectable({
@@ -34,8 +35,6 @@ import * as JSZip from 'jszip';
})
export class PackageCreationStore extends Store<CBAPackage> {
- private folder: FolderNodeElement = new FolderNodeElement();
- private zipFile: JSZip = new JSZip();
constructor(private packageCreationService: PackageCreationService) {
super(new CBAPackage());
@@ -49,6 +48,13 @@ export class PackageCreationStore extends Store<CBAPackage> {
});
}
+ setCustomKeys(mapOfCustomKey: Map<string, string>) {
+ this.setState({
+ ...this.state,
+ metaData: this.state.metaData.setCustomKey(mapOfCustomKey)
+ });
+ }
+
changeDslDefinition(dslDefinition: DslDefinition) {
this.setState({
@@ -67,7 +73,6 @@ export class PackageCreationStore extends Store<CBAPackage> {
}
addScripts(name: string, content: string) {
-
this.setState({
...this.state,
scripts: this.state.scripts.setScripts(name, content)
@@ -93,4 +98,19 @@ export class PackageCreationStore extends Store<CBAPackage> {
templates: this.state.templates.setTemplates(filePath, fileContent)
});
}
+
+ addMapping(filePath: string, fileContent: string) {
+ this.setState({
+ ...this.state,
+ mapping: this.state.mapping.setContent(filePath, fileContent)
+ });
+ }
+
+ getTemplateAndMapping(variables: string[]): Observable<ResourceDictionary[]> {
+ return this.packageCreationService.getTemplateAndMapping(variables);
+ }
+
+ clear() {
+ this.setState(new CBAPackage());
+ }
}
diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/scripts-tab/scripts-tab.component.html b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/scripts-tab/scripts-tab.component.html
index 824152035..5dd68ed72 100644
--- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/scripts-tab/scripts-tab.component.html
+++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/scripts-tab/scripts-tab.component.html
@@ -24,15 +24,16 @@
aria-expanded="false" class="btn btn-link collapsed" data-toggle="collapse">
<i class="icon-file-code"></i> {{file.key}}
</button>
- <a (click)="removeFile(mapIndex)" class="accordion-delete"><i class="icon-delete"></i></a>
+ <a (click)="removeFile(file.key,mapIndex)" class="accordion-delete"><i
+ class="icon-delete"></i></a>
</h5>
</div>
<div [attr.aria-labelledby]="'head-script-'+mapIndex" [id]="'id-script-'+mapIndex" class="collapse"
data-parent="#accordion-script">
<div class="card-body">
- <ace-editor [(text)]="file.value" [mode]="'kotlin'" [autoUpdateContent]="true"
- [durationBeforeCallback]="1000" [theme]="'tomorrow_night_bright'" #editor
- style="height:300px;">
+ <ace-editor [(text)]="file.value" (textChange)="textChanges($event,file.key)" [mode]="'kotlin'"
+ [autoUpdateContent]="true" [durationBeforeCallback]="1000" [theme]="'tomorrow_night_bright'"
+ #editor style="height:300px;">
</ace-editor>
</div>
</div>
@@ -54,7 +55,7 @@
</button>
</div>
<div class="modal-body">
- <ngx-file-drop accept=".kt" (onFileDrop)="dropped($event)" (onFileLeave)="fileLeave($event)"
+ <ngx-file-drop accept=".kt,.py" (onFileDrop)="dropped($event)" (onFileLeave)="fileLeave($event)"
(onFileOver)="fileOver($event)" dropZoneLabel="Drop files here">
<ng-template let-openFileSelector="openFileSelector" ngx-file-drop-content-tmp>
<div class="folder-upload">
@@ -68,7 +69,7 @@
Files
</button>
</div>
- <div class="folder-upload-type">Allowed file type: Kotlin(Kt)</div>
+ <div class="folder-upload-type">Allowed file type: Kotlin(kt), Python(py)</div>
</ng-template>
</ngx-file-drop>
<div *ngFor="let item of uploadedFiles; let i=index" class="upload-table">
diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/scripts-tab/scripts-tab.component.ts b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/scripts-tab/scripts-tab.component.ts
index eee291bba..5387489a2 100644
--- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/scripts-tab/scripts-tab.component.ts
+++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/scripts-tab/scripts-tab.component.ts
@@ -1,7 +1,6 @@
import { Component, OnInit } from '@angular/core';
import { FileSystemFileEntry, NgxFileDropEntry } from 'ngx-file-drop';
import { PackageCreationStore } from '../package-creation.store';
-import { PackageCreationUtils } from '../package-creation.utils';
import 'ace-builds/src-noconflict/ace';
import 'ace-builds/webpack-resolver';
@@ -17,7 +16,12 @@ export class ScriptsTabComponent implements OnInit {
public files: NgxFileDropEntry[] = [];
private fileNames: Set<string> = new Set();
- constructor(private packageCreationStore: PackageCreationStore, private packageCreationUtils: PackageCreationUtils) {
+ constructor(
+ private packageCreationStore: PackageCreationStore,
+ ) { }
+
+
+ ngOnInit() {
this.packageCreationStore.state$.subscribe(cbaPackage => {
if (cbaPackage.scripts && cbaPackage.scripts.files && cbaPackage.scripts.files.size > 0) {
this.scriptsFiles = cbaPackage.scripts.files;
@@ -25,10 +29,6 @@ export class ScriptsTabComponent implements OnInit {
});
}
-
- ngOnInit() {
- }
-
public dropped(files: NgxFileDropEntry[]) {
this.files = files;
for (const droppedFile of files) {
@@ -43,11 +43,18 @@ export class ScriptsTabComponent implements OnInit {
}
}
- removeFile(fileIndex: number) {
- console.log(this.uploadedFiles[fileIndex]);
- const filename = 'Scripts/' + this.uploadedFiles[fileIndex].name;
- this.packageCreationStore.removeFileFromState(filename);
- this.uploadedFiles.splice(fileIndex, 1);
+ removeFile(filePath: string, FileIndex: number) {
+ const filename = filePath.split('/')[2] || '';
+ // const filename = 'Scripts/' + this.getFileType(this.uploadedFiles[fileIndex].name) + '/' + this.uploadedFiles[fileIndex].name;
+ this.packageCreationStore.removeFileFromState(filePath);
+ // remove from upload files array
+ // tslint:disable-next-line: prefer-for-of
+ for (let i = 0; i < this.uploadedFiles.length; i++) {
+ if (this.uploadedFiles[i].name === filename) {
+ this.uploadedFiles.splice(i, 1);
+ break;
+ }
+ }
}
public fileOver(event) {
@@ -64,7 +71,7 @@ export class ScriptsTabComponent implements OnInit {
droppedFile.file((file: File) => {
const fileReader = new FileReader();
fileReader.onload = (e) => {
- this.packageCreationStore.addScripts('Scripts/' + droppedFile.name,
+ this.packageCreationStore.addScripts('Scripts/' + this.getFileType(droppedFile.name) + '/' + droppedFile.name,
fileReader.result.toString());
};
fileReader.readAsText(file);
@@ -73,7 +80,22 @@ export class ScriptsTabComponent implements OnInit {
}
}
+ getFileType(filename: string): string {
+ let fileType = '';
+ const fileExtension = filename.substring(filename.lastIndexOf('.') + 1);
+ if (fileExtension === 'py') {
+ fileType = 'python';
+ } else if (fileExtension === 'kt') {
+ fileType = 'kotlin';
+ }
+ return fileType;
+ }
+
resetTheUploadedFiles() {
this.uploadedFiles = [];
}
+
+ textChanges(code: any, key: string) {
+ this.packageCreationStore.addScripts(key, code);
+ }
}
diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/TemplateAndMapping.ts b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/TemplateAndMapping.ts
new file mode 100644
index 000000000..abfe4982b
--- /dev/null
+++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/TemplateAndMapping.ts
@@ -0,0 +1,7 @@
+export class TemplateAndMapping {
+ isTemplate = false;
+ isMapping = false;
+
+ constructor() {
+ }
+}
diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/templ-mapp-creation/templ-mapp-creation.component.html b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/templ-mapp-creation/templ-mapp-creation.component.html
index 3c92bc7c7..8a43b010b 100644
--- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/templ-mapp-creation/templ-mapp-creation.component.html
+++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/templ-mapp-creation/templ-mapp-creation.component.html
@@ -17,7 +17,7 @@
<div class="card-header" id="headingOne">
<h5 class="mb-0 d-flex justify-content-between">
<button class="btn btn-link" data-toggle="collapse" data-target="#collapseOne" aria-expanded="true"
- aria-controls="collapseOne">
+ aria-controls="collapseOne">
1. Create Template
</button>
@@ -29,25 +29,24 @@
<div class="single-line">
<label class="label-name">Template Type</label>
<div class="label-input">
- <label name="trst">
- <input class="form-check-input" type="radio" name="exampleRadios" id="exampleRadios1"
- value=Velcoity>
-
+ <label name="trst" (click)="allowedExt=['.vtl']">
+ <input class="form-check-input" [(ngModel)]="templateExt" type="radio"
+ name="exampleRadios" id="exampleRadios1" value=Velcoity>
<span>
Velcoity
</span>
</label>
- <label name="trst">
- <input class="form-check-input" type="radio" name="exampleRadios" id="exampleRadios1"
- value=Velcoity>
+ <label name="trst" (click)="allowedExt=['.j2','.jinja2']">
+ <input class="form-check-input" [(ngModel)]="templateExt" type="radio"
+ name="exampleRadios" id="exampleRadios1" value=Jinja>
<span>
Jinja
</span>
</label>
- <label name="trst">
- <input class="form-check-input" type="radio" name="exampleRadios" id="exampleRadios1"
- value=Velcoity>
+ <label name="trst" (click)="allowedExt=['.kt']">
+ <input class="form-check-input" [(ngModel)]="templateExt" type="radio"
+ name="exampleRadios" id="exampleRadios1" value=Kotlin>
<span>
Kotlin
@@ -55,12 +54,13 @@
</label>
</div>
</div>
- <div class="create-template-import">Use the editor to add parameters or you can also <a href="#"
- data-toggle="modal"
- data-target="#exampleModal">Import
- File</a></div>
+ <div class="create-template-import">Use the editor to add parameters or you can also
+ <a href="#" data-toggle="modal" (click)="allowedExt=[getFileExtension()]"
+ data-target="#templateModal">Import
+ File</a></div>
<div class="editor-container">
- <app-dsl-definitions-tab></app-dsl-definitions-tab>
+ <app-source-editor (textChange)="textChanges($event,templateInfo.fileName)"
+ [(text)]="templateFileContent"></app-source-editor>
</div>
</div>
</div>
@@ -69,7 +69,7 @@
<div class="card-header" id="headingTwo">
<h5 class="mb-0">
<button class="btn btn-link collapsed" data-toggle="collapse" data-target="#collapseTwo"
- aria-expanded="false" aria-controls="collapseTwo">
+ aria-expanded="false" aria-controls="collapseTwo">
2. Manage Mapping
</button>
</h5>
@@ -78,14 +78,15 @@
<div class="card-body">
<h6 class="text-center">Select a source to load config parameters</h6>
<div class="text-center">
- <a href="#" class="mapping-source-load">
+ <a href="#" (click)="getMappingTableFromTemplate($event)" class="mapping-source-load">
<i class="icon-current-template"></i>
- <br/>
+ <br />
<span>Use Current Template Instance</span>
</a>
- <a href="#" data-toggle="modal" data-target="#exampleModal" class="mapping-source-load">
+ <a href="#" (click)="allowedExt=['.csv']" data-toggle="modal" data-target="#templateModal"
+ class="mapping-source-load">
<i class="icon-Upload-attribute"></i>
- <br/>
+ <br />
<div>Upload attribute list</div>
<div class="source-load-note">(Should be comma delimited file)</div>
</a>
@@ -101,37 +102,121 @@
</div>
</div>
+ <div id="mapping-table" [hidden]="resourceDictionaryRes?.length == 0" class="mx-4 my-2">
+ <table datatable [dtOptions]="dtOptions" [dtTrigger]="dtTrigger" class="row-border hover">
+ <thead>
+ <tr>
+ <th>Required</th>
+ <th>Parameter Name</th>
+ <th>Dictionary Name</th>
+ <th>Dictionary Source</th>
+ <th>Dependancies</th>
+ <th>Default</th>
+ <th>Data Type</th>
+ <th>Entry Schema</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr *ngFor="let dict of resourceDictionaryRes">
+ <td>
+ <i *ngIf="dict.definition?.property?.required" class="fa fa-check-square mx-2"></i>
+ <i *ngIf="!dict.definition?.property?.required" class="fa fa-square mx-2"></i>
+ </td>
+ <td>{{ dict.name }}</td>
+ <td>{{ dict.name }}</td>
+ <td>
+ <select class="custom-select" (click)="selectSource(dict,$event)">
+ <option *ngFor="let val of dict.definition.sources | keyvalue">
+ {{initMap(dict.name,val)}}
+ </option>
+
+ </select>
+ </td>
+ <td>
+ <!-- <select class="custom-select">
+ <option *ngFor="let val of getKeys(dependancies)">
+ {{ getValue(dict.name)}}</option>
+
+ </select> -->
+ <input type="text" class="form-control" [ngModel]="getValue(dict.name)">
+ <!-- {{ dict.definition.sources }} -->
+ </td>
+ <td>{{ dict.definition?.property?.default }}</td>
+ <td>{{ dict.definition?.property?.type }}</td>
+ <td>{{ dict.definition?.property['entry_schema'] }}</td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+
+ <div id="mapping-table" [hidden]="mappingRes?.length == 0" class="mx-4 my-2">
+ <table datatable [dtOptions]="dtOptions" [dtTrigger]="resTableDtTrigger" class="row-border hover">
+ <thead>
+ <tr>
+ <th>Required</th>
+ <th>Parameter Name</th>
+ <th>Dictionary Name</th>
+ <th>Dictionary Source</th>
+ <th>Dependancies</th>
+ <th>Default</th>
+ <th>Data Type</th>
+ <th>Entry Schema</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr *ngFor="let dict of mappingRes">
+ <td>
+ <i *ngIf="dict.definition?.property?.required" class="fa fa-check-square mx-2"></i>
+ <i *ngIf="!dict.definition?.property?.required" class="fa fa-square mx-2"></i>
+ </td>
+ <td>{{ dict['name'] }}</td>
+ <td>{{ dict['name'] }}</td>
+ <td>
+ <input type="text" class="form-control" [value]="dict['dictionary-source']"
+ disabled>
+
+ </td>
+ <td>
+ <input type="text" class="form-control" [value]="dict['dependencies']" disabled>
+ <!-- {{ dict.definition.sources }} -->
+ </td>
+ <td>{{ dict['property']['default'] }}</td>
+ <td>{{ dict['property']['type'] }}</td>
+ <td>{{ dict['property']['entry_schema'] }}</td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
</div>
</div>
-
<div class="template-mapping-action">
<button class="btn btn-sm btn-outline-secondary">Cancel</button>
- <button class="btn btn-sm btn-primary">Finish</button>
+ <button (click)="saveToStore()" class="btn btn-sm btn-primary">Finish</button>
</div>
</div>
</div>
-<div class="modal fade" id="exampleModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel"
- aria-hidden="true">
+<div class="modal fade" id="templateModal" tabindex="-1" role="dialog" aria-labelledby="templateModalLabel"
+ aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
- <h5 class="modal-title" id="exampleModalLabel">Import File</h5>
+ <h5 class="modal-title" id="templateModalLabel">Import File</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
- <ngx-file-drop dropZoneLabel="Drop files here" (onFileDrop)="dropped($event)"
- (onFileOver)="fileOver($event)" (onFileLeave)="fileLeave($event)">
+ <ngx-file-drop [accept]="allowedExt" dropZoneLabel="Drop files here" (onFileDrop)="dropped($event)"
+ (onFileOver)="fileOver($event)" (onFileLeave)="fileLeave($event)">
<ng-template ngx-file-drop-content-tmp let-openFileSelector="openFileSelector">
<div class="folder-upload">
- <img src="assets/img/folder-upload.svg"/>
+ <img src="assets/img/folder-upload.svg" />
</div>
<div class="folder-upload-text">
Drag & Drop file
@@ -141,15 +226,17 @@
Files
</button>
</div>
- <div class="folder-upload-type">Allowed file type: json</div>
+ <div class="folder-upload-type">Allowed file type:
+ {{allowedExt}}
+ </div>
</ng-template>
</ngx-file-drop>
<div class="upload-table" *ngFor="let item of uploadedFiles; let i=index">
<table class="table">
<thead>
- <tr>
- <th>Name : {{ item.name }}</th>
- </tr>
+ <tr>
+ <th>Name : {{ item.name }}</th>
+ </tr>
</thead>
</table>
</div>
@@ -157,13 +244,13 @@
<div class="modal-footer">
<button type="button" class="btn btn-sm btn-secondary" data-dismiss="modal"
- (click)="resetTheUploadedFiles()">Cancel
+ (click)="resetTheUploadedFiles()">Cancel
</button>
<button type="button" class="btn btn-sm btn-primary" data-dismiss="modal"
- (click)="setFilesToStore()">
+ (click)="uploadFile();openListView()">
Import
</button>
</div>
</div>
</div>
-</div>
+</div> \ No newline at end of file
diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/templ-mapp-creation/templ-mapp-creation.component.ts b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/templ-mapp-creation/templ-mapp-creation.component.ts
index 752bd510b..628d963ce 100644
--- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/templ-mapp-creation/templ-mapp-creation.component.ts
+++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/templ-mapp-creation/templ-mapp-creation.component.ts
@@ -1,24 +1,121 @@
-import {Component, EventEmitter, OnInit, Output} from '@angular/core';
-import {FileSystemFileEntry, NgxFileDropEntry} from 'ngx-file-drop';
-import {PackageCreationStore} from '../../package-creation.store';
+import { Component, EventEmitter, OnDestroy, OnInit, Output, ViewChild } from '@angular/core';
+import { FileSystemFileEntry, NgxFileDropEntry } from 'ngx-file-drop';
+import { PackageCreationStore } from '../../package-creation.store';
+import { TemplateInfo, TemplateStore } from '../../template.store';
+import { Subject } from 'rxjs';
+import { ResourceDictionary } from '../../mapping-models/ResourceDictionary.model';
+import { DataTableDirective } from 'angular-datatables';
+import { Mapping, MappingAdapter } from '../../mapping-models/mappingAdapter.model';
+import { PackageCreationUtils } from '../../package-creation.utils';
+import { JsonConvert } from 'json2typescript';
@Component({
selector: 'app-templ-mapp-creation',
templateUrl: './templ-mapp-creation.component.html',
styleUrls: ['./templ-mapp-creation.component.css']
})
-export class TemplMappCreationComponent implements OnInit {
+export class TemplMappCreationComponent implements OnInit, OnDestroy {
+ @Output() showListViewParent = new EventEmitter<any>();
public uploadedFiles: FileSystemFileEntry[] = [];
private fileNames: Set<string> = new Set();
-
+ private jsonConvert = new JsonConvert();
public files: NgxFileDropEntry[] = [];
fileName: any;
+ templateInfo = new TemplateInfo();
+ private variables: string[] = [];
+ dtOptions: DataTables.Settings = {};
+ // We use this trigger because fetching the list of persons can be quite long,
+ // thus we ensure the data is fetched before rendering
+ dtTrigger = new Subject();
+ resTableDtTrigger = new Subject();
+ resourceDictionaryRes: ResourceDictionary[] = [];
+ allowedExt = ['.vtl'];
+ @ViewChild(DataTableDirective, { static: false })
+ dtElement: DataTableDirective;
+ MappingAdapter: MappingAdapter;
+ mapping = new Map();
+ templateFileContent: string;
+ templateExt = 'Velcoity';
+ dependancies = new Map<string, Array<string>>();
+ dependanciesSource = new Map<string, string>();
+ mappingRes = [];
+
+
- constructor(private packageCreationStore: PackageCreationStore) {
+ constructor(
+ private packageCreationStore: PackageCreationStore,
+ private templateStore: TemplateStore,
+ private packageCreationUtils: PackageCreationUtils
+ ) {
}
ngOnInit() {
+ this.templateStore.state$.subscribe(templateInfo => {
+ console.log('----------');
+ console.log(templateInfo);
+ this.templateInfo = templateInfo;
+ this.fileName = templateInfo.fileName.split('/')[1];
+ if (templateInfo.type === 'mapping') {
+ this.mappingRes = templateInfo.mapping;
+ this.resourceDictionaryRes = [];
+ this.resTableDtTrigger.next();
+ } else {
+
+ this.templateFileContent = templateInfo.fileContent;
+ }
+ });
+
+ this.dtOptions = {
+ pagingType: 'full_numbers',
+ pageLength: 10,
+ destroy: true,
+ retrieve: true,
+ };
+ }
+
+ getFileExtension() {
+ switch (this.templateExt) {
+ case 'Velcoity':
+ return '.vtl';
+ case 'Koltin':
+ return '.ktl';
+ case 'Jinja':
+ return '.j2';
+ default:
+ return '.vtl';
+ }
+ }
+
+ public getTemplateVariable(fileContent: string) {
+ const variables: string[] = [];
+ const stringsSlittedByBraces = fileContent.split('${');
+ const stringsDefaultByDollarSignOnly = fileContent.split('"$');
+
+ for (let i = 1; i < stringsSlittedByBraces.length; i++) {
+ const element = stringsSlittedByBraces[i];
+ if (element) {
+ const firstElement = element.split('}')[0];
+ if (!variables.includes(firstElement)) {
+ variables.push(firstElement);
+ } else {
+ console.log(firstElement);
+ }
+ }
+ }
+
+ for (let i = 1; i < stringsDefaultByDollarSignOnly.length; i++) {
+ const element = stringsDefaultByDollarSignOnly[i];
+ if (element && !element.includes('$')) {
+ const firstElement = element.split('"')[0]
+ .replace('{', '')
+ .replace('}', '').trim();
+ if (!variables.includes(firstElement)) {
+ variables.push(firstElement);
+ }
+ }
+ }
+ return variables;
}
public dropped(files: NgxFileDropEntry[]) {
@@ -34,24 +131,59 @@ export class TemplMappCreationComponent implements OnInit {
}
}
- removeFile(fileIndex: number) {
- /*const filename = 'Definitions/' + this.uploadedFiles[fileIndex].name;
- this.packageCreationStore.removeFileFromDefinition(filename);
- this.uploadedFiles.splice(fileIndex, 1);*/
+ uploadFile() {
+ this.dependancies.clear();
+ this.dependanciesSource.clear();
+ if (this.allowedExt.includes('.csv')) {
+ this.fetchCSVkeys();
+ } else {
+ this.setTemplateFilesToStore();
+ }
}
- setFilesToStore() {
+ fetchCSVkeys() {
for (const droppedFile of this.uploadedFiles) {
droppedFile.file((file: File) => {
const fileReader = new FileReader();
fileReader.onload = (e) => {
- this.packageCreationStore.addTemplate('Templates/' + this.fileName,
- fileReader.result.toString());
+ this.variables = fileReader.result.toString().split(',');
+ console.log(this.variables);
+ this.getMappingTableFromTemplate(null);
};
fileReader.readAsText(file);
});
+ }
+ this.uploadedFiles = [];
+ }
+ private convertDictionaryToMap(resourceDictionaries: ResourceDictionary[]): Mapping[] {
+ const mapArray: Mapping[] = [];
+ for (const resourceDictionary of resourceDictionaries) {
+ this.MappingAdapter = new MappingAdapter(resourceDictionary, this.dependancies, this.dependanciesSource);
+ mapArray.push(this.MappingAdapter.ToMapping());
}
+ console.log(mapArray);
+ return mapArray;
+ }
+
+ setTemplateFilesToStore() {
+ for (const droppedFile of this.uploadedFiles) {
+ droppedFile.file((file: File) => {
+ const fileReader = new FileReader();
+ fileReader.onload = (e) => {
+ this.templateFileContent = fileReader.result.toString();
+ this.variables = this.getTemplateVariable(this.templateFileContent);
+
+ };
+ fileReader.readAsText(file);
+ });
+ }
+ this.uploadedFiles = [];
+ }
+
+ textChanges(code: any, fileName: string) {
+ // this.packageCreationStore.addTemplate(fileName, code);
+ this.templateFileContent = code;
}
public fileOver(event) {
@@ -61,8 +193,114 @@ export class TemplMappCreationComponent implements OnInit {
public fileLeave(event) {
console.log(event);
}
-
+ //
resetTheUploadedFiles() {
this.uploadedFiles = [];
}
+
+ openListView() {
+ this.showListViewParent.emit('tell parent to open create views');
+ }
+
+ getMappingTableFromTemplate(e) {
+ this.resourceDictionaryRes = [];
+ if (e) {
+ e.preventDefault();
+ }
+ if (this.variables && this.variables.length > 0) {
+ console.log('base');
+ this.packageCreationStore.getTemplateAndMapping(this.variables).subscribe(res => {
+ this.mappingRes = [];
+ this.resourceDictionaryRes = res;
+ console.log(this.resourceDictionaryRes);
+ this.rerender();
+ });
+ }
+ }
+
+ initMap(key, map) {
+ if (!this.dependanciesSource.has(key)) {
+ this.dependanciesSource.set(key, map.key);
+ }
+ return map.key;
+ }
+ saveToStore() {
+ console.log(this.dependancies);
+ console.log(this.dependanciesSource);
+ if (this.fileName) {
+ // Save Mapping to Store
+ if (this.resourceDictionaryRes && this.resourceDictionaryRes.length > 0) {
+ const mapArray = this.convertDictionaryToMap(this.resourceDictionaryRes);
+ this.packageCreationStore.addMapping('Templates/' + this.fileName + '-mapping.json',
+ this.packageCreationUtils.transformToJson(this.jsonConvert.serialize(mapArray)));
+ this.resourceDictionaryRes = [];
+ }
+ // Save Template to store
+ if (this.templateFileContent) {
+ this.packageCreationStore.addTemplate('Templates/' + this.fileName + '-template' + this.getFileExtension(),
+ this.templateFileContent);
+ this.templateFileContent = '';
+ }
+ } else {
+
+ }
+ }
+
+ selectSource(dict, e) {
+ const source = e.target.value;
+ let keyDepend = null;
+ try {
+ keyDepend = dict.definition.sources[source].properties['key-dependencies'] || null;
+ } catch (e) { }
+ console.log(dict);
+ console.log(source);
+ if (keyDepend) {
+ this.dependancies.set(dict.name, keyDepend);
+ } else {
+ // this.dependancies.delete(dict.name);
+ // this.dependanciesSource.delete(dict.name);
+ }
+ this.dependanciesSource.set(dict.name, source);
+ console.log(this.dependancies);
+ console.log(this.dependanciesSource);
+ }
+
+ getKeys(map: Map<string, any>) {
+ return Array.from(map.keys());
+ }
+
+ getValue(key) {
+ return this.dependancies.get(key);
+ }
+
+ rerender(): void {
+ if (this.dtElement.dtInstance) {
+ console.log('rerender');
+ this.dtElement.dtInstance.then((dtInstance: DataTables.Api) => {
+ dtInstance.destroy();
+ this.dtElement.dtOptions = this.dtOptions;
+ this.dtElement.dtTrigger.next();
+ dtInstance.draw();
+ });
+ } else {
+ this.dtTrigger.next();
+ }
+ }
+
+ ngOnDestroy(): void {
+ // Do not forget to unsubscribe the event
+ this.dtTrigger.unsubscribe();
+ }
+}
+
+class DependancyVal {
+ source: string;
+ keyDepend: any;
+ constructor(
+ source: string,
+ keyDepend: any
+ ) {
+ this.source = source;
+ this.keyDepend = keyDepend;
+ }
}
diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/templ-mapp-listing/templ-mapp-listing.component.css b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/templ-mapp-listing/templ-mapp-listing.component.css
index e69de29bb..054b5686e 100644
--- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/templ-mapp-listing/templ-mapp-listing.component.css
+++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/templ-mapp-listing/templ-mapp-listing.component.css
@@ -0,0 +1,3 @@
+.template-mapping-list {
+ cursor: pointer;
+} \ No newline at end of file
diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/templ-mapp-listing/templ-mapp-listing.component.html b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/templ-mapp-listing/templ-mapp-listing.component.html
index ddf06c824..ab97159b6 100644
--- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/templ-mapp-listing/templ-mapp-listing.component.html
+++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/templ-mapp-listing/templ-mapp-listing.component.html
@@ -1,8 +1,6 @@
-
-
- <a (click)="openCreationView()" class="create-template-mapping-button">
- <i class="fa fa-plus"></i> <span>Create</span>
- </a>
+<a *ngIf="isCreate" (click)="openCreationView()" class="create-template-mapping-button">
+ <i class="fa fa-plus"></i> <span>Create</span>
+</a>
<div class="template-mapping-accordion">
@@ -10,8 +8,8 @@
<div class="card">
<div class="card-header" id="headingThree">
<h5 class="mb-0 d-flex justify-content-between">
- <button class="btn btn-link" data-toggle="collapse" data-target="#collapseThree" aria-expanded="true"
- aria-controls="collapseThree">
+ <button class="btn btn-link" data-toggle="collapse" data-target="#collapseThree"
+ aria-expanded="true" aria-controls="collapseThree">
Template and Mapping List
</button>
@@ -19,138 +17,19 @@
</div>
<div id="collapseThree" class="collapse show" aria-labelledby="headingThree" data-parent="#accordion">
- <div class="card-body max-height-list" *ngFor="let file of templates.files | keyvalue; let mapIndex = index">
- <div class="row">
- <div class="col">
- <a href="#" class="template-mapping-list active">{{file.key}}
- <span>Mapping</span>
- <span>Template</span>
- </a>
- </div>
- <!-- <div class="col">
- <a href="#" class="template-mapping-list">vf-module-1
- <span>Mapping</span>
- </a>
- </div>
- <div class="col">
- <a href="#" class="template-mapping-list">vf-module-2
- <span>Mapping</span>
- </a>
- </div>-->
- </div>
- <!-- <div class="row">
- <div class="col">
- <a href="#" class="template-mapping-list">hostname
- <span>Mapping</span>
- <span>Template</span>
- </a>
- </div>
- <div class="col">
- <a href="#" class="template-mapping-list">vf-module-1
- <span>Mapping</span>
- </a>
- </div>
- <div class="col">
- <a href="#" class="template-mapping-list">vf-module-2
- <span>Mapping</span>
- </a>
- </div>
- </div>
- <div class="row">
- <div class="col">
- <a href="#" class="template-mapping-list">hostname
-
- <span>Template</span>
- </a>
- </div>
- <div class="col">
- <a href="#" class="template-mapping-list">vf-module-1
- <span>Template</span>
- </a>
- </div>
- <div class="col">
- <a href="#" class="template-mapping-list">vf-module-2
- <span>Mapping</span>
- <span>Template</span>
- </a>
- </div>
- </div>
- <div class="row">
- <div class="col">
- <a href="#" class="template-mapping-list">hostname
-
- <span>Template</span>
- </a>
- </div>
- <div class="col">
- <a href="#" class="template-mapping-list">vf-module-1
- <span>Mapping</span>
- </a>
- </div>
- <div class="col">
- <a href="#" class="template-mapping-list">vf-module-2
- <span>Mapping</span>
- </a>
- </div>
- </div>
- <div class="row">
- <div class="col">
- <a href="#" class="template-mapping-list">hostname
- <span>Mapping</span>
- <span>Template</span>
- </a>
- </div>
- <div class="col">
- <a href="#" class="template-mapping-list">vf-module-1
- <span>Mapping</span>
- </a>
- </div>
- <div class="col">
- <a href="#" class="template-mapping-list">vf-module-2
- <span>Mapping</span>
- </a>
- </div>
- </div>
+ <div class="card-body max-height-list">
<div class="row">
- <div class="col">
- <a href="#" class="template-mapping-list">hostname
- <span>Mapping</span>
- <span>Template</span>
- </a>
- </div>
- <div class="col">
- <a href="#" class="template-mapping-list">vf-module-1
- <span>Mapping</span>
- </a>
- </div>
- <div class="col">
- <a href="#" class="template-mapping-list">vf-module-2
- <span>Mapping</span>
+ <!-- <div class="col-4" style="color:white" *ngFor="let file of templates.files | keyvalue; let mapIndex = index">-->
+ <div class="col-4" style="color:white" *ngFor="let file of getKeys(templateAndMappingMap)">
+ <a (click)="setSourceCodeEditor(file)" class="template-mapping-list active">{{file}}
+ <span *ngIf="getValue(file).isMapping">Mapping</span>
+ <span *ngIf="getValue(file).isTemplate">Template</span>
</a>
</div>
</div>
- <div class="row">
- <div class="col">
- <a href="#" class="template-mapping-list">hostname
-
- <span>Template</span>
- </a>
- </div>
- <div class="col">
- <a href="#" class="template-mapping-list">vf-module-1
- <span>Template</span>
- </a>
- </div>
- <div class="col">
- <a href="#" class="template-mapping-list">vf-module-2
- <span>Mapping</span>
- <span>Template</span>
- </a>
- </div>
- </div>-->
</div>
</div>
</div>
-
+
</div>
-</div>
+</div> \ No newline at end of file
diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/templ-mapp-listing/templ-mapp-listing.component.ts b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/templ-mapp-listing/templ-mapp-listing.component.ts
index 5cb41c35e..372fbca03 100644
--- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/templ-mapp-listing/templ-mapp-listing.component.ts
+++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/templ-mapp-listing/templ-mapp-listing.component.ts
@@ -1,6 +1,10 @@
-import {Component, EventEmitter, OnInit, Output} from '@angular/core';
-import {PackageCreationStore} from '../../package-creation.store';
-import {Template} from '../../mapping-models/CBAPacakge.model';
+import { Component, EventEmitter, OnInit, Output } from '@angular/core';
+import { PackageCreationStore } from '../../package-creation.store';
+import { Mapping, Template } from '../../mapping-models/CBAPacakge.model';
+import { TemplateInfo, TemplateStore } from '../../template.store';
+import { TemplateAndMapping } from '../TemplateAndMapping';
+import { ActivatedRoute } from '@angular/router';
+
@Component({
selector: 'app-templ-mapp-listing',
@@ -9,21 +13,97 @@ import {Template} from '../../mapping-models/CBAPacakge.model';
})
export class TemplMappListingComponent implements OnInit {
@Output() showCreationViewParentNotification = new EventEmitter<any>();
+ private templateAndMappingMap = new Map<string, TemplateAndMapping>();
private templates: Template;
+ private mapping: Mapping;
+ isCreate = true;
+
+ constructor(
+ private packageCreationStore: PackageCreationStore,
+ private templateStore: TemplateStore,
+ private route: ActivatedRoute
+ ) {
+ }
- constructor(private packageCreationStore: PackageCreationStore) {
+ ngOnInit() {
+ if (this.route.snapshot.paramMap.has('id')) {
+ this.isCreate = false;
+ }
this.packageCreationStore.state$.subscribe(cba => {
if (cba.templates) {
this.templates = cba.templates;
+ this.mapping = cba.mapping;
+ console.log(this.mapping);
+ let templateAndMapping;
+ this.templateAndMappingMap.clear();
+ this.templates.files.forEach((value, key) => {
+ templateAndMapping = new TemplateAndMapping();
+ templateAndMapping.isTemplate = true;
+ const isFromTemplate = true;
+ this.setIsMappingOrTemplate(key, templateAndMapping, isFromTemplate);
+ });
+ this.mapping.files.forEach((value, key) => {
+ templateAndMapping = new TemplateAndMapping();
+ templateAndMapping.isMapping = true;
+ const isFromTemplate = false;
+ this.setIsMappingOrTemplate(key, templateAndMapping, isFromTemplate);
+ });
+ console.log('hello there ');
+ console.log(this.templateAndMappingMap);
}
});
}
- ngOnInit() {
+ private setIsMappingOrTemplate(key: string, templateAndMapping: TemplateAndMapping, isFromTemplate: boolean) {
+ const nameOfFile = key.split('/')[1].split('.')[0].split('-')[0];
+ // const fullName = nameOfFile + ',' + key.split('.');
+ if (this.templateAndMappingMap.has(nameOfFile)) {
+ const templateAndMappingExisted = this.templateAndMappingMap.get(nameOfFile);
+ !isFromTemplate ? templateAndMappingExisted.isMapping = true : templateAndMappingExisted.isTemplate = true;
+ this.templateAndMappingMap.set(nameOfFile, templateAndMappingExisted);
+ } else {
+ this.templateAndMappingMap.set(nameOfFile, templateAndMapping);
+ }
+
}
openCreationView() {
this.showCreationViewParentNotification.emit('tell parent to open create views');
}
+ setSourceCodeEditor(key: string) {
+ const templateKey = 'Templates/' + key + '-template.vtl';
+ this.packageCreationStore.state$.subscribe(cba => {
+ console.log('cba ------');
+ console.log(cba);
+ console.log(key);
+ console.log(this.templateAndMappingMap);
+ if (cba.templates && cba.templates.files.has(templateKey)) {
+ const fileContent = cba.templates.getValue(templateKey.trim());
+ console.log(fileContent);
+ const templateInfo = new TemplateInfo();
+ templateInfo.fileContent = fileContent;
+ templateInfo.fileName = templateKey;
+ this.templateStore.changeTemplateInfo(templateInfo);
+ }
+ const mappingKey = 'Templates/' + key + '-mapping.json';
+ if (cba.mapping && cba.mapping.files.has(mappingKey)) {
+ const obj = JSON.parse(cba.mapping.getValue(mappingKey));
+ const templateInfo = new TemplateInfo();
+ templateInfo.mapping = obj;
+ templateInfo.fileName = mappingKey;
+ templateInfo.type = 'mapping';
+ this.templateStore.changeTemplateInfo(templateInfo);
+ }
+ });
+ }
+
+ getKeys(templateAndMappingMap: Map<string, TemplateAndMapping>) {
+ return Array.from(this.templateAndMappingMap.keys());
+ }
+
+ getValue(file: string) {
+ return this.templateAndMappingMap.get(file);
+ }
+
}
diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/template-mapping.component.html b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/template-mapping.component.html
index 83f3c84c8..f8cfe7a6a 100644
--- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/template-mapping.component.html
+++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/template-mapping.component.html
@@ -1,9 +1,9 @@
-<div *ngIf="!creationView">
- <app-templ-mapp-listing
- (showCreationViewParentNotification)="openCreationView($event)">
- </app-templ-mapp-listing>
+<div *ngIf="!listView">
+ <app-templ-mapp-listing
+ (showCreationViewParentNotification)="openCreationView($event)">
+ </app-templ-mapp-listing>
</div>
-<div *ngIf="creationView">
- <app-templ-mapp-creation></app-templ-mapp-creation>
+<div *ngIf="!creationView">
+ <app-templ-mapp-creation (showListViewParent)="openListView($event)"></app-templ-mapp-creation>
</div>
diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/template-mapping.component.ts b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/template-mapping.component.ts
index 7e9ae1639..106765834 100644
--- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/template-mapping.component.ts
+++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/template-mapping.component.ts
@@ -1,20 +1,37 @@
import { Component, OnInit } from '@angular/core';
+import { ActivatedRoute } from '@angular/router';
+import { PackageCreationStore } from '../package-creation.store';
@Component({
- selector: 'app-template-mapping',
- templateUrl: './template-mapping.component.html',
- styleUrls: ['./template-mapping.component.css']
+ selector: 'app-template-mapping',
+ templateUrl: './template-mapping.component.html',
+ styleUrls: ['./template-mapping.component.css']
})
export class TemplateMappingComponent implements OnInit {
- creationView = false;
+ creationView = true;
+ listView = false;
- constructor() { }
+ constructor(private route: ActivatedRoute, private pakcageStore: PackageCreationStore) {
+ }
- ngOnInit() {
- }
+ ngOnInit() {
+ if (this.route.snapshot.paramMap.has('id')) {
+ console.log('Edit mode');
+ this.creationView = false;
+ this.listView = false;
+ } else {
+ console.log('Create mode');
+ this.pakcageStore.clear();
+ }
+ }
+ openCreationView() {
+ this.creationView = false;
+ this.listView = true;
+ }
- openCreationView() {
- this.creationView = true;
- }
+ openListView() {
+ this.listView = false;
+ this.creationView = false;
+ }
}
diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template.store.ts b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template.store.ts
new file mode 100644
index 000000000..9c8775514
--- /dev/null
+++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template.store.ts
@@ -0,0 +1,58 @@
+/*
+============LICENSE_START==========================================
+===================================================================
+Copyright (C) 2019 Orange. All rights reserved.
+===================================================================
+
+Unless otherwise specified, all software contained herein is licensed
+under the Apache License, Version 2.0 (the License);
+you may not use this software 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============================================
+*/
+
+import { Injectable } from '@angular/core';
+
+import { Store } from '../../../../common/core/stores/Store';
+
+
+export class TemplateInfo {
+ fileName: string;
+ fileContent: string;
+ type: string;
+ mapping = [];
+
+
+ constructor() {
+ this.fileName = '';
+ this.fileContent = '';
+ this.type = '';
+ }
+
+
+}
+
+@Injectable({
+ providedIn: 'root'
+})
+export class TemplateStore extends Store<TemplateInfo> {
+
+
+ constructor() {
+ super(new TemplateInfo());
+ }
+
+ changeTemplateInfo(templateInfo: TemplateInfo) {
+ this.setState(templateInfo);
+ }
+
+
+}
diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/packages-dashboard/package-list/package-list.component.html b/cds-ui/designer-client/src/app/modules/feature-modules/packages/packages-dashboard/package-list/package-list.component.html
index 7f6c0a6f4..9322ee783 100644
--- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/packages-dashboard/package-list/package-list.component.html
+++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/packages-dashboard/package-list/package-list.component.html
@@ -7,7 +7,8 @@
</div>
<div class="card-footer row">
<div class="col">
- <a routerLink="/packages/createPackage" role="button" aria-pressed="true" class="btn-create-package float">Create
+ <a routerLink="/packages/createPackage" role="button" aria-pressed="true"
+ class="btn-create-package float">Create
</a>
</div>
<div class="col">
@@ -25,10 +26,11 @@
<div class="card-body">
<div class="row">
<div class="col-9 pr-0">
- <h5 class="card-title" [routerLink]="['/packages/package', bluePrint.id]" (click)="testDispatch(bluePrint)">
+ <a class="card-title" [routerLink]="['/packages/package', bluePrint.id]"
+ (click)="testDispatch(bluePrint)">
<img class="icon-deployed" src="/assets/img/icon-deploy.svg">
{{bluePrint.artifactName}}
- </h5>
+ </a>
</div>
<div class="col-3">
@@ -56,25 +58,24 @@
<div class="row">
<div class="col">
<p class="mb-0">Last modified {{ bluePrint.createdDate | date:'short' }}
- </p>
- <p>By {{bluePrint.updatedBy}}</p>
+ </p>
+ <p>By {{bluePrint.updatedBy}}</p>
<ul class="package-contributers">
<li>
<button type="button" class="border-fade" data-toggle="tooltip"
- data-placement="bottom"
- title="User name">
+ data-placement="bottom" title="User name">
<img src="/assets/img/img-user1.jpeg">
</button>
</li>
<li>
<button type="button" data-toggle="tooltip" data-placement="bottom"
- title="User name">
+ title="User name">
<img src="/assets/img/img-user2.jpg">
</button>
</li>
<li>
<button type="button" data-toggle="tooltip" data-placement="bottom"
- title="User name">
+ title="User name">
<img src="/assets/img/img-user3.jpg">
</button>
</li>
@@ -101,4 +102,4 @@
</div>
</div>
-</div>
+</div> \ No newline at end of file
diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/packages.module.ts b/cds-ui/designer-client/src/app/modules/feature-modules/packages/packages.module.ts
index 7935e12a3..66c7b498a 100644
--- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/packages.module.ts
+++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/packages.module.ts
@@ -1,33 +1,34 @@
-import {NgModule} from '@angular/core';
-import {CommonModule, JsonPipe} from '@angular/common';
-import {ApiService} from '../../../common/core/services/api.typed.service';
-import {PackagesRoutingModule} from './packages.routing.module';
-import {NgbPaginationModule} from '@ng-bootstrap/ng-bootstrap';
-import {SharedModulesModule} from '../../shared-modules/shared-modules.module';
-import {PackagesDashboardComponent} from './packages-dashboard/packages-dashboard.component';
-import {PackageListComponent} from './packages-dashboard/package-list/package-list.component';
-import {DesignerComponent} from './designer/designer.component';
-import {SidebarModule} from 'ng-sidebar';
-import {PackagePaginationComponent} from './packages-dashboard/package-pagination/package-pagination.component';
-import {SortPackagesComponent} from './packages-dashboard/sort-packages/sort-packages.component';
-import {PackagesHeaderComponent} from './packages-dashboard/packages-header/packages-header.component';
-import {PackagesSearchComponent} from './packages-dashboard/search-by-packages/search-by-packages.component';
-import {TagsFilteringComponent} from './packages-dashboard/filter-by-tags/filter-by-tags.component';
-import {ConfigurationDashboardComponent} from './configuration-dashboard/configuration-dashboard.component';
-import {FunctionsComponent} from './designer/functions/functions.component';
-import {ActionsComponent} from './designer/actions/actions.component';
-import {PackageCreationComponent} from './package-creation/package-creation.component';
-import {FormsModule} from '@angular/forms';
-import {ImportsTabComponent} from './package-creation/imports-tab/imports-tab.component';
-import {NgxFileDropModule} from 'ngx-file-drop';
-import {TemplateMappingComponent} from './package-creation/template-mapping/template-mapping.component';
-import {SourceEditorComponent} from './source-editor/source-editor.component';
-import {ScriptsTabComponent} from './package-creation/scripts-tab/scripts-tab.component';
-import {AceEditorModule} from 'ng2-ace-editor';
-import {MetadataTabComponent} from './package-creation/metadata-tab/metadata-tab.component';
-import {DslDefinitionsTabComponent} from './package-creation/dsl-definitions-tab/dsl-definitions-tab.component';
+import { NgModule } from '@angular/core';
+import { CommonModule, JsonPipe } from '@angular/common';
+import { ApiService } from '../../../common/core/services/api.typed.service';
+import { PackagesRoutingModule } from './packages.routing.module';
+import { NgbPaginationModule } from '@ng-bootstrap/ng-bootstrap';
+import { SharedModulesModule } from '../../shared-modules/shared-modules.module';
+import { PackagesDashboardComponent } from './packages-dashboard/packages-dashboard.component';
+import { PackageListComponent } from './packages-dashboard/package-list/package-list.component';
+import { DesignerComponent } from './designer/designer.component';
+import { SidebarModule } from 'ng-sidebar';
+import { PackagePaginationComponent } from './packages-dashboard/package-pagination/package-pagination.component';
+import { SortPackagesComponent } from './packages-dashboard/sort-packages/sort-packages.component';
+import { PackagesHeaderComponent } from './packages-dashboard/packages-header/packages-header.component';
+import { PackagesSearchComponent } from './packages-dashboard/search-by-packages/search-by-packages.component';
+import { TagsFilteringComponent } from './packages-dashboard/filter-by-tags/filter-by-tags.component';
+import { ConfigurationDashboardComponent } from './configuration-dashboard/configuration-dashboard.component';
+import { ActionsComponent } from './designer/actions/actions.component';
+import { PackageCreationComponent } from './package-creation/package-creation.component';
+import { FormsModule } from '@angular/forms';
+import { ImportsTabComponent } from './package-creation/imports-tab/imports-tab.component';
+import { NgxFileDropModule } from 'ngx-file-drop';
+import { TemplateMappingComponent } from './package-creation/template-mapping/template-mapping.component';
+import { SourceEditorComponent } from './source-editor/source-editor.component';
+import { ScriptsTabComponent } from './package-creation/scripts-tab/scripts-tab.component';
+import { AceEditorModule } from 'ng2-ace-editor';
+import { MetadataTabComponent } from './package-creation/metadata-tab/metadata-tab.component';
+import { DslDefinitionsTabComponent } from './package-creation/dsl-definitions-tab/dsl-definitions-tab.component';
import { TemplMappCreationComponent } from './package-creation/template-mapping/templ-mapp-creation/templ-mapp-creation.component';
import { TemplMappListingComponent } from './package-creation/template-mapping/templ-mapp-listing/templ-mapp-listing.component';
+import { DataTablesModule } from 'angular-datatables';
+import { DesignerSourceViewComponent } from './designer/source-view/source-view.component';
@NgModule({
declarations: [PackagesDashboardComponent,
@@ -39,7 +40,6 @@ import { TemplMappListingComponent } from './package-creation/template-mapping/t
SortPackagesComponent,
ConfigurationDashboardComponent,
PackagesHeaderComponent,
- FunctionsComponent,
ActionsComponent,
PackageCreationComponent,
ImportsTabComponent,
@@ -50,6 +50,7 @@ import { TemplMappListingComponent } from './package-creation/template-mapping/t
ScriptsTabComponent,
MetadataTabComponent,
DslDefinitionsTabComponent,
+ DesignerSourceViewComponent,
],
imports: [
CommonModule,
@@ -59,7 +60,8 @@ import { TemplMappListingComponent } from './package-creation/template-mapping/t
SidebarModule.forRoot(),
FormsModule,
NgxFileDropModule,
- AceEditorModule
+ AceEditorModule,
+ DataTablesModule
],
providers: [ApiService, JsonPipe],
bootstrap: []
diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/packages.routing.module.ts b/cds-ui/designer-client/src/app/modules/feature-modules/packages/packages.routing.module.ts
index 913bb1081..ad06cf15f 100644
--- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/packages.routing.module.ts
+++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/packages.routing.module.ts
@@ -4,6 +4,7 @@ import {PackagesDashboardComponent} from './packages-dashboard/packages-dashboar
import {DesignerComponent} from './designer/designer.component';
import {PackageCreationComponent} from './package-creation/package-creation.component';
import {ConfigurationDashboardComponent} from './configuration-dashboard/configuration-dashboard.component';
+import { DesignerSourceViewComponent } from './designer/source-view/source-view.component';
const routes: Routes = [
@@ -12,6 +13,7 @@ const routes: Routes = [
component: PackagesDashboardComponent
},
{path: 'designer', component: DesignerComponent},
+ { path: 'designer/source', component: DesignerSourceViewComponent },
{path: 'package/:id', component: ConfigurationDashboardComponent},
{path: 'createPackage', component: PackageCreationComponent},
];
diff --git a/cds-ui/designer-client/src/app/modules/shared-modules/header/header.component.html b/cds-ui/designer-client/src/app/modules/shared-modules/header/header.component.html
index f57ab100b..502e098d3 100644
--- a/cds-ui/designer-client/src/app/modules/shared-modules/header/header.component.html
+++ b/cds-ui/designer-client/src/app/modules/shared-modules/header/header.component.html
@@ -5,14 +5,14 @@
<div class="overflow-container">
<ul class="menu-dropdown">
<li class="active">
- <a routerLink="packages/list">Packages</a>
+ <a routerLink="/packages">Packages</a>
<span class="icon">
<!-- <i class="fa fa-dashboard"></i> -->
<i class="icon-package"></i>
</span>
</li>
<li class="menu-hasdropdown">
- <a href="#">Data Dictionary</a>
+ <a >Data Dictionary</a>
<span class="icon">
<i class="icon-dictionary"></i>
</span>
diff --git a/cds-ui/designer-client/tslint.json b/cds-ui/designer-client/tslint.json
index ecbd7cf88..f85fc68d9 100644
--- a/cds-ui/designer-client/tslint.json
+++ b/cds-ui/designer-client/tslint.json
@@ -87,10 +87,5 @@
},
"rulesDirectory": [
"codelyzer"
- ],
- "linterOptions": {
- "exclude": [
- "src/app/modules/feature-modules/packages/designer/designer.component.ts"
- ]
- }
+ ]
}
diff --git a/cds-ui/pom.xml b/cds-ui/pom.xml
index 122823419..4a9f0fdad 100644
--- a/cds-ui/pom.xml
+++ b/cds-ui/pom.xml
@@ -24,7 +24,7 @@ limitations under the License.
<parent>
<groupId>org.onap.ccsdk.parent</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
- <version>1.5.1</version>
+ <version>1.5.2</version>
<relativePath/>
</parent>
diff --git a/components/model-catalog/blueprint-model/test-blueprint/baseconfiguration/Definitions/activation-blueprint.json b/components/model-catalog/blueprint-model/test-blueprint/baseconfiguration/Definitions/activation-blueprint.json
index 639c21490..85a056c5e 100644
--- a/components/model-catalog/blueprint-model/test-blueprint/baseconfiguration/Definitions/activation-blueprint.json
+++ b/components/model-catalog/blueprint-model/test-blueprint/baseconfiguration/Definitions/activation-blueprint.json
@@ -179,6 +179,10 @@
"another-mapping": {
"type": "artifact-mapping-resource",
"file": "Definitions/another-mapping.json"
+ },
+ "notemplate-mapping": {
+ "type": "artifact-mapping-resource",
+ "file": "Definitions/notemplate-mapping.json"
}
}
},
diff --git a/components/model-catalog/blueprint-model/test-blueprint/baseconfiguration/Definitions/notemplate-mapping.json b/components/model-catalog/blueprint-model/test-blueprint/baseconfiguration/Definitions/notemplate-mapping.json
new file mode 100644
index 000000000..5aa3b3dcb
--- /dev/null
+++ b/components/model-catalog/blueprint-model/test-blueprint/baseconfiguration/Definitions/notemplate-mapping.json
@@ -0,0 +1,36 @@
+[
+ {
+ "name": "service-instance-id",
+ "input-param": true,
+ "property": {
+ "type": "string"
+ },
+ "dictionary-name": "service-instance-id",
+ "dictionary-source": "input",
+ "dependencies": [
+ ]
+ },
+ {
+ "name": "vnf-id",
+ "input-param": true,
+ "property": {
+ "type": "string"
+ },
+ "dictionary-name": "vnf-id",
+ "dictionary-source": "input",
+ "dependencies": []
+ },
+ {
+ "name": "vnf_name",
+ "input-param": false,
+ "property": {
+ "type": "string"
+ },
+ "dictionary-name": "vnf_name",
+ "dictionary-source": "sdnc",
+ "dependencies": [
+ "service-instance-id",
+ "vnf-id"
+ ]
+ }
+] \ No newline at end of file
diff --git a/components/model-catalog/blueprint-model/test-blueprint/pom.xml b/components/model-catalog/blueprint-model/test-blueprint/pom.xml
index f9dab0227..29daa768e 100644
--- a/components/model-catalog/blueprint-model/test-blueprint/pom.xml
+++ b/components/model-catalog/blueprint-model/test-blueprint/pom.xml
@@ -14,7 +14,6 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
@@ -35,4 +34,8 @@
<module>capability_cli</module>
<module>resource-audit</module>
</modules>
+
+ <properties>
+ <sonar.skip>true</sonar.skip>
+ </properties>
</project>
diff --git a/components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Definitions/PNF_CDS_RESTCONF.json b/components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Definitions/PNF_CDS_RESTCONF.json
new file mode 100644
index 000000000..d84fd8182
--- /dev/null
+++ b/components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Definitions/PNF_CDS_RESTCONF.json
@@ -0,0 +1,424 @@
+{
+ "tosca_definitions_version" : "controller_blueprint_1_0_0",
+ "metadata" : {
+ "template_author" : "Raj Gumma",
+ "author-email" : "raj.gumma@est.tech",
+ "user-groups" : "ADMIN, OPERATION",
+ "template_name" : "PNF_CDS_RESTCONF",
+ "template_version" : "1.0.0",
+ "template_tags" : "PNF, Restconf, config, configuration, software upgrade"
+ },
+ "imports" : [ {
+ "file" : "Definitions/data_types.json"
+ }, {
+ "file" : "Definitions/relationship_types.json"
+ }, {
+ "file" : "Definitions/artifact_types.json"
+ }, {
+ "file" : "Definitions/node_types.json"
+ }, {
+ "file" : "Definitions/policy_types.json"
+ } ],
+ "dsl_definitions" : {
+ "config-deploy-properties" : {
+ "resolution-key" : {
+ "get_input" : "resolution-key"
+ }
+ },
+ "preCheck-properties" : {
+ "resolution-key" : {
+ "get_input" : "resolution-key"
+ }
+ },
+ "downloadNESw-properties" : {
+ "resolution-key" : {
+ "get_input" : "resolution-key"
+ }
+ },
+ "activateNESw-properties" : {
+ "resolution-key" : {
+ "get_input" : "resolution-key"
+ }
+ },
+ "postCheck-properties" : {
+ "resolution-key" : {
+ "get_input" : "resolution-key"
+ }
+ }
+ },
+ "topology_template" : {
+ "workflows" : {
+ "config-assign" : {
+ "steps" : {
+ "activate-process" : {
+ "description" : "Create a configlet",
+ "target" : "config-assign",
+ "activities" : [ {
+ "call_operation" : ""
+ } ]
+ }
+ },
+ "inputs" : {
+ "resolution-key" : {
+ "required" : true,
+ "type" : "string"
+ },
+ "store-result" : {
+ "required" : true,
+ "type" : "boolean"
+ },
+ "config-assign-properties" : {
+ "description" : "Dynamic PropertyDefinition for workflow(config-assign).",
+ "required" : true,
+ "type" : "dt-config-assign-properties"
+ }
+ }
+ },
+ "config-deploy" : {
+ "steps" : {
+ "activate-process" : {
+ "description" : "Send a configlet to the pnf",
+ "target" : "config-deploy",
+ "activities" : [ {
+ "call_operation" : ""
+ } ]
+ }
+ },
+ "inputs" : {
+ "resolution-key" : {
+ "required" : true,
+ "type" : "string"
+ },
+ "config-deploy-properties" : {
+ "description" : "Dynamic PropertyDefinition for workflow(config-deploy).",
+ "required" : true,
+ "type" : "dt-config-deploy-properties"
+ }
+ }
+ },
+ "preCheck" : {
+ "steps" : {
+ "activate-process" : {
+ "description" : "Check if pnf ready for sw upgrade",
+ "target" : "preCheck",
+ "activities" : [ {
+ "call_operation" : ""
+ } ]
+ }
+ },
+ "inputs" : {
+ "resolution-key" : {
+ "required" : true,
+ "type" : "string"
+ },
+ "preCheck-properties" : {
+ "description" : "Dynamic PropertyDefinition for preCheck workflow(software-upgrade).",
+ "required" : true,
+ "type" : "dt-preCheck-properties"
+ }
+ }
+ },
+ "downloadNESw" : {
+ "steps" : {
+ "activate-process" : {
+ "description" : "Trigger download new software for sw upgrade",
+ "target" : "downloadNESw",
+ "activities" : [ {
+ "call_operation" : ""
+ } ]
+ }
+ },
+ "inputs" : {
+ "resolution-key" : {
+ "required" : true,
+ "type" : "string"
+ },
+ "downloadNESw-properties" : {
+ "description" : "Dynamic PropertyDefinition for downloadNESw workflow(software-upgrade).",
+ "required" : true,
+ "type" : "dt-downloadNESw-properties"
+ }
+ }
+ },
+ "activateNESw" : {
+ "steps" : {
+ "activate-process" : {
+ "description" : "Trigger activation of target software version for pnf upgrade",
+ "target" : "activateNESw",
+ "activities" : [ {
+ "call_operation" : ""
+ } ]
+ }
+ },
+ "inputs" : {
+ "resolution-key" : {
+ "required" : true,
+ "type" : "string"
+ },
+ "activateNESw-properties" : {
+ "description" : "Dynamic PropertyDefinition for activateNESw workflow(software-upgrade).",
+ "required" : true,
+ "type" : "dt-activateNESw-properties"
+ }
+ }
+ },
+ "postCheck" : {
+ "steps" : {
+ "activate-process" : {
+ "description" : "Check if pnf upgrade is completed",
+ "target" : "postCheck",
+ "activities" : [ {
+ "call_operation" : ""
+ } ]
+ }
+ },
+ "inputs" : {
+ "resolution-key" : {
+ "required" : true,
+ "type" : "string"
+ },
+ "postCheck-properties" : {
+ "description" : "Dynamic PropertyDefinition for postCheck workflow(software-upgrade).",
+ "required" : true,
+ "type" : "dt-postCheck-properties"
+ }
+ }
+ }
+ },
+ "node_templates" : {
+ "config-assign" : {
+ "type" : "component-resource-resolution",
+ "interfaces" : {
+ "ResourceResolutionComponent" : {
+ "operations" : {
+ "process" : {
+ "inputs" : {
+ "resolution-key" : {
+ "get_input" : "resolution-key"
+ },
+ "store-result" : true,
+ "artifact-prefix-names" : [ "config-assign" ]
+ },
+ "outputs" : {
+ "resource-assignment-params" : {
+ "get_attribute" : [ "SELF", "assignment-params" ]
+ },
+ "status" : "success"
+ }
+ }
+ }
+ }
+ },
+ "artifacts" : {
+ "config-assign-template" : {
+ "type" : "artifact-template-velocity",
+ "file" : "Templates/config-assign-restconf-configlet-template.vtl"
+ },
+ "config-assign-mapping" : {
+ "type" : "artifact-mapping-resource",
+ "file" : "Definitions/config-assign-pnf-mapping.json"
+ }
+ }
+ },
+ "config-deploy" : {
+ "type" : "component-script-executor",
+ "interfaces" : {
+ "ComponentScriptExecutor" : {
+ "operations" : {
+ "process" : {
+ "implementation" : {
+ "primary" : "component-script",
+ "timeout" : 180,
+ "operation_host" : "SELF"
+ },
+ "inputs" : {
+ "script-type" : "kotlin",
+ "script-class-reference" : "cba.pnf.config.aai.RestconfConfigDeploy",
+ "dynamic-properties" : "*config-deploy-properties"
+ },
+ "outputs" : {
+ "response-data" : "",
+ "status" : "success"
+ }
+ }
+ }
+ }
+ },
+ "artifacts" : {
+ "config-deploy-template" : {
+ "type" : "artifact-template-velocity",
+ "file" : "Templates/restconf-mount-template.vtl"
+ },
+ "config-deploy-mapping" : {
+ "type" : "artifact-mapping-resource",
+ "file" : "Definitions/config-deploy-pnf-mapping.json"
+ }
+ }
+ },
+ "preCheck" : {
+ "type" : "component-script-executor",
+ "interfaces" : {
+ "ComponentScriptExecutor" : {
+ "operations" : {
+ "process" : {
+ "implementation" : {
+ "primary" : "component-script",
+ "timeout" : 180,
+ "operation_host" : "SELF"
+ },
+ "inputs" : {
+ "script-type" : "kotlin",
+ "script-class-reference" : "cba.pnf.swug.RestconfSoftwareUpgrade",
+ "dynamic-properties" : "*preCheck-properties"
+ },
+ "outputs" : {
+ "response-data" : "",
+ "status" : "success"
+ }
+ }
+ }
+ }
+ },
+ "artifacts" : {
+ "mount-node-template" : {
+ "type" : "artifact-template-velocity",
+ "file" : "Templates/restconf-mount-template.vtl"
+ },
+ "mount-node-mapping" : {
+ "type" : "artifact-mapping-resource",
+ "file" : "Definitions/pnf-software-upgrade-mapping.json"
+ }
+ }
+ },
+ "downloadNESw" : {
+ "type" : "component-script-executor",
+ "interfaces" : {
+ "ComponentScriptExecutor" : {
+ "operations" : {
+ "process" : {
+ "implementation" : {
+ "primary" : "component-script",
+ "timeout" : 180,
+ "operation_host" : "SELF"
+ },
+ "inputs" : {
+ "script-type" : "kotlin",
+ "script-class-reference" : "cba.pnf.swug.RestconfSoftwareUpgrade",
+ "dynamic-properties" : "*downloadNESw-properties"
+ },
+ "outputs" : {
+ "response-data" : "",
+ "status" : "success"
+ }
+ }
+ }
+ }
+ },
+ "artifacts" : {
+ "mount-node-template" : {
+ "type" : "artifact-template-velocity",
+ "file" : "Templates/restconf-mount-template.vtl"
+ },
+ "mount-node-mapping" : {
+ "type" : "artifact-mapping-resource",
+ "file" : "Definitions/pnf-software-upgrade-mapping.json"
+ },
+ "configure-template" : {
+ "type" : "artifact-template-velocity",
+ "file" : "Templates/pnf-swug-config-template.vtl"
+ },
+ "configure-mapping" : {
+ "type" : "artifact-mapping-resource",
+ "file" : "Definitions/pnf-software-upgrade-mapping.json"
+ },
+ "download-ne-sw-template" : {
+ "type" : "artifact-template-velocity",
+ "file" : "Templates/pnf-swug-download-ne-sw-template.vtl"
+ },
+ "download-ne-sw-mapping" : {
+ "type" : "artifact-mapping-resource",
+ "file" : "Definitions/pnf-software-upgrade-mapping.json"
+ }
+ }
+ },
+ "activateNESw" : {
+ "type" : "component-script-executor",
+ "interfaces" : {
+ "ComponentScriptExecutor" : {
+ "operations" : {
+ "process" : {
+ "implementation" : {
+ "primary" : "component-script",
+ "timeout" : 180,
+ "operation_host" : "SELF"
+ },
+ "inputs" : {
+ "script-type" : "kotlin",
+ "script-class-reference" : "cba.pnf.swug.RestconfSoftwareUpgrade",
+ "dynamic-properties" : "*activateNESw-properties"
+ },
+ "outputs" : {
+ "response-data" : "",
+ "status" : "success"
+ }
+ }
+ }
+ }
+ },
+ "artifacts" : {
+ "mount-node-template" : {
+ "type" : "artifact-template-velocity",
+ "file" : "Templates/restconf-mount-template.vtl"
+ },
+ "mount-node-mapping" : {
+ "type" : "artifact-mapping-resource",
+ "file" : "Definitions/pnf-software-upgrade-mapping.json"
+ },
+ "configure-template" : {
+ "type" : "artifact-template-velocity",
+ "file" : "Templates/pnf-swug-config-template.vtl"
+ },
+ "configure-mapping" : {
+ "type" : "artifact-mapping-resource",
+ "file" : "Definitions/pnf-software-upgrade-mapping.json"
+ }
+ }
+ },
+ "postCheck" : {
+ "type" : "component-script-executor",
+ "interfaces" : {
+ "ComponentScriptExecutor" : {
+ "operations" : {
+ "process" : {
+ "implementation" : {
+ "primary" : "component-script",
+ "timeout" : 180,
+ "operation_host" : "SELF"
+ },
+ "inputs" : {
+ "script-type" : "kotlin",
+ "script-class-reference" : "cba.pnf.swug.RestconfSoftwareUpgrade",
+ "dynamic-properties" : "*postCheck-properties"
+ },
+ "outputs" : {
+ "response-data" : "",
+ "status" : "success"
+ }
+ }
+ }
+ }
+ },
+ "artifacts" : {
+ "mount-node-template" : {
+ "type" : "artifact-template-velocity",
+ "file" : "Templates/restconf-mount-template.vtl"
+ },
+ "mount-node-mapping" : {
+ "type" : "artifact-mapping-resource",
+ "file" : "Definitions/pnf-software-upgrade-mapping.json"
+ }
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/components/model-catalog/blueprint-model/uat-blueprints/pnf_config_aai/Definitions/artifact_types.json b/components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Definitions/artifact_types.json
index 6ec3b4105..6ec3b4105 100644
--- a/components/model-catalog/blueprint-model/uat-blueprints/pnf_config_aai/Definitions/artifact_types.json
+++ b/components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Definitions/artifact_types.json
diff --git a/components/model-catalog/blueprint-model/uat-blueprints/pnf_config_aai/Definitions/config-assign-pnf-mapping.json b/components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Definitions/config-assign-pnf-mapping.json
index fe51488c7..fe51488c7 100644
--- a/components/model-catalog/blueprint-model/uat-blueprints/pnf_config_aai/Definitions/config-assign-pnf-mapping.json
+++ b/components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Definitions/config-assign-pnf-mapping.json
diff --git a/components/model-catalog/blueprint-model/uat-blueprints/pnf_config_aai/Definitions/config-deploy-pnf-mapping.json b/components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Definitions/config-deploy-pnf-mapping.json
index dd8889c80..dd8889c80 100644
--- a/components/model-catalog/blueprint-model/uat-blueprints/pnf_config_aai/Definitions/config-deploy-pnf-mapping.json
+++ b/components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Definitions/config-deploy-pnf-mapping.json
diff --git a/components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Definitions/data_types.json b/components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Definitions/data_types.json
new file mode 100644
index 000000000..cd91f4b3a
--- /dev/null
+++ b/components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Definitions/data_types.json
@@ -0,0 +1,75 @@
+{
+ "data_types" : {
+ "dt-config-assign-properties" : {
+ "description" : "Dynamic DataType definition for workflow(config-assign).",
+ "version" : "1.0.0",
+ "properties" : { },
+ "derived_from" : "tosca.datatypes.Dynamic"
+ },
+ "dt-config-deploy-properties" : {
+ "description" : "Dynamic DataType definition for workflow(config-deploy).",
+ "version" : "1.0.0",
+ "properties" : {
+ "pnf-ipv4-address" : {
+ "type" : "string"
+ },
+ "pnf-id" : {
+ "type" : "string"
+ }
+ },
+ "derived_from" : "tosca.datatypes.Dynamic"
+ },
+ "dt-preCheck-properties": {
+ "description": "Dynamic DataType definition for the preCheck workflow(upgrade-software).",
+ "version": "1.0.0",
+ "properties": {
+ "pnf-id": {
+ "type": "string"
+ },
+ "target-software-version": {
+ "type": "string"
+ }
+ },
+ "derived_from": "tosca.datatypes.Dynamic"
+ },
+ "dt-downloadNESw-properties": {
+ "description": "Dynamic DataType definition for the downloadNESw workflow(upgrade-software).",
+ "version": "1.0.0",
+ "properties": {
+ "pnf-id": {
+ "type": "string"
+ },
+ "target-software-version": {
+ "type": "string"
+ }
+ },
+ "derived_from": "tosca.datatypes.Dynamic"
+ },
+ "dt-activateNESw-properties": {
+ "description": "Dynamic DataType definition for the activateNESw workflow(upgrade-software).",
+ "version": "1.0.0",
+ "properties": {
+ "pnf-id": {
+ "type": "string"
+ },
+ "target-software-version": {
+ "type": "string"
+ }
+ },
+ "derived_from": "tosca.datatypes.Dynamic"
+ },
+ "dt-postCheck-properties": {
+ "description": "Dynamic DataType definition for the postCheck workflow(upgrade-software).",
+ "version": "1.0.0",
+ "properties": {
+ "pnf-id": {
+ "type": "string"
+ },
+ "target-software-version": {
+ "type": "string"
+ }
+ },
+ "derived_from": "tosca.datatypes.Dynamic"
+ }
+ }
+} \ No newline at end of file
diff --git a/components/model-catalog/blueprint-model/uat-blueprints/pnf_config_aai/Definitions/node_types.json b/components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Definitions/node_types.json
index bfae6779e..bfae6779e 100644
--- a/components/model-catalog/blueprint-model/uat-blueprints/pnf_config_aai/Definitions/node_types.json
+++ b/components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Definitions/node_types.json
diff --git a/components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Definitions/pnf-software-upgrade-mapping.json b/components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Definitions/pnf-software-upgrade-mapping.json
new file mode 100644
index 000000000..2c3de2e49
--- /dev/null
+++ b/components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Definitions/pnf-software-upgrade-mapping.json
@@ -0,0 +1,36 @@
+[
+ {
+ "name": "pnf-id",
+ "input-param": true,
+ "property": {
+ "type": "string"
+ },
+ "dictionary-name": "pnf-id",
+ "dictionary-source": "input",
+ "dependencies": [
+ ]
+ },
+ {
+ "name": "target-software-version",
+ "input-param": true,
+ "property": {
+ "type": "string"
+ },
+ "dictionary-name": "target-software-version",
+ "dictionary-source": "input",
+ "dependencies": [
+ ]
+ },
+ {
+ "name": "pnf-ipv4-address",
+ "input-param": false,
+ "property": {
+ "type": "string"
+ },
+ "dictionary-name": "pnf-ipaddress-aai",
+ "dictionary-source": "aai-data",
+ "dependencies": [
+ "pnf-id"
+ ]
+ }
+]
diff --git a/components/model-catalog/blueprint-model/uat-blueprints/pnf_config_aai/Definitions/policy_types.json b/components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Definitions/policy_types.json
index 1e44cc70a..1e44cc70a 100644
--- a/components/model-catalog/blueprint-model/uat-blueprints/pnf_config_aai/Definitions/policy_types.json
+++ b/components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Definitions/policy_types.json
diff --git a/components/model-catalog/blueprint-model/uat-blueprints/pnf_config_aai/Definitions/relationship_types.json b/components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Definitions/relationship_types.json
index 4ddd7a57c..4ddd7a57c 100644
--- a/components/model-catalog/blueprint-model/uat-blueprints/pnf_config_aai/Definitions/relationship_types.json
+++ b/components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Definitions/relationship_types.json
diff --git a/components/model-catalog/blueprint-model/uat-blueprints/pnf_config_aai/Definitions/resources_definition_types.json b/components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Definitions/resources_definition_types.json
index 235a05d27..235a05d27 100644
--- a/components/model-catalog/blueprint-model/uat-blueprints/pnf_config_aai/Definitions/resources_definition_types.json
+++ b/components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Definitions/resources_definition_types.json
diff --git a/components/model-catalog/blueprint-model/uat-blueprints/pnf_config_aai/Environments/source-db.properties b/components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Environments/source-db.properties
index 49a7eb47b..49a7eb47b 100644
--- a/components/model-catalog/blueprint-model/uat-blueprints/pnf_config_aai/Environments/source-db.properties
+++ b/components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Environments/source-db.properties
diff --git a/components/model-catalog/blueprint-model/uat-blueprints/pnf_config_aai/Environments/source-rest.properties b/components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Environments/source-rest.properties
index bc1eb7417..bc1eb7417 100644
--- a/components/model-catalog/blueprint-model/uat-blueprints/pnf_config_aai/Environments/source-rest.properties
+++ b/components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Environments/source-rest.properties
diff --git a/components/model-catalog/blueprint-model/uat-blueprints/pnf_config_aai/Plans/CONFIG_configAssign.xml b/components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Plans/CONFIG_configAssign.xml
index a3eedf172..a3eedf172 100644
--- a/components/model-catalog/blueprint-model/uat-blueprints/pnf_config_aai/Plans/CONFIG_configAssign.xml
+++ b/components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Plans/CONFIG_configAssign.xml
diff --git a/components/model-catalog/blueprint-model/uat-blueprints/pnf_config_aai/Plans/CONFIG_configDeploy.xml b/components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Plans/CONFIG_configDeploy.xml
index f4e1b996f..f4e1b996f 100644
--- a/components/model-catalog/blueprint-model/uat-blueprints/pnf_config_aai/Plans/CONFIG_configDeploy.xml
+++ b/components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Plans/CONFIG_configDeploy.xml
diff --git a/components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Plans/CONFIG_upgradeSoftware.xml b/components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Plans/CONFIG_upgradeSoftware.xml
new file mode 100644
index 000000000..52a9900b2
--- /dev/null
+++ b/components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Plans/CONFIG_upgradeSoftware.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<service-logic xmlns="http://www.onap.org/sdnc/svclogic" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.onap.org/sdnc/svclogic ./svclogic.xsd" module="CONFIG" version="1.0.0">
+ <method rpc="ResourceAssignAndActivate" mode="sync">
+ <block atomic="true">
+ <execute plugin="upgrade-software" method="process">
+ <outcome value="failure">
+ <return status="failure"/>
+ </outcome>
+ <outcome value="success">
+ <return status="success"/>
+ </outcome>
+ </execute>
+ </block>
+ </method>
+</service-logic>
diff --git a/components/model-catalog/blueprint-model/uat-blueprints/pnf_config_aai/Scripts/kotlin/RestconfConfigDeploy.kt b/components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Scripts/kotlin/RestconfConfigDeploy.kt
index 6a034ab94..730565959 100644
--- a/components/model-catalog/blueprint-model/uat-blueprints/pnf_config_aai/Scripts/kotlin/RestconfConfigDeploy.kt
+++ b/components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Scripts/kotlin/RestconfConfigDeploy.kt
@@ -1,6 +1,6 @@
/*
* ============LICENSE_START=======================================================
-* Copyright (C) 2019 Nordix Foundation.
+* Copyright (C) 2020 Nordix Foundation.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -31,11 +31,14 @@ import org.onap.ccsdk.cds.blueprintsprocessor.functions.restconf.executor.restco
import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.AbstractScriptComponentFunction
import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException
import org.onap.ccsdk.cds.controllerblueprints.core.logger
+import com.fasterxml.jackson.databind.ObjectMapper
+import org.onap.ccsdk.cds.blueprintsprocessor.rest.service.BlueprintWebClientService.WebClientResponse
class RestconfConfigDeploy : AbstractScriptComponentFunction() {
private val CONFIGLET_TEMPLATE_NAME = "config-assign"
private val CONFIGLET_RESOURCE_PATH = "yang-ext:mount/mynetconf:netconflist"
private val RESTCONF_SERVER_IDENTIFIER = "sdnc"
+ private val mapper = ObjectMapper()
private val log = logger(AbstractScriptComponentFunction::class.java)
override suspend fun processNB(executionRequest: ExecutionServiceInput) {
@@ -58,9 +61,17 @@ class RestconfConfigDeploy : AbstractScriptComponentFunction() {
val currentConfig: Any = restconfDeviceConfig(webclientService, deviceID, CONFIGLET_RESOURCE_PATH)
log.info("Current configuration subtree : $currentConfig")
//Apply configlet
- restconfApplyDeviceConfig(webclientService, deviceID, CONFIGLET_RESOURCE_PATH,
+ val result = restconfApplyDeviceConfig(webclientService, deviceID, CONFIGLET_RESOURCE_PATH,
storedContentFromResolvedArtifactNB(resolutionKey, CONFIGLET_TEMPLATE_NAME),
- mutableMapOf("Content-Type" to "application/yang.patch+json"))
+ mutableMapOf("Content-Type" to "application/yang.patch+json")) as WebClientResponse<*>
+
+ val jsonResult = mapper.readTree((result.body).toString())
+
+ if (jsonResult.get("ietf-yang-patch:yang-patch-status").get("errors") != null) {
+ log.error("There was an error configuring device")
+ } else {
+ log.info("Device has been configured succesfully")
+ }
} catch (err: Exception) {
log.error("an error occurred while configuring device {}", err)
diff --git a/components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Scripts/kotlin/RestconfSoftwareUpgrade.kt b/components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Scripts/kotlin/RestconfSoftwareUpgrade.kt
new file mode 100644
index 000000000..0540efe80
--- /dev/null
+++ b/components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Scripts/kotlin/RestconfSoftwareUpgrade.kt
@@ -0,0 +1,205 @@
+/*
+* ============LICENSE_START=======================================================
+* Copyright (C) 2020 Nordix Foundation.
+* ================================================================================
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+* ============LICENSE_END=========================================================
+ */
+
+
+package cba.pnf.swug
+
+import com.fasterxml.jackson.databind.node.ObjectNode
+import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput
+import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.contentFromResolvedArtifactNB
+import org.onap.ccsdk.cds.blueprintsprocessor.functions.restconf.executor.restconfApplyDeviceConfig
+import org.onap.ccsdk.cds.blueprintsprocessor.functions.restconf.executor.restconfDeviceConfig
+import org.onap.ccsdk.cds.blueprintsprocessor.functions.restconf.executor.restconfMountDevice
+import org.onap.ccsdk.cds.blueprintsprocessor.functions.restconf.executor.restconfUnMountDevice
+import org.onap.ccsdk.cds.blueprintsprocessor.rest.restClientService
+import org.onap.ccsdk.cds.blueprintsprocessor.rest.service.BlueprintWebClientService
+import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.AbstractScriptComponentFunction
+import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintException
+import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintRetryException
+import org.onap.ccsdk.cds.controllerblueprints.core.logger
+import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintDependencyService
+import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils
+
+class RestconfSoftwareUpgrade : AbstractScriptComponentFunction() {
+
+ private val RESTCONF_SERVER_IDENTIFIER = "sdnc"
+ private val CONFIGLET_RESOURCE_PATH = "yang-ext:mount/pnf-sw-upgrade:software-upgrade"
+ private val log = logger(AbstractScriptComponentFunction::class.java)
+ private val TARGET_SOFTWARE_PATH = "$CONFIGLET_RESOURCE_PATH/upgrade-package/"
+
+ override suspend fun processNB(executionRequest: ExecutionServiceInput) {
+
+ // Extract request properties
+ val model= validatedPayload(executionRequest)
+
+ log.info("Blueprint invoked for ${model.resolutionKey} for SW Upgrade : " +
+ "${model.action} for sw version ${model.targetSwVersion} on pnf: ${model.deviceId}")
+
+ try {
+ val mountPayload = contentFromResolvedArtifactNB("mount-node")
+ log.debug("Mount Payload : $mountPayload")
+ restconfMountDevice(model.client, model.deviceId, mountPayload, mutableMapOf("Content-Type" to "application/json"))
+
+ when (model.action) {
+ Action.PRE_CHECK -> processPreCheck(model)
+ Action.DOWNLOAD_NE_SW -> processDownloadNESw(model)
+ Action.ACTIVATE_NE_SW -> processActivateNESw(model)
+ Action.POST_CHECK -> processPostCheck(model)
+ Action.CANCEL -> processCancel(model)
+ }
+
+ } catch (err: Exception) {
+ log.error("an error occurred while configuring device {}", err)
+ } finally {
+ restconfUnMountDevice(model.client, model.deviceId, "")
+ }
+ }
+
+ private fun validatedPayload(executionRequest: ExecutionServiceInput): SoftwareUpgradeModel {
+ val properties = requestPayloadActionProperty(executionRequest.actionIdentifiers.actionName + "-properties")!!.get(0)
+ if(!properties?.get("pnf-id")?.textValue().isNullOrEmpty() &&
+ !properties?.get("target-software-version")?.textValue().isNullOrEmpty()) {
+ return SoftwareUpgradeModel(getDynamicProperties("resolution-key").asText(),
+ BluePrintDependencyService.restClientService(RESTCONF_SERVER_IDENTIFIER),
+ properties.get("pnf-id").textValue(), properties.get("target-software-version").textValue(),
+ Action.getEnumFromActionName(executionRequest.actionIdentifiers.actionName))
+ }else{
+ throw BluePrintException("Invalid parameters sent to CDS. Request parameters pnf-id or target-software-version missing")
+ }
+ }
+
+ private suspend fun processPreCheck(model: SoftwareUpgradeModel) {
+ log.debug("In PNF SW upgrade : processPreCheck")
+ //Log the current configuration for the subtree
+ val payloadObject = getCurrentConfig(model)
+ log.debug("Current sw version on pnf : ${payloadObject.get("software-upgrade")?.get("upgrade-package")?.get(0)?.get("software-version")?.asText()}")
+ log.info("PNF is Healthy!")
+ }
+
+ private suspend fun processDownloadNESw(model: SoftwareUpgradeModel) {
+ log.debug("In PNF SW upgrade : processDownloadNESw")
+ //Check if there is existing config for the targeted software version
+
+ var downloadConfigPayload: String
+ if (checkIfSwReadyToPerformAction(Action.PRE_CHECK, model)) {
+ downloadConfigPayload = contentFromResolvedArtifactNB("configure")
+ downloadConfigPayload =downloadConfigPayload.replace("%id%", model.yangId)
+ }
+ else {
+ downloadConfigPayload = contentFromResolvedArtifactNB("download-ne-sw")
+ model.yangId=model.targetSwVersion
+ }
+ downloadConfigPayload = downloadConfigPayload.replace("%actionName%", Action.DOWNLOAD_NE_SW.name)
+ log.info("Config Payload to start download : $downloadConfigPayload")
+
+ //Apply configlet
+ restconfApplyDeviceConfig(model.client, model.deviceId, CONFIGLET_RESOURCE_PATH, downloadConfigPayload,
+ mutableMapOf("Content-Type" to "application/yang.patch+json"))
+
+ //Poll PNF for Download action's progress
+ checkExecution(model)
+ }
+
+ private suspend fun processActivateNESw(model: SoftwareUpgradeModel) {
+ log.debug("In PNF SW upgrade : processActivateNESw")
+ //Check if the software is downloaded and ready to be activated
+ if (checkIfSwReadyToPerformAction(Action.DOWNLOAD_NE_SW, model)) {
+ var activateConfigPayload: String = contentFromResolvedArtifactNB("configure")
+ activateConfigPayload = activateConfigPayload.replace("%actionName%", Action.ACTIVATE_NE_SW.name)
+ activateConfigPayload = activateConfigPayload.replace("%id%", model.yangId)
+ log.info("Config Payload to start activate : $activateConfigPayload")
+ //Apply configlet
+ restconfApplyDeviceConfig(model.client, model.deviceId, CONFIGLET_RESOURCE_PATH, activateConfigPayload,
+ mutableMapOf("Content-Type" to "application/yang.patch+json"))
+
+ //Poll PNF for Activate action's progress
+ checkExecution(model)
+ } else {
+ throw BluePrintRetryException("Software Download not completed for device(${model.deviceId}) to activate sw version: ${model.targetSwVersion}")
+ }
+ }
+
+ private suspend fun processPostCheck(model: SoftwareUpgradeModel) {
+ log.info("In PNF SW upgrade : processPostCheck")
+ //Log the current configuration for the subtree
+ if (checkIfSwReadyToPerformAction(Action.POST_CHECK, model)) {
+ log.info("PNF is healthy post activation!")
+ }
+ }
+
+ private fun processCancel(model :SoftwareUpgradeModel) {
+ //This is for future implementation of cancel step during software upgrade
+ log.info("In PNF SW upgrade : processCancel")
+ }
+
+ private suspend fun getCurrentConfig(model: SoftwareUpgradeModel) : ObjectNode{
+ val currentConfig: BlueprintWebClientService.WebClientResponse<String> = restconfDeviceConfig(model.client, model.deviceId, CONFIGLET_RESOURCE_PATH)
+ return JacksonUtils.jsonNode(currentConfig.body) as ObjectNode
+ }
+ private suspend fun checkExecution(model: SoftwareUpgradeModel) {
+ val checkExecutionBlock: suspend (Int) -> String = {
+ val result = restconfDeviceConfig(model.client, model.deviceId, TARGET_SOFTWARE_PATH.plus(model.yangId))
+ if (result.body.contains(model.action.completionStatus)) {
+ log.info("${model.action.name} is complete")
+ result.body
+ } else {
+ throw BluePrintRetryException("Waiting for device(${model.deviceId}) to activate sw version ${model.targetSwVersion}")
+ }
+ }
+ model.client.retry<String>(10, 0, 1000, checkExecutionBlock)
+
+ }
+
+ private suspend fun checkIfSwReadyToPerformAction(action : Action, model: SoftwareUpgradeModel): Boolean {
+ val configBody = getCurrentConfig(model)
+ configBody.get("software-upgrade")?.get("upgrade-package")?.iterator()?.forEach { item ->
+ if (model.targetSwVersion == item.get("software-version")?.asText() &&
+ action.completionStatus == item?.get("current-status")?.asText()) {
+ model.yangId= item.get("id").textValue()
+ return true
+ }
+ }
+ return false
+ }
+
+ override suspend fun recoverNB(runtimeException: RuntimeException, executionRequest: ExecutionServiceInput) {
+ log.info("Recover function called!")
+ log.info("Execution request : $executionRequest")
+ log.error("Exception", runtimeException)
+ }
+}
+
+enum class Action(val actionName: String, val completionStatus: String) {
+ PRE_CHECK("preCheck", "INITIALIZED"),
+ DOWNLOAD_NE_SW("downloadNESw", "DOWNLOAD_COMPLETED"),
+ ACTIVATE_NE_SW("activateNESw", "ACTIVATION_COMPLETED"),
+ POST_CHECK("postCheck", "ACTIVATION_COMPLETED"),
+ CANCEL("cancel", "CANCELLED")
+ ;
+ companion object{
+ fun getEnumFromActionName(name: String): Action {
+ for(value in values()){
+ if (value.actionName==name) return value
+ }
+ throw BluePrintException("Invalid Action sent to CDS")
+ }
+ }
+}
+
+data class SoftwareUpgradeModel(val resolutionKey: String, val client: BlueprintWebClientService, val deviceId: String,
+ val targetSwVersion: String, val action: Action, var yangId: String = "") \ No newline at end of file
diff --git a/components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/TOSCA-Metadata/TOSCA.meta b/components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/TOSCA-Metadata/TOSCA.meta
new file mode 100644
index 000000000..467964604
--- /dev/null
+++ b/components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/TOSCA-Metadata/TOSCA.meta
@@ -0,0 +1,7 @@
+TOSCA-Meta-File-Version: 1.0.0
+CSAR-Version: 1.0
+Created-By: Raj Gumma <raj.gumma@est.tech>
+Entry-Definitions: Definitions/PNF_CDS_RESTCONF.json
+Template-Name: PNF_CDS_RESTCONF
+Template-Version: 1.0.0
+Template-Tags: PNF_CDS_RESTCONF
diff --git a/components/model-catalog/blueprint-model/uat-blueprints/pnf_config_aai/Templates/config-assign-restconf-configlet-template.vtl b/components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Templates/config-assign-restconf-configlet-template.vtl
index af91ba00d..af91ba00d 100644
--- a/components/model-catalog/blueprint-model/uat-blueprints/pnf_config_aai/Templates/config-assign-restconf-configlet-template.vtl
+++ b/components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Templates/config-assign-restconf-configlet-template.vtl
diff --git a/components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Templates/pnf-swug-config-template.vtl b/components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Templates/pnf-swug-config-template.vtl
new file mode 100644
index 000000000..5e52f6779
--- /dev/null
+++ b/components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Templates/pnf-swug-config-template.vtl
@@ -0,0 +1,22 @@
+{
+ "ietf-restconf:yang-patch": {
+ "patch-id": "patch-1",
+ "edit": [
+ {
+ "edit-id": "edit1",
+ "operation": "merge",
+ "target": "/",
+ "value": {
+ "software-upgrade": {
+ "upgrade-package": [
+ {
+ "id": "%id%",
+ "action": "%actionName%"
+ }
+ ]
+ }
+ }
+ }
+ ]
+ }
+} \ No newline at end of file
diff --git a/components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Templates/pnf-swug-download-ne-sw-template.vtl b/components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Templates/pnf-swug-download-ne-sw-template.vtl
new file mode 100644
index 000000000..695b66866
--- /dev/null
+++ b/components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Templates/pnf-swug-download-ne-sw-template.vtl
@@ -0,0 +1,28 @@
+{
+ "ietf-restconf:yang-patch": {
+ "patch-id": "patch-1",
+ "edit": [
+ {
+ "edit-id": "edit1",
+ "operation": "merge",
+ "target": "/",
+ "value": {
+ "software-upgrade": {
+ "upgrade-package": [
+ {
+ "id": "${target-software-version}",
+ "current-status": "INITIALIZED",
+ "action": "%actionName%",
+ "user-label": "trial software update",
+ "uri": "sftp://127.0.0.1/test_software_2.img",
+ "software-version": "${target-software-version}",
+ "user": "test_user",
+ "password": "test_password"
+ }
+ ]
+ }
+ }
+ }
+ ]
+ }
+} \ No newline at end of file
diff --git a/components/model-catalog/blueprint-model/uat-blueprints/pnf_config_aai/Templates/config-deploy-restconf-mount-template.vtl b/components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Templates/restconf-mount-template.vtl
index 8098b05d8..8098b05d8 100644
--- a/components/model-catalog/blueprint-model/uat-blueprints/pnf_config_aai/Templates/config-deploy-restconf-mount-template.vtl
+++ b/components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Templates/restconf-mount-template.vtl
diff --git a/components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Tests/uat.yaml b/components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Tests/uat.yaml
new file mode 100644
index 000000000..c2fd3f788
--- /dev/null
+++ b/components/model-catalog/blueprint-model/uat-blueprints/PNF_CDS_RESTCONF/Tests/uat.yaml
@@ -0,0 +1,374 @@
+%YAML 1.1
+---
+processes:
+ - name: config-assign
+ request:
+ commonHeader: &commonHeader
+ originatorId: sdnc
+ requestId: "123456-1000"
+ subRequestId: sub-123456-1000
+ actionIdentifiers: &assign-ai
+ blueprintName: PNF_CDS_RESTCONF
+ blueprintVersion: "1.0.0"
+ actionName: config-assign
+ mode: sync
+ payload:
+ config-assign-request:
+ resolution-key: &resKey "RES-KEY 61"
+ config-assign-properties:
+ service-instance-id: siid_1234
+ pnf-id: &pnfId pnf-id-2019-07-12
+ service-model-uuid: service-model-uuid
+ pnf-customization-uuid: pnf-customization-uuid
+ expectedResponse:
+ commonHeader: *commonHeader
+ actionIdentifiers: *assign-ai
+ status:
+ code: 200
+ eventType: EVENT_COMPONENT_EXECUTED
+ errorMessage: null
+ message: success
+ payload:
+ config-assign-response: {}
+ - name: config-deploy
+ request:
+ commonHeader: *commonHeader
+ actionIdentifiers: &deploy-ai
+ actionName: config-deploy
+ blueprintName: PNF_CDS_RESTCONF
+ blueprintVersion: "1.0.0"
+ mode: sync
+ payload:
+ config-deploy-request:
+ resolution-key: *resKey
+ config-deploy-properties:
+ service-instance-id: siid_1234
+ pnf-id: *pnfId
+ service-model-uuid: service-model-uuid
+ pnf-customization-uuid: pnf-customization-uuid
+ expectedResponse:
+ commonHeader: *commonHeader
+ actionIdentifiers: *deploy-ai
+ payload:
+ config-deploy-response: {}
+ status:
+ code: 200
+ errorMessage: null
+ eventType: EVENT_COMPONENT_EXECUTED
+ message: success
+ - name: preCheck
+ request:
+ commonHeader: &swugCommonHeader
+ originatorId: sdnc
+ requestId: "123456-1000"
+ subRequestId: sub-123456-1000
+ actionIdentifiers: &preCheck-ai
+ blueprintName: PNF_CDS_RESTCONF
+ blueprintVersion: "1.0.0"
+ actionName: preCheck
+ mode: sync
+ payload:
+ preCheck-request:
+ resolution-key: &resKey "RES-KEY 61"
+ preCheck-properties: &actionProps
+ service-instance-id: siid_1234
+ pnf-id: &pnfId pnf-id-2019-07-12
+ target-software-version: "2.0.2"
+ service-model-uuid: service-model-uuid
+ pnf-customization-uuid: pnf-customization-uuid
+ expectedResponse:
+ commonHeader: *swugCommonHeader
+ actionIdentifiers: *preCheck-ai
+ status:
+ code: 200
+ eventType: EVENT_COMPONENT_EXECUTED
+ errorMessage: null
+ message: success
+ payload:
+ preCheck-response: {}
+ - name: downloadNESw
+ request:
+ commonHeader: *swugCommonHeader
+ actionIdentifiers: &download-ai
+ blueprintName: PNF_CDS_RESTCONF
+ blueprintVersion: "1.0.0"
+ actionName: downloadNESw
+ mode: sync
+ payload:
+ downloadNESw-request:
+ resolution-key: *resKey
+ downloadNESw-properties: *actionProps
+ expectedResponse:
+ commonHeader: *swugCommonHeader
+ actionIdentifiers: *download-ai
+ status:
+ code: 200
+ eventType: EVENT_COMPONENT_EXECUTED
+ errorMessage: null
+ message: success
+ payload:
+ downloadNESw-response: {}
+ - name: activateNESw
+ request:
+ commonHeader: *swugCommonHeader
+ actionIdentifiers: &activate-ai
+ blueprintName: PNF_CDS_RESTCONF
+ blueprintVersion: "1.0.0"
+ actionName: activateNESw
+ mode: sync
+ payload:
+ activateNESw-request:
+ resolution-key: *resKey
+ activateNESw-properties: *actionProps
+ expectedResponse:
+ commonHeader: *swugCommonHeader
+ actionIdentifiers: *activate-ai
+ status:
+ code: 200
+ eventType: EVENT_COMPONENT_EXECUTED
+ errorMessage: null
+ message: success
+ payload:
+ activateNESw-response: {}
+ - name: postCheck
+ request:
+ commonHeader: *swugCommonHeader
+ actionIdentifiers: &postCheck-ai
+ blueprintName: PNF_CDS_RESTCONF
+ blueprintVersion: "1.0.0"
+ actionName: postCheck
+ mode: sync
+ payload:
+ postCheck-request:
+ resolution-key: *resKey
+ postCheck-properties: *actionProps
+ expectedResponse:
+ commonHeader: *swugCommonHeader
+ actionIdentifiers: *postCheck-ai
+ status:
+ code: 200
+ eventType: EVENT_COMPONENT_EXECUTED
+ errorMessage: null
+ message: success
+ payload:
+ postCheck-response: {}
+external-services:
+ - selector: aai-data
+ expectations:
+ - request:
+ method: GET
+ path: [ /aai/v14/network/pnfs/pnf, *pnfId]
+ headers:
+ Accept: application/json
+ response:
+ headers:
+ Content-Type: application/json
+ body:
+ ipaddress-v4-oam: &pnfAddress 13.13.13.13
+ ipaddress-v6-oam: 1::13
+ - selector: sdnc
+ expectations:
+ - request:
+ method: PUT
+ path: &configUri [ /restconf/config, &nodeIdentifier [network-topology:network-topology/topology/topology-netconf/node, *pnfId]]
+ headers:
+ Content-Type: application/json
+ body:
+ node:
+ - node-id: *pnfId
+ netconf-node-topology:protocol: { name: TLS }
+ netconf-node-topology:host: *pnfAddress
+ netconf-node-topology:key-based:
+ username: netconf
+ key-id: ODL_private_key_0
+ netconf-node-topology:port: 6513
+ netconf-node-topology:tcp-only: false
+ netconf-node-topology:max-connection-attempts: 5
+ response:
+ status: 201
+ - request:
+ method: GET
+ path: [ /restconf/operational, *nodeIdentifier]
+ response:
+ body:
+ node: [ { netconf-node-topology:connection-status: connected }]
+ - request:
+ method: GET
+ path: [*configUri, &configletResourcePath yang-ext:mount/mynetconf:netconflist]
+ response:
+ body: {}
+ - request:
+ method: PATCH
+ path: [*configUri, *configletResourcePath]
+ headers:
+ Content-Type: application/yang.patch+json
+ body:
+ ietf-restconf:yang-patch:
+ patch-id: patch-1
+ edit:
+ - edit-id: edit1
+ operation: merge
+ target: /
+ value: { netconflist: { netconf: [ { netconf-id: "10", netconf-param: "1000" }]}}
+ - edit-id: edit2
+ operation: merge
+ target: /
+ value: { netconflist: { netconf: [ { netconf-id: "20", netconf-param: "2000" }]}}
+ - edit-id: edit3
+ operation: merge
+ target: /
+ value: { netconflist: { netconf: [ { netconf-id: "30", netconf-param: "3000" }]}}
+ response:
+ body:
+ ietf-yang-patch:yang-patch-status:
+ patch-id: patch-1
+ ok: [
+ null
+ ]
+ ### External expectations for Software Upgrade
+ - request:
+ method: GET
+ path: &ConfigSwUgUri [*configUri, &configletResourcePath yang-ext:mount/pnf-sw-upgrade:software-upgrade]
+ headers:
+ Accept: application/json
+ responses:
+ - headers:
+ Content-Type: application/json
+ body:
+ software-upgrade:
+ upgrade-package:
+ - id: 2.0.1
+ current-status: INITIALIZED
+ user-label: trial software update
+ uri: sftp:127.0.0.1/test_software_1.img
+ software-version: 2.0.1
+ user: test_user
+ password: test_password
+ - headers:
+ Content-Type: application/json
+ body:
+ software-upgrade:
+ upgrade-package:
+ - id: 2.0.1
+ current-status: INITIALIZED
+ user-label: trial software update
+ uri: sftp:127.0.0.1/test_software_1.img
+ software-version: 2.0.1
+ user: test_user
+ password: test_password
+ - headers:
+ Content-Type: application/json
+ body:
+ software-upgrade:
+ upgrade-package:
+ - id: 2.0.1
+ current-status: INITIALIZED
+ user-label: trial software update
+ uri: sftp:127.0.0.1/test_software_1.img
+ software-version: 2.0.1
+ user: test_user
+ password: test_password
+ - id: 2.0.2
+ current-status: DOWNLOAD_COMPLETED
+ state-change-time: '2020-02-20T13:03:21Z'
+ software-version: 2.0.2
+ user-label: trial software update
+ uri: sftp:127.0.0.1/test_software_1.img
+ user: test_user
+ password: test_password
+ - headers:
+ Content-Type: application/json
+ body:
+ software-upgrade:
+ upgrade-package:
+ - id: 2.0.1
+ current-status: INITIALIZED
+ user-label: trial software update
+ uri: sftp:127.0.0.1/test_software_1.img
+ software-version: 2.0.1
+ user: test_user
+ password: test_password
+ - id: 2.0.2
+ current-status: ACTIVATION_COMPLETED
+ state-change-time: '2020-02-20T13:03:21Z'
+ software-version: 2.0.2
+ user-label: trial software update
+ uri: sftp:127.0.0.1/test_software_1.img
+ user: test_user
+ password: test_password
+ - request:
+ method: PATCH
+ path: *ConfigSwUgUri
+ headers:
+ Content-Type: application/yang.patch+json
+ body:
+ ietf-restconf:yang-patch:
+ patch-id: patch-1
+ edit:
+ - edit-id: edit1
+ operation: merge
+ target: "/"
+ response:
+ headers:
+ Content-Type: application/yang.patch-status+json
+ body:
+ { ietf-yang-patch:yang-patch-status: {patch-id: patch-1, ok: [ ] } }
+ times: 2
+ - request:
+ method: GET
+ path: [*ConfigSwUgUri, upgrade-package/2.0.2]
+ headers:
+ Accept: application/json
+ responses:
+ - headers:
+ Content-Type: application/json
+ body:
+ upgrade-package:
+ - id: 2.0.2
+ current-status: DOWNLOAD_IN_PROGRESS
+ state-change-time: '2020-02-20T12:17:34.984Z'
+ software-version: 2.0.2
+ - headers:
+ Content-Type: application/json
+ body:
+ upgrade-package:
+ - id: 2.0.2
+ current-status: DOWNLOAD_IN_PROGRESS
+ state-change-time: '2020-02-20T12:52:30Z'
+ software-version: 2.0.2
+ - headers:
+ Content-Type: application/json
+ body:
+ upgrade-package:
+ - id: 2.0.2
+ current-status: DOWNLOAD_COMPLETED
+ state-change-time: '2020-02-20T13:03:21Z'
+ software-version: 2.0.2
+ - headers:
+ Content-Type: application/json
+ body:
+ upgrade-package:
+ - id: 2.0.2
+ current-status: ACTIVATION_IN_PROGRESS
+ state-change-time: '2020-02-20T13:05:08Z'
+ software-version: 2.0.2
+ - headers:
+ Content-Type: application/json
+ body:
+ upgrade-package:
+ - id: 2.0.2
+ current-status: ACTIVATION_IN_PROGRESS
+ state-change-time: '2020-02-20T12:52:30Z'
+ software-version: 2.0.2
+ - headers:
+ Content-Type: application/json
+ body:
+ upgrade-package:
+ - id: 2.0.2
+ current-status: ACTIVATION_COMPLETED
+ state-change-time: '2020-02-20T13:07:12Z'
+ software-version: 2.0.2
+ - request:
+ method: DELETE
+ path: *configUri
+ times: 5 \ No newline at end of file
diff --git a/components/model-catalog/blueprint-model/uat-blueprints/README.md b/components/model-catalog/blueprint-model/uat-blueprints/README.md
index 56cb32989..ffbc15aec 100644
--- a/components/model-catalog/blueprint-model/uat-blueprints/README.md
+++ b/components/model-catalog/blueprint-model/uat-blueprints/README.md
@@ -61,7 +61,8 @@ message Uat {
message Expectation {
required Request request = 1;
- required Response response = 2;
+ optional Response response = 2;
+ repeated Response responses = 3;
}
message ExternalService {
diff --git a/components/model-catalog/blueprint-model/uat-blueprints/pnf_config/Tests/uat.yaml b/components/model-catalog/blueprint-model/uat-blueprints/pnf_config/Tests/uat.yaml
index 85b10c611..a58d089ad 100644
--- a/components/model-catalog/blueprint-model/uat-blueprints/pnf_config/Tests/uat.yaml
+++ b/components/model-catalog/blueprint-model/uat-blueprints/pnf_config/Tests/uat.yaml
@@ -64,7 +64,7 @@ external-services:
expectations:
- request:
method: PUT
- path: &configUri [ restconf/config, &nodeIdentifier [network-topology:network-topology/topology/topology-netconf/node, *pnfId]]
+ path: &configUri [ /restconf/config, &nodeIdentifier [network-topology:network-topology/topology/topology-netconf/node, *pnfId]]
headers:
Content-Type: application/json
body:
@@ -82,7 +82,7 @@ external-services:
status: 201
- request:
method: GET
- path: [ restconf/operational, *nodeIdentifier]
+ path: [ /restconf/operational, *nodeIdentifier]
response:
body:
node: [ { netconf-node-topology:connection-status: connected }]
diff --git a/components/model-catalog/blueprint-model/uat-blueprints/pnf_config_aai/Definitions/data_types.json b/components/model-catalog/blueprint-model/uat-blueprints/pnf_config_aai/Definitions/data_types.json
deleted file mode 100644
index a0804bb3f..000000000
--- a/components/model-catalog/blueprint-model/uat-blueprints/pnf_config_aai/Definitions/data_types.json
+++ /dev/null
@@ -1,23 +0,0 @@
-{
- "data_types" : {
- "dt-config-assign-properties" : {
- "description" : "Dynamic DataType definition for workflow(config-assign).",
- "version" : "1.0.0",
- "properties" : { },
- "derived_from" : "tosca.datatypes.Dynamic"
- },
- "dt-config-deploy-properties" : {
- "description" : "Dynamic DataType definition for workflow(config-deploy).",
- "version" : "1.0.0",
- "properties" : {
- "pnf-ipv4-address" : {
- "type" : "string"
- },
- "pnf-id" : {
- "type" : "string"
- }
- },
- "derived_from" : "tosca.datatypes.Dynamic"
- }
- }
-} \ No newline at end of file
diff --git a/components/model-catalog/blueprint-model/uat-blueprints/pnf_config_aai/Definitions/pnf_config_aai.json b/components/model-catalog/blueprint-model/uat-blueprints/pnf_config_aai/Definitions/pnf_config_aai.json
deleted file mode 100644
index 3ef585cb4..000000000
--- a/components/model-catalog/blueprint-model/uat-blueprints/pnf_config_aai/Definitions/pnf_config_aai.json
+++ /dev/null
@@ -1,152 +0,0 @@
-{
- "tosca_definitions_version" : "controller_blueprint_1_0_0",
- "metadata" : {
- "template_author" : "Rahul Tyagi",
- "author-email" : "rahul.tyagi@est.tech",
- "user-groups" : "ADMIN, OPERATION",
- "template_name" : "pnf_config_aai",
- "template_version" : "1.0.0",
- "template_tags" : "pnf, restconf, config, configuration"
- },
- "imports" : [ {
- "file" : "Definitions/data_types.json"
- }, {
- "file" : "Definitions/relationship_types.json"
- }, {
- "file" : "Definitions/artifact_types.json"
- }, {
- "file" : "Definitions/node_types.json"
- }, {
- "file" : "Definitions/policy_types.json"
- } ],
- "dsl_definitions" : {
- "config-deploy-properties" : {
- "resolution-key" : {
- "get_input" : "resolution-key"
- }
- }
- },
- "topology_template" : {
- "workflows" : {
- "config-assign" : {
- "steps" : {
- "activate-process" : {
- "description" : "Create a configlet",
- "target" : "config-assign",
- "activities" : [ {
- "call_operation" : ""
- } ]
- }
- },
- "inputs" : {
- "resolution-key" : {
- "required" : true,
- "type" : "string"
- },
- "store-result" : {
- "required" : true,
- "type" : "boolean"
- },
- "config-assign-properties" : {
- "description" : "Dynamic PropertyDefinition for workflow(config-assign).",
- "required" : true,
- "type" : "dt-config-assign-properties"
- }
- }
- },
- "config-deploy" : {
- "steps" : {
- "activate-process" : {
- "description" : "Send a configlet to the pnf",
- "target" : "config-deploy",
- "activities" : [ {
- "call_operation" : ""
- } ]
- }
- },
- "inputs" : {
- "resolution-key" : {
- "required" : true,
- "type" : "string"
- },
- "config-deploy-properties" : {
- "description" : "Dynamic PropertyDefinition for workflow(config-deploy).",
- "required" : true,
- "type" : "dt-config-deploy-properties"
- }
- }
- }
- },
- "node_templates" : {
- "config-assign" : {
- "type" : "component-resource-resolution",
- "interfaces" : {
- "ResourceResolutionComponent" : {
- "operations" : {
- "process" : {
- "inputs" : {
- "resolution-key" : {
- "get_input" : "resolution-key"
- },
- "store-result" : true,
- "artifact-prefix-names" : [ "config-assign" ]
- },
- "outputs" : {
- "resource-assignment-params" : {
- "get_attribute" : [ "SELF", "assignment-params" ]
- },
- "status" : "success"
- }
- }
- }
- }
- },
- "artifacts" : {
- "config-assign-template" : {
- "type" : "artifact-template-velocity",
- "file" : "Templates/config-assign-restconf-configlet-template.vtl"
- },
- "config-assign-mapping" : {
- "type" : "artifact-mapping-resource",
- "file" : "Definitions/config-assign-pnf-mapping.json"
- }
- }
- },
- "config-deploy" : {
- "type" : "component-script-executor",
- "interfaces" : {
- "ComponentScriptExecutor" : {
- "operations" : {
- "process" : {
- "implementation" : {
- "primary" : "component-script",
- "timeout" : 180,
- "operation_host" : "SELF"
- },
- "inputs" : {
- "script-type" : "kotlin",
- "script-class-reference" : "cba.pnf.config.aai.RestconfConfigDeploy",
- "dynamic-properties" : "*config-deploy-properties"
- },
- "outputs" : {
- "response-data" : "",
- "status" : "success"
- }
- }
- }
- }
- },
- "artifacts" : {
- "config-deploy-template" : {
- "type" : "artifact-template-velocity",
- "file" : "Templates/config-deploy-restconf-mount-template.vtl"
- },
- "config-deploy-mapping" : {
- "type" : "artifact-mapping-resource",
- "file" : "Definitions/config-deploy-pnf-mapping.json"
- }
- }
- }
- }
- }
-} \ No newline at end of file
diff --git a/components/model-catalog/blueprint-model/uat-blueprints/pnf_config_aai/TOSCA-Metadata/TOSCA.meta b/components/model-catalog/blueprint-model/uat-blueprints/pnf_config_aai/TOSCA-Metadata/TOSCA.meta
deleted file mode 100644
index 903600836..000000000
--- a/components/model-catalog/blueprint-model/uat-blueprints/pnf_config_aai/TOSCA-Metadata/TOSCA.meta
+++ /dev/null
@@ -1,7 +0,0 @@
-TOSCA-Meta-File-Version: 1.0.0
-CSAR-Version: 1.0
-Created-By: Rahul Tyagi
-Entry-Definitions: Definitions/pnf_config_aai.json
-Template-Name: pnf_config_aai
-Template-Version: 1.0.0
-Template-Tags: pnf_config_aai
diff --git a/components/model-catalog/blueprint-model/uat-blueprints/pnf_config_aai/Tests/uat.yaml b/components/model-catalog/blueprint-model/uat-blueprints/pnf_config_aai/Tests/uat.yaml
deleted file mode 100644
index 0692eea7f..000000000
--- a/components/model-catalog/blueprint-model/uat-blueprints/pnf_config_aai/Tests/uat.yaml
+++ /dev/null
@@ -1,130 +0,0 @@
-%YAML 1.1
----
-processes:
- - name: config-assign
- request:
- commonHeader: &commonHeader
- originatorId: sdnc
- requestId: "123456-1000"
- subRequestId: sub-123456-1000
- actionIdentifiers: &assign-ai
- blueprintName: pnf_config_aai
- blueprintVersion: "1.0.0"
- actionName: config-assign
- mode: sync
- payload:
- config-assign-request:
- resolution-key: &resKey "RES-KEY 61"
- config-assign-properties:
- service-instance-id: siid_1234
- pnf-id: &pnfId pnf-id-2019-07-12
- service-model-uuid: service-model-uuid
- pnf-customization-uuid: pnf-customization-uuid
- expectedResponse:
- commonHeader: *commonHeader
- actionIdentifiers: *assign-ai
- status:
- code: 200
- eventType: EVENT_COMPONENT_EXECUTED
- errorMessage: null
- message: success
- payload:
- config-assign-response: {}
- - name: config-deploy
- request:
- commonHeader: *commonHeader
- actionIdentifiers: &deploy-ai
- actionName: config-deploy
- blueprintName: pnf_config_aai
- blueprintVersion: "1.0.0"
- mode: sync
- payload:
- config-deploy-request:
- resolution-key: *resKey
- config-deploy-properties:
- service-instance-id: siid_1234
- pnf-id: *pnfId
- service-model-uuid: service-model-uuid
- pnf-customization-uuid: pnf-customization-uuid
- expectedResponse:
- commonHeader: *commonHeader
- actionIdentifiers: *deploy-ai
- payload:
- config-deploy-response: {}
- status:
- code: 200
- errorMessage: null
- eventType: EVENT_COMPONENT_EXECUTED
- message: success
-
-external-services:
- - selector: aai-data
- expectations:
- - request:
- method: GET
- path: [ /aai/v14/network/pnfs/pnf, *pnfId]
- headers:
- Accept: application/json
- response:
- headers:
- Content-Type: application/json
- body:
- ipaddress-v4-oam: &pnfAddress 13.13.13.13
- ipaddress-v6-oam: 1::13
- - selector: sdnc
- expectations:
- - request:
- method: PUT
- path: &configUri [ restconf/config, &nodeIdentifier [network-topology:network-topology/topology/topology-netconf/node, *pnfId]]
- headers:
- Content-Type: application/json
- body:
- node:
- - node-id: *pnfId
- netconf-node-topology:protocol: { name: TLS }
- netconf-node-topology:host: *pnfAddress
- netconf-node-topology:key-based:
- username: netconf
- key-id: ODL_private_key_0
- netconf-node-topology:port: 6513
- netconf-node-topology:tcp-only: false
- netconf-node-topology:max-connection-attempts: 5
- response:
- status: 201
- - request:
- method: GET
- path: [ restconf/operational, *nodeIdentifier]
- response:
- body:
- node: [ { netconf-node-topology:connection-status: connected }]
- - request:
- method: GET
- path: [*configUri, &configletResourcePath yang-ext:mount/mynetconf:netconflist]
- response:
- body: {}
- - request:
- method: PATCH
- path: [*configUri, *configletResourcePath]
- headers:
- Content-Type: application/yang.patch+json
- body:
- ietf-restconf:yang-patch:
- patch-id: patch-1
- edit:
- - edit-id: edit1
- operation: merge
- target: /
- value: { netconflist: { netconf: [ { netconf-id: "10", netconf-param: "1000" }]}}
- - edit-id: edit2
- operation: merge
- target: /
- value: { netconflist: { netconf: [ { netconf-id: "20", netconf-param: "2000" }]}}
- - edit-id: edit3
- operation: merge
- target: /
- value: { netconflist: { netconf: [ { netconf-id: "30", netconf-param: "3000" }]}}
- - request:
- method: DELETE
- path: *configUri
-
-
diff --git a/components/model-catalog/definition-type/starter-type/node_type/component-resource-resolution.json b/components/model-catalog/definition-type/starter-type/node_type/component-resource-resolution.json
index 1c81b7f6e..ff1b5260e 100644
--- a/components/model-catalog/definition-type/starter-type/node_type/component-resource-resolution.json
+++ b/components/model-catalog/definition-type/starter-type/node_type/component-resource-resolution.json
@@ -38,6 +38,11 @@
"required": false,
"type": "string"
},
+ "resolution-summary": {
+ "description": "Enable resolution-summary output",
+ "required": false,
+ "type": "boolean"
+ },
"artifact-prefix-names": {
"required": true,
"description": "Template , Resource Assignment Artifact Prefix names",
diff --git a/ms/blueprintsprocessor/application/pom.xml b/ms/blueprintsprocessor/application/pom.xml
index b007ac7fb..18a61e0e6 100755
--- a/ms/blueprintsprocessor/application/pom.xml
+++ b/ms/blueprintsprocessor/application/pom.xml
@@ -46,9 +46,9 @@
<dependencies>
<dependency>
- <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId>
- <artifactId>blueprint-core</artifactId>
- <exclusions>
+ <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId>
+ <artifactId>blueprint-core</artifactId>
+ <exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
@@ -66,6 +66,12 @@
</exclusions>
</dependency>
+ <!-- Error Catalog Services -->
+ <dependency>
+ <groupId>org.onap.ccsdk.cds.error.catalog</groupId>
+ <artifactId>error-catalog-services</artifactId>
+ </dependency>
+
<!-- North Bound -->
<dependency>
<groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId>
@@ -99,6 +105,10 @@
</dependency>
<dependency>
<groupId>org.onap.ccsdk.cds.blueprintsprocessor.functions</groupId>
+ <artifactId>restful-executor</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.cds.blueprintsprocessor.functions</groupId>
<artifactId>ansible-awx-executor</artifactId>
</dependency>
<dependency>
@@ -153,6 +163,9 @@
<dependency>
<groupId>com.nhaarman.mockitokotlin2</groupId>
<artifactId>mockito-kotlin</artifactId>
+ <!-- It's unusual but 'compile' here is the right scope since mockito is being used at runtime by
+ the UatServices (/api/v1/uat/spy and /api/v1/uat/verify endpoints) -->
+ <scope>compile</scope>
</dependency>
<dependency>
<groupId>com.schibsted.spt.data</groupId>
@@ -299,6 +312,10 @@
<target>1.8</target>
</configuration>
</plugin>
+ <plugin>
+ <groupId>pl.project13.maven</groupId>
+ <artifactId>git-commit-id-plugin</artifactId>
+ </plugin>
</plugins>
</build>
diff --git a/ms/blueprintsprocessor/application/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/BlueprintDatabaseConfiguration.kt b/ms/blueprintsprocessor/application/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/BlueprintDatabaseConfiguration.kt
index 58464cb10..e9557aed9 100644
--- a/ms/blueprintsprocessor/application/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/BlueprintDatabaseConfiguration.kt
+++ b/ms/blueprintsprocessor/application/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/BlueprintDatabaseConfiguration.kt
@@ -31,7 +31,8 @@ import javax.sql.DataSource
@Configuration
@Import(BluePrintDBLibConfiguration::class)
@EnableJpaRepositories(
- basePackages = ["org.onap.ccsdk.cds.controllerblueprints", "org.onap.ccsdk.cds.blueprintsprocessor"],
+ basePackages = ["org.onap.ccsdk.cds.controllerblueprints", "org.onap.ccsdk.cds.blueprintsprocessor",
+ "org.onap.ccsdk.cds.error.catalog"],
entityManagerFactoryRef = "primaryEntityManager",
transactionManagerRef = "primaryTransactionManager"
)
@@ -43,7 +44,8 @@ open class BlueprintDatabaseConfiguration(primaryDataSourceProperties: PrimaryDa
open fun primaryEntityManager(): LocalContainerEntityManagerFactoryBean {
return primaryEntityManager(
"org.onap.ccsdk.cds.controllerblueprints",
- "org.onap.ccsdk.cds.blueprintsprocessor"
+ "org.onap.ccsdk.cds.blueprintsprocessor",
+ "org.onap.ccsdk.cds.error.catalog"
)
}
diff --git a/ms/blueprintsprocessor/application/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/BlueprintProcessorApplication.kt b/ms/blueprintsprocessor/application/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/BlueprintProcessorApplication.kt
index 1d1baeeef..97b7d28b0 100644
--- a/ms/blueprintsprocessor/application/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/BlueprintProcessorApplication.kt
+++ b/ms/blueprintsprocessor/application/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/BlueprintProcessorApplication.kt
@@ -30,7 +30,10 @@ import org.springframework.context.annotation.ComponentScan
*/
@SpringBootApplication
@EnableAutoConfiguration(exclude = [DataSourceAutoConfiguration::class, HazelcastAutoConfiguration::class])
-@ComponentScan(basePackages = ["org.onap.ccsdk.cds.blueprintsprocessor", "org.onap.ccsdk.cds.controllerblueprints"])
+@ComponentScan(
+ basePackages = ["org.onap.ccsdk.cds.error.catalog",
+ "org.onap.ccsdk.cds.blueprintsprocessor", "org.onap.ccsdk.cds.controllerblueprints"]
+)
open class BlueprintProcessorApplication
fun main(args: Array<String>) {
diff --git a/ms/blueprintsprocessor/application/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/BlueprintProcessorExceptionHandler.kt b/ms/blueprintsprocessor/application/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/BlueprintProcessorExceptionHandler.kt
new file mode 100644
index 000000000..f241e3f42
--- /dev/null
+++ b/ms/blueprintsprocessor/application/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/BlueprintProcessorExceptionHandler.kt
@@ -0,0 +1,25 @@
+/*
+ * Copyright © 2018-2019 AT&T Intellectual Property.
+ *
+ * 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.
+ */
+
+package org.onap.ccsdk.cds.blueprintsprocessor
+
+import org.onap.ccsdk.cds.error.catalog.services.ErrorCatalogExceptionHandler
+import org.onap.ccsdk.cds.error.catalog.services.ErrorCatalogService
+import org.springframework.web.bind.annotation.RestControllerAdvice
+
+@RestControllerAdvice("org.onap.ccsdk.cds")
+open class BlueprintProcessorExceptionHandler(private val errorCatalogService: ErrorCatalogService) :
+ ErrorCatalogExceptionHandler(errorCatalogService)
diff --git a/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/logging/ColorMarker.kt b/ms/blueprintsprocessor/application/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/logging/ColorMarker.kt
index 9ae3ff805..9ae3ff805 100644
--- a/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/logging/ColorMarker.kt
+++ b/ms/blueprintsprocessor/application/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/logging/ColorMarker.kt
diff --git a/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/logging/LogColor.kt b/ms/blueprintsprocessor/application/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/logging/LogColor.kt
index f0cba2670..f0cba2670 100644
--- a/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/logging/LogColor.kt
+++ b/ms/blueprintsprocessor/application/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/logging/LogColor.kt
diff --git a/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/logging/MockInvocationLogger.kt b/ms/blueprintsprocessor/application/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/logging/MockInvocationLogger.kt
index f8e6bd486..f8e6bd486 100644
--- a/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/logging/MockInvocationLogger.kt
+++ b/ms/blueprintsprocessor/application/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/logging/MockInvocationLogger.kt
diff --git a/ms/blueprintsprocessor/application/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/InvalidUatDefinition.kt b/ms/blueprintsprocessor/application/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/InvalidUatDefinition.kt
new file mode 100644
index 000000000..4a756411f
--- /dev/null
+++ b/ms/blueprintsprocessor/application/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/InvalidUatDefinition.kt
@@ -0,0 +1,22 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2020 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.ccsdk.cds.blueprintsprocessor.uat.utils
+
+class InvalidUatDefinition(message: String) : RuntimeException(message)
diff --git a/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/JsonNormalizer.kt b/ms/blueprintsprocessor/application/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/JsonNormalizer.kt
index 39caa0178..39caa0178 100644
--- a/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/JsonNormalizer.kt
+++ b/ms/blueprintsprocessor/application/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/JsonNormalizer.kt
diff --git a/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/PathDeserializer.kt b/ms/blueprintsprocessor/application/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/PathDeserializer.kt
index 6c5759155..6c5759155 100644
--- a/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/PathDeserializer.kt
+++ b/ms/blueprintsprocessor/application/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/PathDeserializer.kt
diff --git a/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/RequiredMapEntriesMatcher.kt b/ms/blueprintsprocessor/application/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/RequiredMapEntriesMatcher.kt
index 0f98d7213..0f98d7213 100644
--- a/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/RequiredMapEntriesMatcher.kt
+++ b/ms/blueprintsprocessor/application/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/RequiredMapEntriesMatcher.kt
diff --git a/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/UatDefinition.kt b/ms/blueprintsprocessor/application/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/UatDefinition.kt
index c45ac45c6..17b79f588 100644
--- a/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/UatDefinition.kt
+++ b/ms/blueprintsprocessor/application/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/UatDefinition.kt
@@ -47,18 +47,30 @@ data class RequestDefinition(
)
@JsonInclude(JsonInclude.Include.NON_EMPTY)
-data class ResponseDefinition(val status: Int = 200, val body: JsonNode? = null) {
+data class ResponseDefinition(val status: Int = 200, val body: JsonNode? = null, val headers: Map<String, String> = mapOf("Content-Type" to "application/json")) {
companion object {
- val DEFAULT_RESPONSE = ResponseDefinition()
+ val DEFAULT_RESPONSES = listOf(ResponseDefinition())
}
}
@JsonInclude(JsonInclude.Include.NON_EMPTY)
-data class ExpectationDefinition(
+class ExpectationDefinition(
val request: RequestDefinition,
- val response: ResponseDefinition = ResponseDefinition.DEFAULT_RESPONSE
-)
+ response: ResponseDefinition?,
+ responses: List<ResponseDefinition>? = null,
+ val times: String = ">= 1"
+) {
+ val responses: List<ResponseDefinition> = resolveOneOrMany(response, responses, ResponseDefinition.DEFAULT_RESPONSES)
+
+ companion object {
+ fun <T> resolveOneOrMany(one: T?, many: List<T>?, defaultMany: List<T>): List<T> = when {
+ many != null -> many
+ one != null -> listOf(one)
+ else -> defaultMany
+ }
+ }
+}
@JsonInclude(JsonInclude.Include.NON_EMPTY)
data class ServiceDefinition(val selector: String, val expectations: List<ExpectationDefinition>)
@@ -97,6 +109,6 @@ data class UatDefinition(
companion object {
fun load(mapper: ObjectMapper, spec: String): UatDefinition =
- mapper.convertValue(Yaml().load(spec), UatDefinition::class.java)
+ mapper.convertValue(Yaml().load(spec), UatDefinition::class.java)
}
}
diff --git a/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/UatExecutor.kt b/ms/blueprintsprocessor/application/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/UatExecutor.kt
index a904fa9b6..d120e71d6 100644
--- a/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/UatExecutor.kt
+++ b/ms/blueprintsprocessor/application/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/UatExecutor.kt
@@ -24,9 +24,10 @@ import com.fasterxml.jackson.databind.ObjectMapper
import com.nhaarman.mockitokotlin2.any
import com.nhaarman.mockitokotlin2.argThat
import com.nhaarman.mockitokotlin2.atLeast
-import com.nhaarman.mockitokotlin2.atLeastOnce
+import com.nhaarman.mockitokotlin2.atMost
import com.nhaarman.mockitokotlin2.eq
import com.nhaarman.mockitokotlin2.mock
+import com.nhaarman.mockitokotlin2.times
import com.nhaarman.mockitokotlin2.verify
import com.nhaarman.mockitokotlin2.verifyNoMoreInteractions
import com.nhaarman.mockitokotlin2.whenever
@@ -44,6 +45,7 @@ import org.hamcrest.CoreMatchers.equalTo
import org.hamcrest.CoreMatchers.notNullValue
import org.hamcrest.MatcherAssert.assertThat
import org.mockito.Answers
+import org.mockito.verification.VerificationMode
import org.onap.ccsdk.cds.blueprintsprocessor.rest.service.BluePrintRestLibPropertyService
import org.onap.ccsdk.cds.blueprintsprocessor.rest.service.BlueprintWebClientService
import org.onap.ccsdk.cds.blueprintsprocessor.rest.service.BlueprintWebClientService.WebClientResponse
@@ -77,7 +79,8 @@ class UatExecutor(
companion object {
private const val NOOP_PASSWORD_PREFIX = "{noop}"
-
+ private const val PROPERTY_IN_UAT = "IN_UAT"
+ private val TIMES_SPEC_REGEX = "([<>]=?)?\\s*(\\d+)".toRegex()
private val log: Logger = LoggerFactory.getLogger(UatExecutor::class.java)
private val mockLoggingListener = MockInvocationLogger(markerOf(COLOR_MOCKITO))
}
@@ -103,23 +106,24 @@ class UatExecutor(
fun execute(uat: UatDefinition, cbaBytes: ByteArray): UatDefinition {
val defaultHeaders = listOf(BasicHeader(HttpHeaders.AUTHORIZATION, clientAuthToken()))
val httpClient = HttpClientBuilder.create()
- .setDefaultHeaders(defaultHeaders)
- .build()
+ .setDefaultHeaders(defaultHeaders)
+ .build()
// Only if externalServices are defined
val mockInterceptor = MockPreInterceptor()
// Always defined and used, whatever the case
val spyInterceptor = SpyPostInterceptor(mapper)
restClientFactory.setInterceptors(mockInterceptor, spyInterceptor)
try {
- // Configure mocked external services and save their expected requests for further validation
- val requestsPerClient = uat.externalServices.associateBy(
- { service ->
- createRestClientMock(service.expectations).also { restClient ->
- // side-effect: register restClient to override real instance
- mockInterceptor.registerMock(service.selector, restClient)
- }
- },
- { service -> service.expectations.map { it.request } }
+ markUatBegin()
+ // Configure mocked external services and save their expectations for further validation
+ val expectationsPerClient = uat.externalServices.associateBy(
+ { service ->
+ createRestClientMock(service.expectations).also { restClient ->
+ // side-effect: register restClient to override real instance
+ mockInterceptor.registerMock(service.selector, restClient)
+ }
+ },
+ { service -> service.expectations }
)
val newProcesses = httpClient.use { client ->
@@ -130,26 +134,27 @@ class UatExecutor(
log.info("Executing process '${process.name}'")
val responseNormalizer = JsonNormalizer.getNormalizer(mapper, process.responseNormalizerSpec)
val actualResponse = processBlueprint(
- client, process.request,
- process.expectedResponse, responseNormalizer
+ client, process.request,
+ process.expectedResponse, responseNormalizer
)
ProcessDefinition(
- process.name,
- process.request,
- actualResponse,
- process.responseNormalizerSpec
+ process.name,
+ process.request,
+ actualResponse,
+ process.responseNormalizerSpec
)
}
}
// Validate requests to external services
- for ((mockClient, requests) in requestsPerClient) {
- requests.forEach { request ->
- verify(mockClient, atLeastOnce()).exchangeResource(
- eq(request.method),
- eq(request.path),
- argThat { assertJsonEquals(request.body, this) },
- argThat(RequiredMapEntriesMatcher(request.headers))
+ for ((mockClient, expectations) in expectationsPerClient) {
+ expectations.forEach { expectation ->
+ val request = expectation.request
+ verify(mockClient, evalVerificationMode(expectation.times)).exchangeResource(
+ eq(request.method),
+ eq(request.path),
+ argThat { assertJsonEquals(request.body, this) },
+ argThat(RequiredMapEntriesMatcher(request.headers))
)
}
// Don't mind the invocations to the overloaded exchangeResource(String, String, String)
@@ -158,40 +163,51 @@ class UatExecutor(
}
val newExternalServices = spyInterceptor.getSpies()
- .map(SpyService::asServiceDefinition)
+ .map(SpyService::asServiceDefinition)
return UatDefinition(newProcesses, newExternalServices)
} finally {
restClientFactory.clearInterceptors()
+ markUatEnd()
}
}
+ private fun markUatBegin() {
+ System.setProperty(PROPERTY_IN_UAT, "1")
+ }
+
+ private fun markUatEnd() {
+ System.clearProperty(PROPERTY_IN_UAT)
+ }
+
private fun createRestClientMock(restExpectations: List<ExpectationDefinition>):
BlueprintWebClientService {
val restClient = mock<BlueprintWebClientService>(
- defaultAnswer = Answers.RETURNS_SMART_NULLS,
- // our custom verboseLogging handler
- invocationListeners = arrayOf(mockLoggingListener)
+ defaultAnswer = Answers.RETURNS_SMART_NULLS,
+ // our custom verboseLogging handler
+ invocationListeners = arrayOf(mockLoggingListener)
)
// Delegates to overloaded exchangeResource(String, String, String, Map<String, String>)
whenever(restClient.exchangeResource(any(), any(), any()))
- .thenAnswer { invocation ->
- val method = invocation.arguments[0] as String
- val path = invocation.arguments[1] as String
- val request = invocation.arguments[2] as String
- restClient.exchangeResource(method, path, request, emptyMap())
- }
+ .thenAnswer { invocation ->
+ val method = invocation.arguments[0] as String
+ val path = invocation.arguments[1] as String
+ val request = invocation.arguments[2] as String
+ restClient.exchangeResource(method, path, request, emptyMap())
+ }
for (expectation in restExpectations) {
- whenever(
- restClient.exchangeResource(
- eq(expectation.request.method),
- eq(expectation.request.path),
- any(),
- any()
- )
+ var stubbing = whenever(
+ restClient.exchangeResource(
+ eq(expectation.request.method),
+ eq(expectation.request.path),
+ any(),
+ any()
+ )
)
- .thenReturn(WebClientResponse(expectation.response.status, expectation.response.body.toString()))
+ for (response in expectation.responses) {
+ stubbing = stubbing.thenReturn(WebClientResponse(response.status, response.body.toString()))
+ }
}
return restClient
}
@@ -199,9 +215,9 @@ class UatExecutor(
@Throws(AssertionError::class)
private fun uploadBlueprint(client: HttpClient, cbaBytes: ByteArray) {
val multipartEntity = MultipartEntityBuilder.create()
- .setMode(HttpMultipartMode.BROWSER_COMPATIBLE)
- .addBinaryBody("file", cbaBytes, ContentType.DEFAULT_BINARY, "cba.zip")
- .build()
+ .setMode(HttpMultipartMode.BROWSER_COMPATIBLE)
+ .addBinaryBody("file", cbaBytes, ContentType.DEFAULT_BINARY, "cba.zip")
+ .build()
val request = HttpPost("$baseUrl/api/v1/blueprint-model/publish").apply {
entity = multipartEntity
}
@@ -236,6 +252,19 @@ class UatExecutor(
return mapper.readTree(actualResponse)!!
}
+ private fun evalVerificationMode(times: String): VerificationMode {
+ val matchResult = TIMES_SPEC_REGEX.matchEntire(times) ?: throw InvalidUatDefinition(
+ "Time specification '$times' does not follow expected format $TIMES_SPEC_REGEX")
+ val counter = matchResult.groups[2]!!.value.toInt()
+ return when (matchResult.groups[1]?.value) {
+ ">=" -> atLeast(counter)
+ ">" -> atLeast(counter + 1)
+ "<=" -> atMost(counter)
+ "<" -> atMost(counter - 1)
+ else -> times(counter)
+ }
+ }
+
@Throws(AssertionError::class)
private fun assertJsonEquals(expected: JsonNode?, actual: String): Boolean {
// special case
@@ -249,15 +278,15 @@ class UatExecutor(
}
private fun localServerPort(): Int =
- (environment.getProperty("local.server.port")
- ?: environment.getRequiredProperty("blueprint.httpPort")).toInt()
+ (environment.getProperty("local.server.port")
+ ?: environment.getRequiredProperty("blueprint.httpPort")).toInt()
private fun clientAuthToken(): String {
val username = environment.getRequiredProperty("security.user.name")
val password = environment.getRequiredProperty("security.user.password")
val plainPassword = when {
password.startsWith(NOOP_PASSWORD_PREFIX) -> password.substring(
- NOOP_PASSWORD_PREFIX.length)
+ NOOP_PASSWORD_PREFIX.length)
else -> username
}
return "Basic " + Base64Utils.encodeToString("$username:$plainPassword".toByteArray())
@@ -271,7 +300,7 @@ class UatExecutor(
}
override fun getInstance(selector: String): BlueprintWebClientService? =
- mocks[selector]
+ mocks[selector]
fun registerMock(selector: String, client: BlueprintWebClientService) {
mocks[selector] = client
@@ -293,7 +322,7 @@ class UatExecutor(
}
fun getSpies(): List<SpyService> =
- spies.values.toList()
+ spies.values.toList()
}
private class SpyService(
@@ -301,14 +330,14 @@ class UatExecutor(
val selector: String,
private val realService: BlueprintWebClientService
) :
- BlueprintWebClientService by realService {
+ BlueprintWebClientService by realService {
private val expectations: MutableList<ExpectationDefinition> = mutableListOf()
override fun exchangeResource(methodType: String, path: String, request: String): WebClientResponse<String> =
- exchangeResource(methodType, path, request,
- DEFAULT_HEADERS
- )
+ exchangeResource(methodType, path, request,
+ DEFAULT_HEADERS
+ )
override fun exchangeResource(
methodType: String,
@@ -317,7 +346,7 @@ class UatExecutor(
headers: Map<String, String>
): WebClientResponse<String> {
val requestDefinition =
- RequestDefinition(methodType, path, headers, toJson(request))
+ RequestDefinition(methodType, path, headers, toJson(request))
val realAnswer = realService.exchangeResource(methodType, path, request, headers)
val responseBody = when {
// TODO: confirm if we need to normalize the response here
@@ -325,12 +354,12 @@ class UatExecutor(
else -> null
}
val responseDefinition =
- ResponseDefinition(realAnswer.status, responseBody)
+ ResponseDefinition(realAnswer.status, responseBody)
expectations.add(
- ExpectationDefinition(
- requestDefinition,
- responseDefinition
- )
+ ExpectationDefinition(
+ requestDefinition,
+ responseDefinition
+ )
)
return realAnswer
}
@@ -340,7 +369,7 @@ class UatExecutor(
}
fun asServiceDefinition() =
- ServiceDefinition(selector, expectations)
+ ServiceDefinition(selector, expectations)
private fun toJson(str: String): JsonNode? {
return when {
@@ -351,8 +380,8 @@ class UatExecutor(
companion object {
private val DEFAULT_HEADERS = mapOf(
- HttpHeaders.CONTENT_TYPE to MediaType.APPLICATION_JSON_VALUE,
- HttpHeaders.ACCEPT to MediaType.APPLICATION_JSON_VALUE
+ HttpHeaders.CONTENT_TYPE to MediaType.APPLICATION_JSON_VALUE,
+ HttpHeaders.ACCEPT to MediaType.APPLICATION_JSON_VALUE
)
}
}
diff --git a/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/UatServices.kt b/ms/blueprintsprocessor/application/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/UatServices.kt
index f40b903de..f40b903de 100644
--- a/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/UatServices.kt
+++ b/ms/blueprintsprocessor/application/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/UatServices.kt
diff --git a/ms/blueprintsprocessor/application/src/main/resources/application-dev.properties b/ms/blueprintsprocessor/application/src/main/resources/application-dev.properties
index fffc2f4c6..5beebd8e8 100755
--- a/ms/blueprintsprocessor/application/src/main/resources/application-dev.properties
+++ b/ms/blueprintsprocessor/application/src/main/resources/application-dev.properties
@@ -27,6 +27,11 @@ server.port=8081
security.user.password: {bcrypt}$2a$10$duaUzVUVW0YPQCSIbGEkQOXwafZGwQ/b32/Ys4R1iwSSawFgz7QNu
security.user.name: ccsdkapps
+# Error Managements
+error.catalog.applicationId=cds
+error.catalog.type=properties
+error.catalog.errorDefinitionDir=./src/main/resources/
+
### START -Controller Blueprints Properties
# Load Resource Source Mappings
resourceSourceMappings=processor-db=source-db,input=source-input,default=source-default,sdnc=source-rest,aai-data=source-rest,capability=source-capability,vault-data=source-rest,rest=source-rest,script=source-capability
@@ -137,4 +142,4 @@ blueprintsprocessor.messageproducer.self-service-api.topic=producer.t
#blueprintsprocessor.messageconsumer.prioritize-input.type=kafka-streams-basic-auth
#blueprintsprocessor.messageconsumer.prioritize-input.bootstrapServers=127.0.0.1:9092
#blueprintsprocessor.messageconsumer.prioritize-input.applicationId=cds-controller
-#blueprintsprocessor.messageconsumer.prioritize-input.topic=prioritize-input-topic \ No newline at end of file
+#blueprintsprocessor.messageconsumer.prioritize-input.topic=prioritize-input-topic
diff --git a/ms/blueprintsprocessor/application/src/main/resources/application-local.yml b/ms/blueprintsprocessor/application/src/main/resources/application-local.yml
index de2cf4e52..f2843322c 100644
--- a/ms/blueprintsprocessor/application/src/main/resources/application-local.yml
+++ b/ms/blueprintsprocessor/application/src/main/resources/application-local.yml
@@ -38,10 +38,10 @@ blueprintsprocessor:
remoteScriptCommand:
enabled: true
restclient:
- sdncodl:
+ sdnc:
password: Kp8bJ4SXszM0WXlhak3eHlcse2gAw84vaoGGmJvUy2U
type: basic-auth
- url: http://localhost:8282/
+ url: http://localhost:8282
username: admin
restconfEnabled: true
controllerblueprints:
diff --git a/ms/blueprintsprocessor/application/src/main/resources/application.properties b/ms/blueprintsprocessor/application/src/main/resources/application.properties
index d6082bfa9..74549b0ae 100755
--- a/ms/blueprintsprocessor/application/src/main/resources/application.properties
+++ b/ms/blueprintsprocessor/application/src/main/resources/application.properties
@@ -60,6 +60,11 @@ blueprints.processor.functions.python.executor.modulePaths=/opt/app/onap/scripts
security.user.password: {bcrypt}$2a$10$duaUzVUVW0YPQCSIbGEkQOXwafZGwQ/b32/Ys4R1iwSSawFgz7QNu
security.user.name: ccsdkapps
+# Error Managements
+error.catalog.applicationId=cds
+error.catalog.type=properties
+error.catalog.errorDefinitionDir=/opt/app/onap/config/
+
# Used in Health Check
#endpoints.user.name=ccsdkapps
#endpoints.user.password=ccsdkapps
@@ -130,5 +135,4 @@ cdslistener.healthcheck.mapping-service-name-with-service-link=[SDC Listener ser
#Actuator properties
management.endpoints.web.exposure.include=*
management.endpoint.health.show-details=always
-
-
+management.info.git.mode=full
diff --git a/ms/blueprintsprocessor/application/src/main/resources/error-messages_en.properties b/ms/blueprintsprocessor/application/src/main/resources/error-messages_en.properties
new file mode 100644
index 000000000..71196ce16
--- /dev/null
+++ b/ms/blueprintsprocessor/application/src/main/resources/error-messages_en.properties
@@ -0,0 +1,91 @@
+#
+# Copyright © 2020 IBM, Bell Canada
+#
+# 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.
+#
+org.onap.ccsdk.cds.blueprintsprocessor.generic_failure=cause=Internal error in Blueprint Processor run time.,action=Contact CDS administrator team.
+org.onap.ccsdk.cds.blueprintsprocessor.resource_path_missing=cause=Resource path missing or wrong.,action=Please reload your artifact in run time.
+org.onap.ccsdk.cds.blueprintsprocessor.resource_writing_fail=cause=Fail to write resources files.,action=Please reload your files and make sure it is in the right format.
+org.onap.ccsdk.cds.blueprintsprocessor.io_file_interrupt=cause=IO file system interruption.,action=Please reload your file and make sure it is in the right format.
+org.onap.ccsdk.cds.blueprintsprocessor.invalid_request_format=cause=bad request provided.,action=Verify the request payload.
+org.onap.ccsdk.cds.blueprintsprocessor.unauthorized_request=cause=The request requires user authentication.,action=Please provide the right credentials.
+org.onap.ccsdk.cds.blueprintsprocessor.request_not_found=cause=Request mapping doesn't exist.,action=Please verify your request.
+org.onap.ccsdk.cds.blueprintsprocessor.conflict_adding_resource=cause=Duplicated entry while saving resource.,action=Please make the saving model doesn't exist.
+org.onap.ccsdk.cds.blueprintsprocessor.duplicate_data=cause=Duplicated data - was expecting one result, got more than one.,action=Please provide single resource at a time.
+org.onap.ccsdk.cds.blueprintsprocessor.resource_not_found=cause=No response was found for this request in the server.,action=Provide the ID to find the resource.
+org.onap.ccsdk.cds.blueprintsprocessor.unsupported_media_type=cause=An invalid media was provided.,action=Please make sure your media or artifact is in the proper structure or format.
+
+# Self Service API
+org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api.generic_failure=cause=Internal error in Self Service API.,action=Verify the request and try again.
+org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api.generic_process_failure=cause=Internal error while processing REST call to the Self Service API.,action=Verify the request and try again.
+org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api.invalid_file_extension=cause=Failed trying to upload a non ZIP file format.,action=Please reload your file and make sure it is in ZIP format.
+org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api.resource_path_missing=cause=Resource path missing or wrong.,action=Please reload your artifact in run time.
+org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api.resource_writing_fail=cause=Fail to write resources files.,action=Please reload your files and make sure it is in the right format.
+org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api.io_file_interrupt=cause=IO file system interruption.,action=Please reload your file and make sure it is in the right format.
+org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api.invalid_request_format=cause=bad request provided.,action=Verify the request payload.
+org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api.unauthorized_request=cause=The request requires user authentication.,action=Please provide the right credentials.
+org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api.request_not_found=cause=Request mapping doesn't exist.,action=Please verify your request.
+org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api.conflict_adding_resource=cause=Duplicated entry while saving resource.,action=Please make the saving model doesn't exist.
+org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api.duplicate_data=cause=Duplicated data - was expecting one result, got more than one.,action=Please provide single resource at a time.
+org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api.resource_not_found=cause=No response was found for this request in the server.,action=Provide the ID to find the resource.
+org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api.unsupported_media_type=cause=An invalid media was provided.,action=Please make sure your media or artifact is in the proper structure or format.
+
+# Designer API
+org.onap.ccsdk.cds.blueprintsprocessor.designer.api.generic_failure=cause=Internal error while processing REST call to the Designer API.,action=Verify the request and try again.
+org.onap.ccsdk.cds.blueprintsprocessor.designer.api.invalid_file_extension=cause=Failed trying to upload a non ZIP file format.,action=Please reload your file and make sure it is in ZIP format.
+org.onap.ccsdk.cds.blueprintsprocessor.designer.api.resource_path_missing=cause=Resource path missing or wrong.,action=Please reload your artifact in run time.
+org.onap.ccsdk.cds.blueprintsprocessor.designer.api.resource_writing_fail=cause=Fail to write resources files.,action=Please reload your files and make sure it is in the right format.
+org.onap.ccsdk.cds.blueprintsprocessor.designer.api.io_file_interrupt=cause=IO file system interruption.,action=Please reload your file and make sure it is in the right format.
+org.onap.ccsdk.cds.blueprintsprocessor.designer.api.invalid_request_format=cause=bad request provided.,action=Verify the request payload.
+org.onap.ccsdk.cds.blueprintsprocessor.designer.api.unauthorized_request=cause=The request requires user authentication.,action=Please provide the right credentials.
+org.onap.ccsdk.cds.blueprintsprocessor.designer.api.request_not_found=cause=Request mapping doesn't exist.,action=Please verify your request.
+org.onap.ccsdk.cds.blueprintsprocessor.designer.api.conflict_adding_resource=cause=Duplicated entry while saving resource.,action=Please make the saving model doesn't exist.
+org.onap.ccsdk.cds.blueprintsprocessor.designer.api.duplicate_data=cause=Duplicated data - was expecting one result, got more than one.,action=Please provide single resource at a time.
+org.onap.ccsdk.cds.blueprintsprocessor.designer.api.resource_not_found=cause=No response was found for this request in the server.,action=Provide the ID to find the resource.
+org.onap.ccsdk.cds.blueprintsprocessor.designer.api.unsupported_media_type=cause=An invalid media was provided.,action=Please make sure your media or artifact is in the proper structure or format.
+
+# Resource API
+org.onap.ccsdk.cds.blueprintsprocessor.resource.api.generic_failure=cause=Internal error while processing REST call to the Resource API.,action=Verify the request and try again.
+org.onap.ccsdk.cds.blueprintsprocessor.resource.api.invalid_file_extension=cause=Failed trying to upload a non ZIP file format.,action=Please reload your file and make sure it is in ZIP format.
+org.onap.ccsdk.cds.blueprintsprocessor.resource.api.resource_path_missing=cause=Resource path missing or wrong.,action=Please reload your artifact in run time.
+org.onap.ccsdk.cds.blueprintsprocessor.resource.api.resource_writing_fail=cause=Fail to write resources files.,action=Please reload your files and make sure it is in the right format.
+org.onap.ccsdk.cds.blueprintsprocessor.resource.api.io_file_interrupt=cause=IO file system interruption.,action=Please reload your file and make sure it is in the right format.
+org.onap.ccsdk.cds.blueprintsprocessor.resource.api.invalid_request_format=cause=bad request provided.,action=Verify the request payload.
+org.onap.ccsdk.cds.blueprintsprocessor.resource.api.unauthorized_request=cause=The request requires user authentication.,action=Please provide the right credentials.
+org.onap.ccsdk.cds.blueprintsprocessor.resource.api.request_not_found=cause=Request mapping doesn't exist.,action=Please verify your request.
+org.onap.ccsdk.cds.blueprintsprocessor.resource.api.conflict_adding_resource=cause=Duplicated entry while saving resource.,action=Please make the saving model doesn't exist.
+org.onap.ccsdk.cds.blueprintsprocessor.resource.api.duplicate_data=cause=Duplicated data - was expecting one result, got more than one.,action=Please provide single resource at a time.
+org.onap.ccsdk.cds.blueprintsprocessor.resource.api.resource_not_found=cause=No response was found for this request in the server.,action=Provide the ID to find the resource.
+org.onap.ccsdk.cds.blueprintsprocessor.resource.api.unsupported_media_type=cause=An invalid media was provided.,action=Please make sure your media or artifact is in the proper structure or format.
+
+
+# Configs API
+org.onap.ccsdk.cds.blueprintsprocessor.configs.api.generic_failure=cause=Internal error while processing REST call to the Configs API.,action=Verify the request and try again.
+org.onap.ccsdk.cds.blueprintsprocessor.configs.api.resource_path_missing=cause=Resource path missing or wrong.,action=Please reload your artifact in run time.
+org.onap.ccsdk.cds.blueprintsprocessor.configs.api.io_file_interrupt=cause=IO file system interruption.,action=Please reload your file and make sure it is in the right format.
+org.onap.ccsdk.cds.blueprintsprocessor.configs.api.invalid_request_format=cause=bad request provided.,action=Verify the request payload.
+org.onap.ccsdk.cds.blueprintsprocessor.configs.api.unauthorized_request=cause=The request requires user authentication.,action=Please provide the right credentials.
+org.onap.ccsdk.cds.blueprintsprocessor.configs.api.request_not_found=cause=Request mapping doesn't exist.,action=Please verify your request.
+org.onap.ccsdk.cds.blueprintsprocessor.configs.api.conflict_adding_resource=cause=Duplicated entry while saving resource.,action=Please make the saving model doesn't exist.
+org.onap.ccsdk.cds.blueprintsprocessor.configs.api.duplicate_data=cause=Duplicated data - was expecting one result, got more than one.,action=Please provide single resource at a time.
+org.onap.ccsdk.cds.blueprintsprocessor.configs.api.resource_not_found=cause=No response was found for this request in the server.,action=Provide the ID to find the resource.
+
+# Python Executor
+org.onap.ccsdk.cds.blueprintsprocessor.functions.python.executor.generic_failure=cause=Internal error in Blueprint Processor run time.,action=Contact CDS administrator team.
+
+# Resource resolution
+org.onap.ccsdk.cds.blueprintsprocessor.resource.resolution.invalid_request_format=cause=bad request provided.,action=Verify the request payload.
+org.onap.ccsdk.cds.blueprintsprocessor.resource.resolution.resource_not_found=cause=No response was found for this resolution in CDS.,action=Verify definition of the resource in CBA.
+org.onap.ccsdk.cds.blueprintsprocessor.resource.resolution.internal_error=cause=Internal error while processing Resource Resolution.,action=Verify the payload.
+
+org.onap.ccsdk.cds.sdclistener.generic_failure=cause=Internal error in SDC Listener.,action=Contact CDS administrator team.
diff --git a/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/ErrorCatalogTestConfiguration.kt b/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/ErrorCatalogTestConfiguration.kt
new file mode 100644
index 000000000..c9d55c18a
--- /dev/null
+++ b/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/ErrorCatalogTestConfiguration.kt
@@ -0,0 +1,28 @@
+/*
+ * Copyright © 2020 IBM, Bell Canada.
+ *
+ * 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.
+ */
+
+package org.onap.ccsdk.cds.blueprintsprocessor.uat
+
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration
+import org.springframework.context.annotation.ComponentScan
+import org.springframework.context.annotation.Configuration
+
+@Configuration
+@ComponentScan(
+ basePackages = ["org.onap.ccsdk.cds.error.catalog"]
+)
+@EnableAutoConfiguration
+open class ErrorCatalogTestConfiguration
diff --git a/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/UatServicesTest.kt b/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/UatServicesTest.kt
index aebda8c07..4e7d4ce40 100644
--- a/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/UatServicesTest.kt
+++ b/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/UatServicesTest.kt
@@ -30,6 +30,8 @@ import com.github.tomakehurst.wiremock.client.WireMock.equalToJson
import com.github.tomakehurst.wiremock.client.WireMock.request
import com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo
import com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig
+import com.github.tomakehurst.wiremock.http.HttpHeader
+import com.github.tomakehurst.wiremock.http.HttpHeaders
import org.apache.http.HttpStatus
import org.apache.http.client.methods.HttpPost
import org.apache.http.entity.ContentType
@@ -55,8 +57,6 @@ import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.web.server.LocalServerPort
import org.springframework.core.env.ConfigurableEnvironment
import org.springframework.core.env.MapPropertySource
-import org.springframework.http.HttpHeaders
-import org.springframework.http.MediaType
import org.springframework.test.context.ActiveProfiles
import org.springframework.test.context.support.TestPropertySourceUtils.INLINED_PROPERTIES_PROPERTY_SOURCE_NAME
import org.yaml.snakeyaml.Yaml
@@ -211,7 +211,6 @@ class UatServicesTest : BaseUatTest() {
service.expectations.forEach { expectation ->
val request = expectation.request
- val response = expectation.response
// WebTestClient always use absolute path, prefixing with "/" if necessary
val urlPattern = urlEqualTo(request.path.prefixIfNot("/"))
val mappingBuilder: MappingBuilder = request(request.method, urlPattern)
@@ -222,15 +221,19 @@ class UatServicesTest : BaseUatTest() {
mappingBuilder.withRequestBody(equalToJson(mapper.writeValueAsString(request.body), true, true))
}
- val responseDefinitionBuilder: ResponseDefinitionBuilder = aResponse()
- .withStatus(response.status)
- if (response.body != null) {
- responseDefinitionBuilder.withBody(mapper.writeValueAsBytes(response.body))
- .withHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
+ for (response in expectation.responses) {
+ val responseDefinitionBuilder: ResponseDefinitionBuilder = aResponse()
+ .withStatus(response.status)
+ if (response.body != null) {
+ responseDefinitionBuilder.withBody(mapper.writeValueAsBytes(response.body))
+ .withHeaders(HttpHeaders(
+ response.headers.entries.map { e -> HttpHeader(e.key, e.value) }))
+ }
+
+ // TODO: MockServer verification for multiple responses should be done using Wiremock scenarios
+ mappingBuilder.willReturn(responseDefinitionBuilder)
}
- mappingBuilder.willReturn(responseDefinitionBuilder)
-
mockServer.stubFor(mappingBuilder)
}
return mockServer
diff --git a/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/error/ErrorCatalogServiceTest.kt b/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/error/ErrorCatalogServiceTest.kt
new file mode 100644
index 000000000..4f7ef0ec2
--- /dev/null
+++ b/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/error/ErrorCatalogServiceTest.kt
@@ -0,0 +1,97 @@
+/*
+ * Copyright © 2020 IBM, Bell Canada.
+ *
+ * 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.
+ */
+
+package org.onap.ccsdk.cds.blueprintsprocessor.uat.error
+
+import org.junit.runner.RunWith
+import org.onap.ccsdk.cds.blueprintsprocessor.uat.ErrorCatalogTestConfiguration
+import org.onap.ccsdk.cds.controllerblueprints.core.grpcProcessorException
+import org.onap.ccsdk.cds.controllerblueprints.core.httpProcessorException
+import org.onap.ccsdk.cds.error.catalog.core.ErrorCatalog
+import org.onap.ccsdk.cds.error.catalog.core.ErrorCatalogCodes
+import org.onap.ccsdk.cds.error.catalog.core.ErrorMessage
+import org.onap.ccsdk.cds.error.catalog.core.ErrorPayload
+import org.onap.ccsdk.cds.error.catalog.services.ErrorCatalogService
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.test.context.ContextConfiguration
+import org.springframework.test.context.TestPropertySource
+import org.springframework.test.context.junit4.SpringRunner
+import kotlin.test.BeforeTest
+import kotlin.test.Test
+import kotlin.test.assertTrue
+
+@RunWith(SpringRunner::class)
+@ContextConfiguration(
+ classes = [ErrorCatalogTestConfiguration::class]
+)
+@TestPropertySource(locations = ["classpath:application-test.properties"])
+class ErrorCatalogServiceTest {
+ @Autowired
+ lateinit var errorCatalogService: ErrorCatalogService
+
+ private val domain = "org.onap.ccsdk.cds.blueprintsprocessor"
+ private lateinit var errorType: String
+ private lateinit var errorCatalogHttp: ErrorCatalog
+ private lateinit var errorCatalogGrpc: ErrorCatalog
+ private lateinit var errorPayloadHttp: ErrorPayload
+ private lateinit var errorPayloadGrpc: ErrorPayload
+
+ @BeforeTest
+ fun setup() {
+ errorType = ErrorCatalogCodes.GENERIC_FAILURE
+ errorCatalogHttp = ErrorCatalog(errorType, domain, 500,
+ "Contact CDS administrator team.", "Internal error in Blueprint Processor run time.")
+ errorCatalogGrpc = ErrorCatalog(errorType, domain, 2,
+ "Contact CDS administrator team.", "Internal error in Blueprint Processor run time.")
+
+ errorPayloadHttp = ErrorPayload(500, ErrorCatalogCodes.GENERIC_FAILURE,
+ "Cause: Internal error in Blueprint Processor run time. \n Action : Contact CDS administrator team.",
+ errorMessage = ErrorMessage("org.onap.ccsdk.cds.blueprintsprocessor",
+ "Internal error in Blueprint Processor run time.", ""))
+ errorPayloadGrpc = ErrorPayload(2, ErrorCatalogCodes.GENERIC_FAILURE,
+ "Cause: Internal error in Blueprint Processor run time. \n Action : Contact CDS administrator team.",
+ errorMessage = ErrorMessage("org.onap.ccsdk.cds.blueprintsprocessor",
+ "Internal error in Blueprint Processor run time.", ""))
+ }
+
+ @Test
+ fun errorPayloadHttp() {
+ val errorPayload = errorCatalogService.errorPayload(httpProcessorException(errorType, domain,
+ "Internal error in Blueprint Processor run time."))
+ assertTrue { errorPayload.isEqualTo(errorPayloadHttp) }
+ }
+
+ @Test
+ fun errorPayloadGrpc() {
+ val errorPayload = errorCatalogService.errorPayload(grpcProcessorException(errorType, domain,
+ "Internal error in Blueprint Processor run time."))
+ assertTrue { errorPayload.isEqualTo(errorPayloadGrpc) }
+ }
+
+ @Test
+ fun getErrorCatalogHttp() {
+ val errorCatalog = errorCatalogService.getErrorCatalog(httpProcessorException(errorType, domain,
+ "Internal error in Blueprint Processor run time."))
+ assertTrue { errorCatalog == errorCatalogHttp }
+ }
+
+ @Test
+ fun getErrorCatalogGrpc() {
+ val errorCatalog = errorCatalogService.getErrorCatalog(grpcProcessorException(errorType, domain,
+ "Internal error in Blueprint Processor run time."))
+ assertTrue { errorCatalog == errorCatalogGrpc }
+ }
+}
diff --git a/ms/blueprintsprocessor/application/src/test/resources/application-test.properties b/ms/blueprintsprocessor/application/src/test/resources/application-test.properties
index 1d2565be3..d2170c7c1 100644
--- a/ms/blueprintsprocessor/application/src/test/resources/application-test.properties
+++ b/ms/blueprintsprocessor/application/src/test/resources/application-test.properties
@@ -16,6 +16,11 @@
spring.http.log-request-details=true
+# Error Managements
+error.catalog.applicationId=cds
+error.catalog.type=properties
+error.catalog.errorDefinitionDir=./src/test/resources/
+
blueprintsprocessor.httpPort=0
blueprintsprocessor.grpcEnable=true
blueprintsprocessor.grpcPort=0
@@ -61,4 +66,3 @@ blueprintprocessor.healthcheck.mapping-service-name-with-service-link=[Execution
#BaseUrls for health check Cds Listener services
cdslistener.healthcheck.baseUrl=http://cds-sdc-listener:8080/
cdslistener.healthcheck.mapping-service-name-with-service-link=[SDC Listener service,/api/v1/sdclistener/healthcheck]
-
diff --git a/ms/blueprintsprocessor/application/src/test/resources/application.properties b/ms/blueprintsprocessor/application/src/test/resources/application.properties
index ea14c493a..cb3419397 100644
--- a/ms/blueprintsprocessor/application/src/test/resources/application.properties
+++ b/ms/blueprintsprocessor/application/src/test/resources/application.properties
@@ -61,6 +61,11 @@ blueprints.processor.functions.python.executor.modulePaths=/opt/app/onap/scripts
security.user.password:{bcrypt}$2a$10$duaUzVUVW0YPQCSIbGEkQOXwafZGwQ/b32/Ys4R1iwSSawFgz7QNu
security.user.name:ccsdkapps
+# Error Managements
+error.catalog.applicationId=cds
+error.catalog.type=properties
+error.catalog.errorDefinitionDir=./src/test/resources/
+
# Executor Options
blueprintsprocessor.resourceResolution.enabled=true
blueprintsprocessor.netconfExecutor.enabled=true
diff --git a/ms/blueprintsprocessor/application/src/test/resources/error-messages_en.properties b/ms/blueprintsprocessor/application/src/test/resources/error-messages_en.properties
new file mode 100644
index 000000000..71196ce16
--- /dev/null
+++ b/ms/blueprintsprocessor/application/src/test/resources/error-messages_en.properties
@@ -0,0 +1,91 @@
+#
+# Copyright © 2020 IBM, Bell Canada
+#
+# 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.
+#
+org.onap.ccsdk.cds.blueprintsprocessor.generic_failure=cause=Internal error in Blueprint Processor run time.,action=Contact CDS administrator team.
+org.onap.ccsdk.cds.blueprintsprocessor.resource_path_missing=cause=Resource path missing or wrong.,action=Please reload your artifact in run time.
+org.onap.ccsdk.cds.blueprintsprocessor.resource_writing_fail=cause=Fail to write resources files.,action=Please reload your files and make sure it is in the right format.
+org.onap.ccsdk.cds.blueprintsprocessor.io_file_interrupt=cause=IO file system interruption.,action=Please reload your file and make sure it is in the right format.
+org.onap.ccsdk.cds.blueprintsprocessor.invalid_request_format=cause=bad request provided.,action=Verify the request payload.
+org.onap.ccsdk.cds.blueprintsprocessor.unauthorized_request=cause=The request requires user authentication.,action=Please provide the right credentials.
+org.onap.ccsdk.cds.blueprintsprocessor.request_not_found=cause=Request mapping doesn't exist.,action=Please verify your request.
+org.onap.ccsdk.cds.blueprintsprocessor.conflict_adding_resource=cause=Duplicated entry while saving resource.,action=Please make the saving model doesn't exist.
+org.onap.ccsdk.cds.blueprintsprocessor.duplicate_data=cause=Duplicated data - was expecting one result, got more than one.,action=Please provide single resource at a time.
+org.onap.ccsdk.cds.blueprintsprocessor.resource_not_found=cause=No response was found for this request in the server.,action=Provide the ID to find the resource.
+org.onap.ccsdk.cds.blueprintsprocessor.unsupported_media_type=cause=An invalid media was provided.,action=Please make sure your media or artifact is in the proper structure or format.
+
+# Self Service API
+org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api.generic_failure=cause=Internal error in Self Service API.,action=Verify the request and try again.
+org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api.generic_process_failure=cause=Internal error while processing REST call to the Self Service API.,action=Verify the request and try again.
+org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api.invalid_file_extension=cause=Failed trying to upload a non ZIP file format.,action=Please reload your file and make sure it is in ZIP format.
+org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api.resource_path_missing=cause=Resource path missing or wrong.,action=Please reload your artifact in run time.
+org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api.resource_writing_fail=cause=Fail to write resources files.,action=Please reload your files and make sure it is in the right format.
+org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api.io_file_interrupt=cause=IO file system interruption.,action=Please reload your file and make sure it is in the right format.
+org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api.invalid_request_format=cause=bad request provided.,action=Verify the request payload.
+org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api.unauthorized_request=cause=The request requires user authentication.,action=Please provide the right credentials.
+org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api.request_not_found=cause=Request mapping doesn't exist.,action=Please verify your request.
+org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api.conflict_adding_resource=cause=Duplicated entry while saving resource.,action=Please make the saving model doesn't exist.
+org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api.duplicate_data=cause=Duplicated data - was expecting one result, got more than one.,action=Please provide single resource at a time.
+org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api.resource_not_found=cause=No response was found for this request in the server.,action=Provide the ID to find the resource.
+org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api.unsupported_media_type=cause=An invalid media was provided.,action=Please make sure your media or artifact is in the proper structure or format.
+
+# Designer API
+org.onap.ccsdk.cds.blueprintsprocessor.designer.api.generic_failure=cause=Internal error while processing REST call to the Designer API.,action=Verify the request and try again.
+org.onap.ccsdk.cds.blueprintsprocessor.designer.api.invalid_file_extension=cause=Failed trying to upload a non ZIP file format.,action=Please reload your file and make sure it is in ZIP format.
+org.onap.ccsdk.cds.blueprintsprocessor.designer.api.resource_path_missing=cause=Resource path missing or wrong.,action=Please reload your artifact in run time.
+org.onap.ccsdk.cds.blueprintsprocessor.designer.api.resource_writing_fail=cause=Fail to write resources files.,action=Please reload your files and make sure it is in the right format.
+org.onap.ccsdk.cds.blueprintsprocessor.designer.api.io_file_interrupt=cause=IO file system interruption.,action=Please reload your file and make sure it is in the right format.
+org.onap.ccsdk.cds.blueprintsprocessor.designer.api.invalid_request_format=cause=bad request provided.,action=Verify the request payload.
+org.onap.ccsdk.cds.blueprintsprocessor.designer.api.unauthorized_request=cause=The request requires user authentication.,action=Please provide the right credentials.
+org.onap.ccsdk.cds.blueprintsprocessor.designer.api.request_not_found=cause=Request mapping doesn't exist.,action=Please verify your request.
+org.onap.ccsdk.cds.blueprintsprocessor.designer.api.conflict_adding_resource=cause=Duplicated entry while saving resource.,action=Please make the saving model doesn't exist.
+org.onap.ccsdk.cds.blueprintsprocessor.designer.api.duplicate_data=cause=Duplicated data - was expecting one result, got more than one.,action=Please provide single resource at a time.
+org.onap.ccsdk.cds.blueprintsprocessor.designer.api.resource_not_found=cause=No response was found for this request in the server.,action=Provide the ID to find the resource.
+org.onap.ccsdk.cds.blueprintsprocessor.designer.api.unsupported_media_type=cause=An invalid media was provided.,action=Please make sure your media or artifact is in the proper structure or format.
+
+# Resource API
+org.onap.ccsdk.cds.blueprintsprocessor.resource.api.generic_failure=cause=Internal error while processing REST call to the Resource API.,action=Verify the request and try again.
+org.onap.ccsdk.cds.blueprintsprocessor.resource.api.invalid_file_extension=cause=Failed trying to upload a non ZIP file format.,action=Please reload your file and make sure it is in ZIP format.
+org.onap.ccsdk.cds.blueprintsprocessor.resource.api.resource_path_missing=cause=Resource path missing or wrong.,action=Please reload your artifact in run time.
+org.onap.ccsdk.cds.blueprintsprocessor.resource.api.resource_writing_fail=cause=Fail to write resources files.,action=Please reload your files and make sure it is in the right format.
+org.onap.ccsdk.cds.blueprintsprocessor.resource.api.io_file_interrupt=cause=IO file system interruption.,action=Please reload your file and make sure it is in the right format.
+org.onap.ccsdk.cds.blueprintsprocessor.resource.api.invalid_request_format=cause=bad request provided.,action=Verify the request payload.
+org.onap.ccsdk.cds.blueprintsprocessor.resource.api.unauthorized_request=cause=The request requires user authentication.,action=Please provide the right credentials.
+org.onap.ccsdk.cds.blueprintsprocessor.resource.api.request_not_found=cause=Request mapping doesn't exist.,action=Please verify your request.
+org.onap.ccsdk.cds.blueprintsprocessor.resource.api.conflict_adding_resource=cause=Duplicated entry while saving resource.,action=Please make the saving model doesn't exist.
+org.onap.ccsdk.cds.blueprintsprocessor.resource.api.duplicate_data=cause=Duplicated data - was expecting one result, got more than one.,action=Please provide single resource at a time.
+org.onap.ccsdk.cds.blueprintsprocessor.resource.api.resource_not_found=cause=No response was found for this request in the server.,action=Provide the ID to find the resource.
+org.onap.ccsdk.cds.blueprintsprocessor.resource.api.unsupported_media_type=cause=An invalid media was provided.,action=Please make sure your media or artifact is in the proper structure or format.
+
+
+# Configs API
+org.onap.ccsdk.cds.blueprintsprocessor.configs.api.generic_failure=cause=Internal error while processing REST call to the Configs API.,action=Verify the request and try again.
+org.onap.ccsdk.cds.blueprintsprocessor.configs.api.resource_path_missing=cause=Resource path missing or wrong.,action=Please reload your artifact in run time.
+org.onap.ccsdk.cds.blueprintsprocessor.configs.api.io_file_interrupt=cause=IO file system interruption.,action=Please reload your file and make sure it is in the right format.
+org.onap.ccsdk.cds.blueprintsprocessor.configs.api.invalid_request_format=cause=bad request provided.,action=Verify the request payload.
+org.onap.ccsdk.cds.blueprintsprocessor.configs.api.unauthorized_request=cause=The request requires user authentication.,action=Please provide the right credentials.
+org.onap.ccsdk.cds.blueprintsprocessor.configs.api.request_not_found=cause=Request mapping doesn't exist.,action=Please verify your request.
+org.onap.ccsdk.cds.blueprintsprocessor.configs.api.conflict_adding_resource=cause=Duplicated entry while saving resource.,action=Please make the saving model doesn't exist.
+org.onap.ccsdk.cds.blueprintsprocessor.configs.api.duplicate_data=cause=Duplicated data - was expecting one result, got more than one.,action=Please provide single resource at a time.
+org.onap.ccsdk.cds.blueprintsprocessor.configs.api.resource_not_found=cause=No response was found for this request in the server.,action=Provide the ID to find the resource.
+
+# Python Executor
+org.onap.ccsdk.cds.blueprintsprocessor.functions.python.executor.generic_failure=cause=Internal error in Blueprint Processor run time.,action=Contact CDS administrator team.
+
+# Resource resolution
+org.onap.ccsdk.cds.blueprintsprocessor.resource.resolution.invalid_request_format=cause=bad request provided.,action=Verify the request payload.
+org.onap.ccsdk.cds.blueprintsprocessor.resource.resolution.resource_not_found=cause=No response was found for this resolution in CDS.,action=Verify definition of the resource in CBA.
+org.onap.ccsdk.cds.blueprintsprocessor.resource.resolution.internal_error=cause=Internal error while processing Resource Resolution.,action=Verify the payload.
+
+org.onap.ccsdk.cds.sdclistener.generic_failure=cause=Internal error in SDC Listener.,action=Contact CDS administrator team.
diff --git a/ms/blueprintsprocessor/functions/message-prioritizaion/pom.xml b/ms/blueprintsprocessor/functions/message-prioritizaion/pom.xml
index ac46b3635..c7dbaf174 100644
--- a/ms/blueprintsprocessor/functions/message-prioritizaion/pom.xml
+++ b/ms/blueprintsprocessor/functions/message-prioritizaion/pom.xml
@@ -14,7 +14,6 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/ComponentNetconfExecutor.kt b/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/ComponentNetconfExecutor.kt
index 1262e8500..307e73e6b 100644
--- a/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/ComponentNetconfExecutor.kt
+++ b/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/ComponentNetconfExecutor.kt
@@ -65,6 +65,9 @@ open class ComponentNetconfExecutor(private var componentFunctionScriptingServic
// Handles both script processing and error handling
scriptComponent.executeScript(executionServiceInput)
+
+ componentFunctionScriptingService.cleanupInstance(bluePrintRuntimeService.bluePrintContext(),
+ scriptType)
}
override suspend fun recoverNB(runtimeException: RuntimeException, executionRequest: ExecutionServiceInput) {
diff --git a/ms/blueprintsprocessor/functions/pom.xml b/ms/blueprintsprocessor/functions/pom.xml
index abd186bcf..3097c1b98 100755
--- a/ms/blueprintsprocessor/functions/pom.xml
+++ b/ms/blueprintsprocessor/functions/pom.xml
@@ -33,7 +33,7 @@
<modules>
<module>resource-resolution</module>
- <module>nrm-restful</module>
+ <module>restful-executor</module>
<module>ansible-awx-executor</module>
<module>python-executor</module>
<module>netconf-executor</module>
diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionComponent.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionComponent.kt
index db0a6f0ed..3c95ea7bb 100644
--- a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionComponent.kt
+++ b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionComponent.kt
@@ -43,6 +43,7 @@ open class ResourceResolutionComponent(private val resourceResolutionService: Re
const val INPUT_RESOURCE_TYPE = "resource-type"
const val INPUT_ARTIFACT_PREFIX_NAMES = "artifact-prefix-names"
const val INPUT_RESOLUTION_KEY = "resolution-key"
+ const val INPUT_RESOLUTION_SUMMARY = "resolution-summary"
const val INPUT_STORE_RESULT = "store-result"
const val INPUT_OCCURRENCE = "occurrence"
@@ -64,6 +65,8 @@ open class ResourceResolutionComponent(private val resourceResolutionService: Re
val resourceType =
getOptionalOperationInput(ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOURCE_TYPE)?.returnNullIfMissing()?.textValue() ?: ""
+ val resolutionSummary =
+ getOptionalOperationInput(ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOLUTION_SUMMARY)?.asBoolean() ?: false
val properties: MutableMap<String, Any> = mutableMapOf()
properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_STORE_RESULT] = storeResult
@@ -71,6 +74,7 @@ open class ResourceResolutionComponent(private val resourceResolutionService: Re
properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOURCE_ID] = resourceId
properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOURCE_TYPE] = resourceType
properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_OCCURRENCE] = occurrence
+ properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOLUTION_SUMMARY] = resolutionSummary
val jsonResponse = JsonNodeFactory.instance.objectNode()
// Initialize Output Attribute to empty JSON
diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionComponentDSL.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionComponentDSL.kt
index 6573d0e9a..fd104d3ad 100644
--- a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionComponentDSL.kt
+++ b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionComponentDSL.kt
@@ -82,6 +82,11 @@ fun BluePrintTypes.nodeTypeComponentResourceResolution(): NodeType {
)
property(
+ ResourceResolutionComponent.INPUT_RESOLUTION_SUMMARY, BluePrintConstants.DATA_TYPE_BOOLEAN,
+ false, "Enables ResolutionSummary output"
+ )
+
+ property(
ResourceResolutionComponent.INPUT_OCCURRENCE, BluePrintConstants.DATA_TYPE_INTEGER,
false, "Number of time to perform the resolution."
) {
@@ -176,6 +181,12 @@ class ComponentResourceResolutionNodeTemplateBuilder(id: String, description: St
property(ResourceResolutionComponent.INPUT_RESOLUTION_KEY, resolutionKey)
}
+ fun resolutionSummary(resolutionSummary: Boolean) = resolutionSummary(resolutionSummary.asJsonPrimitive())
+
+ fun resolutionSummary(resolutionSummary: JsonNode) {
+ property(ResourceResolutionComponent.INPUT_RESOLUTION_SUMMARY, resolutionSummary)
+ }
+
fun dynamicProperties(dynamicProperties: String) = dynamicProperties(dynamicProperties.asJsonType())
fun dynamicProperties(dynamicProperties: JsonNode) {
diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionConstants.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionConstants.kt
index c39933dc8..8f6069160 100644
--- a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionConstants.kt
+++ b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionConstants.kt
@@ -29,4 +29,5 @@ object ResourceResolutionConstants {
const val RESOURCE_RESOLUTION_INPUT_OCCURRENCE = "occurrence"
const val RESOURCE_RESOLUTION_INPUT_RESOURCE_ID = "resource-id"
const val RESOURCE_RESOLUTION_INPUT_RESOURCE_TYPE = "resource-type"
+ const val RESOURCE_RESOLUTION_INPUT_RESOLUTION_SUMMARY = "resolution-summary"
}
diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionService.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionService.kt
index 7272a3d63..dff00c7eb 100644
--- a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionService.kt
+++ b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionService.kt
@@ -147,7 +147,7 @@ open class ResourceResolutionServiceImpl(
properties: Map<String, Any>
): String {
- // Velocity Artifact Definition Name
+ // Template Artifact Definition Name
val artifactTemplate = "$artifactPrefix-template"
// Resource Assignment Artifact Definition Name
val artifactMapping = "$artifactPrefix-mapping"
@@ -185,22 +185,28 @@ open class ResourceResolutionServiceImpl(
properties
)
+ val resolutionSummary = properties.getOrDefault(ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOLUTION_SUMMARY, false) as Boolean
val resolvedParamJsonContent =
ResourceAssignmentUtils.generateResourceDataForAssignments(resourceAssignments.toList())
-
val artifactTemplateDefinition = bluePrintRuntimeService.bluePrintContext().checkNodeTemplateArtifact(nodeTemplateName, artifactTemplate)
- val resolvedContent = if (artifactTemplateDefinition != null) {
- blueprintTemplateService.generateContent(
- bluePrintRuntimeService, nodeTemplateName,
- artifactTemplate, resolvedParamJsonContent, false,
- mutableMapOf(
- ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_OCCURRENCE to
- properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_OCCURRENCE].asJsonPrimitive()
+ val resolvedContent = when {
+ artifactTemplateDefinition != null -> {
+ blueprintTemplateService.generateContent(
+ bluePrintRuntimeService, nodeTemplateName,
+ artifactTemplate, resolvedParamJsonContent, false,
+ mutableMapOf(
+ ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_OCCURRENCE to
+ properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_OCCURRENCE].asJsonPrimitive()
+ )
)
- )
- } else {
- resolvedParamJsonContent
+ }
+ resolutionSummary -> {
+ ResourceAssignmentUtils.generateResolutionSummaryData(resourceAssignments, resourceDefinitions)
+ }
+ else -> {
+ resolvedParamJsonContent
+ }
}
if (isToStore(properties)) {
diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionDBService.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionDBService.kt
index f8bf7bd09..dc1553747 100644
--- a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionDBService.kt
+++ b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionDBService.kt
@@ -198,4 +198,27 @@ class ResourceResolutionDBService(private val resourceResolutionRepository: Reso
throw BluePrintException("Failed to store resource resolution result.", ex)
}
}
+
+ /**
+ * This is a deleteByBlueprintNameAndBlueprintVersionAndArtifactNameAndResolutionKey method to delete resources
+ * associated to a specific resolution-key
+ *
+ * @param blueprintName name of the CBA
+ * @param blueprintVersion version of the CBA
+ * @param artifactName name of the artifact
+ * @param resolutionKey value of the resolution-key
+ */
+ suspend fun deleteByBlueprintNameAndBlueprintVersionAndArtifactNameAndResolutionKey(
+ blueprintName: String,
+ blueprintVersion: String,
+ artifactName: String,
+ resolutionKey: String
+ ) {
+ resourceResolutionRepository.deleteByBlueprintNameAndBlueprintVersionAndArtifactNameAndResolutionKey(
+ blueprintName,
+ blueprintVersion,
+ artifactName,
+ resolutionKey
+ )
+ }
}
diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionRepository.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionRepository.kt
index a2a3a753b..c2d630e5e 100644
--- a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionRepository.kt
+++ b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionRepository.kt
@@ -17,6 +17,7 @@ package org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.db
import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.stereotype.Repository
+import javax.transaction.Transactional
@Repository
interface ResourceResolutionRepository : JpaRepository<ResourceResolution, String> {
@@ -59,4 +60,12 @@ interface ResourceResolutionRepository : JpaRepository<ResourceResolution, Strin
resourceType: String,
occurrence: Int
): List<ResourceResolution>
+
+ @Transactional
+ fun deleteByBlueprintNameAndBlueprintVersionAndArtifactNameAndResolutionKey(
+ blueprintName: String?,
+ blueprintVersion: String?,
+ artifactName: String,
+ resolutionKey: String
+ )
}
diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/CapabilityResourceResolutionProcessor.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/CapabilityResourceResolutionProcessor.kt
index feef4c2fe..868f919c1 100644
--- a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/CapabilityResourceResolutionProcessor.kt
+++ b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/CapabilityResourceResolutionProcessor.kt
@@ -81,6 +81,8 @@ open class CapabilityResourceResolutionProcessor(private var componentFunctionSc
// Invoke componentResourceAssignmentProcessor
componentResourceAssignmentProcessor!!.executeScript(resourceAssignment)
+
+ componentFunctionScriptingService.cleanupInstance(raRuntimeService.bluePrintContext(), scriptType)
}
}
diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/DatabaseResourceAssignmentProcessor.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/DatabaseResourceAssignmentProcessor.kt
index e43b45e7d..0bfd7e4e2 100644
--- a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/DatabaseResourceAssignmentProcessor.kt
+++ b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/DatabaseResourceAssignmentProcessor.kt
@@ -28,6 +28,7 @@ import org.onap.ccsdk.cds.controllerblueprints.core.checkNotEmpty
import org.onap.ccsdk.cds.controllerblueprints.core.isNotEmpty
import org.onap.ccsdk.cds.controllerblueprints.core.nullToEmpty
import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils
+import org.onap.ccsdk.cds.controllerblueprints.resource.dict.KeyIdentifier
import org.onap.ccsdk.cds.controllerblueprints.resource.dict.ResourceAssignment
import org.onap.ccsdk.cds.controllerblueprints.resource.dict.ResourceDictionaryConstants
import org.slf4j.LoggerFactory
@@ -91,6 +92,11 @@ open class DatabaseResourceAssignmentProcessor(
"failed to get input-key-mappings for $dName under $dSource properties"
}
+ sourceProperties.inputKeyMapping
+ ?.mapValues { raRuntimeService.getDictionaryStore(it.value) }
+ ?.map { KeyIdentifier(it.key, it.value) }
+ ?.let { resourceAssignment.keyIdentifiers.addAll(it) }
+
logger.info(
"DatabaseResource ($dSource) dictionary information: " +
"Query:($sql), input-key-mapping:($inputKeyMapping), output-key-mapping:(${sourceProperties.outputKeyMapping})"
diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/RestResourceResolutionProcessor.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/RestResourceResolutionProcessor.kt
index 2ff5c441e..5d9226876 100644
--- a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/RestResourceResolutionProcessor.kt
+++ b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/RestResourceResolutionProcessor.kt
@@ -27,6 +27,7 @@ import org.onap.ccsdk.cds.controllerblueprints.core.checkNotEmpty
import org.onap.ccsdk.cds.controllerblueprints.core.isNotEmpty
import org.onap.ccsdk.cds.controllerblueprints.core.nullToEmpty
import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils
+import org.onap.ccsdk.cds.controllerblueprints.resource.dict.KeyIdentifier
import org.onap.ccsdk.cds.controllerblueprints.resource.dict.ResourceAssignment
import org.slf4j.LoggerFactory
import org.springframework.beans.factory.config.ConfigurableBeanFactory
@@ -75,8 +76,14 @@ open class RestResourceResolutionProcessor(private val blueprintRestLibPropertyS
checkNotNull(sourceProperties.inputKeyMapping) { "failed to get input-key-mappings for $dName under $dSource properties" }
val resolvedInputKeyMapping = resolveInputKeyMappingVariables(inputKeyMapping).toMutableMap()
+ sourceProperties.inputKeyMapping
+ ?.mapValues { raRuntimeService.getDictionaryStore(it.value) }
+ ?.map { KeyIdentifier(it.key, it.value) }
+ ?.let { resourceAssignment.keyIdentifiers.addAll(it) }
+
// Resolving content Variables
val payload = resolveFromInputKeyMapping(nullToEmpty(sourceProperties.payload), resolvedInputKeyMapping)
+ resourceSourceProperties["resolved-payload"] = JacksonUtils.jsonNode(payload)
val urlPath =
resolveFromInputKeyMapping(checkNotNull(sourceProperties.urlPath), resolvedInputKeyMapping)
val verb = resolveFromInputKeyMapping(nullToEmpty(sourceProperties.verb), resolvedInputKeyMapping)
diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/utils/ResourceAssignmentUtils.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/utils/ResourceAssignmentUtils.kt
index 7ffc6db39..7bb757b8e 100644
--- a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/utils/ResourceAssignmentUtils.kt
+++ b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/utils/ResourceAssignmentUtils.kt
@@ -42,6 +42,9 @@ import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintRuntimeServ
import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonReactorUtils
import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils
import org.onap.ccsdk.cds.controllerblueprints.core.utils.PropertyDefinitionUtils.Companion.hasLogProtect
+import org.onap.ccsdk.cds.controllerblueprints.resource.dict.DictionaryMetadataEntry
+import org.onap.ccsdk.cds.controllerblueprints.resource.dict.KeyIdentifier
+import org.onap.ccsdk.cds.controllerblueprints.resource.dict.ResolutionSummary
import org.onap.ccsdk.cds.controllerblueprints.resource.dict.ResourceAssignment
import org.onap.ccsdk.cds.controllerblueprints.resource.dict.ResourceDefinition
import org.slf4j.LoggerFactory
@@ -196,6 +199,29 @@ class ResourceAssignmentUtils {
return data
}
+ fun generateResolutionSummaryData(
+ resourceAssignments: List<ResourceAssignment>,
+ resourceDefinitions: Map<String, ResourceDefinition>
+ ): String {
+ val resolutionSummaryList = resourceAssignments.map {
+ val definition = resourceDefinitions[it.name]
+ val payload = definition?.sources?.get(it.dictionarySource)
+ ?.properties?.get("resolved-payload")
+ val metadata = definition?.property?.metadata
+ ?.map { e -> DictionaryMetadataEntry(e.key, e.value) }
+ ?.toMutableList() ?: mutableListOf()
+ val description = definition?.property?.description
+ ResolutionSummary(
+ it.name, it.property?.value, it.property?.required, it.property?.type,
+ it.keyIdentifiers, description, metadata, it.dictionaryName,
+ it.dictionarySource, payload, it.status, it.message
+ )
+ }
+ // Wrapper needed for integration with SDNC
+ val data = mapOf("resolution-summary" to resolutionSummaryList)
+ return JacksonUtils.getJson(data, includeNull = true)
+ }
+
private fun useDefaultValueIfNull(
resourceAssignment: ResourceAssignment,
resourceAssignmentName: String
@@ -263,7 +289,7 @@ class ResourceAssignmentUtils {
return when (type) {
in BluePrintTypes.validPrimitiveTypes() -> {
// Primitive Types
- parseResponseNodeForPrimitiveTypes(responseNode, outputKeyMapping)
+ parseResponseNodeForPrimitiveTypes(responseNode, resourceAssignment, outputKeyMapping)
}
in BluePrintTypes.validCollectionTypes() -> {
// Array Types
@@ -282,6 +308,7 @@ class ResourceAssignmentUtils {
private fun parseResponseNodeForPrimitiveTypes(
responseNode: JsonNode,
+ resourceAssignment: ResourceAssignment,
outputKeyMapping: MutableMap<String, String>
): JsonNode {
// Return responseNode if is not a Complex Type
@@ -306,11 +333,16 @@ class ResourceAssignmentUtils {
if (returnNode.isNullOrMissing() || returnNode!!.isComplexType() && !returnNode.has(outputKeyMapping[outputKey])) {
throw BluePrintProcessorException("Fail to find output key mapping ($outputKey) in the responseNode.")
}
- return if (returnNode.isComplexType()) {
+
+ val returnValue = if (returnNode.isComplexType()) {
returnNode[outputKeyMapping[outputKey]]
} else {
returnNode
}
+
+ outputKey?.let { KeyIdentifier(it, returnValue) }
+ ?.let { resourceAssignment.keyIdentifiers.add(it) }
+ return returnValue
}
private fun parseResponseNodeForCollection(
@@ -337,7 +369,7 @@ class ResourceAssignmentUtils {
val responseArrayNode = responseNode.toList()
for (responseSingleJsonNode in responseArrayNode) {
val arrayChildNode = parseSingleElementOfArrayResponseNode(
- entrySchemaType,
+ entrySchemaType, resourceAssignment,
outputKeyMapping, raRuntimeService, responseSingleJsonNode, metadata
)
arrayNode.add(arrayChildNode)
@@ -347,7 +379,10 @@ class ResourceAssignmentUtils {
is ObjectNode -> {
val responseArrayNode = responseNode.rootFieldsToMap()
resultNode =
- parseObjectResponseNode(entrySchemaType, outputKeyMapping, responseArrayNode, metadata)
+ parseObjectResponseNode(
+ resourceAssignment, entrySchemaType, outputKeyMapping,
+ responseArrayNode, metadata
+ )
}
else -> {
throw BluePrintProcessorException("Key-value response expected to match the responseNode.")
@@ -387,6 +422,7 @@ class ResourceAssignmentUtils {
private fun parseSingleElementOfArrayResponseNode(
entrySchemaType: String,
+ resourceAssignment: ResourceAssignment,
outputKeyMapping: MutableMap<String, String>,
raRuntimeService: ResourceAssignmentRuntimeService,
responseNode: JsonNode,
@@ -397,7 +433,13 @@ class ResourceAssignmentUtils {
in BluePrintTypes.validPrimitiveTypes() -> {
if (outputKeyMappingHasOnlyOneElement) {
val outputKeyMap = outputKeyMapping.entries.first()
+ if (resourceAssignment.keyIdentifiers.none { it.name == outputKeyMap.key }) {
+ resourceAssignment.keyIdentifiers.add(
+ KeyIdentifier(outputKeyMap.key, JacksonUtils.objectMapper.createArrayNode())
+ )
+ }
return parseSingleElementNodeWithOneOutputKeyMapping(
+ resourceAssignment,
responseNode,
outputKeyMap.key,
outputKeyMap.value,
@@ -416,6 +458,7 @@ class ResourceAssignmentUtils {
raRuntimeService
) -> {
parseSingleElementNodeWithAllOutputKeyMapping(
+ resourceAssignment,
responseNode,
outputKeyMapping,
entrySchemaType,
@@ -425,6 +468,7 @@ class ResourceAssignmentUtils {
outputKeyMappingHasOnlyOneElement -> {
val outputKeyMap = outputKeyMapping.entries.first()
parseSingleElementNodeWithOneOutputKeyMapping(
+ resourceAssignment,
responseNode,
outputKeyMap.key,
outputKeyMap.value,
@@ -441,6 +485,7 @@ class ResourceAssignmentUtils {
}
private fun parseObjectResponseNode(
+ resourceAssignment: ResourceAssignment,
entrySchemaType: String,
outputKeyMapping: MutableMap<String, String>,
responseArrayNode: MutableMap<String, JsonNode>,
@@ -449,19 +494,21 @@ class ResourceAssignmentUtils {
val outputKeyMappingHasOnlyOneElement = checkIfOutputKeyMappingProvideOneElement(outputKeyMapping)
if (outputKeyMappingHasOnlyOneElement) {
val outputKeyMap = outputKeyMapping.entries.first()
- return parseObjectResponseNodeWithOneOutputKeyMapping(
+ val returnValue = parseObjectResponseNodeWithOneOutputKeyMapping(
responseArrayNode, outputKeyMap.key, outputKeyMap.value,
entrySchemaType, metadata
)
+ resourceAssignment.keyIdentifiers.add(KeyIdentifier(outputKeyMap.key, returnValue))
+ return returnValue
} else {
throw BluePrintProcessorException("Output-key-mapping do not map the Data Type $entrySchemaType")
}
}
private fun parseSingleElementNodeWithOneOutputKeyMapping(
+ resourceAssignment: ResourceAssignment,
responseSingleJsonNode: JsonNode,
- outputKeyMappingKey:
- String,
+ outputKeyMappingKey: String,
outputKeyMappingValue: String,
type: String,
metadata: MutableMap<String, String>?
@@ -476,11 +523,19 @@ class ResourceAssignmentUtils {
logKeyValueResolvedResource(metadata, outputKeyMappingKey, responseKeyValue, type)
JacksonUtils.populateJsonNodeValues(outputKeyMappingKey, responseKeyValue, type, arrayChildNode)
-
+ resourceAssignment.keyIdentifiers.find { it.name == outputKeyMappingKey && it.value.isArray }
+ .let {
+ if (it != null)
+ (it.value as ArrayNode).add(responseKeyValue)
+ else
+ resourceAssignment.keyIdentifiers.add(
+ KeyIdentifier(outputKeyMappingKey, responseKeyValue))
+ }
return arrayChildNode
}
private fun parseSingleElementNodeWithAllOutputKeyMapping(
+ resourceAssignment: ResourceAssignment,
responseSingleJsonNode: JsonNode,
outputKeyMapping: MutableMap<String, String>,
type: String,
@@ -496,6 +551,7 @@ class ResourceAssignmentUtils {
logKeyValueResolvedResource(metadata, it.key, responseKeyValue, type)
JacksonUtils.populateJsonNodeValues(it.key, responseKeyValue, type, arrayChildNode)
+ resourceAssignment.keyIdentifiers.add(KeyIdentifier(it.key, responseKeyValue))
}
return arrayChildNode
}
@@ -541,6 +597,7 @@ class ResourceAssignmentUtils {
raRuntimeService
) -> {
parseSingleElementNodeWithAllOutputKeyMapping(
+ resourceAssignment,
responseNode,
outputKeyMapping,
entrySchemaType,
@@ -550,8 +607,8 @@ class ResourceAssignmentUtils {
outputKeyMappingHasOnlyOneElement -> {
val outputKeyMap = outputKeyMapping.entries.first()
parseSingleElementNodeWithOneOutputKeyMapping(
- responseNode, outputKeyMap.key, outputKeyMap.value,
- entrySchemaType, metadata
+ resourceAssignment, responseNode, outputKeyMap.key,
+ outputKeyMap.value, entrySchemaType, metadata
)
}
else -> {
diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionComponentDSLTest.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionComponentDSLTest.kt
index ae9b4208f..d1347113a 100644
--- a/ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionComponentDSLTest.kt
+++ b/ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionComponentDSLTest.kt
@@ -41,6 +41,7 @@ class ResourceResolutionComponentDSLTest {
occurrence(2)
resourceType("vnf")
storeResult(false)
+ resolutionSummary(true)
artifactPrefixNames(arrayListOf("template1", "template2"))
dynamicProperties(
"""{
diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionServiceTest.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionServiceTest.kt
index 2f338a3a1..d5c43184e 100644
--- a/ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionServiceTest.kt
+++ b/ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionServiceTest.kt
@@ -36,6 +36,7 @@ import org.onap.ccsdk.cds.controllerblueprints.core.asJsonPrimitive
import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintContext
import org.onap.ccsdk.cds.controllerblueprints.core.utils.BluePrintMetadataUtils
import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils
+import org.onap.ccsdk.cds.controllerblueprints.resource.dict.ResolutionSummary
import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.autoconfigure.EnableAutoConfiguration
@@ -44,6 +45,7 @@ import org.springframework.context.annotation.ComponentScan
import org.springframework.test.context.ContextConfiguration
import org.springframework.test.context.TestPropertySource
import org.springframework.test.context.junit4.SpringRunner
+import kotlin.test.assertEquals
import kotlin.test.assertNotNull
import kotlin.test.assertTrue
@@ -79,6 +81,7 @@ class ResourceResolutionServiceTest {
props[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOURCE_ID] = resourceId
props[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOURCE_TYPE] = resourceType
props[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_OCCURRENCE] = occurrence
+ props[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOLUTION_SUMMARY] = false
}
@Test
@@ -214,6 +217,101 @@ class ResourceResolutionServiceTest {
}
@Test
+ @Throws(Exception::class)
+ fun testResolveResourcesResolutionSummary() {
+ runBlocking {
+ props[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOLUTION_SUMMARY] = true
+ Assert.assertNotNull("failed to create ResourceResolutionService", resourceResolutionService)
+
+ val bluePrintRuntimeService = BluePrintMetadataUtils.getBluePrintRuntime(
+ "1234",
+ "./../../../../components/model-catalog/blueprint-model/test-blueprint/baseconfiguration"
+ )
+
+ val executionServiceInput =
+ JacksonUtils.readValueFromClassPathFile(
+ "payload/requests/sample-resourceresolution-request.json",
+ ExecutionServiceInput::class.java
+ )!!
+
+ val resourceAssignmentRuntimeService =
+ ResourceAssignmentUtils.transformToRARuntimeService(
+ bluePrintRuntimeService,
+ "testResolveResourcesWithMappingAndTemplate"
+ )
+
+ val artifactPrefix = "notemplate"
+
+ // Prepare Inputs
+ PayloadUtils.prepareInputsFromWorkflowPayload(
+ bluePrintRuntimeService,
+ executionServiceInput.payload,
+ "resource-assignment"
+ )
+
+ resourceResolutionService.resolveResources(
+ resourceAssignmentRuntimeService,
+ "resource-assignment",
+ artifactPrefix,
+ props
+ )
+ }.let {
+ val summaries = JacksonUtils.jsonNode(it)["resolution-summary"]
+ val list = JacksonUtils.getListFromJsonNode(summaries, ResolutionSummary::class.java)
+ assertEquals(list.size, 3)
+ }
+ }
+
+ @Test
+ @Throws(Exception::class)
+ fun testResolveResourcesWithoutTemplate() {
+ runBlocking {
+ Assert.assertNotNull("failed to create ResourceResolutionService", resourceResolutionService)
+
+ val bluePrintRuntimeService = BluePrintMetadataUtils.getBluePrintRuntime(
+ "1234",
+ "./../../../../components/model-catalog/blueprint-model/test-blueprint/baseconfiguration"
+ )
+
+ val executionServiceInput =
+ JacksonUtils.readValueFromClassPathFile(
+ "payload/requests/sample-resourceresolution-request.json",
+ ExecutionServiceInput::class.java
+ )!!
+
+ val resourceAssignmentRuntimeService =
+ ResourceAssignmentUtils.transformToRARuntimeService(
+ bluePrintRuntimeService,
+ "testResolveResourcesWithMappingAndTemplate"
+ )
+
+ val artifactPrefix = "notemplate"
+
+ // Prepare Inputs
+ PayloadUtils.prepareInputsFromWorkflowPayload(
+ bluePrintRuntimeService,
+ executionServiceInput.payload,
+ "resource-assignment"
+ )
+
+ resourceResolutionService.resolveResources(
+ resourceAssignmentRuntimeService,
+ "resource-assignment",
+ artifactPrefix,
+ props
+ )
+ }.let {
+ assertEquals("""
+ {
+ "service-instance-id" : "siid_1234",
+ "vnf-id" : "vnf_1234",
+ "vnf_name" : "temp_vnf"
+ }
+ """.trimIndent(), it)
+ }
+ }
+
+ @Test
fun testResolveResourcesWithResourceIdAndResourceType() {
props[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOLUTION_KEY] = ""
runBlocking {
diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionDBServiceTest.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionDBServiceTest.kt
index 4f864a49c..e667cd16f 100644
--- a/ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionDBServiceTest.kt
+++ b/ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionDBServiceTest.kt
@@ -223,4 +223,16 @@ open class ResourceResolutionDBServiceTest {
assertEquals(resourceResolution, res)
}
}
+
+ @Test
+ fun deleteByBlueprintNameAndBlueprintVersionAndArtifactNameAndResolutionKeyTest() {
+ every {
+ resourceResolutionRepository.deleteByBlueprintNameAndBlueprintVersionAndArtifactNameAndResolutionKey(any(), any(), any(), any())
+ } returns Unit
+ runBlocking {
+ val res = resourceResolutionDBService.deleteByBlueprintNameAndBlueprintVersionAndArtifactNameAndResolutionKey(
+ blueprintName, blueprintVersion, artifactPrefix, resolutionKey)
+ assertEquals(Unit, res)
+ }
+ }
}
diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/CapabilityResourceResolutionProcessorTest.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/CapabilityResourceResolutionProcessorTest.kt
index d84488d76..5fbe32e07 100644
--- a/ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/CapabilityResourceResolutionProcessorTest.kt
+++ b/ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/CapabilityResourceResolutionProcessorTest.kt
@@ -52,6 +52,10 @@ class CapabilityResourceResolutionProcessorTest {
.scriptInstance<ResourceAssignmentProcessor>(any(), any(), any())
} returns MockCapabilityScriptRA()
+ coEvery {
+ componentFunctionScriptingService.cleanupInstance(any(), any())
+ } returns mockk()
+
val raRuntimeService = mockk<ResourceAssignmentRuntimeService>()
every { raRuntimeService.bluePrintContext() } returns mockk<BluePrintContext>()
every { raRuntimeService.getInputValue("test-property") } returns NullNode.getInstance()
@@ -96,6 +100,10 @@ class CapabilityResourceResolutionProcessorTest {
.scriptInstance<ResourceAssignmentProcessor>(any(), BluePrintConstants.SCRIPT_JYTHON, any())
} returns MockCapabilityScriptRA()
+ coEvery {
+ componentFunctionScriptingService.cleanupInstance(any(), any())
+ } returns mockk()
+
val resourceAssignmentRuntimeService = ResourceAssignmentRuntimeService("1234", bluePrintContext)
val capabilityResourceResolutionProcessor =
diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/utils/ResourceAssignmentUtilsTest.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/utils/ResourceAssignmentUtilsTest.kt
index 3251dcacb..9df8fb7d7 100644
--- a/ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/utils/ResourceAssignmentUtilsTest.kt
+++ b/ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/utils/ResourceAssignmentUtilsTest.kt
@@ -33,10 +33,12 @@ import org.onap.ccsdk.cds.controllerblueprints.core.asJsonPrimitive
import org.onap.ccsdk.cds.controllerblueprints.core.asJsonType
import org.onap.ccsdk.cds.controllerblueprints.core.data.DataType
import org.onap.ccsdk.cds.controllerblueprints.core.data.EntrySchema
+import org.onap.ccsdk.cds.controllerblueprints.core.data.NodeTemplate
import org.onap.ccsdk.cds.controllerblueprints.core.data.PropertyDefinition
import org.onap.ccsdk.cds.controllerblueprints.core.utils.BluePrintMetadataUtils
import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils
import org.onap.ccsdk.cds.controllerblueprints.resource.dict.ResourceAssignment
+import org.onap.ccsdk.cds.controllerblueprints.resource.dict.ResourceDefinition
import kotlin.test.assertEquals
data class IpAddress(val port: String, val ip: String)
@@ -46,6 +48,7 @@ data class ExpectedResponseIpAddress(val ipAddress: IpAddress)
class ResourceAssignmentUtilsTest {
private lateinit var resourceAssignmentRuntimeService: ResourceAssignmentRuntimeService
+ private lateinit var resourceAssignment: ResourceAssignment
private lateinit var inputMapToTestPrimitiveTypeWithValue: JsonNode
private lateinit var inputMapToTestPrimitiveTypeWithKeyValue: JsonNode
@@ -156,6 +159,46 @@ class ResourceAssignmentUtilsTest {
assertEquals(expected, outcome.replace("\r\n", "\n"), "unexpected outcome generated")
}
+ @Test
+ fun generate() {
+ val resourceAssignment = createResourceAssignmentForTest(null)
+ val resourceDefinition = ResourceDefinition()
+ val nodeTemplate = NodeTemplate().apply {
+ properties = mutableMapOf("resolved-payload" to JacksonUtils.jsonNode("{\"mock\": true}"))
+ }
+ resourceDefinition.sources = mutableMapOf("input" to nodeTemplate)
+ resourceDefinition.property = PropertyDefinition().apply {
+ this.description = "pnf-id"
+ this.metadata = mutableMapOf("aai-path" to "//path/in/aai")
+ }
+
+ val result = ResourceAssignmentUtils.generateResolutionSummaryData(
+ listOf(resourceAssignment), mapOf("pnf-id" to resourceDefinition))
+
+ assertEquals("""
+ {
+ "resolution-summary":[
+ {
+ "name":"pnf-id",
+ "value":null,
+ "required":null,
+ "type":"string",
+ "key-identifiers":[],
+ "dictionary-description":"pnf-id",
+ "dictionary-metadata":[
+ {"name":"aai-path","value":"//path/in/aai"}
+ ],
+ "dictionary-name":"pnf-id",
+ "dictionary-source":"input",
+ "request-payload":{"mock":true},
+ "status":null,
+ "message":null
+ }
+ ]
+ }
+ """.replace("\n|\\s".toRegex(), ""), result)
+ }
+
private fun createResourceAssignmentForTest(resourceValue: String?): ResourceAssignment {
val valueForTest = if (resourceValue == null) null else TextNode(resourceValue)
val resourceAssignmentForTest = ResourceAssignment().apply {
@@ -181,6 +224,7 @@ class ResourceAssignmentUtilsTest {
outcome,
"Unexpected outcome returned for primitive type of simple String"
)
+ assertEquals(0, resourceAssignment.keyIdentifiers.size)
outcome = prepareResponseNodeForTest(
"sample-key-value", "string", "",
@@ -191,6 +235,10 @@ class ResourceAssignmentUtilsTest {
outcome,
"Unexpected outcome returned for primitive type of key-value String"
)
+ assertEquals(
+ expectedValueToTestPrimitiveType,
+ resourceAssignment.keyIdentifiers[0].value
+ )
}
@Test
@@ -204,6 +252,13 @@ class ResourceAssignmentUtilsTest {
outcome,
"unexpected outcome returned for list of String"
)
+
+ val expectedKeyIdentifierValue = JacksonUtils.getJsonNode(outcome.map { it["ip"] })
+ assertEquals(
+ expectedKeyIdentifierValue,
+ resourceAssignment.keyIdentifiers[0].value
+ )
+
// FIXME("Map is not collection type, It is known complex type")
// outcome = prepareResponseNodeForTest(
// "mapOfString", "map", "string",
@@ -250,6 +305,9 @@ class ResourceAssignmentUtilsTest {
outcome,
"Unexpected outcome returned for complex type"
)
+ assertEquals(
+ expectedValueToTestComplexTypeWithOneOutputKeyMapping["host"],
+ resourceAssignment.keyIdentifiers[0].value)
}
@Test
@@ -263,6 +321,16 @@ class ResourceAssignmentUtilsTest {
outcome,
"Unexpected outcome returned for complex type"
)
+ assertEquals(2, resourceAssignment.keyIdentifiers.size)
+ assertEquals(
+ expectedValueToTestComplexTypeWithAllOutputKeyMapping["name"],
+ resourceAssignment.keyIdentifiers[0].value
+ )
+
+ assertEquals(
+ expectedValueToTestComplexTypeWithAllOutputKeyMapping["ipAddress"],
+ resourceAssignment.keyIdentifiers[1].value
+ )
}
private fun initInputMapAndExpectedValuesForPrimitiveType() {
@@ -359,7 +427,7 @@ class ResourceAssignmentUtilsTest {
response: Any
): JsonNode {
- val resourceAssignment = when (sourceType) {
+ resourceAssignment = when (sourceType) {
"list" -> {
prepareRADataDictionaryCollection(dictionary_source, sourceType, entrySchema)
}
diff --git a/ms/blueprintsprocessor/functions/restconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/restconf/executor/RestconfExecutorExtensions.kt b/ms/blueprintsprocessor/functions/restconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/restconf/executor/RestconfExecutorExtensions.kt
index 906bef9a4..408eaf45b 100644
--- a/ms/blueprintsprocessor/functions/restconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/restconf/executor/RestconfExecutorExtensions.kt
+++ b/ms/blueprintsprocessor/functions/restconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/restconf/executor/RestconfExecutorExtensions.kt
@@ -45,12 +45,12 @@ suspend fun AbstractScriptComponentFunction.restconfMountDevice(
headers: Map<String, String> = mutableMapOf("Content-Type" to "application/xml")
) {
- val mountUrl = "restconf/config/network-topology:network-topology/topology/topology-netconf/node/$deviceId"
+ val mountUrl = "/restconf/config/network-topology:network-topology/topology/topology-netconf/node/$deviceId"
log.info("sending mount request, url: $mountUrl")
webClientService.exchangeResource("PUT", mountUrl, payload as String, headers)
/** Check device has mounted */
- val mountCheckUrl = "restconf/operational/network-topology:network-topology/topology/topology-netconf/node/$deviceId"
+ val mountCheckUrl = "/restconf/operational/network-topology:network-topology/topology/topology-netconf/node/$deviceId"
val expectedResult = """"netconf-node-topology:connection-status":"connected""""
val mountCheckExecutionBlock: suspend (Int) -> String = { tryCount: Int ->
@@ -69,6 +69,7 @@ suspend fun AbstractScriptComponentFunction.restconfMountDevice(
/**
* Generic Configure function
+ * @return The WebClientResponse from the request
*/
suspend fun AbstractScriptComponentFunction.restconfApplyDeviceConfig(
webClientService: BlueprintWebClientService,
@@ -76,14 +77,12 @@ suspend fun AbstractScriptComponentFunction.restconfApplyDeviceConfig(
configletResourcePath: String,
configletToApply: Any,
additionalHeaders: Map<String, String> = mutableMapOf("Content-Type" to "application/yang.patch+xml")
-) {
-
+): BlueprintWebClientService.WebClientResponse<String> {
log.debug("headers: $additionalHeaders")
log.info("configuring device: $deviceId, Configlet: $configletToApply")
- val applyConfigUrl = "restconf/config/network-topology:network-topology/topology/topology-netconf/node/" +
+ val applyConfigUrl = "/restconf/config/network-topology:network-topology/topology/topology-netconf/node/" +
"$deviceId/$configletResourcePath"
- val result: Any = webClientService.exchangeResource("PATCH", applyConfigUrl, configletToApply as String, additionalHeaders)
- log.info("Configuration application result: $result")
+ return webClientService.exchangeResource("PATCH", applyConfigUrl, configletToApply as String, additionalHeaders)
}
suspend fun AbstractScriptComponentFunction.restconfDeviceConfig(
@@ -93,7 +92,7 @@ suspend fun AbstractScriptComponentFunction.restconfDeviceConfig(
):
BlueprintWebClientService.WebClientResponse<String> {
- val configPathUrl = "restconf/config/network-topology:network-topology/topology/topology-netconf/node/" +
+ val configPathUrl = "/restconf/config/network-topology:network-topology/topology/topology-netconf/node/" +
"$deviceId/$configletResourcePath"
log.debug("sending GET request, url: $configPathUrl")
return webClientService.exchangeResource("GET", configPathUrl, "")
@@ -107,7 +106,7 @@ suspend fun AbstractScriptComponentFunction.restconfUnMountDevice(
deviceId: String,
payload: String
) {
- val unMountUrl = "restconf/config/network-topology:network-topology/topology/topology-netconf/node/$deviceId"
+ val unMountUrl = "/restconf/config/network-topology:network-topology/topology/topology-netconf/node/$deviceId"
log.info("sending unMount request, url: $unMountUrl")
webClientService.exchangeResource("DELETE", unMountUrl, "")
}
diff --git a/ms/blueprintsprocessor/functions/nrm-restful/pom.xml b/ms/blueprintsprocessor/functions/restful-executor/pom.xml
index 337e71e15..4ac52c4b8 100644
--- a/ms/blueprintsprocessor/functions/nrm-restful/pom.xml
+++ b/ms/blueprintsprocessor/functions/restful-executor/pom.xml
@@ -24,11 +24,10 @@
</parent>
<groupId>org.onap.ccsdk.cds.blueprintsprocessor.functions</groupId>
- <artifactId>nrm-restful</artifactId>
- <packaging>jar</packaging>
+ <artifactId>restful-executor</artifactId>
- <name>Blueprints Processor Function - NRM Restful</name>
- <description>Blueprints Processor Function - NRM Restful</description>
+ <name>Blueprints Processor Function - NRM Restful executor</name>
+ <description>Blueprints Processor Function - NRM Restful executor</description>
<dependencies>
<dependency>
@@ -48,5 +47,10 @@
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
+ <dependency>
+ <groupId>com.h2database</groupId>
+ <artifactId>h2</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
</project>
diff --git a/ms/blueprintsprocessor/functions/restful-executor/src/main/kotlin/internal/scripts/TestRestfulConfigure.kt b/ms/blueprintsprocessor/functions/restful-executor/src/main/kotlin/internal/scripts/TestRestfulConfigure.kt
new file mode 100644
index 000000000..5f867b93f
--- /dev/null
+++ b/ms/blueprintsprocessor/functions/restful-executor/src/main/kotlin/internal/scripts/TestRestfulConfigure.kt
@@ -0,0 +1,42 @@
+/*
+ * Copyright © 2020 Huawei.
+ *
+ * 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.
+ */
+@file:Suppress("unused")
+
+package internal.scripts
+
+import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput
+import org.onap.ccsdk.cds.blueprintsprocessor.functions.restful.executor.RestfulCMComponentFunction
+import org.slf4j.LoggerFactory
+
+/**
+ * This is for used for Testing only
+ */
+open class TestRestfulConfigure : RestfulCMComponentFunction() {
+
+ val log = LoggerFactory.getLogger(TestRestfulConfigure::class.java)!!
+
+ override fun getName(): String {
+ return "TestRestfulConfigure"
+ }
+
+ override suspend fun processNB(executionRequest: ExecutionServiceInput) {
+ log.info("processing request..")
+ }
+
+ override suspend fun recoverNB(runtimeException: RuntimeException, executionRequest: ExecutionServiceInput) {
+ log.info("recovering..")
+ }
+}
diff --git a/ms/blueprintsprocessor/functions/restful-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/restful/executor/ComponentRestfulExecutor.kt b/ms/blueprintsprocessor/functions/restful-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/restful/executor/ComponentRestfulExecutor.kt
new file mode 100644
index 000000000..e1643b576
--- /dev/null
+++ b/ms/blueprintsprocessor/functions/restful-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/restful/executor/ComponentRestfulExecutor.kt
@@ -0,0 +1,69 @@
+/*
+ * Copyright © 2020 Huawei Intellectual Property.
+ *
+ * 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.
+ */
+package org.onap.ccsdk.cds.blueprintsprocessor.functions.restful.executor
+
+import com.fasterxml.jackson.databind.node.ArrayNode
+import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput
+import org.onap.ccsdk.cds.blueprintsprocessor.rest.RestLibConstants
+import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.AbstractComponentFunction
+import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.ComponentFunctionScriptingService
+import org.onap.ccsdk.cds.controllerblueprints.core.getAsString
+import org.springframework.beans.factory.config.ConfigurableBeanFactory
+import org.springframework.context.annotation.Scope
+import org.springframework.stereotype.Component
+
+@Component("component-restful-executor")
+@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
+open class ComponentRestfulExecutor(private var componentFunctionScriptingService: ComponentFunctionScriptingService) : AbstractComponentFunction() {
+
+ lateinit var scriptComponent: RestfulCMComponentFunction
+
+ companion object {
+ const val SCRIPT_TYPE = "script-type"
+ const val SCRIPT_CLASS_REFERENCE = "script-class-reference"
+ const val INSTANCE_DEPENDENCIES = "instance-dependencies"
+ }
+
+ override suspend fun processNB(executionRequest: ExecutionServiceInput) {
+
+ val scriptType = operationInputs.getAsString(SCRIPT_TYPE)
+ val scriptClassReference = operationInputs.getAsString(SCRIPT_CLASS_REFERENCE)
+ val instanceDependenciesNode = operationInputs.get(INSTANCE_DEPENDENCIES) as? ArrayNode
+
+ val scriptDependencies: MutableList<String> = arrayListOf()
+ scriptDependencies.add(RestLibConstants.SERVICE_BLUEPRINT_REST_LIB_PROPERTY)
+
+ instanceDependenciesNode?.forEach { instanceName ->
+ scriptDependencies.add(instanceName.textValue())
+ }
+ /**
+ * Populate the Script Instance based on the Type
+ */
+ scriptComponent = componentFunctionScriptingService
+ .scriptInstance<RestfulCMComponentFunction>(this, scriptType,
+ scriptClassReference, scriptDependencies)
+
+ checkNotNull(scriptComponent) { "failed to get restfulCM script component" }
+
+ // Handles both script processing and error handling
+ scriptComponent.executeScript(executionServiceInput)
+ }
+
+ override suspend fun recoverNB(runtimeException: RuntimeException, executionRequest: ExecutionServiceInput) {
+ bluePrintRuntimeService.getBluePrintError()
+ .addError("Failed in ComponentRestfulExecutor : ${runtimeException.message}")
+ }
+}
diff --git a/ms/blueprintsprocessor/functions/restful-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/restful/executor/RestfulCMComponentFunction.kt b/ms/blueprintsprocessor/functions/restful-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/restful/executor/RestfulCMComponentFunction.kt
new file mode 100644
index 000000000..46fec3126
--- /dev/null
+++ b/ms/blueprintsprocessor/functions/restful-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/restful/executor/RestfulCMComponentFunction.kt
@@ -0,0 +1,126 @@
+/*
+ * Copyright © 2020 Huawei.
+ *
+ * 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.
+ */
+package org.onap.ccsdk.cds.blueprintsprocessor.functions.restful.executor
+
+import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput
+import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.AbstractScriptComponentFunction
+import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintException
+import com.fasterxml.jackson.databind.JsonNode
+import com.fasterxml.jackson.databind.ObjectMapper
+import com.fasterxml.jackson.databind.node.ObjectNode
+import com.fasterxml.jackson.databind.node.ArrayNode
+import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils
+import org.onap.ccsdk.cds.blueprintsprocessor.rest.RestLibConstants
+import org.onap.ccsdk.cds.blueprintsprocessor.rest.service.BluePrintRestLibPropertyService
+import org.onap.ccsdk.cds.blueprintsprocessor.rest.service.BlueprintWebClientService
+import org.onap.ccsdk.cds.blueprintsprocessor.functions.restful.executor.nrmfunction.RestfulNRMServiceClient
+import org.slf4j.LoggerFactory
+
+abstract class RestfulCMComponentFunction : AbstractScriptComponentFunction() {
+
+ private val log = LoggerFactory.getLogger(RestfulCMComponentFunction::class.java)
+ override suspend fun processNB(executionRequest: ExecutionServiceInput) {
+ throw BluePrintException("Not Implemented required")
+ }
+
+ override suspend fun recoverNB(runtimeException: RuntimeException, executionRequest: ExecutionServiceInput) {
+ throw BluePrintException("Not Implemented required")
+ }
+
+ open fun bluePrintRestLibPropertyService(): BluePrintRestLibPropertyService =
+ functionDependencyInstanceAsType(RestLibConstants.SERVICE_BLUEPRINT_REST_LIB_PROPERTY)
+
+ fun restClientService(clientInfo: JsonNode): BlueprintWebClientService {
+ return bluePrintRestLibPropertyService().blueprintWebClientService(clientInfo)
+ }
+
+ fun processNRM(executionRequest: ExecutionServiceInput, input_params: ArrayNode): String {
+ // process the managed object instances
+ log.info("Processing NRM Object")
+ operationInputs = executionServiceInput.stepData!!.properties
+ val dynamic_properties = operationInputs.get("dynamic-properties")
+ // instantiate one restClientService instance
+ val hostname = dynamic_properties?.get("hostname").toString().replace("\"", "")
+ val port = dynamic_properties?.get("port").toString().replace("\"", "")
+ val username = dynamic_properties?.get("username").toString().replace("\"", "")
+ val password = dynamic_properties?.get("password").toString().replace("\"", "")
+ val url = "http://" + hostname + ":" + port
+ val RestInfo: String = "{\n" +
+ " \"type\" : \"basic-auth\",\n" +
+ " \"url\" : \"" + url + "\",\n" +
+ " \"username\" : \"" + username + "\",\n" +
+ " \"password\" : \"" + password + "\"\n" +
+ "}"
+ val mapper = ObjectMapper()
+ val jsonRestInfo: JsonNode = mapper.readTree(RestInfo)
+ val web_client_service = restClientService(jsonRestInfo)
+ val managed_object_instances = input_params
+ var response = JacksonUtils.jsonNode("{}") as ObjectNode
+ // Invoke the corresponding function according to the workflowname
+ when (this.workflowName) {
+ "config-deploy" -> {
+ for (managed_object_instance in managed_object_instances) {
+ // invoke createMOI for each managed-object-instance
+ log.info("invoke createMOI for each managed-object-instance")
+ var NRM_Restful_client = RestfulNRMServiceClient()
+ val MOI_id = NRM_Restful_client.generateMOIid()
+ var httpresponse = NRM_Restful_client.createMOI(web_client_service, MOI_id, managed_object_instance)
+ var MOIname = managed_object_instance.get("className").toString().replace("\"", "")
+ response.put("/$MOIname/$MOI_id", httpresponse)
+ }
+ }
+ "config-get" -> {
+ for (managed_object_instance in managed_object_instances) {
+ // invoke getMOIAttributes for each managed-object-instance
+ log.info("invoke getMOIAttributes for each managed-object-instance")
+ var NRM_Restful_client = RestfulNRMServiceClient()
+ val MOI_id = managed_object_instance.get("id").toString().replace("\"", "")
+ var httpresponse = NRM_Restful_client.getMOIAttributes(web_client_service, MOI_id, managed_object_instance)
+ var MOIname = managed_object_instance.get("className").toString().replace("\"", "")
+ response.put("/$MOIname/$MOI_id", httpresponse)
+ }
+ }
+ "config-modify" -> {
+ for (managed_object_instance in managed_object_instances) {
+ // invoke modifyMOIAttributes for each managed-object-instance
+ log.info("invoke modifyMOIAttributes for each managed-object-instance")
+ var NRM_Restful_client = RestfulNRMServiceClient()
+ val MOI_id = managed_object_instance.get("id").toString().replace("\"", "")
+ var httpresponse = NRM_Restful_client.modifyMOIAttributes(web_client_service, MOI_id, managed_object_instance)
+ var MOIname = managed_object_instance.get("className").toString().replace("\"", "")
+ response.put("/$MOIname/$MOI_id", httpresponse)
+ }
+ }
+ "config-delete" -> {
+ for (managed_object_instance in managed_object_instances) {
+ // invoke deleteMOI for each managed-object-instance
+ log.info("invoke deleteMOI for each managed-object-instance")
+ var NRM_Restful_client = RestfulNRMServiceClient()
+ val MOI_id = managed_object_instance.get("id").toString().replace("\"", "")
+ var httpresponse = NRM_Restful_client.deleteMOI(web_client_service, MOI_id, managed_object_instance)
+ var MOIname = managed_object_instance.get("className").toString().replace("\"", "")
+ response.put("/$MOIname/$MOI_id", httpresponse)
+ }
+ }
+ else -> {
+ print("not Implemented")
+ response.put(this.workflowName, "Not Implemented")
+ }
+ }
+ val strresponse = "$response"
+ return strresponse
+ }
+}
diff --git a/ms/blueprintsprocessor/functions/nrm-restful/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/nrm/restful/RestfulNRMServiceClient.kt b/ms/blueprintsprocessor/functions/restful-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/restful/executor/nrmfunction/RestfulNRMServiceClient.kt
index eb14d255b..31ad377c9 100644
--- a/ms/blueprintsprocessor/functions/nrm-restful/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/nrm/restful/RestfulNRMServiceClient.kt
+++ b/ms/blueprintsprocessor/functions/restful-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/restful/executor/nrmfunction/RestfulNRMServiceClient.kt
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.onap.ccsdk.cds.blueprintsprocessor.functions.nrm.restful
+package org.onap.ccsdk.cds.blueprintsprocessor.functions.restful.executor.nrmfunction
import com.fasterxml.jackson.databind.JsonNode
import com.fasterxml.jackson.databind.ObjectMapper
diff --git a/ms/blueprintsprocessor/functions/restful-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/restful/executor/ComponentRestfulExecutorTest.kt b/ms/blueprintsprocessor/functions/restful-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/restful/executor/ComponentRestfulExecutorTest.kt
new file mode 100644
index 000000000..ad70ac021
--- /dev/null
+++ b/ms/blueprintsprocessor/functions/restful-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/restful/executor/ComponentRestfulExecutorTest.kt
@@ -0,0 +1,105 @@
+/*
+ * Copyright © 2020 Huawei Intellectual Property.
+ *
+ * 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.
+ */
+
+package org.onap.ccsdk.cds.blueprintsprocessor.functions.restful.executor
+
+import com.fasterxml.jackson.databind.JsonNode
+import com.fasterxml.jackson.databind.node.ObjectNode
+import io.mockk.every
+import io.mockk.mockk
+import kotlinx.coroutines.runBlocking
+import org.junit.Test
+import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ActionIdentifiers
+import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.CommonHeader
+import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput
+import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.StepData
+import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.ComponentFunctionScriptingService
+import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants
+import org.onap.ccsdk.cds.controllerblueprints.core.asJsonPrimitive
+import org.onap.ccsdk.cds.controllerblueprints.core.data.Implementation
+import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintContext
+import org.onap.ccsdk.cds.controllerblueprints.core.service.DefaultBluePrintRuntimeService
+import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils
+import org.springframework.context.ApplicationContext
+
+class ComponentRestfulExecutorTest {
+
+ @Test
+ fun testComponentRestfulExecutor() {
+ runBlocking {
+
+ val applicationContext = mockk<ApplicationContext>()
+ every { applicationContext.getBean(any()) } returns mockk()
+
+ val componentFunctionScriptingService = ComponentFunctionScriptingService(applicationContext, mockk())
+
+ val componentRestfulExecutor = ComponentRestfulExecutor(componentFunctionScriptingService)
+
+ val executionServiceInput = ExecutionServiceInput().apply {
+ commonHeader = CommonHeader().apply {
+ requestId = "1234"
+ }
+ actionIdentifiers = ActionIdentifiers().apply {
+ actionName = "config-deploy"
+ }
+ payload = JacksonUtils.jsonNode("{}") as ObjectNode
+ }
+
+ val blueprintContext = mockk<BluePrintContext>()
+ every {
+ blueprintContext.nodeTemplateOperationImplementation(
+ any(), any(), any()
+ )
+ } returns Implementation()
+
+ val bluePrintRuntime = mockk<DefaultBluePrintRuntimeService>("1234")
+ every { bluePrintRuntime.bluePrintContext() } returns blueprintContext
+
+ componentRestfulExecutor.bluePrintRuntimeService = bluePrintRuntime
+ componentRestfulExecutor.stepName = "sample-step"
+
+ val operationInputs = hashMapOf<String, JsonNode>()
+ operationInputs[BluePrintConstants.PROPERTY_CURRENT_NODE_TEMPLATE] = "config-deploy-process".asJsonPrimitive()
+ operationInputs[BluePrintConstants.PROPERTY_CURRENT_INTERFACE] = "interfaceName".asJsonPrimitive()
+ operationInputs[BluePrintConstants.PROPERTY_CURRENT_OPERATION] = "operationName".asJsonPrimitive()
+ operationInputs["script-type"] = BluePrintConstants.SCRIPT_INTERNAL.asJsonPrimitive()
+ operationInputs["script-class-reference"] = "internal.scripts.TestRestfulConfigure".asJsonPrimitive()
+
+ val stepInputData = StepData().apply {
+ name = "call-config-deploy-process"
+ properties = operationInputs
+ }
+ executionServiceInput.stepData = stepInputData
+
+ every {
+ bluePrintRuntime.resolveNodeTemplateInterfaceOperationInputs(
+ "config-deploy-process",
+ "interfaceName", "operationName"
+ )
+ } returns operationInputs
+
+ val operationOutputs = hashMapOf<String, JsonNode>()
+ every {
+ bluePrintRuntime.resolveNodeTemplateInterfaceOperationOutputs(
+ "config-deploy-process",
+ "interfaceName", "operationName"
+ )
+ } returns operationOutputs
+
+ componentRestfulExecutor.applyNB(executionServiceInput)
+ }
+ }
+}
diff --git a/ms/blueprintsprocessor/functions/nrm-restful/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/nrm/restful/RestfulNRMServiceClientTest.kt b/ms/blueprintsprocessor/functions/restful-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/restful/executor/nrmfunction/RestfulNRMServiceClientTest.kt
index 8dcb7975d..e7f04a5d4 100644
--- a/ms/blueprintsprocessor/functions/nrm-restful/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/nrm/restful/RestfulNRMServiceClientTest.kt
+++ b/ms/blueprintsprocessor/functions/restful-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/restful/executor/nrmfunction/RestfulNRMServiceClientTest.kt
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.onap.ccsdk.cds.blueprintsprocessor.functions.nrm.restful
+package org.onap.ccsdk.cds.blueprintsprocessor.functions.restful.executor.nrmfunction
import com.fasterxml.jackson.databind.node.ObjectNode
import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils
diff --git a/ms/blueprintsprocessor/modules/blueprints/blueprint-core/pom.xml b/ms/blueprintsprocessor/modules/blueprints/blueprint-core/pom.xml
index 4700c6337..fb2daab3a 100644
--- a/ms/blueprintsprocessor/modules/blueprints/blueprint-core/pom.xml
+++ b/ms/blueprintsprocessor/modules/blueprints/blueprint-core/pom.xml
@@ -76,6 +76,12 @@
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity</artifactId>
+ <exclusions>
+ <exclusion>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </exclusion>
+ </exclusions>
</dependency>
<dependency>
<groupId>com.hubspot.jinjava</groupId>
@@ -85,6 +91,10 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-compress</artifactId>
+ </dependency>
<!--Testing dependencies-->
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
diff --git a/ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/BluePrintConstants.kt b/ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/BluePrintConstants.kt
index 20aef3498..e26af2b66 100644
--- a/ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/BluePrintConstants.kt
+++ b/ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/BluePrintConstants.kt
@@ -218,9 +218,6 @@ object BluePrintConstants {
const val DEFAULT_STEP_OPERATION = "process"
const val DEFAULT_STEP_INTERFACE = "ComponentInterface"
- const val ARTIFACT_VELOCITY_TYPE_NAME = "artifact-template-velocity"
- const val ARTIFACT_JINJA_TYPE_NAME = "artifact-template-jinja"
-
const val MODEL_TYPE_ARTIFACT_TEMPLATE_VELOCITY = "artifact-template-velocity"
const val MODEL_TYPE_ARTIFACT_TEMPLATE_JINJA = "artifact-template-jinja"
const val MODEL_TYPE_ARTIFACT_MAPPING_RESOURCE = "artifact-mapping-resource"
@@ -229,6 +226,8 @@ object BluePrintConstants {
const val MODEL_TYPE_ARTIFACT_DIRECTED_GRAPH = "artifact-directed-graph"
const val MODEL_TYPE_ARTIFACT_COMPONENT_JAR = "artifact-component-jar"
+ const val TOSCA_SPEC = "TOSCA"
+
val USE_SCRIPT_COMPILE_CACHE: Boolean = (System.getenv("USE_SCRIPT_COMPILE_CACHE") ?: "true").toBoolean()
const val LOG_PROTECT: String = "log-protect"
diff --git a/ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/BluePrintException.kt b/ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/BluePrintException.kt
index a2435da13..74e6bb6bd 100644
--- a/ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/BluePrintException.kt
+++ b/ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/BluePrintException.kt
@@ -1,5 +1,6 @@
/*
* Copyright © 2017-2018 AT&T Intellectual Property.
+ * Modifications Copyright © 2018 - 2020 IBM, Bell Canada.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,29 +22,13 @@ package org.onap.ccsdk.cds.controllerblueprints.core
*
* @author Brinda Santh
*/
-class BluePrintException : Exception {
-
- var code: Int = 100
+class BluePrintException : BluePrintProcessorException {
constructor(cause: Throwable) : super(cause)
constructor(message: String) : super(message)
constructor(message: String, cause: Throwable) : super(message, cause)
- constructor(cause: Throwable, message: String, vararg args: Any?) : super(String.format(message, *args), cause)
-
- constructor(code: Int, cause: Throwable) : super(cause) {
- this.code = code
- }
-
- constructor(code: Int, message: String) : super(message) {
- this.code = code
- }
-
- constructor(code: Int, message: String, cause: Throwable) : super(message, cause) {
- this.code = code
- }
-
- constructor(code: Int, cause: Throwable, message: String, vararg args: Any?) :
- super(String.format(message, *args), cause) {
- this.code = code
- }
+ constructor(cause: Throwable, message: String, vararg args: Any?) : super(cause, message, args)
+ constructor(code: Int, cause: Throwable) : super(code, cause)
+ constructor(code: Int, message: String) : super(code, message)
+ constructor(code: Int, message: String, cause: Throwable) : super(code, message, cause)
}
diff --git a/ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/BluePrintProcessorException.kt b/ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/BluePrintProcessorException.kt
index b0b217051..acb158d89 100644
--- a/ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/BluePrintProcessorException.kt
+++ b/ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/BluePrintProcessorException.kt
@@ -1,6 +1,6 @@
/*
* Copyright © 2017-2018 AT&T Intellectual Property.
- * Modifications Copyright © 2018 IBM.
+ * Modifications Copyright © 2018 - 2020 IBM, Bell Canada.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,35 +17,55 @@
package org.onap.ccsdk.cds.controllerblueprints.core
+import org.onap.ccsdk.cds.error.catalog.core.ErrorCatalogException
+import org.onap.ccsdk.cds.error.catalog.core.ErrorCatalogExceptionFluent
+import org.onap.ccsdk.cds.error.catalog.core.ErrorMessage
+
/**
*
*
* @author Brinda Santh
*/
-class BluePrintProcessorException : RuntimeException {
-
- var code: Int = 100
+open class BluePrintProcessorException : ErrorCatalogException, ErrorCatalogExceptionFluent<BluePrintProcessorException> {
constructor(message: String, cause: Throwable) : super(message, cause)
constructor(message: String) : super(message)
constructor(cause: Throwable) : super(cause)
- constructor(cause: Throwable, message: String, vararg args: Any?) : super(format(message, *args), cause)
+ constructor(cause: Throwable, message: String, vararg args: Any?) : super(cause, message, args)
+ constructor(code: Int, cause: Throwable) : super(code, cause)
+ constructor(code: Int, message: String) : super(code, message)
+ constructor(code: Int, message: String, cause: Throwable) : super(code, message, cause)
+
+ override fun code(code: Int): BluePrintProcessorException {
+ return this.updateCode(code)
+ }
+
+ override fun domain(domain: String): BluePrintProcessorException {
+ return this.updateDomain(domain)
+ }
+
+ override fun action(action: String): BluePrintProcessorException {
+ return this.updateAction(action)
+ }
- constructor(code: Int, cause: Throwable) : super(cause) {
- this.code = code
+ override fun http(type: String): BluePrintProcessorException {
+ return this.updateHttp(type)
}
- constructor(code: Int, message: String) : super(message) {
- this.code = code
+ override fun grpc(type: String): BluePrintProcessorException {
+ return this.updateGrpc(type)
}
- constructor(code: Int, message: String, cause: Throwable) : super(message, cause) {
- this.code = code
+ override fun payloadMessage(message: String): BluePrintProcessorException {
+ return this.updatePayloadMessage(message)
}
- constructor(code: Int, cause: Throwable, message: String, vararg args: Any?) :
- super(String.format(message, *args), cause) {
- this.code = code
+ override fun addErrorPayloadMessage(message: String): BluePrintProcessorException {
+ return this.updateErrorPayloadMessage(message)
+ }
+
+ override fun addSubError(errorMessage: ErrorMessage): BluePrintProcessorException {
+ return this.updateSubError(errorMessage)
}
}
@@ -55,3 +75,65 @@ class BluePrintRetryException : RuntimeException {
constructor(cause: Throwable) : super(cause)
constructor(cause: Throwable, message: String, vararg args: Any?) : super(format(message, *args), cause)
}
+
+/** Extension Functions */
+
+fun processorException(message: String): BluePrintProcessorException {
+ return BluePrintProcessorException(message)
+}
+
+fun processorException(code: Int, message: String): BluePrintProcessorException {
+ return processorException(message).code(code)
+}
+
+fun httpProcessorException(type: String, message: String): BluePrintProcessorException {
+ return processorException(message).http(type)
+}
+
+fun grpcProcessorException(type: String, message: String): BluePrintProcessorException {
+ return processorException(message).grpc(type)
+}
+
+fun httpProcessorException(type: String, domain: String, message: String): BluePrintProcessorException {
+ val bluePrintProcessorException = processorException(message).http(type)
+ return bluePrintProcessorException.addDomainAndErrorMessage(domain, message)
+}
+
+fun grpcProcessorException(type: String, domain: String, message: String): BluePrintProcessorException {
+ val bluePrintProcessorException = processorException(message).grpc(type)
+ return bluePrintProcessorException.addDomainAndErrorMessage(domain, message)
+}
+
+fun httpProcessorException(type: String, domain: String, message: String, cause: Throwable):
+ BluePrintProcessorException {
+ val bluePrintProcessorException = processorException(message).http(type)
+ return bluePrintProcessorException.addDomainAndErrorMessage(domain, message, cause)
+}
+
+fun grpcProcessorException(type: String, domain: String, message: String, cause: Throwable):
+ BluePrintProcessorException {
+ val bluePrintProcessorException = processorException(message).grpc(type)
+ return bluePrintProcessorException.addDomainAndErrorMessage(domain, message, cause)
+}
+
+fun BluePrintProcessorException.updateErrorMessage(domain: String, message: String, cause: Throwable):
+ BluePrintProcessorException {
+ return this.addDomainAndErrorMessage(domain, message, cause).domain(domain)
+ .addErrorPayloadMessage(message)
+ .payloadMessage(message)
+}
+
+fun BluePrintProcessorException.updateErrorMessage(domain: String, message: String): BluePrintProcessorException {
+ return this.addDomainAndErrorMessage(domain, message).domain(domain)
+ .addErrorPayloadMessage(message)
+ .payloadMessage(message)
+}
+
+private fun BluePrintProcessorException.addDomainAndErrorMessage(
+ domain: String,
+ message: String,
+ cause: Throwable = Throwable()
+): BluePrintProcessorException {
+ return this.addSubError(ErrorMessage(domain, message, cause.message
+ ?: "")).domain(domain)
+}
diff --git a/ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/interfaces/BluePrintScriptsService.kt b/ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/interfaces/BluePrintScriptsService.kt
index aa61b0c4d..0f7cb79f2 100644
--- a/ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/interfaces/BluePrintScriptsService.kt
+++ b/ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/interfaces/BluePrintScriptsService.kt
@@ -36,4 +36,6 @@ interface BluePrintScriptsService {
suspend fun <T> scriptInstance(cacheKey: String, scriptClassName: String): T
suspend fun <T> scriptInstance(scriptClassName: String): T
+
+ suspend fun cleanupInstance(blueprintBasePath: String)
}
diff --git a/ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/scripts/BluePrintCompileService.kt b/ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/scripts/BluePrintCompileService.kt
index a8c630387..a9684a14d 100644
--- a/ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/scripts/BluePrintCompileService.kt
+++ b/ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/scripts/BluePrintCompileService.kt
@@ -25,11 +25,9 @@ import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler
import org.jetbrains.kotlin.config.Services
-import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants
import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintException
import org.onap.ccsdk.cds.controllerblueprints.core.checkFileExists
import org.onap.ccsdk.cds.controllerblueprints.core.logger
-import org.onap.ccsdk.cds.controllerblueprints.core.utils.BluePrintFileUtils
import java.io.File
import java.net.URLClassLoader
import java.util.ArrayList
@@ -58,13 +56,7 @@ open class BluePrintCompileService {
compile(bluePrintSourceCode)
}
- val classLoaderWithDependencies = if (BluePrintConstants.USE_SCRIPT_COMPILE_CACHE) {
- /** Get the class loader with compiled jar from cache */
- BluePrintCompileCache.classLoader(bluePrintSourceCode.cacheKey)
- } else {
- /** Get the class loader with compiled jar from disk */
- BluePrintFileUtils.getURLClassLoaderFromDirectory(bluePrintSourceCode.cacheKey)
- }
+ val classLoaderWithDependencies = BluePrintCompileCache.classLoader(bluePrintSourceCode.cacheKey)
/** Create the instance from the class loader */
return instance(classLoaderWithDependencies, kClassName, args)
@@ -126,9 +118,6 @@ open class BluePrintCompileService {
.single().newInstance(*args.toArray())
} ?: throw BluePrintException("failed to create class($kClassName) instance for constructor argument($args).")
- if (!BluePrintConstants.USE_SCRIPT_COMPILE_CACHE) {
- classLoader.close()
- }
return instance as T
}
}
diff --git a/ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/scripts/BluePrintScriptsServiceImpl.kt b/ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/scripts/BluePrintScriptsServiceImpl.kt
index f3eb1a2b9..fa8ca2719 100644
--- a/ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/scripts/BluePrintScriptsServiceImpl.kt
+++ b/ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/scripts/BluePrintScriptsServiceImpl.kt
@@ -79,4 +79,11 @@ open class BluePrintScriptsServiceImpl : BluePrintScriptsService {
return Thread.currentThread().contextClassLoader.loadClass(scriptClassName).constructors
.single().newInstance(*args.toArray()) as T
}
+
+ override suspend fun cleanupInstance(blueprintBasePath: String) {
+ if (!BluePrintConstants.USE_SCRIPT_COMPILE_CACHE) {
+ log.info("Invalidating compile cache for blueprint ($blueprintBasePath)")
+ BluePrintCompileCache.cleanClassLoader(blueprintBasePath)
+ }
+ }
}
diff --git a/ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/service/BluePrintTemplateService.kt b/ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/service/BluePrintTemplateService.kt
index db733bda1..51a6e10ee 100644
--- a/ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/service/BluePrintTemplateService.kt
+++ b/ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/service/BluePrintTemplateService.kt
@@ -40,7 +40,7 @@ class BluePrintTemplateService(private val bluePrintLoadConfiguration: BluePrint
val template = bluePrintRuntimeService.resolveNodeTemplateArtifact(nodeTemplateName, artifactName)
return when (templateType) {
- BluePrintConstants.ARTIFACT_JINJA_TYPE_NAME -> {
+ BluePrintConstants.MODEL_TYPE_ARTIFACT_TEMPLATE_JINJA -> {
BluePrintJinjaTemplateService.generateContent(
template,
jsonData,
@@ -51,13 +51,13 @@ class BluePrintTemplateService(private val bluePrintLoadConfiguration: BluePrint
bluePrintRuntimeService.bluePrintContext().version()
)
}
- BluePrintConstants.ARTIFACT_VELOCITY_TYPE_NAME -> {
+ BluePrintConstants.MODEL_TYPE_ARTIFACT_TEMPLATE_VELOCITY -> {
BluePrintVelocityTemplateService.generateContent(template, jsonData, ignoreJsonNull, additionalContext)
}
else -> {
throw BluePrintProcessorException(
- "Unknown Artifact type, expecting ${BluePrintConstants.ARTIFACT_JINJA_TYPE_NAME}" +
- "or ${BluePrintConstants.ARTIFACT_VELOCITY_TYPE_NAME}"
+ "Unknown Artifact type, expecting ${BluePrintConstants.MODEL_TYPE_ARTIFACT_TEMPLATE_JINJA}" +
+ "or ${BluePrintConstants.MODEL_TYPE_ARTIFACT_TEMPLATE_VELOCITY}"
)
}
}
diff --git a/ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/utils/BluePrintArchiveUtils.kt b/ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/utils/BluePrintArchiveUtils.kt
index 9ccf856b5..595dbce6b 100755
--- a/ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/utils/BluePrintArchiveUtils.kt
+++ b/ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/utils/BluePrintArchiveUtils.kt
@@ -22,22 +22,39 @@ import com.google.common.base.Predicates
import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException
import org.slf4j.LoggerFactory
import java.io.BufferedInputStream
+import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream
+import java.io.Closeable
import java.io.File
import java.io.FileOutputStream
+import java.io.InputStream
+import java.io.InputStreamReader
import java.io.IOException
import java.io.OutputStream
-import java.nio.charset.Charset
import java.nio.file.FileVisitResult
import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.SimpleFileVisitor
import java.nio.file.attribute.BasicFileAttributes
import java.util.function.Predicate
+import org.apache.commons.compress.archivers.ArchiveEntry
+import org.apache.commons.compress.archivers.ArchiveInputStream
+import org.apache.commons.compress.archivers.ArchiveOutputStream
+import org.apache.commons.compress.archivers.tar.TarArchiveEntry
+import org.apache.commons.compress.archivers.tar.TarArchiveInputStream
+import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream
+import org.apache.commons.compress.archivers.zip.ZipArchiveEntry
+import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream
+import org.apache.commons.compress.archivers.zip.ZipFile
+import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream
+import org.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream
+import java.util.Enumeration
import java.util.zip.Deflater
-import java.util.zip.ZipEntry
-import java.util.zip.ZipFile
-import java.util.zip.ZipOutputStream
+
+enum class ArchiveType {
+ TarGz,
+ Zip
+}
class BluePrintArchiveUtils {
@@ -51,7 +68,7 @@ class BluePrintArchiveUtils {
* @param destination the output filename
* @return True if OK
*/
- fun compress(source: File, destination: File): Boolean {
+ fun compress(source: File, destination: File, archiveType: ArchiveType = ArchiveType.Zip): Boolean {
try {
if (!destination.parentFile.exists()) {
destination.parentFile.mkdirs()
@@ -59,7 +76,7 @@ class BluePrintArchiveUtils {
destination.createNewFile()
val ignoreZipFiles = Predicate<Path> { path -> !path.endsWith(".zip") && !path.endsWith(".ZIP") }
FileOutputStream(destination).use { out ->
- compressFolder(source.toPath(), out, pathFilter = ignoreZipFiles)
+ compressFolder(source.toPath(), out, archiveType, pathFilter = ignoreZipFiles)
}
} catch (e: Exception) {
log.error("Fail to compress folder($source) to path(${destination.path})", e)
@@ -71,8 +88,12 @@ class BluePrintArchiveUtils {
/**
* In-memory compress an entire folder.
*/
- fun compressToBytes(baseDir: Path, compressionLevel: Int = Deflater.NO_COMPRESSION): ByteArray {
- return compressFolder(baseDir, ByteArrayOutputStream(), compressionLevel = compressionLevel)
+ fun compressToBytes(
+ baseDir: Path,
+ archiveType: ArchiveType = ArchiveType.Zip,
+ compressionLevel: Int = Deflater.NO_COMPRESSION
+ ): ByteArray {
+ return compressFolder(baseDir, ByteArrayOutputStream(), archiveType, compressionLevel = compressionLevel)
.toByteArray()
}
@@ -89,38 +110,51 @@ class BluePrintArchiveUtils {
private fun <T> compressFolder(
baseDir: Path,
output: T,
+ archiveType: ArchiveType,
pathFilter: Predicate<Path> = Predicates.alwaysTrue(),
compressionLevel: Int = Deflater.DEFAULT_COMPRESSION,
fixedModificationTime: Long? = null
): T
where T : OutputStream {
- ZipOutputStream(output)
- .apply { setLevel(compressionLevel) }
- .use { zos ->
+ val stream: ArchiveOutputStream = if (archiveType == ArchiveType.Zip)
+ ZipArchiveOutputStream(output).apply { setLevel(compressionLevel) }
+ else
+ TarArchiveOutputStream(GzipCompressorOutputStream(output))
+ stream
+ .use { aos ->
Files.walkFileTree(baseDir, object : SimpleFileVisitor<Path>() {
@Throws(IOException::class)
override fun visitFile(file: Path, attrs: BasicFileAttributes): FileVisitResult {
if (pathFilter.test(file)) {
- val zipEntry = ZipEntry(baseDir.relativize(file).toString())
- fixedModificationTime?.let {
- zipEntry.time = it
+ var archiveEntry: ArchiveEntry = aos.createArchiveEntry(file.toFile(),
+ baseDir.relativize(file).toString())
+ if (archiveType == ArchiveType.Zip) {
+ val entry = archiveEntry as ZipArchiveEntry
+ fixedModificationTime?.let {
+ entry.time = it
+ }
+ entry.time = 0
}
- zipEntry.time = 0
- zos.putNextEntry(zipEntry)
- Files.copy(file, zos)
- zos.closeEntry()
+ aos.putArchiveEntry(archiveEntry)
+ Files.copy(file, aos)
+ aos.closeArchiveEntry()
}
return FileVisitResult.CONTINUE
}
@Throws(IOException::class)
override fun preVisitDirectory(dir: Path, attrs: BasicFileAttributes): FileVisitResult {
- val zipEntry = ZipEntry(baseDir.relativize(dir).toString() + "/")
- fixedModificationTime?.let {
- zipEntry.time = it
- }
- zos.putNextEntry(zipEntry)
- zos.closeEntry()
+ var archiveEntry: ArchiveEntry?
+ if (archiveType == ArchiveType.Zip) {
+ val entry = ZipArchiveEntry(baseDir.relativize(dir).toString() + "/")
+ fixedModificationTime?.let {
+ entry.time = it
+ }
+ archiveEntry = entry
+ } else
+ archiveEntry = TarArchiveEntry(baseDir.relativize(dir).toString() + "/")
+ aos.putArchiveEntry(archiveEntry)
+ aos.closeArchiveEntry()
return FileVisitResult.CONTINUE
}
})
@@ -128,31 +162,111 @@ class BluePrintArchiveUtils {
return output
}
- fun deCompress(zipFile: File, targetPath: String): File {
- val zip = ZipFile(zipFile, Charset.defaultCharset())
- val enumeration = zip.entries()
- while (enumeration.hasMoreElements()) {
- val entry = enumeration.nextElement()
- val destFilePath = File(targetPath, entry.name)
- destFilePath.parentFile.mkdirs()
+ private fun getDefaultEncoding(): String? {
+ val bytes = byteArrayOf('D'.toByte())
+ val inputStream: InputStream = ByteArrayInputStream(bytes)
+ val reader = InputStreamReader(inputStream)
+ return reader.encoding
+ }
- if (entry.isDirectory)
- continue
+ fun deCompress(archiveFile: File, targetPath: String, archiveType: ArchiveType = ArchiveType.Zip): File {
+ var enumeration: ArchiveEnumerator? = null
+ if (archiveType == ArchiveType.Zip) {
+ val zipArchive = ZipFile(archiveFile, getDefaultEncoding())
+ enumeration = ArchiveEnumerator(zipArchive)
+ } else { // Tar Gz
+ var tarGzArchiveIs: InputStream = BufferedInputStream(archiveFile.inputStream())
+ tarGzArchiveIs = GzipCompressorInputStream(tarGzArchiveIs)
+ val tarGzArchive: ArchiveInputStream = TarArchiveInputStream(tarGzArchiveIs)
+ enumeration = ArchiveEnumerator(tarGzArchive)
+ }
+
+ enumeration.use {
+ while (enumeration!!.hasMoreElements()) {
+ val entry: ArchiveEntry? = enumeration.nextElement()
+ val destFilePath = File(targetPath, entry!!.name)
+ destFilePath.parentFile.mkdirs()
- val bufferedIs = BufferedInputStream(zip.getInputStream(entry))
- bufferedIs.use {
+ if (entry!!.isDirectory)
+ continue
+
+ val bufferedIs = BufferedInputStream(enumeration.getInputStream(entry))
destFilePath.outputStream().buffered(1024).use { bos ->
bufferedIs.copyTo(bos)
}
+
+ if (!enumeration.getHasSharedEntryInputStream())
+ bufferedIs.close()
}
}
val destinationDir = File(targetPath)
check(destinationDir.isDirectory && destinationDir.exists()) {
- throw BluePrintProcessorException("failed to decompress blueprint(${zipFile.absolutePath}) to ($targetPath) ")
+ throw BluePrintProcessorException("failed to decompress blueprint(${archiveFile.absolutePath}) to ($targetPath) ")
}
return destinationDir
}
}
+
+ class ArchiveEnumerator : Enumeration<ArchiveEntry>, Closeable {
+ private val zipArchive: ZipFile?
+ private val zipEnumeration: Enumeration<ZipArchiveEntry>?
+ private val archiveStream: ArchiveInputStream?
+ private var nextEntry: ArchiveEntry? = null
+ private val hasSharedEntryInputStream: Boolean
+
+ constructor(zipFile: ZipFile) {
+ zipArchive = zipFile
+ zipEnumeration = zipFile.entries
+ archiveStream = null
+ hasSharedEntryInputStream = false
+ }
+
+ constructor(archiveStream: ArchiveInputStream) {
+ this.archiveStream = archiveStream
+ zipArchive = null
+ zipEnumeration = null
+ hasSharedEntryInputStream = true
+ }
+
+ fun getHasSharedEntryInputStream(): Boolean {
+ return hasSharedEntryInputStream
+ }
+
+ fun getInputStream(entry: ArchiveEntry): InputStream? {
+ return if (zipArchive != null)
+ zipArchive?.getInputStream(entry as ZipArchiveEntry?)
+ else
+ archiveStream
+ }
+
+ override fun hasMoreElements(): Boolean {
+ if (zipEnumeration != null)
+ return zipEnumeration?.hasMoreElements()
+ else if (archiveStream != null) {
+ nextEntry = archiveStream.nextEntry
+ if (nextEntry != null && !archiveStream.canReadEntryData(nextEntry))
+ return hasMoreElements()
+ return nextEntry != null
+ }
+ return false
+ }
+
+ override fun nextElement(): ArchiveEntry? {
+ if (zipEnumeration != null)
+ nextEntry = zipEnumeration.nextElement()
+ else if (archiveStream != null) {
+ if (nextEntry == null)
+ nextEntry = archiveStream.nextEntry
+ }
+ return nextEntry
+ }
+
+ override fun close() {
+ if (zipArchive != null)
+ zipArchive.close()
+ else archiveStream?.close()
+ }
+ }
}
diff --git a/ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/utils/JacksonUtils.kt b/ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/utils/JacksonUtils.kt
index 3db1f84cd..573fc17d2 100644
--- a/ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/utils/JacksonUtils.kt
+++ b/ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/utils/JacksonUtils.kt
@@ -133,9 +133,13 @@ class JacksonUtils {
return getJson(wrapperMap, pretty)
}
- fun getJson(any: kotlin.Any, pretty: Boolean = false): String {
+ fun getJson(any: kotlin.Any, pretty: Boolean = false, includeNull: Boolean = false): String {
val objectMapper = jacksonObjectMapper()
- objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL)
+ if (includeNull) {
+ objectMapper.setSerializationInclusion(JsonInclude.Include.ALWAYS)
+ } else {
+ objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL)
+ }
if (pretty) {
objectMapper.enable(SerializationFeature.INDENT_OUTPUT)
}
diff --git a/ms/blueprintsprocessor/modules/blueprints/blueprint-proto/pom.xml b/ms/blueprintsprocessor/modules/blueprints/blueprint-proto/pom.xml
index b208cbda5..1e90cca76 100644
--- a/ms/blueprintsprocessor/modules/blueprints/blueprint-proto/pom.xml
+++ b/ms/blueprintsprocessor/modules/blueprints/blueprint-proto/pom.xml
@@ -28,6 +28,10 @@
<name>Controller Blueprints Proto</name>
<description>Controller Blueprints Proto</description>
+ <properties>
+ <sonar.skip>true</sonar.skip>
+ </properties>
+
<dependencies>
<dependency>
<groupId>com.github.marcoferrer.krotoplus</groupId>
diff --git a/ms/blueprintsprocessor/modules/blueprints/pom.xml b/ms/blueprintsprocessor/modules/blueprints/pom.xml
index cd6a17e88..527a5bf98 100644
--- a/ms/blueprintsprocessor/modules/blueprints/pom.xml
+++ b/ms/blueprintsprocessor/modules/blueprints/pom.xml
@@ -14,7 +14,6 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
diff --git a/ms/blueprintsprocessor/modules/blueprints/resource-dict/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/resource/dict/ResourceDefinition.kt b/ms/blueprintsprocessor/modules/blueprints/resource-dict/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/resource/dict/ResourceDefinition.kt
index 4ed98ddd0..77025c5a4 100644
--- a/ms/blueprintsprocessor/modules/blueprints/resource-dict/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/resource/dict/ResourceDefinition.kt
+++ b/ms/blueprintsprocessor/modules/blueprints/resource-dict/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/resource/dict/ResourceDefinition.kt
@@ -19,6 +19,7 @@ package org.onap.ccsdk.cds.controllerblueprints.resource.dict
import com.fasterxml.jackson.annotation.JsonFormat
import com.fasterxml.jackson.annotation.JsonProperty
+import com.fasterxml.jackson.databind.JsonNode
import org.onap.ccsdk.cds.controllerblueprints.core.data.NodeTemplate
import org.onap.ccsdk.cds.controllerblueprints.core.data.PropertyDefinition
import java.io.Serializable
@@ -87,6 +88,9 @@ open class ResourceAssignment {
@JsonProperty("updated-by")
var updatedBy: String? = null
+ /** input & output key-mapping with their resolved values **/
+ var keyIdentifiers: MutableList<KeyIdentifier> = mutableListOf()
+
override fun toString(): String {
return """
[
@@ -101,6 +105,33 @@ open class ResourceAssignment {
}
}
+data class KeyIdentifier(val name: String, val value: JsonNode)
+data class DictionaryMetadataEntry(val name: String, val value: String)
+/**
+ * Data class for exposing summary of resource resolution
+ */
+data class ResolutionSummary(
+ val name: String,
+ val value: JsonNode?,
+ val required: Boolean?,
+ val type: String?,
+ @JsonProperty("key-identifiers")
+ val keyIdentifiers: MutableList<KeyIdentifier>,
+ @JsonProperty("dictionary-description")
+ val dictionaryDescription: String?,
+ @JsonProperty("dictionary-metadata")
+ val dictionaryMetadata: MutableList<DictionaryMetadataEntry>,
+ @JsonProperty("dictionary-name")
+ val dictionaryName: String?,
+ @JsonProperty("dictionary-source")
+ val dictionarySource: String?,
+ @JsonProperty("request-payload")
+ val requestPayload: JsonNode?,
+ @JsonProperty("status")
+ val status: String?,
+ @JsonProperty("message")
+ val message: String?
+)
/**
* Interface for Source Definitions (ex Input Source,
* Default Source, Database Source, Rest Sources, etc)
diff --git a/ms/blueprintsprocessor/modules/commons/nats-lib/pom.xml b/ms/blueprintsprocessor/modules/commons/nats-lib/pom.xml
index f4e7f4d98..f28a7132e 100644
--- a/ms/blueprintsprocessor/modules/commons/nats-lib/pom.xml
+++ b/ms/blueprintsprocessor/modules/commons/nats-lib/pom.xml
@@ -14,7 +14,6 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
diff --git a/ms/blueprintsprocessor/modules/commons/processor-core/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/cluster/HazlecastClusterService.kt b/ms/blueprintsprocessor/modules/commons/processor-core/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/cluster/HazlecastClusterService.kt
index 6be3334bb..a58c077fa 100644
--- a/ms/blueprintsprocessor/modules/commons/processor-core/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/cluster/HazlecastClusterService.kt
+++ b/ms/blueprintsprocessor/modules/commons/processor-core/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/cluster/HazlecastClusterService.kt
@@ -243,8 +243,11 @@ open class ClusterLockImpl(private val hazelcast: HazelcastInstance, private val
}
override suspend fun unLock() {
- distributedLock.unlock()
- log.trace("Cluster unlock(${name()}) successfully..")
+ // Added condition to avoid failures like - "Current thread is not owner of the lock!"
+ if (distributedLock.isLockedByCurrentThread) {
+ distributedLock.unlock()
+ log.trace("Cluster unlock(${name()}) successfully..")
+ }
}
override fun isLocked(): Boolean {
diff --git a/ms/blueprintsprocessor/modules/commons/processor-core/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/cluster/HazlecastClusterServiceTest.kt b/ms/blueprintsprocessor/modules/commons/processor-core/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/cluster/HazlecastClusterServiceTest.kt
index b298eacae..80cf41558 100644
--- a/ms/blueprintsprocessor/modules/commons/processor-core/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/cluster/HazlecastClusterServiceTest.kt
+++ b/ms/blueprintsprocessor/modules/commons/processor-core/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/cluster/HazlecastClusterServiceTest.kt
@@ -113,7 +113,7 @@ class HazlecastClusterServiceTest {
} else {
ClusterInfo(
id = "test-cluster", nodeId = nodeId, joinAsClient = false,
- configFile = "./src/test/resources/hazelcast/hazelcast-$port.yaml",
+ configFile = "./src/test/resources/hazelcast/hazelcast-cluster.yaml",
properties = properties
)
}
@@ -162,7 +162,7 @@ class HazlecastClusterServiceTest {
executeLock(bluePrintClusterServices[0], "first", lockName)
}
val deferred2 = async {
- executeLock(bluePrintClusterServices[0], "second", lockName)
+ executeLock(bluePrintClusterServices[1], "second", lockName)
}
val deferred3 = async {
executeLock(bluePrintClusterServices[2], "third", lockName)
diff --git a/ms/blueprintsprocessor/modules/commons/processor-core/src/test/resources/hazelcast/hazelcast-5679.yaml b/ms/blueprintsprocessor/modules/commons/processor-core/src/test/resources/hazelcast/hazelcast-5679.yaml
deleted file mode 100644
index e7ac273ed..000000000
--- a/ms/blueprintsprocessor/modules/commons/processor-core/src/test/resources/hazelcast/hazelcast-5679.yaml
+++ /dev/null
@@ -1,21 +0,0 @@
-hazelcast:
- cluster-name: ${CLUSTER_ID}
- instance-name: node-5679
- lite-member:
- enabled: false
- cp-subsystem:
- cp-member-count: 3
- group-size: 3
- session-time-to-live-seconds: 60
- session-heartbeat-interval-seconds: 5
- missing-cp-member-auto-removal-seconds: 120
-# network:
-# join:
-# multicast:
-# enabled: false
-# kubernetes:
-# enabled: true
-# namespace: MY-KUBERNETES-NAMESPACE
-# service-name: MY-SERVICE-NAME
-# service-label-name: MY-SERVICE-LABEL-NAME
-# service-label-value: MY-SERVICE-LABEL-VALUE \ No newline at end of file
diff --git a/ms/blueprintsprocessor/modules/commons/processor-core/src/test/resources/hazelcast/hazelcast-5680.yaml b/ms/blueprintsprocessor/modules/commons/processor-core/src/test/resources/hazelcast/hazelcast-5680.yaml
deleted file mode 100644
index cb493d169..000000000
--- a/ms/blueprintsprocessor/modules/commons/processor-core/src/test/resources/hazelcast/hazelcast-5680.yaml
+++ /dev/null
@@ -1,21 +0,0 @@
-hazelcast:
- cluster-name: ${CLUSTER_ID}
- instance-name: node-5680
- lite-member:
- enabled: false
- cp-subsystem:
- cp-member-count: 3
- group-size: 3
- session-time-to-live-seconds: 60
- session-heartbeat-interval-seconds: 5
- missing-cp-member-auto-removal-seconds: 120
-# network:
-# join:
-# multicast:
-# enabled: false
-# kubernetes:
-# enabled: true
-# namespace: MY-KUBERNETES-NAMESPACE
-# service-name: MY-SERVICE-NAME
-# service-label-name: MY-SERVICE-LABEL-NAME
-# service-label-value: MY-SERVICE-LABEL-VALUE \ No newline at end of file
diff --git a/ms/blueprintsprocessor/modules/commons/processor-core/src/test/resources/hazelcast/hazelcast-5681.yaml b/ms/blueprintsprocessor/modules/commons/processor-core/src/test/resources/hazelcast/hazelcast-5681.yaml
deleted file mode 100644
index e60b0c506..000000000
--- a/ms/blueprintsprocessor/modules/commons/processor-core/src/test/resources/hazelcast/hazelcast-5681.yaml
+++ /dev/null
@@ -1,21 +0,0 @@
-hazelcast:
- cluster-name: ${CLUSTER_ID}
- instance-name: node-5681
- lite-member:
- enabled: false
- cp-subsystem:
- cp-member-count: 3
- group-size: 3
- session-time-to-live-seconds: 60
- session-heartbeat-interval-seconds: 5
- missing-cp-member-auto-removal-seconds: 120
-# network:
-# join:
-# multicast:
-# enabled: false
-# kubernetes:
-# enabled: true
-# namespace: MY-KUBERNETES-NAMESPACE
-# service-name: MY-SERVICE-NAME
-# service-label-name: MY-SERVICE-LABEL-NAME
-# service-label-value: MY-SERVICE-LABEL-VALUE \ No newline at end of file
diff --git a/ms/blueprintsprocessor/modules/commons/processor-core/src/test/resources/hazelcast/hazelcast-5682.yaml b/ms/blueprintsprocessor/modules/commons/processor-core/src/test/resources/hazelcast/hazelcast-5682.yaml
index 3cb10a08b..859ea3328 100644
--- a/ms/blueprintsprocessor/modules/commons/processor-core/src/test/resources/hazelcast/hazelcast-5682.yaml
+++ b/ms/blueprintsprocessor/modules/commons/processor-core/src/test/resources/hazelcast/hazelcast-5682.yaml
@@ -9,10 +9,11 @@ hazelcast:
session-time-to-live-seconds: 60
session-heartbeat-interval-seconds: 5
missing-cp-member-auto-removal-seconds: 120
-# network:
-# join:
-# multicast:
-# enabled: false
+ network:
+ join:
+ multicast:
+ enabled: true
+ multicast-group: 224.0.0.1
# kubernetes:
# enabled: true
# namespace: MY-KUBERNETES-NAMESPACE
diff --git a/ms/blueprintsprocessor/modules/commons/processor-core/src/test/resources/hazelcast/hazelcast-cluster.yaml b/ms/blueprintsprocessor/modules/commons/processor-core/src/test/resources/hazelcast/hazelcast-cluster.yaml
new file mode 100644
index 000000000..de6047a90
--- /dev/null
+++ b/ms/blueprintsprocessor/modules/commons/processor-core/src/test/resources/hazelcast/hazelcast-cluster.yaml
@@ -0,0 +1,23 @@
+hazelcast:
+ lite-member:
+ enabled: false
+ cp-subsystem:
+ cp-member-count: 3
+ group-size: 3
+ session-time-to-live-seconds: 60
+ session-heartbeat-interval-seconds: 5
+ missing-cp-member-auto-removal-seconds: 120
+ network:
+ join:
+ multicast:
+ enabled: true
+ # Specify 224.0.0.1 instead of default 224.2.2.3 since there's some issue
+ # on macOs with docker installed and multicast address different than 224.0.0.1
+ # https://stackoverflow.com/questions/46341715/hazelcast-multicast-does-not-work-because-of-vboxnet-which-is-used-by-docker-mac
+ multicast-group: 224.0.0.1
+ # kubernetes:
+ # enabled: true
+ # namespace: MY-KUBERNETES-NAMESPACE
+ # service-name: MY-SERVICE-NAME
+ # service-label-name: MY-SERVICE-LABEL-NAME
+ # service-label-value: MY-SERVICE-LABEL-VALUE
diff --git a/ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/service/BasicAuthRestClientService.kt b/ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/service/BasicAuthRestClientService.kt
index 540b3d9ad..bfc0a5cd4 100644
--- a/ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/service/BasicAuthRestClientService.kt
+++ b/ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/service/BasicAuthRestClientService.kt
@@ -20,6 +20,7 @@ import org.apache.http.message.BasicHeader
import org.onap.ccsdk.cds.blueprintsprocessor.rest.BasicAuthRestClientProperties
import org.springframework.http.HttpHeaders
import org.springframework.http.MediaType
+import java.net.URI
import java.nio.charset.Charset
import java.util.Base64
@@ -43,7 +44,8 @@ class BasicAuthRestClientService(
}
override fun host(uri: String): String {
- return restClientProperties.url + uri
+ val uri: URI = URI.create(restClientProperties.url + uri)
+ return uri.resolve(uri).toString()
}
override fun convertToBasicHeaders(headers: Map<String, String>):
diff --git a/ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/BlueprintModelController.kt b/ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/BlueprintModelController.kt
index bb824ce4d..1f01d1ce3 100644
--- a/ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/BlueprintModelController.kt
+++ b/ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/BlueprintModelController.kt
@@ -26,6 +26,7 @@ import org.onap.ccsdk.cds.blueprintsprocessor.designer.api.handler.BluePrintMode
import org.onap.ccsdk.cds.blueprintsprocessor.designer.api.utils.BlueprintSortByOption
import org.onap.ccsdk.cds.blueprintsprocessor.rest.service.mdcWebCoroutineScope
import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintException
+import org.onap.ccsdk.cds.controllerblueprints.core.asJsonString
import org.springframework.core.io.Resource
import org.springframework.data.domain.Page
import org.springframework.data.domain.PageRequest
@@ -208,4 +209,42 @@ open class BlueprintModelController(private val bluePrintModelHandler: BluePrint
) = mdcWebCoroutineScope {
bluePrintModelHandler.deleteBlueprintModel(name, version)
}
+
+ @PostMapping(
+ path = arrayOf("/workflow-spec"), produces = arrayOf(
+ MediaType
+ .APPLICATION_JSON_VALUE
+ ),
+ consumes = arrayOf(MediaType.APPLICATION_JSON_VALUE)
+ )
+ @ResponseBody
+ @Throws(BluePrintException::class)
+ @PreAuthorize("hasRole('USER')")
+ suspend fun workflowSpec(@RequestBody workFlowSpecReq: WorkFlowSpecRequest):
+ ResponseEntity<String> = mdcWebCoroutineScope {
+ var json = bluePrintModelHandler.prepareWorkFlowSpec(workFlowSpecReq)
+ .asJsonString()
+ ResponseEntity(json, HttpStatus.OK)
+ }
+
+ @GetMapping(
+ path = arrayOf(
+ "/workflows/blueprint-name/{name}/version/{version" +
+ "}"
+ ),
+ produces = arrayOf(MediaType.APPLICATION_JSON_VALUE)
+ )
+ @ResponseBody
+ @Throws(BluePrintException::class)
+ @PreAuthorize("hasRole('USER')")
+ suspend fun getWorkflowList(
+ @ApiParam(value = "Name of the CBA.", required = true)
+ @PathVariable(value = "name") name: String,
+ @ApiParam(value = "Version of the CBA.", required = true)
+ @PathVariable(value = "version") version: String
+ ): ResponseEntity<String> = mdcWebCoroutineScope {
+ var json = bluePrintModelHandler.getWorkflowNames(name, version)
+ .asJsonString()
+ ResponseEntity(json, HttpStatus.OK)
+ }
}
diff --git a/ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/DesignerApiData.kt b/ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/DesignerApiData.kt
index d0cb67315..369844445 100644
--- a/ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/DesignerApiData.kt
+++ b/ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/DesignerApiData.kt
@@ -22,6 +22,11 @@ import com.fasterxml.jackson.annotation.JsonInclude
import com.fasterxml.jackson.annotation.JsonTypeInfo
import com.fasterxml.jackson.annotation.JsonTypeName
import org.onap.ccsdk.cds.blueprintsprocessor.designer.api.domain.ResourceDictionary
+import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants.DATA_TYPE_JSON
+import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants.DEFAULT_VERSION_NUMBER
+import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants.TOSCA_SPEC
+import org.onap.ccsdk.cds.controllerblueprints.core.data.DataType
+import org.onap.ccsdk.cds.controllerblueprints.core.data.PropertyDefinition
import org.onap.ccsdk.cds.controllerblueprints.resource.dict.ResourceAssignment
import java.io.Serializable
import java.util.Date
@@ -32,6 +37,33 @@ class BootstrapRequest {
var loadCBA: Boolean = false
}
+class WorkFlowsResponse {
+ lateinit var blueprintName: String
+ var version: String = DEFAULT_VERSION_NUMBER
+ var workflows: MutableSet<String> = mutableSetOf()
+}
+
+class WorkFlowSpecRequest {
+ lateinit var blueprintName: String
+ var version: String = DEFAULT_VERSION_NUMBER
+ var returnContent: String = DATA_TYPE_JSON
+ lateinit var workflowName: String
+ var specType: String = TOSCA_SPEC
+}
+
+class WorkFlowSpecResponse {
+ lateinit var blueprintName: String
+ var version: String = DEFAULT_VERSION_NUMBER
+ lateinit var workFlowData: WorkFlowData
+ var dataTypes: MutableMap<String, DataType>? = mutableMapOf()
+}
+
+class WorkFlowData {
+ lateinit var workFlowName: String
+ var inputs: MutableMap<String, PropertyDefinition>? = null
+ var outputs: MutableMap<String, PropertyDefinition>? = null
+}
+
/**
* ArtifactRequest.java Purpose: Provide Configuration Generator ArtifactRequest Model
*
diff --git a/ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/ErrorHandling.kt b/ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/ErrorHandling.kt
new file mode 100644
index 000000000..ae91246fe
--- /dev/null
+++ b/ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/ErrorHandling.kt
@@ -0,0 +1,40 @@
+/*
+ * Copyright © 2018-2019 AT&T Intellectual Property.
+ *
+ * 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.
+ */
+
+package org.onap.ccsdk.cds.blueprintsprocessor.designer.api
+
+object DesignerApiDomains {
+ // Designer Api Domains Constants
+ const val DESIGNER_API = "org.onap.ccsdk.cds.blueprintsprocessor.designer.api"
+ const val DESIGNER_API_ENHANCER = "org.onap.ccsdk.cds.blueprintsprocessor.designer.api.enhancer"
+ const val DESIGNER_API_HANDLER = "org.onap.ccsdk.cds.blueprintsprocessor.designer.api.handler"
+ const val DESIGNER_API_LOAD = "org.onap.ccsdk.cds.blueprintsprocessor.designer.api.load"
+ const val DESIGNER_API_SERVICE = "org.onap.ccsdk.cds.blueprintsprocessor.designer.api.service"
+}
+
+object DesignerApiHttpErrorCodes {
+ init {
+ // Register HttpErrorCodes
+ // HttpErrorCodes.register("", 200)
+ }
+}
+
+object DesignerGrpcErrorCodes {
+ init {
+ // Register GrpcErrorCodes
+ // GrpcErrorCodes.register("", 3)
+ }
+}
diff --git a/ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/handler/BluePrintModelHandler.kt b/ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/handler/BluePrintModelHandler.kt
index 274650ae4..e9839328b 100644
--- a/ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/handler/BluePrintModelHandler.kt
+++ b/ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/handler/BluePrintModelHandler.kt
@@ -25,10 +25,15 @@ import org.onap.ccsdk.cds.blueprintsprocessor.db.primary.repository.BlueprintMod
import org.onap.ccsdk.cds.blueprintsprocessor.db.primary.repository.BlueprintModelRepository
import org.onap.ccsdk.cds.blueprintsprocessor.db.primary.repository.BlueprintModelSearchRepository
import org.onap.ccsdk.cds.blueprintsprocessor.designer.api.BootstrapRequest
+import org.onap.ccsdk.cds.blueprintsprocessor.designer.api.WorkFlowData
+import org.onap.ccsdk.cds.blueprintsprocessor.designer.api.WorkFlowSpecRequest
+import org.onap.ccsdk.cds.blueprintsprocessor.designer.api.WorkFlowSpecResponse
+import org.onap.ccsdk.cds.blueprintsprocessor.designer.api.WorkFlowsResponse
import org.onap.ccsdk.cds.blueprintsprocessor.designer.api.load.BluePrintDatabaseLoadService
import org.onap.ccsdk.cds.blueprintsprocessor.designer.api.utils.BluePrintEnhancerUtils
import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintException
import org.onap.ccsdk.cds.controllerblueprints.core.config.BluePrintLoadConfiguration
+import org.onap.ccsdk.cds.controllerblueprints.core.data.DataType
import org.onap.ccsdk.cds.controllerblueprints.core.data.ErrorCode
import org.onap.ccsdk.cds.controllerblueprints.core.deleteNBDir
import org.onap.ccsdk.cds.controllerblueprints.core.interfaces.BluePrintCatalogService
@@ -37,7 +42,9 @@ import org.onap.ccsdk.cds.controllerblueprints.core.logger
import org.onap.ccsdk.cds.controllerblueprints.core.normalizedFile
import org.onap.ccsdk.cds.controllerblueprints.core.normalizedPathName
import org.onap.ccsdk.cds.controllerblueprints.core.scripts.BluePrintCompileCache
+import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintContext
import org.onap.ccsdk.cds.controllerblueprints.core.utils.BluePrintFileUtils
+import org.onap.ccsdk.cds.controllerblueprints.core.utils.BluePrintMetadataUtils
import org.springframework.core.io.ByteArrayResource
import org.springframework.core.io.Resource
import org.springframework.data.domain.Page
@@ -89,6 +96,68 @@ open class BluePrintModelHandler(
}
}
+ @Throws(BluePrintException::class)
+ open suspend fun prepareWorkFlowSpec(req: WorkFlowSpecRequest):
+ WorkFlowSpecResponse {
+ val basePath = blueprintsProcessorCatalogService.getFromDatabase(req
+ .blueprintName, req.version)
+ log.info("blueprint base path $basePath")
+
+ val blueprintContext = BluePrintMetadataUtils.getBluePrintContext(basePath.toString())
+ val workFlow = blueprintContext.workflowByName(req.workflowName)
+
+ val wfRes = WorkFlowSpecResponse()
+ wfRes.blueprintName = req.blueprintName
+ wfRes.version = req.version
+
+ val workFlowData = WorkFlowData()
+ workFlowData.workFlowName = req.workflowName
+ workFlowData.inputs = workFlow.inputs
+ workFlowData.outputs = workFlow.outputs
+
+ for ((k, v) in workFlow.inputs!!) {
+ addDataType(v.type, blueprintContext, wfRes)
+ }
+
+ for ((k, v) in workFlow.outputs!!) {
+ addDataType(v.type, blueprintContext, wfRes)
+ }
+ wfRes.workFlowData = workFlowData
+ return wfRes
+ }
+
+ private fun addDataType(name: String, ctx: BluePrintContext, res: WorkFlowSpecResponse) {
+ var data = ctx.dataTypeByName(name)
+ if (data != null) {
+ res.dataTypes?.put(name, data)
+ addParentDataType(data, ctx, res)
+ }
+ }
+
+ private fun addParentDataType(data: DataType, ctx: BluePrintContext, res: WorkFlowSpecResponse) {
+ for ((k, v) in data.properties!!) {
+ addDataType(v.type, ctx, res)
+ }
+ }
+
+ @Throws(BluePrintException::class)
+ open suspend fun getWorkflowNames(name: String, version: String): WorkFlowsResponse {
+ val basePath = blueprintsProcessorCatalogService.getFromDatabase(
+ name, version)
+ log.info("blueprint base path $basePath")
+
+ var res = WorkFlowsResponse()
+ res.blueprintName = name
+ res.version = version
+
+ val blueprintContext = BluePrintMetadataUtils.getBluePrintContext(
+ basePath.toString())
+ if (blueprintContext.workflows() != null) {
+ res.workflows = blueprintContext.workflows()!!.keys
+ }
+ return res
+ }
+
/**
* This is a getAllBlueprintModel method to retrieve all the BlueprintModel in Database
*
diff --git a/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/ErrorHandling.kt b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/ErrorHandling.kt
new file mode 100644
index 000000000..b37cd0eda
--- /dev/null
+++ b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/ErrorHandling.kt
@@ -0,0 +1,36 @@
+/*
+ * Copyright © 2018-2019 AT&T Intellectual Property.
+ *
+ * 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.
+ */
+
+package org.onap.ccsdk.cds.blueprintsprocessor.resource.api
+
+object ResourceApiDomains {
+ // Resource Api Domains Constants
+ const val RESOURCE_API = "org.onap.ccsdk.cds.blueprintsprocessor.resource.api"
+}
+
+object ResourceApiHttpErrorCodes {
+ init {
+ // Register HttpErrorCodes
+ // HttpErrorCodes.register("", 200)
+ }
+}
+
+object ResourceGrpcErrorCodes {
+ init {
+ // Register GrpcErrorCodes
+ // GrpcErrorCodes.register("", 3)
+ }
+}
diff --git a/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/ResourceController.kt b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/ResourceController.kt
index b49ca68ed..264cd23ff 100644
--- a/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/ResourceController.kt
+++ b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/ResourceController.kt
@@ -103,6 +103,28 @@ open class ResourceController(private var resourceResolutionDBService: ResourceR
}
@RequestMapping(
+ path = [""],
+ method = [RequestMethod.DELETE], produces = [MediaType.APPLICATION_JSON_VALUE]
+ )
+ @ApiOperation(value = "Delete resources using resolution key",
+ notes = "Delete all the resources associated to a resolution-key using blueprint metadata, artifact name and the resolution-key.",
+ produces = MediaType.APPLICATION_JSON_VALUE)
+ @PreAuthorize("hasRole('USER')")
+ fun deleteByBlueprintNameAndBlueprintVersionAndArtifactNameAndResolutionKey(
+ @ApiParam(value = "Name of the CBA.", required = true)
+ @RequestParam(value = "bpName", required = true) bpName: String,
+ @ApiParam(value = "Version of the CBA.", required = true)
+ @RequestParam(value = "bpVersion", required = true) bpVersion: String,
+ @ApiParam(value = "Artifact name for which to retrieve a resolved resource.", required = true)
+ @RequestParam(value = "artifactName", required = false, defaultValue = "") artifactName: String,
+ @ApiParam(value = "Resolution Key associated with the resolution.", required = true)
+ @RequestParam(value = "resolutionKey", required = true) resolutionKey: String
+ ) = runBlocking {
+ ResponseEntity.ok()
+ .body(resourceResolutionDBService.deleteByBlueprintNameAndBlueprintVersionAndArtifactNameAndResolutionKey(bpName, bpVersion, artifactName, resolutionKey))
+ }
+
+ @RequestMapping(
path = ["/resource"],
method = [RequestMethod.GET],
produces = [MediaType.APPLICATION_JSON_VALUE]
diff --git a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/ErrorHandling.kt b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/ErrorHandling.kt
new file mode 100644
index 000000000..b76bc263a
--- /dev/null
+++ b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/ErrorHandling.kt
@@ -0,0 +1,44 @@
+/*
+ * Copyright © 2018-2019 AT&T Intellectual Property.
+ *
+ * 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.
+ */
+
+package org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api
+
+object SelfServiceApiDomains {
+ // SelfServiceApi Domains Constants
+ const val BLUEPRINT_PROCESSOR = "org.onap.ccsdk.cds.blueprintsprocessor"
+ const val SELF_SERVICE_API = "org.onap.ccsdk.cds.blueprintsprocessor.resource.api"
+ const val SELF_SERVICE_API_VALIDATOR = "org.onap.ccsdk.cds.blueprintsprocessor.resource.api.validator"
+ const val NETCONF_EXECUTOR = "org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor"
+ const val RESOURCE_RESOLUTION = "org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution"
+ const val RESTCONF_EXECUTOR = "org.onap.ccsdk.cds.blueprintsprocessor.functions.restconf.executor"
+ const val CLI_EXECUTOR = "org.onap.ccsdk.cds.blueprintsprocessor.functions.cli.executor"
+ const val PYTHON_EXECUTOR = "org.onap.ccsdk.cds.blueprintsprocessor.functions.python.executor"
+ const val SDC_LISTENER = "org.onap.ccsdk.cds.sdclistener"
+}
+
+object SelfServiceApiHttpErrorCodes {
+ init {
+ // Register HttpErrorCodes
+ // HttpErrorCodes.register("", 200)
+ }
+}
+
+object SelfServiceGrpcErrorCodes {
+ init {
+ // Register GrpcErrorCodes
+ // GrpcErrorCodes.register("", 3)
+ }
+}
diff --git a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/ExecutionServiceController.kt b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/ExecutionServiceController.kt
index 8b268d6f8..e5daecede 100644
--- a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/ExecutionServiceController.kt
+++ b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/ExecutionServiceController.kt
@@ -27,7 +27,9 @@ import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceOutp
import org.onap.ccsdk.cds.blueprintsprocessor.rest.service.mdcWebCoroutineScope
import org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api.utils.determineHttpStatusCode
import org.onap.ccsdk.cds.controllerblueprints.core.asJsonPrimitive
+import org.onap.ccsdk.cds.controllerblueprints.core.httpProcessorException
import org.onap.ccsdk.cds.controllerblueprints.core.logger
+import org.onap.ccsdk.cds.error.catalog.core.ErrorCatalogCodes
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.http.MediaType
import org.springframework.http.ResponseEntity
@@ -81,7 +83,9 @@ open class ExecutionServiceController {
): ResponseEntity<ExecutionServiceOutput> = mdcWebCoroutineScope {
if (executionServiceInput.actionIdentifiers.mode == ACTION_MODE_ASYNC) {
- throw IllegalStateException("Can't process async request through the REST endpoint. Use gRPC for async processing.")
+ throw httpProcessorException(ErrorCatalogCodes.GENERIC_FAILURE,
+ SelfServiceApiDomains.BLUEPRINT_PROCESSOR,
+ "Can't process async request through the REST endpoint. Use gRPC for async processing.")
}
ph.register()
val processResult = executionServiceHandler.doProcess(executionServiceInput)
diff --git a/ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/ComponentFunctionScriptingService.kt b/ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/ComponentFunctionScriptingService.kt
index 4c7d5d0ec..34b18091f 100644
--- a/ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/ComponentFunctionScriptingService.kt
+++ b/ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/ComponentFunctionScriptingService.kt
@@ -101,4 +101,10 @@ class ComponentFunctionScriptingService(
}
return scriptComponent
}
+
+ suspend fun cleanupInstance(bluePrintContext: BluePrintContext, scriptType: String) {
+ if (scriptType == BluePrintConstants.SCRIPT_KOTLIN) {
+ BluePrintScriptsServiceImpl().cleanupInstance(bluePrintContext.rootPath)
+ }
+ }
}
diff --git a/ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/ComponentScriptExecutor.kt b/ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/ComponentScriptExecutor.kt
index 09eee6717..2a63297be 100644
--- a/ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/ComponentScriptExecutor.kt
+++ b/ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/ComponentScriptExecutor.kt
@@ -60,6 +60,8 @@ open class ComponentScriptExecutor(private var componentFunctionScriptingService
// Handles both script processing and error handling
scriptComponentFunction.executeScript(executionServiceInput)
+
+ componentFunctionScriptingService.cleanupInstance(bluePrintRuntimeService.bluePrintContext(), scriptType)
}
override suspend fun recoverNB(runtimeException: RuntimeException, executionRequest: ExecutionServiceInput) {
diff --git a/ms/blueprintsprocessor/modules/services/workflow-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/workflow/BlueprintSvcLogicService.kt b/ms/blueprintsprocessor/modules/services/workflow-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/workflow/BlueprintSvcLogicService.kt
index 9cc325d94..4efe9f12d 100644
--- a/ms/blueprintsprocessor/modules/services/workflow-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/workflow/BlueprintSvcLogicService.kt
+++ b/ms/blueprintsprocessor/modules/services/workflow-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/workflow/BlueprintSvcLogicService.kt
@@ -49,6 +49,10 @@ interface BlueprintSvcLogicService : SvcLogicServiceBase {
suspend fun execute(graph: SvcLogicGraph, bluePrintRuntimeService: BluePrintRuntimeService<*>, input: Any): Any
+ override fun execute(module: String, rpc: String, version: String, mode: String, ctx: SvcLogicContext): SvcLogicContext {
+ TODO("not implemented")
+ }
+
@Deprecated("Populate Graph Dynamically from Blueprints, No need to get from Database Store ")
override fun getStore(): SvcLogicStore {
TODO("not implemented")
diff --git a/ms/blueprintsprocessor/parent/pom.xml b/ms/blueprintsprocessor/parent/pom.xml
index 4ee3f3656..ce78c55fa 100755
--- a/ms/blueprintsprocessor/parent/pom.xml
+++ b/ms/blueprintsprocessor/parent/pom.xml
@@ -35,6 +35,7 @@
<sli.version>${ccsdk.sli.core.version}</sli.version>
<!-- Override CDS version from parent to be project.version -->
<ccsdk.cds.version>${project.version}</ccsdk.cds.version>
+ <error.catalog.version>${project.version}</error.catalog.version>
<dmaap.client.version>1.1.5</dmaap.client.version>
<!-- Should be using released artifact as soon as available: -->
<!-- https://github.com/springfox/springfox/milestone/44 -->
@@ -55,14 +56,12 @@
<jslt.version>0.1.8</jslt.version>
<jython.version>2.7.1</jython.version>
<jinja.version>2.5.1</jinja.version>
- <velocity.version>1.7</velocity.version>
<guava.version>27.0.1-jre</guava.version>
- <jsoup.version>1.10.3</jsoup.version>
<json-patch.version>1.9</json-patch.version>
<json-smart.version>2.3</json-smart.version>
<commons-io-version>2.6</commons-io-version>
- <commons-lang3-version>3.2.1</commons-lang3-version>
+ <commons-compress-version>1.20</commons-compress-version>
<commons-collections-version>3.2.2</commons-collections-version>
</properties>
@@ -78,12 +77,6 @@
</dependency>
<dependency>
- <groupId>org.jsoup</groupId>
- <artifactId>jsoup</artifactId>
- <version>${jsoup.version}</version>
- </dependency>
-
- <dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
<version>${spring-kafka.version}</version>
@@ -129,11 +122,6 @@
<!-- Common Utils Dependencies -->
<dependency>
- <groupId>org.apache.commons</groupId>
- <artifactId>commons-lang3</artifactId>
- <version>${commons-lang3-version}</version>
- </dependency>
- <dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>${commons-collections-version}</version>
@@ -144,15 +132,9 @@
<version>${commons-io-version}</version>
</dependency>
<dependency>
- <groupId>org.apache.velocity</groupId>
- <artifactId>velocity</artifactId>
- <version>${velocity.version}</version>
- <exclusions>
- <exclusion>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-api</artifactId>
- </exclusion>
- </exclusions>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-compress</artifactId>
+ <version>${commons-compress-version}</version>
</dependency>
<dependency>
<groupId>com.hubspot.jinjava</groupId>
@@ -251,47 +233,6 @@
<version>${kotlin.version}</version>
</dependency>
- <!-- GRPC Dependencies -->
- <dependency>
- <groupId>io.grpc</groupId>
- <artifactId>grpc-core</artifactId>
- <version>${grpc.version}</version>
- </dependency>
- <dependency>
- <groupId>io.grpc</groupId>
- <artifactId>grpc-netty</artifactId>
- <version>${grpc.version}</version>
- </dependency>
- <dependency>
- <groupId>io.grpc</groupId>
- <artifactId>grpc-protobuf</artifactId>
- <version>${grpc.version}</version>
- </dependency>
- <dependency>
- <groupId>io.grpc</groupId>
- <artifactId>grpc-stub</artifactId>
- <version>${grpc.version}</version>
- </dependency>
- <dependency>
- <groupId>io.grpc</groupId>
- <artifactId>grpc-netty-shaded</artifactId>
- <version>${grpc.version}</version>
- </dependency>
- <dependency>
- <groupId>io.grpc</groupId>
- <artifactId>grpc-grpclb</artifactId>
- <version>${grpc.version}</version>
- </dependency>
- <dependency>
- <groupId>com.google.protobuf</groupId>
- <artifactId>protobuf-java</artifactId>
- <version>${protobuff.java.version}</version>
- </dependency>
- <dependency>
- <groupId>com.google.protobuf</groupId>
- <artifactId>protobuf-java-util</artifactId>
- <version>${protobuff.java.utils.version}</version>
- </dependency>
<dependency>
<groupId>com.github.marcoferrer.krotoplus</groupId>
<artifactId>kroto-plus-coroutines</artifactId>
@@ -351,6 +292,30 @@
<version>${kafka.version}</version>
</dependency>
+ <!-- Error Catalog -->
+ <dependency>
+ <groupId>org.onap.ccsdk.cds.error.catalog</groupId>
+ <artifactId>error-catalog-core</artifactId>
+ <version>${error.catalog.version}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>*</groupId>
+ <artifactId>*</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.cds.error.catalog</groupId>
+ <artifactId>error-catalog-services</artifactId>
+ <version>${error.catalog.version}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>*</groupId>
+ <artifactId>*</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+
<!-- SLI Version -->
<dependency>
<groupId>org.onap.ccsdk.sli.core</groupId>
@@ -485,7 +450,7 @@
</dependency>
<dependency>
<groupId>org.onap.ccsdk.cds.blueprintsprocessor.functions</groupId>
- <artifactId>nrm-restful</artifactId>
+ <artifactId>restful-executor</artifactId>
<version>${ccsdk.cds.version}</version>
</dependency>
<dependency>
@@ -614,13 +579,6 @@
<scope>test</scope>
</dependency>
- <dependency>
- <groupId>io.grpc</groupId>
- <artifactId>grpc-testing</artifactId>
- <version>${grpc.version}</version>
- <scope>test</scope>
- </dependency>
-
<!-- Spring Kafka -->
<dependency>
<groupId>org.springframework.kafka</groupId>
@@ -628,7 +586,6 @@
<version>${spring-kafka.version}</version>
<scope>test</scope>
</dependency>
-
</dependencies>
</dependencyManagement>
<dependencies>
@@ -757,6 +714,11 @@
<groupId>io.netty</groupId>
<artifactId>netty-tcnative-boringssl-static</artifactId>
</dependency>
+
+ <dependency>
+ <groupId>org.onap.ccsdk.cds.error.catalog</groupId>
+ <artifactId>error-catalog-core</artifactId>
+ </dependency>
</dependencies>
<repositories>
diff --git a/ms/error-catalog/README.md b/ms/error-catalog/README.md
new file mode 100755
index 000000000..1df859574
--- /dev/null
+++ b/ms/error-catalog/README.md
@@ -0,0 +1,40 @@
+## How to use library
+
+##### 1. Set Error Catalog service type (Database or properties file service) in application.properties file
+
+```
+##### Error Managements #####
+## For database service type ##
+# error.catalog.type=DB
+## For database service type ##
+# error.catalog.type=properties
+error.catalog.applicationId=cds
+error.catalog.type=properties
+error.catalog.errorDefinitionDir=/opt/app/onap/config
+```
+
+##### 2. Generate exception
+
+- HTTP Error Exception
+```
+errorCatalogException: ErrorCatalogException = httpProcessorException(ErrorCatalogCodes.ERROR_TYPE,
+"Error message here...")
+```
+
+- GRPC Error Exception
+```
+errorCatalogException: ErrorCatalogException = grpcProcessorException(ErrorCatalogCodes.ERROR_TYPE,
+"Error message here...")
+```
+
+##### 3. Update an existing exception
+```
+e = errorCatalogException.code(500)
+e = errorCatalogException.action("message")
+...
+```
+
+##### 4. Add a HTTP REST Exception handler
+@RestControllerAdvice("domain.here")
+open class ExceptionHandler(private val errorCatalogService: ErrorCatalogService) :
+ ErrorCatalogExceptionHandler(errorCatalogService) \ No newline at end of file
diff --git a/ms/error-catalog/application/pom.xml b/ms/error-catalog/application/pom.xml
new file mode 100644
index 000000000..4e1a6f3f1
--- /dev/null
+++ b/ms/error-catalog/application/pom.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright © 2018-2019 AT&T Intellectual Property.
+ ~
+ ~ 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.
+ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.cds.error.catalog</groupId>
+ <artifactId>error-catalog</artifactId>
+ <version>0.7.0-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>error-catalog-application</artifactId>
+
+ <name>Error Catalog Application</name>
+ <description>Error Catalog Application</description>
+</project>
diff --git a/ms/error-catalog/core/pom.xml b/ms/error-catalog/core/pom.xml
new file mode 100644
index 000000000..f117aa83f
--- /dev/null
+++ b/ms/error-catalog/core/pom.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright © 2018-2019 AT&T Intellectual Property.
+ ~
+ ~ 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.
+ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.cds.error.catalog</groupId>
+ <artifactId>error-catalog</artifactId>
+ <version>0.7.0-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>error-catalog-core</artifactId>
+
+ <name>Error Catalog Core</name>
+ <description>Error Catalog Core</description>
+</project>
diff --git a/ms/error-catalog/core/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/core/ErrorCatalogException.kt b/ms/error-catalog/core/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/core/ErrorCatalogException.kt
new file mode 100644
index 000000000..032feb62c
--- /dev/null
+++ b/ms/error-catalog/core/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/core/ErrorCatalogException.kt
@@ -0,0 +1,112 @@
+/*
+ * Copyright © 2020 IBM, Bell Canada.
+ * Modifications Copyright © 2019-2020 AT&T Intellectual Property.
+ *
+ * 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.
+ */
+
+package org.onap.ccsdk.cds.error.catalog.core
+
+interface ErrorCatalogExceptionFluent<T> {
+ fun code(code: Int): T
+ fun domain(domain: String): T
+ fun action(action: String): T
+ fun http(type: String): T
+ fun grpc(type: String): T
+ fun payloadMessage(message: String): T
+ fun addErrorPayloadMessage(message: String): T
+ fun addSubError(errorMessage: ErrorMessage): T
+}
+
+open class ErrorCatalogException : RuntimeException {
+ var code: Int = -1
+ var domain: String = ""
+ var name: String = ErrorCatalogCodes.GENERIC_FAILURE
+ var action: String = ""
+ var errorPayload: ErrorPayload? = null
+ var protocol: String = ""
+ var errorPayloadMessages: MutableList<String>? = null
+
+ val messageSeparator = "${System.lineSeparator()} -> "
+
+ constructor(message: String, cause: Throwable) : super(message, cause)
+ constructor(message: String) : super(message)
+ constructor(cause: Throwable) : super(cause)
+ constructor(cause: Throwable, message: String, vararg args: Any?) : super(format(message, *args), cause)
+
+ constructor(code: Int, cause: Throwable) : super(cause) {
+ this.code = code
+ }
+
+ constructor(code: Int, message: String) : super(message) {
+ this.code = code
+ }
+
+ constructor(code: Int, message: String, cause: Throwable) : super(message, cause) {
+ this.code = code
+ }
+
+ constructor(code: Int, cause: Throwable, message: String, vararg args: Any?) :
+ super(String.format(message, *args), cause) {
+ this.code = code
+ }
+
+ open fun <T : ErrorCatalogException> updateCode(code: Int): T {
+ this.code = code
+ return this as T
+ }
+
+ open fun <T : ErrorCatalogException> updateDomain(domain: String): T {
+ this.domain = domain
+ return this as T
+ }
+
+ open fun <T : ErrorCatalogException> updateAction(action: String): T {
+ this.action = action
+ return this as T
+ }
+
+ fun <T : ErrorCatalogException> updateHttp(type: String): T {
+ this.protocol = ErrorMessageLibConstants.ERROR_CATALOG_PROTOCOL_HTTP
+ this.code = HttpErrorCodes.code(type)
+ return this as T
+ }
+
+ fun <T : ErrorCatalogException> updateGrpc(type: String): T {
+ this.protocol = ErrorMessageLibConstants.ERROR_CATALOG_PROTOCOL_GRPC
+ this.code = GrpcErrorCodes.code(type)
+ return this as T
+ }
+
+ fun <T : ErrorCatalogException> updatePayloadMessage(message: String): T {
+ if (this.errorPayloadMessages == null) this.errorPayloadMessages = arrayListOf()
+ this.errorPayloadMessages!!.add(message)
+ return this as T
+ }
+
+ fun <T : ErrorCatalogException> updateErrorPayloadMessage(message: String): T {
+ if (errorPayload == null) {
+ errorPayload = ErrorPayload()
+ }
+ errorPayload!!.message = "${errorPayload!!.message} $messageSeparator $message"
+ return this as T
+ }
+
+ fun <T : ErrorCatalogException> updateSubError(errorMessage: ErrorMessage): T {
+ if (errorPayload == null) {
+ errorPayload = ErrorPayload()
+ }
+ errorPayload!!.subErrors.add(errorMessage)
+ return this as T
+ }
+}
diff --git a/ms/error-catalog/core/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/core/ErrorCatalogExtensions.kt b/ms/error-catalog/core/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/core/ErrorCatalogExtensions.kt
new file mode 100644
index 000000000..65c547245
--- /dev/null
+++ b/ms/error-catalog/core/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/core/ErrorCatalogExtensions.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright © 2018-2019 AT&T Intellectual Property.
+ *
+ * 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.
+ */
+
+package org.onap.ccsdk.cds.error.catalog.core
+
+import org.slf4j.LoggerFactory
+import org.slf4j.helpers.MessageFormatter
+import kotlin.reflect.KClass
+
+fun <T : Any> logger(clazz: T) = LoggerFactory.getLogger(clazz.javaClass)!!
+
+fun <T : KClass<*>> logger(clazz: T) = LoggerFactory.getLogger(clazz.java)!!
+
+fun format(message: String, vararg args: Any?): String {
+ if (args != null && args.isNotEmpty()) {
+ return MessageFormatter.arrayFormat(message, args).message
+ }
+ return message
+}
diff --git a/ms/error-catalog/core/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/core/ErrorCodes.kt b/ms/error-catalog/core/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/core/ErrorCodes.kt
new file mode 100644
index 000000000..86483e3e9
--- /dev/null
+++ b/ms/error-catalog/core/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/core/ErrorCodes.kt
@@ -0,0 +1,88 @@
+/*
+ * Copyright © 2018-2019 AT&T Intellectual Property.
+ *
+ * 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.
+ */
+
+package org.onap.ccsdk.cds.error.catalog.core
+
+object ErrorCatalogCodes {
+ const val GENERIC_FAILURE = "GENERIC_FAILURE"
+ const val GENERIC_PROCESS_FAILURE = "GENERIC_PROCESS_FAILURE"
+ const val INVALID_FILE_EXTENSION = "INVALID_FILE_EXTENSION"
+ const val RESOURCE_NOT_FOUND = "RESOURCE_NOT_FOUND"
+ const val RESOURCE_PATH_MISSING = "RESOURCE_PATH_MISSING"
+ const val RESOURCE_WRITING_FAIL = "RESOURCE_WRITING_FAIL"
+ const val IO_FILE_INTERRUPT = "IO_FILE_INTERRUPT"
+ const val INVALID_REQUEST_FORMAT = "INVALID_REQUEST_FORMAT"
+ const val UNAUTHORIZED_REQUEST = "UNAUTHORIZED_REQUEST"
+ const val REQUEST_NOT_FOUND = "REQUEST_NOT_FOUND"
+ const val CONFLICT_ADDING_RESOURCE = "CONFLICT_ADDING_RESOURCE"
+ const val DUPLICATE_DATA = "DUPLICATE_DATA"
+}
+
+object HttpErrorCodes {
+ private val store: MutableMap<String, Int> = mutableMapOf()
+
+ init {
+ store[ErrorCatalogCodes.GENERIC_FAILURE] = 500
+ store[ErrorCatalogCodes.GENERIC_PROCESS_FAILURE] = 500
+ store[ErrorCatalogCodes.INVALID_FILE_EXTENSION] = 415
+ store[ErrorCatalogCodes.RESOURCE_NOT_FOUND] = 404
+ store[ErrorCatalogCodes.RESOURCE_PATH_MISSING] = 503
+ store[ErrorCatalogCodes.RESOURCE_WRITING_FAIL] = 503
+ store[ErrorCatalogCodes.IO_FILE_INTERRUPT] = 503
+ store[ErrorCatalogCodes.INVALID_REQUEST_FORMAT] = 400
+ store[ErrorCatalogCodes.UNAUTHORIZED_REQUEST] = 401
+ store[ErrorCatalogCodes.REQUEST_NOT_FOUND] = 404
+ store[ErrorCatalogCodes.CONFLICT_ADDING_RESOURCE] = 409
+ store[ErrorCatalogCodes.DUPLICATE_DATA] = 409
+ }
+
+ fun register(type: String, code: Int) {
+ store[type] = code
+ }
+
+ fun code(type: String): Int {
+ // FIXME("Return Default Error Code , If missing")
+ return store[type]!!
+ }
+}
+
+object GrpcErrorCodes {
+ private val store: MutableMap<String, Int> = mutableMapOf()
+
+ init {
+ store[ErrorCatalogCodes.GENERIC_FAILURE] = 2
+ store[ErrorCatalogCodes.GENERIC_PROCESS_FAILURE] = 2
+ store[ErrorCatalogCodes.INVALID_FILE_EXTENSION] = 3
+ store[ErrorCatalogCodes.RESOURCE_NOT_FOUND] = 5
+ store[ErrorCatalogCodes.RESOURCE_PATH_MISSING] = 3
+ store[ErrorCatalogCodes.RESOURCE_WRITING_FAIL] = 9
+ store[ErrorCatalogCodes.IO_FILE_INTERRUPT] = 3
+ store[ErrorCatalogCodes.INVALID_REQUEST_FORMAT] = 3
+ store[ErrorCatalogCodes.UNAUTHORIZED_REQUEST] = 16
+ store[ErrorCatalogCodes.REQUEST_NOT_FOUND] = 8
+ store[ErrorCatalogCodes.CONFLICT_ADDING_RESOURCE] = 10
+ store[ErrorCatalogCodes.DUPLICATE_DATA] = 11
+ }
+
+ fun register(type: String, code: Int) {
+ store[type] = code
+ }
+
+ fun code(type: String): Int {
+ // FIXME("Return Default Error Code , If missing")
+ return store[type]!!
+ }
+}
diff --git a/ms/error-catalog/core/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/core/ErrorLibData.kt b/ms/error-catalog/core/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/core/ErrorLibData.kt
new file mode 100644
index 000000000..2c0772e31
--- /dev/null
+++ b/ms/error-catalog/core/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/core/ErrorLibData.kt
@@ -0,0 +1,94 @@
+/*
+ * Copyright © 2020 IBM, Bell Canada.
+ *
+ * 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.
+ */
+
+package org.onap.ccsdk.cds.error.catalog.core
+
+import com.fasterxml.jackson.annotation.JsonFormat
+import org.slf4j.event.Level
+import org.onap.ccsdk.cds.error.catalog.core.ErrorMessageLibConstants.ERROR_CATALOG_DEFAULT_ERROR_CODE
+import java.time.LocalDateTime
+
+open class ErrorPayload {
+ var code: Int = ERROR_CATALOG_DEFAULT_ERROR_CODE
+ var status: String = ""
+ @get:JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
+ var timestamp: LocalDateTime = LocalDateTime.now()
+ var message: String = ""
+ var debugMessage: String = ""
+ var logLevel: String = Level.ERROR.name
+ val subErrors: ArrayList<ErrorMessage> = ArrayList()
+
+ constructor()
+
+ constructor(
+ code: Int = ERROR_CATALOG_DEFAULT_ERROR_CODE,
+ status: String,
+ message: String,
+ logLevel: String = Level.ERROR.name,
+ debugMessage: String = ""
+ ) {
+ this.code = code
+ this.status = status
+ this.message = message
+ this.logLevel = logLevel
+ this.debugMessage = debugMessage
+ }
+
+ constructor(
+ code: Int = ERROR_CATALOG_DEFAULT_ERROR_CODE,
+ status: String,
+ message: String,
+ logLevel: String = Level.ERROR.name,
+ debugMessage: String = "",
+ errorMessage: ErrorMessage
+ ) {
+ this.code = code
+ this.status = status
+ this.message = message
+ this.logLevel = logLevel
+ this.debugMessage = debugMessage
+ this.subErrors.add(errorMessage)
+ }
+
+ fun isEqualTo(errorPayload: ErrorPayload): Boolean {
+ return (this.code == errorPayload.code && this.status == errorPayload.status && this.message == errorPayload.message &&
+ this.logLevel == errorPayload.logLevel && this.debugMessage == errorPayload.debugMessage &&
+ this.subErrors == errorPayload.subErrors)
+ }
+}
+
+/**
+ *
+ *
+ * @author Steve Siani
+ */
+data class ErrorMessage(
+ val domainId: String,
+ val message: String,
+ val cause: String
+)
+
+data class ErrorCatalog(
+ val errorId: String,
+ val domainId: String,
+ val code: Int,
+ val action: String,
+ val cause: String
+) {
+ fun getMessage(): String {
+ return "Cause: $cause ${System.lineSeparator()} Action : $action"
+ }
+}
diff --git a/ms/error-catalog/core/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/core/ErrorMessageLibConstants.kt b/ms/error-catalog/core/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/core/ErrorMessageLibConstants.kt
new file mode 100644
index 000000000..6570e3e66
--- /dev/null
+++ b/ms/error-catalog/core/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/core/ErrorMessageLibConstants.kt
@@ -0,0 +1,31 @@
+/*
+ * Copyright © 2020 IBM, Bell Canada.
+ *
+ * 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.
+ */
+
+package org.onap.ccsdk.cds.error.catalog.core
+
+object ErrorMessageLibConstants {
+ const val ERROR_CATALOG_DOMAIN = "org.onap.ccsdk.cds.error.catalog"
+ const val ERROR_CATALOG_TYPE = "error.catalog.type"
+ const val ERROR_CATALOG_TYPE_PROPERTIES = "properties"
+ const val ERROR_CATALOG_TYPE_DB = "DB"
+ const val ERROR_CATALOG_PROPERTIES_FILENAME = "error-messages_en.properties"
+ const val ERROR_CATALOG_PROPERTIES_DIRECTORY = "/opt/app/onap/config/"
+ const val ERROR_CATALOG_MODELS = "org.onap.ccsdk.cds.error.catalog.domain"
+ const val ERROR_CATALOG_REPOSITORY = "org.onap.ccsdk.cds.error.catalog.repository"
+ const val ERROR_CATALOG_DEFAULT_ERROR_CODE = 500
+ const val ERROR_CATALOG_PROTOCOL_HTTP = "http"
+ const val ERROR_CATALOG_PROTOCOL_GRPC = "grpc"
+}
diff --git a/ms/error-catalog/pom.xml b/ms/error-catalog/pom.xml
new file mode 100644
index 000000000..1e6707a75
--- /dev/null
+++ b/ms/error-catalog/pom.xml
@@ -0,0 +1,157 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright © 2018-2019 AT&T Intellectual Property.
+ ~
+ ~ 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.
+ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.cds</groupId>
+ <artifactId>ms</artifactId>
+ <version>0.7.0-SNAPSHOT</version>
+ <relativePath>..</relativePath>
+ </parent>
+
+ <groupId>org.onap.ccsdk.cds.error.catalog</groupId>
+ <artifactId>error-catalog</artifactId>
+ <packaging>pom</packaging>
+
+ <name>Error Catalog Lib</name>
+ <description>Error Catalog Lib for ONAP Components</description>
+
+ <modules>
+ <module>application</module>
+ <module>core</module>
+ <module>services</module>
+ </modules>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.onap.ccsdk.cds.error.catalog</groupId>
+ <artifactId>error-catalog-core</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.cds.error.catalog</groupId>
+ <artifactId>error-catalog-services</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+ <dependencies>
+ <!-- Kotlin Dependencies -->
+ <dependency>
+ <groupId>org.jetbrains.kotlin</groupId>
+ <artifactId>kotlin-stdlib</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.jetbrains.kotlin</groupId>
+ <artifactId>kotlin-stdlib-common</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.jetbrains.kotlin</groupId>
+ <artifactId>kotlin-script-util</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.jetbrains.kotlin</groupId>
+ <artifactId>kotlin-stdlib-jdk8</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.jetbrains.kotlinx</groupId>
+ <artifactId>kotlinx-coroutines-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.jetbrains.kotlinx</groupId>
+ <artifactId>kotlinx-coroutines-reactor</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.module</groupId>
+ <artifactId>jackson-module-kotlin</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.jetbrains.kotlin</groupId>
+ <artifactId>kotlin-compiler-embeddable</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.jetbrains.kotlin</groupId>
+ <artifactId>kotlin-scripting-jvm-host</artifactId>
+ <!--Use kotlin-compiler-embeddable as koltin-compiler wrap-->
+ <!--guava dependency creating classpath issues at runtime-->
+ <exclusions>
+ <exclusion>
+ <groupId>org.jetbrains.kotlin</groupId>
+ <artifactId>kotlin-compiler</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-webflux</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>javax.persistence</groupId>
+ <artifactId>javax.persistence-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-data-jpa</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-test</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>io.projectreactor</groupId>
+ <artifactId>reactor-test</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.jetbrains.kotlin</groupId>
+ <artifactId>kotlin-maven-plugin</artifactId>
+ <version>${kotlin.maven.version}</version>
+ <executions>
+ <execution>
+ <id>compile</id>
+ <goals>
+ <goal>compile</goal>
+ </goals>
+ <configuration>
+ <sourceDirs>
+ <sourceDir>src/main/kotlin</sourceDir>
+ </sourceDirs>
+ </configuration>
+ </execution>
+ <execution>
+ <id>test-compile</id>
+ <goals>
+ <goal>test-compile</goal>
+ </goals>
+ <configuration>
+ <sourceDirs>
+ <sourceDir>${project.basedir}/src/test/kotlin</sourceDir>
+ </sourceDirs>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/ms/error-catalog/services/pom.xml b/ms/error-catalog/services/pom.xml
new file mode 100644
index 000000000..6fcf158f5
--- /dev/null
+++ b/ms/error-catalog/services/pom.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright © 2018-2019 AT&T Intellectual Property.
+ ~
+ ~ 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.
+ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.cds.error.catalog</groupId>
+ <artifactId>error-catalog</artifactId>
+ <version>0.7.0-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>error-catalog-services</artifactId>
+
+ <name>Error Catalog Service</name>
+ <description>Error Catalog Service</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.onap.ccsdk.cds.error.catalog</groupId>
+ <artifactId>error-catalog-core</artifactId>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/ms/error-catalog/services/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/services/ErrorCatalogConfiguration.kt b/ms/error-catalog/services/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/services/ErrorCatalogConfiguration.kt
new file mode 100644
index 000000000..f0a75e087
--- /dev/null
+++ b/ms/error-catalog/services/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/services/ErrorCatalogConfiguration.kt
@@ -0,0 +1,34 @@
+/*
+ * Copyright © 2020 IBM, Bell Canada.
+ * Modifications Copyright © 2019-2020 AT&T Intellectual Property.
+ *
+ * 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.
+ */
+package org.onap.ccsdk.cds.error.catalog.services
+
+import org.springframework.boot.context.properties.ConfigurationProperties
+import org.springframework.boot.context.properties.EnableConfigurationProperties
+import org.springframework.context.annotation.Configuration
+import org.springframework.stereotype.Component
+
+@Configuration
+@EnableConfigurationProperties(ErrorCatalogProperties::class)
+open class ErrorCatalogConfiguration
+
+@Component
+@ConfigurationProperties(prefix = "error.catalog")
+open class ErrorCatalogProperties {
+ lateinit var type: String
+ lateinit var applicationId: String
+ var errorDefinitionDir: String? = null
+}
diff --git a/ms/error-catalog/services/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/services/ErrorCatalogDBService.kt b/ms/error-catalog/services/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/services/ErrorCatalogDBService.kt
new file mode 100644
index 000000000..95b44e683
--- /dev/null
+++ b/ms/error-catalog/services/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/services/ErrorCatalogDBService.kt
@@ -0,0 +1,98 @@
+/*
+ * Copyright © 2020 IBM, Bell Canada.
+ * Modifications Copyright © 2019-2020 AT&T Intellectual Property.
+ *
+ * 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.
+ */
+
+package org.onap.ccsdk.cds.error.catalog.services
+
+import org.onap.ccsdk.cds.error.catalog.core.ErrorMessageLibConstants
+import org.onap.ccsdk.cds.error.catalog.services.domain.Domain
+import org.onap.ccsdk.cds.error.catalog.services.domain.ErrorMessageModel
+import org.onap.ccsdk.cds.error.catalog.services.repository.DomainRepository
+import org.onap.ccsdk.cds.error.catalog.services.repository.ErrorMessageModelRepository
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
+import org.springframework.data.domain.Page
+import org.springframework.data.domain.Pageable
+import org.springframework.stereotype.Service
+
+@Service
+@ConditionalOnProperty(
+ name = [ErrorMessageLibConstants.ERROR_CATALOG_TYPE],
+ havingValue = ErrorMessageLibConstants.ERROR_CATALOG_TYPE_DB
+)
+open class ErrorCatalogDBService(
+ private val domainRepository: DomainRepository,
+ private val errorMessageModelRepository: ErrorMessageModelRepository
+) {
+
+ /**
+ * This is a getAllDomains method to retrieve all the Domain in Error Catalog Database by pages
+ *
+ * @return Page<Domain> list of the domains by page
+ </Domain> */
+ open fun getAllDomains(pageRequest: Pageable): Page<Domain> {
+ return domainRepository.findAll(pageRequest)
+ }
+
+ /**
+ * This is a getAllDomains method to retrieve all the Domain in Error Catalog Database
+ *
+ * @return List<Domain> list of the domains
+ </Domain> */
+ open fun getAllDomains(): List<Domain> {
+ return domainRepository.findAll()
+ }
+
+ /**
+ * This is a getAllDomainsByApplication method to retrieve all the Domain that belong to an application in Error Catalog Database
+ *
+ * @return List<Domain> list of the domains
+ </Domain> */
+ open fun getAllDomainsByApplication(applicationId: String): List<Domain> {
+ return domainRepository.findAllByApplicationId(applicationId)
+ }
+
+ /**
+ * This is a getAllErrorMessagesByApplication method to retrieve all the Messages that belong to an application in Error Catalog Database
+ *
+ * @return MutableMap<String, ErrorCode> list of the abstractErrorModel
+ </Domain> */
+ open fun getAllErrorMessagesByApplication(applicationId: String): MutableMap<String, ErrorMessageModel> {
+ val domains = domainRepository.findAllByApplicationId(applicationId)
+ val errorMessages = mutableMapOf<String, ErrorMessageModel>()
+ for (domain in domains) {
+ val errorMessagesFound = errorMessageModelRepository.findByDomainsId(domain.id)
+ for (errorMessageFound in errorMessagesFound) {
+ errorMessages["${domain.name}$MESSAGE_KEY_SEPARATOR${errorMessageFound.messageID}"] = errorMessageFound
+ }
+ }
+ return errorMessages
+ }
+
+ open fun saveDomain(
+ domain: String,
+ applicationId: String,
+ description: String = "",
+ errorMessageList: List<ErrorMessageModel>
+ ) {
+ val domainModel = Domain(domain, applicationId, description)
+ domainModel.errorMessages.addAll(errorMessageList)
+ domainRepository.saveAndFlush(domainModel)
+ }
+
+ companion object {
+ private const val MESSAGE_KEY_SEPARATOR = "."
+ }
+}
diff --git a/ms/error-catalog/services/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/services/ErrorCatalogExceptionHandler.kt b/ms/error-catalog/services/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/services/ErrorCatalogExceptionHandler.kt
new file mode 100644
index 000000000..88e2f4522
--- /dev/null
+++ b/ms/error-catalog/services/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/services/ErrorCatalogExceptionHandler.kt
@@ -0,0 +1,31 @@
+/*
+ * Copyright © 2020 IBM, Bell Canada.
+ *
+ * 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.
+ */
+
+package org.onap.ccsdk.cds.error.catalog.services
+
+import org.onap.ccsdk.cds.error.catalog.core.ErrorCatalogException
+import org.onap.ccsdk.cds.error.catalog.core.ErrorPayload
+import org.springframework.http.ResponseEntity
+import org.springframework.web.bind.annotation.ExceptionHandler
+
+abstract class ErrorCatalogExceptionHandler(private val errorCatalogService: ErrorCatalogService) {
+
+ @ExceptionHandler(ErrorCatalogException::class)
+ fun errorCatalogException(e: ErrorCatalogException): ResponseEntity<ErrorPayload> {
+ val errorPayload = errorCatalogService.errorPayload(e)
+ return errorPayload.toResponseEntity()
+ }
+}
diff --git a/ms/error-catalog/services/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/services/ErrorCatalogLoadService.kt b/ms/error-catalog/services/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/services/ErrorCatalogLoadService.kt
new file mode 100644
index 000000000..ca7d72b50
--- /dev/null
+++ b/ms/error-catalog/services/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/services/ErrorCatalogLoadService.kt
@@ -0,0 +1,147 @@
+/*
+ * Copyright © 2020 IBM, Bell Canada.
+ * Modifications Copyright © 2019-2020 AT&T Intellectual Property.
+ *
+ * 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.
+ */
+
+package org.onap.ccsdk.cds.error.catalog.services
+
+import org.onap.ccsdk.cds.error.catalog.core.ErrorMessageLibConstants
+import org.onap.ccsdk.cds.error.catalog.core.logger
+import org.onap.ccsdk.cds.error.catalog.services.domain.ErrorMessageModel
+import org.springframework.boot.autoconfigure.condition.ConditionalOnBean
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
+import org.springframework.stereotype.Service
+import java.io.File
+import java.io.FileNotFoundException
+import java.io.IOException
+import java.io.InputStream
+import java.nio.file.Paths
+import java.util.Properties
+
+interface ErrorCatalogLoadService {
+
+ suspend fun loadErrorCatalog()
+
+ fun getErrorMessage(domain: String, key: String): String?
+
+ fun getErrorMessage(attribute: String): String?
+}
+
+/**
+ * Representation of Blueprint Error Message lib from database service to load the properties
+ */
+@Service
+@ConditionalOnBean(ErrorCatalogDBService::class)
+open class ErrorCatalogLoadDBService(
+ private var errorCatalogProperties: ErrorCatalogProperties,
+ private var errorCatalogDBService: ErrorCatalogDBService
+) : ErrorCatalogLoadService {
+
+ private var log = logger(ErrorCatalogLoadDBService::class)
+
+ lateinit var errorMessageInDB: Map<String, ErrorMessageModel>
+
+ override suspend fun loadErrorCatalog() {
+ log.info("Application ID: ${errorCatalogProperties.applicationId} > Initializing error catalog message from database...")
+ errorMessageInDB = getErrorMessagesFromDB()
+ }
+
+ override fun getErrorMessage(domain: String, key: String): String? {
+ return getErrorMessage("$domain.${key.toLowerCase()}")
+ }
+
+ override fun getErrorMessage(attribute: String): String? {
+ val errorMessage = findErrorMessage(attribute)
+ return prepareErrorMessage(errorMessage)
+ }
+
+ /**
+ * Parses the error-messages.properties file which contains error messages
+ */
+ private suspend fun getErrorMessagesFromDB(): Map<String, ErrorMessageModel> {
+ return errorCatalogDBService.getAllErrorMessagesByApplication(errorCatalogProperties.applicationId)
+ }
+
+ private fun findErrorMessage(attribute: String): ErrorMessageModel? {
+ return if (errorMessageInDB.containsKey(attribute)) {
+ errorMessageInDB[attribute]
+ } else {
+ null
+ }
+ }
+
+ private fun prepareErrorMessage(errorMessage: ErrorMessageModel?): String? {
+ return if (errorMessage != null) {
+ "cause=${errorMessage.cause}, action=${errorMessage.action}"
+ } else {
+ null
+ }
+ }
+}
+
+/**
+ * Representation of Blueprint Error Message lib property service to load the properties
+ */
+@Service
+@ConditionalOnProperty(
+ name = [ErrorMessageLibConstants.ERROR_CATALOG_TYPE],
+ havingValue = ErrorMessageLibConstants.ERROR_CATALOG_TYPE_PROPERTIES
+)
+open class ErrorCatalogLoadPropertyService(private var errorCatalogProperties: ErrorCatalogProperties) :
+ ErrorCatalogLoadService {
+
+ private val propertyFileName = ErrorMessageLibConstants.ERROR_CATALOG_PROPERTIES_FILENAME
+ private lateinit var propertyFile: File
+
+ private var log = logger(ErrorCatalogLoadPropertyService::class)
+
+ lateinit var properties: Properties
+
+ override suspend fun loadErrorCatalog() {
+ log.info("Application ID: ${errorCatalogProperties.applicationId} > Initializing error catalog message from properties...")
+ val propertyDir = errorCatalogProperties.errorDefinitionDir ?: ErrorMessageLibConstants.ERROR_CATALOG_PROPERTIES_DIRECTORY
+ propertyFile = Paths.get(propertyDir, propertyFileName).toFile().normalize()
+ properties = parseErrorMessagesProps()
+ }
+
+ override fun getErrorMessage(domain: String, key: String): String? {
+ return getErrorMessage("$domain.${key.toLowerCase()}")
+ }
+
+ override fun getErrorMessage(attribute: String): String? {
+ return properties.getProperty(attribute)
+ }
+
+ /**
+ * Parses the error-messages.properties file which contains error messages
+ */
+ private fun parseErrorMessagesProps(): Properties {
+ var inputStream: InputStream? = null
+ val props = Properties()
+ try {
+ inputStream = propertyFile.inputStream()
+ props.load(inputStream)
+ } catch (e: FileNotFoundException) {
+ log.error("Application ID: ${errorCatalogProperties.applicationId} > Property File '$propertyFileName' " +
+ "not found in the application directory.")
+ } catch (e: IOException) {
+ log.error("Application ID: ${errorCatalogProperties.applicationId} > Fail to load property file " +
+ "'$propertyFileName' for message errors.")
+ } finally {
+ inputStream!!.close()
+ }
+ return props
+ }
+}
diff --git a/ms/error-catalog/services/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/services/ErrorCatalogService.kt b/ms/error-catalog/services/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/services/ErrorCatalogService.kt
new file mode 100644
index 000000000..91f817133
--- /dev/null
+++ b/ms/error-catalog/services/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/services/ErrorCatalogService.kt
@@ -0,0 +1,91 @@
+/*
+ * Copyright © 2020 IBM, Bell Canada.
+ * Modifications Copyright © 2019-2020 AT&T Intellectual Property.
+ *
+ * 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.
+ */
+
+package org.onap.ccsdk.cds.error.catalog.services
+
+import kotlinx.coroutines.runBlocking
+import org.onap.ccsdk.cds.error.catalog.core.ErrorCatalog
+import org.onap.ccsdk.cds.error.catalog.core.ErrorCatalogException
+import org.onap.ccsdk.cds.error.catalog.core.ErrorMessageLibConstants
+import org.onap.ccsdk.cds.error.catalog.core.ErrorPayload
+import org.onap.ccsdk.cds.error.catalog.core.GrpcErrorCodes
+import org.onap.ccsdk.cds.error.catalog.core.HttpErrorCodes
+import org.onap.ccsdk.cds.error.catalog.services.utils.ErrorCatalogUtils
+import org.springframework.boot.autoconfigure.condition.ConditionalOnBean
+import org.springframework.stereotype.Service
+import javax.annotation.PostConstruct
+
+@Service
+@ConditionalOnBean(ErrorCatalogLoadService::class)
+open class ErrorCatalogService(private var errorCatalogLoadService: ErrorCatalogLoadService) {
+
+ @PostConstruct
+ open fun init() = runBlocking {
+ errorCatalogLoadService.loadErrorCatalog()
+ }
+
+ fun errorPayload(errorCatalogException: ErrorCatalogException): ErrorPayload {
+ val errorCatalog = getErrorCatalog(errorCatalogException)
+ val errorPayload = ErrorPayload(errorCatalog.code, errorCatalog.errorId, errorCatalog.getMessage())
+ errorPayload.subErrors.addAll(errorCatalogException.errorPayload!!.subErrors)
+ if (errorCatalogException.cause != null) {
+ errorPayload.debugMessage = errorCatalogException.cause!!.printStackTrace().toString()
+ }
+ return errorPayload
+ }
+
+ fun getErrorCatalog(errorCatalogException: ErrorCatalogException): ErrorCatalog {
+ val errorMessage = getMessage(errorCatalogException.domain, errorCatalogException.name)
+ val errorCode =
+ if (errorCatalogException.code == -1) {
+ getProtocolErrorCode(
+ errorCatalogException.protocol,
+ errorCatalogException.name
+ )
+ } else {
+ errorCatalogException.code
+ }
+ val action: String
+ val errorCause: String
+ if (errorMessage.isNullOrEmpty()) {
+ action = errorCatalogException.action
+ errorCause = errorCatalogException.message ?: ""
+ } else {
+ action = ErrorCatalogUtils.readErrorActionFromMessage(errorMessage)
+ errorCause = errorCatalogException.message ?: ErrorCatalogUtils.readErrorCauseFromMessage(errorMessage)
+ }
+
+ return ErrorCatalog(
+ errorCatalogException.name,
+ errorCatalogException.domain,
+ errorCode,
+ action,
+ errorCause
+ )
+ }
+
+ private fun getProtocolErrorCode(protocol: String, type: String): Int {
+ return when (protocol) {
+ ErrorMessageLibConstants.ERROR_CATALOG_PROTOCOL_GRPC -> GrpcErrorCodes.code(type)
+ else -> HttpErrorCodes.code(type)
+ }
+ }
+
+ private fun getMessage(domain: String, key: String): String? {
+ return errorCatalogLoadService.getErrorMessage(domain, key)
+ }
+}
diff --git a/ms/error-catalog/services/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/services/ErrorCatalogServiceExtensions.kt b/ms/error-catalog/services/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/services/ErrorCatalogServiceExtensions.kt
new file mode 100644
index 000000000..bb4a8f15e
--- /dev/null
+++ b/ms/error-catalog/services/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/services/ErrorCatalogServiceExtensions.kt
@@ -0,0 +1,25 @@
+/*
+ * Copyright © 2018-2019 AT&T Intellectual Property.
+ *
+ * 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.
+ */
+
+package org.onap.ccsdk.cds.error.catalog.services
+
+import org.onap.ccsdk.cds.error.catalog.core.ErrorPayload
+import org.springframework.http.HttpStatus
+import org.springframework.http.ResponseEntity
+
+fun ErrorPayload.toResponseEntity(): ResponseEntity<ErrorPayload> {
+ return ResponseEntity(this, HttpStatus.resolve(this.code)!!)
+}
diff --git a/ms/error-catalog/services/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/services/domain/Domain.kt b/ms/error-catalog/services/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/services/domain/Domain.kt
new file mode 100755
index 000000000..7ade1c2a2
--- /dev/null
+++ b/ms/error-catalog/services/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/services/domain/Domain.kt
@@ -0,0 +1,76 @@
+/*
+ * Copyright © 2020 IBM, Bell Canada.
+ *
+ * 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.
+ */
+
+package org.onap.ccsdk.cds.error.catalog.services.domain
+
+import java.io.Serializable
+import javax.persistence.CascadeType
+import javax.persistence.Column
+import javax.persistence.Entity
+import javax.persistence.FetchType
+import javax.persistence.Id
+import javax.persistence.Lob
+import javax.persistence.ManyToMany
+import javax.persistence.Table
+import javax.persistence.UniqueConstraint
+import java.util.UUID
+import javax.persistence.JoinTable
+import javax.persistence.JoinColumn
+
+/**
+ * Provide ErrorCode Entity
+ *
+ * @author Steve Siani
+ * @version 1.0
+ */
+
+@Entity
+@Table(name = "ERROR_DOMAINS", uniqueConstraints = [UniqueConstraint(columnNames = ["name", "application_id"])])
+class Domain : Serializable {
+ @Id
+ var id: String = UUID.randomUUID().toString()
+
+ @Column(name = "name")
+ lateinit var name: String
+
+ @Column(name = "application_id")
+ lateinit var applicationId: String
+
+ @Lob
+ @Column(name = "description")
+ var description: String = ""
+
+ @ManyToMany(fetch = FetchType.EAGER, cascade = [CascadeType.ALL])
+ @JoinTable(
+ name = "ERROR_DOMAINS_ERROR_MESSAGES",
+ joinColumns = [JoinColumn(name = "domain_id", referencedColumnName = "id")],
+ inverseJoinColumns = [JoinColumn(name = "message_id", referencedColumnName = "id")]
+ )
+ @Column(name = "error_msg")
+ val errorMessages: MutableSet<ErrorMessageModel> = mutableSetOf()
+
+ constructor()
+
+ constructor(name: String, applicationId: String, description: String) {
+ this.name = name
+ this.description = description
+ this.applicationId = applicationId
+ }
+
+ companion object {
+ private const val serialVersionUID = 1L
+ }
+}
diff --git a/ms/error-catalog/services/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/services/domain/ErrorMessageModel.kt b/ms/error-catalog/services/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/services/domain/ErrorMessageModel.kt
new file mode 100644
index 000000000..a4e92af48
--- /dev/null
+++ b/ms/error-catalog/services/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/services/domain/ErrorMessageModel.kt
@@ -0,0 +1,69 @@
+/*
+ * Copyright © 2020 IBM, Bell Canada.
+ *
+ * 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.
+ */
+
+package org.onap.ccsdk.cds.error.catalog.services.domain
+
+import java.io.Serializable
+import java.util.UUID
+import javax.persistence.CascadeType
+import javax.persistence.Column
+import javax.persistence.Entity
+import javax.persistence.FetchType
+import javax.persistence.Id
+import javax.persistence.Lob
+import javax.persistence.ManyToMany
+import javax.persistence.Table
+import javax.persistence.UniqueConstraint
+
+/**
+ * Provide Error Message Model Entity
+ *
+ * @author Steve Siani
+ * @version 1.0
+ */
+@Entity
+@Table(name = "ERROR_MESSAGES", uniqueConstraints = [UniqueConstraint(columnNames = ["message_id"])])
+class ErrorMessageModel : Serializable {
+
+ @Id
+ var id: String = UUID.randomUUID().toString()
+
+ @Column(name = "message_id", nullable = false)
+ lateinit var messageID: String
+
+ @Lob
+ @Column(name = "cause")
+ var cause: String = ""
+
+ @Lob
+ @Column(name = "action")
+ lateinit var action: String
+
+ @ManyToMany(mappedBy = "errorMessages", fetch = FetchType.EAGER, cascade = [CascadeType.PERSIST])
+ val domains: MutableSet<Domain> = mutableSetOf()
+
+ companion object {
+ private const val serialVersionUID = 1L
+ }
+
+ constructor()
+
+ constructor(messageId: String, cause: String, action: String) {
+ this.messageID = messageId
+ this.cause = cause
+ this.action = action
+ }
+}
diff --git a/ms/error-catalog/services/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/services/repository/DomainRepository.kt b/ms/error-catalog/services/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/services/repository/DomainRepository.kt
new file mode 100644
index 000000000..197e385e0
--- /dev/null
+++ b/ms/error-catalog/services/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/services/repository/DomainRepository.kt
@@ -0,0 +1,45 @@
+/*
+ * Copyright © 2020 IBM, Bell Canada.
+ *
+ * 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.
+ */
+
+package org.onap.ccsdk.cds.error.catalog.services.repository
+
+import org.onap.ccsdk.cds.error.catalog.services.domain.Domain
+import org.springframework.data.jpa.repository.JpaRepository
+import org.springframework.stereotype.Repository
+
+/**
+ * @param <T> Model
+ */
+@Repository
+interface DomainRepository : JpaRepository<Domain, String> {
+
+ /**
+ * This is a findByNameAndApplicationId method
+ *
+ * @param name name
+ * @param applicationId applicationId
+ * @return Optional<T>
+ */
+ fun findByNameAndApplicationId(name: String, applicationId: String): Domain?
+
+ /**
+ * This is a findAllByApplicationId method
+ *
+ * @param applicationId applicationId
+ * @return List<T>
+ */
+ fun findAllByApplicationId(applicationId: String): List<Domain>
+}
diff --git a/ms/error-catalog/services/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/services/repository/ErrorMessageModelRepository.kt b/ms/error-catalog/services/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/services/repository/ErrorMessageModelRepository.kt
new file mode 100644
index 000000000..4a0f78672
--- /dev/null
+++ b/ms/error-catalog/services/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/services/repository/ErrorMessageModelRepository.kt
@@ -0,0 +1,36 @@
+/*
+ * Copyright © 2020 IBM, Bell Canada.
+ *
+ * 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.
+ */
+
+package org.onap.ccsdk.cds.error.catalog.services.repository
+
+import org.onap.ccsdk.cds.error.catalog.services.domain.ErrorMessageModel
+import org.springframework.data.jpa.repository.JpaRepository
+import org.springframework.stereotype.Repository
+
+/**
+ * @param <T> Model
+ */
+@Repository
+interface ErrorMessageModelRepository : JpaRepository<ErrorMessageModel, String> {
+
+ /**
+ * This is a findByDomains method
+ *
+ * @param domainId domainId
+ * @return List<T>
+ */
+ fun findByDomainsId(domainId: String): List<ErrorMessageModel>
+}
diff --git a/ms/error-catalog/services/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/services/utils/ErrorCatalogUtils.kt b/ms/error-catalog/services/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/services/utils/ErrorCatalogUtils.kt
new file mode 100644
index 000000000..967d3560c
--- /dev/null
+++ b/ms/error-catalog/services/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/services/utils/ErrorCatalogUtils.kt
@@ -0,0 +1,39 @@
+/*
+ * Copyright © 2020 IBM, Bell Canada.
+ *
+ * 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.
+ */
+package org.onap.ccsdk.cds.error.catalog.services.utils
+
+object ErrorCatalogUtils {
+ private const val REGEX_PATTERN = "^cause=(.*),action=(.*)"
+ private val regex = REGEX_PATTERN.toRegex()
+
+ fun readErrorCauseFromMessage(message: String): String {
+ val matchResults = regex.matchEntire(message)
+ return matchResults!!.groupValues[1]
+ }
+
+ fun readErrorActionFromMessage(message: String): String {
+ val matchResults = regex.matchEntire(message)
+ return matchResults!!.groupValues[2]
+ }
+}
+
+fun Exception.errorCauseOrDefault(): Throwable {
+ return this.cause ?: Throwable()
+}
+
+fun Exception.errorMessageOrDefault(): String {
+ return this.message ?: ""
+}
diff --git a/ms/pom.xml b/ms/pom.xml
index 7ec3f39a2..7a0168f5b 100644
--- a/ms/pom.xml
+++ b/ms/pom.xml
@@ -32,9 +32,29 @@
<description>Micro-services</description>
<modules>
+ <module>error-catalog</module>
<module>blueprintsprocessor</module>
<module>py-executor</module>
<module>command-executor</module>
<module>sdclistener</module>
</modules>
+
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>pl.project13.maven</groupId>
+ <artifactId>git-commit-id-plugin</artifactId>
+ <version>4.0.0</version>
+ <configuration>
+ <includeOnlyProperties>
+ <includeOnlyProperty>^git.build.(time|version)$</includeOnlyProperty>
+ <includeOnlyProperty>^git.commit.id.(abbrev|full)$</includeOnlyProperty>
+ </includeOnlyProperties>
+ <commitIdGenerationMode>full</commitIdGenerationMode>
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
</project>
diff --git a/ms/py-executor/pom.xml b/ms/py-executor/pom.xml
index 9ede1b21b..5c8ac17cf 100644
--- a/ms/py-executor/pom.xml
+++ b/ms/py-executor/pom.xml
@@ -36,6 +36,7 @@
<ccsdk.project.version>${project.version}</ccsdk.project.version>
<ccsdk.build.timestamp>${maven.build.timestamp}</ccsdk.build.timestamp>
<maven.build.timestamp.format>yyyyMMdd'T'HHmmss'Z'</maven.build.timestamp.format>
+ <sonar.skip>true</sonar.skip>
</properties>
<build>
diff --git a/ms/py-executor/resource_resolution/README b/ms/py-executor/resource_resolution/README
index 222dae499..353600445 100644
--- a/ms/py-executor/resource_resolution/README
+++ b/ms/py-executor/resource_resolution/README
@@ -77,4 +77,67 @@ if __name__ == "__main__":
for response in client.process(generate_messages()):
print(response)
+```
+
+### Authorizarion header
+
+```
+from proto.BluePrintCommon_pb2 import ActionIdentifiers, CommonHeader
+from proto.BluePrintProcessing_pb2 import ExecutionServiceInput
+from resource_resolution.client import Client as ResourceResolutionClient
+
+
+def generate_messages():
+ commonHeader = CommonHeader()
+ commonHeader.requestId = "1234"
+ commonHeader.subRequestId = "1234-1"
+ commonHeader.originatorId = "CDS"
+
+ actionIdentifiers = ActionIdentifiers()
+ actionIdentifiers.blueprintName = "sample-cba"
+ actionIdentifiers.blueprintVersion = "1.0.0"
+ actionIdentifiers.actionName = "SampleScript"
+
+ input = ExecutionServiceInput(commonHeader=commonHeader, actionIdentifiers=actionIdentifiers)
+
+ commonHeader2 = CommonHeader()
+ commonHeader2.requestId = "1235"
+ commonHeader2.subRequestId = "1234-2"
+ commonHeader2.originatorId = "CDS"
+
+ input2 = ExecutionServiceInput(commonHeader=commonHeader2, actionIdentifiers=actionIdentifiers)
+
+ yield from [input, input2]
+
+
+if __name__ == "__main__":
+ with ResourceResolutionClient("127.0.0.1:9111", use_header_auth=True, header_auth_token="Token test") as client:
+ for response in client.process(generate_messages()):
+ print(response)
+
+```
+
+# ResourceResoulution helper class
+
+## How to use examples
+
+### Insecure channel
+
+```
+from resource_resolution.resource_resolution import ResourceResolution, WorkflowExecution, WorkflowExecutionResult
+
+
+if __name__ == "__main__":
+ with ResourceResolution(use_header_auth=True, header_auth_token="Basic token") as rr:
+ for response in rr.execute_workflows( # type: WorkflowExecutionResult
+ WorkflowExecution(
+ blueprint_name="blueprintName",
+ blueprint_version="1.0",
+ workflow_name="resource-assignment"
+ )
+ ):
+ if response.has_error:
+ print(response.error_message)
+ else:
+ print(response.payload)
``` \ No newline at end of file
diff --git a/ms/py-executor/resource_resolution/authorization.py b/ms/py-executor/resource_resolution/authorization.py
new file mode 100644
index 000000000..ae5954ecc
--- /dev/null
+++ b/ms/py-executor/resource_resolution/authorization.py
@@ -0,0 +1,64 @@
+"""Copyright 2020 Deutsche Telekom.
+
+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.
+"""
+from collections import namedtuple
+from typing import Any, Callable, List
+
+from grpc import ClientCallDetails, StreamStreamClientInterceptor
+
+
+class NewClientCallDetails(
+ namedtuple("_ClientCallDetails", ("method", "timeout", "metadata", "credentials")), ClientCallDetails
+):
+ """Namedtuple class to store metadata.
+
+ It's impossible to change original metadata in ClientCallDetails object
+ passed as a parameter to intercept method, so this class is going to get
+ original metadata tuple and add the authorization one.
+ """
+
+ pass
+
+
+class AuthTokenInterceptor(StreamStreamClientInterceptor):
+ """Interceptor class to set authorization header.
+
+ Set authorization header (but it can be any header also) for a gRPC call.
+ """
+
+ def __init__(self, token: str, header: str = "authorization") -> None:
+ """Initialize interceptor.
+
+ Set token and header which should be set into call. By default header is "authorization".
+ Header have to be lowercase.
+
+ Args:
+ token (str): Token value to be set.
+ header (str, optional): Header name. It must be lowercase. Defaults to "authorization".
+ """
+ self.token: str = token
+ if not header.islower():
+ raise ValueError("Header must be lowercase.")
+ self.header: str = header
+
+ def intercept_stream_stream(
+ self, continuation: Callable, client_call_details: ClientCallDetails, request_iterator: Any
+ ) -> Any:
+ """Add header into metadata."""
+ metadata: List = list(client_call_details.metadata) if client_call_details.metadata is not None else []
+ metadata.append((self.header, self.token,))
+ new_client_call_details: NewClientCallDetails = NewClientCallDetails(
+ client_call_details.method, client_call_details.timeout, metadata, client_call_details.credentials
+ )
+ return continuation(new_client_call_details, request_iterator)
diff --git a/ms/py-executor/resource_resolution/client.py b/ms/py-executor/resource_resolution/client.py
index 89087745c..fee168628 100644
--- a/ms/py-executor/resource_resolution/client.py
+++ b/ms/py-executor/resource_resolution/client.py
@@ -14,12 +14,20 @@ limitations under the License.
"""
from logging import Logger, getLogger
from types import TracebackType
-from typing import Iterable, List, Optional, Type
-
-from grpc import Channel, insecure_channel, secure_channel, ssl_channel_credentials
+from typing import Iterable, Optional, Type
+
+from grpc import (
+ Channel,
+ insecure_channel,
+ intercept_channel,
+ secure_channel,
+ ssl_channel_credentials,
+)
from proto.BluePrintProcessing_pb2 import ExecutionServiceInput, ExecutionServiceOutput
from proto.BluePrintProcessing_pb2_grpc import BluePrintProcessingServiceStub
+from .authorization import AuthTokenInterceptor
+
class Client:
"""Resource resoulution client class."""
@@ -28,20 +36,29 @@ class Client:
self,
server_address: str,
*,
+ # TLS/SSL configuration
use_ssl: bool = False,
root_certificates: bytes = None,
private_key: bytes = None,
certificate_chain: bytes = None,
+ # Authentication header configuration
+ use_header_auth: bool = False,
+ header_auth_token: str = None,
) -> None:
"""Client class initialization.
:param server_address: Address to server to connect.
:param use_ssl: Boolean flag to determine if secure channel should be created or not. Keyword argument.
:param root_certificates: The PEM-encoded root certificates. None if it shouldn't be used. Keyword argument.
- :param private_key: The PEM-encoded private key as a byte string, or None if no private key should be used. Keyword argument.
- :param certificate_chain: The PEM-encoded certificate chain as a byte string to use or or None if no certificate chain should be used. Keyword argument.
+ :param private_key: The PEM-encoded private key as a byte string, or None if no private key should be used.
+ Keyword argument.
+ :param certificate_chain: The PEM-encoded certificate chain as a byte string to use or or None if
+ no certificate chain should be used. Keyword argument.
+ :param use_header_auth: Boolean flag to determine if authorization headed shoud be added for every call or not.
+ Keyword argument.
+ :param header_auth_token: Authorization token value. Keyword argument.
"""
- self.logger = getLogger(__name__)
+ self.logger: Logger = getLogger(__name__)
if use_ssl:
self.channel: Channel = secure_channel(
server_address, ssl_channel_credentials(root_certificates, private_key, certificate_chain)
@@ -50,6 +67,8 @@ class Client:
else:
self.channel: Channel = insecure_channel(server_address)
self.logger.debug(f"Create insecure channel to connect to {server_address}")
+ if use_header_auth:
+ self.channel: Channel = intercept_channel(self.channel, AuthTokenInterceptor(header_auth_token))
self.stub: BluePrintProcessingServiceStub = BluePrintProcessingServiceStub(self.channel)
def close(self) -> None:
diff --git a/ms/py-executor/resource_resolution/resource_resolution.py b/ms/py-executor/resource_resolution/resource_resolution.py
new file mode 100644
index 000000000..e4f162f8f
--- /dev/null
+++ b/ms/py-executor/resource_resolution/resource_resolution.py
@@ -0,0 +1,294 @@
+"""Copyright 2020 Deutsche Telekom.
+
+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.
+"""
+
+from enum import Enum, unique
+from logging import Logger, getLogger
+from types import TracebackType
+from typing import Any, Dict, Generator, Optional, Type
+
+from google.protobuf import json_format
+
+from proto.BluePrintProcessing_pb2 import ExecutionServiceInput, ExecutionServiceOutput
+
+from .client import Client
+
+
+@unique
+class WorkflowMode(Enum):
+ """Workflow mode enumerator.
+
+ Workflow can be executed in two modes: synchronously and asynchronously.
+ This enumerator stores valid values to set the mode: SYNC for synchronously mode and ASYNC for asynchronously.
+ """
+
+ SYNC = "sync"
+ ASYNC = "async"
+
+
+class WorkflowExecution:
+ """Wokflow execution class.
+
+ Describes workflow to call. Set blueprint name and version and workflow name to execute.
+ Workflow inputs are optional, by default set to empty directory.
+ Workflow mode is also optional. It is set by default to call workflow synchronously.
+ """
+
+ def __init__(
+ self,
+ blueprint_name: str,
+ blueprint_version: str,
+ workflow_name: str,
+ workflow_inputs: Dict[str, Any] = None,
+ workflow_mode: WorkflowMode = WorkflowMode.SYNC,
+ ) -> None:
+ """Initialize workflow execution.
+
+ Get all needed information to execute workflow.
+
+ Args:
+ blueprint_name (str): Blueprint name to execute workflow from.
+ blueprint_version (str): Blueprint version.
+ workflow_name (str): Name of the workflow to execute
+ workflow_inputs (Dict[str, Any], optional): Key-value workflow inputs. Defaults to None.
+ workflow_mode (WorkflowMode, optional): Workflow execution mode. It can be run synchronously or
+ asynchronously. Defaults to WorkflowMode.SYNC.
+ """
+ self.blueprint_name: str = blueprint_name
+ self.blueprint_version: str = blueprint_version
+ self.workflow_name: str = workflow_name
+ if workflow_inputs is None:
+ workflow_inputs = {}
+ self.workflow_inputs: Dict[str, Any] = workflow_inputs
+ self.workflow_mode: WorkflowMode = workflow_mode
+
+ @property
+ def message(self) -> ExecutionServiceInput:
+ """Workflow execution protobuf message.
+
+ This message is going to be sent to gRPC server to execute workflow.
+
+ Returns:
+ ExecutionServiceInput: Properly filled protobuf message.
+ """
+ execution_msg: ExecutionServiceInput = ExecutionServiceInput()
+ execution_msg.actionIdentifiers.mode = self.workflow_mode.value
+ execution_msg.actionIdentifiers.blueprintName = self.blueprint_name
+ execution_msg.actionIdentifiers.blueprintVersion = self.blueprint_version
+ execution_msg.actionIdentifiers.actionName = self.workflow_name
+ execution_msg.payload.update({f"{self.workflow_name}-request": self.workflow_inputs})
+ return execution_msg
+
+
+class WorkflowExecutionResult:
+ """Result of workflow execution.
+
+ Store both workflow data and the result returns by server.
+ """
+
+ def __init__(self, workflow_execution: WorkflowExecution, execution_output: ExecutionServiceOutput) -> None:
+ """Initialize workflow execution result object.
+
+ Stores workflow execution data and execution result.
+
+ Args:
+ workflow_execution (WorkflowExecution): WorkflowExecution object which was used to call request.
+ execution_output (ExecutionServiceOutput): gRPC server response.
+ """
+ self.workflow_execution: WorkflowExecution = workflow_execution
+ self.execution_output: ExecutionServiceOutput = execution_output
+
+ @property
+ def blueprint_name(self) -> str:
+ """Name of blueprint used to call workflow.
+
+ This value is taken from server response not request (should be the same).
+
+ Returns:
+ str: Blueprint name
+ """
+ return self.execution_output.actionIdentifiers.blueprintName
+
+ @property
+ def blueprint_version(self) -> str:
+ """Blueprint version.
+
+ This value is taken from server response not request (should be the same).
+
+ Returns:
+ str: Blueprint version
+ """
+ return self.execution_output.actionIdentifiers.blueprintVersion
+
+ @property
+ def workflow_name(self) -> str:
+ """Workflow name.
+
+ This value is taken from server response not request (should be the same).
+
+ Returns:
+ str: Workflow name
+ """
+ return self.execution_output.actionIdentifiers.actionName
+
+ @property
+ def has_error(self) -> bool:
+ """Returns bool if request returns error or not.
+
+ Returns:
+ bool: True if response has status code different than 200
+ """
+ return self.execution_output.status.code != 200
+
+ @property
+ def error_message(self) -> str:
+ """Error message.
+
+ This property is available only if response has error. Otherwise AttributeError will be raised.
+
+ Raises:
+ AttributeError: Response has 200 response code and hasn't error message.
+
+ Returns:
+ str: Error message returned by server
+ """
+ if self.has_error:
+ return self.execution_output.status.errorMessage
+ raise AttributeError("Execution does not finish with error")
+
+ @property
+ def payload(self) -> dict:
+ """Response payload.
+
+ Payload retured by the server is migrated to Python dict.
+
+ Returns:
+ dict: Response's payload.
+ """
+ return json_format.MessageToDict(self.execution_output.payload)
+
+
+class ResourceResolution:
+ """Resource resolution class.
+
+ Helper class to connect to blueprintprocessor's gRPC server, send request to execute workflow and parse responses.
+ Blueprint with workflow must be deployed before workflow request.
+ It's possible to create both secre or unsecure connection (without SSL/TLS).
+ """
+
+ def __init__(
+ self,
+ *,
+ server_address: str = "127.0.0.1",
+ server_port: int = "9111",
+ use_ssl: bool = False,
+ root_certificates: bytes = None,
+ private_key: bytes = None,
+ certificate_chain: bytes = None,
+ # Authentication header configuration
+ use_header_auth: bool = False,
+ header_auth_token: str = None,
+ ) -> None:
+ """Resource resolution object initialization.
+
+ Args:
+ server_address (str, optional): gRPC server address. Defaults to "127.0.0.1".
+ server_port (int, optional): gRPC server address port. Defaults to "9111".
+ use_ssl (bool, optional): Boolean flag to determine if secure channel should be created or not.
+ Defaults to False.
+ root_certificates (bytes, optional): The PEM-encoded root certificates. None if it shouldn't be used.
+ Defaults to None.
+ private_key (bytes, optional): The PEM-encoded private key as a byte string, or None if no private key
+ should be used. Defaults to None.
+ certificate_chain (bytes, optional): The PEM-encoded certificate chain as a byte string to use or or None if
+ no certificate chain should be used. Defaults to None.
+ use_header_auth (bool, optional): Boolean flag to determine if authorization headed shoud be added for
+ every call or not. Defaults to False.
+ header_auth_token (str, optional): Authorization token value. Defaults to None.
+ """
+ # Logger
+ self.logger: Logger = getLogger(__name__)
+ # Client settings
+ self.client_server_address: str = server_address
+ self.client_server_port: str = server_port
+ self.client_use_ssl: bool = use_ssl
+ self.client_root_certificates: bytes = root_certificates
+ self.client_private_key: bytes = private_key
+ self.client_certificate_chain: bytes = certificate_chain
+ self.client_use_header_auth: bool = use_header_auth
+ self.client_header_auth_token: str = header_auth_token
+ self.client: Client = None
+
+ def __enter__(self) -> "ResourceResolution":
+ """Enter ResourceResolution instance context.
+
+ Client connection is created.
+ """
+ self.client = Client(
+ server_address=f"{self.client_server_address}:{self.client_server_port}",
+ use_ssl=self.client_use_ssl,
+ root_certificates=self.client_root_certificates,
+ private_key=self.client_private_key,
+ certificate_chain=self.client_certificate_chain,
+ use_header_auth=self.client_use_header_auth,
+ header_auth_token=self.client_header_auth_token,
+ )
+ return self
+
+ def __exit__(
+ self,
+ unused_exc_type: Optional[Type[BaseException]],
+ unused_exc_value: Optional[BaseException],
+ unused_traceback: Optional[TracebackType],
+ ) -> None:
+ """Exit ResourceResolution instance context.
+
+ Client connection is closed.
+ """
+ self.client.close()
+
+ def execute_workflows(self, *workflows: WorkflowExecution) -> Generator[WorkflowExecutionResult, None, None]:
+ """Execute provided workflows.
+
+ Workflows are going to be execured using one gRPC API call. Depends of implementation that may has
+ some consequences. In some cases if any request fails all requests after that won't be called.
+
+ Responses and zipped with workflows and WorkflowExecutionResult object is initialized and yielded.
+
+ Raises:
+ AttributeError: Raises if client object is not created. It occurs only if you not uses context manager.
+ Then user have to create client instance for ResourceResolution object by himself calling:
+ ```
+ resource_resoulution.client = Client(
+ server_address=f"{resource_resoulution.client_server_address}:{resource_resoulution.client_server_port}",
+ use_ssl=resource_resoulution.client_use_ssl,
+ root_certificates=resource_resoulution.client_root_certificates,
+ private_key=resource_resoulution.client_private_key,
+ certificate_chain=resource_resoulution.client_certificate_chain,
+ use_header_auth=resource_resoulution.client_use_header_auth,
+ header_auth_token=resource_resoulution.client_header_auth_token,
+ )
+ ```
+ Remeber also to close client connection.
+
+ Returns:
+ Generator[WorkflowExecutionResult, None, None]: WorkflowExecutionResult object
+ with both WorkflowExection object and server response for it's request.
+ """
+ self.logger.debug("Execute workflows")
+ if not self.client:
+ raise AttributeError("gRPC client not connected")
+
+ for response, workflow in zip(self.client.process((workflow.message for workflow in workflows)), workflows):
+ yield WorkflowExecutionResult(workflow, response)
diff --git a/ms/py-executor/resource_resolution/tests/authorization_interceptor_test.py b/ms/py-executor/resource_resolution/tests/authorization_interceptor_test.py
new file mode 100644
index 000000000..4b03f0b36
--- /dev/null
+++ b/ms/py-executor/resource_resolution/tests/authorization_interceptor_test.py
@@ -0,0 +1,50 @@
+"""Copyright 2020 Deutsche Telekom.
+
+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.
+"""
+
+from unittest.mock import MagicMock, _Call
+
+import pytest
+
+from resource_resolution.authorization import AuthTokenInterceptor, NewClientCallDetails
+
+
+def test_resource_resolution_auth_token_interceptor():
+ """Test AuthTokenInterceptor class.
+
+ - Checks if it's correctly set default value.
+ - Checks if it's correctly set passed values.
+ - Checks if it's correctly checked if all header characters are lowercase.
+ - Checks if continuation function is called with headers setted
+ """
+ interceptor: AuthTokenInterceptor = AuthTokenInterceptor("test_token", header="header")
+ assert interceptor.token == "test_token"
+ assert interceptor.header == "header"
+
+ interceptor: AuthTokenInterceptor = AuthTokenInterceptor("test_token")
+ assert interceptor.token == "test_token"
+ assert interceptor.header == "authorization"
+
+ with pytest.raises(ValueError):
+ AuthTokenInterceptor("test_token", header="Auth")
+
+ continuation_mock: MagicMock = MagicMock()
+ client_call_details: MagicMock = MagicMock()
+ request_iterator: MagicMock = MagicMock()
+
+ interceptor.intercept_stream_stream(continuation_mock, client_call_details, request_iterator)
+ continuation_mock.assert_called_once()
+ client_call_details_argument: _Call = continuation_mock.call_args_list[0][0][0] # Get NewClientCallDetails instance
+ assert isinstance(client_call_details_argument, NewClientCallDetails)
+ assert client_call_details_argument.metadata[0] == (interceptor.header, interceptor.token)
diff --git a/ms/py-executor/resource_resolution/tests/resource_resolution_test.py b/ms/py-executor/resource_resolution/tests/resource_resolution_test.py
new file mode 100644
index 000000000..8a41357e6
--- /dev/null
+++ b/ms/py-executor/resource_resolution/tests/resource_resolution_test.py
@@ -0,0 +1,105 @@
+"""Copyright 2020 Deutsche Telekom.
+
+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.
+"""
+
+from google.protobuf import json_format
+from pytest import raises
+
+from resource_resolution.resource_resolution import (
+ ExecutionServiceInput,
+ ExecutionServiceOutput,
+ WorkflowExecution,
+ WorkflowExecutionResult,
+ WorkflowMode,
+)
+
+
+def test_workflow_execution_class():
+ """Workflow execution class tests.
+
+ - Test initialization and default values
+ - Test request message formatting
+ """
+ # Without inputs
+ workflow_execution: WorkflowExecution = WorkflowExecution("test blueprint", "test version", "test workflow")
+ assert workflow_execution.blueprint_name == "test blueprint"
+ assert workflow_execution.blueprint_version == "test version"
+ assert workflow_execution.workflow_name == "test workflow"
+ assert workflow_execution.workflow_inputs == {}
+ assert workflow_execution.workflow_mode == WorkflowMode.SYNC
+
+ msg: ExecutionServiceInput = workflow_execution.message
+ msg_dict: dict = json_format.MessageToDict(msg)
+ assert msg_dict["actionIdentifiers"]["blueprintName"] == "test blueprint"
+ assert msg_dict["actionIdentifiers"]["blueprintVersion"] == "test version"
+ assert msg_dict["actionIdentifiers"]["actionName"] == "test workflow"
+ assert msg_dict["actionIdentifiers"]["mode"] == "sync"
+ assert list(msg_dict["payload"].keys())[0] == "test workflow-request"
+ assert msg_dict["payload"]["test workflow-request"] == {}
+
+ # With inputs
+ workflow_execution: WorkflowExecution = WorkflowExecution(
+ "test blueprint2",
+ "test version2",
+ "test workflow2",
+ workflow_inputs={"test": "test"},
+ workflow_mode=WorkflowMode.ASYNC,
+ )
+ assert workflow_execution.blueprint_name == "test blueprint2"
+ assert workflow_execution.blueprint_version == "test version2"
+ assert workflow_execution.workflow_name == "test workflow2"
+ assert workflow_execution.workflow_inputs == {"test": "test"}
+ assert workflow_execution.workflow_mode == WorkflowMode.ASYNC
+
+ msg: ExecutionServiceInput = workflow_execution.message
+ msg_dict: dict = json_format.MessageToDict(msg)
+ assert msg_dict["actionIdentifiers"]["blueprintName"] == "test blueprint2"
+ assert msg_dict["actionIdentifiers"]["blueprintVersion"] == "test version2"
+ assert msg_dict["actionIdentifiers"]["actionName"] == "test workflow2"
+ assert msg_dict["actionIdentifiers"]["mode"] == "async"
+ assert list(msg_dict["payload"].keys())[0] == "test workflow2-request"
+ assert msg_dict["payload"]["test workflow2-request"] == {"test": "test"}
+
+
+def test_workflow_execution_result_class():
+ """Workflow execution result class tests.
+
+ - Test initizalization and default values
+ - Test `has_error` property
+ - Test `error_message` property
+ - Test payload formatting
+ """
+ workflow_execution: WorkflowExecution = WorkflowExecution("test blueprint", "test version", "test workflow")
+ execution_output: ExecutionServiceOutput = ExecutionServiceOutput()
+ execution_output.actionIdentifiers.blueprintName = "test blueprint"
+ execution_output.actionIdentifiers.blueprintVersion = "test version"
+ execution_output.actionIdentifiers.actionName = "test workflow"
+ execution_output.status.code = 200
+
+ execution_result: WorkflowExecutionResult = WorkflowExecutionResult(workflow_execution, execution_output)
+ assert not execution_result.has_error
+ with raises(AttributeError):
+ execution_result.error_message
+ assert execution_result.payload == {}
+ assert execution_result.blueprint_name == "test blueprint"
+ assert execution_result.blueprint_version == "test version"
+ assert execution_result.workflow_name == "test workflow"
+
+ execution_output.payload.update({"test_key": "test_value"})
+ execution_result: WorkflowExecutionResult = WorkflowExecutionResult(workflow_execution, execution_output)
+ assert execution_result.payload == {"test_key": "test_value"}
+
+ execution_output.status.code = 500
+ assert execution_result.has_error
+ assert execution_result.error_message == ""
diff --git a/ms/sdclistener/application/pom.xml b/ms/sdclistener/application/pom.xml
index 88d8d1b2f..72f552cdd 100644
--- a/ms/sdclistener/application/pom.xml
+++ b/ms/sdclistener/application/pom.xml
@@ -63,7 +63,6 @@
<dependency>
<groupId>org.onap.sdc.sdc-distribution-client</groupId>
<artifactId>sdc-distribution-client</artifactId>
- <version>1.3.0</version>
</dependency>
<dependency>
@@ -112,6 +111,11 @@
</dependency>
<dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-classic</artifactId>
+ </dependency>
+
+ <dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-core</artifactId>
<scope>compile</scope>
diff --git a/ms/sdclistener/application/src/main/resources/application.yaml b/ms/sdclistener/application/src/main/resources/application.yaml
index 424f0a5c0..d07d8ae61 100644
--- a/ms/sdclistener/application/src/main/resources/application.yaml
+++ b/ms/sdclistener/application/src/main/resources/application.yaml
@@ -2,7 +2,7 @@ listenerservice:
config:
asdcAddress: ${asdcAddress:localhost:8443}
messageBusAddress: ${messageBusAddress:localhost}
- user: ${sdcusername:vid}
+ user: ${sdcusername:cds}
password: ${password:Kp8bJ4SXszM0WXlhak3eHlcse2gAw84vaoGGmJvUy2U}
pollingInterval: ${pollingInterval:15}
pollingTimeout: ${pollingTimeout:60}
diff --git a/ms/sdclistener/application/src/test/java/org/onap/ccsdk/cds/sdclistener/SdcListenerConfigurationTest.java b/ms/sdclistener/application/src/test/java/org/onap/ccsdk/cds/sdclistener/SdcListenerConfigurationTest.java
index 26757a657..8275bc084 100644
--- a/ms/sdclistener/application/src/test/java/org/onap/ccsdk/cds/sdclistener/SdcListenerConfigurationTest.java
+++ b/ms/sdclistener/application/src/test/java/org/onap/ccsdk/cds/sdclistener/SdcListenerConfigurationTest.java
@@ -37,7 +37,7 @@ public class SdcListenerConfigurationTest {
public void testCdsSdcListenerConfiguration() {
assertEquals(listenerConfiguration.getAsdcAddress(), "localhost:8443");
assertEquals(listenerConfiguration.getMsgBusAddress().stream().findFirst().get(), "localhost");
- assertEquals(listenerConfiguration.getUser(), "vid");
+ assertEquals(listenerConfiguration.getUser(), "cds");
assertEquals(listenerConfiguration.getPassword(), "Kp8bJ4SXszM0WXlhak3eHlcse2gAw84vaoGGmJvUy2U");
assertEquals(listenerConfiguration.getPollingInterval(), 15);
assertEquals(listenerConfiguration.getPollingTimeout(), 60);
diff --git a/ms/sdclistener/parent/pom.xml b/ms/sdclistener/parent/pom.xml
index eaa1d60f4..2cbc79dcc 100755
--- a/ms/sdclistener/parent/pom.xml
+++ b/ms/sdclistener/parent/pom.xml
@@ -40,7 +40,7 @@
<mockk.version>1.9</mockk.version>
<dmaap.client.version>1.1.5</dmaap.client.version>
<mockkserver.version>5.5.1</mockkserver.version>
- <sdc-distribution-client.version>1.3.0</sdc-distribution-client.version>
+ <sdc-distribution-client.version>1.4.0</sdc-distribution-client.version>
<jmockit.version>1.19</jmockit.version>
<reactorcore.version>3.2.6.RELEASE</reactorcore.version>
</properties>
diff --git a/pom.xml b/pom.xml
index 65de1c54a..da7368259 100644
--- a/pom.xml
+++ b/pom.xml
@@ -22,7 +22,7 @@ limitations under the License.
<parent>
<groupId>org.onap.ccsdk.parent</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
- <version>1.5.2-SNAPSHOT</version>
+ <version>1.5.2</version>
<relativePath/>
</parent>
@@ -111,8 +111,7 @@ limitations under the License.
<phase>validate</phase>
<configuration>
<target name="ktlint">
- <java taskname="ktlint" dir="${project.basedir}" fork="true" failonerror="true"
- classname="com.pinterest.ktlint.Main" classpathref="maven.plugin.classpath">
+ <java taskname="ktlint" dir="${project.basedir}" fork="true" failonerror="true" classname="com.pinterest.ktlint.Main" classpathref="maven.plugin.classpath">
<arg value="src/**/*.kt"/>
</java>
</target>
@@ -128,8 +127,7 @@ limitations under the License.
<phase>process-sources</phase>
<configuration>
<target name="ktlint">
- <java taskname="ktlint" dir="${project.basedir}" fork="true" failonerror="true"
- classname="com.pinterest.ktlint.Main" classpathref="maven.plugin.classpath">
+ <java taskname="ktlint" dir="${project.basedir}" fork="true" failonerror="true" classname="com.pinterest.ktlint.Main" classpathref="maven.plugin.classpath">
<arg value="-F"/>
<arg value="src/**/*.kt"/>
</java>