From 14f6f95c84a4a1fa8774190db4a03fd0214ec55f Mon Sep 17 00:00:00 2001 From: Rohan Patel Date: Wed, 25 Sep 2019 14:35:28 -0400 Subject: [PATCH] added svcapi ui and camunda code Signed-off-by: Rohan Patel Change-Id: I197b4b40fe3d047a417479214e471ae26d51fb2b --- otf-camunda/.gitignore | 34 + otf-camunda/Jenkinsfile | 197 +++++ otf-camunda/LICENSE.txt | 28 + otf-camunda/docker/Dockerfile | 34 + otf-camunda/helm/forceDelete.sh | 11 + otf-camunda/helm/otf-camunda/Chart.yaml | 5 + .../helm/otf-camunda/mysqlRouterConfig-dev.ini | 9 + .../helm/otf-camunda/mysqlRouterConfig-prod.ini | 9 + .../helm/otf-camunda/mysqlRouterConfig-st.ini | 9 + otf-camunda/helm/otf-camunda/templates/config.yaml | 13 + .../helm/otf-camunda/templates/deployment.yaml | 314 ++++++++ otf-camunda/helm/otf-camunda/templates/secret.yaml | 10 + .../helm/otf-camunda/templates/service.yaml | 18 + otf-camunda/helm/otf-camunda/values.yaml | 86 +++ otf-camunda/mvnw | 225 ++++++ otf-camunda/mvnw.cmd | 143 ++++ otf-camunda/pom.xml | 413 +++++++++++ .../src/main/java/org/oran/otf/Application.java | 100 +++ .../configuration/CadiFilterConfiguration.java | 97 +++ .../otf/cadi/configuration/FilterCondition.java | 33 + .../OTFApiEnforcementFilterConfiguration.java | 67 ++ .../otf/cadi/filter/OTFApiEnforcementFilter.java | 134 ++++ .../OTFAuthorizationConfiguration.java | 21 + .../configuration/OTFDataSourceConfiguration.java | 63 ++ .../configuration/OTFDeploymentConfiguration.java | 21 + .../configuration/OTFFailedJobConfiguration.java | 21 + .../configuration/OTFJacksonDataConfigurator.java | 43 ++ .../camunda/configuration/OTFJobConfiguration.java | 73 ++ .../camunda/configuration/OTFLoggingFeature.java | 238 ++++++ .../configuration/OtfCamundaConfiguration.java | 155 ++++ .../OTFJobExecutorStartingEventListener.java | 44 ++ .../delegate/otf/common/CallTestHeadDelegate.java | 329 ++++++++ .../delegate/otf/common/LogTestResultDelegate.java | 114 +++ .../otf/common/PostResultsToDMaaPDelegate.java | 159 ++++ .../otf/common/RunTestInstanceDelegate.java | 180 +++++ .../delegate/otf/common/SendMailDelegate.java | 170 +++++ .../runnable/AsynchronousTestInstanceCallable.java | 199 +++++ .../runnable/SynchronousTestInstanceCallable.java | 227 ++++++ .../otf/common/runnable/TestHeadCallable.java | 267 +++++++ .../camunda/exception/TestExecutionException.java | 32 + .../otf/camunda/exception/WorkflowException.java | 95 +++ .../exception/WorkflowProcessorException.java | 32 + .../otf/camunda/listener/EndEventListener.java | 60 ++ .../otf/camunda/listener/StartEventListener.java | 97 +++ .../otf/camunda/listener/TaskEndEventListener.java | 83 +++ .../oran/otf/camunda/model/ExecutionConstants.java | 56 ++ .../oran/otf/camunda/model/WorkflowResponse.java | 88 +++ .../camunda/plugin/OtfIncidentHandlerPlugin.java | 54 ++ .../oran/otf/camunda/service/CamundaShutdown.java | 143 ++++ .../camunda/service/OtfExternalTaskService.java | 195 +++++ .../service/OtfWorkflowTaskCleanupService.java | 75 ++ .../camunda/service/ProcessEngineAwareService.java | 68 ++ .../otf/camunda/workflow/WorkflowProcessor.java | 526 +++++++++++++ .../oran/otf/camunda/workflow/WorkflowRequest.java | 182 +++++ .../handler/ExternalTaskIncidentHandler.java | 139 ++++ .../workflow/handler/FailedJobIncidentHandler.java | 145 ++++ .../workflow/utility/RsaEncryptDecrypt.java | 55 ++ .../otf/camunda/workflow/utility/WorkflowTask.java | 169 +++++ .../camunda/workflow/utility/WorkflowUtility.java | 291 ++++++++ .../main/java/org/oran/otf/common/model/Group.java | 109 +++ .../org/oran/otf/common/model/GroupMember.java | 42 ++ .../main/java/org/oran/otf/common/model/Role.java | 41 + .../org/oran/otf/common/model/TestDefinition.java | 138 ++++ .../org/oran/otf/common/model/TestExecution.java | 235 ++++++ .../java/org/oran/otf/common/model/TestHead.java | 224 ++++++ .../org/oran/otf/common/model/TestInstance.java | 259 +++++++ .../main/java/org/oran/otf/common/model/User.java | 139 ++++ .../model/historic/TestDefinitionHistoric.java | 188 +++++ .../model/historic/TestInstanceHistoric.java | 234 ++++++ .../oran/otf/common/model/local/BpmnInstance.java | 187 +++++ .../oran/otf/common/model/local/DMaaPRequest.java | 69 ++ .../otf/common/model/local/OTFApiResponse.java | 66 ++ .../common/model/local/OTFDeploymentResponse.java | 67 ++ .../OTFProcessInstanceCompletionResponse.java | 166 +++++ .../otf/common/model/local/ParallelFlowInput.java | 91 +++ .../org/oran/otf/common/model/local/PfloNode.java | 62 ++ .../oran/otf/common/model/local/TestHeadNode.java | 58 ++ .../otf/common/model/local/TestHeadRequest.java | 53 ++ .../otf/common/model/local/TestHeadResult.java | 145 ++++ .../org/oran/otf/common/model/local/UserGroup.java | 56 ++ .../otf/common/repository/GroupRepository.java | 29 + .../repository/TestDefinitionRepository.java | 25 + .../common/repository/TestExecutionRepository.java | 25 + .../otf/common/repository/TestHeadRepository.java | 24 + .../common/repository/TestInstanceRepository.java | 35 + .../oran/otf/common/repository/UserRepository.java | 25 + .../java/org/oran/otf/common/utility/Utility.java | 70 ++ .../oran/otf/common/utility/database/Generic.java | 36 + .../utility/database/TestExecutionUtility.java | 35 + .../org/oran/otf/common/utility/gson/Convert.java | 121 +++ .../otf/common/utility/http/HeadersUtility.java | 42 ++ .../otf/common/utility/http/RequestUtility.java | 195 +++++ .../otf/common/utility/http/ResponseUtility.java | 107 +++ .../oran/otf/common/utility/logger/ErrorCode.java | 36 + .../utility/logger/LoggerStartupListener.java | 91 +++ .../otf/common/utility/logger/MessageEnum.java | 35 + .../utility/permissions/PermissionChecker.java | 57 ++ .../common/utility/permissions/PermissionUtil.java | 238 ++++++ .../common/utility/permissions/UserPermission.java | 58 ++ .../oran/otf/common/utility/sftp/SftpUtility.java | 94 +++ .../otf/event/TestInstanceCompletionEvent.java | 49 ++ .../oran/otf/event/TestInstanceIncidentEvent.java | 59 ++ .../otf/service/DeleteProcessInstanceService.java | 34 + .../otf/service/DeleteTestDefinitionService.java | 48 ++ .../org/oran/otf/service/DeveloperService.java | 80 ++ .../java/org/oran/otf/service/HealthService.java | 35 + .../service/ProcessInstanceCompletionService.java | 37 + .../oran/otf/service/TestControlUnitService.java | 47 ++ .../service/TestDefinitionDeploymentService.java | 46 ++ .../impl/DeleteProcessInstanceServiceImpl.java | 96 +++ .../impl/DeleteTestDefinitionServiceImpl.java | 119 +++ .../otf/service/impl/DeveloperServiceImpl.java | 161 ++++ .../oran/otf/service/impl/HealthServiceImpl.java | 39 + .../impl/ProcessInstanceCompletionServiceImpl.java | 119 +++ .../service/impl/TestControlUnitServiceImpl.java | 119 +++ .../impl/TestDefinitionDeploymentServiceImpl.java | 134 ++++ .../configuration/HttpSecurityConfiguration.java | 66 ++ .../spring/configuration/JerseyConfiguration.java | 83 +++ .../spring/configuration/OTFLoggingFeature.java | 242 ++++++ .../configuration/OTFMongoConfiguration.java | 78 ++ .../src/main/resources/META-INF/processes.xml.off | 13 + .../resources/META-INF/securityFilterRules.json | 52 ++ otf-camunda/src/main/resources/application.yaml | 108 +++ otf-camunda/src/main/resources/banner.txt | 12 + .../src/main/resources/bpmn/pingGoogleDNS.bpmn | 89 +++ .../src/main/resources/mail-config.properties | 7 + .../org/oran/otf/api/tests/config/DataConfig.java | 21 + .../oran/otf/api/tests/config/InMemoryConfig.java | 21 + .../oran/otf/api/tests/shared/MemoryDatabase.java | 21 + .../common/utility/http/HeadersUtilityTest.java | 74 ++ .../src/test/resources/application-test.properties | 0 otf-frontend/.dockerignore | 1 + otf-frontend/.gitignore | 121 +++ otf-frontend/Dockerfile | 31 + otf-frontend/Jenkinsfile | 153 ++++ otf-frontend/LICENSES.txt | 28 + otf-frontend/angular.json | 147 ++++ otf-frontend/client/.gitignore | 45 ++ otf-frontend/client/config/.editorconfig | 13 + otf-frontend/client/config/.travis.yml | 14 + otf-frontend/client/config/karma.conf.js | 50 ++ otf-frontend/client/config/protractor.conf.js | 28 + otf-frontend/client/config/tsconfig.json | 19 + otf-frontend/client/config/tslint.json | 139 ++++ otf-frontend/client/e2e/app.e2e-spec.ts | 14 + otf-frontend/client/e2e/app.po.ts | 11 + otf-frontend/client/e2e/tsconfig.e2e.json | 14 + .../access-denied/access-denied-routing.module.ts | 32 + .../app/access-denied/access-denied.component.html | 19 + .../app/access-denied/access-denied.component.scss | 16 + .../access-denied/access-denied.component.spec.ts | 41 + .../app/access-denied/access-denied.component.ts | 31 + .../app/access-denied/access-denied.module.spec.ts | 29 + .../src/app/access-denied/access-denied.module.ts | 30 + .../src/app/account/account-routing.module.ts | 32 + .../client/src/app/account/account.component.html | 25 + .../client/src/app/account/account.component.scss | 115 +++ .../src/app/account/account.component.spec.ts | 41 + .../client/src/app/account/account.component.ts | 60 ++ .../client/src/app/account/account.module.spec.ts | 29 + .../client/src/app/account/account.module.ts | 31 + otf-frontend/client/src/app/app-routing.module.ts | 39 + otf-frontend/client/src/app/app.component.html | 17 + otf-frontend/client/src/app/app.component.scss | 16 + otf-frontend/client/src/app/app.component.spec.ts | 47 ++ otf-frontend/client/src/app/app.component.ts | 35 + otf-frontend/client/src/app/app.global.ts | 23 + otf-frontend/client/src/app/app.module.spec.ts | 29 + otf-frontend/client/src/app/app.module.ts | 90 +++ .../client/src/app/core/core.module.spec.ts | 29 + otf-frontend/client/src/app/core/core.module.ts | 56 ++ otf-frontend/client/src/app/error.interceptor.ts | 41 + .../layout/components/header/header.component.html | 111 +++ .../layout/components/header/header.component.scss | 62 ++ .../components/header/header.component.spec.ts | 48 ++ .../layout/components/header/header.component.ts | 205 +++++ .../right-sidebar/right-sidebar.component.html | 26 + .../right-sidebar/right-sidebar.component.scss | 176 +++++ .../right-sidebar/right-sidebar.component.spec.ts | 41 + .../right-sidebar/right-sidebar.component.ts | 31 + .../components/sidebar/sidebar.component.html | 160 ++++ .../components/sidebar/sidebar.component.scss | 175 +++++ .../components/sidebar/sidebar.component.spec.ts | 48 ++ .../layout/components/sidebar/sidebar.component.ts | 147 ++++ .../stats/assets/icons/ProfessionalHeadshot(2).png | Bin 0 -> 529315 bytes .../components/stats/assets/icons/download.jfif | Bin 0 -> 4180 bytes .../components/stats/assets/icons/equalizer.gif | Bin 0 -> 90816 bytes .../components/stats/assets/icons/loading-pies.gif | Bin 0 -> 174423 bytes .../components/stats/assets/icons/loading-pies.svg | 1 + .../stats/filter-modal/filter-modal.component.pug | 139 ++++ .../stats/filter-modal/filter-modal.component.scss | 23 + .../filter-modal/filter-modal.component.spec.ts | 41 + .../stats/filter-modal/filter-modal.component.ts | 151 ++++ .../horiz-bar-chart/horiz-bar-chart.component.pug | 17 + .../horiz-bar-chart/horiz-bar-chart.component.scss | 16 + .../horiz-bar-chart.component.spec.ts | 41 + .../horiz-bar-chart/horiz-bar-chart.component.ts | 175 +++++ .../stats/line-chart/line-chart.component.pug | 17 + .../stats/line-chart/line-chart.component.scss | 16 + .../stats/line-chart/line-chart.component.spec.ts | 41 + .../stats/line-chart/line-chart.component.ts | 172 +++++ .../multi-line-chart.component.pug | 19 + .../multi-line-chart.component.scss | 16 + .../multi-line-chart.component.spec.ts | 41 + .../multi-line-chart/multi-line-chart.component.ts | 336 +++++++++ .../stats/pie-chart/pie-chart.component.pug | 17 + .../stats/pie-chart/pie-chart.component.scss | 16 + .../stats/pie-chart/pie-chart.component.spec.ts | 41 + .../stats/pie-chart/pie-chart.component.ts | 181 +++++ .../stats/schedule/schedule.component.pug | 34 + .../stats/schedule/schedule.component.scss | 28 + .../stats/schedule/schedule.component.spec.ts | 41 + .../stats/schedule/schedule.component.ts | 71 ++ .../layout/components/stats/stats.service.spec.ts | 28 + .../app/layout/components/stats/stats.service.ts | 765 +++++++++++++++++++ ...t-definition-executions-bar-chart.component.pug | 17 + ...-definition-executions-bar-chart.component.scss | 16 + ...finition-executions-bar-chart.component.spec.ts | 41 + ...st-definition-executions-bar-chart.component.ts | 198 +++++ .../test-head-execution-bar-chart.component.pug | 17 + .../test-head-execution-bar-chart.component.scss | 16 + ...test-head-execution-bar-chart.component.spec.ts | 41 + .../test-head-execution-bar-chart.component.ts | 236 ++++++ .../test-head-executions-line-chart.component.pug | 17 + .../test-head-executions-line-chart.component.scss | 16 + ...st-head-executions-line-chart.component.spec.ts | 41 + .../test-head-executions-line-chart.component.ts | 219 ++++++ .../control-panel/control-panel-routing.module.ts | 29 + .../control-panel/control-panel.component.pug | 270 +++++++ .../control-panel/control-panel.component.scss | 132 ++++ .../control-panel/control-panel.component.spec.ts | 41 + .../control-panel/control-panel.component.ts | 564 ++++++++++++++ .../control-panel/control-panel.module.spec.ts | 29 + .../layout/control-panel/control-panel.module.ts | 67 ++ .../layout/dashboard/dashboard-routing.module.ts | 31 + .../app/layout/dashboard/dashboard.component.pug | 115 +++ .../app/layout/dashboard/dashboard.component.scss | 82 ++ .../layout/dashboard/dashboard.component.spec.ts | 41 + .../app/layout/dashboard/dashboard.component.ts | 173 +++++ .../app/layout/dashboard/dashboard.module.spec.ts | 29 + .../src/app/layout/dashboard/dashboard.module.ts | 110 +++ .../app/layout/feedback/feedback-routing.module.ts | 30 + .../src/app/layout/feedback/feedback.component.pug | 45 ++ .../app/layout/feedback/feedback.component.scss | 17 + .../app/layout/feedback/feedback.component.spec.ts | 41 + .../src/app/layout/feedback/feedback.component.ts | 98 +++ .../app/layout/feedback/feedback.module.spec.ts | 29 + .../src/app/layout/feedback/feedback.module.ts | 49 ++ .../client/src/app/layout/layout-routing.module.ts | 51 ++ .../client/src/app/layout/layout.component.html | 21 + .../client/src/app/layout/layout.component.scss | 37 + .../client/src/app/layout/layout.component.spec.ts | 55 ++ .../client/src/app/layout/layout.component.ts | 28 + .../client/src/app/layout/layout.module.spec.ts | 29 + .../client/src/app/layout/layout.module.ts | 49 ++ .../dropdown-multiselect.component.pug | 26 + .../dropdown-multiselect.component.scss | 16 + .../dropdown-multiselect.component.spec.ts | 41 + .../manage-group/dropdown-multiselect.component.ts | 96 +++ .../manage-group-roles.component.pug | 96 +++ .../manage-group-roles.component.scss | 16 + .../manage-group-roles.component.spec.ts | 41 + .../manage-group-roles.component.ts | 243 ++++++ .../manage-group/manage-group-routing.module.ts | 36 + .../layout/manage-group/manage-group.component.pug | 40 + .../manage-group/manage-group.component.scss | 16 + .../manage-group/manage-group.component.spec.ts | 41 + .../layout/manage-group/manage-group.component.ts | 234 ++++++ .../manage-group/manage-group.module.spec.ts | 29 + .../app/layout/manage-group/manage-group.module.ts | 60 ++ .../app/layout/modeler/color-picker/ColorPicker.js | 80 ++ .../layout/modeler/color-picker/ColoredRenderer.js | 67 ++ .../src/app/layout/modeler/color-picker/index.js | 24 + .../log-test-result/draw/LogTestResultRenderer.js | 60 ++ .../custom-elements/log-test-result/draw/index.js | 22 + .../custom-elements/log-test-result/image/cat.gif | Bin 0 -> 29361 bytes .../custom-elements/log-test-result/image/index.js | 19 + .../palette/LogTestResultPaletteProvider.js | 61 ++ .../log-test-result/palette/index.js | 22 + .../app/layout/modeler/modeler-routing.module.ts | 31 + .../src/app/layout/modeler/modeler.component.pug | 162 ++++ .../src/app/layout/modeler/modeler.component.scss | 97 +++ .../app/layout/modeler/modeler.component.spec.ts | 41 + .../src/app/layout/modeler/modeler.component.ts | 821 ++++++++++++++++++++ .../src/app/layout/modeler/modeler.module.spec.ts | 29 + .../src/app/layout/modeler/modeler.module.ts | 67 ++ .../client/src/app/layout/modeler/new.bpmn | 98 +++ .../src/app/layout/modeler/templates/elements.json | 20 + .../modeler/test-definition-element.class.ts | 203 +++++ .../create-test/create-test-routing.module.ts | 31 + .../create-test/create-test.component.pug | 92 +++ .../create-test/create-test.component.scss | 19 + .../create-test/create-test.component.spec.ts | 41 + .../create-test/create-test.component.ts | 73 ++ .../create-test/create-test.module.spec.ts | 29 + .../onboarding/create-test/create-test.module.ts | 61 ++ .../layout/onboarding/onboarding-routing.module.ts | 38 + .../app/layout/onboarding/onboarding.component.pug | 83 +++ .../layout/onboarding/onboarding.component.scss | 29 + .../layout/onboarding/onboarding.component.spec.ts | 41 + .../app/layout/onboarding/onboarding.component.ts | 30 + .../layout/onboarding/onboarding.module.spec.ts | 29 + .../src/app/layout/onboarding/onboarding.module.ts | 32 + .../app/layout/onboarding/onboarding.service.ts | 32 + .../onboarding/start/start-routing.module.ts | 29 + .../layout/onboarding/start/start.component.pug | 24 + .../layout/onboarding/start/start.component.scss | 16 + .../onboarding/start/start.component.spec.ts | 41 + .../app/layout/onboarding/start/start.component.ts | 35 + .../layout/onboarding/start/start.module.spec.ts | 29 + .../app/layout/onboarding/start/start.module.ts | 32 + .../test-head/test-head-routing.module.ts | 31 + .../onboarding/test-head/test-head.component.pug | 52 ++ .../onboarding/test-head/test-head.component.scss | 16 + .../test-head/test-head.component.spec.ts | 41 + .../onboarding/test-head/test-head.component.ts | 91 +++ .../onboarding/test-head/test-head.module.spec.ts | 29 + .../onboarding/test-head/test-head.module.ts | 51 ++ .../test-instances-routing.module.ts | 31 + .../test-instances/test-instances.component.pug | 35 + .../test-instances/test-instances.component.scss | 16 + .../test-instances.component.spec.ts | 41 + .../test-instances/test-instances.component.ts | 57 ++ .../test-instances/test-instances.module.spec.ts | 29 + .../test-instances/test-instances.module.ts | 50 ++ .../layout/robot-report/robot-report.component.pug | 24 + .../robot-report/robot-report.component.scss | 16 + .../robot-report/robot-report.component.spec.ts | 41 + .../layout/robot-report/robot-report.component.ts | 82 ++ .../layout/scheduling/scheduling-routing.module.ts | 28 + .../app/layout/scheduling/scheduling.component.pug | 52 ++ .../layout/scheduling/scheduling.component.scss | 34 + .../layout/scheduling/scheduling.component.spec.ts | 41 + .../app/layout/scheduling/scheduling.component.ts | 154 ++++ .../layout/scheduling/scheduling.module.spec.ts | 29 + .../src/app/layout/scheduling/scheduling.module.ts | 52 ++ .../app/layout/settings/settings-routing.module.ts | 32 + .../src/app/layout/settings/settings.component.pug | 42 ++ .../app/layout/settings/settings.component.scss | 16 + .../app/layout/settings/settings.component.spec.ts | 41 + .../src/app/layout/settings/settings.component.ts | 103 +++ .../app/layout/settings/settings.module.spec.ts | 29 + .../src/app/layout/settings/settings.module.ts | 48 ++ .../test-definition-expanded-details.component.pug | 63 ++ ...test-definition-expanded-details.component.scss | 27 + ...t-definition-expanded-details.component.spec.ts | 41 + .../test-definition-expanded-details.component.ts | 216 ++++++ .../test-executions-catalog-routing.module.ts | 33 + .../test-executions-catalog.component.pug | 61 ++ .../test-executions-catalog.component.scss | 21 + .../test-executions-catalog.component.spec.ts | 41 + .../test-executions-catalog.component.ts | 162 ++++ .../test-executions-catalog.module.spec.ts | 29 + .../test-executions-catalog.module.ts | 61 ++ .../test-instance-expanded-details.component.pug | 28 + .../test-instance-expanded-details.component.scss | 39 + ...est-instance-expanded-details.component.spec.ts | 41 + .../test-instance-expanded-details.component.ts | 59 ++ .../test-instances-catalog-routing.module.ts | 30 + .../test-instances-catalog.component.pug | 72 ++ .../test-instances-catalog.component.scss | 53 ++ .../test-instances-catalog.component.spec.ts | 46 ++ .../test-instances-catalog.component.ts | 436 +++++++++++ .../test-instances-catalog.module.spec.ts | 29 + .../test-instances-catalog.module.ts | 65 ++ .../test-definition-details.component.pug | 64 ++ .../test-definition-details.component.scss | 16 + .../test-definition-details.component.spec.ts | 41 + .../test-definition-details.component.ts | 107 +++ .../src/app/layout/tests/tests-routing.module.ts | 31 + .../src/app/layout/tests/tests.component.pug | 180 +++++ .../src/app/layout/tests/tests.component.scss | 34 + .../src/app/layout/tests/tests.component.spec.ts | 41 + .../client/src/app/layout/tests/tests.component.ts | 535 ++++++++++++++ .../src/app/layout/tests/tests.module.spec.ts | 29 + .../client/src/app/layout/tests/tests.module.ts | 83 +++ .../user-management-routing.module.ts | 29 + .../user-management/user-management.component.pug | 86 +++ .../user-management/user-management.component.scss | 25 + .../user-management.component.spec.ts | 41 + .../user-management/user-management.component.ts | 347 +++++++++ .../user-management/user-management.module.spec.ts | 29 + .../user-management/user-management.module.ts | 71 ++ .../test-head-executions-line-chart.component.pug | 17 + .../test-head-executions-line-chart.component.scss | 16 + ...st-head-executions-line-chart.component.spec.ts | 41 + .../test-head-executions-line-chart.component.ts | 190 +++++ .../virtual-test-head-details.component.pug | 98 +++ .../virtual-test-head-details.component.scss | 16 + .../virtual-test-head-details.component.spec.ts | 41 + .../virtual-test-head-details.component.ts | 104 +++ .../virtual-test-heads-routing.module.ts | 31 + .../virtual-test-heads.component.pug | 80 ++ .../virtual-test-heads.component.scss | 39 + .../virtual-test-heads.component.spec.ts | 41 + .../virtual-test-heads.component.ts | 145 ++++ .../virtual-test-heads.module.spec.ts | 29 + .../virtual-test-heads.module.ts | 78 ++ .../client/src/app/login/login-routing.module.ts | 32 + .../client/src/app/login/login.component.html | 46 ++ .../client/src/app/login/login.component.scss | 112 +++ .../client/src/app/login/login.component.spec.ts | 48 ++ .../client/src/app/login/login.component.ts | 102 +++ .../client/src/app/login/login.module.spec.ts | 29 + otf-frontend/client/src/app/login/login.module.ts | 29 + .../src/app/not-found/not-found-routing.module.ts | 32 + .../src/app/not-found/not-found.component.html | 35 + .../src/app/not-found/not-found.component.pug | 20 + .../src/app/not-found/not-found.component.scss | 241 ++++++ .../src/app/not-found/not-found.component.spec.ts | 41 + .../src/app/not-found/not-found.component.ts | 69 ++ .../src/app/not-found/not-found.module.spec.ts | 29 + .../client/src/app/not-found/not-found.module.ts | 30 + otf-frontend/client/src/app/router.animations.ts | 178 +++++ .../server-error/server-error-routing.module.ts | 32 + .../app/server-error/server-error.component.html | 19 + .../app/server-error/server-error.component.scss | 16 + .../server-error/server-error.component.spec.ts | 41 + .../src/app/server-error/server-error.component.ts | 31 + .../app/server-error/server-error.module.spec.ts | 29 + .../src/app/server-error/server-error.module.ts | 30 + .../components/menu-item/menu-item.component.pug | 29 + .../components/menu-item/menu-item.component.scss | 16 + .../menu-item/menu-item.component.spec.ts | 41 + .../components/menu-item/menu-item.component.ts | 54 ++ .../shared/factories/bpmn-factory.service.spec.ts | 28 + .../app/shared/factories/bpmn-factory.service.ts | 132 ++++ .../src/app/shared/guard/admin.guard.spec.ts | 33 + .../client/src/app/shared/guard/admin.guard.ts | 48 ++ .../client/src/app/shared/guard/auth.guard.spec.ts | 33 + .../client/src/app/shared/guard/auth.guard.ts | 38 + otf-frontend/client/src/app/shared/guard/index.ts | 18 + otf-frontend/client/src/app/shared/index.ts | 19 + .../src/app/shared/models/base-model.model.ts | 23 + .../client/src/app/shared/models/bpmn.model.ts | 159 ++++ .../client/src/app/shared/models/group.model.ts | 51 ++ .../src/app/shared/models/test-definition.model.ts | 60 ++ .../src/app/shared/models/test-execution.model.ts | 39 + .../src/app/shared/models/test-head.model.ts | 34 + .../src/app/shared/models/test-instance.model.ts | 36 + .../client/src/app/shared/models/user.model.ts | 45 ++ .../modules/alert-modal/alert-modal.component.pug | 83 +++ .../modules/alert-modal/alert-modal.component.scss | 38 + .../alert-modal/alert-modal.component.spec.ts | 41 + .../modules/alert-modal/alert-modal.component.ts | 67 ++ .../modules/alert-modal/alert-modal.module.spec.ts | 29 + .../modules/alert-modal/alert-modal.module.ts | 36 + .../alert-snackbar/alert-snackbar.component.pug | 19 + .../alert-snackbar/alert-snackbar.component.scss | 16 + .../alert-snackbar.component.spec.ts | 41 + .../alert-snackbar/alert-snackbar.component.ts | 36 + .../alert-snackbar/alert-snackbar.module.spec.ts | 29 + .../alert-snackbar/alert-snackbar.module.ts | 31 + .../create-group-modal.component.pug | 37 + .../create-group-modal.component.scss | 16 + .../create-group-modal.component.spec.ts | 41 + .../create-group-modal.component.ts | 131 ++++ .../create-group-modal.module.spec.ts | 29 + .../create-group-modal.module.ts | 43 ++ .../create-test-form.component.pug | 167 +++++ .../create-test-form.component.scss | 50 ++ .../create-test-form.component.spec.ts | 41 + .../create-test-form/create-test-form.component.ts | 823 +++++++++++++++++++++ .../create-test-form.module.spec.ts | 41 + .../create-test-form/create-test-form.module.ts | 77 ++ .../create-test-form/definition-instance.class.ts | 60 ++ .../create-test-form/test-definition.class.ts | 222 ++++++ .../create-test-head-form.component.pug | 78 ++ .../create-test-head-form.component.scss | 35 + .../create-test-head-form.component.spec.ts | 41 + .../create-test-head-form.component.ts | 170 +++++ .../create-test-head-form.module.spec.ts | 29 + .../create-test-head-form.module.ts | 53 ++ .../create-test-instance-form.component.pug | 139 ++++ .../create-test-instance-form.component.scss | 19 + .../create-test-instance-form.component.spec.ts | 41 + .../create-test-instance-form.component.ts | 788 ++++++++++++++++++++ .../create-test-instance-form.module.spec.ts | 29 + .../create-test-instance-form.module.ts | 70 ++ .../filterNonDeployed.pipe.ts | 32 + .../create-test-instance-form/instance.class.ts | 41 + .../form-generator/form-generator.component.html | 23 + .../form-generator/form-generator.component.scss | 16 + .../form-generator.component.spec.ts | 41 + .../form-generator/form-generator.component.ts | 381 ++++++++++ .../form-generator/form-generator.module.spec.ts | 29 + .../form-generator/form-generator.module.ts | 37 + .../text-area/text-area.component.html | 17 + .../text-area/text-area.component.scss | 16 + .../text-area/text-area.component.spec.ts | 41 + .../text-area/text-area.component.ts | 31 + .../client/src/app/shared/modules/index.ts | 18 + .../onboard-mechid/onboard-mechid.component.pug | 18 + .../onboard-mechid/onboard-mechid.component.scss | 16 + .../onboard-mechid.component.spec.ts | 41 + .../onboard-mechid/onboard-mechid.component.ts | 42 ++ .../onboard-mechid/onboard-mechid.module.spec.ts | 29 + .../onboard-mechid/onboard-mechid.module.ts | 29 + .../modules/page-header/page-header.component.html | 31 + .../modules/page-header/page-header.component.scss | 16 + .../page-header/page-header.component.spec.ts | 43 ++ .../modules/page-header/page-header.component.ts | 31 + .../modules/page-header/page-header.module.spec.ts | 29 + .../modules/page-header/page-header.module.ts | 28 + .../schedule-test-modal.component.pug | 72 ++ .../schedule-test-modal.component.scss | 16 + .../schedule-test-modal.component.spec.ts | 41 + .../schedule-test-modal.component.ts | 190 +++++ .../schedule-test-modal.module.spec.ts | 29 + .../schedule-test-modal.module.ts | 55 ++ .../select-strategy-modal.component.pug | 35 + .../select-strategy-modal.component.scss | 16 + .../select-strategy-modal.component.spec.ts | 41 + .../select-strategy-modal.component.ts | 65 ++ .../select-strategy-modal.module.spec.ts | 29 + .../select-strategy-modal.module.ts | 40 + .../select-test-head-modal.component.pug | 30 + .../select-test-head-modal.component.scss | 16 + .../select-test-head-modal.component.spec.ts | 41 + .../select-test-head-modal.component.ts | 53 ++ .../select-test-head-modal.module.spec.ts | 29 + .../select-test-head-modal.module.ts | 41 + .../app/shared/modules/stat/stat.component.html | 35 + .../app/shared/modules/stat/stat.component.scss | 16 + .../app/shared/modules/stat/stat.component.spec.ts | 42 ++ .../src/app/shared/modules/stat/stat.component.ts | 35 + .../app/shared/modules/stat/stat.module.spec.ts | 29 + .../src/app/shared/modules/stat/stat.module.ts | 26 + .../test-definition-modal.component.pug | 25 + .../test-definition-modal.component.scss | 16 + .../test-definition-modal.component.spec.ts | 41 + .../test-definition-modal.component.ts | 53 ++ .../test-definition-modal.module.spec.ts | 29 + .../test-definition-modal.module.ts | 41 + .../test-head-modal/test-head-modal.component.pug | 25 + .../test-head-modal/test-head-modal.component.scss | 16 + .../test-head-modal.component.spec.ts | 41 + .../test-head-modal/test-head-modal.component.ts | 53 ++ .../test-head-modal/test-head-modal.module.spec.ts | 29 + .../test-head-modal/test-head-modal.module.ts | 43 ++ .../test-instance-modal.component.pug | 25 + .../test-instance-modal.component.scss | 16 + .../test-instance-modal.component.spec.ts | 41 + .../test-instance-modal.component.ts | 80 ++ .../test-instance-modal.module.spec.ts | 29 + .../test-instance-modal.module.ts | 42 ++ .../modules/user-select/user-select.component.pug | 44 ++ .../modules/user-select/user-select.component.scss | 16 + .../user-select/user-select.component.spec.ts | 41 + .../modules/user-select/user-select.component.ts | 117 +++ .../modules/user-select/user-select.module.spec.ts | 29 + .../modules/user-select/user-select.module.ts | 40 + .../view-schedule-modal.component.pug | 32 + .../view-schedule-modal.component.scss | 16 + .../view-schedule-modal.component.spec.ts | 41 + .../view-schedule-modal.component.ts | 45 ++ .../view-schedule-modal.module.spec.ts | 29 + .../view-schedule-modal.module.ts | 32 + .../view-workflow-modal.component.pug | 23 + .../view-workflow-modal.component.scss | 20 + .../view-workflow-modal.component.spec.ts | 41 + .../view-workflow-modal.component.ts | 53 ++ .../view-workflow-modal.module.spec.ts | 29 + .../view-workflow-modal.module.ts | 33 + .../workflow-request.component.pug | 36 + .../workflow-request.component.scss | 16 + .../workflow-request.component.spec.ts | 41 + .../workflow-request/workflow-request.component.ts | 48 ++ .../workflow-request.module.spec.ts | 29 + .../workflow-request/workflow-request.module.ts | 41 + .../src/app/shared/pipes/shared-pipes.module.ts | 31 + .../app/shared/services/account.service.spec.ts | 28 + .../src/app/shared/services/account.service.ts | 47 ++ .../src/app/shared/services/auth.service.spec.ts | 28 + .../client/src/app/shared/services/auth.service.ts | 85 +++ .../src/app/shared/services/execute.service.ts | 38 + .../src/app/shared/services/feathers.service.ts | 88 +++ .../app/shared/services/feedback.service.spec.ts | 28 + .../src/app/shared/services/feedback.service.ts | 42 ++ .../shared/services/file-transfer.service.spec.ts | 31 + .../app/shared/services/file-transfer.service.ts | 34 + .../src/app/shared/services/file.service.spec.ts | 31 + .../client/src/app/shared/services/file.service.ts | 34 + .../src/app/shared/services/group.service.spec.ts | 31 + .../src/app/shared/services/group.service.ts | 145 ++++ .../src/app/shared/services/health.service.spec.ts | 28 + .../src/app/shared/services/health.service.ts | 37 + .../src/app/shared/services/json2html.service.ts | 60 ++ .../src/app/shared/services/list.service.spec.ts | 31 + .../client/src/app/shared/services/list.service.ts | 77 ++ .../src/app/shared/services/model.service.ts | 211 ++++++ .../src/app/shared/services/params.service.ts | 32 + .../app/shared/services/scheduling.service.spec.ts | 31 + .../src/app/shared/services/scheduling.service.ts | 58 ++ .../services/test-definition.service.spec.ts | 28 + .../app/shared/services/test-definition.service.ts | 89 +++ .../shared/services/test-execution.service.spec.ts | 31 + .../app/shared/services/test-execution.service.ts | 38 + .../app/shared/services/test-head.service.spec.ts | 31 + .../src/app/shared/services/test-head.service.ts | 41 + .../shared/services/test-instance.service.spec.ts | 31 + .../app/shared/services/test-instance.service.ts | 41 + .../src/app/shared/services/user.service.spec.ts | 31 + .../client/src/app/shared/services/user.service.ts | 75 ++ .../client/src/app/signup/signup-routing.module.ts | 32 + .../client/src/app/signup/signup.component.html | 68 ++ .../client/src/app/signup/signup.component.scss | 18 + .../client/src/app/signup/signup.component.spec.ts | 48 ++ .../client/src/app/signup/signup.component.ts | 102 +++ .../client/src/app/signup/signup.module.spec.ts | 29 + .../client/src/app/signup/signup.module.ts | 40 + otf-frontend/client/src/assets/fakedata.json | 115 +++ otf-frontend/client/src/assets/i18n/de.json | 32 + otf-frontend/client/src/assets/i18n/en.json | 32 + otf-frontend/client/src/assets/i18n/es.json | 32 + otf-frontend/client/src/assets/i18n/fa.json | 32 + otf-frontend/client/src/assets/i18n/fr.json | 32 + otf-frontend/client/src/assets/i18n/it.json | 32 + otf-frontend/client/src/assets/i18n/ur.json | 32 + otf-frontend/client/src/assets/i18n/zh-CHS.json | 32 + otf-frontend/client/src/assets/images/404image.png | Bin 0 -> 51614 bytes .../client/src/assets/images/NetworkLogo.jpg | Bin 0 -> 1455632 bytes otf-frontend/client/src/assets/images/OtfIcon.png | Bin 0 -> 436156 bytes .../client/src/assets/images/equalizer.gif | Bin 0 -> 90816 bytes otf-frontend/client/src/assets/images/logo.png | Bin 0 -> 84440 bytes .../client/src/assets/images/networkBackground.jpg | Bin 0 -> 256809 bytes .../src/assets/images/networkBackground1.jpg | Bin 0 -> 264935 bytes otf-frontend/client/src/assets/images/slider1.jpg | Bin 0 -> 280620 bytes otf-frontend/client/src/assets/images/slider2.jpg | Bin 0 -> 55476 bytes .../client/src/assets/workflows/blank.bpmn | 13 + .../client/src/environments/environment.prod.ts | 19 + .../client/src/environments/environment.ts | 24 + otf-frontend/client/src/favicon.ico | Bin 0 -> 130199 bytes otf-frontend/client/src/global-shims.ts | 19 + otf-frontend/client/src/index.html | 36 + otf-frontend/client/src/main.ts | 29 + otf-frontend/client/src/polyfills.ts | 85 +++ otf-frontend/client/src/styles/_responsive.scss | 23 + otf-frontend/client/src/styles/_rtl.scss | 90 +++ otf-frontend/client/src/styles/_spinner.scss | 60 ++ otf-frontend/client/src/styles/_utils.scss | 19 + otf-frontend/client/src/styles/app.scss | 187 +++++ otf-frontend/client/src/test.ts | 48 ++ otf-frontend/client/src/tsconfig.app.json | 20 + otf-frontend/client/src/tsconfig.json | 21 + otf-frontend/client/src/tsconfig.spec.json | 21 + otf-frontend/client/src/typings.d.ts | 28 + otf-frontend/helm/otf-frontend/Chart.yaml | 5 + .../helm/otf-frontend/templates/deployment.yaml | 218 ++++++ .../helm/otf-frontend/templates/secret.yaml | 9 + .../helm/otf-frontend/templates/service.yaml | 18 + otf-frontend/helm/otf-frontend/values.yaml | 59 ++ otf-frontend/package.json | 168 +++++ otf-frontend/server/config/.eslintrc | 474 ++++++++++++ otf-frontend/server/config/cert/info.txt | 1 + .../config/custom-environment-variables.json | 29 + otf-frontend/server/config/production.json | 0 otf-frontend/server/src/agenda/agenda.js | 51 ++ .../controllers/test-execution-controller.js | 220 ++++++ .../server/src/agenda/jobs/test-execution-job.js | 133 ++++ .../server/src/agenda/models/test-schedule.js | 154 ++++ otf-frontend/server/src/agenda/result-emitter.js | 32 + otf-frontend/server/src/app.js | 101 +++ otf-frontend/server/src/feathers/app.hooks.js | 83 +++ otf-frontend/server/src/feathers/authentication.js | 69 ++ otf-frontend/server/src/feathers/channels.js | 78 ++ .../server/src/feathers/hooks/agendaJobPopulate.js | 62 ++ .../server/src/feathers/hooks/checkLocks.js | 48 ++ .../server/src/feathers/hooks/checkPermissions.js | 42 ++ .../server/src/feathers/hooks/convertToJSON.js | 142 ++++ .../server/src/feathers/hooks/convertToYAML.js | 335 +++++++++ .../src/feathers/hooks/convertToYAMLRecursive.js | 70 ++ .../server/src/feathers/hooks/createdBy.js | 28 + .../server/src/feathers/hooks/delete-definition.js | 46 ++ .../server/src/feathers/hooks/delete-version.js | 70 ++ otf-frontend/server/src/feathers/hooks/filters.js | 225 ++++++ otf-frontend/server/src/feathers/hooks/log.js | 40 + .../server/src/feathers/hooks/paginate-option.js | 26 + .../src/feathers/hooks/permissions/abilities.js | 110 +++ .../feathers/hooks/permissions/get-permissions.js | 93 +++ .../src/feathers/hooks/permissions/permissions.js | 234 ++++++ .../src/feathers/hooks/testDefinitionIsDeployed.js | 51 ++ otf-frontend/server/src/feathers/hooks/throw.js | 21 + .../server/src/feathers/hooks/updatedBy.js | 28 + otf-frontend/server/src/feathers/index.js | 166 +++++ .../server/src/feathers/models/file.model.js | 29 + .../server/src/feathers/models/groups.model.js | 39 + .../server/src/feathers/models/jobs.model.js | 45 ++ .../src/feathers/models/test-definitions.model.js | 58 ++ .../src/feathers/models/test-executions.model.js | 53 ++ .../server/src/feathers/models/test-heads.model.js | 42 ++ .../src/feathers/models/test-instances.model.js | 71 ++ .../server/src/feathers/models/users.model.js | 46 ++ .../auth-management/auth-management.hooks.js | 70 ++ .../auth-management/auth-management.service.js | 36 + .../feathers/services/auth-management/notifier.js | 120 +++ .../services/bpmn-upload/bpmn-upload.class.js | 196 +++++ .../services/bpmn-upload/bpmn-upload.hooks.js | 48 ++ .../services/bpmn-upload/bpmn-upload.service.js | 35 + .../services/bpmn-validate/bpmn-validate.class.js | 297 ++++++++ .../services/bpmn-validate/bpmn-validate.hooks.js | 49 ++ .../bpmn-validate/bpmn-validate.service.js | 36 + .../feathers/services/bpmn-validate/bpmn.class.js | 360 +++++++++ .../src/feathers/services/execute/execute.class.js | 132 ++++ .../src/feathers/services/execute/execute.hooks.js | 93 +++ .../feathers/services/execute/execute.service.js | 34 + .../feathers/services/feedback/feedback.class.js | 62 ++ .../feathers/services/feedback/feedback.hooks.js | 78 ++ .../feathers/services/feedback/feedback.service.js | 36 + .../services/file-transfer/file-transfer.class.js | 177 +++++ .../services/file-transfer/file-transfer.hooks.js | 50 ++ .../file-transfer/file-transfer.service.js | 49 ++ .../src/feathers/services/files/files.hooks.js | 52 ++ .../src/feathers/services/files/files.service.js | 35 + .../src/feathers/services/groups/groups.hooks.js | 51 ++ .../src/feathers/services/groups/groups.service.js | 38 + .../src/feathers/services/health/health.class.js | 106 +++ .../src/feathers/services/health/health.hooks.js | 47 ++ .../src/feathers/services/health/health.service.js | 36 + otf-frontend/server/src/feathers/services/index.js | 57 ++ .../src/feathers/services/jobs/jobs.class.js | 16 + .../src/feathers/services/jobs/jobs.hooks.js | 218 ++++++ .../src/feathers/services/jobs/jobs.service.js | 37 + .../src/feathers/services/mailer/mailer.class.js | 75 ++ .../src/feathers/services/mailer/mailer.hooks.js | 50 ++ .../src/feathers/services/mailer/mailer.service.js | 36 + .../feathers/services/messages/messages.class.js | 57 ++ .../feathers/services/messages/messages.hooks.js | 57 ++ .../feathers/services/messages/messages.service.js | 37 + .../test-definitions/test-definitions.hooks.js | 62 ++ .../test-definitions/test-definitions.service.js | 38 + .../test-execution-status.class.js | 109 +++ .../test-execution-status.hooks.js | 49 ++ .../test-execution-status.service.js | 36 + .../test-executions/test-executions.hooks.js | 56 ++ .../test-executions/test-executions.service.js | 38 + .../services/test-heads/test-heads.hooks.js | 58 ++ .../services/test-heads/test-heads.service.js | 38 + .../test-instances/test-instances.hooks.js | 62 ++ .../test-instances/test-instances.service.js | 38 + .../src/feathers/services/users/users.hooks.js | 181 +++++ .../src/feathers/services/users/users.service.js | 62 ++ otf-frontend/server/src/lib/logger.js | 71 ++ otf-frontend/server/src/lib/mongoose.js | 30 + otf-frontend/server/src/lib/music.js | 66 ++ otf-frontend/server/src/lib/otf-util.js | 36 + otf-frontend/server/test/app.test.js | 55 ++ .../server/test/hooks/group-filter.test.js | 25 + .../server/test/services/bpmn-upload.test.js | 10 + .../server/test/services/bpmn-validate.test.js | 10 + otf-frontend/server/test/services/groups-m.test.js | 10 + otf-frontend/server/test/services/groups.test.js | 10 + otf-frontend/server/test/services/health.test.js | 10 + .../server/test/services/strategy-upload.test.js | 10 + .../server/test/services/test-definition.test.js | 10 + .../server/test/services/test-heads.test.js | 10 + .../server/test/services/test-instances.test.js | 10 + .../server/test/services/test-requests.test.js | 10 + .../server/test/services/test-strategies.test.js | 10 + otf-frontend/server/test/services/tests.test.js | 10 + otf-frontend/server/test/services/users.test.js | 10 + otf-ping-test-head/Dockerfile | 13 +- otf-robot-test-head/Dockerfile | 17 +- otf-service-api/.gitignore | 34 + otf-service-api/Jenkinsfile | 169 +++++ otf-service-api/LICENSE.txt | 28 + otf-service-api/README.txt | 13 + otf-service-api/docker/Dockerfile | 43 ++ otf-service-api/helm/otf-service-api/Chart.yaml | 5 + .../helm/otf-service-api/templates/deployment.yaml | 280 +++++++ .../helm/otf-service-api/templates/secret.yaml | 8 + .../helm/otf-service-api/templates/service.yaml | 18 + otf-service-api/helm/otf-service-api/values.yaml | 89 +++ otf-service-api/pom.xml | 348 +++++++++ .../main/java/org/oran/otf/api/Application.java | 74 ++ .../src/main/java/org/oran/otf/api/Utilities.java | 394 ++++++++++ .../otf/api/config/CadiFilterConfiguration.java | 119 +++ .../otf/api/config/CombinedResourceProvider.java | 46 ++ .../java/org/oran/otf/api/config/DataConfig.java | 83 +++ .../otf/api/config/HttpSecurityConfiguration.java | 68 ++ .../oran/otf/api/config/JerseyConfiguration.java | 99 +++ .../otf/api/config/OTFApiEnforcementFilter.java | 134 ++++ .../OTFApiEnforcementFilterConfiguration.java | 60 ++ .../org/oran/otf/api/config/OTFLoggingFeature.java | 238 ++++++ .../api/exception/TestHeadNotFoundException.java | 33 + .../otf/api/exception/TestParametersException.java | 33 + .../otf/api/exception/UserNotFoundException.java | 33 + .../handler/CamundaProcessDeploymentHandler.java | 131 ++++ .../handler/CamundaProcessExecutionHandler.java | 105 +++ .../org/oran/otf/api/service/HealthService.java | 54 ++ .../org/oran/otf/api/service/OtfOpenService.java | 35 + .../oran/otf/api/service/TestExecutionService.java | 92 +++ .../oran/otf/api/service/TestInstanceService.java | 374 ++++++++++ .../oran/otf/api/service/TestStrategyService.java | 66 ++ .../otf/api/service/VirtualTestHeadService.java | 55 ++ .../otf/api/service/impl/HealthServiceImpl.java | 34 + .../otf/api/service/impl/OtfOpenServiceImpl.java | 49 ++ .../api/service/impl/TestExecutionServiceImpl.java | 160 ++++ .../api/service/impl/TestInstanceServiceImpl.java | 807 ++++++++++++++++++++ .../api/service/impl/TestStrategyServiceImpl.java | 228 ++++++ .../service/impl/VirtualTestHeadServiceImpl.java | 164 ++++ .../main/java/org/oran/otf/common/model/Group.java | 110 +++ .../org/oran/otf/common/model/GroupMember.java | 43 ++ .../main/java/org/oran/otf/common/model/Role.java | 41 + .../org/oran/otf/common/model/TestDefinition.java | 137 ++++ .../org/oran/otf/common/model/TestExecution.java | 245 ++++++ .../java/org/oran/otf/common/model/TestHead.java | 224 ++++++ .../org/oran/otf/common/model/TestInstance.java | 256 +++++++ .../main/java/org/oran/otf/common/model/User.java | 142 ++++ .../model/historic/TestDefinitionHistoric.java | 185 +++++ .../model/historic/TestInstanceHistoric.java | 234 ++++++ .../oran/otf/common/model/local/ApiRequest.java | 19 + .../oran/otf/common/model/local/BpmnInstance.java | 191 +++++ .../model/local/DeployTestStrategyRequest.java | 73 ++ .../otf/common/model/local/OTFApiResponse.java | 66 ++ .../otf/common/model/local/ParallelFlowInput.java | 83 +++ .../org/oran/otf/common/model/local/PfloNode.java | 61 ++ .../oran/otf/common/model/local/TestHeadNode.java | 58 ++ .../otf/common/model/local/TestHeadRequest.java | 53 ++ .../otf/common/model/local/TestHeadResult.java | 146 ++++ .../model/local/TestInstanceCreateRequest.java | 215 ++++++ .../org/oran/otf/common/model/local/UserGroup.java | 57 ++ .../otf/common/model/local/WorkflowRequest.java | 163 ++++ .../otf/common/repository/GroupRepository.java | 31 + .../repository/TestDefinitionRepository.java | 26 + .../common/repository/TestExecutionRepository.java | 26 + .../otf/common/repository/TestHeadRepository.java | 28 + .../common/repository/TestInstanceRepository.java | 36 + .../oran/otf/common/repository/UserRepository.java | 25 + .../java/org/oran/otf/common/util/HttpUtils.java | 19 + .../oran/otf/common/utility/RSAEncryptDecrypt.java | 54 ++ .../java/org/oran/otf/common/utility/Utility.java | 84 +++ .../oran/otf/common/utility/database/Generic.java | 36 + .../utility/database/TestExecutionUtility.java | 36 + .../org/oran/otf/common/utility/gson/Convert.java | 95 +++ .../oran/otf/common/utility/gson/GsonUtils.java | 69 ++ .../otf/common/utility/http/RequestUtility.java | 160 ++++ .../otf/common/utility/http/ResponseUtility.java | 107 +++ .../oran/otf/common/utility/logger/ErrorCode.java | 36 + .../utility/logger/LoggerStartupListener.java | 91 +++ .../otf/common/utility/logger/MessageEnum.java | 35 + .../utility/permissions/PermissionChecker.java | 57 ++ .../common/utility/permissions/PermissionUtil.java | 237 ++++++ .../common/utility/permissions/UserPermission.java | 58 ++ .../src/main/resources/application.properties | 50 ++ otf-service-api/src/main/resources/banner.txt | 8 + .../src/main/resources/truststore2018.jks | Bin 0 -> 8366 bytes .../org/oran/otf/api/tests/config/DataConfig2.java | 109 +++ .../org/oran/otf/api/tests/config/InMemory.java | 69 ++ .../services/ExecutionServiceRouteIT.java | 79 ++ .../tests/integration/services/HealthRouteIT.java | 80 ++ .../services/InstanceServiceRouteIT.java | 170 +++++ .../tests/integration/services/OtfOpenRouteIT.java | 67 ++ .../services/Permissions/PermissionServiceIT.java | 331 +++++++++ .../services/StrategyServiceRouteIT.java | 74 ++ .../oran/otf/api/tests/shared/MemoryDatabase.java | 386 ++++++++++ .../otf/api/tests/unit/models/DefinitionTest.java | 82 ++ .../otf/api/tests/unit/models/ExecutionTest.java | 107 +++ .../oran/otf/api/tests/unit/models/GroupTest.java | 50 ++ .../oran/otf/api/tests/unit/models/HeadTest.java | 72 ++ .../otf/api/tests/unit/models/InstanceTest.java | 104 +++ .../oran/otf/api/tests/unit/models/UserTest.java | 63 ++ .../otf/api/tests/unit/models/local/BpmnTest.java | 83 +++ .../local/DeployTestStrategyRequestTest.java | 44 ++ .../api/tests/unit/models/local/HeadNodeTest.java | 40 + .../tests/unit/models/local/HeadResultTest.java | 60 ++ .../models/local/InstanceCreateRequestTest.java | 93 +++ .../unit/models/local/OtfApiResponseTest.java | 43 ++ .../unit/models/local/ParallelFlowInputTest.java | 47 ++ .../api/tests/unit/models/local/PfloNodeTest.java | 40 + .../api/tests/unit/models/local/UserGroupTest.java | 42 ++ .../unit/models/local/WorkFlowRequestTest.java | 61 ++ .../api/tests/unit/utility/BuildResponseTest.java | 74 ++ .../api/tests/unit/utility/UserPermissionTest.java | 67 ++ .../src/test/resources/application-test.properties | 19 + otf-service-api/swagger.json | 1 + otf-service-api/swagger.yml | 714 ++++++++++++++++++ otf-ssh-test-head/Dockerfile | 12 +- 878 files changed, 64724 insertions(+), 12 deletions(-) create mode 100644 otf-camunda/.gitignore create mode 100644 otf-camunda/Jenkinsfile create mode 100644 otf-camunda/LICENSE.txt create mode 100644 otf-camunda/docker/Dockerfile create mode 100644 otf-camunda/helm/forceDelete.sh create mode 100644 otf-camunda/helm/otf-camunda/Chart.yaml create mode 100644 otf-camunda/helm/otf-camunda/mysqlRouterConfig-dev.ini create mode 100644 otf-camunda/helm/otf-camunda/mysqlRouterConfig-prod.ini create mode 100644 otf-camunda/helm/otf-camunda/mysqlRouterConfig-st.ini create mode 100644 otf-camunda/helm/otf-camunda/templates/config.yaml create mode 100644 otf-camunda/helm/otf-camunda/templates/deployment.yaml create mode 100644 otf-camunda/helm/otf-camunda/templates/secret.yaml create mode 100644 otf-camunda/helm/otf-camunda/templates/service.yaml create mode 100644 otf-camunda/helm/otf-camunda/values.yaml create mode 100644 otf-camunda/mvnw create mode 100644 otf-camunda/mvnw.cmd create mode 100644 otf-camunda/pom.xml create mode 100644 otf-camunda/src/main/java/org/oran/otf/Application.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/cadi/configuration/CadiFilterConfiguration.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/cadi/configuration/FilterCondition.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/cadi/configuration/OTFApiEnforcementFilterConfiguration.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/cadi/filter/OTFApiEnforcementFilter.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/camunda/configuration/OTFAuthorizationConfiguration.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/camunda/configuration/OTFDataSourceConfiguration.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/camunda/configuration/OTFDeploymentConfiguration.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/camunda/configuration/OTFFailedJobConfiguration.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/camunda/configuration/OTFJacksonDataConfigurator.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/camunda/configuration/OTFJobConfiguration.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/camunda/configuration/OTFLoggingFeature.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/camunda/configuration/OtfCamundaConfiguration.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/camunda/configuration/listener/OTFJobExecutorStartingEventListener.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/camunda/delegate/otf/common/CallTestHeadDelegate.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/camunda/delegate/otf/common/LogTestResultDelegate.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/camunda/delegate/otf/common/PostResultsToDMaaPDelegate.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/camunda/delegate/otf/common/RunTestInstanceDelegate.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/camunda/delegate/otf/common/SendMailDelegate.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/camunda/delegate/otf/common/runnable/AsynchronousTestInstanceCallable.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/camunda/delegate/otf/common/runnable/SynchronousTestInstanceCallable.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/camunda/delegate/otf/common/runnable/TestHeadCallable.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/camunda/exception/TestExecutionException.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/camunda/exception/WorkflowException.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/camunda/exception/WorkflowProcessorException.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/camunda/listener/EndEventListener.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/camunda/listener/StartEventListener.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/camunda/listener/TaskEndEventListener.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/camunda/model/ExecutionConstants.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/camunda/model/WorkflowResponse.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/camunda/plugin/OtfIncidentHandlerPlugin.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/camunda/service/CamundaShutdown.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/camunda/service/OtfExternalTaskService.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/camunda/service/OtfWorkflowTaskCleanupService.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/camunda/service/ProcessEngineAwareService.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/camunda/workflow/WorkflowProcessor.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/camunda/workflow/WorkflowRequest.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/camunda/workflow/handler/ExternalTaskIncidentHandler.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/camunda/workflow/handler/FailedJobIncidentHandler.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/camunda/workflow/utility/RsaEncryptDecrypt.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/camunda/workflow/utility/WorkflowTask.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/camunda/workflow/utility/WorkflowUtility.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/common/model/Group.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/common/model/GroupMember.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/common/model/Role.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/common/model/TestDefinition.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/common/model/TestExecution.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/common/model/TestHead.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/common/model/TestInstance.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/common/model/User.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/common/model/historic/TestDefinitionHistoric.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/common/model/historic/TestInstanceHistoric.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/common/model/local/BpmnInstance.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/common/model/local/DMaaPRequest.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/common/model/local/OTFApiResponse.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/common/model/local/OTFDeploymentResponse.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/common/model/local/OTFProcessInstanceCompletionResponse.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/common/model/local/ParallelFlowInput.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/common/model/local/PfloNode.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/common/model/local/TestHeadNode.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/common/model/local/TestHeadRequest.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/common/model/local/TestHeadResult.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/common/model/local/UserGroup.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/common/repository/GroupRepository.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/common/repository/TestDefinitionRepository.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/common/repository/TestExecutionRepository.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/common/repository/TestHeadRepository.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/common/repository/TestInstanceRepository.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/common/repository/UserRepository.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/common/utility/Utility.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/common/utility/database/Generic.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/common/utility/database/TestExecutionUtility.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/common/utility/gson/Convert.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/common/utility/http/HeadersUtility.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/common/utility/http/RequestUtility.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/common/utility/http/ResponseUtility.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/common/utility/logger/ErrorCode.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/common/utility/logger/LoggerStartupListener.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/common/utility/logger/MessageEnum.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/common/utility/permissions/PermissionChecker.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/common/utility/permissions/PermissionUtil.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/common/utility/permissions/UserPermission.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/common/utility/sftp/SftpUtility.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/event/TestInstanceCompletionEvent.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/event/TestInstanceIncidentEvent.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/service/DeleteProcessInstanceService.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/service/DeleteTestDefinitionService.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/service/DeveloperService.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/service/HealthService.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/service/ProcessInstanceCompletionService.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/service/TestControlUnitService.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/service/TestDefinitionDeploymentService.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/service/impl/DeleteProcessInstanceServiceImpl.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/service/impl/DeleteTestDefinitionServiceImpl.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/service/impl/DeveloperServiceImpl.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/service/impl/HealthServiceImpl.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/service/impl/ProcessInstanceCompletionServiceImpl.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/service/impl/TestControlUnitServiceImpl.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/service/impl/TestDefinitionDeploymentServiceImpl.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/spring/configuration/HttpSecurityConfiguration.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/spring/configuration/JerseyConfiguration.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/spring/configuration/OTFLoggingFeature.java create mode 100644 otf-camunda/src/main/java/org/oran/otf/spring/configuration/OTFMongoConfiguration.java create mode 100644 otf-camunda/src/main/resources/META-INF/processes.xml.off create mode 100644 otf-camunda/src/main/resources/META-INF/securityFilterRules.json create mode 100644 otf-camunda/src/main/resources/application.yaml create mode 100644 otf-camunda/src/main/resources/banner.txt create mode 100644 otf-camunda/src/main/resources/bpmn/pingGoogleDNS.bpmn create mode 100644 otf-camunda/src/main/resources/mail-config.properties create mode 100644 otf-camunda/src/test/java/org/oran/otf/api/tests/config/DataConfig.java create mode 100644 otf-camunda/src/test/java/org/oran/otf/api/tests/config/InMemoryConfig.java create mode 100644 otf-camunda/src/test/java/org/oran/otf/api/tests/shared/MemoryDatabase.java create mode 100644 otf-camunda/src/test/java/org/oran/otf/api/tests/unit/common/utility/http/HeadersUtilityTest.java create mode 100644 otf-camunda/src/test/resources/application-test.properties create mode 100644 otf-frontend/.dockerignore create mode 100644 otf-frontend/.gitignore create mode 100644 otf-frontend/Dockerfile create mode 100644 otf-frontend/Jenkinsfile create mode 100644 otf-frontend/LICENSES.txt create mode 100644 otf-frontend/angular.json create mode 100644 otf-frontend/client/.gitignore create mode 100644 otf-frontend/client/config/.editorconfig create mode 100644 otf-frontend/client/config/.travis.yml create mode 100644 otf-frontend/client/config/karma.conf.js create mode 100644 otf-frontend/client/config/protractor.conf.js create mode 100644 otf-frontend/client/config/tsconfig.json create mode 100644 otf-frontend/client/config/tslint.json create mode 100644 otf-frontend/client/e2e/app.e2e-spec.ts create mode 100644 otf-frontend/client/e2e/app.po.ts create mode 100644 otf-frontend/client/e2e/tsconfig.e2e.json create mode 100644 otf-frontend/client/src/app/access-denied/access-denied-routing.module.ts create mode 100644 otf-frontend/client/src/app/access-denied/access-denied.component.html create mode 100644 otf-frontend/client/src/app/access-denied/access-denied.component.scss create mode 100644 otf-frontend/client/src/app/access-denied/access-denied.component.spec.ts create mode 100644 otf-frontend/client/src/app/access-denied/access-denied.component.ts create mode 100644 otf-frontend/client/src/app/access-denied/access-denied.module.spec.ts create mode 100644 otf-frontend/client/src/app/access-denied/access-denied.module.ts create mode 100644 otf-frontend/client/src/app/account/account-routing.module.ts create mode 100644 otf-frontend/client/src/app/account/account.component.html create mode 100644 otf-frontend/client/src/app/account/account.component.scss create mode 100644 otf-frontend/client/src/app/account/account.component.spec.ts create mode 100644 otf-frontend/client/src/app/account/account.component.ts create mode 100644 otf-frontend/client/src/app/account/account.module.spec.ts create mode 100644 otf-frontend/client/src/app/account/account.module.ts create mode 100644 otf-frontend/client/src/app/app-routing.module.ts create mode 100644 otf-frontend/client/src/app/app.component.html create mode 100644 otf-frontend/client/src/app/app.component.scss create mode 100644 otf-frontend/client/src/app/app.component.spec.ts create mode 100644 otf-frontend/client/src/app/app.component.ts create mode 100644 otf-frontend/client/src/app/app.global.ts create mode 100644 otf-frontend/client/src/app/app.module.spec.ts create mode 100644 otf-frontend/client/src/app/app.module.ts create mode 100644 otf-frontend/client/src/app/core/core.module.spec.ts create mode 100644 otf-frontend/client/src/app/core/core.module.ts create mode 100644 otf-frontend/client/src/app/error.interceptor.ts create mode 100644 otf-frontend/client/src/app/layout/components/header/header.component.html create mode 100644 otf-frontend/client/src/app/layout/components/header/header.component.scss create mode 100644 otf-frontend/client/src/app/layout/components/header/header.component.spec.ts create mode 100644 otf-frontend/client/src/app/layout/components/header/header.component.ts create mode 100644 otf-frontend/client/src/app/layout/components/right-sidebar/right-sidebar.component.html create mode 100644 otf-frontend/client/src/app/layout/components/right-sidebar/right-sidebar.component.scss create mode 100644 otf-frontend/client/src/app/layout/components/right-sidebar/right-sidebar.component.spec.ts create mode 100644 otf-frontend/client/src/app/layout/components/right-sidebar/right-sidebar.component.ts create mode 100644 otf-frontend/client/src/app/layout/components/sidebar/sidebar.component.html create mode 100644 otf-frontend/client/src/app/layout/components/sidebar/sidebar.component.scss create mode 100644 otf-frontend/client/src/app/layout/components/sidebar/sidebar.component.spec.ts create mode 100644 otf-frontend/client/src/app/layout/components/sidebar/sidebar.component.ts create mode 100644 otf-frontend/client/src/app/layout/components/stats/assets/icons/ProfessionalHeadshot(2).png create mode 100644 otf-frontend/client/src/app/layout/components/stats/assets/icons/download.jfif create mode 100644 otf-frontend/client/src/app/layout/components/stats/assets/icons/equalizer.gif create mode 100644 otf-frontend/client/src/app/layout/components/stats/assets/icons/loading-pies.gif create mode 100644 otf-frontend/client/src/app/layout/components/stats/assets/icons/loading-pies.svg create mode 100644 otf-frontend/client/src/app/layout/components/stats/filter-modal/filter-modal.component.pug create mode 100644 otf-frontend/client/src/app/layout/components/stats/filter-modal/filter-modal.component.scss create mode 100644 otf-frontend/client/src/app/layout/components/stats/filter-modal/filter-modal.component.spec.ts create mode 100644 otf-frontend/client/src/app/layout/components/stats/filter-modal/filter-modal.component.ts create mode 100644 otf-frontend/client/src/app/layout/components/stats/horiz-bar-chart/horiz-bar-chart.component.pug create mode 100644 otf-frontend/client/src/app/layout/components/stats/horiz-bar-chart/horiz-bar-chart.component.scss create mode 100644 otf-frontend/client/src/app/layout/components/stats/horiz-bar-chart/horiz-bar-chart.component.spec.ts create mode 100644 otf-frontend/client/src/app/layout/components/stats/horiz-bar-chart/horiz-bar-chart.component.ts create mode 100644 otf-frontend/client/src/app/layout/components/stats/line-chart/line-chart.component.pug create mode 100644 otf-frontend/client/src/app/layout/components/stats/line-chart/line-chart.component.scss create mode 100644 otf-frontend/client/src/app/layout/components/stats/line-chart/line-chart.component.spec.ts create mode 100644 otf-frontend/client/src/app/layout/components/stats/line-chart/line-chart.component.ts create mode 100644 otf-frontend/client/src/app/layout/components/stats/multi-line-chart/multi-line-chart.component.pug create mode 100644 otf-frontend/client/src/app/layout/components/stats/multi-line-chart/multi-line-chart.component.scss create mode 100644 otf-frontend/client/src/app/layout/components/stats/multi-line-chart/multi-line-chart.component.spec.ts create mode 100644 otf-frontend/client/src/app/layout/components/stats/multi-line-chart/multi-line-chart.component.ts create mode 100644 otf-frontend/client/src/app/layout/components/stats/pie-chart/pie-chart.component.pug create mode 100644 otf-frontend/client/src/app/layout/components/stats/pie-chart/pie-chart.component.scss create mode 100644 otf-frontend/client/src/app/layout/components/stats/pie-chart/pie-chart.component.spec.ts create mode 100644 otf-frontend/client/src/app/layout/components/stats/pie-chart/pie-chart.component.ts create mode 100644 otf-frontend/client/src/app/layout/components/stats/schedule/schedule.component.pug create mode 100644 otf-frontend/client/src/app/layout/components/stats/schedule/schedule.component.scss create mode 100644 otf-frontend/client/src/app/layout/components/stats/schedule/schedule.component.spec.ts create mode 100644 otf-frontend/client/src/app/layout/components/stats/schedule/schedule.component.ts create mode 100644 otf-frontend/client/src/app/layout/components/stats/stats.service.spec.ts create mode 100644 otf-frontend/client/src/app/layout/components/stats/stats.service.ts create mode 100644 otf-frontend/client/src/app/layout/components/stats/test-definition-executions-bar-chart/test-definition-executions-bar-chart.component.pug create mode 100644 otf-frontend/client/src/app/layout/components/stats/test-definition-executions-bar-chart/test-definition-executions-bar-chart.component.scss create mode 100644 otf-frontend/client/src/app/layout/components/stats/test-definition-executions-bar-chart/test-definition-executions-bar-chart.component.spec.ts create mode 100644 otf-frontend/client/src/app/layout/components/stats/test-definition-executions-bar-chart/test-definition-executions-bar-chart.component.ts create mode 100644 otf-frontend/client/src/app/layout/components/stats/test-head-execution-bar-chart/test-head-execution-bar-chart.component.pug create mode 100644 otf-frontend/client/src/app/layout/components/stats/test-head-execution-bar-chart/test-head-execution-bar-chart.component.scss create mode 100644 otf-frontend/client/src/app/layout/components/stats/test-head-execution-bar-chart/test-head-execution-bar-chart.component.spec.ts create mode 100644 otf-frontend/client/src/app/layout/components/stats/test-head-execution-bar-chart/test-head-execution-bar-chart.component.ts create mode 100644 otf-frontend/client/src/app/layout/components/stats/test-head-executions-line-chart/test-head-executions-line-chart.component.pug create mode 100644 otf-frontend/client/src/app/layout/components/stats/test-head-executions-line-chart/test-head-executions-line-chart.component.scss create mode 100644 otf-frontend/client/src/app/layout/components/stats/test-head-executions-line-chart/test-head-executions-line-chart.component.spec.ts create mode 100644 otf-frontend/client/src/app/layout/components/stats/test-head-executions-line-chart/test-head-executions-line-chart.component.ts create mode 100644 otf-frontend/client/src/app/layout/control-panel/control-panel-routing.module.ts create mode 100644 otf-frontend/client/src/app/layout/control-panel/control-panel.component.pug create mode 100644 otf-frontend/client/src/app/layout/control-panel/control-panel.component.scss create mode 100644 otf-frontend/client/src/app/layout/control-panel/control-panel.component.spec.ts create mode 100644 otf-frontend/client/src/app/layout/control-panel/control-panel.component.ts create mode 100644 otf-frontend/client/src/app/layout/control-panel/control-panel.module.spec.ts create mode 100644 otf-frontend/client/src/app/layout/control-panel/control-panel.module.ts create mode 100644 otf-frontend/client/src/app/layout/dashboard/dashboard-routing.module.ts create mode 100644 otf-frontend/client/src/app/layout/dashboard/dashboard.component.pug create mode 100644 otf-frontend/client/src/app/layout/dashboard/dashboard.component.scss create mode 100644 otf-frontend/client/src/app/layout/dashboard/dashboard.component.spec.ts create mode 100644 otf-frontend/client/src/app/layout/dashboard/dashboard.component.ts create mode 100644 otf-frontend/client/src/app/layout/dashboard/dashboard.module.spec.ts create mode 100644 otf-frontend/client/src/app/layout/dashboard/dashboard.module.ts create mode 100644 otf-frontend/client/src/app/layout/feedback/feedback-routing.module.ts create mode 100644 otf-frontend/client/src/app/layout/feedback/feedback.component.pug create mode 100644 otf-frontend/client/src/app/layout/feedback/feedback.component.scss create mode 100644 otf-frontend/client/src/app/layout/feedback/feedback.component.spec.ts create mode 100644 otf-frontend/client/src/app/layout/feedback/feedback.component.ts create mode 100644 otf-frontend/client/src/app/layout/feedback/feedback.module.spec.ts create mode 100644 otf-frontend/client/src/app/layout/feedback/feedback.module.ts create mode 100644 otf-frontend/client/src/app/layout/layout-routing.module.ts create mode 100644 otf-frontend/client/src/app/layout/layout.component.html create mode 100644 otf-frontend/client/src/app/layout/layout.component.scss create mode 100644 otf-frontend/client/src/app/layout/layout.component.spec.ts create mode 100644 otf-frontend/client/src/app/layout/layout.component.ts create mode 100644 otf-frontend/client/src/app/layout/layout.module.spec.ts create mode 100644 otf-frontend/client/src/app/layout/layout.module.ts create mode 100644 otf-frontend/client/src/app/layout/manage-group/dropdown-multiselect.component.pug create mode 100644 otf-frontend/client/src/app/layout/manage-group/dropdown-multiselect.component.scss create mode 100644 otf-frontend/client/src/app/layout/manage-group/dropdown-multiselect.component.spec.ts create mode 100644 otf-frontend/client/src/app/layout/manage-group/dropdown-multiselect.component.ts create mode 100644 otf-frontend/client/src/app/layout/manage-group/manage-group-roles/manage-group-roles.component.pug create mode 100644 otf-frontend/client/src/app/layout/manage-group/manage-group-roles/manage-group-roles.component.scss create mode 100644 otf-frontend/client/src/app/layout/manage-group/manage-group-roles/manage-group-roles.component.spec.ts create mode 100644 otf-frontend/client/src/app/layout/manage-group/manage-group-roles/manage-group-roles.component.ts create mode 100644 otf-frontend/client/src/app/layout/manage-group/manage-group-routing.module.ts create mode 100644 otf-frontend/client/src/app/layout/manage-group/manage-group.component.pug create mode 100644 otf-frontend/client/src/app/layout/manage-group/manage-group.component.scss create mode 100644 otf-frontend/client/src/app/layout/manage-group/manage-group.component.spec.ts create mode 100644 otf-frontend/client/src/app/layout/manage-group/manage-group.component.ts create mode 100644 otf-frontend/client/src/app/layout/manage-group/manage-group.module.spec.ts create mode 100644 otf-frontend/client/src/app/layout/manage-group/manage-group.module.ts create mode 100644 otf-frontend/client/src/app/layout/modeler/color-picker/ColorPicker.js create mode 100644 otf-frontend/client/src/app/layout/modeler/color-picker/ColoredRenderer.js create mode 100644 otf-frontend/client/src/app/layout/modeler/color-picker/index.js create mode 100644 otf-frontend/client/src/app/layout/modeler/custom-elements/log-test-result/draw/LogTestResultRenderer.js create mode 100644 otf-frontend/client/src/app/layout/modeler/custom-elements/log-test-result/draw/index.js create mode 100644 otf-frontend/client/src/app/layout/modeler/custom-elements/log-test-result/image/cat.gif create mode 100644 otf-frontend/client/src/app/layout/modeler/custom-elements/log-test-result/image/index.js create mode 100644 otf-frontend/client/src/app/layout/modeler/custom-elements/log-test-result/palette/LogTestResultPaletteProvider.js create mode 100644 otf-frontend/client/src/app/layout/modeler/custom-elements/log-test-result/palette/index.js create mode 100644 otf-frontend/client/src/app/layout/modeler/modeler-routing.module.ts create mode 100644 otf-frontend/client/src/app/layout/modeler/modeler.component.pug create mode 100644 otf-frontend/client/src/app/layout/modeler/modeler.component.scss create mode 100644 otf-frontend/client/src/app/layout/modeler/modeler.component.spec.ts create mode 100644 otf-frontend/client/src/app/layout/modeler/modeler.component.ts create mode 100644 otf-frontend/client/src/app/layout/modeler/modeler.module.spec.ts create mode 100644 otf-frontend/client/src/app/layout/modeler/modeler.module.ts create mode 100644 otf-frontend/client/src/app/layout/modeler/new.bpmn create mode 100644 otf-frontend/client/src/app/layout/modeler/templates/elements.json create mode 100644 otf-frontend/client/src/app/layout/modeler/test-definition-element.class.ts create mode 100644 otf-frontend/client/src/app/layout/onboarding/create-test/create-test-routing.module.ts create mode 100644 otf-frontend/client/src/app/layout/onboarding/create-test/create-test.component.pug create mode 100644 otf-frontend/client/src/app/layout/onboarding/create-test/create-test.component.scss create mode 100644 otf-frontend/client/src/app/layout/onboarding/create-test/create-test.component.spec.ts create mode 100644 otf-frontend/client/src/app/layout/onboarding/create-test/create-test.component.ts create mode 100644 otf-frontend/client/src/app/layout/onboarding/create-test/create-test.module.spec.ts create mode 100644 otf-frontend/client/src/app/layout/onboarding/create-test/create-test.module.ts create mode 100644 otf-frontend/client/src/app/layout/onboarding/onboarding-routing.module.ts create mode 100644 otf-frontend/client/src/app/layout/onboarding/onboarding.component.pug create mode 100644 otf-frontend/client/src/app/layout/onboarding/onboarding.component.scss create mode 100644 otf-frontend/client/src/app/layout/onboarding/onboarding.component.spec.ts create mode 100644 otf-frontend/client/src/app/layout/onboarding/onboarding.component.ts create mode 100644 otf-frontend/client/src/app/layout/onboarding/onboarding.module.spec.ts create mode 100644 otf-frontend/client/src/app/layout/onboarding/onboarding.module.ts create mode 100644 otf-frontend/client/src/app/layout/onboarding/onboarding.service.ts create mode 100644 otf-frontend/client/src/app/layout/onboarding/start/start-routing.module.ts create mode 100644 otf-frontend/client/src/app/layout/onboarding/start/start.component.pug create mode 100644 otf-frontend/client/src/app/layout/onboarding/start/start.component.scss create mode 100644 otf-frontend/client/src/app/layout/onboarding/start/start.component.spec.ts create mode 100644 otf-frontend/client/src/app/layout/onboarding/start/start.component.ts create mode 100644 otf-frontend/client/src/app/layout/onboarding/start/start.module.spec.ts create mode 100644 otf-frontend/client/src/app/layout/onboarding/start/start.module.ts create mode 100644 otf-frontend/client/src/app/layout/onboarding/test-head/test-head-routing.module.ts create mode 100644 otf-frontend/client/src/app/layout/onboarding/test-head/test-head.component.pug create mode 100644 otf-frontend/client/src/app/layout/onboarding/test-head/test-head.component.scss create mode 100644 otf-frontend/client/src/app/layout/onboarding/test-head/test-head.component.spec.ts create mode 100644 otf-frontend/client/src/app/layout/onboarding/test-head/test-head.component.ts create mode 100644 otf-frontend/client/src/app/layout/onboarding/test-head/test-head.module.spec.ts create mode 100644 otf-frontend/client/src/app/layout/onboarding/test-head/test-head.module.ts create mode 100644 otf-frontend/client/src/app/layout/onboarding/test-instances/test-instances-routing.module.ts create mode 100644 otf-frontend/client/src/app/layout/onboarding/test-instances/test-instances.component.pug create mode 100644 otf-frontend/client/src/app/layout/onboarding/test-instances/test-instances.component.scss create mode 100644 otf-frontend/client/src/app/layout/onboarding/test-instances/test-instances.component.spec.ts create mode 100644 otf-frontend/client/src/app/layout/onboarding/test-instances/test-instances.component.ts create mode 100644 otf-frontend/client/src/app/layout/onboarding/test-instances/test-instances.module.spec.ts create mode 100644 otf-frontend/client/src/app/layout/onboarding/test-instances/test-instances.module.ts create mode 100644 otf-frontend/client/src/app/layout/robot-report/robot-report.component.pug create mode 100644 otf-frontend/client/src/app/layout/robot-report/robot-report.component.scss create mode 100644 otf-frontend/client/src/app/layout/robot-report/robot-report.component.spec.ts create mode 100644 otf-frontend/client/src/app/layout/robot-report/robot-report.component.ts create mode 100644 otf-frontend/client/src/app/layout/scheduling/scheduling-routing.module.ts create mode 100644 otf-frontend/client/src/app/layout/scheduling/scheduling.component.pug create mode 100644 otf-frontend/client/src/app/layout/scheduling/scheduling.component.scss create mode 100644 otf-frontend/client/src/app/layout/scheduling/scheduling.component.spec.ts create mode 100644 otf-frontend/client/src/app/layout/scheduling/scheduling.component.ts create mode 100644 otf-frontend/client/src/app/layout/scheduling/scheduling.module.spec.ts create mode 100644 otf-frontend/client/src/app/layout/scheduling/scheduling.module.ts create mode 100644 otf-frontend/client/src/app/layout/settings/settings-routing.module.ts create mode 100644 otf-frontend/client/src/app/layout/settings/settings.component.pug create mode 100644 otf-frontend/client/src/app/layout/settings/settings.component.scss create mode 100644 otf-frontend/client/src/app/layout/settings/settings.component.spec.ts create mode 100644 otf-frontend/client/src/app/layout/settings/settings.component.ts create mode 100644 otf-frontend/client/src/app/layout/settings/settings.module.spec.ts create mode 100644 otf-frontend/client/src/app/layout/settings/settings.module.ts create mode 100644 otf-frontend/client/src/app/layout/test-definition-expanded-details/test-definition-expanded-details.component.pug create mode 100644 otf-frontend/client/src/app/layout/test-definition-expanded-details/test-definition-expanded-details.component.scss create mode 100644 otf-frontend/client/src/app/layout/test-definition-expanded-details/test-definition-expanded-details.component.spec.ts create mode 100644 otf-frontend/client/src/app/layout/test-definition-expanded-details/test-definition-expanded-details.component.ts create mode 100644 otf-frontend/client/src/app/layout/test-executions-catalog/test-executions-catalog-routing.module.ts create mode 100644 otf-frontend/client/src/app/layout/test-executions-catalog/test-executions-catalog.component.pug create mode 100644 otf-frontend/client/src/app/layout/test-executions-catalog/test-executions-catalog.component.scss create mode 100644 otf-frontend/client/src/app/layout/test-executions-catalog/test-executions-catalog.component.spec.ts create mode 100644 otf-frontend/client/src/app/layout/test-executions-catalog/test-executions-catalog.component.ts create mode 100644 otf-frontend/client/src/app/layout/test-executions-catalog/test-executions-catalog.module.spec.ts create mode 100644 otf-frontend/client/src/app/layout/test-executions-catalog/test-executions-catalog.module.ts create mode 100644 otf-frontend/client/src/app/layout/test-instance-expanded-details/test-instance-expanded-details.component.pug create mode 100644 otf-frontend/client/src/app/layout/test-instance-expanded-details/test-instance-expanded-details.component.scss create mode 100644 otf-frontend/client/src/app/layout/test-instance-expanded-details/test-instance-expanded-details.component.spec.ts create mode 100644 otf-frontend/client/src/app/layout/test-instance-expanded-details/test-instance-expanded-details.component.ts create mode 100644 otf-frontend/client/src/app/layout/test-instances-catalog/test-instances-catalog-routing.module.ts create mode 100644 otf-frontend/client/src/app/layout/test-instances-catalog/test-instances-catalog.component.pug create mode 100644 otf-frontend/client/src/app/layout/test-instances-catalog/test-instances-catalog.component.scss create mode 100644 otf-frontend/client/src/app/layout/test-instances-catalog/test-instances-catalog.component.spec.ts create mode 100644 otf-frontend/client/src/app/layout/test-instances-catalog/test-instances-catalog.component.ts create mode 100644 otf-frontend/client/src/app/layout/test-instances-catalog/test-instances-catalog.module.spec.ts create mode 100644 otf-frontend/client/src/app/layout/test-instances-catalog/test-instances-catalog.module.ts create mode 100644 otf-frontend/client/src/app/layout/tests/test-definition-details/test-definition-details.component.pug create mode 100644 otf-frontend/client/src/app/layout/tests/test-definition-details/test-definition-details.component.scss create mode 100644 otf-frontend/client/src/app/layout/tests/test-definition-details/test-definition-details.component.spec.ts create mode 100644 otf-frontend/client/src/app/layout/tests/test-definition-details/test-definition-details.component.ts create mode 100644 otf-frontend/client/src/app/layout/tests/tests-routing.module.ts create mode 100644 otf-frontend/client/src/app/layout/tests/tests.component.pug create mode 100644 otf-frontend/client/src/app/layout/tests/tests.component.scss create mode 100644 otf-frontend/client/src/app/layout/tests/tests.component.spec.ts create mode 100644 otf-frontend/client/src/app/layout/tests/tests.component.ts create mode 100644 otf-frontend/client/src/app/layout/tests/tests.module.spec.ts create mode 100644 otf-frontend/client/src/app/layout/tests/tests.module.ts create mode 100644 otf-frontend/client/src/app/layout/user-management/user-management-routing.module.ts create mode 100644 otf-frontend/client/src/app/layout/user-management/user-management.component.pug create mode 100644 otf-frontend/client/src/app/layout/user-management/user-management.component.scss create mode 100644 otf-frontend/client/src/app/layout/user-management/user-management.component.spec.ts create mode 100644 otf-frontend/client/src/app/layout/user-management/user-management.component.ts create mode 100644 otf-frontend/client/src/app/layout/user-management/user-management.module.spec.ts create mode 100644 otf-frontend/client/src/app/layout/user-management/user-management.module.ts create mode 100644 otf-frontend/client/src/app/layout/virtual-test-heads/virtual-test-head-details/charts/test-head-executions-line-chart/test-head-executions-line-chart.component.pug create mode 100644 otf-frontend/client/src/app/layout/virtual-test-heads/virtual-test-head-details/charts/test-head-executions-line-chart/test-head-executions-line-chart.component.scss create mode 100644 otf-frontend/client/src/app/layout/virtual-test-heads/virtual-test-head-details/charts/test-head-executions-line-chart/test-head-executions-line-chart.component.spec.ts create mode 100644 otf-frontend/client/src/app/layout/virtual-test-heads/virtual-test-head-details/charts/test-head-executions-line-chart/test-head-executions-line-chart.component.ts create mode 100644 otf-frontend/client/src/app/layout/virtual-test-heads/virtual-test-head-details/virtual-test-head-details.component.pug create mode 100644 otf-frontend/client/src/app/layout/virtual-test-heads/virtual-test-head-details/virtual-test-head-details.component.scss create mode 100644 otf-frontend/client/src/app/layout/virtual-test-heads/virtual-test-head-details/virtual-test-head-details.component.spec.ts create mode 100644 otf-frontend/client/src/app/layout/virtual-test-heads/virtual-test-head-details/virtual-test-head-details.component.ts create mode 100644 otf-frontend/client/src/app/layout/virtual-test-heads/virtual-test-heads-routing.module.ts create mode 100644 otf-frontend/client/src/app/layout/virtual-test-heads/virtual-test-heads.component.pug create mode 100644 otf-frontend/client/src/app/layout/virtual-test-heads/virtual-test-heads.component.scss create mode 100644 otf-frontend/client/src/app/layout/virtual-test-heads/virtual-test-heads.component.spec.ts create mode 100644 otf-frontend/client/src/app/layout/virtual-test-heads/virtual-test-heads.component.ts create mode 100644 otf-frontend/client/src/app/layout/virtual-test-heads/virtual-test-heads.module.spec.ts create mode 100644 otf-frontend/client/src/app/layout/virtual-test-heads/virtual-test-heads.module.ts create mode 100644 otf-frontend/client/src/app/login/login-routing.module.ts create mode 100644 otf-frontend/client/src/app/login/login.component.html create mode 100644 otf-frontend/client/src/app/login/login.component.scss create mode 100644 otf-frontend/client/src/app/login/login.component.spec.ts create mode 100644 otf-frontend/client/src/app/login/login.component.ts create mode 100644 otf-frontend/client/src/app/login/login.module.spec.ts create mode 100644 otf-frontend/client/src/app/login/login.module.ts create mode 100644 otf-frontend/client/src/app/not-found/not-found-routing.module.ts create mode 100644 otf-frontend/client/src/app/not-found/not-found.component.html create mode 100644 otf-frontend/client/src/app/not-found/not-found.component.pug create mode 100644 otf-frontend/client/src/app/not-found/not-found.component.scss create mode 100644 otf-frontend/client/src/app/not-found/not-found.component.spec.ts create mode 100644 otf-frontend/client/src/app/not-found/not-found.component.ts create mode 100644 otf-frontend/client/src/app/not-found/not-found.module.spec.ts create mode 100644 otf-frontend/client/src/app/not-found/not-found.module.ts create mode 100644 otf-frontend/client/src/app/router.animations.ts create mode 100644 otf-frontend/client/src/app/server-error/server-error-routing.module.ts create mode 100644 otf-frontend/client/src/app/server-error/server-error.component.html create mode 100644 otf-frontend/client/src/app/server-error/server-error.component.scss create mode 100644 otf-frontend/client/src/app/server-error/server-error.component.spec.ts create mode 100644 otf-frontend/client/src/app/server-error/server-error.component.ts create mode 100644 otf-frontend/client/src/app/server-error/server-error.module.spec.ts create mode 100644 otf-frontend/client/src/app/server-error/server-error.module.ts create mode 100644 otf-frontend/client/src/app/shared/components/menu-item/menu-item.component.pug create mode 100644 otf-frontend/client/src/app/shared/components/menu-item/menu-item.component.scss create mode 100644 otf-frontend/client/src/app/shared/components/menu-item/menu-item.component.spec.ts create mode 100644 otf-frontend/client/src/app/shared/components/menu-item/menu-item.component.ts create mode 100644 otf-frontend/client/src/app/shared/factories/bpmn-factory.service.spec.ts create mode 100644 otf-frontend/client/src/app/shared/factories/bpmn-factory.service.ts create mode 100644 otf-frontend/client/src/app/shared/guard/admin.guard.spec.ts create mode 100644 otf-frontend/client/src/app/shared/guard/admin.guard.ts create mode 100644 otf-frontend/client/src/app/shared/guard/auth.guard.spec.ts create mode 100644 otf-frontend/client/src/app/shared/guard/auth.guard.ts create mode 100644 otf-frontend/client/src/app/shared/guard/index.ts create mode 100644 otf-frontend/client/src/app/shared/index.ts create mode 100644 otf-frontend/client/src/app/shared/models/base-model.model.ts create mode 100644 otf-frontend/client/src/app/shared/models/bpmn.model.ts create mode 100644 otf-frontend/client/src/app/shared/models/group.model.ts create mode 100644 otf-frontend/client/src/app/shared/models/test-definition.model.ts create mode 100644 otf-frontend/client/src/app/shared/models/test-execution.model.ts create mode 100644 otf-frontend/client/src/app/shared/models/test-head.model.ts create mode 100644 otf-frontend/client/src/app/shared/models/test-instance.model.ts create mode 100644 otf-frontend/client/src/app/shared/models/user.model.ts create mode 100644 otf-frontend/client/src/app/shared/modules/alert-modal/alert-modal.component.pug create mode 100644 otf-frontend/client/src/app/shared/modules/alert-modal/alert-modal.component.scss create mode 100644 otf-frontend/client/src/app/shared/modules/alert-modal/alert-modal.component.spec.ts create mode 100644 otf-frontend/client/src/app/shared/modules/alert-modal/alert-modal.component.ts create mode 100644 otf-frontend/client/src/app/shared/modules/alert-modal/alert-modal.module.spec.ts create mode 100644 otf-frontend/client/src/app/shared/modules/alert-modal/alert-modal.module.ts create mode 100644 otf-frontend/client/src/app/shared/modules/alert-snackbar/alert-snackbar.component.pug create mode 100644 otf-frontend/client/src/app/shared/modules/alert-snackbar/alert-snackbar.component.scss create mode 100644 otf-frontend/client/src/app/shared/modules/alert-snackbar/alert-snackbar.component.spec.ts create mode 100644 otf-frontend/client/src/app/shared/modules/alert-snackbar/alert-snackbar.component.ts create mode 100644 otf-frontend/client/src/app/shared/modules/alert-snackbar/alert-snackbar.module.spec.ts create mode 100644 otf-frontend/client/src/app/shared/modules/alert-snackbar/alert-snackbar.module.ts create mode 100644 otf-frontend/client/src/app/shared/modules/create-group-modal/create-group-modal.component.pug create mode 100644 otf-frontend/client/src/app/shared/modules/create-group-modal/create-group-modal.component.scss create mode 100644 otf-frontend/client/src/app/shared/modules/create-group-modal/create-group-modal.component.spec.ts create mode 100644 otf-frontend/client/src/app/shared/modules/create-group-modal/create-group-modal.component.ts create mode 100644 otf-frontend/client/src/app/shared/modules/create-group-modal/create-group-modal.module.spec.ts create mode 100644 otf-frontend/client/src/app/shared/modules/create-group-modal/create-group-modal.module.ts create mode 100644 otf-frontend/client/src/app/shared/modules/create-test-form/create-test-form.component.pug create mode 100644 otf-frontend/client/src/app/shared/modules/create-test-form/create-test-form.component.scss create mode 100644 otf-frontend/client/src/app/shared/modules/create-test-form/create-test-form.component.spec.ts create mode 100644 otf-frontend/client/src/app/shared/modules/create-test-form/create-test-form.component.ts create mode 100644 otf-frontend/client/src/app/shared/modules/create-test-form/create-test-form.module.spec.ts create mode 100644 otf-frontend/client/src/app/shared/modules/create-test-form/create-test-form.module.ts create mode 100644 otf-frontend/client/src/app/shared/modules/create-test-form/definition-instance.class.ts create mode 100644 otf-frontend/client/src/app/shared/modules/create-test-form/test-definition.class.ts create mode 100644 otf-frontend/client/src/app/shared/modules/create-test-head-form/create-test-head-form.component.pug create mode 100644 otf-frontend/client/src/app/shared/modules/create-test-head-form/create-test-head-form.component.scss create mode 100644 otf-frontend/client/src/app/shared/modules/create-test-head-form/create-test-head-form.component.spec.ts create mode 100644 otf-frontend/client/src/app/shared/modules/create-test-head-form/create-test-head-form.component.ts create mode 100644 otf-frontend/client/src/app/shared/modules/create-test-head-form/create-test-head-form.module.spec.ts create mode 100644 otf-frontend/client/src/app/shared/modules/create-test-head-form/create-test-head-form.module.ts create mode 100644 otf-frontend/client/src/app/shared/modules/create-test-instance-form/create-test-instance-form.component.pug create mode 100644 otf-frontend/client/src/app/shared/modules/create-test-instance-form/create-test-instance-form.component.scss create mode 100644 otf-frontend/client/src/app/shared/modules/create-test-instance-form/create-test-instance-form.component.spec.ts create mode 100644 otf-frontend/client/src/app/shared/modules/create-test-instance-form/create-test-instance-form.component.ts create mode 100644 otf-frontend/client/src/app/shared/modules/create-test-instance-form/create-test-instance-form.module.spec.ts create mode 100644 otf-frontend/client/src/app/shared/modules/create-test-instance-form/create-test-instance-form.module.ts create mode 100644 otf-frontend/client/src/app/shared/modules/create-test-instance-form/filterNonDeployed.pipe.ts create mode 100644 otf-frontend/client/src/app/shared/modules/create-test-instance-form/instance.class.ts create mode 100644 otf-frontend/client/src/app/shared/modules/form-generator/form-generator.component.html create mode 100644 otf-frontend/client/src/app/shared/modules/form-generator/form-generator.component.scss create mode 100644 otf-frontend/client/src/app/shared/modules/form-generator/form-generator.component.spec.ts create mode 100644 otf-frontend/client/src/app/shared/modules/form-generator/form-generator.component.ts create mode 100644 otf-frontend/client/src/app/shared/modules/form-generator/form-generator.module.spec.ts create mode 100644 otf-frontend/client/src/app/shared/modules/form-generator/form-generator.module.ts create mode 100644 otf-frontend/client/src/app/shared/modules/form-generator/text-area/text-area.component.html create mode 100644 otf-frontend/client/src/app/shared/modules/form-generator/text-area/text-area.component.scss create mode 100644 otf-frontend/client/src/app/shared/modules/form-generator/text-area/text-area.component.spec.ts create mode 100644 otf-frontend/client/src/app/shared/modules/form-generator/text-area/text-area.component.ts create mode 100644 otf-frontend/client/src/app/shared/modules/index.ts create mode 100644 otf-frontend/client/src/app/shared/modules/onboard-mechid/onboard-mechid.component.pug create mode 100644 otf-frontend/client/src/app/shared/modules/onboard-mechid/onboard-mechid.component.scss create mode 100644 otf-frontend/client/src/app/shared/modules/onboard-mechid/onboard-mechid.component.spec.ts create mode 100644 otf-frontend/client/src/app/shared/modules/onboard-mechid/onboard-mechid.component.ts create mode 100644 otf-frontend/client/src/app/shared/modules/onboard-mechid/onboard-mechid.module.spec.ts create mode 100644 otf-frontend/client/src/app/shared/modules/onboard-mechid/onboard-mechid.module.ts create mode 100644 otf-frontend/client/src/app/shared/modules/page-header/page-header.component.html create mode 100644 otf-frontend/client/src/app/shared/modules/page-header/page-header.component.scss create mode 100644 otf-frontend/client/src/app/shared/modules/page-header/page-header.component.spec.ts create mode 100644 otf-frontend/client/src/app/shared/modules/page-header/page-header.component.ts create mode 100644 otf-frontend/client/src/app/shared/modules/page-header/page-header.module.spec.ts create mode 100644 otf-frontend/client/src/app/shared/modules/page-header/page-header.module.ts create mode 100644 otf-frontend/client/src/app/shared/modules/schedule-test-modal/schedule-test-modal.component.pug create mode 100644 otf-frontend/client/src/app/shared/modules/schedule-test-modal/schedule-test-modal.component.scss create mode 100644 otf-frontend/client/src/app/shared/modules/schedule-test-modal/schedule-test-modal.component.spec.ts create mode 100644 otf-frontend/client/src/app/shared/modules/schedule-test-modal/schedule-test-modal.component.ts create mode 100644 otf-frontend/client/src/app/shared/modules/schedule-test-modal/schedule-test-modal.module.spec.ts create mode 100644 otf-frontend/client/src/app/shared/modules/schedule-test-modal/schedule-test-modal.module.ts create mode 100644 otf-frontend/client/src/app/shared/modules/select-strategy-modal/select-strategy-modal.component.pug create mode 100644 otf-frontend/client/src/app/shared/modules/select-strategy-modal/select-strategy-modal.component.scss create mode 100644 otf-frontend/client/src/app/shared/modules/select-strategy-modal/select-strategy-modal.component.spec.ts create mode 100644 otf-frontend/client/src/app/shared/modules/select-strategy-modal/select-strategy-modal.component.ts create mode 100644 otf-frontend/client/src/app/shared/modules/select-strategy-modal/select-strategy-modal.module.spec.ts create mode 100644 otf-frontend/client/src/app/shared/modules/select-strategy-modal/select-strategy-modal.module.ts create mode 100644 otf-frontend/client/src/app/shared/modules/select-test-head-modal/select-test-head-modal.component.pug create mode 100644 otf-frontend/client/src/app/shared/modules/select-test-head-modal/select-test-head-modal.component.scss create mode 100644 otf-frontend/client/src/app/shared/modules/select-test-head-modal/select-test-head-modal.component.spec.ts create mode 100644 otf-frontend/client/src/app/shared/modules/select-test-head-modal/select-test-head-modal.component.ts create mode 100644 otf-frontend/client/src/app/shared/modules/select-test-head-modal/select-test-head-modal.module.spec.ts create mode 100644 otf-frontend/client/src/app/shared/modules/select-test-head-modal/select-test-head-modal.module.ts create mode 100644 otf-frontend/client/src/app/shared/modules/stat/stat.component.html create mode 100644 otf-frontend/client/src/app/shared/modules/stat/stat.component.scss create mode 100644 otf-frontend/client/src/app/shared/modules/stat/stat.component.spec.ts create mode 100644 otf-frontend/client/src/app/shared/modules/stat/stat.component.ts create mode 100644 otf-frontend/client/src/app/shared/modules/stat/stat.module.spec.ts create mode 100644 otf-frontend/client/src/app/shared/modules/stat/stat.module.ts create mode 100644 otf-frontend/client/src/app/shared/modules/test-definition-modal/test-definition-modal.component.pug create mode 100644 otf-frontend/client/src/app/shared/modules/test-definition-modal/test-definition-modal.component.scss create mode 100644 otf-frontend/client/src/app/shared/modules/test-definition-modal/test-definition-modal.component.spec.ts create mode 100644 otf-frontend/client/src/app/shared/modules/test-definition-modal/test-definition-modal.component.ts create mode 100644 otf-frontend/client/src/app/shared/modules/test-definition-modal/test-definition-modal.module.spec.ts create mode 100644 otf-frontend/client/src/app/shared/modules/test-definition-modal/test-definition-modal.module.ts create mode 100644 otf-frontend/client/src/app/shared/modules/test-head-modal/test-head-modal.component.pug create mode 100644 otf-frontend/client/src/app/shared/modules/test-head-modal/test-head-modal.component.scss create mode 100644 otf-frontend/client/src/app/shared/modules/test-head-modal/test-head-modal.component.spec.ts create mode 100644 otf-frontend/client/src/app/shared/modules/test-head-modal/test-head-modal.component.ts create mode 100644 otf-frontend/client/src/app/shared/modules/test-head-modal/test-head-modal.module.spec.ts create mode 100644 otf-frontend/client/src/app/shared/modules/test-head-modal/test-head-modal.module.ts create mode 100644 otf-frontend/client/src/app/shared/modules/test-instance-modal/test-instance-modal.component.pug create mode 100644 otf-frontend/client/src/app/shared/modules/test-instance-modal/test-instance-modal.component.scss create mode 100644 otf-frontend/client/src/app/shared/modules/test-instance-modal/test-instance-modal.component.spec.ts create mode 100644 otf-frontend/client/src/app/shared/modules/test-instance-modal/test-instance-modal.component.ts create mode 100644 otf-frontend/client/src/app/shared/modules/test-instance-modal/test-instance-modal.module.spec.ts create mode 100644 otf-frontend/client/src/app/shared/modules/test-instance-modal/test-instance-modal.module.ts create mode 100644 otf-frontend/client/src/app/shared/modules/user-select/user-select.component.pug create mode 100644 otf-frontend/client/src/app/shared/modules/user-select/user-select.component.scss create mode 100644 otf-frontend/client/src/app/shared/modules/user-select/user-select.component.spec.ts create mode 100644 otf-frontend/client/src/app/shared/modules/user-select/user-select.component.ts create mode 100644 otf-frontend/client/src/app/shared/modules/user-select/user-select.module.spec.ts create mode 100644 otf-frontend/client/src/app/shared/modules/user-select/user-select.module.ts create mode 100644 otf-frontend/client/src/app/shared/modules/view-schedule-modal/view-schedule-modal.component.pug create mode 100644 otf-frontend/client/src/app/shared/modules/view-schedule-modal/view-schedule-modal.component.scss create mode 100644 otf-frontend/client/src/app/shared/modules/view-schedule-modal/view-schedule-modal.component.spec.ts create mode 100644 otf-frontend/client/src/app/shared/modules/view-schedule-modal/view-schedule-modal.component.ts create mode 100644 otf-frontend/client/src/app/shared/modules/view-schedule-modal/view-schedule-modal.module.spec.ts create mode 100644 otf-frontend/client/src/app/shared/modules/view-schedule-modal/view-schedule-modal.module.ts create mode 100644 otf-frontend/client/src/app/shared/modules/view-workflow-modal/view-workflow-modal.component.pug create mode 100644 otf-frontend/client/src/app/shared/modules/view-workflow-modal/view-workflow-modal.component.scss create mode 100644 otf-frontend/client/src/app/shared/modules/view-workflow-modal/view-workflow-modal.component.spec.ts create mode 100644 otf-frontend/client/src/app/shared/modules/view-workflow-modal/view-workflow-modal.component.ts create mode 100644 otf-frontend/client/src/app/shared/modules/view-workflow-modal/view-workflow-modal.module.spec.ts create mode 100644 otf-frontend/client/src/app/shared/modules/view-workflow-modal/view-workflow-modal.module.ts create mode 100644 otf-frontend/client/src/app/shared/modules/workflow-request/workflow-request.component.pug create mode 100644 otf-frontend/client/src/app/shared/modules/workflow-request/workflow-request.component.scss create mode 100644 otf-frontend/client/src/app/shared/modules/workflow-request/workflow-request.component.spec.ts create mode 100644 otf-frontend/client/src/app/shared/modules/workflow-request/workflow-request.component.ts create mode 100644 otf-frontend/client/src/app/shared/modules/workflow-request/workflow-request.module.spec.ts create mode 100644 otf-frontend/client/src/app/shared/modules/workflow-request/workflow-request.module.ts create mode 100644 otf-frontend/client/src/app/shared/pipes/shared-pipes.module.ts create mode 100644 otf-frontend/client/src/app/shared/services/account.service.spec.ts create mode 100644 otf-frontend/client/src/app/shared/services/account.service.ts create mode 100644 otf-frontend/client/src/app/shared/services/auth.service.spec.ts create mode 100644 otf-frontend/client/src/app/shared/services/auth.service.ts create mode 100644 otf-frontend/client/src/app/shared/services/execute.service.ts create mode 100644 otf-frontend/client/src/app/shared/services/feathers.service.ts create mode 100644 otf-frontend/client/src/app/shared/services/feedback.service.spec.ts create mode 100644 otf-frontend/client/src/app/shared/services/feedback.service.ts create mode 100644 otf-frontend/client/src/app/shared/services/file-transfer.service.spec.ts create mode 100644 otf-frontend/client/src/app/shared/services/file-transfer.service.ts create mode 100644 otf-frontend/client/src/app/shared/services/file.service.spec.ts create mode 100644 otf-frontend/client/src/app/shared/services/file.service.ts create mode 100644 otf-frontend/client/src/app/shared/services/group.service.spec.ts create mode 100644 otf-frontend/client/src/app/shared/services/group.service.ts create mode 100644 otf-frontend/client/src/app/shared/services/health.service.spec.ts create mode 100644 otf-frontend/client/src/app/shared/services/health.service.ts create mode 100644 otf-frontend/client/src/app/shared/services/json2html.service.ts create mode 100644 otf-frontend/client/src/app/shared/services/list.service.spec.ts create mode 100644 otf-frontend/client/src/app/shared/services/list.service.ts create mode 100644 otf-frontend/client/src/app/shared/services/model.service.ts create mode 100644 otf-frontend/client/src/app/shared/services/params.service.ts create mode 100644 otf-frontend/client/src/app/shared/services/scheduling.service.spec.ts create mode 100644 otf-frontend/client/src/app/shared/services/scheduling.service.ts create mode 100644 otf-frontend/client/src/app/shared/services/test-definition.service.spec.ts create mode 100644 otf-frontend/client/src/app/shared/services/test-definition.service.ts create mode 100644 otf-frontend/client/src/app/shared/services/test-execution.service.spec.ts create mode 100644 otf-frontend/client/src/app/shared/services/test-execution.service.ts create mode 100644 otf-frontend/client/src/app/shared/services/test-head.service.spec.ts create mode 100644 otf-frontend/client/src/app/shared/services/test-head.service.ts create mode 100644 otf-frontend/client/src/app/shared/services/test-instance.service.spec.ts create mode 100644 otf-frontend/client/src/app/shared/services/test-instance.service.ts create mode 100644 otf-frontend/client/src/app/shared/services/user.service.spec.ts create mode 100644 otf-frontend/client/src/app/shared/services/user.service.ts create mode 100644 otf-frontend/client/src/app/signup/signup-routing.module.ts create mode 100644 otf-frontend/client/src/app/signup/signup.component.html create mode 100644 otf-frontend/client/src/app/signup/signup.component.scss create mode 100644 otf-frontend/client/src/app/signup/signup.component.spec.ts create mode 100644 otf-frontend/client/src/app/signup/signup.component.ts create mode 100644 otf-frontend/client/src/app/signup/signup.module.spec.ts create mode 100644 otf-frontend/client/src/app/signup/signup.module.ts create mode 100644 otf-frontend/client/src/assets/fakedata.json create mode 100644 otf-frontend/client/src/assets/i18n/de.json create mode 100644 otf-frontend/client/src/assets/i18n/en.json create mode 100644 otf-frontend/client/src/assets/i18n/es.json create mode 100644 otf-frontend/client/src/assets/i18n/fa.json create mode 100644 otf-frontend/client/src/assets/i18n/fr.json create mode 100644 otf-frontend/client/src/assets/i18n/it.json create mode 100644 otf-frontend/client/src/assets/i18n/ur.json create mode 100644 otf-frontend/client/src/assets/i18n/zh-CHS.json create mode 100644 otf-frontend/client/src/assets/images/404image.png create mode 100644 otf-frontend/client/src/assets/images/NetworkLogo.jpg create mode 100644 otf-frontend/client/src/assets/images/OtfIcon.png create mode 100644 otf-frontend/client/src/assets/images/equalizer.gif create mode 100644 otf-frontend/client/src/assets/images/logo.png create mode 100644 otf-frontend/client/src/assets/images/networkBackground.jpg create mode 100644 otf-frontend/client/src/assets/images/networkBackground1.jpg create mode 100644 otf-frontend/client/src/assets/images/slider1.jpg create mode 100644 otf-frontend/client/src/assets/images/slider2.jpg create mode 100644 otf-frontend/client/src/assets/workflows/blank.bpmn create mode 100644 otf-frontend/client/src/environments/environment.prod.ts create mode 100644 otf-frontend/client/src/environments/environment.ts create mode 100644 otf-frontend/client/src/favicon.ico create mode 100644 otf-frontend/client/src/global-shims.ts create mode 100644 otf-frontend/client/src/index.html create mode 100644 otf-frontend/client/src/main.ts create mode 100644 otf-frontend/client/src/polyfills.ts create mode 100644 otf-frontend/client/src/styles/_responsive.scss create mode 100644 otf-frontend/client/src/styles/_rtl.scss create mode 100644 otf-frontend/client/src/styles/_spinner.scss create mode 100644 otf-frontend/client/src/styles/_utils.scss create mode 100644 otf-frontend/client/src/styles/app.scss create mode 100644 otf-frontend/client/src/test.ts create mode 100644 otf-frontend/client/src/tsconfig.app.json create mode 100644 otf-frontend/client/src/tsconfig.json create mode 100644 otf-frontend/client/src/tsconfig.spec.json create mode 100644 otf-frontend/client/src/typings.d.ts create mode 100644 otf-frontend/helm/otf-frontend/Chart.yaml create mode 100644 otf-frontend/helm/otf-frontend/templates/deployment.yaml create mode 100644 otf-frontend/helm/otf-frontend/templates/secret.yaml create mode 100644 otf-frontend/helm/otf-frontend/templates/service.yaml create mode 100644 otf-frontend/helm/otf-frontend/values.yaml create mode 100644 otf-frontend/package.json create mode 100644 otf-frontend/server/config/.eslintrc create mode 100644 otf-frontend/server/config/cert/info.txt create mode 100644 otf-frontend/server/config/custom-environment-variables.json create mode 100644 otf-frontend/server/config/production.json create mode 100644 otf-frontend/server/src/agenda/agenda.js create mode 100644 otf-frontend/server/src/agenda/controllers/test-execution-controller.js create mode 100644 otf-frontend/server/src/agenda/jobs/test-execution-job.js create mode 100644 otf-frontend/server/src/agenda/models/test-schedule.js create mode 100644 otf-frontend/server/src/agenda/result-emitter.js create mode 100644 otf-frontend/server/src/app.js create mode 100644 otf-frontend/server/src/feathers/app.hooks.js create mode 100644 otf-frontend/server/src/feathers/authentication.js create mode 100644 otf-frontend/server/src/feathers/channels.js create mode 100644 otf-frontend/server/src/feathers/hooks/agendaJobPopulate.js create mode 100644 otf-frontend/server/src/feathers/hooks/checkLocks.js create mode 100644 otf-frontend/server/src/feathers/hooks/checkPermissions.js create mode 100644 otf-frontend/server/src/feathers/hooks/convertToJSON.js create mode 100644 otf-frontend/server/src/feathers/hooks/convertToYAML.js create mode 100644 otf-frontend/server/src/feathers/hooks/convertToYAMLRecursive.js create mode 100644 otf-frontend/server/src/feathers/hooks/createdBy.js create mode 100644 otf-frontend/server/src/feathers/hooks/delete-definition.js create mode 100644 otf-frontend/server/src/feathers/hooks/delete-version.js create mode 100644 otf-frontend/server/src/feathers/hooks/filters.js create mode 100644 otf-frontend/server/src/feathers/hooks/log.js create mode 100644 otf-frontend/server/src/feathers/hooks/paginate-option.js create mode 100644 otf-frontend/server/src/feathers/hooks/permissions/abilities.js create mode 100644 otf-frontend/server/src/feathers/hooks/permissions/get-permissions.js create mode 100644 otf-frontend/server/src/feathers/hooks/permissions/permissions.js create mode 100644 otf-frontend/server/src/feathers/hooks/testDefinitionIsDeployed.js create mode 100644 otf-frontend/server/src/feathers/hooks/throw.js create mode 100644 otf-frontend/server/src/feathers/hooks/updatedBy.js create mode 100644 otf-frontend/server/src/feathers/index.js create mode 100644 otf-frontend/server/src/feathers/models/file.model.js create mode 100644 otf-frontend/server/src/feathers/models/groups.model.js create mode 100644 otf-frontend/server/src/feathers/models/jobs.model.js create mode 100644 otf-frontend/server/src/feathers/models/test-definitions.model.js create mode 100644 otf-frontend/server/src/feathers/models/test-executions.model.js create mode 100644 otf-frontend/server/src/feathers/models/test-heads.model.js create mode 100644 otf-frontend/server/src/feathers/models/test-instances.model.js create mode 100644 otf-frontend/server/src/feathers/models/users.model.js create mode 100644 otf-frontend/server/src/feathers/services/auth-management/auth-management.hooks.js create mode 100644 otf-frontend/server/src/feathers/services/auth-management/auth-management.service.js create mode 100644 otf-frontend/server/src/feathers/services/auth-management/notifier.js create mode 100644 otf-frontend/server/src/feathers/services/bpmn-upload/bpmn-upload.class.js create mode 100644 otf-frontend/server/src/feathers/services/bpmn-upload/bpmn-upload.hooks.js create mode 100644 otf-frontend/server/src/feathers/services/bpmn-upload/bpmn-upload.service.js create mode 100644 otf-frontend/server/src/feathers/services/bpmn-validate/bpmn-validate.class.js create mode 100644 otf-frontend/server/src/feathers/services/bpmn-validate/bpmn-validate.hooks.js create mode 100644 otf-frontend/server/src/feathers/services/bpmn-validate/bpmn-validate.service.js create mode 100644 otf-frontend/server/src/feathers/services/bpmn-validate/bpmn.class.js create mode 100644 otf-frontend/server/src/feathers/services/execute/execute.class.js create mode 100644 otf-frontend/server/src/feathers/services/execute/execute.hooks.js create mode 100644 otf-frontend/server/src/feathers/services/execute/execute.service.js create mode 100644 otf-frontend/server/src/feathers/services/feedback/feedback.class.js create mode 100644 otf-frontend/server/src/feathers/services/feedback/feedback.hooks.js create mode 100644 otf-frontend/server/src/feathers/services/feedback/feedback.service.js create mode 100644 otf-frontend/server/src/feathers/services/file-transfer/file-transfer.class.js create mode 100644 otf-frontend/server/src/feathers/services/file-transfer/file-transfer.hooks.js create mode 100644 otf-frontend/server/src/feathers/services/file-transfer/file-transfer.service.js create mode 100644 otf-frontend/server/src/feathers/services/files/files.hooks.js create mode 100644 otf-frontend/server/src/feathers/services/files/files.service.js create mode 100644 otf-frontend/server/src/feathers/services/groups/groups.hooks.js create mode 100644 otf-frontend/server/src/feathers/services/groups/groups.service.js create mode 100644 otf-frontend/server/src/feathers/services/health/health.class.js create mode 100644 otf-frontend/server/src/feathers/services/health/health.hooks.js create mode 100644 otf-frontend/server/src/feathers/services/health/health.service.js create mode 100644 otf-frontend/server/src/feathers/services/index.js create mode 100644 otf-frontend/server/src/feathers/services/jobs/jobs.class.js create mode 100644 otf-frontend/server/src/feathers/services/jobs/jobs.hooks.js create mode 100644 otf-frontend/server/src/feathers/services/jobs/jobs.service.js create mode 100644 otf-frontend/server/src/feathers/services/mailer/mailer.class.js create mode 100644 otf-frontend/server/src/feathers/services/mailer/mailer.hooks.js create mode 100644 otf-frontend/server/src/feathers/services/mailer/mailer.service.js create mode 100644 otf-frontend/server/src/feathers/services/messages/messages.class.js create mode 100644 otf-frontend/server/src/feathers/services/messages/messages.hooks.js create mode 100644 otf-frontend/server/src/feathers/services/messages/messages.service.js create mode 100644 otf-frontend/server/src/feathers/services/test-definitions/test-definitions.hooks.js create mode 100644 otf-frontend/server/src/feathers/services/test-definitions/test-definitions.service.js create mode 100644 otf-frontend/server/src/feathers/services/test-execution-status/test-execution-status.class.js create mode 100644 otf-frontend/server/src/feathers/services/test-execution-status/test-execution-status.hooks.js create mode 100644 otf-frontend/server/src/feathers/services/test-execution-status/test-execution-status.service.js create mode 100644 otf-frontend/server/src/feathers/services/test-executions/test-executions.hooks.js create mode 100644 otf-frontend/server/src/feathers/services/test-executions/test-executions.service.js create mode 100644 otf-frontend/server/src/feathers/services/test-heads/test-heads.hooks.js create mode 100644 otf-frontend/server/src/feathers/services/test-heads/test-heads.service.js create mode 100644 otf-frontend/server/src/feathers/services/test-instances/test-instances.hooks.js create mode 100644 otf-frontend/server/src/feathers/services/test-instances/test-instances.service.js create mode 100644 otf-frontend/server/src/feathers/services/users/users.hooks.js create mode 100644 otf-frontend/server/src/feathers/services/users/users.service.js create mode 100644 otf-frontend/server/src/lib/logger.js create mode 100644 otf-frontend/server/src/lib/mongoose.js create mode 100644 otf-frontend/server/src/lib/music.js create mode 100644 otf-frontend/server/src/lib/otf-util.js create mode 100644 otf-frontend/server/test/app.test.js create mode 100644 otf-frontend/server/test/hooks/group-filter.test.js create mode 100644 otf-frontend/server/test/services/bpmn-upload.test.js create mode 100644 otf-frontend/server/test/services/bpmn-validate.test.js create mode 100644 otf-frontend/server/test/services/groups-m.test.js create mode 100644 otf-frontend/server/test/services/groups.test.js create mode 100644 otf-frontend/server/test/services/health.test.js create mode 100644 otf-frontend/server/test/services/strategy-upload.test.js create mode 100644 otf-frontend/server/test/services/test-definition.test.js create mode 100644 otf-frontend/server/test/services/test-heads.test.js create mode 100644 otf-frontend/server/test/services/test-instances.test.js create mode 100644 otf-frontend/server/test/services/test-requests.test.js create mode 100644 otf-frontend/server/test/services/test-strategies.test.js create mode 100644 otf-frontend/server/test/services/tests.test.js create mode 100644 otf-frontend/server/test/services/users.test.js create mode 100644 otf-service-api/.gitignore create mode 100644 otf-service-api/Jenkinsfile create mode 100644 otf-service-api/LICENSE.txt create mode 100644 otf-service-api/README.txt create mode 100644 otf-service-api/docker/Dockerfile create mode 100644 otf-service-api/helm/otf-service-api/Chart.yaml create mode 100644 otf-service-api/helm/otf-service-api/templates/deployment.yaml create mode 100644 otf-service-api/helm/otf-service-api/templates/secret.yaml create mode 100644 otf-service-api/helm/otf-service-api/templates/service.yaml create mode 100644 otf-service-api/helm/otf-service-api/values.yaml create mode 100644 otf-service-api/pom.xml create mode 100644 otf-service-api/src/main/java/org/oran/otf/api/Application.java create mode 100644 otf-service-api/src/main/java/org/oran/otf/api/Utilities.java create mode 100644 otf-service-api/src/main/java/org/oran/otf/api/config/CadiFilterConfiguration.java create mode 100644 otf-service-api/src/main/java/org/oran/otf/api/config/CombinedResourceProvider.java create mode 100644 otf-service-api/src/main/java/org/oran/otf/api/config/DataConfig.java create mode 100644 otf-service-api/src/main/java/org/oran/otf/api/config/HttpSecurityConfiguration.java create mode 100644 otf-service-api/src/main/java/org/oran/otf/api/config/JerseyConfiguration.java create mode 100644 otf-service-api/src/main/java/org/oran/otf/api/config/OTFApiEnforcementFilter.java create mode 100644 otf-service-api/src/main/java/org/oran/otf/api/config/OTFApiEnforcementFilterConfiguration.java create mode 100644 otf-service-api/src/main/java/org/oran/otf/api/config/OTFLoggingFeature.java create mode 100644 otf-service-api/src/main/java/org/oran/otf/api/exception/TestHeadNotFoundException.java create mode 100644 otf-service-api/src/main/java/org/oran/otf/api/exception/TestParametersException.java create mode 100644 otf-service-api/src/main/java/org/oran/otf/api/exception/UserNotFoundException.java create mode 100644 otf-service-api/src/main/java/org/oran/otf/api/handler/CamundaProcessDeploymentHandler.java create mode 100644 otf-service-api/src/main/java/org/oran/otf/api/handler/CamundaProcessExecutionHandler.java create mode 100644 otf-service-api/src/main/java/org/oran/otf/api/service/HealthService.java create mode 100644 otf-service-api/src/main/java/org/oran/otf/api/service/OtfOpenService.java create mode 100644 otf-service-api/src/main/java/org/oran/otf/api/service/TestExecutionService.java create mode 100644 otf-service-api/src/main/java/org/oran/otf/api/service/TestInstanceService.java create mode 100644 otf-service-api/src/main/java/org/oran/otf/api/service/TestStrategyService.java create mode 100644 otf-service-api/src/main/java/org/oran/otf/api/service/VirtualTestHeadService.java create mode 100644 otf-service-api/src/main/java/org/oran/otf/api/service/impl/HealthServiceImpl.java create mode 100644 otf-service-api/src/main/java/org/oran/otf/api/service/impl/OtfOpenServiceImpl.java create mode 100644 otf-service-api/src/main/java/org/oran/otf/api/service/impl/TestExecutionServiceImpl.java create mode 100644 otf-service-api/src/main/java/org/oran/otf/api/service/impl/TestInstanceServiceImpl.java create mode 100644 otf-service-api/src/main/java/org/oran/otf/api/service/impl/TestStrategyServiceImpl.java create mode 100644 otf-service-api/src/main/java/org/oran/otf/api/service/impl/VirtualTestHeadServiceImpl.java create mode 100644 otf-service-api/src/main/java/org/oran/otf/common/model/Group.java create mode 100644 otf-service-api/src/main/java/org/oran/otf/common/model/GroupMember.java create mode 100644 otf-service-api/src/main/java/org/oran/otf/common/model/Role.java create mode 100644 otf-service-api/src/main/java/org/oran/otf/common/model/TestDefinition.java create mode 100644 otf-service-api/src/main/java/org/oran/otf/common/model/TestExecution.java create mode 100644 otf-service-api/src/main/java/org/oran/otf/common/model/TestHead.java create mode 100644 otf-service-api/src/main/java/org/oran/otf/common/model/TestInstance.java create mode 100644 otf-service-api/src/main/java/org/oran/otf/common/model/User.java create mode 100644 otf-service-api/src/main/java/org/oran/otf/common/model/historic/TestDefinitionHistoric.java create mode 100644 otf-service-api/src/main/java/org/oran/otf/common/model/historic/TestInstanceHistoric.java create mode 100644 otf-service-api/src/main/java/org/oran/otf/common/model/local/ApiRequest.java create mode 100644 otf-service-api/src/main/java/org/oran/otf/common/model/local/BpmnInstance.java create mode 100644 otf-service-api/src/main/java/org/oran/otf/common/model/local/DeployTestStrategyRequest.java create mode 100644 otf-service-api/src/main/java/org/oran/otf/common/model/local/OTFApiResponse.java create mode 100644 otf-service-api/src/main/java/org/oran/otf/common/model/local/ParallelFlowInput.java create mode 100644 otf-service-api/src/main/java/org/oran/otf/common/model/local/PfloNode.java create mode 100644 otf-service-api/src/main/java/org/oran/otf/common/model/local/TestHeadNode.java create mode 100644 otf-service-api/src/main/java/org/oran/otf/common/model/local/TestHeadRequest.java create mode 100644 otf-service-api/src/main/java/org/oran/otf/common/model/local/TestHeadResult.java create mode 100644 otf-service-api/src/main/java/org/oran/otf/common/model/local/TestInstanceCreateRequest.java create mode 100644 otf-service-api/src/main/java/org/oran/otf/common/model/local/UserGroup.java create mode 100644 otf-service-api/src/main/java/org/oran/otf/common/model/local/WorkflowRequest.java create mode 100644 otf-service-api/src/main/java/org/oran/otf/common/repository/GroupRepository.java create mode 100644 otf-service-api/src/main/java/org/oran/otf/common/repository/TestDefinitionRepository.java create mode 100644 otf-service-api/src/main/java/org/oran/otf/common/repository/TestExecutionRepository.java create mode 100644 otf-service-api/src/main/java/org/oran/otf/common/repository/TestHeadRepository.java create mode 100644 otf-service-api/src/main/java/org/oran/otf/common/repository/TestInstanceRepository.java create mode 100644 otf-service-api/src/main/java/org/oran/otf/common/repository/UserRepository.java create mode 100644 otf-service-api/src/main/java/org/oran/otf/common/util/HttpUtils.java create mode 100644 otf-service-api/src/main/java/org/oran/otf/common/utility/RSAEncryptDecrypt.java create mode 100644 otf-service-api/src/main/java/org/oran/otf/common/utility/Utility.java create mode 100644 otf-service-api/src/main/java/org/oran/otf/common/utility/database/Generic.java create mode 100644 otf-service-api/src/main/java/org/oran/otf/common/utility/database/TestExecutionUtility.java create mode 100644 otf-service-api/src/main/java/org/oran/otf/common/utility/gson/Convert.java create mode 100644 otf-service-api/src/main/java/org/oran/otf/common/utility/gson/GsonUtils.java create mode 100644 otf-service-api/src/main/java/org/oran/otf/common/utility/http/RequestUtility.java create mode 100644 otf-service-api/src/main/java/org/oran/otf/common/utility/http/ResponseUtility.java create mode 100644 otf-service-api/src/main/java/org/oran/otf/common/utility/logger/ErrorCode.java create mode 100644 otf-service-api/src/main/java/org/oran/otf/common/utility/logger/LoggerStartupListener.java create mode 100644 otf-service-api/src/main/java/org/oran/otf/common/utility/logger/MessageEnum.java create mode 100644 otf-service-api/src/main/java/org/oran/otf/common/utility/permissions/PermissionChecker.java create mode 100644 otf-service-api/src/main/java/org/oran/otf/common/utility/permissions/PermissionUtil.java create mode 100644 otf-service-api/src/main/java/org/oran/otf/common/utility/permissions/UserPermission.java create mode 100644 otf-service-api/src/main/resources/application.properties create mode 100644 otf-service-api/src/main/resources/banner.txt create mode 100644 otf-service-api/src/main/resources/truststore2018.jks create mode 100644 otf-service-api/src/test/java/org/oran/otf/api/tests/config/DataConfig2.java create mode 100644 otf-service-api/src/test/java/org/oran/otf/api/tests/config/InMemory.java create mode 100644 otf-service-api/src/test/java/org/oran/otf/api/tests/integration/services/ExecutionServiceRouteIT.java create mode 100644 otf-service-api/src/test/java/org/oran/otf/api/tests/integration/services/HealthRouteIT.java create mode 100644 otf-service-api/src/test/java/org/oran/otf/api/tests/integration/services/InstanceServiceRouteIT.java create mode 100644 otf-service-api/src/test/java/org/oran/otf/api/tests/integration/services/OtfOpenRouteIT.java create mode 100644 otf-service-api/src/test/java/org/oran/otf/api/tests/integration/services/Permissions/PermissionServiceIT.java create mode 100644 otf-service-api/src/test/java/org/oran/otf/api/tests/integration/services/StrategyServiceRouteIT.java create mode 100644 otf-service-api/src/test/java/org/oran/otf/api/tests/shared/MemoryDatabase.java create mode 100644 otf-service-api/src/test/java/org/oran/otf/api/tests/unit/models/DefinitionTest.java create mode 100644 otf-service-api/src/test/java/org/oran/otf/api/tests/unit/models/ExecutionTest.java create mode 100644 otf-service-api/src/test/java/org/oran/otf/api/tests/unit/models/GroupTest.java create mode 100644 otf-service-api/src/test/java/org/oran/otf/api/tests/unit/models/HeadTest.java create mode 100644 otf-service-api/src/test/java/org/oran/otf/api/tests/unit/models/InstanceTest.java create mode 100644 otf-service-api/src/test/java/org/oran/otf/api/tests/unit/models/UserTest.java create mode 100644 otf-service-api/src/test/java/org/oran/otf/api/tests/unit/models/local/BpmnTest.java create mode 100644 otf-service-api/src/test/java/org/oran/otf/api/tests/unit/models/local/DeployTestStrategyRequestTest.java create mode 100644 otf-service-api/src/test/java/org/oran/otf/api/tests/unit/models/local/HeadNodeTest.java create mode 100644 otf-service-api/src/test/java/org/oran/otf/api/tests/unit/models/local/HeadResultTest.java create mode 100644 otf-service-api/src/test/java/org/oran/otf/api/tests/unit/models/local/InstanceCreateRequestTest.java create mode 100644 otf-service-api/src/test/java/org/oran/otf/api/tests/unit/models/local/OtfApiResponseTest.java create mode 100644 otf-service-api/src/test/java/org/oran/otf/api/tests/unit/models/local/ParallelFlowInputTest.java create mode 100644 otf-service-api/src/test/java/org/oran/otf/api/tests/unit/models/local/PfloNodeTest.java create mode 100644 otf-service-api/src/test/java/org/oran/otf/api/tests/unit/models/local/UserGroupTest.java create mode 100644 otf-service-api/src/test/java/org/oran/otf/api/tests/unit/models/local/WorkFlowRequestTest.java create mode 100644 otf-service-api/src/test/java/org/oran/otf/api/tests/unit/utility/BuildResponseTest.java create mode 100644 otf-service-api/src/test/java/org/oran/otf/api/tests/unit/utility/UserPermissionTest.java create mode 100644 otf-service-api/src/test/resources/application-test.properties create mode 100644 otf-service-api/swagger.json create mode 100644 otf-service-api/swagger.yml diff --git a/otf-camunda/.gitignore b/otf-camunda/.gitignore new file mode 100644 index 0000000..7f70bd4 --- /dev/null +++ b/otf-camunda/.gitignore @@ -0,0 +1,34 @@ +/target/ +tokens/ +out/ +/otf/ + +/src/main/resources/bpmn/local/ +/src/main/resources/local/ +src/main/resources/otf_dev.p12 + +!.mvn/wrapper/maven-wrapper.jar + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +original.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/build/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ diff --git a/otf-camunda/Jenkinsfile b/otf-camunda/Jenkinsfile new file mode 100644 index 0000000..1548993 --- /dev/null +++ b/otf-camunda/Jenkinsfile @@ -0,0 +1,197 @@ +#!/usr/bin/env groovy + + +properties([[$class: 'ParametersDefinitionProperty', parameterDefinitions: [ + [$class: 'hudson.model.StringParameterDefinition', name: 'PHASE', defaultValue: "BUILD"], + [$class: 'hudson.model.StringParameterDefinition', name: 'ENV', defaultValue: "dev"], + [$class: 'hudson.model.StringParameterDefinition', name: 'MECHID', defaultValue: "username"], + [$class: 'hudson.model.StringParameterDefinition', name: 'KUBE_CONFIG', defaultValue: "kubeConfig-dev"], + [$class: 'hudson.model.StringParameterDefinition', name: 'OTF_MONGO_DB', defaultValue: "otf_mongo_dev_db"], + [$class: 'hudson.model.StringParameterDefinition', name: 'OTF_CAMUNDA_DB', defaultValue: "otf_camunda_dev_db"], + [$class: 'hudson.model.StringParameterDefinition', name: 'TILLER_NAMESPACE', defaultValue: "org.oran.otf"] + +]]]) + + +echo "Build branch: ${env.BRANCH_NAME}" + +node("docker") { + stage 'Checkout' + checkout scm + PHASES = PHASE.tokenize('_'); + echo "PHASES : " + PHASES + pom = readMavenPom file: 'pom.xml' + ARTIFACT_ID = pom.artifactId; + VERSION = pom.version; + LABEL_VERSION = pom.version.replaceAll("\\.", "-"); + echo "LabelVerion: " + LABEL_VERSION + NAMESPACE = pom.groupId + echo "Tiller Namespace: " + TILLER_NAMESPACE + DOCKER_REGISTRY = pom.properties['docker.registry'] + + if( ENV.equalsIgnoreCase("dev") ){ + IMAGE_NAME = pom.properties['docker.registry'] + "/" + NAMESPACE + "/" + ARTIFACT_ID + ":" + VERSION + } + if( ENV.equalsIgnoreCase("prod") || ENV.equalsIgnoreCase("prod-dr") ){ + IMAGE_NAME = pom.properties['docker.registry'] + "/" + NAMESPACE + ".prod" + "/" + ARTIFACT_ID + ":" + VERSION + } + + if( ENV.equalsIgnoreCase("st") ){ + IMAGE_NAME = pom.properties['docker.registry'] + "/" + NAMESPACE + ".st" + "/" + ARTIFACT_ID + ":" + VERSION + } + echo "Artifact: " + IMAGE_NAME + + + if( ENV.equalsIgnoreCase("dev") ){ + ROUTER_CONFIG="mysqlRouterConfig-dev.ini" + } + if( ENV.equalsIgnoreCase("st") ){ + ROUTER_CONFIG="mysqlRouterConfig-st.ini" + } + if( ENV.equalsIgnoreCase("prod") || ENV.equalsIgnoreCase("prod-dr")){ + ROUTER_CONFIG="mysqlRouterConfig-prod.ini" + } + + withEnv(["PATH=${env.PATH}:${tool 'mvn352'}/bin:${tool 'jdk180'}/bin:${env.WORKSPACE}/linux-amd64", "JAVA_HOME=${tool 'jdk180'}", "MAVEN_HOME=${tool 'mvn352'}", "HELM_HOME=${env.WORKSPACE}"]) { + + echo "JAVA_HOME=${env.JAVA_HOME}" + echo "MAVEN_HOME=${env.MAVEN_HOME}" + echo "PATH=${env.PATH}" + echo "HELM_HOME=${env.HELM_HOME}" + + wrap([$class: 'ConfigFileBuildWrapper', managedFiles: [ + [fileId: 'maven-settings.xml', variable: 'MAVEN_SETTINGS'], + [fileId: 'maven-settings-security.xml', variable: 'MAVEN_SETTINGS_SECURITY'] + ]]) { + + + if (PHASES.contains("BUILD")) { + stage 'Compile' + sh 'mvn -s $MAVEN_SETTINGS -Dsettings.security=$MAVEN_SETTINGS_SECURITY clean compile' + + stage 'Unit Test' + sh 'mvn -s $MAVEN_SETTINGS -Dsettings.security=$MAVEN_SETTINGS_SECURITY test' + + stage 'Package' + sh 'mvn -s $MAVEN_SETTINGS -Dsettings.security=$MAVEN_SETTINGS_SECURITY package' + //sh 'mvn -DskipTests -Dmaven.test.skip=true -s $MAVEN_SETTINGS package' + + stage 'Verify' + sh 'mvn -s $MAVEN_SETTINGS -Dsettings.security=$MAVEN_SETTINGS_SECURITY verify' + + stage 'Publish Artifact' + + withCredentials([usernamePassword(credentialsId: MECHID, usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD')]) { + + echo "Artifact: " + DOCKER_REGISTRY + + sh """ + docker login $DOCKER_REGISTRY --username $USERNAME --password $PASSWORD + docker build -t $IMAGE_NAME -f target/Dockerfile target + docker push $IMAGE_NAME + """ + } + + } + if (PHASES.contains("DEPLOY") || PHASES.contains("UNDEPLOY") || PHASES.contains("UNDEPLOYFORCE")) { + + stage 'Init Helm' + + //check if helm exists if not install + if (fileExists('linux-amd64/helm')) { + sh """ + echo "helm is already installed" + """ + } else { + //download helm + sh """ + echo "installing helm" + wget https://storage.googleapis.com/kubernetes-helm/helm-v2.8.2-linux-amd64.tar.gz + tar -xf helm-v2.8.2-linux-amd64.tar.gz + rm helm-v2.8.2-linux-amd64.tar.gz + """ + } + + withCredentials([file(credentialsId: KUBE_CONFIG, variable: 'KUBECONFIG')]) { + + dir('helm') { + //check if charts are valid, and then perform dry run, if successful then upgrade/install charts + + if (PHASES.contains("UNDEPLOY")) { + stage 'Undeploy' + + sh """ + helm delete --tiller-namespace=$TILLER_NAMESPACE --purge $ARTIFACT_ID + """ + } + if (PHASES.contains("UNDEPLOYFORCE")) { + stage 'Undeploy Force' + + sh """ + + helm delete --tiller-namespace=$TILLER_NAMESPACE --purge $ARTIFACT_ID & + chmod 755 forceDelete.sh + ./forceDelete.sh $ARTIFACT_ID + """ + + } + + //NOTE Double quotes are used below to access groovy variables like artifact_id and tiller_namespace + if (PHASES.contains("DEPLOY")) { + stage 'Deploy' + withCredentials([ + usernamePassword(credentialsId: OTF_MONGO_DB, usernameVariable: 'USERNAME_MONGO', passwordVariable: 'PASSWORD_MONGO'), + usernamePassword(credentialsId: OTF_CAMUNDA_DB, usernameVariable: 'USERNAME_CAMUNDA', passwordVariable: 'PASSWORD_CAMUNDA') + ]) { + + sh """ + + echo "Validate Yaml" + helm lint $ARTIFACT_ID + + echo "View Helm Templates" + helm template $ARTIFACT_ID \ + --set appName=$ARTIFACT_ID \ + --set version=$VERSION \ + --set image=$IMAGE_NAME \ + --set namespace=$TILLER_NAMESPACE \ + --set env=$ENV \ + --set otf.mongo.username=$USERNAME_MONGO \ + --set otf.mongo.password=$PASSWORD_MONGO \ + --set otf.camunda.db.username=$USERNAME_CAMUNDA \ + --set otf.camunda.db.password=$PASSWORD_CAMUNDA \ + + + echo "Perform Dry Run Of Install" + helm upgrade --tiller-namespace=$TILLER_NAMESPACE --install --dry-run $ARTIFACT_ID $ARTIFACT_ID \ + --set version=$VERSION \ + --set image=$IMAGE_NAME \ + --set namespace=$TILLER_NAMESPACE \ + --set env=$ENV \ + --set otf.mongo.username=$USERNAME_MONGO \ + --set otf.mongo.password=$PASSWORD_MONGO \ + --set otf.camunda.db.username=$USERNAME_CAMUNDA \ + --set otf.camunda.db.password=$PASSWORD_CAMUNDA \ + + + echo "Helm Install/Upgrade" + helm upgrade --tiller-namespace=$TILLER_NAMESPACE --install $ARTIFACT_ID $ARTIFACT_ID \ + --set version=$VERSION \ + --set image=$IMAGE_NAME \ + --set namespace=$TILLER_NAMESPACE \ + --set env=$ENV \ + --set otf.mongo.username=$USERNAME_MONGO \ + --set otf.mongo.password=$PASSWORD_MONGO \ + --set otf.camunda.db.username=$USERNAME_CAMUNDA \ + --set otf.camunda.db.password=$PASSWORD_CAMUNDA \ + + """ + } + } + + } + } + } + } + } +} \ No newline at end of file diff --git a/otf-camunda/LICENSE.txt b/otf-camunda/LICENSE.txt new file mode 100644 index 0000000..695ac56 --- /dev/null +++ b/otf-camunda/LICENSE.txt @@ -0,0 +1,28 @@ +Unless otherwise specified, all software contained herein is licensed +under the Apache License, Version 2.0 (the "Software License"); +you may not use this software except in compliance with the Software +License. You may obtain a copy of the Software License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the Software License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the Software License for the specific language governing permissions +and limitations under the Software License. + + + +Unless otherwise specified, all documentation contained herein is licensed +under the Creative Commons License, Attribution 4.0 Intl. (the +"Documentation License"); you may not use this documentation except in +compliance with the Documentation License. You may obtain a copy of the +Documentation License at + +https://creativecommons.org/licenses/by/4.0/ + +Unless required by applicable law or agreed to in writing, documentation +distributed under the Documentation License is distributed on an "AS IS" +BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the Documentation License for the specific language governing +permissions and limitations under the Documentation License. diff --git a/otf-camunda/docker/Dockerfile b/otf-camunda/docker/Dockerfile new file mode 100644 index 0000000..4df636c --- /dev/null +++ b/otf-camunda/docker/Dockerfile @@ -0,0 +1,34 @@ +FROM openjdk:8 + +ENV ENV=development +ENV NAMESPACE=namespace +ENV APP_NAME=otf-camunda +ENV EXECUTORS_ACTIVE=true +ENV OTF_MONGO_USERNAME=username +ENV OTF_MONGO_PASSWORD=password +ENV OTF_MONGO_HOSTS=localhost:27017 +ENV OTF_MONGO_REPLICASET=mongoOTF +ENV OTF_MONGO_DATABASE=otf +ENV OTF_CAMUNDA_DB_URL=localhost:3306/otf-camunda +ENV OTF_CAMUNDA_DB_USERNAME=username +ENV OTF_CAMUNDA_DB_PASSWORD=password +ENV AAF_PERM_TYPE=type +ENV CADI_HOSTNAME=localhost +ENV AAF_ID=username +ENV AAF_MECH_PASSWORD=password +ENV AAF_PASSWORD=password +ENV CADI_KEYFILE=/opt/secret/keyfile +ENV OTF_CERT_PATH=opt/cert/cert.p12 +ENV OTF_CERT_PASS=password +ENV APP_VERSION=1.0 +ENV PRIVATE_KEY=opt/cert/cert.key +ENV PRIVATE_KEY_USERNAME=username +ENV PRIVATE_KEY_PASSPHRASE=password + +COPY otf-camunda.jar app.jar + +RUN mkdir -p /otf/logs + +ADD src src + +ENTRYPOINT ["java", "-jar", "app.jar"] \ No newline at end of file diff --git a/otf-camunda/helm/forceDelete.sh b/otf-camunda/helm/forceDelete.sh new file mode 100644 index 0000000..9347939 --- /dev/null +++ b/otf-camunda/helm/forceDelete.sh @@ -0,0 +1,11 @@ +#/bin/bash +podName=$1 +echo $podName +podInfo=$(kubectl get pods -l app=$1 -o custom-columns=:metadata.name) +echo $podInfo +podArray=(`echo ${podInfo}`) +for var in "${podArray[@]}" +do + echo "Force deleting pod ${var}" + kubectl delete pods ${var} --grace-period=0 --force --ignore-not-found=true +done \ No newline at end of file diff --git a/otf-camunda/helm/otf-camunda/Chart.yaml b/otf-camunda/helm/otf-camunda/Chart.yaml new file mode 100644 index 0000000..9c55445 --- /dev/null +++ b/otf-camunda/helm/otf-camunda/Chart.yaml @@ -0,0 +1,5 @@ +apiVersion: v1 +appVersion: "1.0" +description: A Helm chart the OTF TCU camunda engine +name: otf-camunda +version: 0.0.1-SNAPSHOT \ No newline at end of file diff --git a/otf-camunda/helm/otf-camunda/mysqlRouterConfig-dev.ini b/otf-camunda/helm/otf-camunda/mysqlRouterConfig-dev.ini new file mode 100644 index 0000000..f858b47 --- /dev/null +++ b/otf-camunda/helm/otf-camunda/mysqlRouterConfig-dev.ini @@ -0,0 +1,9 @@ +[DEFAULT] + +[logger] +level = INFO + +[routing] +bind_address = 0.0.0.0:3306 +destinations = localhost:3306 +mode = read-write \ No newline at end of file diff --git a/otf-camunda/helm/otf-camunda/mysqlRouterConfig-prod.ini b/otf-camunda/helm/otf-camunda/mysqlRouterConfig-prod.ini new file mode 100644 index 0000000..6ad94a3 --- /dev/null +++ b/otf-camunda/helm/otf-camunda/mysqlRouterConfig-prod.ini @@ -0,0 +1,9 @@ +[DEFAULT] + +[logger] +level = INFO + +[routing] +bind_address = 0.0.0.0:3306 +destinations = 135.49.207.141:3316,135.49.207.140:3316,130.6.37.195:3316 +mode = read-write \ No newline at end of file diff --git a/otf-camunda/helm/otf-camunda/mysqlRouterConfig-st.ini b/otf-camunda/helm/otf-camunda/mysqlRouterConfig-st.ini new file mode 100644 index 0000000..f858b47 --- /dev/null +++ b/otf-camunda/helm/otf-camunda/mysqlRouterConfig-st.ini @@ -0,0 +1,9 @@ +[DEFAULT] + +[logger] +level = INFO + +[routing] +bind_address = 0.0.0.0:3306 +destinations = localhost:3306 +mode = read-write \ No newline at end of file diff --git a/otf-camunda/helm/otf-camunda/templates/config.yaml b/otf-camunda/helm/otf-camunda/templates/config.yaml new file mode 100644 index 0000000..8c59908 --- /dev/null +++ b/otf-camunda/helm/otf-camunda/templates/config.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ .Values.appName }}-config +data: + router_config: |+ +{{if or (eq .Values.env "prod") (eq .Values.env "prod-dr")}} +{{ .Files.Get .Values.otf.camunda.router.config.prod | indent 4}} +{{ else if eq .Values.env "st"}} +{{ .Files.Get .Values.otf.camunda.router.config.st | indent 4}} +{{ else }} +{{ .Files.Get .Values.otf.camunda.router.config.dev | indent 4}} +{{ end }} \ No newline at end of file diff --git a/otf-camunda/helm/otf-camunda/templates/deployment.yaml b/otf-camunda/helm/otf-camunda/templates/deployment.yaml new file mode 100644 index 0000000..89f751e --- /dev/null +++ b/otf-camunda/helm/otf-camunda/templates/deployment.yaml @@ -0,0 +1,314 @@ +apiVersion: apps/v1beta1 +kind: StatefulSet +metadata: + name: {{ .Values.appName}}-{{ .Values.env }} + namespace: {{.Values.namespace}} + labels: + app: {{ .Values.appName}} + version: {{.Values.version}} +spec: + revisionHistoryLimit: 1 + minReadySeconds: 10 + strategy: + # indicate which strategy we want for rolling update + type: RollingUpdate + rollingUpdate: + maxSurge: 3 + maxUnavailable: 1 + replicas: {{ .Values.replicas}} + selector: + matchLabels: + app: {{ .Values.appName}} + version: {{.Values.version}} + template: + metadata: + labels: + app: {{ .Values.appName}} + version: {{.Values.version}} + spec: + serviceAccount: default + volumes: + - name: {{ .Values.appName}}-aaf-volume + secret: + secretName: {{.Values.sharedSecret}} + - name: {{ .Values.appName}}-keyfile-volume + secret: + secretName: {{.Values.sharedSecret}} + optional: true + items: + - key: cadi_keyfile + path: keyfile + - name: {{ .Values.appName}}-cert-volume + secret: + secretName: {{.Values.sharedCert}} + optional: true + items: + - key: PKCS12_CERT + {{if or (eq .Values.env "prod") (eq .Values.env "prod-dr")}} + path: {{ .Values.cert.prod.name | quote }} + {{ else if eq .Values.env "st" }} + path: {{ .Values.cert.st.name | quote }} + {{ else }} + path: {{ .Values.cert.dev.name | quote }} + {{ end }} + - key: private_key + path: {{ .Values.Secret.privateKey.name }} + - name: {{.Values.appName}}-config-volume + configMap: + name: {{.Values.appName}}-config + items: + - key: router_config + path: config.ini + {{ if or (eq .Values.env "st") (eq .Values.env "prod-dr")}} + {{else}} + - name: logging-pvc + persistentVolumeClaim: + {{if eq .Values.env "prod"}} + claimName: {{ .Values.pvc.prod | quote }} + {{ else }} + claimName: {{ .Values.pvc.dev | quote }} + {{ end }} + {{end}} + containers: + - name: mysql-router + image: {{ .Values.otf.camunda.router.image }} + imagePullPolicy: Always + ports: + - name: http + containerPort: {{ .Values.otf.camunda.router.port }} + protocol: TCP + {{ if eq .Values.env "st"}} + resources: + limits: + memory: "1Gi" + cpu: "500m" + requests: + memory: "512Mi" + cpu: "100m" + {{else}} + resources: + limits: + memory: "4Gi" + cpu: "2" + requests: + memory: "2Gi" + cpu: "1" + {{end}} + args: ["--config=/opt/config/config.ini"] + lifecycle: + preStop: + exec: + command: ["/bin/sh", "-c", {{ "sleep 0" | replace "0" (.Values.terminationGracePeriodSeconds | toString) | quote}} ] + volumeMounts: + - name: {{.Values.appName}}-config-volume + mountPath: /opt/config + - name: {{ .Values.appName}} + image: {{ .Values.image}} + imagePullPolicy: Always + ports: + - name: http + containerPort: {{ .Values.otf.camunda.tcu.port }} + nodePort: {{.Values.nodePort}} + protocol: TCP + {{ if eq .Values.env "st"}} + resources: + limits: + memory: "6Gi" + cpu: "2.8" + requests: + memory: "2Gi" + cpu: "1.5" + {{else}} + resources: + limits: + memory: "10Gi" + cpu: "6" + requests: + memory: "4Gi" + cpu: "2" + {{end}} + env: + - name: ENV + {{if or (eq .Values.env "prod") (eq .Values.env "prod-dr")}} + value: "production" + {{ else if eq .Values.env "st" }} + value: "system_test" + {{ else }} + value: "development" + {{ end }} + - name: NAMESPACE + value: {{.Values.namespace}} + - name: APP_NAME + value: {{ .Values.appName}} + - name: EXECUTORS_ACTIVE + {{if eq .Values.env "prod"}} + value: {{ .Values.otf.camunda.executors_active.prod | quote }} + {{else if eq .Values.env "prod-dr"}} + value: {{ .Values.otf.camunda.executors_active.prod_dr | quote }} + {{else if eq .Values.env "st"}} + value: {{ .Values.otf.camunda.executors_active.st | quote }} + {{ else }} + value: {{ .Values.otf.camunda.executors_active.dev | quote }} + {{ end }} + - name: OTF_MONGO_USERNAME + valueFrom: + secretKeyRef: + name: {{ .Values.appName}} + key: mongo_username + optional: true + - name: OTF_MONGO_PASSWORD + valueFrom: + secretKeyRef: + name: {{ .Values.appName}} + key: mongo_password + optional: true + - name: OTF_MONGO_HOSTS + {{if or (eq .Values.env "prod") (eq .Values.env "prod-dr")}} + value: {{ .Values.otf.mongo.prod.host | quote }} + {{ else if eq .Values.env "st" }} + value: {{ .Values.otf.mongo.st.host | quote }} + {{ else }} + value: {{.Values.otf.mongo.dev.host | quote }} + {{ end }} + - name: OTF_MONGO_REPLICASET + {{if or (eq .Values.env "prod") (eq .Values.env "prod-dr")}} + value: {{ .Values.otf.mongo.prod.replicaSet | quote }} + {{ else if eq .Values.env "st"}} + value: {{ .Values.otf.mongo.st.replicaSet | quote }} + {{ else }} + value: {{ .Values.otf.mongo.dev.replicaSet | quote }} + {{ end }} + - name: OTF_MONGO_DATABASE + {{if or (eq .Values.env "prod") (eq .Values.env "prod-dr")}} + value: {{ .Values.otf.mongo.prod.database | quote }} + {{else if eq .Values.env "st"}} + value: {{ .Values.otf.mongo.st.database | quote }} + {{ else }} + value: {{ .Values.otf.mongo.dev.database | quote }} + {{ end }} + - name: OTF_CAMUNDA_DB_URL + {{if or (eq .Values.env "prod") (eq .Values.env "prod-dr")}} + value: {{ .Values.otf.camunda.db.prod.url}} + {{else if eq .Values.env "st"}} + value: {{ .Values.otf.camunda.db.st.url}} + {{ else }} + value: {{ .Values.otf.camunda.db.dev.url}} + {{ end }} + - name: OTF_CAMUNDA_DB_USERNAME + valueFrom: + secretKeyRef: + name: {{ .Values.appName}} + key: camunda_db_username + optional: true + - name: OTF_CAMUNDA_DB_PASSWORD + valueFrom: + secretKeyRef: + name: {{ .Values.appName}} + key: camunda_db_password + optional: true + - name: AAF_PERM_TYPE + {{if or (eq .Values.env "prod") (eq .Values.env "prod-dr")}} + value: {{ .Values.aafPermType.prod | quote }} + {{ else if eq .Values.env "st"}} + value: {{ .Values.aafPermType.st | quote }} + {{ else }} + value: {{ .Values.aafPermType.dev | quote }} + {{ end }} + - name: CADI_HOSTNAME + {{if eq .Values.env "prod"}} + value: {{ .Values.cadiHostname.prod | quote }} + {{else if eq .Values.env "prod-dr"}} + value: {{ .Values.cadiHostname.prod_dr | quote }} + {{else if eq .Values.env "st"}} + value: {{ .Values.cadiHostname.st | quote }} + {{ else }} + value: {{ .Values.cadiHostname.dev | quote }} + {{ end }} + - name: AAF_ID + valueFrom: + secretKeyRef: + name: {{ .Values.sharedSecret}} + key: aaf_id + optional: true + - name: AAF_MECH_PASSWORD + valueFrom: + secretKeyRef: + name: {{ .Values.sharedSecret}} + key: aaf_mech_password + optional: true + - name: AAF_PASSWORD + valueFrom: + secretKeyRef: + name: {{ .Values.sharedSecret}} + key: aaf_password + optional: true + - name: CADI_KEYFILE + valueFrom: + secretKeyRef: + name: {{ .Values.sharedSecret}} + key: keyfile_secret_path + optional: true + - name: OTF_CERT_PATH + {{if or (eq .Values.env "prod") (eq .Values.env "prod-dr")}} + value: {{ .Values.cert.prod.path | quote }} + {{ else if eq .Values.env "st" }} + value: {{ .Values.cert.st.path | quote }} + {{ else }} + value: {{ .Values.cert.dev.path | quote }} + {{ end }} + - name: OTF_CERT_PASS + valueFrom: + secretKeyRef: + name: {{ .Values.sharedCert}} + key: PKCS12_KEY + optional: true + - name: APP_VERSION + value: {{.Values.version}} + - name: PRIVATE_KEY + value: {{ .Values.Secret.privateKey.path }} + - name: PRIVATE_KEY_USERNAME + valueFrom: + secretKeyRef: + name: {{.Values.sharedCert}} + key: private_key_username + optional: true + - name: PRIVATE_KEY_PASSPHRASE + valueFrom: + secretKeyRef: + name: {{.Values.sharedCert}} + key: private_key_passphrase + optional: true + volumeMounts: + - name: {{.Values.appName}}-keyfile-volume + mountPath: /opt/secret + - name: {{.Values.appName}}-cert-volume + mountPath: /opt/cert + {{ if or (eq .Values.env "st") (eq .Values.env "prod-dr")}} + {{else}} + - name: logging-pvc + mountPath: "/otf/logs" + {{end}} + livenessProbe: + httpGet: + path: /otf/health/v1 + port: http + scheme: HTTPS + httpHeaders: + - name: X-Custom-Header + value: Alive + initialDelaySeconds: 30 + timeoutSeconds: 30 + periodSeconds: 30 + readinessProbe: + httpGet: + path: /otf/health/v1 + port: http + scheme: HTTPS + httpHeaders: + - name: X-Custom-Header + value: Ready + initialDelaySeconds: 30 + timeoutSeconds: 30 + periodSeconds: 30 + restartPolicy: Always + terminationGracePeriodSeconds: {{ .Values.terminationGracePeriodSeconds}} diff --git a/otf-camunda/helm/otf-camunda/templates/secret.yaml b/otf-camunda/helm/otf-camunda/templates/secret.yaml new file mode 100644 index 0000000..52438d2 --- /dev/null +++ b/otf-camunda/helm/otf-camunda/templates/secret.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: Secret +metadata: + name: {{ .Values.appName}} +type: Opaque +data: + mongo_username: {{ .Values.otf.mongo.username | b64enc}} + mongo_password: {{ .Values.otf.mongo.password | b64enc}} + camunda_db_username: {{ .Values.otf.camunda.db.username | b64enc}} + camunda_db_password: {{ .Values.otf.camunda.db.password | b64enc}} \ No newline at end of file diff --git a/otf-camunda/helm/otf-camunda/templates/service.yaml b/otf-camunda/helm/otf-camunda/templates/service.yaml new file mode 100644 index 0000000..ae5f832 --- /dev/null +++ b/otf-camunda/helm/otf-camunda/templates/service.yaml @@ -0,0 +1,18 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ .Values.appName }} + namespace: {{ .Values.namespace}} + labels: + app: {{ .Values.appName }} + version: {{ .Values.version}} +spec: + type: NodePort + ports: + - name: http + port: {{ .Values.otf.camunda.tcu.port }} + protocol: TCP + nodePort: {{ .Values.nodePort}} + selector: + app: {{ .Values.appName }} + version: {{ .Values.version}} diff --git a/otf-camunda/helm/otf-camunda/values.yaml b/otf-camunda/helm/otf-camunda/values.yaml new file mode 100644 index 0000000..cbd86f0 --- /dev/null +++ b/otf-camunda/helm/otf-camunda/values.yaml @@ -0,0 +1,86 @@ +appName: otf-camunda +version: 0.0.1-SNAPSHOT +image: otf-camunda:0.0.1-SNAPSHOT +namespace: org.oran.otf +nodePort: 31313 +replicas: 2 +terminationGracePeriodSeconds: 360 +env: dev + +# Environment variables for the service api. +otf: + mongo: + dev: + host: localhost:27017,localhost:27017,localhost:27017 + replicaSet: mongoOTF + database: otf + st: + host: localhost:27017,localhost:27017,localhost:27017 + replicaSet: mongoOTF + database: otf_st + prod: + host: localhost:18720,localhost:18720,localhost:18720 + replicaSet: otf-rs-prod2 + database: otf + username: "test" + password: "test" + camunda: + executors_active: + dev: true + st: true + prod: false + prod_dr: true + tcu: + port: 8443 + db: + dev: + url: localhost:3306/otf-camunda + st: + url: localhost:3306/otf_st-camunda + prod: + url: localhost:3306/otf-camunda + username: username + password: password + router: + config: + dev: mysqlRouterConfig-dev.ini + st: mysqlRouterConfig-st.ini + prod: mysqlRouterConfig-prod.ini + image: mysql/mysql-router + port: 3306 +# permission type for aaf +aafPermType: + dev: org.oran.otf.dev.camunda + st: org.oran.otf.st.camunda + prod: org.oran.otf.prod.camunda + +cadiHostname: + dev: localhost + st: localhost + prod: localhost + prod_dr: localhost + + +# Secret related information. +sharedSecret: otf-aaf-credential-generator +sharedCert: otf-cert-secret-builder +cert: + dev: + name: otf_dev.p12 + path: opt/cert/otf_dev.p12 + st: + name: otf_st.p12 + path: opt/cert/otf_st.p12 + prod: + name: otf_prod.p12 + path: opt/cert/otf_prod.p12 + +Secret: + privateKey: + name: key.key + path: opt/cert/key.key + +pvc: + dev: org-oran-otf-dev-logs-pv + prod: org-oran-otf-prod-logs-pv + diff --git a/otf-camunda/mvnw b/otf-camunda/mvnw new file mode 100644 index 0000000..7778d42 --- /dev/null +++ b/otf-camunda/mvnw @@ -0,0 +1,225 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Maven2 Start Up Batch script +# +# Required ENV vars: +# ------------------ +# JAVA_HOME - location of a JDK home dir +# +# Optional ENV vars +# ----------------- +# M2_HOME - location of maven2's installed home dir +# MAVEN_OPTS - parameters passed to the Java VM when running Maven +# e.g. to debug Maven itself, use +# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +# MAVEN_SKIP_RC - flag to disable loading of mavenrc files +# ---------------------------------------------------------------------------- + +if [ -z "$MAVEN_SKIP_RC" ] ; then + + if [ -f /etc/mavenrc ] ; then + . /etc/mavenrc + fi + + if [ -f "$HOME/.mavenrc" ] ; then + . "$HOME/.mavenrc" + fi + +fi + +# OS specific support. $var _must_ be set to either true or false. +cygwin=false; +darwin=false; +mingw=false +case "`uname`" in + CYGWIN*) cygwin=true ;; + MINGW*) mingw=true;; + Darwin*) darwin=true + # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home + # See https://developer.apple.com/library/mac/qa/qa1170/_index.html + if [ -z "$JAVA_HOME" ]; then + if [ -x "/usr/libexec/java_home" ]; then + export JAVA_HOME="`/usr/libexec/java_home`" + else + export JAVA_HOME="/Library/Java/Home" + fi + fi + ;; +esac + +if [ -z "$JAVA_HOME" ] ; then + if [ -r /etc/gentoo-release ] ; then + JAVA_HOME=`java-config --jre-home` + fi +fi + +if [ -z "$M2_HOME" ] ; then + ## resolve links - $0 may be a link to maven's home + PRG="$0" + + # need this for relative symlinks + while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG="`dirname "$PRG"`/$link" + fi + done + + saveddir=`pwd` + + M2_HOME=`dirname "$PRG"`/.. + + # make it fully qualified + M2_HOME=`cd "$M2_HOME" && pwd` + + cd "$saveddir" + # echo Using m2 at $M2_HOME +fi + +# For Cygwin, ensure paths are in UNIX format before anything is touched +if $cygwin ; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --unix "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --unix "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --unix "$CLASSPATH"` +fi + +# For Migwn, ensure paths are in UNIX format before anything is touched +if $mingw ; then + [ -n "$M2_HOME" ] && + M2_HOME="`(cd "$M2_HOME"; pwd)`" + [ -n "$JAVA_HOME" ] && + JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" + # TODO classpath? +fi + +if [ -z "$JAVA_HOME" ]; then + javaExecutable="`which javac`" + if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then + # readlink(1) is not available as standard on Solaris 10. + readLink=`which readlink` + if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then + if $darwin ; then + javaHome="`dirname \"$javaExecutable\"`" + javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" + else + javaExecutable="`readlink -f \"$javaExecutable\"`" + fi + javaHome="`dirname \"$javaExecutable\"`" + javaHome=`expr "$javaHome" : '\(.*\)/bin'` + JAVA_HOME="$javaHome" + export JAVA_HOME + fi + fi +fi + +if [ -z "$JAVACMD" ] ; then + if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + else + JAVACMD="`which java`" + fi +fi + +if [ ! -x "$JAVACMD" ] ; then + echo "Error: JAVA_HOME is not defined correctly." >&2 + echo " We cannot execute $JAVACMD" >&2 + exit 1 +fi + +if [ -z "$JAVA_HOME" ] ; then + echo "Warning: JAVA_HOME environment variable is not set." +fi + +CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher + +# traverses directory structure from process work directory to filesystem root +# first directory with .mvn subdirectory is considered project base directory +find_maven_basedir() { + + if [ -z "$1" ] + then + echo "Path not specified to find_maven_basedir" + return 1 + fi + + basedir="$1" + wdir="$1" + while [ "$wdir" != '/' ] ; do + if [ -d "$wdir"/.mvn ] ; then + basedir=$wdir + break + fi + # workaround for JBEAP-8937 (on Solaris 10/Sparc) + if [ -d "${wdir}" ]; then + wdir=`cd "$wdir/.."; pwd` + fi + # end of workaround + done + echo "${basedir}" +} + +# concatenates all lines of a file +concat_lines() { + if [ -f "$1" ]; then + echo "$(tr -s '\n' ' ' < "$1")" + fi +} + +BASE_DIR=`find_maven_basedir "$(pwd)"` +if [ -z "$BASE_DIR" ]; then + exit 1; +fi + +export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} +echo $MAVEN_PROJECTBASEDIR +MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" + +# For Cygwin, switch paths to Windows format before running java +if $cygwin; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --path --windows "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --windows "$CLASSPATH"` + [ -n "$MAVEN_PROJECTBASEDIR" ] && + MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` +fi + +WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +exec "$JAVACMD" \ + $MAVEN_OPTS \ + -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ + "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ + ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/otf-camunda/mvnw.cmd b/otf-camunda/mvnw.cmd new file mode 100644 index 0000000..48c810e --- /dev/null +++ b/otf-camunda/mvnw.cmd @@ -0,0 +1,143 @@ +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Maven2 Start Up Batch script +@REM +@REM Required ENV vars: +@REM JAVA_HOME - location of a JDK home dir +@REM +@REM Optional ENV vars +@REM M2_HOME - location of maven2's installed home dir +@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending +@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven +@REM e.g. to debug Maven itself, use +@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files +@REM ---------------------------------------------------------------------------- + +@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' +@echo off +@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' +@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% + +@REM set %HOME% to equivalent of $HOME +if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") + +@REM Execute a user defined script before this one +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre +@REM check for pre script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" +if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" +:skipRcPre + +@setlocal + +set ERROR_CODE=0 + +@REM To isolate internal variables from possible post scripts, we use another setlocal +@setlocal + +@REM ==== START VALIDATION ==== +if not "%JAVA_HOME%" == "" goto OkJHome + +echo. +echo Error: JAVA_HOME not found in your environment. >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +:OkJHome +if exist "%JAVA_HOME%\bin\java.exe" goto init + +echo. +echo Error: JAVA_HOME is set to an invalid directory. >&2 +echo JAVA_HOME = "%JAVA_HOME%" >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +@REM ==== END VALIDATION ==== + +:init + +@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". +@REM Fallback to current working directory if not found. + +set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% +IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir + +set EXEC_DIR=%CD% +set WDIR=%EXEC_DIR% +:findBaseDir +IF EXIST "%WDIR%"\.mvn goto baseDirFound +cd .. +IF "%WDIR%"=="%CD%" goto baseDirNotFound +set WDIR=%CD% +goto findBaseDir + +:baseDirFound +set MAVEN_PROJECTBASEDIR=%WDIR% +cd "%EXEC_DIR%" +goto endDetectBaseDir + +:baseDirNotFound +set MAVEN_PROJECTBASEDIR=%EXEC_DIR% +cd "%EXEC_DIR%" + +:endDetectBaseDir + +IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig + +@setlocal EnableExtensions EnableDelayedExpansion +for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a +@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% + +:endReadAdditionalConfig + +SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" + +set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" +set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end +@endlocal & set ERROR_CODE=%ERROR_CODE% + +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost +@REM check for post script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" +if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" +:skipRcPost + +@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' +if "%MAVEN_BATCH_PAUSE%" == "on" pause + +if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% + +exit /B %ERROR_CODE% diff --git a/otf-camunda/pom.xml b/otf-camunda/pom.xml new file mode 100644 index 0000000..4fa0994 --- /dev/null +++ b/otf-camunda/pom.xml @@ -0,0 +1,413 @@ + + + 4.0.0 + + org.oran.otf + otf-camunda + Camille.1.1 + jar + + + + com.github.tomakehurst + wiremock-jre8 + 2.24.0 + test + + + org.mockito + mockito-core + 2.15.0 + test + + + org.mockito + mockito-inline + test + + + io.rest-assured + rest-assured + 4.0.0 + test + + + io.rest-assured + rest-assured-all + 4.0.0 + test + + + + + + + org.camunda.bpm + camunda-engine + ${camunda.bpm.version} + + + org.camunda.bpm + camunda-engine-plugin-spin + ${camunda.bpm.base.version} + + + org.camunda.bpm + camunda-engine-plugin-connect + ${camunda.bpm.base.version} + + + org.camunda.connect + camunda-connect-connectors-all + + + org.camunda.bpm.springboot + camunda-bpm-spring-boot-starter + ${camunda.springboot.version} + + + org.camunda.bpm.springboot + camunda-bpm-spring-boot-starter-rest + ${camunda.springboot.version} + + + org.camunda.bpm.springboot + camunda-bpm-spring-boot-starter-webapp-ee + ${camunda.springboot.version} + + + camunda-external-task-client + org.camunda.bpm + ${camunda.bpm.external-task-client.version} + + + + + org.camunda.bpm.extension.mockito + camunda-bpm-mockito + ${camunda.mockito.version} + test + + + org.camunda.bpm.extension.reactor + camunda-bpm-reactor-core + ${camunda.bpm.reactor.version} + + + camunda-bpm-reactor-spring + org.camunda.bpm.extension.reactor + ${camunda.bpm.reactor.version} + + + org.camunda.bpm.extension + camunda-bpm-assert + ${camunda.bpm.assert.version} + + + + + + org.camunda.spin + camunda-spin-core + ${camunda.spin.version} + + + org.camunda.spin + camunda-spin-dataformat-all + ${camunda.spin.version} + + + + + org.springframework.boot + spring-boot-starter-actuator + ${springboot.version} + + + spring-boot-starter-amqp + org.springframework.boot + ${springboot.version} + + + org.springframework.boot + spring-boot-starter-jersey + ${springboot.version} + + + org.springframework.boot + spring-boot-starter-data-mongodb + ${springboot.version} + + + org.springframework.boot + spring-boot-starter-test + test + ${springboot.version} + + + + + + + + org.springframework.boot + spring-boot-configuration-processor + ${springboot.version} + true + + + org.springframework.boot + spring-boot-starter-json + ${springboot.version} + + + org.springframework.boot + spring-boot-starter-jdbc + ${springboot.version} + + + + + org.onap.aaf.authz + aaf-auth-client + ${cadi.version} + + + org.onap.aaf.authz + aaf-cadi-core + ${cadi.version} + + + org.onap.aaf.authz + aaf-cadi-aaf + ${cadi.version} + + + + com.h2database + h2 + + + org.apache.commons + commons-lang3 + 3.4 + + + org.codehaus.groovy + groovy-all + ${groovy.version} + + + com.google.code.gson + gson + ${google.gson.version} + + + com.google.guava + guava + ${google.guava.version} + + + org.python + jython-standalone + ${python.version} + + + + mysql + mysql-connector-java + 8.0.14 + + + de.flapdoodle.embed.mongo + de.flapdoodle.embed + test + + + jersey-media-multipart + org.glassfish.jersey.media + + + junit + junit + + + httpclient + org.apache.httpcomponents + 4.5.7 + + + httpasyncclient + org.apache.httpcomponents + 4.1.4 + + + jackson-module-kotlin + com.fasterxml.jackson.module + ${jackson.version} + + + jackson-datatype-jsr310 + com.fasterxml.jackson.datatype + ${jackson.version} + + + org.apache.commons + commons-vfs2 + 2.2 + + + com.jcraft + jsch + 0.1.54 + + + + org.springframework.boot + spring-boot-starter-parent + 2.1.4.RELEASE + + + + + + org.camunda.bpm + camunda-bom + ${camunda.version} + import + pom + + + + + + + + false + ${skipTests} + ${skipTests} + + 2.1.10 + registry.hub.docker.io + 7.10.0-ee + 2.0-alpha2 + 7.10.0 + 1.1.0 + 2.1.2 + 7.10.4-ee + 1.1.1 + 3.2.1 + 1.6.6 + 3.2.0 + 27.1-jre + 2.8.5 + 2.1.3 + 2.9.5 + 2.7.1 + 2.1.4.RELEASE + + + otf-camunda + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.8 + 1.8 + + + + org.springframework.boot + spring-boot-maven-plugin + ${springboot.version} + + + + org.python + jython-standalone + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.22.1 + + ${skipUTs} + + + + org.apache.maven.plugins + maven-failsafe-plugin + 2.22.1 + + + run-integration-tests + integration-test + + verify + + + + + ${skipTests} + ${skipITs} + + + + + + + src/main/resources + ${basedir}/target/src/main/resources + true + + **/* + + + otf_dev.p12 + + + + src/main/resources + true + + **/* + + + otf_dev.p12 + + + + src/main/resources + ${basedir}/target/src/main/resources + + otf_dev.p12 + + + + src/main/resources + + otf_dev.p12 + + + + docker + ${basedir}/target + + Dockerfile + + + + + otf-camunda + One of the core components of the Open Test Framework Test Control Unit. + + + \ No newline at end of file diff --git a/otf-camunda/src/main/java/org/oran/otf/Application.java b/otf-camunda/src/main/java/org/oran/otf/Application.java new file mode 100644 index 0000000..7dfa547 --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/Application.java @@ -0,0 +1,100 @@ +/* Copyright (c) 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.oran.otf; + +import java.util.List; +import java.util.concurrent.Executor; +import org.camunda.bpm.application.PostDeploy; +import org.camunda.bpm.application.PreUndeploy; +import org.camunda.bpm.application.ProcessApplicationInfo; +import org.camunda.bpm.engine.ProcessEngine; +import org.camunda.bpm.spring.boot.starter.annotation.EnableProcessApplication; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration; +import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; +import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration; +import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration; +import org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Primary; +import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; + +@SpringBootApplication +@EnableAsync +@ComponentScan(basePackages = "org.oran.otf") +@EnableProcessApplication +@EnableAutoConfiguration( + exclude = { + ErrorMvcAutoConfiguration.class, + DataSourceAutoConfiguration.class, + HibernateJpaAutoConfiguration.class, + MongoDataAutoConfiguration.class, + MongoAutoConfiguration.class + }) +public class Application { + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + + } + + private static final Logger logger = LoggerFactory.getLogger(Application.class); + + @Value("${otf.camunda.executor.async.core-pool-size}") + private int corePoolSize; + + @Value("${otf.camunda.executor.async.max-pool-size}") + private int maxPoolSize; + + @Value("${otf.camunda.executor.async.queue-capacity}") + private int queueCapacity; + + private static final String LOGS_DIR = "logs_dir"; + + + private static void setLogsDir() { + if (System.getProperty(LOGS_DIR) == null) { + System.getProperties().setProperty(LOGS_DIR, "./logs/camunda/"); + } + } + + @PostDeploy + public void postDeploy(ProcessEngine processEngineInstance) {} + + @PreUndeploy + public void cleanup(ProcessEngine processEngine, ProcessApplicationInfo processApplicationInfo, + List processEngines) {} + + @Bean + @Primary + public Executor asyncExecutor() { + ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); + //executor.setTaskDecorator(new MDCTaskDecorator()); + executor.setCorePoolSize(corePoolSize); + executor.setMaxPoolSize(maxPoolSize); + executor.setQueueCapacity(queueCapacity); + executor.setThreadNamePrefix("Camunda-"); + executor.initialize(); + return executor; + } +} diff --git a/otf-camunda/src/main/java/org/oran/otf/cadi/configuration/CadiFilterConfiguration.java b/otf-camunda/src/main/java/org/oran/otf/cadi/configuration/CadiFilterConfiguration.java new file mode 100644 index 0000000..d0b09ec --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/cadi/configuration/CadiFilterConfiguration.java @@ -0,0 +1,97 @@ +/* Copyright (c) 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.oran.otf.cadi.configuration; + +import javax.servlet.Filter; +import org.onap.aaf.cadi.Access.Level; +import org.onap.aaf.cadi.config.Config; +import org.onap.aaf.cadi.filter.CadiFilter; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Conditional; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; + +@PropertySource("classpath:application.yaml") +@Configuration +@Conditional(value = FilterCondition.class) +public class CadiFilterConfiguration { + + @Value("${otf.cadi.aaf-mech-id}") + private String AAF_APPID; + + @Value("${otf.cadi.aaf-mech-password}") + private String AAF_APPPASS; + + @Value("${otf.cadi.hostname}") + private String CADI_HOSTNAME; + + @Value("${otf.cadi.keyfile}") + private String CADI_KEYFILE; + + @Value("${otf.ssl.keystore-path}") + private String CADI_KEYSTORE; + + @Value("${otf.ssl.keystore-password}") + private String CADI_KEYSTORE_PASSWORD; + + @Bean(name = "cadiFilterRegistrationBean") +// @ConditionalOnProperty(prefix = "otf.cadi", name = "enabled", havingValue = "true", matchIfMissing = true) + public FilterRegistrationBean cadiFilterRegistration() { + FilterRegistrationBean registration = new FilterRegistrationBean<>(); + // set cadi configuration properties + initCadiProperties(registration); + + registration.addUrlPatterns("/otf/tcu/*", "/rest/*"); + registration.setFilter(cadiFilter()); + registration.setName("otfCadiFilter"); + registration.setOrder(0); + return registration; + } + + Filter cadiFilter() { + return new CadiFilter(); + } + + private void initCadiProperties(FilterRegistrationBean registration) { + registration.addInitParameter(Config.AAF_APPID, AAF_APPID); + registration.addInitParameter(Config.AAF_APPPASS, AAF_APPPASS); + registration.addInitParameter(Config.AAF_CALL_TIMEOUT, "10000"); + registration.addInitParameter(Config.AAF_CONN_TIMEOUT, "6000"); + registration.addInitParameter(Config.AAF_DEFAULT_REALM, "localhost"); + registration.addInitParameter(Config.AAF_ENV, "PROD"); + registration.addInitParameter(Config.AAF_LOCATE_URL, "https://localhost"); + registration.addInitParameter(Config.AAF_LUR_CLASS, "org.onap.aaf.cadi.aaf.v2_0.AAFLurPerm"); + registration.addInitParameter( + Config.AAF_URL, "https://localhost"); + + registration.addInitParameter(Config.BASIC_REALM, "localhost"); + registration.addInitParameter(Config.BASIC_WARN, "true"); + + registration.addInitParameter(Config.CADI_KEYFILE, CADI_KEYFILE); + registration.addInitParameter(Config.CADI_LATITUDE, "38.62782"); + registration.addInitParameter(Config.CADI_LOGLEVEL, Level.ERROR.name()); + registration.addInitParameter(Config.CADI_LONGITUDE, "-90.19458"); + registration.addInitParameter(Config.CADI_NOAUTHN, "/health/v1"); + registration.addInitParameter(Config.CADI_PROTOCOLS, "TLSv1.1,TLSv1.2"); + registration.addInitParameter(Config.CADI_KEYSTORE, CADI_KEYSTORE); + registration.addInitParameter(Config.CADI_KEYSTORE_PASSWORD, CADI_KEYSTORE_PASSWORD); + + registration.addInitParameter(Config.HOSTNAME, CADI_HOSTNAME); + } +} diff --git a/otf-camunda/src/main/java/org/oran/otf/cadi/configuration/FilterCondition.java b/otf-camunda/src/main/java/org/oran/otf/cadi/configuration/FilterCondition.java new file mode 100644 index 0000000..d1f1515 --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/cadi/configuration/FilterCondition.java @@ -0,0 +1,33 @@ +/* Copyright (c) 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.oran.otf.cadi.configuration; + +import org.springframework.context.annotation.Condition; +import org.springframework.context.annotation.ConditionContext; +import org.springframework.core.type.AnnotatedTypeMetadata; + +import java.lang.annotation.Annotation; + +public class FilterCondition implements Condition { + @Override + public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) { + String enabled = conditionContext.getEnvironment().getProperty("otf.cadi.enabled"); + if (enabled == null) + return true; + return !enabled.equalsIgnoreCase("false"); + } +} diff --git a/otf-camunda/src/main/java/org/oran/otf/cadi/configuration/OTFApiEnforcementFilterConfiguration.java b/otf-camunda/src/main/java/org/oran/otf/cadi/configuration/OTFApiEnforcementFilterConfiguration.java new file mode 100644 index 0000000..6649b12 --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/cadi/configuration/OTFApiEnforcementFilterConfiguration.java @@ -0,0 +1,67 @@ +/* Copyright (c) 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.oran.otf.cadi.configuration; + +import org.oran.otf.cadi.filter.OTFApiEnforcementFilter; +import javax.servlet.Filter; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import org.onap.aaf.cadi.Access; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Conditional; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; + +@PropertySource("classpath:application.yaml") +@Configuration +@Conditional(value = FilterCondition.class) +public class OTFApiEnforcementFilterConfiguration { + + @Value("${otf.cadi.aaf-perm-type}") + private String AAF_PERM_TYPE; + + private Access access; + private FilterConfig fc; + + @Bean(name = "otfApiEnforcementFilterRegistrationBean") +// @ConditionalOnProperty(prefix ="otf.cadi", name ="enabled", havingValue = "true" ,matchIfMissing = true) + @Conditional(value = FilterCondition.class) + public FilterRegistrationBean otfApiEnforcementFilterRegistration() + throws ServletException { + FilterRegistrationBean registration = new FilterRegistrationBean<>(); + initFilterParameters(registration); + + registration.addUrlPatterns("/otf/tcu/*", "/rest/*"); + registration.setFilter(otfApiEnforcementFilter()); + registration.setName("otfApiEnforcementFilter"); + registration.setOrder(1); + return registration; + } + + @Bean(name = "otfApiEnforcementFilter") + @Conditional(value = FilterCondition.class) +// @ConditionalOnProperty(prefix ="otf.cadi", name ="enabled", havingValue = "true", matchIfMissing = true) + Filter otfApiEnforcementFilter() throws ServletException { + return new OTFApiEnforcementFilter(access, AAF_PERM_TYPE); + } + + private void initFilterParameters(FilterRegistrationBean registration) { + registration.addInitParameter("aaf_perm_type", AAF_PERM_TYPE); + } +} diff --git a/otf-camunda/src/main/java/org/oran/otf/cadi/filter/OTFApiEnforcementFilter.java b/otf-camunda/src/main/java/org/oran/otf/cadi/filter/OTFApiEnforcementFilter.java new file mode 100644 index 0000000..cf04193 --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/cadi/filter/OTFApiEnforcementFilter.java @@ -0,0 +1,134 @@ +/* Copyright (c) 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.oran.otf.cadi.filter; + +import com.google.common.base.Strings; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.onap.aaf.cadi.Access; +import org.onap.aaf.cadi.Access.Level; +import org.onap.aaf.cadi.ServletContextAccess; +import org.onap.aaf.cadi.util.Split; + +public class OTFApiEnforcementFilter implements Filter { + private static final Log log = LogFactory.getLog(OTFApiEnforcementFilter.class); + private String type; + private Map> publicPaths; + private Access access = null; + + public OTFApiEnforcementFilter(Access access, String enforce) throws ServletException { + this.access = access; + init(enforce); + } + + @Override + public void init(FilterConfig fc) throws ServletException { + init(fc.getInitParameter("aaf_perm_type")); + // need the Context for Logging, instantiating ClassLoader, etc + ServletContextAccess sca = new ServletContextAccess(fc); + if (access == null) { + access = sca; + } + } + + private void init(final String ptypes) throws ServletException { + if (Strings.isNullOrEmpty(ptypes)) { + throw new ServletException("OTFApiEnforcement requires aaf_perm_type property"); + } + String[] full = Split.splitTrim(';', ptypes); + if (full.length <= 0) { + throw new ServletException("aaf_perm_type property is empty"); + } + + type = full[0]; + publicPaths = new TreeMap<>(); + if (full.length > 1) { + for (int i = 1; i < full.length; ++i) { + String[] pubArray = Split.split(':', full[i]); + if (pubArray.length == 2) { + List ls = publicPaths.get(pubArray[0]); + if (ls == null) { + ls = new ArrayList<>(); + publicPaths.put(pubArray[0], ls); + } + ls.add(pubArray[1]); + } + } + } + } + + @Override + public void doFilter(ServletRequest req, ServletResponse resp, FilterChain fc) + throws IOException, ServletException { + HttpServletRequest hreq = (HttpServletRequest) req; + final String meth = hreq.getMethod(); + String path = hreq.getContextPath(); // + hreq.getPathInfo(); + + if (Strings.isNullOrEmpty(path) || "null".equals(path)) { + path = hreq.getRequestURI().substring(hreq.getContextPath().length()); + } + + List list = publicPaths.get(meth); + if (list != null) { + for (String p : publicPaths.get(meth)) { + if (path.startsWith(p)) { + access.printf( + Level.INFO, + "%s accessed public API %s %s\n", + hreq.getUserPrincipal().getName(), + meth, + path); + fc.doFilter(req, resp); + return; + } + } + } + if (hreq.isUserInRole(type + '|' + path + '|' + meth)) { + access.printf( + Level.INFO, + "%s is allowed access to %s %s\n", + hreq.getUserPrincipal().getName(), + meth, + path); + fc.doFilter(req, resp); + } else { + access.printf( + Level.AUDIT, + "%s is denied access to %s %s\n", + hreq.getUserPrincipal().getName(), + meth, + path); + ((HttpServletResponse) resp).sendError(HttpServletResponse.SC_UNAUTHORIZED); + } + } + + @Override + public void destroy() {} +} diff --git a/otf-camunda/src/main/java/org/oran/otf/camunda/configuration/OTFAuthorizationConfiguration.java b/otf-camunda/src/main/java/org/oran/otf/camunda/configuration/OTFAuthorizationConfiguration.java new file mode 100644 index 0000000..f79550b --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/camunda/configuration/OTFAuthorizationConfiguration.java @@ -0,0 +1,21 @@ +/* Copyright (c) 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.oran.otf.camunda.configuration; + +public class OTFAuthorizationConfiguration { + +} diff --git a/otf-camunda/src/main/java/org/oran/otf/camunda/configuration/OTFDataSourceConfiguration.java b/otf-camunda/src/main/java/org/oran/otf/camunda/configuration/OTFDataSourceConfiguration.java new file mode 100644 index 0000000..87936f5 --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/camunda/configuration/OTFDataSourceConfiguration.java @@ -0,0 +1,63 @@ +/* Copyright (c) 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.oran.otf.camunda.configuration; + +import javax.sql.DataSource; + +import com.zaxxer.hikari.HikariDataSource; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.jdbc.DataSourceBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; +import org.springframework.jdbc.datasource.DataSourceTransactionManager; +import org.springframework.transaction.PlatformTransactionManager; + +@Configuration +public class OTFDataSourceConfiguration { + @Value("${otf.camunda.mysql.url}") + private String url; + + @Value("${otf.camunda.mysql.username}") + private String username; + + @Value("${otf.camunda.mysql.password}") + private String password; + + @Bean + @Primary + public DataSource dataSource() { + DataSource dataSource = DataSourceBuilder.create() + .url(url) + .username(username) + .password(password) + .driverClassName("com.mysql.cj.jdbc.Driver") + .build(); + if (dataSource instanceof HikariDataSource){ +// ((HikariDataSource) dataSource).setLeakDetectionThreshold(10000); + + ((HikariDataSource) dataSource).setMaximumPoolSize(75); + ((HikariDataSource) dataSource).setMinimumIdle(15); + } + return dataSource; + } + + @Bean + public PlatformTransactionManager transactionManager() { + return new DataSourceTransactionManager(dataSource()); + } +} diff --git a/otf-camunda/src/main/java/org/oran/otf/camunda/configuration/OTFDeploymentConfiguration.java b/otf-camunda/src/main/java/org/oran/otf/camunda/configuration/OTFDeploymentConfiguration.java new file mode 100644 index 0000000..40d2a74 --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/camunda/configuration/OTFDeploymentConfiguration.java @@ -0,0 +1,21 @@ +/* Copyright (c) 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.oran.otf.camunda.configuration; + +public class OTFDeploymentConfiguration { + +} diff --git a/otf-camunda/src/main/java/org/oran/otf/camunda/configuration/OTFFailedJobConfiguration.java b/otf-camunda/src/main/java/org/oran/otf/camunda/configuration/OTFFailedJobConfiguration.java new file mode 100644 index 0000000..a8b62f9 --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/camunda/configuration/OTFFailedJobConfiguration.java @@ -0,0 +1,21 @@ +/* Copyright (c) 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.oran.otf.camunda.configuration; + +public class OTFFailedJobConfiguration { + +} diff --git a/otf-camunda/src/main/java/org/oran/otf/camunda/configuration/OTFJacksonDataConfigurator.java b/otf-camunda/src/main/java/org/oran/otf/camunda/configuration/OTFJacksonDataConfigurator.java new file mode 100644 index 0000000..11b8705 --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/camunda/configuration/OTFJacksonDataConfigurator.java @@ -0,0 +1,43 @@ +/* Copyright (c) 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.oran.otf.camunda.configuration; + +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import com.fasterxml.jackson.module.kotlin.KotlinModule; +import org.camunda.spin.impl.json.jackson.format.JacksonJsonDataFormat; +import org.camunda.spin.spi.DataFormatConfigurator; +import org.springframework.context.annotation.Configuration; +import spinjar.com.fasterxml.jackson.databind.ObjectMapper; +import spinjar.com.fasterxml.jackson.databind.module.SimpleModule; + +@Configuration +public class OTFJacksonDataConfigurator implements DataFormatConfigurator { + + @Override + public Class getDataFormatClass() { + return JacksonJsonDataFormat.class; + } + + @Override + public void configure(JacksonJsonDataFormat dataFormat) { + ObjectMapper mapper = dataFormat.getObjectMapper(); + SimpleModule module = new SimpleModule(); + module.registerSubtypes(KotlinModule.class); + module.registerSubtypes(JavaTimeModule.class); + mapper.registerModule(module); + } +} diff --git a/otf-camunda/src/main/java/org/oran/otf/camunda/configuration/OTFJobConfiguration.java b/otf-camunda/src/main/java/org/oran/otf/camunda/configuration/OTFJobConfiguration.java new file mode 100644 index 0000000..6ece823 --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/camunda/configuration/OTFJobConfiguration.java @@ -0,0 +1,73 @@ +/* Copyright (c) 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.oran.otf.camunda.configuration; + +import org.oran.otf.camunda.configuration.listener.OTFJobExecutorStartingEventListener; +import org.camunda.bpm.engine.impl.jobexecutor.JobExecutor; +import org.camunda.bpm.engine.spring.SpringProcessEngineConfiguration; +import org.camunda.bpm.spring.boot.starter.configuration.impl.DefaultJobConfiguration; +import org.camunda.bpm.spring.boot.starter.event.JobExecutorStartingEventListener; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; + +@Configuration +public class OTFJobConfiguration extends DefaultJobConfiguration { + @Autowired protected JobExecutor jobExecutor; + + @Override + protected void configureJobExecutor(SpringProcessEngineConfiguration configuration) { + int podNumber = -1; + String[] hostnameSplit = {"0", "0", "0"}; + + try { + String hostname = System.getenv("HOSTNAME"); + hostnameSplit = hostname.split("-"); + podNumber = Integer.parseInt(hostnameSplit[2]); + } catch (Exception e) { + podNumber = 1; + } + + //if (podNumber == 1) { + camundaBpmProperties.getJobExecution().setLockTimeInMillis(43200000); + camundaBpmProperties.getJobExecution().setBackoffTimeInMillis(90); + camundaBpmProperties.getJobExecution().setMaxBackoff(450L); + camundaBpmProperties.getJobExecution().setWaitIncreaseFactor(2f); + + super.configureJobExecutor(configuration); + + configuration.getJobExecutor().setLockTimeInMillis(43200000); + configuration.getJobExecutor().setBackoffTimeInMillis(90); + configuration.getJobExecutor().setMaxBackoff(450L); + configuration.getJobExecutor().setWaitIncreaseFactor(2); + + + // configuration.getJobExecutor().setAutoActivate(false); + // } + } + + @Bean + @Primary + @ConditionalOnProperty(prefix = "camunda.bpm.job-execution", name = "enabled", havingValue = "true", matchIfMissing = true) + @ConditionalOnBean(JobExecutor.class) + public static JobExecutorStartingEventListener jobExecutorStartingEventListener() { + return new OTFJobExecutorStartingEventListener(); + } +} diff --git a/otf-camunda/src/main/java/org/oran/otf/camunda/configuration/OTFLoggingFeature.java b/otf-camunda/src/main/java/org/oran/otf/camunda/configuration/OTFLoggingFeature.java new file mode 100644 index 0000000..9715fc0 --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/camunda/configuration/OTFLoggingFeature.java @@ -0,0 +1,238 @@ +/* Copyright (c) 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.oran.otf.camunda.configuration; + +import org.glassfish.jersey.logging.LoggingFeature; +import org.glassfish.jersey.message.MessageUtils; + +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.client.ClientRequestContext; +import javax.ws.rs.client.ClientRequestFilter; +import javax.ws.rs.client.ClientResponseContext; +import javax.ws.rs.client.ClientResponseFilter; +import javax.ws.rs.container.ContainerRequestContext; +import javax.ws.rs.container.ContainerRequestFilter; +import javax.ws.rs.container.ContainerResponseContext; +import javax.ws.rs.container.ContainerResponseFilter; +import javax.ws.rs.core.FeatureContext; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.ext.WriterInterceptor; +import javax.ws.rs.ext.WriterInterceptorContext; +import java.io.*; +import java.net.URI; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.Base64; +import java.util.List; +import java.util.Objects; +import java.util.logging.Level; +import java.util.logging.Logger; + +public class OTFLoggingFeature extends LoggingFeature implements ContainerRequestFilter, ContainerResponseFilter, + ClientRequestFilter, ClientResponseFilter, WriterInterceptor { + + private static final boolean printEntity = true; + private static final int maxEntitySize = 8 * 1024; + private final Logger logger = Logger.getLogger("OTFLoggingFeature"); + private static final String ENTITY_LOGGER_PROPERTY = OTFLoggingFeature.class.getName(); + private static final String NOTIFICATION_PREFIX = "* "; + private static final String REQUEST_PREFIX = "> "; + private static final String RESPONSE_PREFIX = "< "; + private static final String AUTHORIZATION = "Authorization"; + private static final String EQUAL = " = "; + private static final String HEADERS_SEPARATOR = ", "; + private static List requestHeaders; + + static { + requestHeaders = new ArrayList<>(); + requestHeaders.add(AUTHORIZATION); + } + + public OTFLoggingFeature(Logger logger, Level level, Verbosity verbosity, Integer maxEntitySize) { + super(logger, level, verbosity, maxEntitySize); + } + + @Override + public boolean configure(FeatureContext context) { + context.register(this); + return true; + } + + private Object getEmail(Object authorization){ + try{ + String encoded = ((String) authorization).split(" ")[1]; + String decoded = new String(Base64.getDecoder().decode(encoded)); + return decoded.split(":")[0]; + } + catch (Exception e){ + return authorization; + } + } + + @Override + public void filter(final ClientRequestContext context) { + final StringBuilder b = new StringBuilder(); + printHeaders(b, context.getStringHeaders()); + printRequestLine(b, "Sending client request", context.getMethod(), context.getUri()); + + if (printEntity && context.hasEntity()) { + final OutputStream stream = new LoggingStream(b, context.getEntityStream()); + context.setEntityStream(stream); + context.setProperty(ENTITY_LOGGER_PROPERTY, stream); + // not calling log(b) here - it will be called by the interceptor + } else { + log(b); + } + } + + @Override + public void filter(final ClientRequestContext requestContext, final ClientResponseContext responseContext) throws IOException { + final StringBuilder b = new StringBuilder(); + printResponseLine(b, "Client response received", responseContext.getStatus()); + + if (printEntity && responseContext.hasEntity()) { + responseContext.setEntityStream(logInboundEntity(b, responseContext.getEntityStream(), + MessageUtils.getCharset(responseContext.getMediaType()))); + } + log(b); + } + + @Override + public void filter(final ContainerRequestContext context) throws IOException { + final StringBuilder b = new StringBuilder(); + printHeaders(b, context.getHeaders()); + printRequestLine(b, "Server has received a request", context.getMethod(), context.getUriInfo().getRequestUri()); + + if (printEntity && context.hasEntity()) { + context.setEntityStream(logInboundEntity(b, context.getEntityStream(), MessageUtils.getCharset(context.getMediaType()))); + } + log(b); + } + + @Override + public void filter(final ContainerRequestContext requestContext, final ContainerResponseContext responseContext) { + final StringBuilder b = new StringBuilder(); + printResponseLine(b, "Server responded with a response", responseContext.getStatus()); + + if (printEntity && responseContext.hasEntity()) { + final OutputStream stream = new LoggingStream(b, responseContext.getEntityStream()); + responseContext.setEntityStream(stream); + requestContext.setProperty(ENTITY_LOGGER_PROPERTY, stream); + // not calling log(b) here - it will be called by the interceptor + } else { + log(b); + } + } + + @Override + public void aroundWriteTo(final WriterInterceptorContext writerInterceptorContext) throws IOException, WebApplicationException { + final LoggingStream stream = (LoggingStream) writerInterceptorContext.getProperty(ENTITY_LOGGER_PROPERTY); + writerInterceptorContext.proceed(); + if (stream != null) { + log(stream.getStringBuilder(MessageUtils.getCharset(writerInterceptorContext.getMediaType()))); + } + } + + private static class LoggingStream extends FilterOutputStream { + private final StringBuilder b; + private final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + + LoggingStream(final StringBuilder b, final OutputStream inner) { + super(inner); + + this.b = b; + } + + StringBuilder getStringBuilder(Charset charset) { + // write entity to the builder + final byte[] entity = byteArrayOutputStream.toByteArray(); + + b.append(new String(entity, 0, Math.min(entity.length, maxEntitySize), charset)); + if (entity.length > maxEntitySize) { + b.append("...more..."); + } + b.append('\n'); + + return b; + } + + public void write(final int i) throws IOException { + if (byteArrayOutputStream.size() <= maxEntitySize) { + byteArrayOutputStream.write(i); + } + out.write(i); + } + } + + private void printHeaders(StringBuilder b, MultivaluedMap headers) { + for (String header : requestHeaders) { + if (Objects.nonNull(headers.get(header))) { + if(header.equalsIgnoreCase("Authorization")){ + b.append(header).append(EQUAL).append(getEmail(headers.get(header).get(0))).append(HEADERS_SEPARATOR); + } + else{ + b.append(header).append(EQUAL).append(headers.get(header)).append(HEADERS_SEPARATOR); + } + } + } + int lastIndex = b.lastIndexOf(HEADERS_SEPARATOR); + if (lastIndex != -1) { + b.delete(lastIndex, lastIndex + HEADERS_SEPARATOR.length()); + b.append("\n"); + } + } + + private void log(final StringBuilder b) { + String message = b.toString(); + if (logger != null) { + logger.info(message); + } + } + + private void printRequestLine(final StringBuilder b, final String note, final String method, final URI uri) { + b.append(NOTIFICATION_PREFIX) + .append(note) + .append(" on thread ").append(Thread.currentThread().getId()) + .append(REQUEST_PREFIX).append(method).append(" ") + .append(uri.toASCIIString()).append("\n"); + } + + private void printResponseLine(final StringBuilder b, final String note, final int status) { + b.append(NOTIFICATION_PREFIX) + .append(note) + .append(" on thread ").append(Thread.currentThread().getId()) + .append(RESPONSE_PREFIX) + .append(Integer.toString(status)) + .append("\n"); + } + + private InputStream logInboundEntity(final StringBuilder b, InputStream stream, final Charset charset) throws IOException { + if (!stream.markSupported()) { + stream = new BufferedInputStream(stream); + } + stream.mark(maxEntitySize + 1); + final byte[] entity = new byte[maxEntitySize + 1]; + final int entitySize = stream.read(entity); + b.append(new String(entity, 0, Math.min(entitySize, maxEntitySize), charset)); + if (entitySize > maxEntitySize) { + b.append("...more..."); + } + b.append('\n'); + stream.reset(); + return stream; + } +} \ No newline at end of file diff --git a/otf-camunda/src/main/java/org/oran/otf/camunda/configuration/OtfCamundaConfiguration.java b/otf-camunda/src/main/java/org/oran/otf/camunda/configuration/OtfCamundaConfiguration.java new file mode 100644 index 0000000..a816786 --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/camunda/configuration/OtfCamundaConfiguration.java @@ -0,0 +1,155 @@ +/* Copyright (c) 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.oran.otf.camunda.configuration; + +import com.google.common.base.Strings; +import java.util.Optional; +import java.util.UUID; +import javax.sql.DataSource; +import org.camunda.bpm.application.impl.event.ProcessApplicationEventListenerPlugin; +import org.camunda.bpm.engine.ProcessEngineConfiguration; +import org.camunda.bpm.engine.impl.cfg.IdGenerator; +import org.camunda.bpm.engine.impl.cfg.ProcessEngineConfigurationImpl; +import org.camunda.bpm.engine.impl.history.HistoryLevel; +import org.camunda.bpm.engine.spring.SpringProcessEngineConfiguration; +import org.camunda.bpm.extension.reactor.bus.CamundaEventBus; +import org.camunda.bpm.extension.reactor.plugin.ReactorProcessEnginePlugin; +import org.camunda.bpm.extension.reactor.projectreactor.EventBus; +import org.camunda.bpm.spring.boot.starter.configuration.impl.DefaultProcessEngineConfiguration; +import org.camunda.connect.plugin.impl.ConnectProcessEnginePlugin; +import org.camunda.spin.plugin.impl.SpinProcessEnginePlugin; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.util.StringUtils; + +@Configuration +public class OtfCamundaConfiguration extends DefaultProcessEngineConfiguration { + + @Autowired + private DataSource dataSource; + @Autowired + private PlatformTransactionManager transactionManager; + @Autowired private Optional idGenerator; + + public static String processEngineName; + + @Bean + public ProcessEngineConfiguration configureEngine(ProcessEngineConfigurationImpl configuration) { + configuration.setJavaSerializationFormatEnabled(true); + return configuration; + } + + @Override + public void preInit(SpringProcessEngineConfiguration configuration) { + + logger.info(configuration.getProcessEngineName()); + processEngineName = System.getenv("HOSTNAME"); + if (Strings.isNullOrEmpty(processEngineName)) { + processEngineName = "otf-camunda-" + UUID.randomUUID().toString(); + } + processEngineName = processEngineName.replaceAll("-", "_"); + camundaBpmProperties.setProcessEngineName(processEngineName); + camundaBpmProperties.setAutoDeploymentEnabled(true); + camundaBpmProperties.setHistoryLevel(HistoryLevel.HISTORY_LEVEL_FULL.getName()); + camundaBpmProperties.setDefaultNumberOfRetries(1); + + setProcessEngineName(configuration); + setDefaultSerializationFormat(configuration); + setIdGenerator(configuration); + setJobExecutorAcquireByPriority(configuration); + setDefaultNumberOfRetries(configuration); + + configuration.setDataSource(dataSource); + configuration.setTransactionManager(transactionManager); + configuration.setHistory("true"); + configuration.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE); + configuration.setJobExecutorActivate(true); + configuration.setCreateIncidentOnFailedJobEnabled(true); + configuration.setFailedJobListenerMaxRetries(0); + configuration.setJavaSerializationFormatEnabled(true); + configuration.setMetricsEnabled(false); + } + + private void setIdGenerator(SpringProcessEngineConfiguration configuration) { + idGenerator.ifPresent(configuration::setIdGenerator); + } + + private void setDefaultSerializationFormat(SpringProcessEngineConfiguration configuration) { + String defaultSerializationFormat = camundaBpmProperties.getDefaultSerializationFormat(); + if (StringUtils.hasText(defaultSerializationFormat)) { + configuration.setDefaultSerializationFormat(defaultSerializationFormat); + } else { + logger.warn("Ignoring invalid defaultSerializationFormat='{}'", defaultSerializationFormat); + } + } + + private void setProcessEngineName(SpringProcessEngineConfiguration configuration) { + String processEngineName = + StringUtils.trimAllWhitespace(camundaBpmProperties.getProcessEngineName()); + if (!StringUtils.isEmpty(processEngineName) && !processEngineName.contains("-")) { + configuration.setProcessEngineName(processEngineName); + } else { + logger.warn( + "Ignoring invalid processEngineName='{}' - must not be null, blank or contain hyphen", + camundaBpmProperties.getProcessEngineName()); + } + } + + private void setJobExecutorAcquireByPriority(SpringProcessEngineConfiguration configuration) { + Optional.ofNullable(camundaBpmProperties.getJobExecutorAcquireByPriority()) + .ifPresent(configuration::setJobExecutorAcquireByPriority); + } + + private void setDefaultNumberOfRetries(SpringProcessEngineConfiguration configuration) { + Optional.ofNullable(camundaBpmProperties.getDefaultNumberOfRetries()) + .ifPresent(configuration::setDefaultNumberOfRetries); + } + + @Bean + CamundaEventBus camundaEventBus() { + return new CamundaEventBus(); + } + + @Bean + @Qualifier("camunda") + EventBus eventBus(final CamundaEventBus camundaEventBus) { + return camundaEventBus.get(); + } + + @Bean + ReactorProcessEnginePlugin reactorProcessEnginePlugin(final CamundaEventBus camundaEventBus) { + return new ReactorProcessEnginePlugin(camundaEventBus); + } + + @Bean + ConnectProcessEnginePlugin connectProcessEnginePlugin() { + return new ConnectProcessEnginePlugin(); + } + + @Bean + SpinProcessEnginePlugin spinProcessEnginePlugin() { + return new SpinProcessEnginePlugin(); + } + + @Bean + ProcessApplicationEventListenerPlugin processApplicationEventListenerPlugin() { + return new ProcessApplicationEventListenerPlugin(); + } +} diff --git a/otf-camunda/src/main/java/org/oran/otf/camunda/configuration/listener/OTFJobExecutorStartingEventListener.java b/otf-camunda/src/main/java/org/oran/otf/camunda/configuration/listener/OTFJobExecutorStartingEventListener.java new file mode 100644 index 0000000..d2d0194 --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/camunda/configuration/listener/OTFJobExecutorStartingEventListener.java @@ -0,0 +1,44 @@ +/* Copyright (c) 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.oran.otf.camunda.configuration.listener; + +import org.camunda.bpm.spring.boot.starter.event.JobExecutorStartingEventListener; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; + +public class OTFJobExecutorStartingEventListener extends JobExecutorStartingEventListener { + + private static final Logger LOGGER = LoggerFactory.getLogger(OTFJobExecutorStartingEventListener.class); + + @Value("${otf.camunda.executors-active}") + private boolean executorsActive; + + protected void activate() { + if(!executorsActive){ + LOGGER.info("job executor auto start disabled. otf.camunda.executors-active: " + this.executorsActive); + jobExecutor.shutdown(); + return; + } + if (!jobExecutor.isActive()) { + jobExecutor.start(); + } else { + LOGGER.info("job executor is already active"); + } + } + +} diff --git a/otf-camunda/src/main/java/org/oran/otf/camunda/delegate/otf/common/CallTestHeadDelegate.java b/otf-camunda/src/main/java/org/oran/otf/camunda/delegate/otf/common/CallTestHeadDelegate.java new file mode 100644 index 0000000..45511b0 --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/camunda/delegate/otf/common/CallTestHeadDelegate.java @@ -0,0 +1,329 @@ +/* Copyright (c) 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.oran.otf.camunda.delegate.otf.common; + +import org.oran.otf.camunda.delegate.otf.common.runnable.TestHeadCallable; +import org.oran.otf.camunda.exception.TestExecutionException; +import org.oran.otf.camunda.workflow.utility.WorkflowTask; +import org.oran.otf.camunda.workflow.utility.WorkflowUtility; +import org.oran.otf.common.model.*; +import org.oran.otf.common.model.local.BpmnInstance; +import org.oran.otf.common.model.local.TestHeadNode; +import org.oran.otf.common.model.local.TestHeadResult; +import org.oran.otf.common.repository.*; +import org.oran.otf.common.utility.Utility; +import org.oran.otf.common.utility.database.Generic; +import org.oran.otf.common.utility.permissions.PermissionChecker; +import org.oran.otf.common.utility.permissions.UserPermission; +import com.mongodb.client.result.UpdateResult; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.TimeUnit; + +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.camunda.bpm.engine.delegate.JavaDelegate; +import org.oran.otf.common.model.*; +import org.oran.otf.common.repository.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.query.Criteria; +import org.springframework.data.mongodb.core.query.Query; +import org.springframework.data.mongodb.core.query.Update; +import org.springframework.stereotype.Component; + +@Component +public class CallTestHeadDelegate implements JavaDelegate { + private static final Logger logger = LoggerFactory.getLogger(CallTestHeadDelegate.class); + + @Autowired + private UserRepository userRepository; + @Autowired + private GroupRepository groupRepository; + @Autowired + private WorkflowUtility utility; + @Autowired + private TestDefinitionRepository testDefinitionRepository; + @Autowired + private TestHeadRepository testHeadRepository; + @Autowired + private TestInstanceRepository testInstanceRepository; + @Autowired + private MongoTemplate mongoOperation; + + // Used to retrieve the results from test head runnables. + List testHeadResults = Collections.synchronizedList(new ArrayList<>()); + + @Override + public void execute(DelegateExecution execution) throws Exception { + callTestHead( + execution.getCurrentActivityId(), + execution.getProcessDefinitionId(), + execution.getProcessInstanceId(), + execution.getProcessBusinessKey(), + execution.getVariables()); + } + + public void callTestHead( + String currentActivityId, + String processDefinitionId, + String processInstanceId, + String processBusinessKey, + Map variables) + throws Exception { + final String logPrefix = Utility.getLoggerPrefix(); + logger.info(logPrefix + "::execute()"); + + // Get vthInput from the Camunda execution variable map. + List> activityParameters = utility.getVthInput(variables, currentActivityId, logPrefix); + + // Get the current test execution object. + TestExecution testExecution = utility.getTestExecution(variables, logPrefix); + + // Lookup the test head before making computations in the loop, and before calling the runnable. + // If the lookup is made inside the runnable, concurrent test head calls would bombard the db. + TestHead testHead = getTestHead(testExecution, currentActivityId, processDefinitionId); + + WorkflowTask workflowTask = new WorkflowTask(processInstanceId, activityParameters.size(), false); + ExecutorService pool = workflowTask.getPool(); + + // Try to cast each parameter to a Map, and create runnable tasks. + for (int i = 0; i < activityParameters.size(); i++) { + Object oTestHeadParameter = activityParameters.get(i); + Map mTestHeadParameter; + try { + mTestHeadParameter = Utility.toMap(oTestHeadParameter); + verifyOtfTestHead(mTestHeadParameter, testHead, testExecution, currentActivityId); + } catch (Exception e) { + // TODO: Make a design decision to either stop the execution, or attempt to convert the + // other parameters. + logger.error( + String.format( + "Unable to convert test head parameter at vthInput[%s][%d] to a Map.", + currentActivityId, i)); + continue; + } + + // Get all the arguments for the runnable. + Object oHeaders = mTestHeadParameter.get("headers"); // optional + Object oMethod = mTestHeadParameter.get("method"); // required + Object oPayload = mTestHeadParameter.get("payload"); // optional + Object oTimeoutInMillis = mTestHeadParameter.get("timeoutInMillis"); // optional + + // Target typed parameters. Convert all objects to their expected types. Throw exceptions for + // required parameters, or for parameters that are provided but not of the expected type. + Map headers = new HashMap<>(); + String method = ""; + Map payload = new HashMap<>(); + int timeoutInMillis = 0; + + if (oHeaders != null) { + try { + headers = (Map) Utility.toMap(oHeaders); + } catch (Exception e) { + logger.error( + String.format( + "Unable to convert test head parameter at vthInput[%s][%d][headers] to a Map.", + currentActivityId, i)); + } + } + + if (oMethod == null) { + throw new TestExecutionException( + String.format( + "vthInput[%s][%d][method] is a required parameter.", currentActivityId, i)); + } else { + try { + method = (String) oMethod; + } catch (ClassCastException cce) { + throw new TestExecutionException( + String.format( + "Unable to read vthInput[%s][%d][method] as primitive type String.", + processInstanceId, i)); + } + } + + if (oPayload != null) { + try { + payload = (Map) Utility.toMap(oPayload); + } catch (Exception e) { + logger.error( + String.format( + "Unable to convert test head parameter at vthInput[%s][%d][payload] to a Map.", + currentActivityId, i)); + } + } + + if (oTimeoutInMillis != null) { + try { + timeoutInMillis = (int) oTimeoutInMillis; + } catch (ClassCastException cce) { + throw new TestExecutionException( + String.format( + "Unable to read vthInput[%s][%d][timeoutInMillis] as primitive type int.", + currentActivityId, i)); + } + } + +// logger.info("{}(BEFORE) PRINTING THREAD INFORMATION", logPrefix); +// WorkflowTask.printThreadInformation(); +// logger.info("{}(BEFORE) PRINTING WORKFLOW TASKS", logPrefix); +// WorkflowTask.printWorkflowTaskResources(); + TestHeadCallable callable = + new TestHeadCallable( + timeoutInMillis, + method, + headers, + payload, + testHead, + currentActivityId, + testExecution, + mongoOperation); + + // Submit the test head call to the executor service. + workflowTask.getFutures().add(pool.submit(callable)); + } + + // Prevent new tasks from being submitted, and allow running tasks to finish. + pool.shutdown(); + + int numResults = 0; + while (!pool.isTerminated()) { + try { + pool.awaitTermination(1, TimeUnit.SECONDS); + } catch (InterruptedException e) { + workflowTask.shutdown(true); + throw e; + } + } + + workflowTask.shutdown(false); + +// logger.info("{}(AFTER) PRINTING THREAD INFORMATION", logPrefix); +// WorkflowTask.printThreadInformation(); +// logger.info("{}(AFTER) PRINTING WORKFLOW TASKS", logPrefix); +// WorkflowTask.printWorkflowTaskResources(); + } + + private void saveTestHeadResults(String businessKey) { + Query query = new Query(); + query.addCriteria(Criteria.where("businessKey").is(businessKey)); + Update update = new Update(); + update.set("testHeadResults", testHeadResults); + UpdateResult result = mongoOperation.updateFirst(query, update, TestExecution.class); + // Check the status of the findAndUpdate database, and appropriately handle the errors. + if (result.getMatchedCount() == 0) { + throw new TestExecutionException( + String.format( + "Unable to log the test result because a testExecution associated with businessKey, %s, was not found.", + businessKey)); + } else if (result.getModifiedCount() == 0) { + throw new TestExecutionException("Unable to persist the testExecution to the database."); + } + } + + private TestHead getTestHead( + TestExecution testExecution, String currentActivityId, String processDefinitionId) { + List bpmnInstances = testExecution.getHistoricTestDefinition().getBpmnInstances(); + BpmnInstance bpmnInstance = + bpmnInstances.stream() + .filter( + _bpmnInstance -> + _bpmnInstance.getProcessDefinitionId().equalsIgnoreCase(processDefinitionId)) + .findFirst() + .orElse(null); + + if (bpmnInstance == null) { + throw new TestExecutionException( + String.format( + "Error looking BpmnInstance with processDefinitionId %s.", processDefinitionId)); + } + + List testHeads = bpmnInstance.getTestHeads(); + TestHeadNode testHeadNode = + testHeads.stream() + .filter(testHead -> testHead.getBpmnVthTaskId().equals(currentActivityId)) + .findAny() + .orElse(null); + + if (testHeadNode == null) { + throw new TestExecutionException( + String.format( + "No test head associated with the currentActivityId %s.", currentActivityId)); + } + + TestHead testHead = Generic.findByIdGeneric(testHeadRepository, testHeadNode.getTestHeadId()); + if (testHead == null) { + throw new TestExecutionException( + String.format( + "The test head with id, %s, was not found in the database.", + testHeadNode.getTestHeadId())); + } + User testExecUser = userRepository.findById(testExecution.getExecutorId().toString()).orElse(null); + Group testheadGroup = groupRepository.findById(testHead.getGroupId().toString()).orElse(null); + if(testExecUser == null){ + throw new TestExecutionException( + String.format("Can not find user, user id: %s",testExecution.getExecutorId().toString())); + } + if(testheadGroup == null){ + throw new TestExecutionException( + String.format("Can not find test head group, group id: %s",testHead.getGroupId().toString()) + ); + } + + if( (testHead.isPublic() != null && !testHead.isPublic()) && + !PermissionChecker.hasPermissionTo(testExecUser,testheadGroup,UserPermission.Permission.EXECUTE,groupRepository)){ + throw new TestExecutionException( + String.format( + "User(%s) does not have permission to in testHead Group(%s)", + testExecUser.get_id().toString(),testheadGroup.get_id().toString() + )); + } + return testHead; + } + + private void verifyOtfTestHead(Map activityParams, TestHead testHead, TestExecution execution, String currentActivityId){ + String testHeadName = testHead.getTestHeadName().toLowerCase(); + switch(testHeadName) { + case "robot": + try { + TestInstance testInstance = Generic.findByIdGeneric(testInstanceRepository, execution.getHistoricTestInstance().get_id()); + Map internalTestDataByActivity = (Map) testInstance.getInternalTestData().get(currentActivityId); + String robotFileId = (String) internalTestDataByActivity.get("robotFileId"); + Map testData = new HashMap<>(); + Map vthInput = new HashMap<>(); + testData.put("robotFileId", robotFileId); + vthInput.put("testData", testData); + Map payload = (Map) activityParams.get("payload"); + payload.put("vthInput", vthInput); + } + catch (Exception e){ + throw new TestExecutionException( + String.format( + "Robot test head needs a robot file id: %s.", e.getMessage())); + } + break; + default: + break; + } + } +} diff --git a/otf-camunda/src/main/java/org/oran/otf/camunda/delegate/otf/common/LogTestResultDelegate.java b/otf-camunda/src/main/java/org/oran/otf/camunda/delegate/otf/common/LogTestResultDelegate.java new file mode 100644 index 0000000..0ecb37e --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/camunda/delegate/otf/common/LogTestResultDelegate.java @@ -0,0 +1,114 @@ +/* Copyright (c) 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.oran.otf.camunda.delegate.otf.common; + +import org.oran.otf.camunda.exception.TestExecutionException; +import org.oran.otf.camunda.model.ExecutionConstants; +import org.oran.otf.camunda.workflow.utility.WorkflowUtility; +import org.oran.otf.common.model.TestExecution; +import org.oran.otf.common.repository.TestExecutionRepository; +import org.oran.otf.common.utility.Utility; +import com.mongodb.client.result.UpdateResult; + +import java.util.Arrays; +import java.util.Date; +import java.util.Map; +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.camunda.bpm.engine.delegate.JavaDelegate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.query.Criteria; +import org.springframework.data.mongodb.core.query.Query; +import org.springframework.data.mongodb.core.query.Update; +import org.springframework.stereotype.Component; + +@Component +public class LogTestResultDelegate implements JavaDelegate { + + private static Logger logger = LoggerFactory.getLogger(LogTestResultDelegate.class); + + @Autowired + private TestExecutionRepository testExecutionRepository; + @Autowired + private MongoTemplate mongoOperation; + @Autowired + private WorkflowUtility utility; + + @Override + public void execute(DelegateExecution execution) throws Exception { + logger.info("[LogTestResult] Starting to log test result."); + final String logPrefix = Utility.getLoggerPrefix(); + // Get the current test execution object. + TestExecution testExecution = utility.getTestExecution(execution.getVariables(), logPrefix); + + // Set the end time right after retrieving the execution. This will not include the save time + // to the database. + testExecution.setEndTime(new Date(System.currentTimeMillis())); + + // Set the processInstanceId because the user may have modified it through a script task. + testExecution.setProcessInstanceId(execution.getProcessInstanceId()); + + // Get the test result from the execution. + String testResult = utility.getTestResult(execution.getVariables(), logPrefix).toUpperCase(); + if(testResult.equalsIgnoreCase(ExecutionConstants.TestResult.WORKFLOW_ERROR)){ + testResult = ExecutionConstants.TestResult.ERROR; + } + if(Arrays.asList(ExecutionConstants.getAllTestResultStr()).contains(testResult.toUpperCase())) + testExecution.setTestResult(testResult.toUpperCase()); + else{ + testExecution.setTestResult(ExecutionConstants.TestResult.OTHER); + } + + //Get the test result message from the execution + String testResultMessage = utility.getTestResultMessage(execution.getVariables(), logPrefix); + testExecution.setTestResultMessage(testResultMessage); + + // Get test details as a String because it can be saved as one of many "JSON" types. Then try + // to convert it to a generic map. + Map testDetails = utility.getTestDetails(execution.getVariables(), logPrefix); + // Save the converted object to the test execution. + testExecution.setTestDetails(testDetails); + + + // Update the Test Execution object to save the result. Find the existing test execution by the + // processBusinessKey from the delegate execution because it is saved to the database before the + // user can modify the value. + Query query = new Query(); + query.addCriteria(Criteria.where("businessKey").is(execution.getProcessBusinessKey())); + Update update = new Update(); + update.set("testResult", testExecution.getTestResult()); + update.set("testResultMessage", testExecution.getTestResultMessage()); + update.set("testDetails", testExecution.getTestDetails()); + update.set("endTime", testExecution.getEndTime()); + update.set("processInstanceId", execution.getProcessInstanceId()); + UpdateResult result = mongoOperation.updateFirst(query, update, TestExecution.class); + // Check the status of the findAndUpdate database, and appropriately handle the errors. + if (result.getMatchedCount() == 0) { + throw new TestExecutionException( + String.format( + "Unable to log the test result because a testExecution associated with businessKey, %s, was not found.", + execution.getProcessBusinessKey())); + } else if (result.getModifiedCount() == 0) { + throw new TestExecutionException("Unable to persist the testExecution to the database."); + } else { + logger.info( + logPrefix + execution.getProcessInstanceId() + ": Saved test result to the database."); + } + } +} diff --git a/otf-camunda/src/main/java/org/oran/otf/camunda/delegate/otf/common/PostResultsToDMaaPDelegate.java b/otf-camunda/src/main/java/org/oran/otf/camunda/delegate/otf/common/PostResultsToDMaaPDelegate.java new file mode 100644 index 0000000..41b9d8a --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/camunda/delegate/otf/common/PostResultsToDMaaPDelegate.java @@ -0,0 +1,159 @@ +/* Copyright (c) 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.oran.otf.camunda.delegate.otf.common; + +import org.oran.otf.cadi.configuration.FilterCondition; +import org.oran.otf.camunda.exception.TestExecutionException; +import org.oran.otf.camunda.model.ExecutionConstants; +import org.oran.otf.camunda.workflow.utility.WorkflowUtility; +import org.oran.otf.common.model.TestExecution; +import org.oran.otf.common.model.local.DMaaPRequest; +import org.oran.otf.common.utility.Utility; +import org.oran.otf.common.utility.gson.Convert; +import org.oran.otf.common.utility.http.RequestUtility; +import com.fasterxml.jackson.core.type.TypeReference; + +import java.util.Base64; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import javax.ws.rs.core.MediaType; +import org.apache.http.HttpResponse; +import org.apache.http.util.EntityUtils; +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.camunda.bpm.engine.delegate.JavaDelegate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Conditional; +import org.springframework.stereotype.Component; + +@Component +public class PostResultsToDMaaPDelegate implements JavaDelegate { + + private static Logger logger = LoggerFactory.getLogger(PostResultsToDMaaPDelegate.class); + + @Value("${otf.cadi.aaf-mech-id}") + private String AAF_APPID; + + @Value("${otf.cadi.aaf-mech-password}") + private String AAF_APPPASS; + + @Value("${otf.environment}") + private String env; + + @Autowired private WorkflowUtility utility; + + private final String template = "https://:3905/events/"; + + @Override + public void execute(DelegateExecution execution) throws Exception { + logger.info("[PostResultsToDMaaP] Starting to post test results to dmaap."); + final String logPrefix = Utility.getLoggerPrefix(); + + // Get the current test execution object. + TestExecution testExecution = utility.getTestExecution(execution.getVariables(), logPrefix); + + List testDataActivity = null; + Object dataByActivity = + utility.getTestDataByActivity( + execution.getVariables(), execution.getCurrentActivityId(), logPrefix); + if (!(dataByActivity instanceof List)) { + logger.error( + execution.getActivityInstanceId() + + ": Failed to retrieve dmaap requests in test data as list"); + throw new TestExecutionException( + execution.getActivityInstanceId() + + ": Missing data to post to dmaap. Failed to retrieve dmaap requests in test data as list"); + } + + // convert data to map and grab dmaaprequest array + testDataActivity = (List) dataByActivity; + List dmaapRequests = null; + try { + dmaapRequests = + Convert.listToObjectList(testDataActivity, new TypeReference>() {}); + } catch (Exception e) { + logger.error( + execution.getActivityInstanceId() + ": Failed to get dmaap requests from test data"); + throw new TestExecutionException( + execution.getActivityInstanceId() + ": Missing data to post to dmaap. " + e.getMessage(), + e); + } + if (dmaapRequests == null || dmaapRequests.isEmpty()) { + logger.error(execution.getActivityInstanceId() + ": Failed to retrieve dmaap request list"); + throw new TestExecutionException( + execution.getActivityInstanceId() + ": Missing dmaap request list"); + } + + // Get the testDetails object + Map testDetails = utility.getTestDetails(execution.getVariables(), logPrefix); + + // Post results to Dmaap + Map results = postResultsToDmaap(testExecution, dmaapRequests, logPrefix); + + // Set test details to show results of each post to dmaap + testDetails.put(execution.getCurrentActivityId(), results); + execution.setVariable(ExecutionConstants.ExecutionVariable.TEST_DETAILS, testDetails); + logger.info("[PostResultsToDMaaP] Finished posting test results to dmaap."); + } + + private Map postResultsToDmaap( + TestExecution execution, List dmaapRequests, String logPrefix) { + String payload = execution.toString(); + Map results = new HashMap<>(); + Map headers = new HashMap<>(); + headers.put("Authorization", getAuthorizationHeader()); + headers.put("Content-Type", MediaType.APPLICATION_JSON); + + for (DMaaPRequest request : dmaapRequests) { + String url = new String(template); + url = url.replace("", request.getHostname()); + url = url.replace("", request.getAsyncTopic()); + + try { + results.put(url, getResponse(url, payload, headers, request.getRequiresProxy())); + } catch (Exception e) { + e.printStackTrace(); + logger.info(logPrefix + "Error while posting to dmaap : " + e.getMessage()); + results.put(url, e.getMessage()); + } + } + return results; + } + + private Map getResponse( + String url, String payload, Map headers, boolean proxy) + throws Exception { + HttpResponse response = RequestUtility.postSync(url, payload, headers, proxy); + String sRes = EntityUtils.toString(response.getEntity()); + Map res; + try { + res = Convert.jsonToMap(sRes); + } catch (Exception e) { + res = new HashMap<>(); + res.put("response", sRes); + } + return res; + } + + private String getAuthorizationHeader() { + return "Basic " + + new String(Base64.getEncoder().encode((AAF_APPID + ":" + AAF_APPPASS).getBytes())); + } +} diff --git a/otf-camunda/src/main/java/org/oran/otf/camunda/delegate/otf/common/RunTestInstanceDelegate.java b/otf-camunda/src/main/java/org/oran/otf/camunda/delegate/otf/common/RunTestInstanceDelegate.java new file mode 100644 index 0000000..7b90e7e --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/camunda/delegate/otf/common/RunTestInstanceDelegate.java @@ -0,0 +1,180 @@ +/* Copyright (c) 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.oran.otf.camunda.delegate.otf.common; + +import org.oran.otf.camunda.delegate.otf.common.runnable.SynchronousTestInstanceCallable; +import org.oran.otf.camunda.exception.TestExecutionException; +import org.oran.otf.camunda.workflow.WorkflowProcessor; +import org.oran.otf.camunda.workflow.WorkflowRequest; +import org.oran.otf.camunda.workflow.utility.WorkflowTask; +import org.oran.otf.camunda.workflow.utility.WorkflowUtility; +import org.oran.otf.common.model.TestExecution; +import org.oran.otf.common.model.local.ParallelFlowInput; +import org.oran.otf.common.repository.TestExecutionRepository; +import org.oran.otf.common.utility.Utility; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.TimeUnit; +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.camunda.bpm.engine.delegate.JavaDelegate; +import org.oran.otf.camunda.model.ExecutionConstants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.stereotype.Component; + +@Component +public class RunTestInstanceDelegate implements JavaDelegate { + + private final String logPrefix = Utility.getLoggerPrefix(); + private final Logger logger = LoggerFactory.getLogger(RunTestInstanceDelegate.class); + // Used to retrieve the results from test head runnables. + private final List testExecutions = + Collections.synchronizedList(new ArrayList<>()); + + private @Autowired + WorkflowUtility utility; + private @Autowired + TestExecutionRepository testExecutionRepository; + private @Autowired + WorkflowProcessor processor; + private @Autowired MongoTemplate mongoOperation; + + @Override + public void execute(DelegateExecution execution) throws Exception { + runTestInstance( + execution.getCurrentActivityId(), + execution.getProcessInstanceId(), + execution.getVariables()); + } + + public void runTestInstance( + String currentActivityId, String processInstanceId, Map variables) + throws Exception { + @SuppressWarnings("unchecked") + + // Get the current test execution object to pass as an argument to the callable, and for data + // stored in the historicTestInstance + TestExecution testExecution = utility.getTestExecution(variables, logPrefix); + + // Get the parallel flow input + Map pfloInput = + (Map) variables.get("pfloInput"); + + if (!pfloInput.containsKey(currentActivityId)) { + throw new TestExecutionException( + String.format( + "%sCould not find activityId %s in pfloInput.", logPrefix, currentActivityId)); + } + + ParallelFlowInput parallelFlowInput = pfloInput.get(currentActivityId); + List args = parallelFlowInput.getArgs(); + boolean interruptOnFailure = parallelFlowInput.isInterruptOnFailure(); + int maxFailures = parallelFlowInput.getMaxFailures(); + int threadPoolSize = parallelFlowInput.getThreadPoolSize(); + + WorkflowTask workflowTask = + new WorkflowTask(processInstanceId, threadPoolSize, interruptOnFailure); + ExecutorService pool = workflowTask.getPool(); + +// logger.info("{}(BEFORE) PRINTING THREAD INFORMATION", logPrefix); +// WorkflowTask.printThreadInformation(); +// logger.info("{}(BEFORE) PRINTING WORKFLOW TASKS", logPrefix); +// WorkflowTask.printWorkflowTaskResources(); + + for (WorkflowRequest request : args) { + request.setExecutorId(testExecution.getExecutorId()); + // If an inner workflow calls the parent workflow, there is a cyclic dependency. To prevent + // infinite test instances from being spawned, we need to check for cycles. This is only a top + // level check, but a more thorough check needs to be implemented after 1906. + if (request.getTestInstanceId() == testExecution.getHistoricTestInstance().get_id()) { + // Prevent new tasks from being submitted + pool.shutdown(); + // Shutdown the thread pool, and cleanup threads. + workflowTask.shutdown(true); + break; + } + + SynchronousTestInstanceCallable synchronousTestInstanceCallable = + new SynchronousTestInstanceCallable( + request, testExecution, testExecutionRepository, processor, mongoOperation); + workflowTask.getFutures().add(pool.submit(synchronousTestInstanceCallable)); + } + + // Prevent new tasks from being submitted, and allow running tasks to finish. + pool.shutdown(); + + // Wait for test instances to finish execution, and check for failures. + while (!pool.isTerminated()) { + try { + // Terminate tasks if the test execution failure limit is reached. + int numFailures; + synchronized (testExecution) { + numFailures = getNumberOfFailures(testExecution.getTestInstanceResults()); + } + + if (numFailures > maxFailures) { + logger.error( + String.format( + "[PARENT-%s] Shutting down workflow - numFailures: %s, maxFailures: %s.", + processInstanceId, numFailures, maxFailures)); + workflowTask.shutdown(); + } + + pool.awaitTermination(1, TimeUnit.SECONDS); + } catch (InterruptedException e) { + throw e; + } + } + + workflowTask.shutdown(false); + +// logger.info("{}(AFTER) PRINTING THREAD INFORMATION", logPrefix); +// WorkflowTask.printThreadInformation(); +// logger.info("{}(AFTER) PRINTING WORKFLOW TASKS", logPrefix); +// WorkflowTask.printWorkflowTaskResources(); + } + + // Gets the total number of testExecutions that have failed. + private int getNumberOfFailures(List testExecutions) { + int numFailures = 0; + + for (TestExecution testExecution : testExecutions) { + if (isTestFailed(testExecution)) { + numFailures++; + } + } + + return numFailures; + } + + // Checks if the testResult is marked as FAILED or FAILURE. + private boolean isTestFailed(TestExecution testExecution) { + String testResult = testExecution.getTestResult(); + logger.debug( + String.format( + "[PARENT-%s] Test result for inner execution: %s.", + testExecution.getProcessInstanceId(), testExecution.getTestResult())); + return testResult.equalsIgnoreCase(ExecutionConstants.TestResult.FAILED) +// || testResult.equalsIgnoreCase(TestResult.FAILED) + || testResult.equalsIgnoreCase(ExecutionConstants.TestResult.TERMINATED); + } +} diff --git a/otf-camunda/src/main/java/org/oran/otf/camunda/delegate/otf/common/SendMailDelegate.java b/otf-camunda/src/main/java/org/oran/otf/camunda/delegate/otf/common/SendMailDelegate.java new file mode 100644 index 0000000..9755214 --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/camunda/delegate/otf/common/SendMailDelegate.java @@ -0,0 +1,170 @@ +/* Copyright (c) 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.oran.otf.camunda.delegate.otf.common; + +import org.oran.otf.camunda.exception.TestExecutionException; +import org.oran.otf.camunda.workflow.utility.WorkflowUtility; +import org.oran.otf.common.model.TestExecution; +import org.oran.otf.common.utility.Utility; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import javax.mail.Message; +import javax.mail.MessagingException; +import javax.mail.Session; +import javax.mail.Transport; +import javax.mail.internet.InternetAddress; +import javax.mail.internet.MimeMessage; +import org.assertj.core.util.Strings; +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.camunda.bpm.engine.delegate.JavaDelegate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class SendMailDelegate implements JavaDelegate { + + @Autowired private WorkflowUtility utility; + + private static final String logPrefix = Utility.getLoggerPrefix(); + private static final Logger log = LoggerFactory.getLogger(SendMailDelegate.class); + + @Override + public void execute(DelegateExecution execution) throws Exception { + Map variables = execution.getVariables(); + Map testData = utility.getTestData(variables, logPrefix); + + Map sendMailData = null; + try { + sendMailData = + (Map) testData.getOrDefault(execution.getCurrentActivityId(), null); + } catch (Exception e) { + log.error(e.getMessage()); + throw new TestExecutionException(e); + } + + if (sendMailData == null) { + String err = + String.format( + "%sMissing parameters for activityId, %s.", + logPrefix, execution.getCurrentActivityId()); + log.error(err); + throw new TestExecutionException(err); + } + + // Get the recipient(s) + Object oRecipients = sendMailData.get("to"); + if (oRecipients == null) { + String err = String.format("%sRecipients array cannot be null or empty.", logPrefix); + log.error(err); + throw new TestExecutionException(err); + } + List recipients = null; + try { + recipients = (ArrayList) (oRecipients); + if (recipients.size() == 0) { + String err = String.format("%sRecipients array cannot be null or empty.", logPrefix); + log.error(err); + throw new TestExecutionException(err); + } + } catch (Exception e) { + throw new TestExecutionException(e); + } + + for (String recipient : recipients) { + if (Strings.isNullOrEmpty(recipient)) { + String err = String.format("%sRecipient cannot be null or empty.", logPrefix); + log.error(err); + throw new TestExecutionException(err); + } + } + + // Get the email subject. + String subject = (String) sendMailData.get("subject"); + if (Strings.isNullOrEmpty(subject.trim())) { + String err = String.format("%sSubject cannot be null or empty.", logPrefix); + log.error(err); + throw new TestExecutionException(err); + } + + // Get the body contents. + String body = (String) sendMailData.get("body"); + if (Strings.isNullOrEmpty(body.trim())) { + String err = String.format("%sBody cannot be null or empty.", logPrefix); + log.error(err); + throw new TestExecutionException(err); + } + + TestExecution testExecution = utility.getTestExecution(variables, logPrefix); + String sender = testExecution.getHistoricEmail(); + String hTestInstanceId = testExecution.getHistoricTestInstance().get_id().toString(); + String processInstanceId = execution.getProcessInstanceId(); + + sendMail(recipients, subject, body, sender, processInstanceId, hTestInstanceId); + } + + public void sendMail( + List recipients, + String subject, + String body, + String sender, + String processInstanceId, + String testInstanceId) + throws Exception { + // Get the system properties. + Properties properties = System.getProperties(); + + // Set the SMTP host. + properties.setProperty("mail.smtp.host", "localhost"); + + // creating session object to get properties + Session session = Session.getDefaultInstance(properties); + + try { + // MimeMessage object. + MimeMessage message = new MimeMessage(session); + + // Set From Field: adding senders email to from field. + message.setFrom(new InternetAddress("OTF_EMAIL-ALERT@localhost")); + + // Set Subject: subject of the email + message.setSubject(subject); + + // set body of the email. + StringBuffer sb = new StringBuffer(); + sb.append("************************OTF Alerting System************************"); + sb.append("\n\n"); + sb.append(String.format("This message was sent by %s via the Open Test Framework\n", sender)); + sb.append(String.format("processInstanceId: %s\n", processInstanceId)); + sb.append(String.format("testInstanceId: %s", testInstanceId)); + sb.append("\n\n"); + sb.append("******************************************************************"); + sb.append("\n\n"); + sb.append(body); + + message.setText(sb.toString()); + + // Send email. + Transport.send(message); + } catch (MessagingException mex) { + mex.printStackTrace(); + } + } +} diff --git a/otf-camunda/src/main/java/org/oran/otf/camunda/delegate/otf/common/runnable/AsynchronousTestInstanceCallable.java b/otf-camunda/src/main/java/org/oran/otf/camunda/delegate/otf/common/runnable/AsynchronousTestInstanceCallable.java new file mode 100644 index 0000000..680688c --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/camunda/delegate/otf/common/runnable/AsynchronousTestInstanceCallable.java @@ -0,0 +1,199 @@ +/* Copyright (c) 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.oran.otf.camunda.delegate.otf.common.runnable; + +import org.oran.otf.camunda.configuration.OtfCamundaConfiguration; +import org.oran.otf.camunda.exception.TestExecutionException; +import org.oran.otf.camunda.exception.WorkflowProcessorException; +import org.oran.otf.camunda.service.ProcessEngineAwareService; +import org.oran.otf.camunda.workflow.WorkflowProcessor; +import org.oran.otf.camunda.workflow.WorkflowRequest; +import org.oran.otf.common.model.TestExecution; +import org.oran.otf.common.repository.TestExecutionRepository; +import org.oran.otf.common.utility.database.TestExecutionUtility; +import com.mongodb.client.result.UpdateResult; +import java.util.Timer; +import java.util.TimerTask; +import java.util.concurrent.Callable; + +import org.camunda.bpm.BpmPlatform; +import org.camunda.bpm.engine.RuntimeService; +import org.camunda.bpm.engine.runtime.ProcessInstance; +import org.oran.otf.camunda.model.ExecutionConstants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.query.Criteria; +import org.springframework.data.mongodb.core.query.Query; +import org.springframework.data.mongodb.core.query.Update; + +public class AsynchronousTestInstanceCallable extends ProcessEngineAwareService + implements Callable { + + private static final Logger logger = + LoggerFactory.getLogger(AsynchronousTestInstanceCallable.class); + private final TestExecution parentTestExecution; + private final TestExecutionRepository testExecutionRepository; + private final WorkflowProcessor processor; + private final MongoTemplate mongoOperation; + + private final WorkflowRequest request; + private String processInstanceId; + + public AsynchronousTestInstanceCallable( + WorkflowRequest request, + TestExecution parentTestExecution, + TestExecutionRepository testExecutionRepository, + WorkflowProcessor processor, + MongoTemplate mongoOperation) { + this.request = request; + this.parentTestExecution = parentTestExecution; + + this.processInstanceId = ""; + + this.testExecutionRepository = testExecutionRepository; + this.processor = processor; + this.mongoOperation = mongoOperation; + } + + public AsynchronousTestInstanceCallable( + WorkflowRequest request, + TestExecutionRepository testExecutionRepository, + WorkflowProcessor processor, + MongoTemplate mongoOperation) { + this.request = request; + this.parentTestExecution = null; + + this.processInstanceId = ""; + + this.testExecutionRepository = testExecutionRepository; + this.processor = processor; + this.mongoOperation = mongoOperation; + } + + @Override + public TestExecution call() throws WorkflowProcessorException { + try { + TestExecution initialTestExecution = processor.processWorkflowRequest(request); + this.processInstanceId = initialTestExecution.getProcessInstanceId(); + + // Create a timer task that will call the cancellation after the specified time. + TimerTask abortTestInstanceTask = + new TimerTask() { + @Override + public void run() { + cancelProcessInstance(processInstanceId); + + // Find the result after the process instance after it has finished. + TestExecution testExecution = + testExecutionRepository + .findFirstByProcessInstanceId(processInstanceId) + .orElse(null); + if (testExecution == null) { + logger.error( + String.format( + "Process instance with id %s completed, however, a corresponding test execution was not found in the database.", + processInstanceId)); + } else { + testExecution.setTestResult(ExecutionConstants.TestResult.TERMINATED); + TestExecutionUtility.saveTestResult( + mongoOperation, testExecution, testExecution.getTestResult()); + + // Saves the testExecution to the parent test execution if this belongs to a "sub" + // test + // instance call. + // updated terminated + saveToParentTestExecution(testExecution); + } + } + }; + + // Start the daemon that waits the max time for a running test instance. + long maxExecutionTimeInMillis = request.getMaxExecutionTimeInMillis(); + if (maxExecutionTimeInMillis > 0) { + new Timer(true).schedule(abortTestInstanceTask, maxExecutionTimeInMillis); + } + + return initialTestExecution; + } catch (WorkflowProcessorException e) { + throw e; + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + private void saveToParentTestExecution(TestExecution testExecution) { + if (parentTestExecution == null) { + return; + } + + synchronized (parentTestExecution) { + // Add the testExecution to the parentTestExecution + parentTestExecution.getTestInstanceResults().add(testExecution); + Query query = new Query(); + query.addCriteria(Criteria.where("_id").is(parentTestExecution.get_id())); + // Also add businessKey as a criteria because the object won't be found if the business key + // was somehow modified in the workflow. + query.addCriteria(Criteria.where("businessKey").is(parentTestExecution.getBusinessKey())); + Update update = new Update(); + update.set("testInstanceResults", parentTestExecution.getTestInstanceResults()); + UpdateResult result = mongoOperation.updateFirst(query, update, TestExecution.class); + // Check the status of the findAndUpdate database, and appropriately handle the errors. + if (result.getMatchedCount() == 0) { + throw new TestExecutionException( + String.format( + "Unable to log the test result because a testExecution associated with _id, %s and businessKey %s, was not found.", + parentTestExecution.get_id(), parentTestExecution.getBusinessKey())); + } else if (result.getModifiedCount() == 0) { + throw new TestExecutionException("Unable to persist the testExecution to the database."); + } + } + } + + private boolean isProcessInstanceEnded(String processInstanceId) { + try { + RuntimeService runtimeService = BpmPlatform.getProcessEngineService().getProcessEngine(OtfCamundaConfiguration.processEngineName).getRuntimeService(); + ProcessInstance processInstance = + runtimeService + .createProcessInstanceQuery() + .processInstanceId(processInstanceId) + .singleResult(); + return processInstance == null || processInstance.isEnded(); + } catch (Exception e) { + logger.error("Exception :", e); + return true; + } + } + + private boolean cancelProcessInstance(String processInstanceId) { + try { + RuntimeService runtimeService = BpmPlatform.getProcessEngineService().getProcessEngine(OtfCamundaConfiguration.processEngineName).getRuntimeService(); + runtimeService.deleteProcessInstance( + processInstanceId, "Triggered by user defined max execution time timeout."); + ProcessInstance processInstance = + runtimeService + .createProcessInstanceQuery() + .processInstanceId(processInstanceId) + .singleResult(); + return processInstance == null || processInstance.isEnded(); + } catch (Exception e) { + logger.error("Exception :", e); + return true; + } + } +} diff --git a/otf-camunda/src/main/java/org/oran/otf/camunda/delegate/otf/common/runnable/SynchronousTestInstanceCallable.java b/otf-camunda/src/main/java/org/oran/otf/camunda/delegate/otf/common/runnable/SynchronousTestInstanceCallable.java new file mode 100644 index 0000000..cffdc1e --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/camunda/delegate/otf/common/runnable/SynchronousTestInstanceCallable.java @@ -0,0 +1,227 @@ +/* Copyright (c) 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.oran.otf.camunda.delegate.otf.common.runnable; + +import org.oran.otf.camunda.configuration.OtfCamundaConfiguration; +import org.oran.otf.camunda.exception.TestExecutionException; +import org.oran.otf.camunda.exception.WorkflowProcessorException; +import org.oran.otf.camunda.service.ProcessEngineAwareService; +import org.oran.otf.camunda.workflow.WorkflowProcessor; +import org.oran.otf.camunda.workflow.WorkflowRequest; +import org.oran.otf.common.model.TestExecution; +import org.oran.otf.common.repository.TestExecutionRepository; +import org.oran.otf.common.utility.database.TestExecutionUtility; +import com.mongodb.client.result.UpdateResult; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Timer; +import java.util.TimerTask; +import java.util.concurrent.Callable; +import org.camunda.bpm.BpmPlatform; +import org.camunda.bpm.engine.RuntimeService; +import org.camunda.bpm.engine.runtime.ProcessInstance; +import org.oran.otf.camunda.model.ExecutionConstants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.query.Criteria; +import org.springframework.data.mongodb.core.query.Query; +import org.springframework.data.mongodb.core.query.Update; + +public class SynchronousTestInstanceCallable extends ProcessEngineAwareService + implements Callable { + + private static final Logger logger = + LoggerFactory.getLogger(SynchronousTestInstanceCallable.class); + private final TestExecution parentTestExecution; + private final TestExecutionRepository testExecutionRepository; + private final WorkflowProcessor processor; + private final MongoTemplate mongoOperation; + + private final WorkflowRequest request; + private String processInstanceId; + + public SynchronousTestInstanceCallable( + WorkflowRequest request, + TestExecution parentTestExecution, + TestExecutionRepository testExecutionRepository, + WorkflowProcessor processor, + MongoTemplate mongoOperation) { + this.request = request; + this.parentTestExecution = parentTestExecution; + + this.processInstanceId = ""; + + this.testExecutionRepository = testExecutionRepository; + this.processor = processor; + this.mongoOperation = mongoOperation; + } + + public SynchronousTestInstanceCallable( + WorkflowRequest request, + TestExecutionRepository testExecutionRepository, + WorkflowProcessor processor, + MongoTemplate mongoOperation) { + this.request = request; + this.parentTestExecution = null; + + this.processInstanceId = ""; + + this.testExecutionRepository = testExecutionRepository; + this.processor = processor; + this.mongoOperation = mongoOperation; + } + + @Override + public TestExecution call() throws WorkflowProcessorException { + try { + TestExecution initialTestExecution = processor.processWorkflowRequest(request); + this.processInstanceId = initialTestExecution.getProcessInstanceId(); + final Map abortionStatus = Collections.synchronizedMap(new HashMap<>()); + abortionStatus.put("isAborted", false); + + // Create a timer task that will call the cancellation after the specified time. + TimerTask abortTestInstanceTask = + new TimerTask() { + @Override + public void run() { + cancelProcessInstance(processInstanceId); + abortionStatus.put("isAborted", true); + } + }; + + // Start the daemon that waits the max time for a running test instance. + long maxExecutionTimeInMillis = request.getMaxExecutionTimeInMillis(); + if (maxExecutionTimeInMillis > 0) { + new Timer(true).schedule(abortTestInstanceTask, maxExecutionTimeInMillis); + } + + while (!isProcessInstanceEnded(processInstanceId)) { + Thread.sleep(1000); + } + + // Find the result after the process instance after it has finished. + TestExecution testExecution = + testExecutionRepository.findFirstByProcessInstanceId(processInstanceId).orElse(null); + if (testExecution == null) { + logger.error( + String.format( + "Process instance with id %s completed, however, a corresponding test execution was not found in the database.", + processInstanceId)); + } else { + // If the test result was not set in the workflow, set it to completed now that we know the + // process instance has finished executing. + String testResult = testExecution.getTestResult(); + if (testResult.equalsIgnoreCase("UNKNOWN") || testResult.equalsIgnoreCase("STARTED")) { + if (abortionStatus.get("isAborted")) { + testExecution.setTestResult(ExecutionConstants.TestResult.TERMINATED); + } else { + testExecution.setTestResult(ExecutionConstants.TestResult.COMPLETED); + } + + //TODO: RG remove prints + System.out.println(testExecution.getTestHeadResults()); + System.out.println(request); + TestExecutionUtility.saveTestResult( + mongoOperation, testExecution, testExecution.getTestResult()); + } + + // Saves the testExecution to the parent test execution if this belongs to a "sub" test + // instance call. + saveToParentTestExecution(testExecution); + } + + return testExecution; + } catch (WorkflowProcessorException e) { + throw e; + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + private void saveToParentTestExecution(TestExecution testExecution) { + if (parentTestExecution == null) { + return; + } + + synchronized (parentTestExecution) { + // Add the testExecution to the parentTestExecution + parentTestExecution.getTestInstanceResults().add(testExecution); + Query query = new Query(); + query.addCriteria(Criteria.where("_id").is(parentTestExecution.get_id())); + // Also add businessKey as a criteria because the object won't be found if the business key + // was somehow modified in the workflow. + query.addCriteria(Criteria.where("businessKey").is(parentTestExecution.getBusinessKey())); + Update update = new Update(); + update.set("testInstanceResults", parentTestExecution.getTestInstanceResults()); + UpdateResult result = mongoOperation.updateFirst(query, update, TestExecution.class); + // Check the status of the findAndUpdate database, and appropriately handle the errors. + if (result.getMatchedCount() == 0) { + throw new TestExecutionException( + String.format( + "Unable to log the test result because a testExecution associated with _id, %s and businessKey %s, was not found.", + parentTestExecution.get_id(), parentTestExecution.getBusinessKey())); + } else if (result.getModifiedCount() == 0) { + throw new TestExecutionException("Unable to persist the testExecution to the database."); + } + } + logger.info( + String.format( + "\t[Child-%s] finished saving result to parentTestExecution with result %s.", + processInstanceId, testExecution.getTestResult())); + } + + private boolean isProcessInstanceEnded(String processInstanceId) { + try { + RuntimeService runtimeService = + BpmPlatform.getProcessEngineService() + .getProcessEngine(OtfCamundaConfiguration.processEngineName) + .getRuntimeService(); + ProcessInstance processInstance = + runtimeService + .createProcessInstanceQuery() + .processInstanceId(processInstanceId) + .singleResult(); + return processInstance == null || processInstance.isEnded(); + } catch (Exception e) { + logger.error("Exception :", e); + return true; + } + } + + private boolean cancelProcessInstance(String processInstanceId) { + try { + RuntimeService runtimeService = + BpmPlatform.getProcessEngineService() + .getProcessEngine(OtfCamundaConfiguration.processEngineName) + .getRuntimeService(); + runtimeService.deleteProcessInstance( + processInstanceId, "Triggered by user defined max execution time timeout."); + ProcessInstance processInstance = + runtimeService + .createProcessInstanceQuery() + .processInstanceId(processInstanceId) + .singleResult(); + return processInstance == null || processInstance.isEnded(); + } catch (Exception e) { + logger.error("Exception :", e); + return true; + } + } +} diff --git a/otf-camunda/src/main/java/org/oran/otf/camunda/delegate/otf/common/runnable/TestHeadCallable.java b/otf-camunda/src/main/java/org/oran/otf/camunda/delegate/otf/common/runnable/TestHeadCallable.java new file mode 100644 index 0000000..d0ee267 --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/camunda/delegate/otf/common/runnable/TestHeadCallable.java @@ -0,0 +1,267 @@ +/* Copyright (c) 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.oran.otf.camunda.delegate.otf.common.runnable; + + +import org.oran.otf.camunda.exception.TestExecutionException; +import org.oran.otf.common.model.TestExecution; +import org.oran.otf.common.model.TestHead; +import org.oran.otf.common.model.local.TestHeadRequest; +import org.oran.otf.common.model.local.TestHeadResult; +import org.oran.otf.common.utility.Utility; +import org.oran.otf.common.utility.gson.Convert; +import org.oran.otf.common.utility.http.RequestUtility; +import com.google.common.base.Strings; +import com.google.gson.JsonParser; +import com.mongodb.client.result.UpdateResult; +import java.io.IOException; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.Callable; + +import org.apache.http.HttpHeaders; +import org.apache.http.HttpResponse; +import org.apache.http.util.EntityUtils; +import org.oran.otf.common.utility.http.HeadersUtility; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.query.Criteria; +import org.springframework.data.mongodb.core.query.Query; +import org.springframework.data.mongodb.core.query.Update; + +// TODO : Create a constructor that does not take a testexecution object as a parameter. This means +// that the result should only be returned, and the call to saveResult should be avoided. +public class TestHeadCallable implements Callable { + + private static Logger logger = LoggerFactory.getLogger(TestHeadCallable.class); + private final String logPrefix = Utility.getLoggerPrefix(); + private final TestExecution testExecution; + + private final int timeoutInMillis; + private final String httpMethod; + private final Map headers; + private final Map body; + private final TestHead testHead; + private final String activityId; + + private final MongoTemplate mongoOperation; + + private String url; + private TestHeadResult result; + private Date startTime; + private Date endTime; + + public TestHeadCallable( + int timeoutInMillis, + String httpMethod, + Map headers, + Map vthInput, + TestHead testHead, + String activityId, + TestExecution testExecution, + MongoTemplate mongoOperation) { + this.timeoutInMillis = timeoutInMillis; + this.httpMethod = httpMethod; + this.headers = headers; + this.body = vthInput; + this.testHead = testHead; + this.activityId = activityId; + this.testExecution = testExecution; + + this.mongoOperation = mongoOperation; + + // Generate the url after the test head is set. + this.url = generateUrl(); + } + + @Override + public TestHeadResult call() throws Exception { + // If simulation mode is set, then send back expected result after expected delay + if (testExecution.getHistoricTestInstance().isSimulationMode()) { + logger.info(logPrefix + "Start call to test head in simulation mode."); + startTime = new Date(System.currentTimeMillis()); + Map response = + simulateVTH( + this.activityId, testExecution.getHistoricTestInstance().getSimulationVthInput()); + endTime = new Date(System.currentTimeMillis()); + logger.info(logPrefix + "Finished call to test head in simulation mode."); + + //TODO: This will need to change if enhancement is made to allow status codes + TestHeadResult result = generateResult(response); + testExecution.getTestHeadResults().add(result); + saveResult(testExecution); + return result; + } + logger.info(logPrefix + "Start call to test head."); + HttpResponse response = null; + TestHeadResult result = null; + // Set the start time right before the request. + startTime = new Date(System.currentTimeMillis()); + + // add api key to headers if required + setApiKeyIfEnabled(); + + //TODO RG Added to slow Execution + //Thread.sleep(60000); + + try { + switch (httpMethod.toLowerCase()) { + case "post": + response = + timeoutInMillis > 0 + ? RequestUtility.postSync( + url, Convert.mapToJson(body), headers, timeoutInMillis, false) + : RequestUtility.postSync(url, Convert.mapToJson(body), headers, false); + break; + case "get": + response = + timeoutInMillis > 0 + ? RequestUtility.getSync(url, headers, timeoutInMillis, false) + : RequestUtility.getSync(url, headers, false); + break; + default: + throw new RuntimeException(); + } + // Set the end time when the request returns. + endTime = new Date(System.currentTimeMillis()); + logger.info(logPrefix + "Finished call to test head."); + + // Generate and return the result. + result = generateResult(response); + } catch (Exception e) { + Map error = new HashMap<>(); + error.put("error", e.getMessage()); + result = generateFailedResult(error); + + logger.info(logPrefix + "There was an error calling the test head."); + } + + testExecution.getTestHeadResults().add(result); + saveResult(testExecution); + return result; + } + + private void setApiKeyIfEnabled(){ + if(this.testHead.getAuthorizationEnabled() != null && this.testHead.getAuthorizationEnabled().booleanValue()){ + this.headers.put(HttpHeaders.AUTHORIZATION, testHead.getAuthorizationType() + " " + testHead.getAuthorizationCredential()); + } + } + + private String generateUrl() { + String resource = testHead.getResourcePath(); + // Prepend a forward-slash if the resource path exists, and does NOT already start with one. The + // order of this condition is relevant for null-checks. + if (!Strings.isNullOrEmpty(resource) && !resource.startsWith("/")) { + resource = "/" + resource; + } + return testHead.getHostname() + ":" + testHead.getPort() + resource; + } + + private TestHeadResult generateFailedResult(Map error) { + int statusCodeError = -1; + TestHeadRequest requestContent = new TestHeadRequest(HeadersUtility.maskAuth(headers), body); + + return new TestHeadResult( + testHead.get_id(), testHead.getTestHeadName(), testHead.getGroupId(), activityId, statusCodeError, requestContent, error, startTime, endTime); + } + + private TestHeadResult generateResult(HttpResponse response) throws IOException { + String sRes = EntityUtils.toString(response.getEntity()); + JsonParser parser = new JsonParser(); + Map res; + try { + res = Convert.jsonToMap(sRes); + } catch (Exception e) { + res = new HashMap<>(); + res.put("response", sRes); + } + + TestHeadRequest requestContent = new TestHeadRequest(HeadersUtility.maskAuth(headers), body); + + return new TestHeadResult( + testHead.get_id(), testHead.getTestHeadName(), testHead.getGroupId(), activityId, response.getStatusLine().getStatusCode(), requestContent, res, startTime, endTime); + } + + private TestHeadResult generateResult(Map res) { + + //TODO: This will need to change if enhancement is made to allow status codes + TestHeadRequest requestContent = new TestHeadRequest(HeadersUtility.maskAuth(headers), body); + + return new TestHeadResult( + testHead.get_id(), testHead.getTestHeadName(), testHead.getGroupId(), activityId, 200, requestContent, res, startTime, endTime); + } + + private void saveResult(TestExecution testExecution) { + Query query = new Query(); + query.addCriteria(Criteria.where("_id").is(testExecution.get_id())); + // Also add businessKey as a criteria because the object won't be found if the business key + // was somehow modified in the workflow. + query.addCriteria(Criteria.where("businessKey").is(testExecution.getBusinessKey())); + Update update = new Update(); + update.set("testHeadResults", testExecution.getTestHeadResults()); + UpdateResult result = mongoOperation.updateFirst(query, update, TestExecution.class); + // Check the status of the findAndUpdate database, and appropriately handle the errors. + if (result.getMatchedCount() == 0) { + throw new TestExecutionException( + String.format( + "Unable to log the test result because a testExecution associated with _id, %s and businessKey %s, was not found.", + testExecution.get_id(), testExecution.getBusinessKey())); + } else if (result.getModifiedCount() == 0) { + throw new TestExecutionException("Unable to persist the testExecution to the database."); + } + } + + private Map simulateVTH(String activityId, Map simulationVth) { + int delay = 0; + Map response = new HashMap(); + if (simulationVth.containsKey(activityId)) { + Object obj = simulationVth.get(activityId); + if (obj instanceof Map) { + simulationVth = (Map) obj; + } + } else { + return null; + } + + if (simulationVth.containsKey("delay")) { + Object obj = simulationVth.get("delay"); + if (obj instanceof Integer) { + delay = (int) obj; + } + } + + if (simulationVth.containsKey("response")) { + Object obj = simulationVth.get("response"); + if (obj instanceof Map) { + response = (Map) obj; + } + } + logger.info(logPrefix + "Starting simulated call to test head."); + + try { + Thread.sleep(delay); + } catch (InterruptedException e) { + e.printStackTrace(); + logger.info(logPrefix + "Error simulating call to test head."); + return null; + } + logger.info(logPrefix + "Finished simulating call to test head."); + return response; + } +} diff --git a/otf-camunda/src/main/java/org/oran/otf/camunda/exception/TestExecutionException.java b/otf-camunda/src/main/java/org/oran/otf/camunda/exception/TestExecutionException.java new file mode 100644 index 0000000..b5f673d --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/camunda/exception/TestExecutionException.java @@ -0,0 +1,32 @@ +/* Copyright (c) 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.oran.otf.camunda.exception; + +public class TestExecutionException extends RuntimeException { + + public TestExecutionException(String message) { + super(message); + } + + public TestExecutionException(String message, Throwable cause) { + super(message, cause); + } + + public TestExecutionException(Throwable cause) { + super(cause); + } +} diff --git a/otf-camunda/src/main/java/org/oran/otf/camunda/exception/WorkflowException.java b/otf-camunda/src/main/java/org/oran/otf/camunda/exception/WorkflowException.java new file mode 100644 index 0000000..605c6b0 --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/camunda/exception/WorkflowException.java @@ -0,0 +1,95 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP - SO + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.oran.otf.camunda.exception; + +import java.io.Serializable; + +/** + * An object that represents a workflow exception. + */ +public class WorkflowException implements Serializable { + + private static final long serialVersionUID = 1L; + + private final String processKey; + private final int errorCode; + private final String errorMessage; + private final String workStep; + + /** + * Constructor + * + * @param processKey the process key for the process that generated the exception + * @param errorCode the numeric error code (normally 1xxx or greater) + * @param errorMessage a short error message + */ + public WorkflowException(String processKey, int errorCode, String errorMessage) { + this.processKey = processKey; + this.errorCode = errorCode; + this.errorMessage = errorMessage; + workStep = "*"; + } + + public WorkflowException(String processKey, int errorCode, String errorMessage, String workStep) { + this.processKey = processKey; + this.errorCode = errorCode; + this.errorMessage = errorMessage; + this.workStep = workStep; + } + + /** + * Returns the process key. + */ + public String getProcessKey() { + return processKey; + } + + /** + * Returns the error code. + */ + public int getErrorCode() { + return errorCode; + } + + /** + * Returns the error message. + */ + public String getErrorMessage() { + return errorMessage; + } + + /** + * Returns the error message. + */ + public String getWorkStep() { + return workStep; + } + + /** + * Returns a string representation of this object. + */ + @Override + public String toString() { + return getClass().getSimpleName() + "[processKey=" + getProcessKey() + ",errorCode=" + + getErrorCode() + + ",errorMessage=" + getErrorMessage() + ",workStep=" + getWorkStep() + "]"; + } +} diff --git a/otf-camunda/src/main/java/org/oran/otf/camunda/exception/WorkflowProcessorException.java b/otf-camunda/src/main/java/org/oran/otf/camunda/exception/WorkflowProcessorException.java new file mode 100644 index 0000000..8997656 --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/camunda/exception/WorkflowProcessorException.java @@ -0,0 +1,32 @@ +/* Copyright (c) 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.oran.otf.camunda.exception; + +import org.oran.otf.camunda.model.WorkflowResponse; + +public class WorkflowProcessorException extends RuntimeException { + + private WorkflowResponse response; + + public WorkflowProcessorException(WorkflowResponse response) { + this.response = response; + } + + public WorkflowResponse getWorkflowResponse() { + return response; + } +} diff --git a/otf-camunda/src/main/java/org/oran/otf/camunda/listener/EndEventListener.java b/otf-camunda/src/main/java/org/oran/otf/camunda/listener/EndEventListener.java new file mode 100644 index 0000000..f886000 --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/camunda/listener/EndEventListener.java @@ -0,0 +1,60 @@ +/* Copyright (c) 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.oran.otf.camunda.listener; + +import org.oran.otf.event.TestInstanceCompletionEvent; +import com.google.gson.JsonObject; +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.camunda.bpm.engine.delegate.ExecutionListener; +import org.camunda.bpm.extension.reactor.bus.CamundaSelector; +import org.camunda.bpm.extension.reactor.spring.listener.ReactorExecutionListener; +import org.camunda.bpm.model.bpmn.instance.EndEvent; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.stereotype.Component; + +@Component +@CamundaSelector(event = ExecutionListener.EVENTNAME_END) +public class EndEventListener extends ReactorExecutionListener { + + private static Logger LOGGER = LoggerFactory.getLogger(EndEventListener.class); + + @Autowired + private ApplicationEventPublisher publisher; + + @Override + public void notify(DelegateExecution execution) { + JsonObject jmsg = new JsonObject(); + jmsg.addProperty("executionId", execution.getProcessInstanceId()); + jmsg.addProperty("origin", "otf-camunda"); + if (execution.getBpmnModelElementInstance() instanceof EndEvent) { + LOGGER.info(execution.getProcessInstanceId() + " is finished."); + jmsg.addProperty("status", "completed"); + publisher.publishEvent(new TestInstanceCompletionEvent(this, jmsg, execution)); + } + } + + private void onEndEvent(DelegateExecution execution) { + + } + + private void onVthEnd(DelegateExecution execution) { + // Useful for reporting back the result of a VTH + } +} diff --git a/otf-camunda/src/main/java/org/oran/otf/camunda/listener/StartEventListener.java b/otf-camunda/src/main/java/org/oran/otf/camunda/listener/StartEventListener.java new file mode 100644 index 0000000..9fa6d14 --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/camunda/listener/StartEventListener.java @@ -0,0 +1,97 @@ +/* Copyright (c) 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.oran.otf.camunda.listener; + +import org.oran.otf.camunda.exception.TestExecutionException; +import org.oran.otf.camunda.model.ExecutionConstants; +import org.oran.otf.camunda.workflow.utility.WorkflowUtility; +import org.oran.otf.common.model.TestExecution; +import org.oran.otf.common.utility.Utility; +import com.google.gson.JsonObject; +import com.mongodb.client.result.UpdateResult; +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.camunda.bpm.engine.delegate.ExecutionListener; +import org.camunda.bpm.extension.reactor.bus.CamundaSelector; +import org.camunda.bpm.extension.reactor.spring.listener.ReactorExecutionListener; +import org.camunda.bpm.model.bpmn.instance.StartEvent; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.query.Criteria; +import org.springframework.data.mongodb.core.query.Query; +import org.springframework.data.mongodb.core.query.Update; +import org.springframework.stereotype.Component; + +@Component +@CamundaSelector(event = ExecutionListener.EVENTNAME_END) +public class StartEventListener extends ReactorExecutionListener { + + @Autowired + WorkflowUtility utility; + + @Autowired + MongoTemplate mongoOperation; + + private static Logger LOGGER = LoggerFactory.getLogger(StartEventListener.class); + + @Override + public void notify(DelegateExecution execution) { + if (execution.getBpmnModelElementInstance() instanceof StartEvent) { + LOGGER.info(execution.getProcessInstanceId() + " has started."); + //setTestResult(execution, ExecutionConstants.TestResult.STARTED); + } + } + + private void onStartEvent(DelegateExecution execution) { + } + + private void onVthStart(DelegateExecution execution) { + // Useful for reporting back the exact parameters being sent to the VTH as they can be modified + // in the workflow + } + + private void setTestResult(DelegateExecution execution, String result){ + // Get the current test execution object. + final String logPrefix = Utility.getLoggerPrefix(); + + TestExecution testExecution = + utility.getExecutionVariable( + execution.getVariables(), ExecutionConstants.ExecutionVariable.TEST_EXECUTION, TestExecution.class); + // Perform a null-check to ensure it is available. It's critical to throw an exception if it + // is not available since the object is essential for results. + if (testExecution == null) { + LOGGER.error(logPrefix + "Test execution is null."); + throw new TestExecutionException("The test execution was not found."); + } + execution.setVariable(ExecutionConstants.ExecutionVariable.TEST_RESULT, result); + + testExecution.setTestResult(result); + testExecution.setProcessInstanceId(execution.getProcessInstanceId()); + + + Query query = new Query(); + query.addCriteria(Criteria.where("businessKey").is(execution.getProcessBusinessKey())); + Update update = new Update(); + update.set("testResult", testExecution.getTestResult()); + update.set("processInstanceId", execution.getProcessInstanceId()); + UpdateResult updateResult = mongoOperation.updateFirst(query, update, TestExecution.class); + + } + + +} diff --git a/otf-camunda/src/main/java/org/oran/otf/camunda/listener/TaskEndEventListener.java b/otf-camunda/src/main/java/org/oran/otf/camunda/listener/TaskEndEventListener.java new file mode 100644 index 0000000..37ca685 --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/camunda/listener/TaskEndEventListener.java @@ -0,0 +1,83 @@ +/* Copyright (c) 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.oran.otf.camunda.listener; + +import org.oran.otf.camunda.exception.TestExecutionException; +import org.oran.otf.camunda.workflow.utility.WorkflowUtility; +import org.oran.otf.common.utility.Utility; +import org.camunda.bpm.engine.RuntimeService; +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.camunda.bpm.engine.delegate.ExecutionListener; +import org.camunda.bpm.engine.impl.context.Context; +import org.camunda.bpm.engine.impl.interceptor.Command; +import org.camunda.bpm.engine.impl.interceptor.CommandContext; +import org.camunda.bpm.engine.runtime.ProcessInstance; +import org.camunda.bpm.extension.reactor.bus.CamundaSelector; +import org.camunda.bpm.extension.reactor.spring.listener.ReactorExecutionListener; +import org.camunda.bpm.model.bpmn.instance.Task; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.stereotype.Component; + +@Component +@CamundaSelector(event = ExecutionListener.EVENTNAME_END) +public class TaskEndEventListener extends ReactorExecutionListener { + + @Autowired + WorkflowUtility utility; + + @Autowired + MongoTemplate mongoOperation; + + @Autowired + RuntimeService runtimeService; + + private static Logger LOGGER = LoggerFactory.getLogger(TaskEndEventListener.class); + + @Override + public void notify(DelegateExecution execution) { + if(execution.getBpmnModelElementInstance() instanceof Task){ + String processInstanceId = execution.getProcessInstanceId(); + ProcessInstance processInstance; + try { + processInstance = checkProcessInstanceStatus(processInstanceId); + }catch(Exception e){ + throw new TestExecutionException("Error trying to obtain process instance status, error: " + e) ; + } + // if process instance not found then terminate the current process + if(processInstance == null || processInstance.isEnded() || processInstance.isSuspended()){ + String logPrefix = Utility.getLoggerPrefix(); + + LOGGER.info(logPrefix + "Process Instance not found. Terminating current job (thread)."); + Thread.currentThread().interrupt(); + throw new TestExecutionException("Terminated Process Instance: " + processInstanceId + ". Process Instance no longer exists, thread has been forcefully interrupted"); + } + } + } + + private ProcessInstance checkProcessInstanceStatus(String processInstanceId){ + return Context.getProcessEngineConfiguration().getCommandExecutorTxRequiresNew().execute(new Command() { + @Override + public ProcessInstance execute(CommandContext commandContext){ + return runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult(); + } + }); + } + +} diff --git a/otf-camunda/src/main/java/org/oran/otf/camunda/model/ExecutionConstants.java b/otf-camunda/src/main/java/org/oran/otf/camunda/model/ExecutionConstants.java new file mode 100644 index 0000000..d266457 --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/camunda/model/ExecutionConstants.java @@ -0,0 +1,56 @@ +/* Copyright (c) 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.oran.otf.camunda.model; + +public class ExecutionConstants { + public class TestResult { + public static final String STARTED = "STARTED"; + public static final String COMPLETED = "COMPLETED"; + //remore redundent test results +// public static final String FAILURE = "FAILURE"; + public static final String FAILED = "FAILED"; + public static final String STOPPED = "STOPPED"; + public static final String SUCCESS = "SUCCESS"; + public static final String TERMINATED = "TERMINATED"; + public static final String UNAUTHORIZED = "UNAUTHORIZED"; + public static final String DOES_NOT_EXIST = "DOES_NOT_EXIST"; + public static final String UNKNOWN = "UNKNOWN"; + // error can be assignned in a workflow. if user uses workflow error reassign to error + public static final String ERROR = "ERROR"; + // workflow error is only used for exceptions and bugs + public static final String WORKFLOW_ERROR = "WORKFLOW_ERROR"; + public static final String OTHER = "OTHER"; + } + + public class ExecutionVariable { + public static final String TEST_EXECUTION = "otf-execution-testExecution"; + public static final String TEST_EXECUTION_ENCRYPTED = "otf-execution-encrypted"; + public static final String PFLO_INPUT = "pfloInput"; + public static final String TEST_DATA = "testData"; + public static final String TEST_DETAILS = "testDetails"; + public static final String TEST_RESULT = "testResult"; + public static final String VTH_INPUT = "vthInput"; + public static final String TEST_RESULT_MESSAGE = "testResultMessage"; + } + + public static String [] getAllTestResultStr(){ + return new String[] {TestResult.STARTED,TestResult.COMPLETED,TestResult.FAILED, + TestResult.STOPPED,TestResult.SUCCESS,TestResult.TERMINATED, + TestResult.UNAUTHORIZED,TestResult.DOES_NOT_EXIST,TestResult.UNKNOWN, + TestResult.ERROR,TestResult.OTHER}; + } +} diff --git a/otf-camunda/src/main/java/org/oran/otf/camunda/model/WorkflowResponse.java b/otf-camunda/src/main/java/org/oran/otf/camunda/model/WorkflowResponse.java new file mode 100644 index 0000000..ea9fc28 --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/camunda/model/WorkflowResponse.java @@ -0,0 +1,88 @@ +/* Copyright (c) 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.oran.otf.camunda.model; + +import org.oran.otf.common.model.TestExecution; +import org.oran.otf.common.utility.gson.Convert; + +import java.util.Map; + +/** + * @version 1.0 Synchronous workflow response bean + */ +public class WorkflowResponse { + + private String response; + private String message; + private String processInstanceId; + private Map variables; + private TestExecution testExecution; + private int messageCode; + + public String getResponse() { + return response; + } + + public void setResponse(String response) { + this.response = response; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public String getProcessInstanceId() { + return processInstanceId; + } + + public void setProcessInstanceId(String pID) { + this.processInstanceId = pID; + } + + public Map getVariables() { + return variables; + } + + public void setVariables(Map variables) { + this.variables = variables; + } + + public int getMessageCode() { + return messageCode; + } + + public void setMessageCode(int messageCode) { + this.messageCode = messageCode; + } + + public TestExecution getTestExecution() { + return testExecution; + } + + public void setTestExecution(TestExecution testExecution) { + this.testExecution = testExecution; + } + + @Override + public String toString() { + return Convert.objectToJson(this); + } +} diff --git a/otf-camunda/src/main/java/org/oran/otf/camunda/plugin/OtfIncidentHandlerPlugin.java b/otf-camunda/src/main/java/org/oran/otf/camunda/plugin/OtfIncidentHandlerPlugin.java new file mode 100644 index 0000000..6aceed4 --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/camunda/plugin/OtfIncidentHandlerPlugin.java @@ -0,0 +1,54 @@ +/* Copyright (c) 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.oran.otf.camunda.plugin; + +import org.oran.otf.camunda.workflow.handler.ExternalTaskIncidentHandler; +import org.oran.otf.camunda.workflow.handler.FailedJobIncidentHandler; +import java.util.Arrays; +import org.camunda.bpm.engine.ProcessEngine; +import org.camunda.bpm.engine.impl.cfg.ProcessEngineConfigurationImpl; +import org.camunda.bpm.engine.impl.cfg.ProcessEnginePlugin; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class OtfIncidentHandlerPlugin implements ProcessEnginePlugin { + + private static final Logger logger = LoggerFactory.getLogger(OtfIncidentHandlerPlugin.class); + + @Autowired + private FailedJobIncidentHandler failedJobIncidentHandler; + @Autowired + private ExternalTaskIncidentHandler externalTaskIncidentHandler; + + @Override + public void preInit(ProcessEngineConfigurationImpl processEngineConfiguration) { + logger.info("Adding Open Test Framework custom incident handlers."); + processEngineConfiguration.setCustomIncidentHandlers( + Arrays.asList(failedJobIncidentHandler, externalTaskIncidentHandler)); + } + + @Override + public void postInit(ProcessEngineConfigurationImpl processEngineConfiguration) { + } + + @Override + public void postProcessEngineBuild(ProcessEngine processEngine) { + } +} diff --git a/otf-camunda/src/main/java/org/oran/otf/camunda/service/CamundaShutdown.java b/otf-camunda/src/main/java/org/oran/otf/camunda/service/CamundaShutdown.java new file mode 100644 index 0000000..c414528 --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/camunda/service/CamundaShutdown.java @@ -0,0 +1,143 @@ +/* Copyright (c) 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.oran.otf.camunda.service; + +import static org.springframework.data.mongodb.core.query.Criteria.where; + +import org.oran.otf.camunda.configuration.OtfCamundaConfiguration; +import org.oran.otf.camunda.model.ExecutionConstants.TestResult; +import org.oran.otf.camunda.workflow.utility.WorkflowTask; +import org.oran.otf.common.model.TestExecution; + +import org.oran.otf.service.impl.DeveloperServiceImpl; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +import org.camunda.bpm.BpmPlatform; +import org.camunda.bpm.engine.OptimisticLockingException; +import org.camunda.bpm.engine.RuntimeService; +import org.camunda.bpm.engine.runtime.ProcessInstance; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.mongodb.core.BulkOperations; +import org.springframework.data.mongodb.core.BulkOperations.BulkMode; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.query.Query; +import org.springframework.data.mongodb.core.query.Update; +import org.springframework.stereotype.Component; + +@Component +public class CamundaShutdown { + + private Logger logger = LoggerFactory.getLogger(DeveloperServiceImpl.class); + + @Autowired + private MongoTemplate mongoTemplate; + + public CamundaShutdown(){} + + //TODO: delete unused code + public Set gracefulShutdown(){ + Set processIds = new HashSet<>(); + + try { + if (!WorkflowTask.workflowTasksByExecutionId.isEmpty()) { + processIds = WorkflowTask.workflowTasksByExecutionId.keySet(); + if (processIds != null) { + suspendTasks(processIds); + //1. Update processes running as TERMINATED + BulkOperations updates = prepareBatchUpdate(processIds); + updates.execute(); + + //3.kill poolthreads + processIds = this.shutdownAllProcessThreads(processIds); + //this.shutdownAllProcessThreads(processIds); + + //2.look up process instances and delete the suspeded processes + processIds = queryProcessInstances(processIds); + + } + } + }catch (OptimisticLockingException e){ + //4. Update processes running as TERMINATED + BulkOperations threadsInterrupted = prepareBatchUpdate(processIds); + threadsInterrupted.execute(); + logger.info("Optimistic error was caught by graceful shutdown method"); + } + return processIds; + } + private void suspendTasks(Set processIds){ + RuntimeService runtimeService = BpmPlatform.getProcessEngineService().getProcessEngine( + OtfCamundaConfiguration.processEngineName).getRuntimeService(); + for(String id: processIds){ + runtimeService.suspendProcessInstanceById(id); + } + } + + private Set queryProcessInstances(Set processIds){ + RuntimeService runtimeService = BpmPlatform.getProcessEngineService().getProcessEngine( + OtfCamundaConfiguration.processEngineName).getRuntimeService(); + for(String id: processIds){ + ProcessInstance instance = runtimeService.createProcessInstanceQuery().processInstanceId(id).singleResult(); + if(instance == null || instance.isEnded()){ + processIds.remove(id); + } + } + List del = new ArrayList<>(processIds); + runtimeService.deleteProcessInstances(del, "Camunda Shutting down, proccess forcefully terminated", false, false , false); + return processIds; + + } + + private Set shutdownAllProcessThreads(Set processIds){ + Set terminatedProcesses = new HashSet<>(); + Iterator processes = processIds.iterator(); + //Iterator processes = WorkflowTask.workflowTasksByExecutionId.entrySet().iterator(); + while(processes.hasNext()){ + Object processHolder = processes.next(); + List tasks = WorkflowTask.workflowTasksByExecutionId.get(processHolder.toString()); + //List tasks = WorkflowTask.workflowTasksByExecutionId.get(processes.next()); + if(tasks != null){ + terminatedProcesses.add(processHolder.toString()); + for(WorkflowTask task: tasks){ + task.shutdown(true); + } + } + + else{ + //processIds.remove(processes.next()); + } + } + return terminatedProcesses; + } + private BulkOperations prepareBatchUpdate(Set processIds){ + //Set processInstanceIds = this.runningProcessInstanceIds(); + Iterator ids = processIds.iterator();//processInstanceIds.iterator(); + BulkOperations bulkOperations = mongoTemplate.bulkOps(BulkMode.ORDERED, TestExecution.class); + while(ids.hasNext()){ + ids.hasNext(); + //Get tasks by processInstanceId + Update update = new Update().set("testResult", TestResult.TERMINATED).set("testResultMessage", "Camunda application had to shutdown for maintenance, Test execution was TERMINATED"); + bulkOperations.updateOne(Query.query(where("processInstanceId").is(ids.next())), update); + } + return bulkOperations; + } +} diff --git a/otf-camunda/src/main/java/org/oran/otf/camunda/service/OtfExternalTaskService.java b/otf-camunda/src/main/java/org/oran/otf/camunda/service/OtfExternalTaskService.java new file mode 100644 index 0000000..c23d1cb --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/camunda/service/OtfExternalTaskService.java @@ -0,0 +1,195 @@ +/* Copyright (c) 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.oran.otf.camunda.service; + +import org.oran.otf.camunda.configuration.OtfCamundaConfiguration; +import org.oran.otf.camunda.delegate.otf.common.CallTestHeadDelegate; +import org.oran.otf.camunda.delegate.otf.common.RunTestInstanceDelegate; +import com.google.common.util.concurrent.ThreadFactoryBuilder; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.ThreadLocalRandom; +import org.camunda.bpm.BpmPlatform; +import org.camunda.bpm.engine.ExternalTaskService; +import org.camunda.bpm.engine.externaltask.LockedExternalTask; +import org.camunda.bpm.engine.variable.VariableMap; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.context.event.ApplicationReadyEvent; +import org.springframework.context.event.EventListener; +import org.springframework.stereotype.Component; + +@Component +public class OtfExternalTaskService { + + private static Logger logger = LoggerFactory.getLogger(OtfExternalTaskService.class); + public static boolean isEnabled; + private static long pollIntervalInMillis = 1000; + @Autowired CallTestHeadDelegate callTestHeadDelegate; + @Autowired RunTestInstanceDelegate runTestInstanceDelegate; + private ExternalTaskService externalTaskService; + + private List externalTasks; + + @Value("${otf.camunda.executors-active}") + private boolean executorsActive; + + @EventListener(ApplicationReadyEvent.class) + public void initialize() { + this.externalTaskService = + BpmPlatform.getProcessEngineService() + .getProcessEngine(OtfCamundaConfiguration.processEngineName) + .getExternalTaskService(); + + pollIntervalInMillis = ThreadLocalRandom.current().nextLong(500, 5000); + // this.externalTaskService = + // BpmPlatform.getProcessEngineService() + // .getProcessEngine(OtfCamundaConfiguration.processEngineName) + // .getExternalTaskService(); + + logger.info( + "Initializing external task service with poll interval at {}", pollIntervalInMillis); + externalTasks = new ArrayList<>(); + isEnabled = this.executorsActive; + logger.info("External Task Worker otf.camunda.executors-active set to : " + this.executorsActive); + Thread t = + new Thread( + () -> { + while (true) { + try { + if (isEnabled) { + acquire(); + } + + Thread.sleep(pollIntervalInMillis); + } catch (Exception e) { + logger.error(e.getMessage()); + } + } + }); + + t.start(); + } + + private void acquire() { + externalTasks.clear(); + List externalTasks = + externalTaskService + .fetchAndLock(10, "etw_" + OtfCamundaConfiguration.processEngineName) + .topic("vth", 43200000) + .enableCustomObjectDeserialization() + .topic("testInstance", 43200000) + .enableCustomObjectDeserialization() + .execute(); + externalTasks.forEach(this::handleExternalTask); + } + + private void handleExternalTask(LockedExternalTask task) { + logger.info("[" + task.getId() + "]: Handling external task for topic: " + task.getTopicName()); + String topicName = task.getTopicName(); + ExternalTaskCallable callable; + + // Set retries to 0 for the current task. + // externalTaskService.setRetries(task.getId(), 0); + + switch (topicName) { + case "vth": + callable = new ExternalTaskCallable(task, OtfExternalTask.VTH); + break; + case "testInstance": + callable = new ExternalTaskCallable(task, OtfExternalTask.TEST_INSTANCE); + break; + default: + String err = String.format("The topic name %s has no external task handler.", topicName); + logger.error(err); + externalTaskService.handleFailure(task.getId(), task.getWorkerId(), err, 0, 0); + return; + } + + try { + ThreadFactory namedThreadFactory = + new ThreadFactoryBuilder().setNameFormat("etw-" + task.getTopicName() + "-%d").build(); + namedThreadFactory.newThread(callable).start(); + } catch (Exception e) { + externalTaskService.handleFailure( + task.getId(), task.getWorkerId(), e.getMessage(), e.toString(), 0, 0); + } + } + + public enum OtfExternalTask { + VTH, + TEST_INSTANCE + } + + public class ExternalTaskCallable implements Runnable { + + private final LockedExternalTask task; + private final OtfExternalTask type; + + private final String activityId; + private final String processDefinitionId; + private final String processInstanceId; + private final String processBusinessKey; + private VariableMap variables; + + private ExternalTaskCallable(LockedExternalTask lockedExternalTask, OtfExternalTask type) { + this.task = lockedExternalTask; + this.type = type; + + this.activityId = task.getActivityId(); + this.processDefinitionId = task.getProcessDefinitionId(); + this.processInstanceId = task.getProcessInstanceId(); + this.processBusinessKey = task.getBusinessKey(); + this.variables = task.getVariables(); + } + + @Override + public void run() { + try { + if (type == OtfExternalTask.VTH) { + callTestHeadDelegate.callTestHead( + activityId, processDefinitionId, processInstanceId, processBusinessKey, variables); + } else if (type == OtfExternalTask.TEST_INSTANCE) { + runTestInstanceDelegate.runTestInstance(activityId, processInstanceId, variables); + } else { + logger.error( + String.format( + "Could not find the appropriate function for external task with id %s.", type)); + } + } catch (Exception e) { + String err = String.format("Encountered error %s", e.getMessage()); + externalTaskService.handleFailure( + task.getId(), task.getWorkerId(), e.getMessage(), err, 0, 0); + return; + } + + synchronized (externalTaskService) { + try { + externalTaskService.complete(task.getId(), task.getWorkerId(), variables); + } catch (Exception e) { + String err = String.format("Encountered error %s", e.getMessage()); + e.printStackTrace(); + externalTaskService.handleFailure( + task.getId(), task.getWorkerId(), e.getMessage(), err, 0, 0); + } + } + } + } +} diff --git a/otf-camunda/src/main/java/org/oran/otf/camunda/service/OtfWorkflowTaskCleanupService.java b/otf-camunda/src/main/java/org/oran/otf/camunda/service/OtfWorkflowTaskCleanupService.java new file mode 100644 index 0000000..ca9d7a8 --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/camunda/service/OtfWorkflowTaskCleanupService.java @@ -0,0 +1,75 @@ +/* Copyright (c) 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.oran.otf.camunda.service; + +import org.oran.otf.camunda.workflow.utility.WorkflowTask; +import java.util.List; +import java.util.Map.Entry; +import java.util.Set; +import org.camunda.bpm.engine.RuntimeService; +import org.camunda.bpm.engine.runtime.ProcessInstance; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.context.event.ApplicationReadyEvent; +import org.springframework.context.event.EventListener; +import org.springframework.stereotype.Component; + +@Component +public class OtfWorkflowTaskCleanupService { + @Autowired RuntimeService runtimeService; + public static boolean isEnabled = false; + + @EventListener(ApplicationReadyEvent.class) + public void init() { + Thread otfCleanupService = new Thread(new Worker()); + otfCleanupService.start(); + } + + public class Worker implements Runnable { + @Override + public void run() { + try { + while (true) { + if (isEnabled) { + synchronized (WorkflowTask.workflowTasksByExecutionId) { + Set>> set = + WorkflowTask.workflowTasksByExecutionId.entrySet(); + + for (Entry> entry : set) { + String processInstanceId = entry.getKey(); + List workflowTasks = entry.getValue(); + + ProcessInstance processInstance = + runtimeService + .createProcessInstanceQuery() + .processInstanceId(processInstanceId) + .singleResult(); + + if (processInstance == null) { + System.out.println("Cleaning up WorkflowTasks under processInstanceId, " + processInstanceId); + workflowTasks.forEach(WorkflowTask::shutdown); + } + } + } + } + Thread.sleep(10000); + } + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } +} diff --git a/otf-camunda/src/main/java/org/oran/otf/camunda/service/ProcessEngineAwareService.java b/otf-camunda/src/main/java/org/oran/otf/camunda/service/ProcessEngineAwareService.java new file mode 100644 index 0000000..6c8215b --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/camunda/service/ProcessEngineAwareService.java @@ -0,0 +1,68 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP - SO + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2017 Huawei Technologies Co., Ltd. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.oran.otf.camunda.service; + +import org.oran.otf.camunda.configuration.OtfCamundaConfiguration; +import java.util.Optional; +import org.camunda.bpm.engine.ProcessEngineServices; +import org.camunda.bpm.engine.ProcessEngines; +import org.springframework.stereotype.Service; + +/** + * Base class for services that must be process-engine aware. The only process engine currently + * supported is the "default" process engine. + */ +@Service +public class ProcessEngineAwareService { + + // private final String processEngineName = OTFProcessEngineConfiguration.processEngineName; + private final String processEngineName = OtfCamundaConfiguration.processEngineName; + private volatile Optional pes4junit = Optional.empty(); + + /** + * Gets the process engine name. + * + * @return the process engine name + */ + public String getProcessEngineName() { + return processEngineName; + } + + /** + * Gets process engine services. + * + * @return process engine services + */ + public ProcessEngineServices getProcessEngineServices() { + return pes4junit.orElse(ProcessEngines.getProcessEngine(getProcessEngineName())); + } + + /** + * Allows a particular process engine to be specified, overriding the usual process engine lookup + * by name. Intended primarily for the unit test environment. + * + * @param pes process engine services + */ + public void setProcessEngineServices4junit(ProcessEngineServices pes) { + pes4junit = Optional.ofNullable(pes); + } +} diff --git a/otf-camunda/src/main/java/org/oran/otf/camunda/workflow/WorkflowProcessor.java b/otf-camunda/src/main/java/org/oran/otf/camunda/workflow/WorkflowProcessor.java new file mode 100644 index 0000000..10a1dfd --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/camunda/workflow/WorkflowProcessor.java @@ -0,0 +1,526 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP - SO + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Modifications Copyright (c) 2019 Samsung + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.oran.otf.camunda.workflow; + +import org.oran.otf.camunda.configuration.OtfCamundaConfiguration; +import org.oran.otf.camunda.exception.TestExecutionException; +import org.oran.otf.camunda.exception.WorkflowProcessorException; +import org.oran.otf.camunda.model.ExecutionConstants.ExecutionVariable; +import org.oran.otf.camunda.model.ExecutionConstants.TestResult; +import org.oran.otf.camunda.model.WorkflowResponse; +import org.oran.otf.camunda.service.ProcessEngineAwareService; +import org.oran.otf.camunda.workflow.utility.WorkflowUtility; +import org.oran.otf.common.model.*; +import org.oran.otf.common.model.historic.TestDefinitionHistoric; +import org.oran.otf.common.model.historic.TestInstanceHistoric; +import org.oran.otf.common.model.local.BpmnInstance; +import org.oran.otf.common.model.local.ParallelFlowInput; +import org.oran.otf.common.repository.*; +import org.oran.otf.common.utility.Utility; +import org.oran.otf.common.utility.database.Generic; +import org.oran.otf.common.utility.permissions.PermissionChecker; +import org.oran.otf.common.utility.permissions.UserPermission; +import com.mongodb.client.result.UpdateResult; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.UUID; +import org.bson.types.ObjectId; +import org.camunda.bpm.BpmPlatform; +import org.camunda.bpm.engine.RepositoryService; +import org.camunda.bpm.engine.RuntimeService; +import org.camunda.bpm.engine.repository.ProcessDefinition; +import org.camunda.bpm.engine.runtime.ProcessInstance; +import org.camunda.bpm.engine.variable.VariableMap; +import org.camunda.bpm.engine.variable.Variables; +import org.camunda.bpm.engine.variable.impl.VariableMapImpl; +import org.oran.otf.common.model.*; +import org.oran.otf.common.repository.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.context.event.ApplicationReadyEvent; +import org.springframework.context.event.EventListener; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.query.Criteria; +import org.springframework.data.mongodb.core.query.Query; +import org.springframework.data.mongodb.core.query.Update; +import org.springframework.stereotype.Component; + +@Component +public class WorkflowProcessor extends ProcessEngineAwareService { + + private static final String logPrefix = Utility.getLoggerPrefix(); + private static final Logger logger = LoggerFactory.getLogger(WorkflowProcessor.class); + + @Autowired + GroupRepository groupRepository; + @Autowired + TestDefinitionRepository testDefinitionRepository; + @Autowired + TestInstanceRepository testInstanceRepository; + @Autowired + UserRepository userRepository; + @Autowired + TestExecutionRepository testExecutionRepository; + @Autowired + MongoTemplate mongoOperation; + @Autowired + WorkflowUtility workflowUtility; + + private RuntimeService runtimeService; + private RepositoryService repositoryService; + + // Note: the business key is used to identify the process in unit tests + protected static String getBusinessKey(Map inputVariables) { + return getOrCreate(inputVariables, "otf-business-key"); + } + + protected static Map getInputVariables(VariableMapImpl variableMap) { + Map inputVariables = new HashMap<>(); + @SuppressWarnings("unchecked") + Map vMap = (Map) variableMap.get("variables"); + for (Map.Entry entry : vMap.entrySet()) { + String vName = entry.getKey(); + Object value = entry.getValue(); + @SuppressWarnings("unchecked") + Map valueMap = (Map) value; // value, type + inputVariables.put(vName, valueMap.get("value")); + } + return inputVariables; + } + + protected static String getOrCreate(Map inputVariables, String key) { + String value = Objects.toString(inputVariables.get(key), null); + if (value == null) { + value = UUID.randomUUID().toString(); + inputVariables.put(key, value); + } + return value; + } + + private static void buildVariable( + String key, String value, Map variableValueType) { + Map host = new HashMap<>(); + host.put("value", value); + host.put("type", "String"); + variableValueType.put(key, host); + } + + @EventListener(ApplicationReadyEvent.class) + private void initialize() { + if (this.runtimeService == null) { + this.runtimeService = + BpmPlatform.getProcessEngineService() + .getProcessEngine(OtfCamundaConfiguration.processEngineName) + .getRuntimeService(); + } + if (this.repositoryService == null) { + this.repositoryService = + BpmPlatform.getProcessEngineService() + .getProcessEngine(OtfCamundaConfiguration.processEngineName) + .getRepositoryService(); + } + } + + public TestExecution processWorkflowRequest(WorkflowRequest request) + throws WorkflowProcessorException { + + // Check if the test instance exists. + TestInstance testInstance = + Generic.findByIdGeneric(testInstanceRepository, request.getTestInstanceId()); + if (testInstance == null) { + WorkflowResponse response = new WorkflowResponse(); + response.setMessage( + String.format( + "Test instance with identifier %s was not found.", + request.getTestInstanceId().toString())); + response.setMessageCode(404); + response.setResponse("Unable to start the test instance."); + TestExecution testExecution = generateTestExecution(request, null, null, null); + testExecution.setTestResult(TestResult.DOES_NOT_EXIST); + testExecution.setTestDetails(generateTestDetailsWithMessage(response.getMessage())); + response.setTestExecution(testExecution); + throw new WorkflowProcessorException(response); + } + + // Override the test data and vth input of the instance if the request contains the data. + Map vthInput = + request.getVthInput() == null ? testInstance.getVthInput() : request.getVthInput(); + Map testData = + request.getTestData() == null ? testInstance.getTestData() : request.getTestData(); + Map plfoInput = + request.getPfloInput() == null ? testInstance.getPfloInput() : request.getPfloInput(); + + testInstance.setVthInput((HashMap) vthInput); + testInstance.setTestData((HashMap) testData); + testInstance.setPfloInput((HashMap) plfoInput); + + + // Check if the test definition linked to the test instance is also present. + TestDefinition testDefinition = + Generic.findByIdGeneric(testDefinitionRepository, testInstance.getTestDefinitionId()); + if (testDefinition == null) { + WorkflowResponse response = new WorkflowResponse(); + response.setMessage( + String.format( + "Test definition with identifier %s was not found.", + testInstance.getTestDefinitionId().toString())); + response.setMessageCode(404); + response.setResponse("Unable to start the test instance."); + TestExecution testExecution = generateTestExecution(request, testInstance, null, null); + testExecution.setTestResult(TestResult.DOES_NOT_EXIST); + testExecution.setTestDetails(generateTestDetailsWithMessage(response.getMessage())); + response.setTestExecution(testExecution); + throw new WorkflowProcessorException(response); + } + + // is using latest defintion, verify that the processDefinitionId within camunda is present in + // the test definition bpmn instance list + if (testInstance.isUseLatestTestDefinition()) { + String processDefinitionId = + findLatestProcessDefinition(testDefinition.getProcessDefinitionKey()); + boolean isBpmnInstancePresent = + verifyIdExistsInTestDefinition(testDefinition, processDefinitionId); + if (isBpmnInstancePresent) { + testInstance.setProcessDefinitionId(processDefinitionId); + } else { + WorkflowResponse response = new WorkflowResponse(); + response.setMessage( + String.format( + "Latest Test Definition does not exist for key %s.", + testDefinition.getProcessDefinitionKey())); + response.setMessageCode(404); + response.setResponse("Unable to start the test instance."); + TestExecution testExecution = + generateTestExecution(request, testInstance, testDefinition, null); + testExecution.setTestResult(TestResult.DOES_NOT_EXIST); + testExecution.setTestDetails(generateTestDetailsWithMessage(response.getMessage())); + response.setTestExecution(testExecution); + throw new WorkflowProcessorException(response); + } + } + + // Check if the entity making the request has permission to run the test instance. + User executor = Generic.findByIdGeneric(userRepository, request.getExecutorId()); + if (executor == null) { + WorkflowResponse response = new WorkflowResponse(); + response.setMessage( + String + .format("User with id %s was not found.", request.getExecutorId().toString())); + response.setMessageCode(404); + response.setResponse("Unable to start the test instance."); + TestExecution testExecution = + generateTestExecution(request, testInstance, testDefinition, null); + testExecution.setTestResult(TestResult.DOES_NOT_EXIST); + testExecution.setTestDetails(generateTestDetailsWithMessage(response.getMessage())); + response.setTestExecution(testExecution); + throw new WorkflowProcessorException(response); + } +// if (!workflowUtility.hasPermission(executor, testInstance)) { +// WorkflowResponse response = new WorkflowResponse(); +// response.setMessage( +// String.format( +// "The user with email %s does not have permission to execute test instance with id: %s.", +// executor.getEmail(), testInstance.get_id().toString())); +// response.setMessageCode(401); +// response.setResponse("Unauthorized to execute the test instance."); +// TestExecution testExecution = +// generateTestExecution(request, testInstance, testDefinition, executor); +// testExecution.setTestResult(TestResult.UNAUTHORIZED); +// testExecution.setTestDetails(generateTestDetailsWithMessage(response.getMessage())); +// response.setTestExecution(testExecution); +// throw new WorkflowProcessorException(response); +// } + Group testInstanceGroup = groupRepository.findById(testInstance.getGroupId().toString()).orElse(null); + if(testInstanceGroup == null){ + WorkflowResponse response = new WorkflowResponse(); + response.setMessage( + String.format("unable to find test instance group. Group id: %s",testInstance.getGroupId().toString())); + response.setMessageCode(404); + response.setResponse("unable to find test instance group"); + TestExecution testExecution = generateTestExecution(request,testInstance,testDefinition,executor); + testExecution.setTestResult(TestResult.DOES_NOT_EXIST); + testExecution.setTestDetails(generateTestDetailsWithMessage(response.getMessage())); + response.setTestExecution(testExecution); + throw new WorkflowProcessorException(response); + } + if (!PermissionChecker.hasPermissionTo(executor,testInstanceGroup, UserPermission.Permission.EXECUTE,groupRepository)){ + WorkflowResponse response = new WorkflowResponse(); + response.setMessage( + String.format( + "User with email: %s does not have execute permission on test instance group with id: %s", + executor.getEmail(),testInstance.getGroupId().toString())); + response.setMessageCode(401); + response.setResponse("unauthorized to execute test instance"); + TestExecution testExecution = generateTestExecution(request,testInstance,testDefinition,executor); + testExecution.setTestResult(TestResult.UNAUTHORIZED); + testExecution.setTestDetails(generateTestDetailsWithMessage(response.getMessage())); + response.setTestExecution(testExecution); + throw new WorkflowProcessorException(response); + } + + // Generate a testExecution with a historic copy of the test instance, test definition, and the + // email of the person executing the test. + TestExecution testExecution = + generateTestExecution(request, testInstance, testDefinition, executor); + + // Prepare the test details, test result, test execution, and vth input variables for the + // process instance. + VariableMap variableMap = + Variables.createVariables() + .putValueTyped( + ExecutionVariable.TEST_DETAILS, + Variables.objectValue(testExecution.getTestDetails()).create()) + .putValueTyped( + ExecutionVariable.TEST_RESULT, + Variables.objectValue(testExecution.getTestResult()).create()) + .putValueTyped( + ExecutionVariable.TEST_RESULT_MESSAGE, + Variables.objectValue(testExecution.getTestResultMessage()).create()) + .putValueTyped(ExecutionVariable.VTH_INPUT, + Variables.objectValue(vthInput).create()) + .putValueTyped(ExecutionVariable.TEST_DATA, + Variables.objectValue(testData).create()) + .putValue( + ExecutionVariable.TEST_EXECUTION, + Variables.objectValue(testExecution) + .serializationDataFormat(Variables.SerializationDataFormats.JAVA) + .create()) + .putValue( + ExecutionVariable.PFLO_INPUT, + Variables.objectValue(plfoInput) + .serializationDataFormat(Variables.SerializationDataFormats.JAVA) + .create()); + + if (testInstance.isUseLatestTestDefinition()) { + return startProcessByKey( + testDefinition.getProcessDefinitionKey(), variableMap, testExecution); + } else { + return startProcessById(testInstance.getProcessDefinitionId(), variableMap, + testExecution); + } + } + + public TestExecution startProcessByKey( + String processKey, Map variableMap, TestExecution testExecution) { + try { + logger.info( + "***OTF startProcessInstanceByKey with processKey: {} and variables: {}", + processKey, + variableMap); + + // Set the start time as close to the runtime service start function. + testExecution.setStartTime(new Date(System.currentTimeMillis())); + testExecutionRepository.insert(testExecution); + + ProcessInstance processInstance = + runtimeService.startProcessInstanceByKey( + processKey, testExecution.getBusinessKey(), variableMap); + + // Update the test execution object with the processInstanceId after the processInstanceId is + // available. + testExecution.setProcessInstanceId(processInstance.getProcessInstanceId()); + Query query = new Query(); + query.addCriteria(Criteria.where("_id").is(testExecution.get_id())); + // Also add businessKey as a criteria because the object won't be found if the business key + // was somehow modified in the workflow. + query.addCriteria(Criteria.where("businessKey").is(testExecution.getBusinessKey())); + Update update = new Update(); + update.set("processInstanceId", processInstance.getProcessInstanceId()); + UpdateResult result = mongoOperation.updateFirst(query, update, TestExecution.class); + // Check the status of the findAndUpdate database, and appropriately handle the errors. + if (result.getMatchedCount() == 0) { + throw new TestExecutionException( + String.format( + "Unable to log the test result because a testExecution associated with _id, %s and businessKey %s, was not found.", + testExecution.get_id(), testExecution.getBusinessKey())); + } else if (result.getModifiedCount() == 0) { + throw new TestExecutionException( + "Unable to persist the testExecution to the database."); + } + + logger.debug( + logPrefix + + "Process " + + processKey + + ":" + + processInstance.getProcessInstanceId() + + " " + + (processInstance.isEnded() ? "ENDED" : "RUNNING")); + } catch (Exception e) { + WorkflowResponse workflowResponse = new WorkflowResponse(); + workflowResponse.setResponse("Error occurred while executing the process: " + e); + workflowResponse.setProcessInstanceId(testExecution.getProcessInstanceId()); + workflowResponse.setMessageCode(500); + workflowResponse.setMessage("Failed to execute test instance: " + e.getMessage()); + testExecution.setTestResult(TestResult.FAILED); + testExecution + .setTestDetails(generateTestDetailsWithMessage(workflowResponse.getMessage())); + workflowResponse.setTestExecution(testExecution); + throw new WorkflowProcessorException(workflowResponse); + } + + return testExecution; + } + + private TestExecution startProcessById( + String processId, Map variableMap, TestExecution testExecution) { + try { + logger.debug( + "***OTF startProcessInstanceById with processId: {} and variables: {}", + processId, + variableMap); + + // Set the start time as close to the runtime service start function. + testExecution.setStartTime(new Date(System.currentTimeMillis())); + testExecutionRepository.insert(testExecution); + + ProcessInstance processInstance = + runtimeService.startProcessInstanceById( + processId, testExecution.getBusinessKey(), variableMap); + + // Update the test execution object with the processInstanceId after the processInstanceId is + // available. + testExecution.setProcessInstanceId(processInstance.getProcessInstanceId()); + Query query = new Query(); + query.addCriteria(Criteria.where("_id").is(testExecution.get_id())); + // Also add businessKey as a criteria because the object won't be found if the business key + // was somehow modified in the workflow. + query.addCriteria(Criteria.where("businessKey").is(testExecution.getBusinessKey())); + Update update = new Update(); + update.set("processInstanceId", processInstance.getProcessInstanceId()); + UpdateResult result = mongoOperation.updateFirst(query, update, TestExecution.class); + // Check the status of the findAndUpdate database, and appropriately handle the errors. + if (result.getMatchedCount() == 0) { + throw new TestExecutionException( + String.format( + "Unable to log the test result because a testExecution associated with _id, %s and businessKey %s, was not found.", + testExecution.get_id(), testExecution.getBusinessKey())); + } else if (result.getModifiedCount() == 0) { + throw new TestExecutionException( + "Unable to persist the testExecution to the database."); + } + + logger.debug( + logPrefix + + "Process " + + processInstance.getProcessInstanceId() + + ":" + + processInstance.getProcessInstanceId() + + " " + + (processInstance.isEnded() ? "ENDED" : "RUNNING")); + } catch (Exception e) { + WorkflowResponse workflowResponse = new WorkflowResponse(); + workflowResponse.setResponse("Error occurred while executing the process: " + e); + workflowResponse.setProcessInstanceId(testExecution.getProcessInstanceId()); + workflowResponse.setMessageCode(500); + workflowResponse.setMessage("Failed to execute test instance: " + e.getMessage()); + testExecution.setTestResult(TestResult.FAILED); + testExecution + .setTestDetails(generateTestDetailsWithMessage(workflowResponse.getMessage())); + workflowResponse.setTestExecution(testExecution); + throw new WorkflowProcessorException(workflowResponse); + } + + return testExecution; + } + + private TestExecution generateTestExecution( + WorkflowRequest request, + TestInstance testInstance, + TestDefinition testDefinition, + User executor) { + TestExecution testExecution = new TestExecution(); + testExecution.set_id(new ObjectId()); + testExecution.setExecutorId(request.getExecutorId()); + testExecution.setAsync(request.isAsync()); + testExecution.setStartTime(null); + testExecution.setTestDetails(new HashMap<>()); + testExecution.setTestResult(TestResult.UNKNOWN); + testExecution.setTestResultMessage(""); + testExecution.setProcessInstanceId(null); + testExecution.setBusinessKey(UUID.randomUUID().toString()); + testExecution.setTestHeadResults(new ArrayList<>()); + testExecution.setTestInstanceResults(new ArrayList<>()); + if (testInstance != null) { + testExecution.setGroupId(testInstance.getGroupId()); + TestInstanceHistoric testInstanceHistoric = new TestInstanceHistoric(testInstance); + testExecution.setHistoricTestInstance(testInstanceHistoric); + } + if (testDefinition != null && testInstance != null) { + TestDefinitionHistoric testDefinitionHistoric = + new TestDefinitionHistoric(testDefinition, testInstance.getProcessDefinitionId()); + testExecution.setHistoricTestDefinition(testDefinitionHistoric); + } + if (executor != null) { + testExecution.setHistoricEmail(executor.getEmail()); + } + return testExecution; + } + + private Map generateTestDetailsWithMessage(String message) { + Map map = new HashMap<>(); + map.put("message", message); + return map; + } + + private String findLatestProcessDefinition(String processDefinitionKey) { + logger.info("Before find process definition key query."); + ProcessDefinition definition = + repositoryService + .createProcessDefinitionQuery() + .processDefinitionKey(processDefinitionKey) + .latestVersion() + .singleResult(); + logger.info("After find process definition key query."); + String processDefinitionId = null; + if (definition != null) { + processDefinitionId = definition.getId(); + } + return processDefinitionId; + } + + private boolean verifyIdExistsInTestDefinition( + TestDefinition definition, String processDefinitionId) { + if (processDefinitionId == null || definition == null) { + return false; + } + + List bpmnInstances = definition.getBpmnInstances(); + BpmnInstance bpmnInstance = + bpmnInstances.stream() + .filter( + _bpmnInstance -> { + return _bpmnInstance.isDeployed() + && _bpmnInstance.getProcessDefinitionId() != null + && _bpmnInstance.getProcessDefinitionId().equals(processDefinitionId); + }) + .findFirst() + .orElse(null); + return bpmnInstance != null; + } +} diff --git a/otf-camunda/src/main/java/org/oran/otf/camunda/workflow/WorkflowRequest.java b/otf-camunda/src/main/java/org/oran/otf/camunda/workflow/WorkflowRequest.java new file mode 100644 index 0000000..fa5f10e --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/camunda/workflow/WorkflowRequest.java @@ -0,0 +1,182 @@ +/* Copyright (c) 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.oran.otf.camunda.workflow; + +import org.oran.otf.common.model.local.ParallelFlowInput; +import org.oran.otf.common.utility.gson.Convert; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import java.io.Serializable; +import java.util.Map; +import org.bson.types.ObjectId; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class WorkflowRequest implements Serializable { + + private static final long serialVersionUID = 1L; + + private boolean async = false; + @JsonSerialize(using = ToStringSerializer.class) + private ObjectId executorId = null; + + @JsonSerialize(using = ToStringSerializer.class) + private ObjectId testInstanceId = null; + + private Map pfloInput = null; + private Map testData = null; + private Map vthInput = null; + private long maxExecutionTimeInMillis = 0L; + + public WorkflowRequest() throws Exception { + //this.validate(); + } + + public WorkflowRequest( + boolean async, + String executorId, + String testInstanceId, + long maxExecutionTimeInMillis) { + this.async = async; + this.executorId = new ObjectId(executorId); + this.testInstanceId = new ObjectId(testInstanceId); + this.maxExecutionTimeInMillis = maxExecutionTimeInMillis; + } + + public WorkflowRequest( + boolean async, + ObjectId executorId, + ObjectId testInstanceId, + Map pfloInput, + Map testData, + Map vthInput, + int maxExecutionTimeInMillis) + throws Exception { + this.async = async; + this.executorId = executorId; + this.testInstanceId = testInstanceId; + this.pfloInput = pfloInput; + this.testData = testData; + this.vthInput = vthInput; + this.maxExecutionTimeInMillis = maxExecutionTimeInMillis; + + this.validate(); + } + + @JsonCreator + public WorkflowRequest( + @JsonProperty(value = "async", required = false) boolean async, + @JsonProperty(value = "executorId", required = true) String executorId, + @JsonProperty(value = "testInstanceId", required = true) String testInstanceId, + @JsonProperty(value = "pfloInput", required = false) Map pfloInput, + @JsonProperty(value = "testData", required = false) Map testData, + @JsonProperty(value = "vthInput", required = false) Map vthInput, + @JsonProperty(value = "maxExecutionTimeInMillis", required = false) + int maxExecutionTimeInMillis) throws Exception { + this.async = async; + this.executorId = new ObjectId(executorId); + this.testInstanceId = new ObjectId(testInstanceId); + this.pfloInput = pfloInput; + this.testData = testData; + this.vthInput = vthInput; + this.maxExecutionTimeInMillis = maxExecutionTimeInMillis; + + this.validate(); + } + + private void validate() throws Exception { + String missingFieldFormat = "Missing required field %s."; +// if (this.executorId == null) { +// throw new Exception(String.format(missingFieldFormat, "executorId")); +// } + + if (this.testInstanceId == null) { + throw new Exception(String.format(missingFieldFormat, "testInstanceId")); + } + + if (this.maxExecutionTimeInMillis < 0L) { + this.maxExecutionTimeInMillis = 0L; + } + } + + public boolean isAsync() { + return async; + } + + public void setAsync(boolean async) { + this.async = async; + } + + public ObjectId getExecutorId() { + return executorId; + } + + public void setExecutorId(ObjectId executorId) { + this.executorId = executorId; + } + + public ObjectId getTestInstanceId() { + return testInstanceId; + } + + public void setTestInstanceId(String testInstanceId) { + this.testInstanceId = new ObjectId(testInstanceId); + } + + public void setTestInstanceId(ObjectId testInstanceId) { + this.testInstanceId = testInstanceId; + } + + public Map getPfloInput() { + return pfloInput; + } + + public void setPfloInput(Map pfloInput) { + this.pfloInput = pfloInput; + } + + public Map getTestData() { + return testData; + } + + public void setTestData(Map testData) { + this.testData = testData; + } + + public Map getVthInput() { + return vthInput; + } + + public void setVthInput(Map vthInput) { + this.vthInput = vthInput; + } + + public long getMaxExecutionTimeInMillis() { + return maxExecutionTimeInMillis; + } + + public void setMaxExecutionTimeInMillis(long maxExecutionTimeInMillis) { + this.maxExecutionTimeInMillis = maxExecutionTimeInMillis; + } + + @Override + public String toString() { + return Convert.objectToJson(this); + } +} diff --git a/otf-camunda/src/main/java/org/oran/otf/camunda/workflow/handler/ExternalTaskIncidentHandler.java b/otf-camunda/src/main/java/org/oran/otf/camunda/workflow/handler/ExternalTaskIncidentHandler.java new file mode 100644 index 0000000..0e7d2ca --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/camunda/workflow/handler/ExternalTaskIncidentHandler.java @@ -0,0 +1,139 @@ +/* Copyright (c) 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.oran.otf.camunda.workflow.handler; + +import org.oran.otf.camunda.configuration.OtfCamundaConfiguration; +import org.oran.otf.camunda.exception.TestExecutionException; +import org.oran.otf.camunda.model.ExecutionConstants.TestResult; +import org.oran.otf.camunda.workflow.utility.WorkflowTask; +import org.oran.otf.common.model.TestExecution; +import org.oran.otf.common.repository.TestExecutionRepository; +import org.oran.otf.common.utility.Utility; +import org.oran.otf.service.impl.DeleteProcessInstanceServiceImpl; +import com.mongodb.client.result.UpdateResult; + +import java.util.Date; +import java.util.List; + +import org.camunda.bpm.BpmPlatform; +import org.camunda.bpm.engine.RuntimeService; +import org.camunda.bpm.engine.impl.incident.IncidentContext; +import org.camunda.bpm.engine.impl.incident.IncidentHandler; +import org.camunda.bpm.engine.runtime.Execution; +import org.camunda.bpm.engine.runtime.Incident; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.context.event.ApplicationReadyEvent; +import org.springframework.context.event.EventListener; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.query.Criteria; +import org.springframework.data.mongodb.core.query.Query; +import org.springframework.data.mongodb.core.query.Update; +import org.springframework.stereotype.Service; + +@Service +public class ExternalTaskIncidentHandler implements IncidentHandler { + + private static final Logger logger = LoggerFactory.getLogger(ExternalTaskIncidentHandler.class); + private static final String logPrefix = Utility.getLoggerPrefix(); + + @Autowired + private TestExecutionRepository testExecutionRepository; + @Autowired + private MongoTemplate mongoOperation; + @Autowired + private DeleteProcessInstanceServiceImpl deleteProcessInstanceService; + + @Override + public String getIncidentHandlerType() { + return Incident.EXTERNAL_TASK_HANDLER_TYPE; + } + + @Override + public Incident handleIncident(IncidentContext context, String message) { + //need to get process instance id from executionid (parent process) + String executionId = context.getExecutionId(); + RuntimeService runtimeService = BpmPlatform.getProcessEngineService().getProcessEngine(OtfCamundaConfiguration.processEngineName).getRuntimeService(); + + Execution execution = runtimeService.createExecutionQuery().executionId(executionId).singleResult(); + String processInstanceId = execution.getProcessInstanceId(); + TestExecution testExecution = + testExecutionRepository.findFirstByProcessInstanceId(processInstanceId).orElse(null); + + if (testExecution == null) { + String error = + String.format( + "%sUnable to find testExecution with processInstanceId %s. This process instance will forcefully be terminated to avoid a rogue process.", + logPrefix, processInstanceId); + logger.error(error); + deleteProcessInstanceService.deleteProcessInstanceInternal(processInstanceId, error); + } else { + if(!testExecution.getTestResult().equals(TestResult.TERMINATED)){ + updateTestResult(testExecution, TestResult.WORKFLOW_ERROR, message); + } + deleteProcessInstanceService.deleteProcessInstanceInternal(processInstanceId, message); + + List workflowTasks = + WorkflowTask.workflowTasksByExecutionId.getOrDefault(processInstanceId, null); + + if (workflowTasks != null) { + logger.debug("Forcefully terminating workflow tasks for processInstanceId: " + processInstanceId); + for (WorkflowTask workflowTask : workflowTasks) { + workflowTask.shutdown(true); + } + } + } + + return null; + } + + private void updateTestResult(TestExecution testExecution, String testResult, String testResultMessage) { + // Set the test result + testExecution.setTestResult(testResult); + testExecution.setTestResultMessage(testResultMessage); + Query query = new Query(); + query.addCriteria(Criteria.where("_id").is(testExecution.get_id())); + // Also add businessKey as a criteria because the object won't be found if the business key + // was somehow modified in the workflow. + query.addCriteria(Criteria.where("businessKey").is(testExecution.getBusinessKey())); + Update update = new Update(); + update.set("testResult", testExecution.getTestResult()); + update.set("testResultMessage", testExecution.getTestResultMessage()); + update.set("endTime", new Date(System.currentTimeMillis())); + UpdateResult result = mongoOperation.updateFirst(query, update, TestExecution.class); + // Check the status of the findAndUpdate database, and appropriately handle the errors. + if (result.getMatchedCount() == 0) { + throw new TestExecutionException( + String.format( + "Unable to log the test result because a testExecution associated with _id, %s and businessKey %s, was not found.", + testExecution.get_id(), testExecution.getBusinessKey())); + } else if (result.getModifiedCount() == 0) { + throw new TestExecutionException("Unable to persist the testExecution to the database."); + } + } + + @Override + public void resolveIncident(IncidentContext context) { + // logger.info("incident resolved"); + } + + @Override + public void deleteIncident(IncidentContext context) { + // logger.info("incident deleted"); + } +} diff --git a/otf-camunda/src/main/java/org/oran/otf/camunda/workflow/handler/FailedJobIncidentHandler.java b/otf-camunda/src/main/java/org/oran/otf/camunda/workflow/handler/FailedJobIncidentHandler.java new file mode 100644 index 0000000..f01d550 --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/camunda/workflow/handler/FailedJobIncidentHandler.java @@ -0,0 +1,145 @@ +/* Copyright (c) 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.oran.otf.camunda.workflow.handler; + +import org.oran.otf.camunda.configuration.OtfCamundaConfiguration; +import org.oran.otf.camunda.exception.TestExecutionException; +import org.oran.otf.camunda.model.ExecutionConstants.TestResult; +import org.oran.otf.camunda.workflow.utility.WorkflowTask; +import org.oran.otf.common.model.TestExecution; +import org.oran.otf.common.repository.TestExecutionRepository; +import org.oran.otf.common.utility.Utility; +import org.oran.otf.service.impl.DeleteProcessInstanceServiceImpl; +import com.google.common.base.Strings; +import com.mongodb.client.result.UpdateResult; + +import java.util.Date; +import java.util.List; + +import org.camunda.bpm.BpmPlatform; +import org.camunda.bpm.engine.RuntimeService; +import org.camunda.bpm.engine.impl.incident.IncidentContext; +import org.camunda.bpm.engine.impl.incident.IncidentHandler; +import org.camunda.bpm.engine.runtime.Execution; +import org.camunda.bpm.engine.runtime.Incident; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.context.event.ApplicationReadyEvent; +import org.springframework.context.event.EventListener; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.query.Criteria; +import org.springframework.data.mongodb.core.query.Query; +import org.springframework.data.mongodb.core.query.Update; +import org.springframework.stereotype.Service; + +@Service +public class FailedJobIncidentHandler implements IncidentHandler { + + private static final Logger logger = LoggerFactory.getLogger(FailedJobIncidentHandler.class); + private static final String logPrefix = Utility.getLoggerPrefix(); + + @Autowired + private TestExecutionRepository testExecutionRepository; + @Autowired + private MongoTemplate mongoOperation; + @Autowired + private DeleteProcessInstanceServiceImpl deleteProcessInstanceService; + + @Override + public String getIncidentHandlerType() { + return Incident.FAILED_JOB_HANDLER_TYPE; + } + + @Override + public Incident handleIncident(IncidentContext context, String message) { + String executionId = context.getExecutionId(); + if (Strings.isNullOrEmpty(executionId)) { + return null; + } + RuntimeService runtimeService = BpmPlatform.getProcessEngineService().getProcessEngine(OtfCamundaConfiguration.processEngineName).getRuntimeService(); + + Execution execution = runtimeService.createExecutionQuery().executionId(executionId).singleResult(); + String processInstanceId = execution.getProcessInstanceId(); + TestExecution testExecution = + testExecutionRepository.findFirstByProcessInstanceId(processInstanceId).orElse(null); + + if (testExecution == null) { + String error = String.format( + "%sUnable to find testExecution with processInstanceId %s. This process instance will forcefully be terminated to avoid a rogue process.", + logPrefix, processInstanceId); + logger.error(error); + deleteProcessInstanceService.deleteProcessInstanceInternal(processInstanceId, error); + + } else { + if(!testExecution.getTestResult().equals(TestResult.TERMINATED)){ + updateTestResult(testExecution, TestResult.WORKFLOW_ERROR, message); + } + deleteProcessInstanceService.deleteProcessInstanceInternal(processInstanceId, message); + + } + + List workflowTasks = + WorkflowTask.workflowTasksByExecutionId.getOrDefault(processInstanceId, null); + + if (workflowTasks != null) { + logger.debug("Forcefully terminating workflow tasks for processInstanceId: " + processInstanceId); + for (WorkflowTask workflowTask : workflowTasks) { + workflowTask.shutdown(true); + } + } + + return null; + } + + private void updateTestResult(TestExecution testExecution, String testResult, String testResultMessage) { + // Set the test result + testExecution.setTestResult(testResult); + testExecution.setTestResultMessage(testResultMessage); + Query query = new Query(); + query.addCriteria(Criteria.where("_id").is(testExecution.get_id())); + // Also add businessKey as a criteria because the object won't be found if the business key + // was somehow modified in the workflow. + query.addCriteria(Criteria.where("businessKey").is(testExecution.getBusinessKey())); + Update update = new Update(); + update.set("testResult", testExecution.getTestResult()); + update.set("testResultMessage", testExecution.getTestResultMessage()); + update.set("endTime", new Date(System.currentTimeMillis())); + UpdateResult result = mongoOperation.updateFirst(query, update, TestExecution.class); + // Check the status of the findAndUpdate database, and appropriately handle the errors. + if (result.getMatchedCount() == 0) { + throw new TestExecutionException( + String.format( + "Unable to log the test result because a testExecution associated with _id, %s and businessKey %s, was not found.", + testExecution.get_id(), testExecution.getBusinessKey())); + } else if (result.getModifiedCount() == 0) { + throw new TestExecutionException("Unable to persist the testExecution to the database."); + } + } + + @Override + public void resolveIncident(IncidentContext context) { + // logger.info("incident resolved"); + + } + + @Override + public void deleteIncident(IncidentContext context) { + // logger.info("incident deleted"); + + } +} diff --git a/otf-camunda/src/main/java/org/oran/otf/camunda/workflow/utility/RsaEncryptDecrypt.java b/otf-camunda/src/main/java/org/oran/otf/camunda/workflow/utility/RsaEncryptDecrypt.java new file mode 100644 index 0000000..b90a8e5 --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/camunda/workflow/utility/RsaEncryptDecrypt.java @@ -0,0 +1,55 @@ +/* Copyright (c) 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.oran.otf.camunda.workflow.utility; + +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.NoSuchAlgorithmException; +import javax.crypto.Cipher; +import org.springframework.stereotype.Service; + +@Service +public class RsaEncryptDecrypt { + + private KeyPair keyPair; + + public RsaEncryptDecrypt() throws NoSuchAlgorithmException { + this.keyPair = buildKeyPair(); + + } + + private KeyPair buildKeyPair() throws NoSuchAlgorithmException { + final int keySize = 2048; + KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); + keyPairGenerator.initialize(keySize); + return keyPairGenerator.genKeyPair(); + } + + public byte[] encrypt(String message) throws Exception { + Cipher cipher = Cipher.getInstance("RSA"); + cipher.init(Cipher.ENCRYPT_MODE, this.keyPair.getPrivate()); + + return cipher.doFinal(message.getBytes()); + } + + public byte[] decrypt(byte[] encrypted) throws Exception { + Cipher cipher = Cipher.getInstance("RSA"); + cipher.init(Cipher.DECRYPT_MODE, this.keyPair.getPublic()); + + return cipher.doFinal(encrypted); + } +} diff --git a/otf-camunda/src/main/java/org/oran/otf/camunda/workflow/utility/WorkflowTask.java b/otf-camunda/src/main/java/org/oran/otf/camunda/workflow/utility/WorkflowTask.java new file mode 100644 index 0000000..e7302e6 --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/camunda/workflow/utility/WorkflowTask.java @@ -0,0 +1,169 @@ +/* Copyright (c) 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.oran.otf.camunda.workflow.utility; + +import org.oran.otf.common.utility.Utility; +import com.google.common.base.Strings; +import com.google.common.util.concurrent.ThreadFactoryBuilder; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class WorkflowTask { + + private static final Logger logger = LoggerFactory.getLogger(WorkflowTask.class); + private static final String logPrefix = Utility.getLoggerPrefix(); + + public static Map> workflowTasksByExecutionId = + new ConcurrentHashMap<>(); + // The processInstanceId of the Camunda process instance the thread pool is created under. + private final String processInstanceId; + // The pool service used to create the fixed thread pool. + private final ExecutorService pool; + // Used to keep track of all the tasks to be executed, which allows tasks to easily be deleted. + private List> futures; + // Used to determine if currently running threads should be interrupted + private boolean interruptOnFailure; + + public WorkflowTask(String executionId, int threads, boolean interruptOnFailure) { + if (threads <= 0 || Strings.isNullOrEmpty(executionId)) { + this.processInstanceId = null; + this.pool = null; + return; + } + + ThreadFactory namedThreadFactory = + new ThreadFactoryBuilder().setNameFormat(executionId + "-%d").build(); + + this.processInstanceId = executionId; + this.pool = + threads == 1 + ? Executors.newSingleThreadExecutor() + : Executors.newFixedThreadPool(threads, namedThreadFactory); + this.futures = Collections.synchronizedList(new ArrayList<>()); + this.interruptOnFailure = interruptOnFailure; + + synchronized (WorkflowTask.workflowTasksByExecutionId) { + if (!WorkflowTask.workflowTasksByExecutionId.containsKey(this.processInstanceId)) { + List list = new ArrayList<>(); + list.add(this); + WorkflowTask.workflowTasksByExecutionId.put( + this.processInstanceId, Collections.synchronizedList(list)); + } else { + WorkflowTask.workflowTasksByExecutionId.get(this.processInstanceId).add(this); + } + } + } + + public void shutdown() { + this.shutdown(this.interruptOnFailure); + } + + public void shutdown(boolean interruptOnFailure) { + if (interruptOnFailure) { + // Cancel currently executing tasks, and halt any waiting tasks. + pool.shutdownNow(); + } else { + // Disable new tasks from being submitted, while allowing currently executing tasks to finish. + pool.shutdown(); + } + + try { + // Wait a while for existing tasks to terminate + if (!pool.awaitTermination(60, TimeUnit.SECONDS)) { + for (Future f : futures) { + f.cancel(interruptOnFailure); + } + + // Wait a while for tasks to respond to being cancelled + if (!pool.awaitTermination(60, TimeUnit.SECONDS)) { + System.err.println("Pool did not terminate"); + } + } + } catch (InterruptedException ie) { + // (Re-)Cancel if current thread also interrupted + pool.shutdownNow(); + // Preserve interrupt status + // Thread.currentThread().interrupt(); + } + + workflowTasksByExecutionId.remove(this.processInstanceId); + } + + public String getProcessInstanceId() { + return processInstanceId; + } + + public ExecutorService getPool() { + return pool; + } + + public List> getFutures() { + return futures; + } + + public void setFutures(List> futures) { + this.futures = futures; + } + + public static void printWorkflowTaskResources() { + for (Map.Entry> entry : workflowTasksByExecutionId.entrySet()) { + logger.info( + "{}--------------Parent processInstanceId: {}--------------", logPrefix, entry.getKey()); + + List workflowTasks = + workflowTasksByExecutionId.getOrDefault(entry.getKey(), null); + for (WorkflowTask task : workflowTasks) { + task.print(); + } + } + } + + public static void printThreadInformation() { + Set threadSet = Thread.getAllStackTraces().keySet(); + for (Thread t : threadSet) { + if (t.getThreadGroup() == Thread.currentThread().getThreadGroup()) { + logger.info("{}{}", logPrefix, t.toString()); + } + } + } + + private void print() { + logger.info("%sWorkflowTask processInstanceId{})", this.processInstanceId); + if (this.pool instanceof ThreadPoolExecutor) { + ThreadPoolExecutor tpe = (ThreadPoolExecutor) pool; + + logger.info("\tActive count: {}.", tpe.getActiveCount()); + logger.info("\tTask status: {}/{}.", tpe.getCompletedTaskCount(), tpe.getTaskCount()); + logger.info("\tPool size: {}.", tpe.getPoolSize()); + logger.info("\tCore pool size: {}.", tpe.getCorePoolSize()); + logger.info("\tQueue size: {}.", tpe.getQueue().size()); + } + } +} diff --git a/otf-camunda/src/main/java/org/oran/otf/camunda/workflow/utility/WorkflowUtility.java b/otf-camunda/src/main/java/org/oran/otf/camunda/workflow/utility/WorkflowUtility.java new file mode 100644 index 0000000..608470e --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/camunda/workflow/utility/WorkflowUtility.java @@ -0,0 +1,291 @@ +/* Copyright (c) 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.oran.otf.camunda.workflow.utility; + +import static org.camunda.spin.Spin.JSON; + +import org.oran.otf.camunda.exception.TestExecutionException; +import org.oran.otf.camunda.model.ExecutionConstants; +import org.oran.otf.camunda.model.ExecutionConstants.ExecutionVariable; +import org.oran.otf.common.model.TestExecution; +import org.oran.otf.common.model.local.ParallelFlowInput; +import org.oran.otf.common.utility.Utility; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.bson.types.ObjectId; +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.camunda.spin.json.SpinJsonNode; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class WorkflowUtility { + + private static Logger logger = LoggerFactory.getLogger(WorkflowUtility.class); + @Autowired + private RsaEncryptDecrypt rsaUtility; + + public boolean verifyTestExecutionChecksum( + DelegateExecution execution, TestExecution testExecution) { + try { + byte[] enc = (byte[]) execution.getVariable(ExecutionVariable.TEST_EXECUTION); + + String test = ""; // testExecution.createTestDescription(); + String dec = new String(rsaUtility.decrypt(enc)); + if (!dec.equals(test)) { + return false; + // throw new TestExecutionException("Modification Error: User modified platform data"); + } + } catch (Exception e) { + logger.error( + execution.getCurrentActivityId() + + ": Failed to decrypt test execution. May have been tampered with.\n" + + e.getMessage()); + return false; + } + return true; + } + + public T getExecutionVariable(Map variables, String key, Class type) { + Object obj = variables.get(key); + if (obj == null) { + logger.error(String.format("Failed to get variable because the key %s does not exist.", key)); + } + // return spin json nodes as maps + if (obj instanceof SpinJsonNode) { + SpinJsonNode node = (SpinJsonNode) obj; + if (!node.isObject()) { + throw new TestExecutionException( + "Unable to retrieve variable as type Map from the execution. Variable was set to SpinJsonNode"); + } + Map map = (Map) node.mapTo(HashMap.class); + } + + return type.isInstance(obj) ? type.cast(obj) : null; + } + +// public boolean hasPermission(User user, TestInstance testInstance) { +// // Groups that the user holds a membership in. +// List userGroups = user.getGroups(); +// // The groupId associated with the test instance. +// ObjectId targetGroupId = testInstance.getGroupId(); +// // Check if any of the groups has access to the test instance. +// UserGroup targetGroup = +// userGroups.stream() +// .filter(userGroup -> userGroup.getGroupId().equals(targetGroupId)) +// .findAny() +// .orElse(null); +// +// return targetGroup != null; +// } + + public TestExecution getTestExecution(Map variables, String logPrefix) + throws TestExecutionException { + // Get the current test execution object. + TestExecution testExecution = + this.getExecutionVariable(variables, ExecutionVariable.TEST_EXECUTION, TestExecution.class); + // Perform a null-check to ensure it is available. It's critical to throw an exception if it + // is not available since the object is essential for results. + if (testExecution == null) { + logger.error(logPrefix + " Test execution is null."); + throw new TestExecutionException("The test execution was not found."); + } + return testExecution; + } + + public Map getTestData(Map variables, String logPrefix) + throws TestExecutionException { + // Get vthInput from the Camunda execution variable map. + @SuppressWarnings({"unchecked"}) + Map testData = + (Map) + this.getExecutionVariable(variables, ExecutionVariable.TEST_DATA, Map.class); + + if (testData == null) { + throw new TestExecutionException( + "Unable to retrieve testData as type Map from the execution."); + } + return testData; + } + + public Object getTestDataByActivity( + Map variables, String currentActivityId, String logPrefix) + throws TestExecutionException, NullPointerException { + // Get vthInput from the Camunda execution variable map. + @SuppressWarnings({"unchecked"}) + Map testData = + (Map) + this.getExecutionVariable(variables, ExecutionVariable.TEST_DATA, Map.class); + + if (testData == null) { + throw new TestExecutionException( + "Unable to retrieve testData as type Map from the execution."); + } + Object activityParameters = testData.get(currentActivityId); + if (activityParameters == null) { + throw new NullPointerException( + logPrefix + + String.format( + "A testData parameter was not found for the activityId, %s.", currentActivityId)); + } + return activityParameters; + } + + + public Map getPfloInputByActivity( + Map variables, String currentActivityId, String logPrefix) + throws TestExecutionException, NullPointerException { + // Get vthInput from the Camunda execution variable map. + @SuppressWarnings({"unchecked"}) + Map pfloInput = + (Map) + this.getExecutionVariable(variables, ExecutionVariable.PFLO_INPUT, Map.class); + + if (pfloInput == null) { + throw new TestExecutionException( + "Unable to retrieve testData as type Map from the execution."); + } + Map activityParameters = + (Map) pfloInput.get(currentActivityId); + if (activityParameters == null) { + throw new NullPointerException( + logPrefix + + String.format( + "A plfoInput parameter was not found for the activityId, %s.", + currentActivityId)); + } + return activityParameters; + } + + public List> getVthInput( + Map variables, String currentActivityId, String logPrefix) + throws TestExecutionException, NullPointerException, IllegalArgumentException { + // Get vthInput from the Camunda execution variable map. + @SuppressWarnings({"unchecked"}) + Map vthInput = + (Map) + this.getExecutionVariable(variables, ExecutionVariable.VTH_INPUT, Map.class); + + if (vthInput == null) { + throw new TestExecutionException( + "Unable to retrieve vthInput as type Map from the execution."); + } + + // Get the current activityId to use as a key to retrieve the vthInput for this task. + // vthInput is expected to be a JSON array of size [1, inf) + Object oActivityParameters = vthInput.get(currentActivityId); + // Throw an exception if no parameters were found for this activity. + if (oActivityParameters == null) { + throw new NullPointerException( + logPrefix + + String.format( + "A vthInput parameter was not found for the activityId, %s.", currentActivityId)); + } + + List> lActivityParameters; + // Legacy hack + try { + @SuppressWarnings("unchecked") + Map mActivityParameters = new HashMap<>(); + mActivityParameters.put("method", "post"); + mActivityParameters.put("payload", Utility.toMap(oActivityParameters)); + Map headers = new HashMap<>(); + headers.put("Content-Type", "application/json"); + mActivityParameters.put("headers", headers); + lActivityParameters = new ArrayList(); + lActivityParameters.add(mActivityParameters); + } catch (Exception e) { + try { + // Try to convert the parameters to an array of "vthInput(s)" + lActivityParameters = (List>) Utility.toList(oActivityParameters); + } catch (Exception ee) { + throw new IllegalArgumentException( + String.format("Unable to parse the value for vthInput[%s].", currentActivityId)); + } + } + return lActivityParameters; + } + + public String getTestResult(Map variables, String logPrefix) { + String testResult = + this.getExecutionVariable(variables, ExecutionVariable.TEST_RESULT, String.class); + // Set the test result to UNKNOWN + if (testResult == null) { + logger.debug( + logPrefix + + "Unable to retrieve test result as primitive type String. Setting result to unknown."); + testResult = ExecutionConstants.TestResult.UNKNOWN; + } + return testResult; + } + + public String getTestResultMessage(Map variables, String logPrefix) { + String testResultMessage = + this.getExecutionVariable(variables, ExecutionVariable.TEST_RESULT_MESSAGE, String.class); + // Set the test result to UNKNOWN + if (testResultMessage == null) { + testResultMessage = ""; +// logger.debug( +// logPrefix +// + "Unable to retrieve test result message as primitive type String. Setting message to empty string."); +// testResultMessage = ""; + } + return testResultMessage; + } + + public Map getTestDetails(Map variables, String logPrefix) + throws TestExecutionException { + // Get test details as a String because it can be saved as one of many "JSON" types. Then try + // to convert it to a generic map. + String testDetailsString = + this.getExecutionVariable(variables, ExecutionVariable.TEST_DETAILS, String.class); + if (testDetailsString != null) { + // Use Spin to map the string to a Map. + @SuppressWarnings({"unchecked"}) + Map mTestDetails; + try { + mTestDetails = JSON(testDetailsString).mapTo(HashMap.class); + } catch (Exception e) { + logger.error( + "Unable to convert testDetails to a map.\nError: " + + e.getMessage() + + "\ntestDetails: " + + testDetailsString); + mTestDetails = new HashMap<>(); + } + return mTestDetails; + } + + // get testDetails as a map. + @SuppressWarnings({"unchecked"}) + Map testDetails = + (Map) + this.getExecutionVariable(variables, ExecutionVariable.TEST_DETAILS, Map.class); + + if (testDetails == null) { + logger.debug( + logPrefix + + "Unable to retrieve test details as primitive type String. Setting to an empty JSON."); + testDetails = new HashMap<>(); + } + return testDetails; + } +} diff --git a/otf-camunda/src/main/java/org/oran/otf/common/model/Group.java b/otf-camunda/src/main/java/org/oran/otf/common/model/Group.java new file mode 100644 index 0000000..93162f8 --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/common/model/Group.java @@ -0,0 +1,109 @@ +/* Copyright (c) 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.oran.otf.common.model; + +import org.oran.otf.common.utility.gson.Convert; +import java.io.Serializable; +import java.util.List; +import org.bson.types.ObjectId; +import org.springframework.data.annotation.Id; +import org.springframework.data.mongodb.core.mapping.Document; + +@Document(collection = "groups") +public class Group implements Serializable { + + private static final long serialVersionUID = 1L; + + @Id + private ObjectId _id; + private String groupName; + private String groupDescription; + private List mechanizedIds; + private ObjectId ownerId; + private List roles; + private List members; + private ObjectId parentGroupId; + + public ObjectId get_id() { + return _id; + } + + public void set_id(ObjectId _id) { + this._id = _id; + } + + public String getGroupName() { + return groupName; + } + + public void setGroupName(String groupName) { + this.groupName = groupName; + } + + public String getGroupDescription() { + return groupDescription; + } + + public void setGroupDescription(String groupDescription) { + this.groupDescription = groupDescription; + } + + public List getMechanizedIds() { + return mechanizedIds; + } + + public void setMechanizedIds(List mechanizedIds) { + this.mechanizedIds = mechanizedIds; + } + + public ObjectId getOwnerId() { + return ownerId; + } + + public void setOwnerId(ObjectId ownerId) { + this.ownerId = ownerId; + } + + public List getRoles() { + return roles; + } + + public void setRoles(List roles) { + this.roles = roles; + } + + public List getMembers() { + return members; + } + + public void setMembers(List members) { + this.members = members; + } + + public ObjectId getParentGroupId() { + return parentGroupId; + } + + public void setParentGroupId(ObjectId parentGroupId) { + this.parentGroupId = parentGroupId; + } + + @Override + public String toString() { + return Convert.objectToJson(this); + } +} diff --git a/otf-camunda/src/main/java/org/oran/otf/common/model/GroupMember.java b/otf-camunda/src/main/java/org/oran/otf/common/model/GroupMember.java new file mode 100644 index 0000000..6ab79c2 --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/common/model/GroupMember.java @@ -0,0 +1,42 @@ +/* Copyright (c) 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.oran.otf.common.model; + +import org.bson.types.ObjectId; + +import java.util.List; + +public class GroupMember { + private ObjectId userId; + private List roles;//this is name of roles assigned to user that are created within the group i.e admin,dev,.. etc + + public ObjectId getUserId() { + return userId; + } + + public void setUserId(ObjectId userId) { + this.userId = userId; + } + + public List getRoles() { + return roles; + } + + public void setRoles(List roles) { + this.roles = roles; + } +} diff --git a/otf-camunda/src/main/java/org/oran/otf/common/model/Role.java b/otf-camunda/src/main/java/org/oran/otf/common/model/Role.java new file mode 100644 index 0000000..aca09f1 --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/common/model/Role.java @@ -0,0 +1,41 @@ +/* Copyright (c) 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.oran.otf.common.model; + +import java.util.List; + +public class Role { + + private String roleName; + private List permissions; + + public String getRoleName() { + return roleName; + } + + public void setRoleName(String roleName) { + this.roleName = roleName; + } + + public List getPermissions() { + return permissions; + } + + public void setPermissions(List permissions) { + this.permissions = permissions; + } +} diff --git a/otf-camunda/src/main/java/org/oran/otf/common/model/TestDefinition.java b/otf-camunda/src/main/java/org/oran/otf/common/model/TestDefinition.java new file mode 100644 index 0000000..b59a746 --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/common/model/TestDefinition.java @@ -0,0 +1,138 @@ +/* Copyright (c) 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.oran.otf.common.model; + +import org.oran.otf.common.model.local.BpmnInstance; +import org.oran.otf.common.utility.gson.Convert; +import java.io.Serializable; +import java.util.Date; +import java.util.List; +import org.bson.types.ObjectId; +import org.springframework.data.annotation.Id; +import org.springframework.data.mongodb.core.mapping.Document; + +@Document(collection = "testDefinitions") +public class TestDefinition implements Serializable { + + private static final long serialVersionUID = 1L; + + @Id + private ObjectId _id; + private String testName; + private String testDescription; + private String processDefinitionKey; + private List bpmnInstances; + private ObjectId groupId; + private Date createdAt; + private Date updatedAt; + private ObjectId createdBy; + private ObjectId updatedBy; + private boolean disabled; + + public ObjectId get_id() { + return _id; + } + + public void set_id(ObjectId _id) { + this._id = _id; + } + + public String getTestName() { + return testName; + } + + public void setTestName(String testName) { + this.testName = testName; + } + + public String getTestDescription() { + return testDescription; + } + + public void setTestDescription(String testDescription) { + this.testDescription = testDescription; + } + + public String getProcessDefinitionKey() { + return processDefinitionKey; + } + + public void setProcessDefinitionKey(String processDefinitionKey) { + this.processDefinitionKey = processDefinitionKey; + } + + public List getBpmnInstances() { + return bpmnInstances; + } + + public void setBpmnInstances(List bpmnInstances) { + this.bpmnInstances = bpmnInstances; + } + + public ObjectId getGroupId() { + return groupId; + } + + public void setGroupId(ObjectId groupId) { + this.groupId = groupId; + } + + public Date getCreatedAt() { + return createdAt; + } + + public void setCreatedAt(Date createdAt) { + this.createdAt = createdAt; + } + + public Date getUpdatedAt() { + return updatedAt; + } + + public void setUpdatedAt(Date updatedAt) { + this.updatedAt = updatedAt; + } + + public ObjectId getCreatedBy() { + return createdBy; + } + + public void setCreatedBy(ObjectId createdBy) { + this.createdBy = createdBy; + } + + public ObjectId getUpdatedBy() { + return updatedBy; + } + + public void setUpdatedBy(ObjectId updatedBy) { + this.updatedBy = updatedBy; + } + + public boolean isDisabled() { + return disabled; + } + + public void setDisabled(boolean disabled) { + this.disabled = disabled; + } + + @Override + public String toString() { + return Convert.objectToJson(this); + } +} diff --git a/otf-camunda/src/main/java/org/oran/otf/common/model/TestExecution.java b/otf-camunda/src/main/java/org/oran/otf/common/model/TestExecution.java new file mode 100644 index 0000000..85b4a71 --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/common/model/TestExecution.java @@ -0,0 +1,235 @@ +/* Copyright (c) 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.oran.otf.common.model; + +import org.oran.otf.common.model.historic.TestDefinitionHistoric; +import org.oran.otf.common.model.historic.TestInstanceHistoric; +import org.oran.otf.common.model.local.TestHeadResult; +import org.oran.otf.common.utility.gson.Convert; +import java.io.Serializable; +import java.util.Date; +import java.util.List; +import java.util.Map; +import org.bson.types.ObjectId; +import org.springframework.data.annotation.Id; +import org.springframework.data.mongodb.core.mapping.Document; + +@Document(collection = "testExecutions") +public class TestExecution implements Serializable { + + private static final long serialVersionUID = 1L; + + @Id + private ObjectId _id; + private ObjectId groupId; + private ObjectId executorId; + + private boolean async; + private Date startTime; + private Date endTime; + private String businessKey; + private String processInstanceId; + private String testResult; + private String testResultMessage; + private Map testDetails; + private List testHeadResults; + private List testInstanceResults; + // Stores historic information of associated + private String historicEmail; + private TestInstanceHistoric historicTestInstance; + private TestDefinitionHistoric historicTestDefinition; + + public TestExecution() { + } + + public TestExecution( + ObjectId _id, + ObjectId groupId, + ObjectId executorId, + boolean async, + Date startTime, + Date endTime, + String businessKey, + String processInstanceId, + String testResult, + String testResultMessage, + Map testDetails, + List testHeadResults, + List testInstanceResults, + String historicEmail, + TestInstanceHistoric historicTestInstance, + TestDefinitionHistoric historicTestDefinition) { + this._id = _id; + this.groupId = groupId; + this.executorId = executorId; + this.async = async; + this.startTime = startTime; + this.endTime = endTime; + this.businessKey = businessKey; + this.processInstanceId = processInstanceId; + this.testResult = testResult; + this.testResultMessage = testResultMessage; + this.testDetails = testDetails; + this.testHeadResults = testHeadResults; + this.testInstanceResults = testInstanceResults; + this.historicEmail = historicEmail; + this.historicTestInstance = historicTestInstance; + this.historicTestDefinition = historicTestDefinition; + } + + public ObjectId get_id() { + return _id; + } + + public void set_id(ObjectId _id) { + this._id = _id; + } + + public ObjectId getGroupId() { + return groupId; + } + + public void setGroupId(ObjectId groupId) { + this.groupId = groupId; + } + + public ObjectId getExecutorId() { + return executorId; + } + + public void setExecutorId(ObjectId executorId) { + this.executorId = executorId; + } + + public boolean isAsync() { + return async; + } + + public void setAsync(boolean async) { + this.async = async; + } + + public Date getStartTime() { + return startTime; + } + + public void setStartTime(Date startTime) { + this.startTime = startTime; + } + + public Date getEndTime() { + return endTime; + } + + public void setEndTime(Date endTime) { + this.endTime = endTime; + } + + public String getBusinessKey() { + return businessKey; + } + + public void setBusinessKey(String businessKey) { + this.businessKey = businessKey; + } + + public String getProcessInstanceId() { + return processInstanceId; + } + + public void setProcessInstanceId(String processInstanceId) { + this.processInstanceId = processInstanceId; + } + + public String getTestResult() { + return testResult; + } + + public void setTestResult(String testResult) { + this.testResult = testResult; + } + + public String getTestResultMessage() { + return testResultMessage; + } + + public void setTestResultMessage(String testResultMessage) { + this.testResultMessage = testResultMessage; + } + + public Map getTestDetails() { + return testDetails; + } + + public void setTestDetails(Map testDetails) { + this.testDetails = testDetails; + } + + public List getTestHeadResults() { + synchronized (testHeadResults) { + return testHeadResults; + } + } + + public void setTestHeadResults(List testHeadResults) { + synchronized (testHeadResults) { + this.testHeadResults = testHeadResults; + } + } + + public List getTestInstanceResults() { + synchronized (testInstanceResults) { + return testInstanceResults; + } + } + + public void setTestInstanceResults(List testInstanceResults) { + synchronized (testInstanceResults) { + this.testInstanceResults = testInstanceResults; + } + } + + public String getHistoricEmail() { + return historicEmail; + } + + public void setHistoricEmail(String historicEmail) { + this.historicEmail = historicEmail; + } + + public TestInstanceHistoric getHistoricTestInstance() { + return historicTestInstance; + } + + public void setHistoricTestInstance(TestInstanceHistoric historicTestInstance) { + this.historicTestInstance = historicTestInstance; + } + + public TestDefinitionHistoric getHistoricTestDefinition() { + return historicTestDefinition; + } + + public void setHistoricTestDefinition( + TestDefinitionHistoric historicTestDefinition) { + this.historicTestDefinition = historicTestDefinition; + } + + @Override + public String toString() { + return Convert.objectToJson(this); + } +} diff --git a/otf-camunda/src/main/java/org/oran/otf/common/model/TestHead.java b/otf-camunda/src/main/java/org/oran/otf/common/model/TestHead.java new file mode 100644 index 0000000..7f4bcbc --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/common/model/TestHead.java @@ -0,0 +1,224 @@ +/* Copyright (c) 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.oran.otf.common.model; + +import org.oran.otf.common.utility.gson.Convert; +import java.io.Serializable; +import java.util.Date; +import java.util.Map; + +import org.bson.types.ObjectId; +import org.springframework.data.annotation.Id; +import org.springframework.data.mongodb.core.index.Indexed; +import org.springframework.data.mongodb.core.mapping.Document; + +@Document(collection = "testHeads") +public class TestHead implements Serializable { + + private static final long serialVersionUID = 1L; + + @Id + private ObjectId _id; + + @Indexed(unique = true) + private String testHeadName; + + private String testHeadDescription; + private String hostname; + private String port; + private String resourcePath; + private ObjectId creatorId; + private ObjectId groupId; + private String authorizationType; + private String authorizationCredential; + private Boolean authorizationEnabled; + private Map vthInputTemplate; + private Date createdAt; + private Date updatedAt; + private ObjectId updatedBy; + private Boolean isPublic; + public TestHead() { + } + + public TestHead( + ObjectId _id, + String testHeadName, + String testHeadDescription, + String hostname, + String port, + String resourcePath, + ObjectId creatorId, + ObjectId groupId, + String authorizationType, + String authorizationCredential, + boolean authorizationEnabled, + Map vthInputTemplate, + Date createdAt, + Date updatedAt, + ObjectId updatedBy, + Boolean isPublic) { + this._id = _id; + this.testHeadName = testHeadName; + this.testHeadDescription = testHeadDescription; + this.hostname = hostname; + this.port = port; + this.resourcePath = resourcePath; + this.creatorId = creatorId; + this.groupId = groupId; + this.authorizationType = authorizationType; + this.authorizationCredential = authorizationCredential; + this.authorizationEnabled = authorizationEnabled; + this.vthInputTemplate = vthInputTemplate; + this.createdAt = createdAt; + this.updatedAt = updatedAt; + this.updatedBy = updatedBy; + this.isPublic = isPublic; + } + + public ObjectId get_id() { + return _id; + } + + public void set_id(ObjectId _id) { + this._id = _id; + } + + public String getTestHeadName() { + return testHeadName; + } + + public void setTestHeadName(String testHeadName) { + this.testHeadName = testHeadName; + } + + public String getTestHeadDescription() { + return testHeadDescription; + } + + public void setTestHeadDescription(String testHeadDescription) { + this.testHeadDescription = testHeadDescription; + } + + public String getHostname() { + return hostname; + } + + public void setHostname(String hostname) { + this.hostname = hostname; + } + + public String getPort() { + return port; + } + + public void setPort(String port) { + this.port = port; + } + + public String getResourcePath() { + return resourcePath; + } + + public void setResourcePath(String resourcePath) { + this.resourcePath = resourcePath; + } + + public ObjectId getCreatorId() { + return creatorId; + } + + public void setCreatorId(ObjectId creatorId) { + this.creatorId = creatorId; + } + + public ObjectId getGroupId() { + return groupId; + } + + public void setGroupId(ObjectId groupId) { + this.groupId = groupId; + } + + public String getAuthorizationCredential() { + return authorizationCredential; + } + + public String getAuthorizationType() { + return authorizationType; + } + + public void setAuthorizationType(String authorizationType) { + this.authorizationType = authorizationType; + } + + public void setAuthorizationCredential(String authorizationCredential) { + this.authorizationCredential = authorizationCredential; + } + + public Boolean getAuthorizationEnabled() { + return authorizationEnabled; + } + + public void setAuthorizationEnabled(Boolean authorizationEnabled) { + this.authorizationEnabled = authorizationEnabled; + } + + public Map getVthInputTemplate() { + return vthInputTemplate; + } + + public void setVthInputTemplate(Map vthInputTemplate) { + this.vthInputTemplate = vthInputTemplate; + } + + public Date getCreatedAt() { + return createdAt; + } + + public void setCreatedAt(Date createdAt) { + this.createdAt = createdAt; + } + + public Date getUpdatedAt() { + return updatedAt; + } + + public void setUpdatedAt(Date updatedAt) { + this.updatedAt = updatedAt; + } + + public ObjectId getUpdatedBy() { + return updatedBy; + } + + public void setUpdatedBy(ObjectId updatedBy) { + this.updatedBy = updatedBy; + } + + public Boolean isPublic() { + return isPublic; + } + + public void setPublic(Boolean aPublic) { + isPublic = aPublic; + } + + @Override + public String toString() { + return Convert.objectToJson(this); + } +} diff --git a/otf-camunda/src/main/java/org/oran/otf/common/model/TestInstance.java b/otf-camunda/src/main/java/org/oran/otf/common/model/TestInstance.java new file mode 100644 index 0000000..96fcfa9 --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/common/model/TestInstance.java @@ -0,0 +1,259 @@ +/* Copyright (c) 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.oran.otf.common.model; + +import org.oran.otf.common.model.local.ParallelFlowInput; +import org.oran.otf.common.utility.gson.Convert; +import java.io.Serializable; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import org.bson.types.ObjectId; +import org.springframework.data.annotation.Id; +import org.springframework.data.mongodb.core.mapping.Document; + +@Document(collection = "testInstances") +public class TestInstance implements Serializable { + + private static final long serialVersionUID = 1L; + + private @Id + ObjectId _id; + private String testInstanceName; + private String testInstanceDescription; + private ObjectId groupId; + private ObjectId testDefinitionId; + private String processDefinitionId; + private boolean useLatestTestDefinition; + private boolean disabled; + private boolean simulationMode; + private long maxExecutionTimeInMillis; + private Map pfloInput; + private Map internalTestData; + private Map simulationVthInput; + private Map testData; + private Map vthInput; + private Date createdAt; + private Date updatedAt; + private ObjectId createdBy; + private ObjectId updatedBy; + + public TestInstance() { + } + + public TestInstance( + ObjectId _id, + String testInstanceName, + String testInstanceDescription, + ObjectId groupId, + ObjectId testDefinitionId, + String processDefinitionId, + boolean useLatestTestDefinition, + boolean disabled, + boolean simulationMode, + long maxExecutionTimeInMillis, + HashMap pfloInput, + HashMap internalTestData, + HashMap simulationVthInput, + HashMap testData, + HashMap vthInput, + Date createdAt, + Date updatedAt, + ObjectId createdBy, + ObjectId updatedBy) { + this._id = _id; + this.testInstanceName = testInstanceName; + this.testInstanceDescription = testInstanceDescription; + this.groupId = groupId; + this.testDefinitionId = testDefinitionId; + this.processDefinitionId = processDefinitionId; + this.useLatestTestDefinition = useLatestTestDefinition; + this.disabled = disabled; + this.simulationMode = simulationMode; + this.maxExecutionTimeInMillis = maxExecutionTimeInMillis; + this.pfloInput = pfloInput; + this.internalTestData = internalTestData; + this.simulationVthInput = simulationVthInput; + this.testData = testData; + this.vthInput = vthInput; + this.createdAt = createdAt; + this.updatedAt = updatedAt; + this.createdBy = createdBy; + this.updatedBy = updatedBy; + } + + public static long getSerialVersionUID() { + return serialVersionUID; + } + + public ObjectId get_id() { + return _id; + } + + public void set_id(ObjectId _id) { + this._id = _id; + } + + public String getTestInstanceName() { + return testInstanceName; + } + + public void setTestInstanceName(String testInstanceName) { + this.testInstanceName = testInstanceName; + } + + public String getTestInstanceDescription() { + return testInstanceDescription; + } + + public void setTestInstanceDescription(String testInstanceDescription) { + this.testInstanceDescription = testInstanceDescription; + } + + public ObjectId getGroupId() { + return groupId; + } + + public void setGroupId(ObjectId groupId) { + this.groupId = groupId; + } + + public ObjectId getTestDefinitionId() { + return testDefinitionId; + } + + public void setTestDefinitionId(ObjectId testDefinitionId) { + this.testDefinitionId = testDefinitionId; + } + + public String getProcessDefinitionId() { + return processDefinitionId; + } + + public void setProcessDefinitionId(String processDefinitionId) { + this.processDefinitionId = processDefinitionId; + } + + public boolean isUseLatestTestDefinition() { + return useLatestTestDefinition; + } + + public void setUseLatestTestDefinition(boolean useLatestTestDefinition) { + this.useLatestTestDefinition = useLatestTestDefinition; + } + + public boolean isDisabled() { + return disabled; + } + + public void setDisabled(boolean disabled) { + this.disabled = disabled; + } + + public boolean isSimulationMode() { + return simulationMode; + } + + public void setSimulationMode(boolean simulationMode) { + this.simulationMode = simulationMode; + } + + public long getMaxExecutionTimeInMillis() { + return maxExecutionTimeInMillis; + } + + public void setMaxExecutionTimeInMillis(long maxExecutionTimeInMillis) { + this.maxExecutionTimeInMillis = maxExecutionTimeInMillis; + } + + public Map getPfloInput() { + return pfloInput; + } + + public void setPfloInput(HashMap pfloInput) { + this.pfloInput = pfloInput; + } + + public Map getInternalTestData() { + return internalTestData; + } + + public void setInternalTestData(HashMap internalTestData) { + this.internalTestData = internalTestData; + } + + public Map getSimulationVthInput() { + return simulationVthInput; + } + + public void setSimulationVthInput(HashMap simulationVthInput) { + this.simulationVthInput = simulationVthInput; + } + + public Map getTestData() { + return testData; + } + + public void setTestData(HashMap testData) { + this.testData = testData; + } + + public Map getVthInput() { + return vthInput; + } + + public void setVthInput(HashMap vthInput) { + this.vthInput = vthInput; + } + + public Date getCreatedAt() { + return createdAt; + } + + public void setCreatedAt(Date createdAt) { + this.createdAt = createdAt; + } + + public Date getUpdatedAt() { + return updatedAt; + } + + public void setUpdatedAt(Date updatedAt) { + this.updatedAt = updatedAt; + } + + public ObjectId getCreatedBy() { + return createdBy; + } + + public void setCreatedBy(ObjectId createdBy) { + this.createdBy = createdBy; + } + + public ObjectId getUpdatedBy() { + return updatedBy; + } + + public void setUpdatedBy(ObjectId updatedBy) { + this.updatedBy = updatedBy; + } + + @Override + public String toString() { + return Convert.objectToJson(this); + } +} diff --git a/otf-camunda/src/main/java/org/oran/otf/common/model/User.java b/otf-camunda/src/main/java/org/oran/otf/common/model/User.java new file mode 100644 index 0000000..9262b52 --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/common/model/User.java @@ -0,0 +1,139 @@ +/* Copyright (c) 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.oran.otf.common.model; + +import org.oran.otf.common.model.local.UserGroup; +import org.oran.otf.common.utility.gson.Convert; +import java.io.Serializable; +import java.util.Date; +import java.util.List; +import org.bson.types.ObjectId; +import org.springframework.data.mongodb.core.mapping.Document; + +@Document(collection = "users") +public class User implements Serializable { + + private static final long serialVersionUID = 1L; + + private ObjectId _id; + private List permissions; + private String firstName; + private String lastName; + private String email; + private String password; + private List groups; + private Date createdAt; + private Date updatedAt; + + public User( + ObjectId _id, + List permissions, + String firstName, + String lastName, + String email, + String password, + List groups, + Date createdAt, + Date updatedAt) { + this._id = _id; + this.permissions = permissions; + this.firstName = firstName; + this.lastName = lastName; + this.email = email; + this.password = password; + this.groups = groups; + this.createdAt = createdAt; + this.updatedAt = updatedAt; + } + + public ObjectId get_id() { + return _id; + } + + public void set_id(ObjectId _id) { + this._id = _id; + } + + public List getPermissions() { + return permissions; + } + + public void setPermissions(List permissions) { + this.permissions = permissions; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public List getGroups() { + return groups; + } + + public void setGroups(List groups) { + this.groups = groups; + } + + public Date getCreatedAt() { + return createdAt; + } + + public void setCreatedAt(Date createdAt) { + this.createdAt = createdAt; + } + + public Date getUpdatedAt() { + return updatedAt; + } + + public void setUpdatedAt(Date updatedAt) { + this.updatedAt = updatedAt; + } + + @Override + public String toString() { + return Convert.objectToJson(this); + } +} diff --git a/otf-camunda/src/main/java/org/oran/otf/common/model/historic/TestDefinitionHistoric.java b/otf-camunda/src/main/java/org/oran/otf/common/model/historic/TestDefinitionHistoric.java new file mode 100644 index 0000000..aa32b5b --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/common/model/historic/TestDefinitionHistoric.java @@ -0,0 +1,188 @@ +/* Copyright (c) 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.oran.otf.common.model.historic; + +import org.oran.otf.common.model.TestDefinition; +import org.oran.otf.common.model.local.BpmnInstance; +import org.oran.otf.common.utility.gson.Convert; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import org.bson.types.ObjectId; + +public class TestDefinitionHistoric implements Serializable { + + private static final long serialVersionUID = 1L; + + private ObjectId _id; + private String testName; + private String testDescription; + private String processDefinitionKey; + private List bpmnInstances; + private ObjectId groupId; + private Date createdAt; + private Date updatedAt; + private ObjectId createdBy; + private ObjectId updatedBy; + + public TestDefinitionHistoric() { + } + + public TestDefinitionHistoric(TestDefinition testDefinition, String processDefinitionId) { + this._id = testDefinition.get_id(); + this.testName = testDefinition.getTestName(); + this.testDescription = testDefinition.getTestDescription(); + this.processDefinitionKey = testDefinition.getProcessDefinitionKey(); + this.bpmnInstances = + getHistoricBpmnInstanceAsList(testDefinition.getBpmnInstances(), processDefinitionId); + this.groupId = testDefinition.getGroupId(); + this.createdAt = testDefinition.getCreatedAt(); + this.updatedAt = testDefinition.getUpdatedAt(); + this.createdBy = testDefinition.getCreatedBy(); + this.updatedBy = testDefinition.getUpdatedBy(); + } + + public TestDefinitionHistoric( + ObjectId _id, + String testName, + String testDescription, + String processDefinitionKey, + List bpmnInstances, + ObjectId groupId, + Date createdAt, + Date updatedAt, + ObjectId createdBy, + ObjectId updatedBy) { + this._id = _id; + this.testName = testName; + this.testDescription = testDescription; + this.processDefinitionKey = processDefinitionKey; + this.bpmnInstances = bpmnInstances; + this.groupId = groupId; + this.createdAt = createdAt; + this.updatedAt = updatedAt; + this.createdBy = createdBy; + this.updatedBy = updatedBy; + } + + private List getHistoricBpmnInstanceAsList( + List bpmnInstances, String processDefinitionId) { + BpmnInstance bpmnInstance = + bpmnInstances.stream() + .filter( + _bpmnInstance -> { + return _bpmnInstance.isDeployed() + && _bpmnInstance.getProcessDefinitionId() != null + && _bpmnInstance.getProcessDefinitionId().equals(processDefinitionId); + }) + .findFirst() + .orElse(null); + + List historicBpmnInstance = new ArrayList<>(); + if (bpmnInstance != null) { + historicBpmnInstance.add(bpmnInstance); + } + + return historicBpmnInstance; + } + + public ObjectId get_id() { + return _id; + } + + public void set_id(ObjectId _id) { + this._id = _id; + } + + public String getTestName() { + return testName; + } + + public void setTestName(String testName) { + this.testName = testName; + } + + public String getTestDescription() { + return testDescription; + } + + public void setTestDescription(String testDescription) { + this.testDescription = testDescription; + } + + public String getProcessDefinitionKey() { + return processDefinitionKey; + } + + public void setProcessDefinitionKey(String processDefinitionKey) { + this.processDefinitionKey = processDefinitionKey; + } + + public List getBpmnInstances() { + return bpmnInstances; + } + + public void setBpmnInstances(List bpmnInstances) { + this.bpmnInstances = bpmnInstances; + } + + public ObjectId getGroupId() { + return groupId; + } + + public void setGroupId(ObjectId groupId) { + this.groupId = groupId; + } + + public Date getCreatedAt() { + return createdAt; + } + + public void setCreatedAt(Date createdAt) { + this.createdAt = createdAt; + } + + public Date getUpdatedAt() { + return updatedAt; + } + + public void setUpdatedAt(Date updatedAt) { + this.updatedAt = updatedAt; + } + + public ObjectId getCreatedBy() { + return createdBy; + } + + public void setCreatedBy(ObjectId createdBy) { + this.createdBy = createdBy; + } + + public ObjectId getUpdatedBy() { + return updatedBy; + } + + public void setUpdatedBy(ObjectId updatedBy) { + this.updatedBy = updatedBy; + } + + @Override + public String toString() { + return Convert.objectToJson(this); + } +} diff --git a/otf-camunda/src/main/java/org/oran/otf/common/model/historic/TestInstanceHistoric.java b/otf-camunda/src/main/java/org/oran/otf/common/model/historic/TestInstanceHistoric.java new file mode 100644 index 0000000..1263893 --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/common/model/historic/TestInstanceHistoric.java @@ -0,0 +1,234 @@ +/* Copyright (c) 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.oran.otf.common.model.historic; + +import org.oran.otf.common.model.TestInstance; +import org.oran.otf.common.model.local.ParallelFlowInput; +import org.oran.otf.common.utility.gson.Convert; +import java.io.Serializable; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import org.bson.types.ObjectId; +import org.springframework.data.annotation.Id; + +public class TestInstanceHistoric implements Serializable { + + private static final long serialVersionUID = 1L; + + private @Id + ObjectId _id; + private String testInstanceName; + private String testInstanceDescription; + private ObjectId groupId; + private ObjectId testDefinitionId; + private String processDefinitionId; + private Map pfloInput; + private Map simulationVthInput; + private Map testData; + private Map vthInput; + private Date createdAt; + private Date updatedAt; + private ObjectId createdBy; + private ObjectId updatedBy; + private boolean simulationMode; + + public TestInstanceHistoric() { + } + + public TestInstanceHistoric(TestInstance testInstance) { + this._id = testInstance.get_id(); + this.testInstanceName = testInstance.getTestInstanceName(); + this.testInstanceDescription = testInstance.getTestInstanceDescription(); + this.groupId = testInstance.getGroupId(); + this.testDefinitionId = testInstance.getTestDefinitionId(); + this.pfloInput = testInstance.getPfloInput(); + this.processDefinitionId = testInstance.getProcessDefinitionId(); + this.simulationVthInput = testInstance.getSimulationVthInput(); + this.testData = testInstance.getTestData(); + this.vthInput = testInstance.getVthInput(); + this.createdAt = testInstance.getCreatedAt(); + this.updatedAt = testInstance.getUpdatedAt(); + this.createdBy = testInstance.getCreatedBy(); + this.updatedBy = testInstance.getUpdatedBy(); + this.simulationMode = testInstance.isSimulationMode(); + } + + public TestInstanceHistoric( + ObjectId _id, + String testInstanceName, + String testInstanceDescription, + ObjectId groupId, + ObjectId testDefinitionId, + String processDefinitionId, + HashMap pfloInput, + HashMap simulationVthInput, + HashMap testData, + HashMap vthInput, + Date createdAt, + Date updatedAt, + ObjectId createdBy, + ObjectId updatedBy, + boolean simulationMode) { + this._id = _id; + this.testInstanceName = testInstanceName; + this.testInstanceDescription = testInstanceDescription; + this.groupId = groupId; + this.testDefinitionId = testDefinitionId; + this.processDefinitionId = processDefinitionId; + this.pfloInput = pfloInput; + this.simulationVthInput = simulationVthInput; + this.testData = testData; + this.vthInput = vthInput; + this.createdAt = createdAt; + this.updatedAt = updatedAt; + this.createdBy = createdBy; + this.updatedBy = updatedBy; + this.simulationMode = simulationMode; + } + + public static long getSerialVersionUID() { + return serialVersionUID; + } + + public ObjectId get_id() { + return _id; + } + + public void set_id(ObjectId _id) { + this._id = _id; + } + + public String getTestInstanceName() { + return testInstanceName; + } + + public void setTestInstanceName(String testInstanceName) { + this.testInstanceName = testInstanceName; + } + + public String getTestInstanceDescription() { + return testInstanceDescription; + } + + public void setTestInstanceDescription(String testInstanceDescription) { + this.testInstanceDescription = testInstanceDescription; + } + + public ObjectId getGroupId() { + return groupId; + } + + public void setGroupId(ObjectId groupId) { + this.groupId = groupId; + } + + public ObjectId getTestDefinitionId() { + return testDefinitionId; + } + + public void setTestDefinitionId(ObjectId testDefinitionId) { + this.testDefinitionId = testDefinitionId; + } + + public String getProcessDefinitionId() { + return processDefinitionId; + } + + public void setProcessDefinitionId(String processDefinitionId) { + this.processDefinitionId = processDefinitionId; + } + + public Map getPfloInput() { + return pfloInput; + } + + public void setPfloInput( + HashMap pfloInput) { + this.pfloInput = pfloInput; + } + + public Map getSimulationVthInput() { + return simulationVthInput; + } + + public void setSimulationVthInput( + HashMap simulationVthInput) { + this.simulationVthInput = simulationVthInput; + } + + public Map getTestData() { + return testData; + } + + public void setTestData(HashMap testData) { + this.testData = testData; + } + + public Map getVthInput() { + return vthInput; + } + + public void setVthInput(HashMap vthInput) { + this.vthInput = vthInput; + } + + public Date getCreatedAt() { + return createdAt; + } + + public void setCreatedAt(Date createdAt) { + this.createdAt = createdAt; + } + + public Date getUpdatedAt() { + return updatedAt; + } + + public void setUpdatedAt(Date updatedAt) { + this.updatedAt = updatedAt; + } + + public ObjectId getCreatedBy() { + return createdBy; + } + + public void setCreatedBy(ObjectId createdBy) { + this.createdBy = createdBy; + } + + public ObjectId getUpdatedBy() { + return updatedBy; + } + + public void setUpdatedBy(ObjectId updatedBy) { + this.updatedBy = updatedBy; + } + + public boolean isSimulationMode() { + return simulationMode; + } + + public void setSimulationMode(boolean simulationMode) { + this.simulationMode = simulationMode; + } + + @Override + public String toString() { + return Convert.objectToJson(this); + } +} diff --git a/otf-camunda/src/main/java/org/oran/otf/common/model/local/BpmnInstance.java b/otf-camunda/src/main/java/org/oran/otf/common/model/local/BpmnInstance.java new file mode 100644 index 0000000..580e86c --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/common/model/local/BpmnInstance.java @@ -0,0 +1,187 @@ +/* Copyright (c) 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.oran.otf.common.model.local; + +import org.oran.otf.common.utility.gson.Convert; +import java.io.Serializable; +import java.util.Date; +import java.util.List; +import java.util.Map; +import org.bson.types.ObjectId; + +public class BpmnInstance implements Serializable { + + private static final long serialVersionUID = 1L; + + private String processDefinitionId; + private String deploymentId; + private int version; + private ObjectId bpmnFileId; + private ObjectId resourceFileId; + private boolean isDeployed; + private List testHeads; + private List pflos; + private Map testDataTemplate; + private Date createdAt; + private Date updatedAt; + private ObjectId createdBy; + private ObjectId updatedBy; + + public BpmnInstance() { + } + + public BpmnInstance( + String processDefinitionId, + String deploymentId, + int version, + ObjectId bpmnFileId, + ObjectId resourceFileId, + boolean isDeployed, + List testHeads, + List pflos, + Map testDataTemplate, + Date createdAt, + Date updatedAt, + ObjectId createdBy, + ObjectId updatedBy) { + this.processDefinitionId = processDefinitionId; + this.deploymentId = deploymentId; + this.version = version; + this.bpmnFileId = bpmnFileId; + this.resourceFileId = resourceFileId; + this.isDeployed = isDeployed; + this.testHeads = testHeads; + this.testDataTemplate = testDataTemplate; + this.createdAt = createdAt; + this.updatedAt = updatedAt; + this.createdBy = createdBy; + this.updatedBy = updatedBy; + } + + public String getProcessDefinitionId() { + return processDefinitionId; + } + + public void setProcessDefinitionId(String processDefinitionId) { + this.processDefinitionId = processDefinitionId; + } + + public String getDeploymentId() { + return deploymentId; + } + + public void setDeploymentId(String deploymentId) { + this.deploymentId = deploymentId; + } + + public int getVersion() { + return version; + } + + public void setVersion(int version) { + this.version = version; + } + + public ObjectId getBpmnFileId() { + return bpmnFileId; + } + + public void setBpmnFileId(ObjectId bpmnFileId) { + this.bpmnFileId = bpmnFileId; + } + + public ObjectId getResourceFileId() { + return resourceFileId; + } + + public void setResourceFileId(ObjectId resourceFileId) { + this.resourceFileId = resourceFileId; + } + + public boolean isDeployed() { + return isDeployed; + } + + public void setDeployed(boolean deployed) { + isDeployed = deployed; + } + + public List getTestHeads() { + return testHeads; + } + + public void setTestHeads(List testHeads) { + this.testHeads = testHeads; + } + + public List getPflos() { + return pflos; + } + + public void setPflos(List pflos) { + this.pflos = pflos; + } + + public Map getTestDataTemplate() { + return testDataTemplate; + } + + public void setTestDataTemplate(Map testDataTemplate) { + this.testDataTemplate = testDataTemplate; + } + + public Date getCreatedAt() { + return createdAt; + } + + public void setCreatedAt(Date createdAt) { + this.createdAt = createdAt; + } + + public Date getUpdatedAt() { + return updatedAt; + } + + public void setUpdatedAt(Date updatedAt) { + this.updatedAt = updatedAt; + } + + public ObjectId getCreatedBy() { + return createdBy; + } + + public void setCreatedBy(ObjectId createdBy) { + this.createdBy = createdBy; + } + + public ObjectId getUpdatedBy() { + return updatedBy; + } + + public void setUpdatedBy(ObjectId updatedBy) { + this.updatedBy = updatedBy; + } + + private String getObjectIdString(ObjectId value) { + return value == null ? "\"\"" : "\"" + value.toString() + "\""; + } + + @Override + public String toString() { + return Convert.objectToJson(this); + } +} diff --git a/otf-camunda/src/main/java/org/oran/otf/common/model/local/DMaaPRequest.java b/otf-camunda/src/main/java/org/oran/otf/common/model/local/DMaaPRequest.java new file mode 100644 index 0000000..e294d44 --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/common/model/local/DMaaPRequest.java @@ -0,0 +1,69 @@ +/* Copyright (c) 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.oran.otf.common.model.local; + +import org.oran.otf.common.utility.gson.Convert; +import com.fasterxml.jackson.annotation.JsonProperty; + +public class DMaaPRequest { + private String hostname; + private String asyncTopic; + private boolean requiresProxy; + + public DMaaPRequest() { + } + + public DMaaPRequest( + @JsonProperty(value = "hostname", required = true) String hostname, + @JsonProperty(value = "asyncTopic", required = true) String asyncTopic, + @JsonProperty(value = "requriesProxy", required = false) boolean requiresProxy) { + this.hostname = hostname; + this.asyncTopic = asyncTopic; + this.requiresProxy = requiresProxy; + + } + + public String getHostname() { + return hostname; + } + + public void setHostname(String hostname) { + this.hostname = hostname; + } + + public String getAsyncTopic() { + return asyncTopic; + } + + public void setAsyncTopic(String asyncTopic) { + this.asyncTopic = asyncTopic; + } + + public boolean getRequiresProxy(){ + return this.requiresProxy; + } + + public void setRequiresProxy(boolean requiresProxy) { + this.requiresProxy = requiresProxy; + } + + @Override + public String toString() { + return Convert.objectToJson(this); + } +} + diff --git a/otf-camunda/src/main/java/org/oran/otf/common/model/local/OTFApiResponse.java b/otf-camunda/src/main/java/org/oran/otf/common/model/local/OTFApiResponse.java new file mode 100644 index 0000000..cd8ed5a --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/common/model/local/OTFApiResponse.java @@ -0,0 +1,66 @@ +/* Copyright (c) 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.oran.otf.common.model.local; + +import org.oran.otf.common.utility.gson.Convert; + +import java.util.Date; + +public class OTFApiResponse { + + private int statusCode; + private String message; + private Date time; + + public OTFApiResponse() { + } + + public OTFApiResponse(int statusCode, String message) { + this.statusCode = statusCode; + this.message = message; + this.time = new Date(System.currentTimeMillis()); + } + + public int getStatusCode() { + return statusCode; + } + + public void setStatusCode(int statusCode) { + this.statusCode = statusCode; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public Date getTime() { + return time; + } + + public void setTime(Date time) { + this.time = time; + } + + @Override + public String toString() { + return Convert.objectToJson(this); + } +} diff --git a/otf-camunda/src/main/java/org/oran/otf/common/model/local/OTFDeploymentResponse.java b/otf-camunda/src/main/java/org/oran/otf/common/model/local/OTFDeploymentResponse.java new file mode 100644 index 0000000..59c3dcd --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/common/model/local/OTFDeploymentResponse.java @@ -0,0 +1,67 @@ +/* Copyright (c) 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.oran.otf.common.model.local; + +public class OTFDeploymentResponse { + + private String deploymentId; + private String processDefinitionKey; + private String processDefinitionId; + private int version; + + public OTFDeploymentResponse() { + } + + public OTFDeploymentResponse(String deploymentId, String processDefinitionKey, String processDefinitionId, int version) { + this.deploymentId = deploymentId; + this.processDefinitionKey = processDefinitionKey; + this.processDefinitionId = processDefinitionId; + this.version = version; + } + + public String getDeploymentId() { + return deploymentId; + } + + public void setDeploymentId(String deploymentId) { + this.deploymentId = deploymentId; + } + + public String getProcessDefinitionKey() { + return processDefinitionKey; + } + + public void setProcessDefinitionKey(String processDefinitionKey) { + this.processDefinitionKey = processDefinitionKey; + } + + public String getProcessDefinitionId() { + return processDefinitionId; + } + + public void setProcessDefinitionId(String processDefinitionId) { + this.processDefinitionId = processDefinitionId; + } + + public int getVersion() { + return version; + } + + public void setVersion(int version) { + this.version = version; + } +} diff --git a/otf-camunda/src/main/java/org/oran/otf/common/model/local/OTFProcessInstanceCompletionResponse.java b/otf-camunda/src/main/java/org/oran/otf/common/model/local/OTFProcessInstanceCompletionResponse.java new file mode 100644 index 0000000..dd1ecf6 --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/common/model/local/OTFProcessInstanceCompletionResponse.java @@ -0,0 +1,166 @@ +/* Copyright (c) 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.oran.otf.common.model.local; + +import org.oran.otf.camunda.model.ExecutionConstants; +import org.camunda.bpm.engine.history.*; +import org.camunda.bpm.engine.impl.history.event.HistoricExternalTaskLogEntity; +import org.camunda.bpm.engine.impl.persistence.entity.HistoricJobLogEventEntity; +import org.camunda.bpm.engine.impl.persistence.entity.HistoricVariableInstanceEntity; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class OTFProcessInstanceCompletionResponse implements Serializable { + private HistoricProcessInstance historicProcessInstance; + private List historicActivityInstance; + private List historicIncident; + private List> historicJobLog; + private List> historicExternalTaskLog; + private List> historicVariableInstance; + + public OTFProcessInstanceCompletionResponse() { + } + + + public HistoricProcessInstance getHistoricProcessInstance() { + return historicProcessInstance; + } + + public void setHistoricProcessInstance(HistoricProcessInstance historicProcessInstance) { + this.historicProcessInstance = historicProcessInstance; + } + + public List getHistoricActivityInstance() { + return historicActivityInstance; + } + + public void setHistoricActivityInstance(List historicActivityInstance) { + this.historicActivityInstance = historicActivityInstance; + } + + public List getHistoricIncident() { + return historicIncident; + } + + public void setHistoricIncident(List historicIncident) { + this.historicIncident = historicIncident; + } + + public List> getHistoricJobLog() { + return historicJobLog; + } + + public void setHistoricJobLog(List historicJobLog) { + List> list = new ArrayList>(); + for(HistoricJobLog jobLog: historicJobLog){ + HistoricJobLogEventEntity log = (HistoricJobLogEventEntity) jobLog; + HashMap map = new HashMap(); + + map.put("id", log.getId()); + map.put("executionId", log.getExecutionId()); + map.put("activityId", log.getActivityId()); + map.put("eventType", log.getEventType()); + map.put("sequenceCounter", log.getSequenceCounter()); + map.put("retries", log.getJobRetries()); + map.put("jobExceptionMessage", log.getJobExceptionMessage()); + map.put("jobDefinitionType", log.getJobDefinitionType()); + map.put("jobDefinitionConfiguration", log.getJobDefinitionConfiguration()); + map.put("processDefinitionKey", log.getProcessDefinitionKey()); + map.put("state", convertState(log.getState())); + + list.add(map); + } + this.historicJobLog = list; + } + + public List> getHistoricExternalTaskLog() { + return this.historicExternalTaskLog; + } + + public void setHistoricExternalTaskLog(List historicExternalTaskLog) { + List> list = new ArrayList>(); + for(HistoricExternalTaskLog externalTaskLog: historicExternalTaskLog){ + HistoricExternalTaskLogEntity log = (HistoricExternalTaskLogEntity) externalTaskLog; + HashMap map = new HashMap(); + + map.put("id", log.getId()); + map.put("executionId", log.getExecutionId()); + map.put("activityId", log.getActivityId()); + map.put("state", convertState(log.getState())); + map.put("retries", log.getRetries()); + map.put("processDefinitionKey", log.getProcessDefinitionKey()); + map.put("errorMessage", log.getErrorMessage()); + try { + map.put("errorDetails", log.getErrorDetails()); + } + catch (Exception e){} + map.put("workerId", log.getWorkerId()); + map.put("topic", log.getTopicName()); + list.add(map); + } + this.historicExternalTaskLog = list; + } + + public List> getHistoricVariableInstance() { + return historicVariableInstance; + } + + public void setHistoricVariableInstance(List historicVariableInstance) { + List> list = new ArrayList>(); + for(HistoricVariableInstance variableInstanceEntity: historicVariableInstance){ + HistoricVariableInstanceEntity variable = (HistoricVariableInstanceEntity) variableInstanceEntity; + HashMap map = new HashMap(); + if (variable.getVariableName().equalsIgnoreCase(ExecutionConstants.ExecutionVariable.TEST_EXECUTION)){ + continue; + } + map.put("id", variable.getId()); + map.put("executionId", variable.getExecutionId()); + map.put("processDefinitionKey", variable.getProcessDefinitionKey()); + map.put("taskId", variable.getTaskId()); + map.put("eventType", variable.getVariableName()); + map.put("errorMessage", variable.getErrorMessage()); + map.put("state", variable.getState()); + map.put("variableName", variable.getVariableName()); + map.put("type", variable.getTypedValue().getType()); + map.put("value", variable.getTypedValue().getValue()); + map.put("persistentState", variable.getPersistentState()); + + list.add(map); + } + this.historicVariableInstance = list; + } + + private String convertState(int state){ + switch (state){ + case 0 : + return "CREATED"; + case 1 : + return "FAILED"; + case 2 : + return "SUCCESSFUL"; + case 3 : + return "DELETED"; + default: + return "UNKNOWN"; + } + } + +} diff --git a/otf-camunda/src/main/java/org/oran/otf/common/model/local/ParallelFlowInput.java b/otf-camunda/src/main/java/org/oran/otf/common/model/local/ParallelFlowInput.java new file mode 100644 index 0000000..62ee1c8 --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/common/model/local/ParallelFlowInput.java @@ -0,0 +1,91 @@ +/* Copyright (c) 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.oran.otf.common.model.local; + +import org.oran.otf.camunda.workflow.WorkflowRequest; +import org.oran.otf.common.utility.gson.Convert; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.io.Serializable; +import java.util.List; + +public class ParallelFlowInput implements Serializable { + + private static final long serialVersionUID = 1L; + + private List args; + private boolean interruptOnFailure; + private int maxFailures; + private int threadPoolSize; + + public ParallelFlowInput() { + } + + @JsonCreator + public ParallelFlowInput( + @JsonProperty(value = "args", required = true) List args, + @JsonProperty(value = "interruptOnFailure", required = true) boolean interruptOnFailure, + @JsonProperty(value = "maxFailures", required = true) int maxFailures, + @JsonProperty(value = "threadPoolSize", required = true) int threadPoolSize) { + this.args = args; + this.interruptOnFailure = interruptOnFailure; + this.maxFailures = maxFailures; + this.threadPoolSize = threadPoolSize; + } + + public static long getSerialVersionUID() { + return serialVersionUID; + } + + public List getArgs() { + return args; + } + + public void setArgs(List args) { + this.args = args; + } + + public boolean isInterruptOnFailure() { + return interruptOnFailure; + } + + public void setInterruptOnFailure(boolean interruptOnFailure) { + this.interruptOnFailure = interruptOnFailure; + } + + public int getMaxFailures() { + return maxFailures; + } + + public void setMaxFailures(int maxFailures) { + this.maxFailures = maxFailures; + } + + public int getThreadPoolSize() { + return threadPoolSize; + } + + public void setThreadPoolSize(int threadPoolSize) { + this.threadPoolSize = threadPoolSize; + } + + @Override + public String toString() { + return Convert.objectToJson(this); + } +} diff --git a/otf-camunda/src/main/java/org/oran/otf/common/model/local/PfloNode.java b/otf-camunda/src/main/java/org/oran/otf/common/model/local/PfloNode.java new file mode 100644 index 0000000..f70b8a6 --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/common/model/local/PfloNode.java @@ -0,0 +1,62 @@ +/* Copyright (c) 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.oran.otf.common.model.local; + +import org.oran.otf.common.utility.gson.Convert; + +import java.io.Serializable; + +public class PfloNode implements Serializable { + + private static final long serialVersionUID = 1L; + + private String bpmnPlfoTaskId; + private String label; + + public PfloNode() { + } + + public PfloNode(String bpmnPlfoTaskId, String label) { + this.bpmnPlfoTaskId = bpmnPlfoTaskId; + this.label = label; + } + + public static long getSerialVersionUID() { + return serialVersionUID; + } + + public String getBpmnPlfoTaskId() { + return bpmnPlfoTaskId; + } + + public void setBpmnPlfoTaskId(String bpmnPlfoTaskId) { + this.bpmnPlfoTaskId = bpmnPlfoTaskId; + } + + public String getLabel() { + return label; + } + + public void setLabel(String label) { + this.label = label; + } + + @Override + public String toString() { + return Convert.objectToJson(this); + } +} diff --git a/otf-camunda/src/main/java/org/oran/otf/common/model/local/TestHeadNode.java b/otf-camunda/src/main/java/org/oran/otf/common/model/local/TestHeadNode.java new file mode 100644 index 0000000..99ed995 --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/common/model/local/TestHeadNode.java @@ -0,0 +1,58 @@ +/* Copyright (c) 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.oran.otf.common.model.local; + +import org.oran.otf.common.utility.gson.Convert; +import java.io.Serializable; +import org.bson.types.ObjectId; + +public class TestHeadNode implements Serializable { + + private static final long serialVersionUID = 1L; + + private ObjectId testHeadId; + private String bpmnVthTaskId; + + public TestHeadNode() { + } + + public TestHeadNode(ObjectId testHeadId, String taskId) { + this.testHeadId = testHeadId; + this.bpmnVthTaskId = taskId; + } + + public ObjectId getTestHeadId() { + return testHeadId; + } + + public void setTestHeadId(ObjectId testHeadId) { + this.testHeadId = testHeadId; + } + + public String getBpmnVthTaskId() { + return bpmnVthTaskId; + } + + public void setBpmnVthTaskId(String bpmnVthTaskId) { + this.bpmnVthTaskId = bpmnVthTaskId; + } + + @Override + public String toString() { + return Convert.objectToJson(this); + } +} diff --git a/otf-camunda/src/main/java/org/oran/otf/common/model/local/TestHeadRequest.java b/otf-camunda/src/main/java/org/oran/otf/common/model/local/TestHeadRequest.java new file mode 100644 index 0000000..5bebd80 --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/common/model/local/TestHeadRequest.java @@ -0,0 +1,53 @@ +/* Copyright (c) 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.oran.otf.common.model.local; + +import java.io.Serializable; +import java.util.Map; + +public class TestHeadRequest implements Serializable { + private static final long serialVersionUID = 1L; + private Map headers; + private Map body; + + public TestHeadRequest(){} + + public TestHeadRequest(Map headers, + Map body) { + this.headers = headers; + this.body = body; + } + + public Map getHeaders() { + return headers; + } + + public void setHeaders(Map headers) { + this.headers = headers; + } + + public Map getBody() { + return body; + } + + public void setBody(Map body) { + this.body = body; + } + + + +} diff --git a/otf-camunda/src/main/java/org/oran/otf/common/model/local/TestHeadResult.java b/otf-camunda/src/main/java/org/oran/otf/common/model/local/TestHeadResult.java new file mode 100644 index 0000000..33746c1 --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/common/model/local/TestHeadResult.java @@ -0,0 +1,145 @@ +/* Copyright (c) 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.oran.otf.common.model.local; + +import org.oran.otf.common.utility.gson.Convert; +import java.io.Serializable; +import java.util.Date; +import java.util.Map; +import org.bson.types.ObjectId; + +public class TestHeadResult implements Serializable { + + private static final long serialVersionUID = 1L; + + private ObjectId testHeadId; + private String testHeadName; + private ObjectId testHeadGroupId; + private String bpmnVthTaskId; + + //TODO: RG Remove maps below, setters and getters to return to normal + //private Map testHeadHeaders; + //private int testHeadCode; + private int statusCode; + + private TestHeadRequest testHeadRequest; + private Map testHeadResponse; + private Date startTime; + private Date endTime; + + public TestHeadResult() { + } + + public TestHeadResult( + ObjectId testHeadId, + String testHeadName, + ObjectId testHeadGroupId, + String bpmnVthTaskId, + + //TODO: RG changed code to int and changed testHeadRequest from Map to RequestContent + int statusCode, + + TestHeadRequest testHeadRequest, + Map testHeadResponse, + Date startTime, + Date endTime) { + this.testHeadId = testHeadId; + this.testHeadName = testHeadName; + this.testHeadGroupId = testHeadGroupId; + this.bpmnVthTaskId = bpmnVthTaskId; + + //this.testHeadHeaders = testHeadHeaders; + this.statusCode = statusCode; + + this.testHeadRequest = testHeadRequest; + this.testHeadResponse = testHeadResponse; + this.startTime = startTime; + this.endTime = endTime; + } + + public int getStatusCode(){return statusCode;} + public void setStatusCode(int testHeadCode){this.statusCode = statusCode;} + + public ObjectId getTestHeadId() { + return testHeadId; + } + + public void setTestHeadId(ObjectId testHeadId) { + this.testHeadId = testHeadId; + } + + public String getTestHeadName() { + return testHeadName; + } + + public void setTestHeadName(String testHeadName) { + this.testHeadName = testHeadName; + } + + public ObjectId getTestHeadGroupId() { + return testHeadGroupId; + } + + public void setTestHeadGroupId(ObjectId testHeadGroupId) { + this.testHeadGroupId = testHeadGroupId; + } + + public String getBpmnVthTaskId() { + return bpmnVthTaskId; + } + + public void setBpmnVthTaskId(String bpmnVthTaskId) { + this.bpmnVthTaskId = bpmnVthTaskId; + } + + public TestHeadRequest getTestHeadRequest() { + return testHeadRequest; + } + + public void setTestHeadRequest(TestHeadRequest testHeadRequest) { + this.testHeadRequest = testHeadRequest; + } + + public Map getTestHeadResponse() { + return testHeadResponse; + } + + public void setTestHeadResponse(Map testHeadResponse) { + this.testHeadResponse = testHeadResponse; + } + + public Date getStartTime() { + return startTime; + } + + public void setStartTime(Date startTime) { + this.startTime = startTime; + } + + public Date getEndTime() { + return endTime; + } + + public void setEndTime(Date endTime) { + this.endTime = endTime; + } + + @Override + public String toString() { + return Convert.objectToJson(this); + } +} diff --git a/otf-camunda/src/main/java/org/oran/otf/common/model/local/UserGroup.java b/otf-camunda/src/main/java/org/oran/otf/common/model/local/UserGroup.java new file mode 100644 index 0000000..b103f1e --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/common/model/local/UserGroup.java @@ -0,0 +1,56 @@ +/* Copyright (c) 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.oran.otf.common.model.local; + +import org.oran.otf.common.utility.gson.Convert; +import java.io.Serializable; +import java.util.List; +import org.bson.types.ObjectId; + +public class UserGroup implements Serializable { + + private static final long serialVersionUID = 1L; + + private ObjectId groupId; + private List permissions; + + public UserGroup(ObjectId groupId, List permissions) { + this.groupId = groupId; + this.permissions = permissions; + } + + public ObjectId getGroupId() { + return groupId; + } + + public void setGroupId(ObjectId groupId) { + this.groupId = groupId; + } + + public List getPermissions() { + return permissions; + } + + public void setPermissions(List permissions) { + this.permissions = permissions; + } + + @Override + public String toString() { + return Convert.objectToJson(this); + } +} diff --git a/otf-camunda/src/main/java/org/oran/otf/common/repository/GroupRepository.java b/otf-camunda/src/main/java/org/oran/otf/common/repository/GroupRepository.java new file mode 100644 index 0000000..1876651 --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/common/repository/GroupRepository.java @@ -0,0 +1,29 @@ +/* Copyright (c) 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.oran.otf.common.repository; + +import org.oran.otf.common.model.Group; +import org.bson.types.ObjectId; +import org.springframework.data.mongodb.repository.MongoRepository; +import org.springframework.data.mongodb.repository.Query; + +import java.util.List; + +public interface GroupRepository extends MongoRepository { + @Query("{ 'members.userId': ?0 }") + public List findAllByMembersId(ObjectId membersUserId); +} diff --git a/otf-camunda/src/main/java/org/oran/otf/common/repository/TestDefinitionRepository.java b/otf-camunda/src/main/java/org/oran/otf/common/repository/TestDefinitionRepository.java new file mode 100644 index 0000000..fa89a93 --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/common/repository/TestDefinitionRepository.java @@ -0,0 +1,25 @@ +/* Copyright (c) 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.oran.otf.common.repository; + +import org.oran.otf.common.model.TestDefinition; +import java.util.Optional; +import org.springframework.data.mongodb.repository.MongoRepository; + +public interface TestDefinitionRepository extends MongoRepository { + Optional findByProcessDefinitionKey(String processDefinitionKey); +} diff --git a/otf-camunda/src/main/java/org/oran/otf/common/repository/TestExecutionRepository.java b/otf-camunda/src/main/java/org/oran/otf/common/repository/TestExecutionRepository.java new file mode 100644 index 0000000..5122fea --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/common/repository/TestExecutionRepository.java @@ -0,0 +1,25 @@ +/* Copyright (c) 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.oran.otf.common.repository; + +import org.oran.otf.common.model.TestExecution; +import java.util.Optional; +import org.springframework.data.mongodb.repository.MongoRepository; + +public interface TestExecutionRepository extends MongoRepository { + Optional findFirstByProcessInstanceId(String processInstanceId); +} diff --git a/otf-camunda/src/main/java/org/oran/otf/common/repository/TestHeadRepository.java b/otf-camunda/src/main/java/org/oran/otf/common/repository/TestHeadRepository.java new file mode 100644 index 0000000..126d00f --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/common/repository/TestHeadRepository.java @@ -0,0 +1,24 @@ +/* Copyright (c) 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.oran.otf.common.repository; + +import org.oran.otf.common.model.TestHead; +import org.springframework.data.mongodb.repository.MongoRepository; + +public interface TestHeadRepository extends MongoRepository { + +} diff --git a/otf-camunda/src/main/java/org/oran/otf/common/repository/TestInstanceRepository.java b/otf-camunda/src/main/java/org/oran/otf/common/repository/TestInstanceRepository.java new file mode 100644 index 0000000..b073155 --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/common/repository/TestInstanceRepository.java @@ -0,0 +1,35 @@ +/* Copyright (c) 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.oran.otf.common.repository; + +import org.oran.otf.common.model.TestInstance; +import java.util.List; +import java.util.Optional; +import org.bson.types.ObjectId; +import org.springframework.data.mongodb.repository.MongoRepository; +import org.springframework.data.mongodb.repository.Query; + +public interface TestInstanceRepository extends MongoRepository { + Optional findByTestInstanceName(String testInstanceName); + + @Query("{ 'testDefinitionId': ?0 }") + List findAllByTestDefinitionId(ObjectId testDefinitionId); + + @Query("{ 'testDefinitionId': ?0, 'processDefinitionId': ?1 }") + List findAllByTestDefinitionIdAndPDId( + ObjectId testDefinitionId, String processDefinitionId); +} diff --git a/otf-camunda/src/main/java/org/oran/otf/common/repository/UserRepository.java b/otf-camunda/src/main/java/org/oran/otf/common/repository/UserRepository.java new file mode 100644 index 0000000..5dd669f --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/common/repository/UserRepository.java @@ -0,0 +1,25 @@ +/* Copyright (c) 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.oran.otf.common.repository; + +import org.oran.otf.common.model.User; +import java.util.Optional; +import org.springframework.data.mongodb.repository.MongoRepository; + +public interface UserRepository extends MongoRepository { + Optional findFirstByEmail(String email); +} diff --git a/otf-camunda/src/main/java/org/oran/otf/common/utility/Utility.java b/otf-camunda/src/main/java/org/oran/otf/common/utility/Utility.java new file mode 100644 index 0000000..5d7798b --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/common/utility/Utility.java @@ -0,0 +1,70 @@ +/* Copyright (c) 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.oran.otf.common.utility; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.common.base.Strings; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +public class Utility { + + public static String getLoggerPrefix() { + return "[" + Thread.currentThread().getStackTrace()[2].getMethodName() + "]: "; + } + + public static Map toMap(Object obj) throws Exception { + ObjectMapper mapper = new ObjectMapper(); + return mapper.convertValue(obj, HashMap.class); + } + + public static boolean isCollection(Object obj) { + return obj.getClass().isArray() || obj instanceof Collection; + } + + public static List toList(Object obj) { + if (obj == null) { + throw new NullPointerException("Argument cannot be null."); + } + + List list = new ArrayList<>(); + if (obj.getClass().isArray()) { + list = Arrays.asList((Object[]) obj); + } else if (obj instanceof Collection) { + list = new ArrayList<>((Collection) obj); + } + + return list; + } + + public static boolean isValidUuid(String str) { + if (Strings.isNullOrEmpty(str)) { + return false; + } + try { + UUID uuid = UUID.fromString(str); + return uuid.toString().equalsIgnoreCase(str); + } catch (IllegalArgumentException iae) { + return false; + } + } +} diff --git a/otf-camunda/src/main/java/org/oran/otf/common/utility/database/Generic.java b/otf-camunda/src/main/java/org/oran/otf/common/utility/database/Generic.java new file mode 100644 index 0000000..5de5043 --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/common/utility/database/Generic.java @@ -0,0 +1,36 @@ +/* Copyright (c) 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.oran.otf.common.utility.database; + +import java.util.Optional; +import org.bson.types.ObjectId; +import org.springframework.data.mongodb.repository.MongoRepository; + +public class Generic { + + public static boolean identifierExistsInCollection( + MongoRepository repository, ObjectId identifier) { + return repository.findById(identifier.toString()).isPresent(); + } + + public static T findByIdGeneric(MongoRepository repository, ObjectId identifier) { + Optional optionalObj = repository.findById(identifier.toString()); + return optionalObj.orElse(null); + } + + +} diff --git a/otf-camunda/src/main/java/org/oran/otf/common/utility/database/TestExecutionUtility.java b/otf-camunda/src/main/java/org/oran/otf/common/utility/database/TestExecutionUtility.java new file mode 100644 index 0000000..ba236cb --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/common/utility/database/TestExecutionUtility.java @@ -0,0 +1,35 @@ +/* Copyright (c) 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.oran.otf.common.utility.database; + +import org.oran.otf.common.model.TestExecution; +import com.mongodb.client.result.UpdateResult; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.query.Criteria; +import org.springframework.data.mongodb.core.query.Query; +import org.springframework.data.mongodb.core.query.Update; + +public class TestExecutionUtility { + + public static void saveTestResult(MongoTemplate mongoOperation, TestExecution execution, String testResult){ + Query query = new Query(); + query.addCriteria(Criteria.where("businessKey").is(execution.getBusinessKey())); + Update update = new Update(); + update.set("testResult", testResult); + UpdateResult result = mongoOperation.updateFirst(query, update, TestExecution.class); + } +} diff --git a/otf-camunda/src/main/java/org/oran/otf/common/utility/gson/Convert.java b/otf-camunda/src/main/java/org/oran/otf/common/utility/gson/Convert.java new file mode 100644 index 0000000..fb1e55f --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/common/utility/gson/Convert.java @@ -0,0 +1,121 @@ +/* Copyright (c) 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.oran.otf.common.utility.gson; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonParseException; +import com.google.gson.JsonPrimitive; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSerializer; +import com.google.gson.reflect.TypeToken; + +import java.io.IOException; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.bson.types.ObjectId; + +public class Convert { + + private static final GsonBuilder gsonBuilder = + new GsonBuilder() + .setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ") + .registerTypeAdapter( + ObjectId.class, + new JsonSerializer() { + @Override + public JsonElement serialize( + ObjectId src, Type typeOfSrc, JsonSerializationContext context) { + return new JsonPrimitive(src.toHexString()); + } + }) + .registerTypeAdapter( + ObjectId.class, + new JsonDeserializer() { + @Override + public ObjectId deserialize( + JsonElement json, Type typeOfT, JsonDeserializationContext context) + throws JsonParseException { + return new ObjectId(json.getAsString()); + } + }); + + public static Gson getGson() { + return gsonBuilder.create(); + } + + public static String mapToJson(Map map) { + if (map.isEmpty()) { + return "{}"; + } + return getGson().toJson(map); + } + + public static String listToJson(List list) { + if (list.isEmpty()) { + return "[]"; + } + return getGson().toJson(list); + } + + public static Map jsonToMap(String json) { + Type type = new TypeToken>() { + }.getType(); + return getGson().fromJson(json, type); + } + + public static String objectToJson(Object obj) { + return getGson().toJson(obj); + } + + public static T jsonToObject(String json, TypeReference typeReference) throws IOException { + ObjectMapper objectMapper = new ObjectMapper(); + objectMapper + .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true); + return objectMapper.readValue(json, typeReference); + } + + public static T mapToObject(Map map, TypeReference typeReference) throws IOException { + return jsonToObject(mapToJson(map), typeReference); + } + + public static T listToObjectList(List list, TypeReference typeReference) throws IOException { + return jsonToObject(listToJson(list), typeReference); + } + + public static List convertObjectToList(Object obj) { + List list = new ArrayList<>(); + if (obj.getClass().isArray()) { + list = Arrays.asList((Object[])obj); + } else if (obj instanceof Collection) { + list = new ArrayList<>((Collection)obj); + } + return list; + } + +} diff --git a/otf-camunda/src/main/java/org/oran/otf/common/utility/http/HeadersUtility.java b/otf-camunda/src/main/java/org/oran/otf/common/utility/http/HeadersUtility.java new file mode 100644 index 0000000..be6ae88 --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/common/utility/http/HeadersUtility.java @@ -0,0 +1,42 @@ +/* Copyright (c) 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.oran.otf.common.utility.http; + +import com.google.gson.Gson; +import java.util.Map; + +public class HeadersUtility { + public static Map maskAuth(Map headers){ + //Deep copy headers to avoid changing original + Gson gson = new Gson(); + String jsonString = gson.toJson(headers); + Map maskedHeaders = gson.fromJson(jsonString, Map.class); + + if(maskedHeaders.containsKey("Authorization")) { + String[] auth = maskedHeaders.get("Authorization").split(" "); + if(auth.length>1) { + auth[1] = "****"; + maskedHeaders.put("Authorization", auth[0] + " " + auth[1]); + } + else{ + maskedHeaders.put("Authorization", "****"); + } + } + return maskedHeaders; + } + +} diff --git a/otf-camunda/src/main/java/org/oran/otf/common/utility/http/RequestUtility.java b/otf-camunda/src/main/java/org/oran/otf/common/utility/http/RequestUtility.java new file mode 100644 index 0000000..8cd2eff --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/common/utility/http/RequestUtility.java @@ -0,0 +1,195 @@ +/* Copyright (c) 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.oran.otf.common.utility.http; + +import com.google.common.base.Strings; +import java.io.UnsupportedEncodingException; +import java.util.HashMap; +import java.util.Map; +import java.util.Timer; +import java.util.TimerTask; +import java.util.concurrent.Future; +import org.apache.http.HttpHost; +import org.apache.http.HttpResponse; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpRequestBase; +import org.apache.http.client.protocol.HttpClientContext; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.nio.client.CloseableHttpAsyncClient; +import org.apache.http.impl.nio.client.HttpAsyncClients; +import org.apache.http.protocol.BasicHttpContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class RequestUtility { + + private static final Logger logger = LoggerFactory.getLogger(RequestUtility.class); + + public static void postAsync(String url, String body, Map headers, Boolean proxy) + throws Exception { + HttpPost post = buildPost(url, body, headers); + executeAsync(post, proxy); + } + + public static HttpResponse postSync( + String url, String body, Map headers, Boolean proxy) throws Exception { + HttpPost post = buildPost(url, body, headers); + return executeSync(post, proxy); + } + + public static HttpResponse postSync( + String url, String body, Map headers, int timeoutInMillis, Boolean proxy) + throws Exception { + HttpPost post = buildPost(url, body, headers); + return executeSync(post, timeoutInMillis, proxy); + } + + public static HttpResponse getSync(String url, Map headers, Boolean proxy) + throws Exception { + HttpGet get = buildGet(url, headers); + return executeSync(get, proxy); + } + + public static HttpResponse getSync( + String url, Map headers, int timeoutInMillis, Boolean proxy) + throws Exception { + if (timeoutInMillis < 0) { + throw new IllegalArgumentException("The timeoutInMillis must be a value greater than 0."); + } + + HttpGet get = buildGet(url, headers); + return executeSync(get, timeoutInMillis, proxy); + } + + public static void getAsync(String url, Map headers, Boolean proxy) + throws Exception { + HttpGet get = buildGet(url, headers); + executeAsync(get, proxy); + } + + private static HttpPost buildPost(String url, String body, Map headers) + throws UnsupportedEncodingException { + if (Strings.isNullOrEmpty(url) || Strings.isNullOrEmpty(body)) { + return null; + } else if (headers == null) { + headers = new HashMap<>(); + } + + HttpPost post = new HttpPost(url); + headers.forEach(post::setHeader); + post.setEntity(new StringEntity(body)); + return post; + } + + private static HttpGet buildGet(String url, Map headers) { + if (Strings.isNullOrEmpty(url)) { + return null; + } else if (headers == null) { + headers = new HashMap<>(); + } + + HttpGet get = new HttpGet(url); + headers.forEach(get::setHeader); + return get; + } + + private static HttpResponse executeSync(HttpRequestBase request, Boolean proxy) throws Exception { + CloseableHttpAsyncClient httpClient = createHttpAsyncClient(); + try { + httpClient.start(); + Future future = + proxy + ? httpClient.execute(request, createHttpClientContext(), null) + : httpClient.execute(request, null); + return future.get(); + } catch (Exception e) { + throw e; + } finally { + httpClient.close(); + } + } + + private static HttpResponse executeSync( + HttpRequestBase request, int timeoutInMillis, Boolean proxy) throws Exception { + if (timeoutInMillis < 0) { + throw new IllegalArgumentException("The timeoutInMillis must be a value greater than 0."); + } + + // Create a timer task that will abort the task (the request) after the specified time. This + // task will run *timeoutInMillis* ms + TimerTask task = + new TimerTask() { + @Override + public void run() { + if (request != null) { + request.abort(); + } + } + }; + + CloseableHttpAsyncClient httpClient = createHttpAsyncClient(); + try { + httpClient.start(); + // Start the timer before making the request. + new Timer(true).schedule(task, timeoutInMillis); + Future future = + proxy + ? httpClient.execute(request, createHttpClientContext(), null) + : httpClient.execute(request, null); + + return future.get(); + } catch (Exception e) { + throw e; + } finally { + httpClient.close(); + } + } + + private static void executeAsync(HttpRequestBase request, Boolean proxy) throws Exception { + CloseableHttpAsyncClient httpClient = createHttpAsyncClient(); + try { + httpClient.start(); + Future future = + proxy + ? httpClient.execute(request, createHttpClientContext(), null) + : httpClient.execute(request, null); + logger.debug("Sent asynchronous request."); + } catch (Exception e) { + throw e; + } finally { + httpClient.close(); + } + } + + private static RequestConfig configureProxy() { + HttpHost proxy; + proxy = new HttpHost("localhost", 8080, "http"); + return RequestConfig.custom().setProxy(proxy).build(); + } + + private static HttpClientContext createHttpClientContext() { + HttpClientContext localContext = HttpClientContext.adapt(new BasicHttpContext()); + localContext.setRequestConfig(configureProxy()); + return localContext; + } + + private static CloseableHttpAsyncClient createHttpAsyncClient() throws Exception { + return HttpAsyncClients.createDefault(); + } +} diff --git a/otf-camunda/src/main/java/org/oran/otf/common/utility/http/ResponseUtility.java b/otf-camunda/src/main/java/org/oran/otf/common/utility/http/ResponseUtility.java new file mode 100644 index 0000000..abe1e0b --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/common/utility/http/ResponseUtility.java @@ -0,0 +1,107 @@ +/* Copyright (c) 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.oran.otf.common.utility.http; + +import org.oran.otf.common.model.local.OTFApiResponse; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +public class ResponseUtility { + + public static class Build { + + public static Response okRequest() { + return Response.ok().build(); + } + + public static Response badRequest() { + return Response.status(400).build(); + } + + public static Response okRequestWithMessage(String msg) { + return Response.status(200) + .type(MediaType.APPLICATION_JSON) + .entity(new OTFApiResponse(200, msg)) + .build(); + } + + public static Response okRequestWithObject(Object obj) { + return Response.status(200) + .type(MediaType.APPLICATION_JSON) + .entity(obj) + .build(); + } + + public static Response badRequestWithMessage(String msg) { + return Response.status(400) + .type(MediaType.APPLICATION_JSON) + .entity(new OTFApiResponse(400, msg)) + .build(); + } + + public static Response internalServerError() { + return Response.status(500).build(); + } + + public static Response internalServerErrorWithMessage(String msg) { + return Response.status(500) + .type(MediaType.APPLICATION_JSON) + .entity(new OTFApiResponse(500, msg)) + .build(); + } + + public static Response unauthorized() { + return Response.status(401).build(); + } + + public static Response unauthorizedWithMessage(String msg) { + return Response.status(401) + .type(MediaType.APPLICATION_JSON) + .entity(new OTFApiResponse(401, msg)) + .build(); + } + + public static Response notFound() { + return Response.status(404).build(); + } + + public static Response notFoundWithMessage(String msg) { + return Response.status(404) + .type(MediaType.APPLICATION_JSON) + .entity(new OTFApiResponse(404, msg)) + .build(); + } + + public static Response genericWithCode(int code) { + return Response.status(code).build(); + } + + public static Response genericWithMessage(int code, String msg) { + return Response.status(code) + .type(MediaType.APPLICATION_JSON) + .entity(new OTFApiResponse(code, msg)) + .build(); + } + + public static Response genericWithObject(int code, Object obj) { + return Response.status(code) + .type(MediaType.APPLICATION_JSON) + .entity(obj) + .build(); + } + } +} diff --git a/otf-camunda/src/main/java/org/oran/otf/common/utility/logger/ErrorCode.java b/otf-camunda/src/main/java/org/oran/otf/common/utility/logger/ErrorCode.java new file mode 100644 index 0000000..8327a81 --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/common/utility/logger/ErrorCode.java @@ -0,0 +1,36 @@ +/* Copyright (c) 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.oran.otf.common.utility.logger; + +public enum ErrorCode { + PermissionError(100), + AvailabilityError(200), + DataError(300), + SchemaError(400), + BusinessProcesssError(500), + UnknownError(900); + + private int value; + + ErrorCode(int value) { + this.value = value; + } + + public int getValue() { + return this.value; + } +} diff --git a/otf-camunda/src/main/java/org/oran/otf/common/utility/logger/LoggerStartupListener.java b/otf-camunda/src/main/java/org/oran/otf/common/utility/logger/LoggerStartupListener.java new file mode 100644 index 0000000..10c45d8 --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/common/utility/logger/LoggerStartupListener.java @@ -0,0 +1,91 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP - SO + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Modifications Copyright (c) 2019 Samsung + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.oran.otf.common.utility.logger; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.spi.LoggerContextListener; +import ch.qos.logback.core.Context; +import ch.qos.logback.core.spi.ContextAwareBase; +import ch.qos.logback.core.spi.LifeCycle; +import java.net.InetAddress; +import java.net.UnknownHostException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +@Component +public class LoggerStartupListener extends ContextAwareBase + implements LoggerContextListener, LifeCycle { + + private static final Logger logger = LoggerFactory.getLogger(LoggerStartupListener.class); + private boolean started = false; + + @Override + public void start() { + if (started) { + return; + } + InetAddress addr = null; + try { + addr = InetAddress.getLocalHost(); + } catch (UnknownHostException e) { + logger.error("UnknownHostException", e); + } + Context context = getContext(); + if (addr != null) { + context.putProperty("server.name", addr.getHostName()); + } + started = true; + } + + @Override + public void stop() { + } + + @Override + public boolean isStarted() { + return started; + } + + @Override + public boolean isResetResistant() { + return true; + } + + @Override + public void onReset(LoggerContext arg0) { + } + + @Override + public void onStart(LoggerContext arg0) { + } + + @Override + public void onStop(LoggerContext arg0) { + } + + @Override + public void onLevelChange(ch.qos.logback.classic.Logger logger, Level level) { + } +} diff --git a/otf-camunda/src/main/java/org/oran/otf/common/utility/logger/MessageEnum.java b/otf-camunda/src/main/java/org/oran/otf/common/utility/logger/MessageEnum.java new file mode 100644 index 0000000..1103c53 --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/common/utility/logger/MessageEnum.java @@ -0,0 +1,35 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP - SO + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.oran.otf.common.utility.logger; + + +public enum MessageEnum { + // Api Handler Messages + APIH_REQUEST_NULL, APIH_QUERY_FOUND, APIH_QUERY_NOT_FOUND, APIH_QUERY_PARAM_WRONG, APIH_DB_ACCESS_EXC, APIH_DB_ACCESS_EXC_REASON, APIH_VALIDATION_ERROR, APIH_REQUEST_VALIDATION_ERROR, APIH_SERVICE_VALIDATION_ERROR, APIH_GENERAL_EXCEPTION_ARG, APIH_GENERAL_EXCEPTION, APIH_GENERAL_WARNING, APIH_AUDIT_EXEC, APIH_GENERAL_METRICS, APIH_DUPLICATE_CHECK_EXC, APIH_DUPLICATE_FOUND, APIH_BAD_ORDER, APIH_DB_ATTRIBUTE_NOT_FOUND, APIH_BPEL_COMMUNICATE_ERROR, APIH_BPEL_RESPONSE_ERROR, APIH_WARP_REQUEST, APIH_ERROR_FROM_BPEL_SERVER, APIH_DB_INSERT_EXC, APIH_DB_UPDATE_EXC, APIH_NO_PROPERTIES, APIH_PROPERTY_LOAD_SUC, APIH_LOAD_PROPERTIES_FAIL, APIH_SDNC_COMMUNICATE_ERROR, APIH_SDNC_RESPONSE_ERROR, APIH_CANNOT_READ_SCHEMA, APIH_HEALTH_CHECK_EXCEPTION, APIH_REQUEST_VALIDATION_ERROR_REASON, APIH_JAXB_MARSH_ERROR, APIH_JAXB_UNMARSH_ERROR, APIH_VNFREQUEST_VALIDATION_ERROR, APIH_DOM2STR_ERROR, APIH_READ_VNFOUTPUT_CLOB_EXCEPTION, APIH_DUPLICATE_CHECK_EXC_ATT, APIH_GENERATED_REQUEST_ID, APIH_GENERATED_SERVICE_INSTANCE_ID, APIH_REPLACE_REQUEST_ID, + // Resource Adapter Messages + RA_GENERAL_EXCEPTION_ARG, RA_GENERAL_EXCEPTION, RA_GENERAL_WARNING, RA_MISSING_PARAM, RA_AUDIT_EXEC, RA_GENERAL_METRICS, RA_CREATE_STACK_TIMEOUT, RA_DELETE_STACK_TIMEOUT, RA_UPDATE_STACK_TIMEOUT, RA_CONNECTION_EXCEPTION, RA_PARSING_ERROR, RA_PROPERTIES_NOT_FOUND, RA_LOAD_PROPERTIES_SUC, RA_NETWORK_ALREADY_EXIST, RA_UPDATE_NETWORK_ERR, RA_CREATE_STACK_ERR, RA_UPDATE_STACK_ERR, RA_CREATE_TENANT_ERR, RA_NETWORK_NOT_FOUND, RA_NETWORK_ORCHE_MODE_NOT_SUPPORT, RA_CREATE_NETWORK_EXC, RA_NS_EXC, RA_PARAM_NOT_FOUND, RA_CONFIG_EXC, RA_UNKOWN_PARAM, RA_VLAN_PARSE, RA_DELETE_NETWORK_EXC, RA_ROLLBACK_NULL, RA_TENANT_NOT_FOUND, RA_QUERY_NETWORK_EXC, RA_CREATE_NETWORK_NOTIF_EXC, RA_ASYNC_ROLLBACK, RA_WSDL_NOT_FOUND, RA_WSDL_URL_CONVENTION_EXC, RA_INIT_NOTIF_EXC, RA_SET_CALLBACK_AUTH_EXC, RA_FAULT_INFO_EXC, RA_MARSHING_ERROR, RA_PARSING_REQUEST_ERROR, RA_SEND_REQUEST_SDNC, RA_RESPONSE_FROM_SDNC, RA_EXCEPTION_COMMUNICATE_SDNC, RA_EVALUATE_XPATH_ERROR, RA_ANALYZE_ERROR_EXC, RA_ERROR_GET_RESPONSE_SDNC, RA_CALLBACK_BPEL, RA_INIT_CALLBACK_WSDL_ERR, RA_CALLBACK_BPEL_EXC, RA_CALLBACK_BPEL_COMPLETE, RA_SDNC_MISS_CONFIG_PARAM, RA_SDNC_INVALID_CONFIG, RA_PRINT_URL, RA_ERROR_CREATE_SDNC_REQUEST, RA_ERROR_CREATE_SDNC_RESPONSE, RA_ERROR_CONVERT_XML2STR, RA_RECEIVE_SDNC_NOTIF, RA_INIT_SDNC_ADAPTER, RA_SEND_REQUEST_APPC_ERR, RA_SEND_REQUEST_SDNC_ERR, RA_RECEIVE_BPEL_REQUEST, RA_TENANT_ALREADY_EXIST, RA_UPDATE_TENANT_ERR, RA_DELETE_TEMAMT_ERR, RA_ROLLBACK_TENANT_ERR, RA_QUERY_VNF_ERR, RA_VNF_ALREADY_EXIST, RA_VNF_UNKNOWN_PARAM, RA_VNF_EXTRA_PARAM, RA_CREATE_VNF_ERR, RA_VNF_NOT_EXIST, RA_UPDATE_VNF_ERR, RA_DELETE_VNF_ERR, RA_ASYNC_CREATE_VNF, RA_SEND_VNF_NOTIF_ERR, RA_ASYNC_CREATE_VNF_COMPLETE, RA_ASYNC_UPDATE_VNF, RA_ASYNC_UPDATE_VNF_COMPLETE, RA_ASYNC_QUERY_VNF, RA_ASYNC_QUERY_VNF_COMPLETE, RA_ASYNC_DELETE_VNF, RA_ASYNC_DELETE_VNF_COMPLETE, RA_ASYNC_ROLLBACK_VNF, RA_ASYNC_ROLLBACK_VNF_COMPLETE, RA_ROLLBACK_VNF_ERR, RA_DB_INVALID_STATUS, RA_CANT_UPDATE_REQUEST, RA_DB_REQUEST_NOT_EXIST, RA_CONFIG_NOT_FOUND, RA_CONFIG_LOAD, RA_RECEIVE_WORKFLOW_MESSAGE, + // BPEL engine Messages + BPMN_GENERAL_INFO, BPMN_GENERAL_EXCEPTION_ARG, BPMN_GENERAL_EXCEPTION, BPMN_GENERAL_WARNING, BPMN_AUDIT_EXEC, BPMN_GENERAL_METRICS, BPMN_URN_MAPPING_FAIL, BPMN_VARIABLE_NULL, BPMN_CALLBACK_EXCEPTION, + // ASDC Messages + ASDC_GENERAL_EXCEPTION_ARG, ASDC_GENERAL_EXCEPTION, ASDC_GENERAL_WARNING, ASDC_GENERAL_INFO, ASDC_AUDIT_EXEC, ASDC_GENERAL_METRICS, ASDC_CREATE_SERVICE, ASDC_ARTIFACT_ALREADY_DEPLOYED, ASDC_CREATE_ARTIFACT, ASDC_ARTIFACT_INSTALL_EXC, ASDC_ARTIFACT_ALREADY_DEPLOYED_DETAIL, ASDC_ARTIFACT_NOT_DEPLOYED_DETAIL, ASDC_ARTIFACT_CHECK_EXC, ASDC_INIT_ASDC_CLIENT_EXC, ASDC_INIT_ASDC_CLIENT_SUC, ASDC_LOAD_ASDC_CLIENT_EXC, ASDC_SINGLETON_CHECKT_EXC, ASDC_SHUTDOWN_ASDC_CLIENT_EXC, ASDC_CHECK_HEAT_TEMPLATE, ASDC_START_INSTALL_ARTIFACT, ASDC_ARTIFACT_TYPE_NOT_SUPPORT, ASDC_ARTIFACT_ALREADY_EXIST, ASDC_ARTIFACT_DOWNLOAD_SUC, ASDC_ARTIFACT_DOWNLOAD_FAIL, ASDC_START_DEPLOY_ARTIFACT, ASDC_SEND_NOTIF_ASDC, ASDC_SEND_NOTIF_ASDC_EXEC, ASDC_RECEIVE_CALLBACK_NOTIF, ASDC_RECEIVE_SERVICE_NOTIF, ASDC_ARTIFACT_NULL, ASDC_SERVICE_NOT_SUPPORT, ASDC_ARTIFACT_DEPLOY_SUC, ASDC_PROPERTIES_NOT_FOUND, ASDC_PROPERTIES_LOAD_SUCCESS, + // Default Messages, in case Log catalog is not defined + GENERAL_EXCEPTION_ARG, GENERAL_EXCEPTION, GENERAL_WARNING, AUDIT_EXEC, GENERAL_METRICS, LOGGER_SETUP, LOGGER_NOT_FOUND, LOGGER_UPDATE_SUC, LOGGER_UPDATE_DEBUG, LOGGER_UPDATE_DEBUG_SUC, LOAD_PROPERTIES_SUC, NO_PROPERTIES, MADATORY_PARAM_MISSING, LOAD_PROPERTIES_FAIL, INIT_LOGGER, INIT_LOGGER_FAIL, JAXB_EXCEPTION, IDENTITY_SERVICE_NOT_FOUND +} diff --git a/otf-camunda/src/main/java/org/oran/otf/common/utility/permissions/PermissionChecker.java b/otf-camunda/src/main/java/org/oran/otf/common/utility/permissions/PermissionChecker.java new file mode 100644 index 0000000..0bbab4a --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/common/utility/permissions/PermissionChecker.java @@ -0,0 +1,57 @@ +/* Copyright (c) 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.oran.otf.common.utility.permissions; + +import org.oran.otf.common.model.Group; +import org.oran.otf.common.model.User; +import org.oran.otf.common.repository.GroupRepository; + +import java.util.Collection; + +public class PermissionChecker { + //check is a user have a certain permission in a group + public static boolean hasPermissionTo(User user, Group group, String permission, GroupRepository groupRepository){ + UserPermission userPermission = new PermissionUtil().buildUserPermission(user,groupRepository); + return hasPermissionTo(userPermission,group,permission); + } + public static boolean hasPermissionTo(User user, Group group, Collection permissions, GroupRepository groupRepository){ + UserPermission userPermission = new PermissionUtil().buildUserPermission(user,groupRepository); + for(String permission : permissions){ + if(!hasPermissionTo(userPermission,group,permission)){ + return false; + } + } + return true; + } + // check a users list of permission in a group + private static boolean hasPermissionTo(UserPermission userPermission, Group group, String permission){ + switch (permission.toUpperCase()) { + case (UserPermission.Permission.READ): + return userPermission.hasAccessTo(group.get_id().toString(),UserPermission.Permission.READ); + case (UserPermission.Permission.WRITE): + return userPermission.hasAccessTo(group.get_id().toString(),UserPermission.Permission.WRITE); + case (UserPermission.Permission.EXECUTE): + return userPermission.hasAccessTo(group.get_id().toString(),UserPermission.Permission.EXECUTE); + case (UserPermission.Permission.DELETE): + return userPermission.hasAccessTo(group.get_id().toString(),UserPermission.Permission.DELETE); + case (UserPermission.Permission.MANAGEMENT): + return userPermission.hasAccessTo(group.get_id().toString(),UserPermission.Permission.MANAGEMENT); + default: + return false;// reaches here when permission provided is not an option + } + } +} \ No newline at end of file diff --git a/otf-camunda/src/main/java/org/oran/otf/common/utility/permissions/PermissionUtil.java b/otf-camunda/src/main/java/org/oran/otf/common/utility/permissions/PermissionUtil.java new file mode 100644 index 0000000..2a180bc --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/common/utility/permissions/PermissionUtil.java @@ -0,0 +1,238 @@ +/* Copyright (c) 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.oran.otf.common.utility.permissions; + +import org.oran.otf.common.model.Group; +import org.oran.otf.common.model.GroupMember; +import org.oran.otf.common.model.Role; +import org.oran.otf.common.model.User; +import org.oran.otf.common.repository.GroupRepository; + +import java.util.*; + +public class PermissionUtil { + //build userPermission object which contains all access control information of the user + public UserPermission buildUserPermission(User user, GroupRepository groupRepository) { + UserPermission userPermission = new UserPermission(); + userPermission.setUser(user); + Map> userAccessMap; // map from group to permission that user have in that group + + userAccessMap = mapGroupsToPermission(user,groupRepository); + userPermission.setUserAccessMap(userAccessMap); + return userPermission; + } + // return if user have specified permission in a certain group + // ***********only use this on groups that the user is in directly (non-child and non parents)**************** + public static boolean hasDirectPermissionTo(String permission, User user, Group group) { + Set possiblePermissions= getUserGroupPermissions(user,group); + return possiblePermissions.stream().anyMatch(p-> p.equalsIgnoreCase(permission)); // + } + // Get all the permissions the user have in a certain group + public static Set getUserGroupPermissions(User user, Group group){ + Set permissionsAllowed = new HashSet<>(); + Set usersAssignedRoles = findUserRoles(user,group); + if(usersAssignedRoles.isEmpty()) // empty set permissions because the user have no roles in the group aka not a member + return permissionsAllowed; + //get every single permissions for each role that the user have. + for(String role : usersAssignedRoles){ + permissionsAllowed.addAll(getRolePermissions(role,group)); + } + return permissionsAllowed; + } + //get the permissions associated with the userRoleName in group + public static Set getRolePermissions(String userRoleName, Group group) + { + for(Role role : group.getRoles()) + { + if(role.getRoleName().equalsIgnoreCase(userRoleName)) + { + return new HashSet(role.getPermissions()); + } + } + return new HashSet(); // empty string set if the role name cant be found in the group + } + // find the user's role in the specified group + public static Set findUserRoles(User user, Group group){ + for(GroupMember member : group.getMembers()) + { + // if userId matches then get all the user's role in the group + if(member.getUserId().toString().equals(user.get_id().toString())) + return new HashSet(member.getRoles()); + } + return new HashSet(); //if user have no roles + } + + // create map that where key is the group id and value = users permission (string) that that group + private Map> mapGroupsToPermission(User user, GroupRepository groupRepository){ + Map> groupAccessMap = new HashMap<>(); + List enrolledGroups = groupRepository.findAllByMembersId(user.get_id());// enrolledGroups = groups that user is a member of + Map allGroupMap = groupListToMap(groupRepository.findAll()); + // get all permission in the groups the user is ia member of + for(Group group: enrolledGroups) { + Set permissions = getUserGroupPermissions(user,group); + groupAccessMap.put(group.get_id().toString(),convertPermissions(permissions)); + } + //assign add read to all parent groups + Set parentGroupsId = getParentGroups(enrolledGroups,allGroupMap); + for(String parentId : parentGroupsId) + { + // if parent access role already exist in + // group access map cause they are a member + if(groupAccessMap.get(parentId)!= null) + groupAccessMap.get(parentId).add(UserPermission.Permission.READ); + else + groupAccessMap.put(parentId,new HashSet(Arrays.asList(UserPermission.Permission.READ))); + } + // if there is management role + // then assign read access to children + if(hasManagementRole(user,enrolledGroups)){ +// SetchildIds = getChildrenGroupsId(enrolledGroups,allGroupMap,user); + for(Group enrolledGroup : enrolledGroups) { + // if enrolled groups is a management group + if(hasDirectPermissionTo(UserPermission.Permission.MANAGEMENT,user,enrolledGroup)){ + // if there is management role then get all the child of that group, do this for all management groups + Set childIds= getChildrenGroupsId(Arrays.asList(enrolledGroup),allGroupMap,user); + Set userGroupPermissions = convertPermissions(getUserGroupPermissions(user,enrolledGroup)); + for(String childId : childIds){ + if (groupAccessMap.get(childId) != null) + groupAccessMap.get(childId).addAll(userGroupPermissions); + else{ + groupAccessMap.put(childId,userGroupPermissions); + } + } + } + } + } + return groupAccessMap; + } + // check is user have managementRole + private boolean hasManagementRole(User user, List enrolledGroups) + { + for(Group group: enrolledGroups){ + if(hasDirectPermissionTo(UserPermission.Permission.MANAGEMENT,user,group)) + { + return true; + } + } + return false; + } + // get the parent groups starting from the enrolled group of the user + private Set getParentGroups(List enrolledGroup, Map groupMap ) + { + Set parentGroups = new HashSet<>(); + return lookUp(enrolledGroup,groupMap,parentGroups); + } + //recursive lookup starting at the enrolled groups that the user is a member of + private Set lookUp(List groupsToCheck, Map groupMap, Set resultSet) + { + //base case: nothing to check anymore + if(groupsToCheck.isEmpty()) + return resultSet; + //This is the parents directly above the current groups that are being checked + List currentParentGroups = new ArrayList<>(); + + for(Group group : groupsToCheck) + { + if(group.getParentGroupId() != null) // if there is a parent + { + String parentId = group.getParentGroupId().toString(); + Group parentGroup = groupMap.get(parentId); + resultSet.add(parentId); + currentParentGroups.add(parentGroup); // add to currentParentGroup so it can be used recursively check for more parents + } + } + return lookUp(currentParentGroups,groupMap,resultSet); + } + // convert a list of groups to a map of group ids to group + private Map groupListToMap(List allGroups) + { + Map groupMap = new HashMap<>(); + allGroups.forEach(group -> groupMap.put(group.get_id().toString(),group)); + return groupMap; + } + //get all the child group + private Set getChildrenGroupsId(List enrolledGroup, Map allGroupsMap, User user) + { + Set childrenGroups = new HashSet<>(); + Set managementGroupIds = getManagementGroupIds(enrolledGroup,user); + return lookForChildren(managementGroupIds,allGroupsMap,childrenGroups); + } + + private Set getManagementGroupIds(List enrolledGroups, User user) + { + Set parentIds = new HashSet<>(); + for(Group group: enrolledGroups) + { + if(hasDirectPermissionTo(UserPermission.Permission.MANAGEMENT,user,group)) // has Management permission + { + parentIds.add(group.get_id().toString()); + } + } + return parentIds; + } + //recursive look down for childrens via breath first search + private Set lookForChildren (Set parentIds, Map allGroupsMap, Set resultSet) + { + //base case = no groups to check anymore; + if (parentIds.isEmpty()) + return resultSet; + + Set currentChildrenIds = new HashSet<>(); + for(String groupId : allGroupsMap.keySet()) + { + Group possibleChildGroup = allGroupsMap.get(groupId); + if(isChildOf(parentIds,possibleChildGroup)) // if parent id is the same + { + currentChildrenIds.add(groupId); + resultSet.add(groupId); + } + } + return lookForChildren(currentChildrenIds,allGroupsMap,resultSet); + } + //check if a group is a child of a list of parent group ids + private boolean isChildOf(SetparentGroupIds, Group childGroup){ + for(String parentId: parentGroupIds) + { + if(isChildOf(parentId,childGroup)) + return true; + } + return false; + } + //check is group has parent that is specified by parentId + private boolean isChildOf(String parentId, Group childGroup) { + if(childGroup.getParentGroupId() == null) + return false; + return childGroup.getParentGroupId().toString().equals(parentId); + } + + private Set convertPermissions (Set permissions){ + Set result = new HashSet<>(); + for (String permission: permissions){ + if(permission.equalsIgnoreCase(UserPermission.Permission.READ)) + result.add(UserPermission.Permission.READ); + else if (permission.equalsIgnoreCase(UserPermission.Permission.WRITE)) + result.add(UserPermission.Permission.WRITE); + else if (permission.equalsIgnoreCase(UserPermission.Permission.DELETE)) + result.add(UserPermission.Permission.DELETE); + else if (permission.equalsIgnoreCase(UserPermission.Permission.EXECUTE)) + result.add(UserPermission.Permission.EXECUTE); + else if (permission.equalsIgnoreCase(UserPermission.Permission.MANAGEMENT)) + result.add(UserPermission.Permission.MANAGEMENT); + } + return result; + } +} diff --git a/otf-camunda/src/main/java/org/oran/otf/common/utility/permissions/UserPermission.java b/otf-camunda/src/main/java/org/oran/otf/common/utility/permissions/UserPermission.java new file mode 100644 index 0000000..1883721 --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/common/utility/permissions/UserPermission.java @@ -0,0 +1,58 @@ +/* Copyright (c) 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.oran.otf.common.utility.permissions; + +import org.oran.otf.common.model.User; + +import java.util.Map; +import java.util.Set; + +public class UserPermission { + private User user; + private Map> userAccessMap; + + public User getUser() { + return user; + } + + public void setUser(User user) { + this.user = user; + } + + public Map> getUserAccessMap() { + return userAccessMap; + } + + public void setUserAccessMap(Map> userAccessMap) { + this.userAccessMap = userAccessMap; + } + + public boolean hasAccessTo(String groupId,String permission) { + if (userAccessMap.get(groupId) == null) { + return false; + } + Set group = userAccessMap.get(groupId); + return group.stream().anyMatch(groupPermission->groupPermission.equalsIgnoreCase(permission)); + } + public class Permission{ + public static final String READ = "READ"; + public static final String WRITE = "WRITE"; + public static final String EXECUTE = "EXECUTE"; + public static final String DELETE = "DELETE"; + public static final String MANAGEMENT ="MANAGEMENT"; + } +} diff --git a/otf-camunda/src/main/java/org/oran/otf/common/utility/sftp/SftpUtility.java b/otf-camunda/src/main/java/org/oran/otf/common/utility/sftp/SftpUtility.java new file mode 100644 index 0000000..cdaf8fd --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/common/utility/sftp/SftpUtility.java @@ -0,0 +1,94 @@ +/* Copyright (c) 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.oran.otf.common.utility.sftp; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.vfs2.*; +import org.apache.commons.vfs2.provider.sftp.IdentityInfo; +import org.apache.commons.vfs2.provider.sftp.SftpFileSystemConfigBuilder; + +import java.io.File; +import java.io.InputStream; + + +public class SftpUtility { + + public static byte[] getFile(String host, String artifactPath, String privateKeyPath, String privateKeyUsername, String privateKeyPasspharase) throws Exception { + String remoteURI = "sftp://" + privateKeyUsername + "@" + host + "/" + artifactPath; + + FileSystemOptions fsOptions = new FileSystemOptions(); + FileSystemManager fsManager = null; + byte[] bytes = null; + SftpFileSystemConfigBuilder builder = SftpFileSystemConfigBuilder.getInstance(); + builder.setUserDirIsRoot(fsOptions, false); + builder.setStrictHostKeyChecking(fsOptions, "no"); + IdentityInfo identityInfo = new IdentityInfo(new File(privateKeyPath), privateKeyPasspharase.getBytes()); + builder.setIdentityInfo(fsOptions, identityInfo); + fsManager = VFS.getManager(); + FileObject remoteFileObject = fsManager.resolveFile(remoteURI, fsOptions); + if(!remoteFileObject.isFile()) { + remoteFileObject.close(); + throw new Exception("Expected a file, but supplied filePath was not a file."); + } + InputStream is = remoteFileObject.getContent().getInputStream(); + bytes = IOUtils.toByteArray(is); + remoteFileObject.close(); + return bytes; + + } + + public static FileObject getDirectory(String host, String artifactPath, String privateKeyPath, String privateKeyUsername, String privateKeyPasspharase) throws Exception { + String remoteURI = "sftp://" + privateKeyUsername + "@" + host + "/" + artifactPath; + + FileSystemOptions fsOptions = new FileSystemOptions(); + FileSystemManager fsManager = null; + SftpFileSystemConfigBuilder builder = SftpFileSystemConfigBuilder.getInstance(); + builder.setUserDirIsRoot(fsOptions, false); + builder.setStrictHostKeyChecking(fsOptions, "no"); + IdentityInfo identityInfo = new IdentityInfo(new File(privateKeyPath), privateKeyPasspharase.getBytes()); + builder.setIdentityInfo(fsOptions, identityInfo); + fsManager = VFS.getManager(); + FileObject fileObject = fsManager.resolveFile(remoteURI, fsOptions); + if(fileObject.isFolder()) { + return fileObject; + } + fileObject.close(); + throw new Exception("Expected a folder, but supplied filePath was not a folder."); + } + + public static void uploadFile(String host, String artifactPath, String privateKeyPath, String privateKeyUsername, String privateKeyPasspharase, File tempFile) throws Exception { + String remoteURI = "sftp://" + privateKeyUsername + "@" + host + "/" + artifactPath; + + FileSystemOptions fsOptions = new FileSystemOptions(); + FileSystemManager fsManager = null; + SftpFileSystemConfigBuilder builder = SftpFileSystemConfigBuilder.getInstance(); + builder.setUserDirIsRoot(fsOptions, false); + builder.setStrictHostKeyChecking(fsOptions, "no"); + IdentityInfo identityInfo = new IdentityInfo(new File(privateKeyPath), privateKeyPasspharase.getBytes()); + builder.setIdentityInfo(fsOptions, identityInfo); + fsManager = VFS.getManager(); + //resolve file location + FileObject remoteFileObject = fsManager.resolveFile(remoteURI, fsOptions); + FileObject sourceFile = fsManager.resolveFile(tempFile.getAbsolutePath()); + //if file exists then override, else create file + remoteFileObject.copyFrom(sourceFile, Selectors.SELECT_SELF); + remoteFileObject.close(); + sourceFile.close(); + } + + +} diff --git a/otf-camunda/src/main/java/org/oran/otf/event/TestInstanceCompletionEvent.java b/otf-camunda/src/main/java/org/oran/otf/event/TestInstanceCompletionEvent.java new file mode 100644 index 0000000..0d21acf --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/event/TestInstanceCompletionEvent.java @@ -0,0 +1,49 @@ +/* Copyright (c) 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.oran.otf.event; + +import com.google.gson.JsonObject; +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.springframework.context.ApplicationEvent; + +public class TestInstanceCompletionEvent extends ApplicationEvent { + + private JsonObject obj; + private DelegateExecution execution; + + public TestInstanceCompletionEvent(Object source, JsonObject obj, DelegateExecution execution) { + super(source); + this.obj = obj; + this.execution = execution; + } + + public JsonObject getObj() { + return obj; + } + + public void setObj(JsonObject obj) { + this.obj = obj; + } + + public DelegateExecution getExecution() { + return execution; + } + + public void setExecution(DelegateExecution execution) { + this.execution = execution; + } +} diff --git a/otf-camunda/src/main/java/org/oran/otf/event/TestInstanceIncidentEvent.java b/otf-camunda/src/main/java/org/oran/otf/event/TestInstanceIncidentEvent.java new file mode 100644 index 0000000..0bb5eb6 --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/event/TestInstanceIncidentEvent.java @@ -0,0 +1,59 @@ +/* Copyright (c) 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.oran.otf.event; + +import org.camunda.bpm.engine.impl.incident.IncidentContext; +import org.springframework.context.ApplicationEvent; + +public class TestInstanceIncidentEvent extends ApplicationEvent { + + private IncidentContext context; + private String message; + private String type; + + public TestInstanceIncidentEvent(Object source, IncidentContext context, String message, + String type) { + super(source); + this.context = context; + this.message = message; + this.type = type; + } + + public IncidentContext getContext() { + return context; + } + + public void setContext(IncidentContext context) { + this.context = context; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } +} diff --git a/otf-camunda/src/main/java/org/oran/otf/service/DeleteProcessInstanceService.java b/otf-camunda/src/main/java/org/oran/otf/service/DeleteProcessInstanceService.java new file mode 100644 index 0000000..d627f31 --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/service/DeleteProcessInstanceService.java @@ -0,0 +1,34 @@ +/* Copyright (c) 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.oran.otf.service; + +import static javax.ws.rs.core.MediaType.APPLICATION_JSON; + +import javax.ws.rs.DELETE; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Response; + +@Path("/tcu") +public interface DeleteProcessInstanceService { + + @DELETE + @Path("/delete-process-instance/v1/{executionId}") + @Produces(APPLICATION_JSON) + Response deleteProcessInstance(@PathParam("executionId") String executionId); +} diff --git a/otf-camunda/src/main/java/org/oran/otf/service/DeleteTestDefinitionService.java b/otf-camunda/src/main/java/org/oran/otf/service/DeleteTestDefinitionService.java new file mode 100644 index 0000000..b78d23d --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/service/DeleteTestDefinitionService.java @@ -0,0 +1,48 @@ +/* Copyright (c) 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.oran.otf.service; + +import javax.ws.rs.*; +import javax.ws.rs.core.Response; + +import static javax.ws.rs.core.MediaType.APPLICATION_JSON; + +@Path("/tcu") +public interface DeleteTestDefinitionService { + + @DELETE + @Path("/delete-test-strategy/v1/deployment-id/{deploymentId}/") + @Consumes(APPLICATION_JSON) + @Produces(APPLICATION_JSON) + Response deleteTestStrategyByDeploymentId(@PathParam("deploymentId") String deploymentId); + + + + @DELETE + @Path("/delete-test-strategy/v1/test-definition-id/{testDefinitionId}/") + @Consumes(APPLICATION_JSON) + @Produces(APPLICATION_JSON) + public Response deleteTestStrategyByTestDefinitionId(@PathParam("testDefinitionId") String testDefinitionId); + + + +// @DELETE +// @Path("/delete-all-test-strategies/v1/") +// @Consumes(APPLICATION_JSON) +// @Produces(APPLICATION_JSON) +// Response deleteAllTestStrategies(); +} diff --git a/otf-camunda/src/main/java/org/oran/otf/service/DeveloperService.java b/otf-camunda/src/main/java/org/oran/otf/service/DeveloperService.java new file mode 100644 index 0000000..3e6d036 --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/service/DeveloperService.java @@ -0,0 +1,80 @@ +/* Copyright (c) 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.oran.otf.service; + +import static javax.ws.rs.core.MediaType.APPLICATION_JSON; + +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.Response; + +@Path("/tcu") +public interface DeveloperService { + @POST + @Consumes(APPLICATION_JSON) + @Produces(APPLICATION_JSON) + @Path("/dev/workflowTaskCleanup/v1/{enabled}") + Response workflowTaskCleanup(@PathParam("enabled") String enabled); + + @POST + @Consumes(APPLICATION_JSON) + @Produces(APPLICATION_JSON) + @Path("/dev/externalTaskWorker/v1/{enabled}") + Response externalTaskWorker(@PathParam("enabled") String enabled); + + @GET + @Consumes(APPLICATION_JSON) + @Produces(APPLICATION_JSON) + @Path("/dev/printThreads/v1") + Response printThreads(@Context HttpServletRequest request); + + @POST + @Consumes(APPLICATION_JSON) + @Produces(APPLICATION_JSON) + @Path("/dev/jobExecutor/v1/activate") + Response activateJobExecutor(); + + @POST + @Consumes(APPLICATION_JSON) + @Produces(APPLICATION_JSON) + @Path("/dev/jobExecutor/v1/deactivate") + Response deActivateJobExecutor(); + + @POST + @Consumes(APPLICATION_JSON) + @Produces(APPLICATION_JSON) + @Path("/dev/gracefulshutdown/v1") + Response gracefulShutdown(); + + @POST + @Consumes(APPLICATION_JSON) + @Produces(APPLICATION_JSON) + @Path("/dev/disableGracefulShutdown/v1") + Response disableGracefulShutdown(); + + @POST + @Consumes(APPLICATION_JSON) + @Produces(APPLICATION_JSON) + @Path("/dev/enableGracefulShutdown/v1") + Response enableGracefulShutdown(); +} diff --git a/otf-camunda/src/main/java/org/oran/otf/service/HealthService.java b/otf-camunda/src/main/java/org/oran/otf/service/HealthService.java new file mode 100644 index 0000000..065d886 --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/service/HealthService.java @@ -0,0 +1,35 @@ +/* Copyright (c) 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.oran.otf.service; + +import static javax.ws.rs.core.MediaType.APPLICATION_JSON; + +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Response; + +@Path("/") // Base path for unauthenticated services +public interface HealthService { + + @GET + @Consumes(APPLICATION_JSON) + @Produces(APPLICATION_JSON) + @Path("/health/v1") + Response getHealth(); +} diff --git a/otf-camunda/src/main/java/org/oran/otf/service/ProcessInstanceCompletionService.java b/otf-camunda/src/main/java/org/oran/otf/service/ProcessInstanceCompletionService.java new file mode 100644 index 0000000..9d5e575 --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/service/ProcessInstanceCompletionService.java @@ -0,0 +1,37 @@ +/* Copyright (c) 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.oran.otf.service; + + + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Response; + +import static javax.ws.rs.core.MediaType.APPLICATION_JSON; + +@Path("/tcu") +public interface ProcessInstanceCompletionService { + + @GET + @Produces(APPLICATION_JSON) + @Path("/process-instance-completion-check/v1/{id}") + public Response isProcessInstanceComplete(@PathParam("id") String processInstanceId); + +} diff --git a/otf-camunda/src/main/java/org/oran/otf/service/TestControlUnitService.java b/otf-camunda/src/main/java/org/oran/otf/service/TestControlUnitService.java new file mode 100644 index 0000000..e6ed4fc --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/service/TestControlUnitService.java @@ -0,0 +1,47 @@ +/* Copyright (c) 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.oran.otf.service; + +import static javax.ws.rs.core.MediaType.APPLICATION_JSON; + +import javax.ws.rs.Consumes; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.Response; +import org.springframework.web.bind.annotation.RequestHeader; + +@Path("/tcu") +public interface TestControlUnitService { + + @POST + @Consumes(APPLICATION_JSON) + @Produces(APPLICATION_JSON) + @Path("/execute/testInstanceId/{testInstanceId}") + Response executeByTestInstanceId(@PathParam("testInstanceId") String testInstanceId); + + @POST + @Consumes(APPLICATION_JSON) + @Produces(APPLICATION_JSON) + @Path("/execute/workflowRequest") + Response executeByWorkflowRequest(String workflowRequest); +} diff --git a/otf-camunda/src/main/java/org/oran/otf/service/TestDefinitionDeploymentService.java b/otf-camunda/src/main/java/org/oran/otf/service/TestDefinitionDeploymentService.java new file mode 100644 index 0000000..e329652 --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/service/TestDefinitionDeploymentService.java @@ -0,0 +1,46 @@ +/* Copyright (c) 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.oran.otf.service; + + +import org.glassfish.jersey.media.multipart.FormDataParam; + +import javax.ws.rs.*; +import javax.ws.rs.core.Response; + +import java.io.InputStream; + +import static javax.ws.rs.core.MediaType.APPLICATION_JSON; +import static javax.ws.rs.core.MediaType.MULTIPART_FORM_DATA; + +@Path("/tcu") +public interface TestDefinitionDeploymentService { + + @POST + @Path("/deploy-test-strategy-zip/v1") + @Consumes(MULTIPART_FORM_DATA) + @Produces(APPLICATION_JSON) + Response deployTestStrategyWithResources(@FormDataParam("bpmn") InputStream bpmn, + @FormDataParam("resources") InputStream resourcesZip); + + @GET + @Path("/testDefinition/v1/processDefinitionKey/{processDefinitionKey}") + @Consumes(APPLICATION_JSON) + @Produces(APPLICATION_JSON) + Response isProcessDefinitionDeployed(@PathParam("processDefinitionKey") String processDefinitionKey); + +} diff --git a/otf-camunda/src/main/java/org/oran/otf/service/impl/DeleteProcessInstanceServiceImpl.java b/otf-camunda/src/main/java/org/oran/otf/service/impl/DeleteProcessInstanceServiceImpl.java new file mode 100644 index 0000000..8b51c90 --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/service/impl/DeleteProcessInstanceServiceImpl.java @@ -0,0 +1,96 @@ +/* Copyright (c) 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.oran.otf.service.impl; + +import org.oran.otf.camunda.configuration.OtfCamundaConfiguration; +import org.oran.otf.camunda.service.ProcessEngineAwareService; +import org.oran.otf.camunda.workflow.utility.WorkflowTask; +import org.oran.otf.common.utility.gson.Convert; +import org.oran.otf.common.utility.http.ResponseUtility; +import org.oran.otf.service.DeleteProcessInstanceService; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import javax.ws.rs.core.Response; + +import org.camunda.bpm.BpmPlatform; +import org.camunda.bpm.engine.RuntimeService; +import org.camunda.bpm.engine.runtime.ProcessInstance; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +@Service +public class DeleteProcessInstanceServiceImpl extends ProcessEngineAwareService + implements DeleteProcessInstanceService { + + private static Logger logger = LoggerFactory.getLogger(DeleteProcessInstanceServiceImpl.class); + + @Override + public Response deleteProcessInstance(String executionId) { + RuntimeService runtimeService = BpmPlatform.getProcessEngineService().getProcessEngine(OtfCamundaConfiguration.processEngineName).getRuntimeService(); + + Map response = + deleteProcessInstanceInternal( + executionId, "Deleted via TCU endpoint at " + new Date(System.currentTimeMillis())); + + try { + int code = (int) response.get("code"); + String sRes = Convert.mapToJson(response); + if (code == 404) { + return ResponseUtility.Build.notFoundWithMessage(sRes); + } else if (code == 200) { + return ResponseUtility.Build.okRequestWithMessage(sRes); + } + } catch (ClassCastException cce) { + logger.error(cce.getMessage()); + } + // Unhandled response + return ResponseUtility.Build.internalServerError(); + } + + public Map deleteProcessInstanceInternal( + String executionId, String deleteReason) { + RuntimeService runtimeService = BpmPlatform.getProcessEngineService().getProcessEngine(OtfCamundaConfiguration.processEngineName).getRuntimeService(); + + ProcessInstance pi = + runtimeService.createProcessInstanceQuery().processInstanceId(executionId).singleResult(); + + Map response = new HashMap<>(); + + if (pi == null) { + response.put( + "result", + String.format("A process instance with the executionId %s was not found.", executionId)); + response.put("code", 404); + } else { + List workflowTasks = WorkflowTask.workflowTasksByExecutionId.get(executionId); + if (workflowTasks != null) { + for (WorkflowTask workflowTask : workflowTasks) { + workflowTask.shutdown(); + } + } + + runtimeService.deleteProcessInstance(executionId, deleteReason); + response.put("result", "Successfully deleted."); + response.put("code", 200); + } + + return response; + } +} diff --git a/otf-camunda/src/main/java/org/oran/otf/service/impl/DeleteTestDefinitionServiceImpl.java b/otf-camunda/src/main/java/org/oran/otf/service/impl/DeleteTestDefinitionServiceImpl.java new file mode 100644 index 0000000..79eeb45 --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/service/impl/DeleteTestDefinitionServiceImpl.java @@ -0,0 +1,119 @@ +/* Copyright (c) 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.oran.otf.service.impl; + +import org.oran.otf.camunda.configuration.OtfCamundaConfiguration; +import org.oran.otf.common.model.TestDefinition; +import org.oran.otf.common.model.local.BpmnInstance; +import org.oran.otf.common.repository.TestDefinitionRepository; +import org.oran.otf.common.utility.http.ResponseUtility; +import org.oran.otf.service.DeleteTestDefinitionService; +import java.util.List; +import java.util.Optional; +import javax.ws.rs.core.Response; + +import org.camunda.bpm.BpmPlatform; +import org.camunda.bpm.engine.RepositoryService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.context.event.ApplicationReadyEvent; +import org.springframework.context.event.EventListener; +import org.springframework.stereotype.Service; + +@Service +public class DeleteTestDefinitionServiceImpl implements DeleteTestDefinitionService { + + + private RepositoryService repositoryService; + + @Autowired + private TestDefinitionRepository testDefinitionRepository; + + @EventListener(ApplicationReadyEvent.class) + private void initialize(){ + if(this.repositoryService == null){ + this.repositoryService = BpmPlatform.getProcessEngineService().getProcessEngine(OtfCamundaConfiguration.processEngineName).getRepositoryService(); + } + } + + // delete a single version by deploymentId + @Override + public Response deleteTestStrategyByDeploymentId(String deploymentId) { + try { + repositoryService.deleteDeployment(deploymentId, true); + return ResponseUtility.Build.okRequest(); + } catch (Exception e) { + return ResponseUtility.Build.badRequestWithMessage(e.getMessage()); + } + } + + + // delete all deployment versions given test definition + @Override + public Response deleteTestStrategyByTestDefinitionId(String testDefinitionId) { + Optional testDefinitionQuery = + testDefinitionRepository.findById(testDefinitionId); + if (!testDefinitionQuery.isPresent()) { + return Response.status(404).build(); + } + TestDefinition testDefinition = testDefinitionQuery.get(); + + List bpmnInstances = testDefinition.getBpmnInstances(); + // List indices = new ArrayList(); + for (int i = 0; i < bpmnInstances.size(); i++) { + try { + repositoryService.deleteDeployment(bpmnInstances.get(i).getDeploymentId(), true); + // indices.add(i); + } catch (Exception e) { + + } + } + + // for(int i = indices.size()-1; i >=0; i++) { + // bpmnInstances.remove(i); + // } + // testDefinition.setBpmnInstances(new ArrayList()); + // testDefinitionRepository.save(testDefinition); + return ResponseUtility.Build.okRequest(); + + + } + + + // delete all deployments +// public Response deleteAllTestStrategies() { +//// create a database to retrieve all process definitions +// List processDefinitions = repositoryService.createProcessDefinitionQuery() +// .orderByProcessDefinitionVersion().asc().list(); +// +// final int sizeBefore = processDefinitions.size(); +// +// // delete each deployment +// processDefinitions.forEach(processDefinition -> { +// repositoryService.deleteDeployment(processDefinition.getDeploymentId(), true); +// }); +// +// final int sizeAfter = processDefinitions.size(); +// +// Map response = new HashMap(); +// if (sizeBefore - sizeAfter == 0) +// response.put("numDeletions", sizeBefore); +// else +// response.put("numDeletions", sizeBefore - sizeAfter); +// +// return ResponseUtility.Build.okRequestWithObject(response); +// } +} diff --git a/otf-camunda/src/main/java/org/oran/otf/service/impl/DeveloperServiceImpl.java b/otf-camunda/src/main/java/org/oran/otf/service/impl/DeveloperServiceImpl.java new file mode 100644 index 0000000..7501be7 --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/service/impl/DeveloperServiceImpl.java @@ -0,0 +1,161 @@ +/* Copyright (c) 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.oran.otf.service.impl; + +import org.oran.otf.camunda.configuration.OtfCamundaConfiguration; +import org.oran.otf.camunda.service.CamundaShutdown; +import org.oran.otf.camunda.service.OtfExternalTaskService; +import org.oran.otf.camunda.service.OtfWorkflowTaskCleanupService; +import org.oran.otf.camunda.workflow.utility.WorkflowTask; +import org.oran.otf.common.utility.http.ResponseUtility; +import org.oran.otf.service.DeveloperService; +import com.google.common.base.Strings; + +import java.util.Arrays; +import java.util.Set; + +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.core.Response; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.event.ContextClosedEvent; +import org.springframework.context.event.EventListener; + +import org.camunda.bpm.BpmPlatform; +import org.camunda.bpm.engine.impl.cfg.ProcessEngineConfigurationImpl; +import org.camunda.bpm.engine.impl.jobexecutor.JobExecutor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +@Service +public class DeveloperServiceImpl implements DeveloperService { + + private Logger logger = LoggerFactory.getLogger(DeveloperServiceImpl.class); + + @Autowired + CamundaShutdown camundaShutdown; + + @Value("${otf.camunda.graceful-shutdown.wait-time}") + private int gracefulWaitTime; + + private boolean gracefulShutdown = true; + + @Override + public Response workflowTaskCleanup(String enabled) { + if (Strings.isNullOrEmpty(enabled)) + return ResponseUtility.Build.badRequestWithMessage( + "Path parameter, enabled, cannot be null or empty."); + + OtfWorkflowTaskCleanupService.isEnabled = enabled.equalsIgnoreCase("true"); + return ResponseUtility.Build.okRequestWithMessage( + "Clean up service set to " + OtfWorkflowTaskCleanupService.isEnabled); + } + + @Override + public Response externalTaskWorker(String enabled) { + if (Strings.isNullOrEmpty(enabled)) { + return ResponseUtility.Build.badRequestWithMessage( + "Path parameter, enabled, cannot be null or empty."); + } + + OtfExternalTaskService.isEnabled = enabled.equalsIgnoreCase("true"); + return ResponseUtility.Build.okRequestWithMessage( + "OTF External Task set to " + OtfExternalTaskService.isEnabled); + } + + @Override + public Response printThreads(HttpServletRequest request) { + //Logger logger = LoggerFactory.getLogger(HealthServiceImpl.class); + String message = String.format("Health request from %s.", request.getRemoteAddr()); + logger.info(message); + + WorkflowTask.printWorkflowTaskResources(); + logger.info(""); + logger.info(""); + WorkflowTask.printThreadInformation(); + + return ResponseUtility.Build.okRequestWithMessage(message); + } + + @Override + public Response activateJobExecutor() { + JobExecutor jobExecutor = ((ProcessEngineConfigurationImpl) (BpmPlatform.getProcessEngineService().getProcessEngine(OtfCamundaConfiguration.processEngineName)).getProcessEngineConfiguration()).getJobExecutor(); + if (!jobExecutor.isActive()) { + jobExecutor.start(); + } + return ResponseUtility.Build.okRequest(); + } + + @Override + public Response deActivateJobExecutor() { + JobExecutor jobExecutor = ((ProcessEngineConfigurationImpl) (BpmPlatform.getProcessEngineService().getProcessEngine(OtfCamundaConfiguration.processEngineName)).getProcessEngineConfiguration()).getJobExecutor(); + if (jobExecutor.isActive()) { + jobExecutor.shutdown(); + } + return ResponseUtility.Build.okRequest(); + } + + @Override + public Response gracefulShutdown() { + return this.gracefulShutdown ? ResponseUtility.Build.okRequestWithMessage(shutdown()) : ResponseUtility.Build.okRequestWithMessage("Graceful shutdown is disabled."); + } + + @Override + public Response disableGracefulShutdown() { + this.gracefulShutdown = false; + return ResponseUtility.Build.okRequest(); + } + + @Override + public Response enableGracefulShutdown() { + this.gracefulShutdown = true; + return ResponseUtility.Build.okRequest(); + } + + @EventListener(ContextClosedEvent.class) + private String shutdown() { + String message = "Graceful shutdown:"; + String returnMessage = "Graceful shutdown processes terminated: "; + try { + //disable external task service + OtfExternalTaskService.isEnabled = false; + //disable job executor + deActivateJobExecutor(); + logger.info("Disabled job executor and external task service."); + logger.info("Starting to sleep..."); + Thread.sleep(gracefulWaitTime); + logger.info("ending to sleep...calling termination service"); + // Call Termination service + Set processInterrupted = camundaShutdown.gracefulShutdown(); + returnMessage = returnMessage + " " + processInterrupted.size(); + message += String.format("processesInterrupted %s ", + Arrays.toString(processInterrupted.toArray())); + + logger.info(message += String.format("processesInterrupted %s ", + Arrays.toString(processInterrupted.toArray()))); + } catch (InterruptedException e) { + return "Graceful shutdown processes encountered an error."; + } + return returnMessage; + } + + + + +} diff --git a/otf-camunda/src/main/java/org/oran/otf/service/impl/HealthServiceImpl.java b/otf-camunda/src/main/java/org/oran/otf/service/impl/HealthServiceImpl.java new file mode 100644 index 0000000..180f722 --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/service/impl/HealthServiceImpl.java @@ -0,0 +1,39 @@ +/* Copyright (c) 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.oran.otf.service.impl; + +import org.oran.otf.common.utility.http.ResponseUtility; +import org.oran.otf.service.HealthService; +import javax.ws.rs.core.Response; + +import org.camunda.bpm.engine.RuntimeService; +import org.camunda.bpm.engine.runtime.Incident; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class HealthServiceImpl implements HealthService { + + private HealthServiceImpl() { + // prohibit instantiation + } + + @Override + public Response getHealth() { + return ResponseUtility.Build.okRequestWithMessage("UP"); + } +} diff --git a/otf-camunda/src/main/java/org/oran/otf/service/impl/ProcessInstanceCompletionServiceImpl.java b/otf-camunda/src/main/java/org/oran/otf/service/impl/ProcessInstanceCompletionServiceImpl.java new file mode 100644 index 0000000..66e262b --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/service/impl/ProcessInstanceCompletionServiceImpl.java @@ -0,0 +1,119 @@ +/* Copyright (c) 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.oran.otf.service.impl; + +import org.oran.otf.camunda.configuration.OtfCamundaConfiguration; +import org.oran.otf.common.model.local.OTFProcessInstanceCompletionResponse; +import org.oran.otf.common.utility.http.ResponseUtility; +import org.oran.otf.service.ProcessInstanceCompletionService; +import java.util.List; +import javax.ws.rs.core.Response; + +import org.camunda.bpm.BpmPlatform; +import org.camunda.bpm.engine.HistoryService; +import org.camunda.bpm.engine.ManagementService; +import org.camunda.bpm.engine.RuntimeService; +import org.camunda.bpm.engine.history.*; +import org.springframework.boot.context.event.ApplicationReadyEvent; +import org.springframework.context.event.EventListener; +import org.springframework.stereotype.Service; + +@Service +public class ProcessInstanceCompletionServiceImpl implements ProcessInstanceCompletionService { + + RuntimeService runtimeService; + + ManagementService managementService; + + HistoryService historyService; + + + + private ProcessInstanceCompletionServiceImpl() { + // prohibit instantiation + } + + @EventListener(ApplicationReadyEvent.class) + private void initialize(){ + if(this.runtimeService == null){ + this.runtimeService = BpmPlatform.getProcessEngineService().getProcessEngine(OtfCamundaConfiguration.processEngineName).getRuntimeService(); + } + if(this.managementService == null){ + this.managementService = BpmPlatform.getProcessEngineService().getProcessEngine(OtfCamundaConfiguration.processEngineName).getManagementService(); + } + if(this.historyService == null){ + this.historyService = BpmPlatform.getProcessEngineService().getProcessEngine(OtfCamundaConfiguration.processEngineName).getHistoryService(); + } + + } + + @Override + public Response isProcessInstanceComplete(String processInstanceId) { + + HistoricProcessInstance historicProcessInstance = historyService + .createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult(); + + List historicActivityInstance = historyService + .createHistoricActivityInstanceQuery().processInstanceId(processInstanceId).list(); + + List historicIncident = + historyService.createHistoricIncidentQuery().processInstanceId(processInstanceId).list(); + + List historicJobLog = + historyService.createHistoricJobLogQuery().processInstanceId(processInstanceId).list(); + + List historicExternalTaskLog = + historyService.createHistoricExternalTaskLogQuery().processInstanceId(processInstanceId).list(); + + List historicVariableInstance = + historyService.createHistoricVariableInstanceQuery().processInstanceId(processInstanceId).list(); + + + + OTFProcessInstanceCompletionResponse response = new OTFProcessInstanceCompletionResponse(); + response.setHistoricProcessInstance(historicProcessInstance); + response.setHistoricActivityInstance(historicActivityInstance); + response.setHistoricIncident(historicIncident); + response.setHistoricJobLog(historicJobLog); + response.setHistoricExternalTaskLog(historicExternalTaskLog); + response.setHistoricVariableInstance(historicVariableInstance); + + + return ResponseUtility.Build.okRequestWithObject(response); + + // Boolean done = runtimeService +// .createProcessInstanceQuery() +// .processInstanceId(processInstanceId) +// .singleResult() == null; +// +// if(done) { +// return Response.ok(new ProcessInstanceCompletionResponse("Completed", "Process Instance Completed Execution")).build(); +// } +// +// +// Incident incident = runtimeService.createIncidentQuery().processInstanceId(processInstanceId).singleResult(); +// if(incident != null && incident.getIncidentType().equals("failedJob")) { +// String errorMessage = incident.getIncidentMessage(); +// return Response.ok(new ProcessInstanceCompletionResponse("Failed", errorMessage)).build(); +// } +// +// +// else { +// return Response.ok(new ProcessInstanceCompletionResponse("In Progress", "Process Instance is active")).build(); +// } + } +} diff --git a/otf-camunda/src/main/java/org/oran/otf/service/impl/TestControlUnitServiceImpl.java b/otf-camunda/src/main/java/org/oran/otf/service/impl/TestControlUnitServiceImpl.java new file mode 100644 index 0000000..a607d5c --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/service/impl/TestControlUnitServiceImpl.java @@ -0,0 +1,119 @@ +/* Copyright (c) 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.oran.otf.service.impl; + +import org.oran.otf.camunda.delegate.otf.common.runnable.AsynchronousTestInstanceCallable; +import org.oran.otf.camunda.delegate.otf.common.runnable.SynchronousTestInstanceCallable; +import org.oran.otf.camunda.exception.WorkflowProcessorException; +import org.oran.otf.camunda.workflow.WorkflowProcessor; +import org.oran.otf.camunda.workflow.WorkflowRequest; +import org.oran.otf.common.model.TestExecution; +import org.oran.otf.common.model.TestInstance; +import org.oran.otf.common.repository.TestExecutionRepository; +import org.oran.otf.common.repository.TestInstanceRepository; +import org.oran.otf.common.utility.gson.Convert; +import org.oran.otf.common.utility.http.ResponseUtility; +import org.oran.otf.service.TestControlUnitService; +import com.fasterxml.jackson.core.type.TypeReference; +import java.io.IOException; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.Response; +import org.bson.types.ObjectId; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.stereotype.Service; +import org.springframework.web.bind.annotation.RequestHeader; + +@Service +public class TestControlUnitServiceImpl implements TestControlUnitService { + + private static Logger logger = LoggerFactory.getLogger(TestControlUnitServiceImpl.class); + + @Autowired + TestInstanceRepository testInstanceRepository; + + @Autowired + TestExecutionRepository testExecutionRepository; + + @Autowired + MongoTemplate mongoOperation; + + @Autowired + WorkflowProcessor processor; + + @Override + public Response executeByTestInstanceId(String testInstanceId) { + try { + TestInstance testInstance = testInstanceRepository.findById(testInstanceId).orElse(null); + if (testInstance == null) { + return Response.status(404).entity("Test Instance not found.").build(); + } + + WorkflowRequest req = new WorkflowRequest(); + req.setAsync(false); + req.setExecutorId(new ObjectId("5cb72a7e10ba2a0042e6282a")); + req.setTestInstanceId(testInstance.get_id()); + req.setTestData(testInstance.getTestData()); + req.setVthInput(testInstance.getVthInput()); + req.setPfloInput(testInstance.getPfloInput()); + req.setMaxExecutionTimeInMillis(testInstance.getMaxExecutionTimeInMillis()); + return processWorkflowRequest(req); + } catch (Exception e) { + return ResponseUtility.Build.internalServerErrorWithMessage(e.getMessage()); + } + } + + @Override + public Response executeByWorkflowRequest(String workflowRequestJson) { + try { + WorkflowRequest workflowRequest = + Convert.jsonToObject(workflowRequestJson, new TypeReference() { + }); + + return processWorkflowRequest(workflowRequest); + } catch (IOException e) { + logger.error(e.getMessage()); + return ResponseUtility.Build.badRequestWithMessage(e.getMessage()); + } + } + + private Response processWorkflowRequest(WorkflowRequest request) { + TestExecution testExecution = null; + int statusCode = 200; + try { + if (request.isAsync()) { + AsynchronousTestInstanceCallable asynchronousTestInstanceCallable = + new AsynchronousTestInstanceCallable( + request, testExecutionRepository, processor, mongoOperation); + testExecution = asynchronousTestInstanceCallable.call(); + } else { + SynchronousTestInstanceCallable synchronousTestInstanceCallable = + new SynchronousTestInstanceCallable( + request, testExecutionRepository, processor, mongoOperation); + testExecution = synchronousTestInstanceCallable.call(); + } + } catch (WorkflowProcessorException e) { + testExecution = e.getWorkflowResponse().getTestExecution(); + statusCode = e.getWorkflowResponse().getMessageCode(); + } + return ResponseUtility.Build.genericWithMessage(statusCode, testExecution.toString()); + } +} diff --git a/otf-camunda/src/main/java/org/oran/otf/service/impl/TestDefinitionDeploymentServiceImpl.java b/otf-camunda/src/main/java/org/oran/otf/service/impl/TestDefinitionDeploymentServiceImpl.java new file mode 100644 index 0000000..e7f932c --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/service/impl/TestDefinitionDeploymentServiceImpl.java @@ -0,0 +1,134 @@ +/* Copyright (c) 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.oran.otf.service.impl; + +import org.oran.otf.camunda.configuration.OtfCamundaConfiguration; +import org.oran.otf.common.model.local.OTFDeploymentResponse; +import org.oran.otf.common.utility.http.ResponseUtility; +import org.oran.otf.service.TestDefinitionDeploymentService; +import java.io.InputStream; +import java.util.List; +import java.util.zip.ZipInputStream; +import javax.ws.rs.core.Response; + +import org.camunda.bpm.BpmPlatform; +import org.camunda.bpm.engine.RepositoryService; +import org.camunda.bpm.engine.impl.persistence.entity.DeploymentEntity; +import org.camunda.bpm.engine.repository.ProcessDefinition; +import org.camunda.bpm.model.bpmn.Bpmn; +import org.camunda.bpm.model.bpmn.BpmnModelInstance; +import org.camunda.bpm.model.xml.instance.DomElement; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.context.event.ApplicationReadyEvent; +import org.springframework.context.event.EventListener; +import org.springframework.stereotype.Service; + +@Service +public class TestDefinitionDeploymentServiceImpl implements TestDefinitionDeploymentService { + + private static Logger logger = LoggerFactory.getLogger(TestDefinitionDeploymentServiceImpl.class); + + + private RepositoryService repositoryService; + + private TestDefinitionDeploymentServiceImpl() { + // prohibit instantiation + } + + @EventListener(ApplicationReadyEvent.class) + private void initialize(){ + if(this.repositoryService == null){ + this.repositoryService = BpmPlatform.getProcessEngineService().getProcessEngine(OtfCamundaConfiguration.processEngineName).getRepositoryService(); + } + } + + public Response deployTestStrategyWithResources(InputStream bpmn, InputStream resourcesZip) { + + if (bpmn == null) { + logger.error("no bpmn file provided with name 'bpmn' in multipart form"); + return ResponseUtility.Build.badRequestWithMessage("No bpmn file provided with name 'bpmn' in multipart form"); + } + DeploymentEntity deployment = null; + try { + InputStream processDefinitionStream = bpmn; + BpmnModelInstance bpmnModelInstance = null; + try { + bpmnModelInstance = Bpmn.readModelFromStream(processDefinitionStream); + Bpmn.validateModel(bpmnModelInstance); + } + catch(Exception e){ + e.printStackTrace(); + return ResponseUtility.Build.badRequestWithMessage("Unable to deploy BPMN: " + e.getMessage()); + } + String namespace = bpmnModelInstance.getDefinitions().getDomElement().getNamespaceURI(); + List bpmnProcess = + bpmnModelInstance.getDocument().getElementsByNameNs(namespace, "process"); + if (bpmnProcess.size() != 1) { + logger.info("Invalid number of bpmn process tags"); + return ResponseUtility.Build.internalServerErrorWithMessage("Invalid number of bpmn process tags"); + } else { + String processDefinitionKey = bpmnProcess.get(0).getAttribute("id"); + if (resourcesZip == null) { + deployment = (DeploymentEntity) repositoryService.createDeployment() + .addModelInstance(processDefinitionKey + ".bpmn", bpmnModelInstance).deploy(); + } else { + ZipInputStream zis = new ZipInputStream(resourcesZip); + + deployment = (DeploymentEntity) repositoryService.createDeployment() + .addModelInstance(processDefinitionKey + ".bpmn", bpmnModelInstance) + .addZipInputStream(zis).deploy(); + } + } + } catch (Exception e) { + logger.info("Error: Creating Deployment: " + e.getMessage()); + return ResponseUtility.Build.internalServerErrorWithMessage("Error: Creating Deployment: " + e.getMessage()); + } + return Response.ok(generateResponseFromDeployment(deployment)).build(); + } + + @Override + public Response isProcessDefinitionDeployed(String processDefinitionKey) { + try { + ProcessDefinition definition = + repositoryService + .createProcessDefinitionQuery() + .processDefinitionKey(processDefinitionKey) + .latestVersion() + .singleResult(); + if (definition != null) { + return ResponseUtility.Build.okRequest(); + } + return ResponseUtility.Build.notFound(); + } + catch (Exception e){ + return ResponseUtility.Build.internalServerErrorWithMessage(e.getMessage()); + } + } + + private OTFDeploymentResponse generateResponseFromDeployment(DeploymentEntity deployment) { + if (deployment == null) { + return new OTFDeploymentResponse(null, null, null, -1); + } + String deploymentId = deployment.getId(); + String id = deployment.getDeployedProcessDefinitions().get(0).getId(); + String key = deployment.getDeployedProcessDefinitions().get(0).getKey(); + int version = deployment.getDeployedProcessDefinitions().get(0).getVersion(); + return new OTFDeploymentResponse(deploymentId, key, id, version); + } +} diff --git a/otf-camunda/src/main/java/org/oran/otf/spring/configuration/HttpSecurityConfiguration.java b/otf-camunda/src/main/java/org/oran/otf/spring/configuration/HttpSecurityConfiguration.java new file mode 100644 index 0000000..56b5901 --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/spring/configuration/HttpSecurityConfiguration.java @@ -0,0 +1,66 @@ +/* Copyright (c) 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.oran.otf.spring.configuration; + +import org.apache.catalina.Context; +import org.apache.catalina.connector.Connector; +import org.apache.tomcat.util.descriptor.web.SecurityCollection; +import org.apache.tomcat.util.descriptor.web.SecurityConstraint; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; +import org.springframework.boot.web.servlet.server.ServletWebServerFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +@EnableConfigurationProperties +public class HttpSecurityConfiguration { + @Value("${security.server.port.http}") + private int httpPort; + + @Value("${security.server.port}") + private int httpsPort; + + @Value("${security.https-only}") + private boolean httpsOnly; + @Bean + public ServletWebServerFactory servletContainer() { + TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory() { + @Override + protected void postProcessContext(Context context) { + SecurityConstraint securityConstraint = new SecurityConstraint(); + if(httpsOnly){ securityConstraint.setUserConstraint("CONFIDENTIAL");} + SecurityCollection collection = new SecurityCollection(); + collection.addPattern("/*"); + securityConstraint.addCollection(collection); + context.addConstraint(securityConstraint); + } + }; + tomcat.addAdditionalTomcatConnectors(redirectConnector()); + return tomcat; + } + + private Connector redirectConnector() { + Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol"); + connector.setScheme("http"); + connector.setPort(httpPort); + connector.setSecure(false); + if(httpsOnly) { connector.setRedirectPort(httpsPort); } + return connector; + } +} \ No newline at end of file diff --git a/otf-camunda/src/main/java/org/oran/otf/spring/configuration/JerseyConfiguration.java b/otf-camunda/src/main/java/org/oran/otf/spring/configuration/JerseyConfiguration.java new file mode 100644 index 0000000..487a8da --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/spring/configuration/JerseyConfiguration.java @@ -0,0 +1,83 @@ +/* Copyright (c) 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.oran.otf.spring.configuration; + +import org.oran.otf.service.impl.DeleteProcessInstanceServiceImpl; +import org.oran.otf.service.impl.DeleteTestDefinitionServiceImpl; +import org.oran.otf.service.impl.DeveloperServiceImpl; +import org.oran.otf.service.impl.HealthServiceImpl; +import org.oran.otf.service.impl.ProcessInstanceCompletionServiceImpl; +import org.oran.otf.service.impl.TestControlUnitServiceImpl; +import org.oran.otf.service.impl.TestDefinitionDeploymentServiceImpl; + +import java.util.logging.Logger; +import org.glassfish.jersey.logging.LoggingFeature; +import org.glassfish.jersey.media.multipart.MultiPartFeature; +import org.glassfish.jersey.server.ResourceConfig; +import org.glassfish.jersey.server.ServerProperties; +import org.glassfish.jersey.servlet.ServletContainer; +import org.glassfish.jersey.servlet.ServletProperties; +import org.springframework.boot.web.servlet.ServletRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/* + * Note: JerseyAutoConfiguration is used to incorporate camunda rest api In this configuration class + * we create a new servletregistrationbean to serve at /service/* while camunda serves at /rest/* + */ +@Configuration +public class JerseyConfiguration { + + private static final Logger logger = Logger.getLogger(JerseyConfiguration.class.getName()); + + @Bean + public ServletRegistrationBean applicationJersey() { + ServletRegistrationBean applicationJersey = + new ServletRegistrationBean<>(new ServletContainer(new ApplicationJerseyConfig())); + applicationJersey.addUrlMappings("/otf/*"); + applicationJersey.setName("Open Test Framework - Test Control Unit"); + applicationJersey.setLoadOnStartup(0); + return applicationJersey; + } + + public class ApplicationJerseyConfig extends ResourceConfig { + + public ApplicationJerseyConfig() { + register(MultiPartFeature.class); +// register( +// new OTFLoggingFeature( +// Logger.getLogger(getClass().getName()), +// Level.INFO, +// LoggingFeature.Verbosity.PAYLOAD_ANY, +// 8192)); + + logger.info("Registering REST resources."); + register(TestControlUnitServiceImpl.class); + register(HealthServiceImpl.class); + register(DeleteTestDefinitionServiceImpl.class); + register(ProcessInstanceCompletionServiceImpl.class); + register(TestDefinitionDeploymentServiceImpl.class); + register(DeleteProcessInstanceServiceImpl.class); + register(DeveloperServiceImpl.class); + + property(ServletProperties.FILTER_FORWARD_ON_404, true); + property(ServerProperties.RESPONSE_SET_STATUS_OVER_SEND_ERROR, true); + register(new LoggingFeature(logger)); + logger.info("Finished registering REST resources."); + } + } +} diff --git a/otf-camunda/src/main/java/org/oran/otf/spring/configuration/OTFLoggingFeature.java b/otf-camunda/src/main/java/org/oran/otf/spring/configuration/OTFLoggingFeature.java new file mode 100644 index 0000000..36bfb51 --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/spring/configuration/OTFLoggingFeature.java @@ -0,0 +1,242 @@ +/* Copyright (c) 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.oran.otf.spring.configuration; + +import java.io.BufferedInputStream; +import java.io.ByteArrayOutputStream; +import java.io.FilterOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URI; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.Base64; +import java.util.List; +import java.util.Objects; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.client.ClientRequestContext; +import javax.ws.rs.client.ClientRequestFilter; +import javax.ws.rs.client.ClientResponseContext; +import javax.ws.rs.client.ClientResponseFilter; +import javax.ws.rs.container.ContainerRequestContext; +import javax.ws.rs.container.ContainerRequestFilter; +import javax.ws.rs.container.ContainerResponseContext; +import javax.ws.rs.container.ContainerResponseFilter; +import javax.ws.rs.core.FeatureContext; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.ext.WriterInterceptor; +import javax.ws.rs.ext.WriterInterceptorContext; +import org.glassfish.jersey.logging.LoggingFeature; +import org.glassfish.jersey.message.MessageUtils; + +public class OTFLoggingFeature extends LoggingFeature implements ContainerRequestFilter, ContainerResponseFilter, + ClientRequestFilter, ClientResponseFilter, WriterInterceptor { + + private static final boolean printEntity = true; + private static final int maxEntitySize = 8 * 1024; + private final Logger logger = Logger.getLogger("OTFLoggingFeature"); + private static final String ENTITY_LOGGER_PROPERTY = OTFLoggingFeature.class.getName(); + private static final String NOTIFICATION_PREFIX = "* "; + private static final String REQUEST_PREFIX = "> "; + private static final String RESPONSE_PREFIX = "< "; + private static final String AUTHORIZATION = "Authorization"; + private static final String EQUAL = " = "; + private static final String HEADERS_SEPARATOR = ", "; + private static List requestHeaders; + + static { + requestHeaders = new ArrayList<>(); + requestHeaders.add(AUTHORIZATION); + } + + public OTFLoggingFeature(Logger logger, Level level, Verbosity verbosity, Integer maxEntitySize) { + super(logger, level, verbosity, maxEntitySize); + } + + @Override + public boolean configure(FeatureContext context) { + context.register(this); + return true; + } + + private Object getEmail(Object authorization){ + try{ + String encoded = ((String) authorization).split(" ")[1]; + String decoded = new String(Base64.getDecoder().decode(encoded)); + return decoded.split(":")[0]; + } + catch (Exception e){ + return authorization; + } + } + + @Override + public void filter(final ClientRequestContext context) { + final StringBuilder b = new StringBuilder(); + printHeaders(b, context.getStringHeaders()); + printRequestLine(b, "Sending client request", context.getMethod(), context.getUri()); + + if (printEntity && context.hasEntity()) { + final OutputStream stream = new LoggingStream(b, context.getEntityStream()); + context.setEntityStream(stream); + context.setProperty(ENTITY_LOGGER_PROPERTY, stream); + // not calling log(b) here - it will be called by the interceptor + } else { + log(b); + } + } + + @Override + public void filter(final ClientRequestContext requestContext, final ClientResponseContext responseContext) throws IOException { + final StringBuilder b = new StringBuilder(); + printResponseLine(b, "Client response received", responseContext.getStatus()); + + if (printEntity && responseContext.hasEntity()) { + responseContext.setEntityStream(logInboundEntity(b, responseContext.getEntityStream(), + MessageUtils.getCharset(responseContext.getMediaType()))); + } + log(b); + } + + @Override + public void filter(final ContainerRequestContext context) throws IOException { + final StringBuilder b = new StringBuilder(); + printHeaders(b, context.getHeaders()); + printRequestLine(b, "Server has received a request", context.getMethod(), context.getUriInfo().getRequestUri()); + + if (printEntity && context.hasEntity()) { + context.setEntityStream(logInboundEntity(b, context.getEntityStream(), MessageUtils.getCharset(context.getMediaType()))); + } + log(b); + } + + @Override + public void filter(final ContainerRequestContext requestContext, final ContainerResponseContext responseContext) { + final StringBuilder b = new StringBuilder(); + printResponseLine(b, "Server responded with a response", responseContext.getStatus()); + + if (printEntity && responseContext.hasEntity()) { + final OutputStream stream = new LoggingStream(b, responseContext.getEntityStream()); + responseContext.setEntityStream(stream); + requestContext.setProperty(ENTITY_LOGGER_PROPERTY, stream); + // not calling log(b) here - it will be called by the interceptor + } else { + log(b); + } + } + + @Override + public void aroundWriteTo(final WriterInterceptorContext writerInterceptorContext) throws IOException, WebApplicationException { + final LoggingStream stream = (LoggingStream) writerInterceptorContext.getProperty(ENTITY_LOGGER_PROPERTY); + writerInterceptorContext.proceed(); + if (stream != null) { + log(stream.getStringBuilder(MessageUtils.getCharset(writerInterceptorContext.getMediaType()))); + } + } + + private static class LoggingStream extends FilterOutputStream { + private final StringBuilder b; + private final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + + LoggingStream(final StringBuilder b, final OutputStream inner) { + super(inner); + + this.b = b; + } + + StringBuilder getStringBuilder(Charset charset) { + // write entity to the builder + final byte[] entity = byteArrayOutputStream.toByteArray(); + + b.append(new String(entity, 0, Math.min(entity.length, maxEntitySize), charset)); + if (entity.length > maxEntitySize) { + b.append("...more..."); + } + b.append('\n'); + + return b; + } + + public void write(final int i) throws IOException { + if (byteArrayOutputStream.size() <= maxEntitySize) { + byteArrayOutputStream.write(i); + } + out.write(i); + } + } + + private void printHeaders(StringBuilder b, MultivaluedMap headers) { + for (String header : requestHeaders) { + if (Objects.nonNull(headers.get(header))) { + if(header.equalsIgnoreCase("Authorization")){ + b.append(header).append(EQUAL).append(getEmail(headers.get(header).get(0))).append(HEADERS_SEPARATOR); + } + else{ + b.append(header).append(EQUAL).append(headers.get(header)).append(HEADERS_SEPARATOR); + } + } + } + int lastIndex = b.lastIndexOf(HEADERS_SEPARATOR); + if (lastIndex != -1) { + b.delete(lastIndex, lastIndex + HEADERS_SEPARATOR.length()); + b.append("\n"); + } + } + + private void log(final StringBuilder b) { + String message = b.toString(); + if (logger != null) { + logger.info(message); + } + } + + private void printRequestLine(final StringBuilder b, final String note, final String method, final URI uri) { + b.append(NOTIFICATION_PREFIX) + .append(note) + .append(" on thread ").append(Thread.currentThread().getId()) + .append(REQUEST_PREFIX).append(method).append(" ") + .append(uri.toASCIIString()).append("\n"); + } + + private void printResponseLine(final StringBuilder b, final String note, final int status) { + b.append(NOTIFICATION_PREFIX) + .append(note) + .append(" on thread ").append(Thread.currentThread().getId()) + .append(RESPONSE_PREFIX) + .append(Integer.toString(status)) + .append("\n"); + } + + private InputStream logInboundEntity(final StringBuilder b, InputStream stream, final Charset charset) throws IOException { + if (!stream.markSupported()) { + stream = new BufferedInputStream(stream); + } + stream.mark(maxEntitySize + 1); + final byte[] entity = new byte[maxEntitySize + 1]; + final int entitySize = stream.read(entity); + b.append(new String(entity, 0, Math.min(entitySize, maxEntitySize), charset)); + if (entitySize > maxEntitySize) { + b.append("...more..."); + } + b.append('\n'); + stream.reset(); + return stream; + } +} \ No newline at end of file diff --git a/otf-camunda/src/main/java/org/oran/otf/spring/configuration/OTFMongoConfiguration.java b/otf-camunda/src/main/java/org/oran/otf/spring/configuration/OTFMongoConfiguration.java new file mode 100644 index 0000000..665823f --- /dev/null +++ b/otf-camunda/src/main/java/org/oran/otf/spring/configuration/OTFMongoConfiguration.java @@ -0,0 +1,78 @@ +/* Copyright (c) 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.oran.otf.spring.configuration; + +import com.mongodb.MongoClient; +import com.mongodb.MongoClientOptions; +import com.mongodb.MongoCredential; +import com.mongodb.ServerAddress; +import java.util.ArrayList; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.mongodb.config.AbstractMongoConfiguration; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.repository.config.EnableMongoRepositories; + +@Configuration +@EnableMongoRepositories(basePackages = "org.oran.otf.common.repository") +public class OTFMongoConfiguration extends AbstractMongoConfiguration { + @Value("${otf.mongo.hosts}") + private String hosts; + + @Value("${otf.mongo.username}") + private String username; + + @Value("${otf.mongo.password}") + private String password; + + @Value("${otf.mongo.replica-set}") + private String replicaSet; + + @Value("${otf.mongo.database}") + private String database; + + @Override + protected String getDatabaseName() { + return database; + } + + @Override + public MongoClient mongoClient() { + MongoCredential credential = + MongoCredential.createScramSha1Credential(username, database, password.toCharArray()); + + MongoClientOptions options = + MongoClientOptions.builder().sslEnabled(false).requiredReplicaSetName(replicaSet).build(); + + String[] hostArray = hosts.split(","); + ArrayList hosts = new ArrayList<>(); + + for (String host : hostArray) { + String[] hostSplit = host.split(":"); + hosts.add(new ServerAddress(hostSplit[0], Integer.parseInt(hostSplit[1]))); + } + + return new MongoClient(hosts, credential, options); + } + + @Override + public @Bean + MongoTemplate mongoTemplate() { + return new MongoTemplate(mongoClient(), database); + } +} diff --git a/otf-camunda/src/main/resources/META-INF/processes.xml.off b/otf-camunda/src/main/resources/META-INF/processes.xml.off new file mode 100644 index 0000000..77e5a39 --- /dev/null +++ b/otf-camunda/src/main/resources/META-INF/processes.xml.off @@ -0,0 +1,13 @@ + + + + + + false + true + + + + \ No newline at end of file diff --git a/otf-camunda/src/main/resources/META-INF/securityFilterRules.json b/otf-camunda/src/main/resources/META-INF/securityFilterRules.json new file mode 100644 index 0000000..ef7694c --- /dev/null +++ b/otf-camunda/src/main/resources/META-INF/securityFilterRules.json @@ -0,0 +1,52 @@ +{ + "pathFilter": { + "deniedPaths": [ + { + "path": "/camunda/api/engine/.*", + "methods": "*" + }, + { + "path": "/camunda/api/cockpit/.*", + "methods": "*" + }, + { + "path": "/camunda/app/tasklist/{engine}/.*", + "methods": "*" + }, + { + "path": "/camunda/app/cockpit/{engine}/.*", + "methods": "*" + } + ], + "allowedPaths": [ + { + "path": "/camunda/api/engine/engine/", + "methods": "GET" + }, + { + "path": "/camunda/api/{app:cockpit}/plugin/{engine}/static/.*", + "methods": "GET" + }, + { + "path": "/camunda/api/{app:cockpit}/plugin/{plugin}/{engine}/.*", + "methods": "*", + "authorizer": "org.camunda.bpm.webapp.impl.security.filter.EngineRequestAuthorizer" + }, + { + "path": "/camunda/api/engine/engine/{engine}/.*", + "methods": "*", + "authorizer": "org.camunda.bpm.webapp.impl.security.filter.EngineRequestAuthorizer" + }, + { + "path": "/camunda/app/{app:cockpit}/{engine}/.*", + "methods": "*", + "authorizer": "org.camunda.bpm.webapp.impl.security.filter.ApplicationRequestAuthorizer" + }, + { + "path": "/camunda/app/{app:tasklist}/{engine}/.*", + "methods": "*", + "authorizer": "org.camunda.bpm.webapp.impl.security.filter.ApplicationRequestAuthorizer" + } + ] + } +} diff --git a/otf-camunda/src/main/resources/application.yaml b/otf-camunda/src/main/resources/application.yaml new file mode 100644 index 0000000..bf92302 --- /dev/null +++ b/otf-camunda/src/main/resources/application.yaml @@ -0,0 +1,108 @@ +otf: + environment: ${ENV} + mode: 'debug' + camunda: + bpm: + admin-user: + id: 'username' + password: 'password' + firstName: 'firstname' + executor: + async.core-pool-size: 50 + async.max-pool-size: 400 + async.queue-capacity: 25 + external-task-client: + retry-limit: 0 + fetch-interval-ms: 1000 + lock-duration-ms: 43200000 + max-tasks: 10 + worker-id: 'otf-camunda-etw' + graceful-shutdown: + wait-time: 300000 + executors-active: ${EXECUTORS_ACTIVE} + mysql: + url: jdbc:mysql://${OTF_CAMUNDA_DB_URL}?useSSL=false&serverTimezone=UTC #&logger=com.mysql.cj.log.Slf4JLogger&profileSQL=true + username: ${OTF_CAMUNDA_DB_USERNAME} + password: ${OTF_CAMUNDA_DB_PASSWORD} + cadi: + enabled: true + aaf-mech-id: ${AAF_ID} + aaf-mech-password: ${AAF_MECH_PASSWORD} + aaf-perm-type: ${AAF_PERM_TYPE} + hostname: ${CADI_HOSTNAME} + keyfile: ${CADI_KEYFILE} + aaf-call-timeout: 10000 + aaf-conn-timeout: 6000 + aaf-default-realm: 'localhost' + aaf-env: 'PROD' + aaf-locate-url: 'https://localhost' + aaf-lur-class: 'org.onap.aaf.cadi.aaf.v2_0.AAFLurPerm' + aaf-url: 'https://localhost' + basic-realm: 'localhost' + basic-warn: true + cadi-latitude: '38.62782' + cadi-logLevel: '16384' + cadi-longitude: '-90.19458' + cadi-protocols: 'TLSv1.1,TLSv1.2' + + mongo: + hosts: ${OTF_MONGO_HOSTS} + username: ${OTF_MONGO_USERNAME} + password: ${OTF_MONGO_PASSWORD} + replica-set: ${OTF_MONGO_REPLICASET} + database: ${OTF_MONGO_DATABASE} + ssl: + key-store-type: 'PKCS12' + keystore-path: ${OTF_CERT_PATH} + keystore-password: ${OTF_CERT_PASS} + +#https://stackoverflow.com/questions/50387638/spring-boot-jersey-type-filter-bad-request-400-for-service-consumes-multipar/50423639#50423639 +spring.jersey.filter.order: -100000 +spring.main.allow-bean-definition-overriding: true +server: + port: 8443 + port.http: 8000 + tomcat.max-threads: 800 +# ssl: + key-store-type: 'PKCS12' + key-store: ${OTF_CERT_PATH} + key-store-password: ${OTF_CERT_PASS} +security: + https-only: true + require-ssl: false + server.port: 8443 + server.port.http: 8080 +# server.tomcat.max-threads=800 +# security.require-ssl=true +# server.ssl.key-store-type=PKCS12 +# server.ssl.key-store=${OTF_CERT_PATH} +# server.ssl.key-store-password=${OTF_CERT_PASS} + +camunda.bpm.job-execution.enabled: true +camunda.bpm.job-execution.queueSize: 25 +camunda.bpm.job-execution.corePoolSize: 50 +camunda.bpm.job-execution.maxPoolSize: 400 +#camunda.bpm.job-execution.max-jobs-per-acquisition: 99 + +camunda.bpm.database.schema-update: true +logging: + level: + com.zaxxer.hikari: DEBUG + +logging.file.max-history: 5 +logging.file: otf/logs/camunda.log +logging.path: otf/logs + +#logging: +# level: +# org.camunda.bpm.engine.jobexecutor: OFF +# org.camunda.bpm.engine.context: OFF +# org.camunda.bpm.extension.reactor.projectreactor: OFF + #org.camunda.bpm.extension.reactor.projectreactor.routing.ConsumerFilterRouter: OFF + #org.camunda.bpm.extension.reactor.projectreactor: INFO + #org.camunda.engine.ProcessEngineException: INFO + #org.camunda.bpm.cfg: DEBUG + #org.camunda.bpm.engine.impl.persistence.entity.JobEntity: DEBUG + #org.camunda.bpm.engine.cmd: DEBUG + #org.springframework.web: DEBUG + #org.camunda.bpm.engine.rest: DEBUG diff --git a/otf-camunda/src/main/resources/banner.txt b/otf-camunda/src/main/resources/banner.txt new file mode 100644 index 0000000..7a62038 --- /dev/null +++ b/otf-camunda/src/main/resources/banner.txt @@ -0,0 +1,12 @@ + U ___ u _____ _____ + \/"_ \/ |_ " _| |" ___| + | | | | | | U| |_ u + .-,_| |_| | /| |\ \| _|/ + \_)-\___/ u |_|U |_| + \\ _// \\_ )(\\,- + (__) (__) (__) (__)(_/ + + Open Test Framework: (Blitzcrank) + Spring-Boot: (v2.1.4.RELEASE) + Camunda BPM: (v7.10.4-ee) + Camunda BPM Spring Boot Starter: (v3.2.0) diff --git a/otf-camunda/src/main/resources/bpmn/pingGoogleDNS.bpmn b/otf-camunda/src/main/resources/bpmn/pingGoogleDNS.bpmn new file mode 100644 index 0000000..7ef5852 --- /dev/null +++ b/otf-camunda/src/main/resources/bpmn/pingGoogleDNS.bpmn @@ -0,0 +1,89 @@ + + + + + SequenceFlow_1gpkkbm + + + SequenceFlow_1psgifi + + + + + + + + SequenceFlow_1gpkkbm + SequenceFlow_12x2s0z + var vthInput = { + vthInput: { + Task_1r783jz: { + testData: { + targetHost: "8.8.8.8", + useJumpServer: false + }, + vthName: "Unused parameter", + testConfig: {} + } + } +}; + +execution.setVariable("vthInput", JSON.stringify(vthInput)); + + + SequenceFlow_12x2s0z + SequenceFlow_054puyx + + + SequenceFlow_054puyx + SequenceFlow_1psgifi + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/otf-camunda/src/main/resources/mail-config.properties b/otf-camunda/src/main/resources/mail-config.properties new file mode 100644 index 0000000..38c3819 --- /dev/null +++ b/otf-camunda/src/main/resources/mail-config.properties @@ -0,0 +1,7 @@ +# send mails via SMTP +mail.transport.protocol=smtp + +mail.smtp.host=localhost +mail.smtp.port=25 +mail.smtp.auth=false +mail.smtp.ssl.enable=false \ No newline at end of file diff --git a/otf-camunda/src/test/java/org/oran/otf/api/tests/config/DataConfig.java b/otf-camunda/src/test/java/org/oran/otf/api/tests/config/DataConfig.java new file mode 100644 index 0000000..2307939 --- /dev/null +++ b/otf-camunda/src/test/java/org/oran/otf/api/tests/config/DataConfig.java @@ -0,0 +1,21 @@ +/* Copyright (c) 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.oran.otf.api.tests.config; + +public class DataConfig { + +} diff --git a/otf-camunda/src/test/java/org/oran/otf/api/tests/config/InMemoryConfig.java b/otf-camunda/src/test/java/org/oran/otf/api/tests/config/InMemoryConfig.java new file mode 100644 index 0000000..06e8464 --- /dev/null +++ b/otf-camunda/src/test/java/org/oran/otf/api/tests/config/InMemoryConfig.java @@ -0,0 +1,21 @@ +/* Copyright (c) 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.oran.otf.api.tests.config; + +public class InMemoryConfig { + +} diff --git a/otf-camunda/src/test/java/org/oran/otf/api/tests/shared/MemoryDatabase.java b/otf-camunda/src/test/java/org/oran/otf/api/tests/shared/MemoryDatabase.java new file mode 100644 index 0000000..edb8b72 --- /dev/null +++ b/otf-camunda/src/test/java/org/oran/otf/api/tests/shared/MemoryDatabase.java @@ -0,0 +1,21 @@ +/* Copyright (c) 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.oran.otf.api.tests.shared; + +public class MemoryDatabase { + +} diff --git a/otf-camunda/src/test/java/org/oran/otf/api/tests/unit/common/utility/http/HeadersUtilityTest.java b/otf-camunda/src/test/java/org/oran/otf/api/tests/unit/common/utility/http/HeadersUtilityTest.java new file mode 100644 index 0000000..ae0e133 --- /dev/null +++ b/otf-camunda/src/test/java/org/oran/otf/api/tests/unit/common/utility/http/HeadersUtilityTest.java @@ -0,0 +1,74 @@ +/* Copyright (c) 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.oran.otf.api.tests.unit.common.utility.http; + +import org.oran.otf.common.utility.http.HeadersUtility; +import java.util.HashMap; +import java.util.Map; +import org.assertj.core.api.Assertions; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class HeadersUtilityTest { + public Map headers; + + @Before + public void setup(){ + headers = new HashMap<>(); + headers.put("GET", "/some/random/route/exmaple"); + headers.put("Host", "localhost"); + headers.put("Authorization", "Basic som3R4ndOmStringK3y"); + headers.put("User-Agent", "James Bond"); + headers.put("Accept", "*/*"); + + } + @Test + public void authIsMasked(){ + + System.out.println("Authorization header in format 'Basic: key' will mask the auth with 4 *"); + Map maskedAuth = HeadersUtility.maskAuth(headers); + Assertions.assertThat(maskedAuth.get("Authorization")).isEqualTo("Basic ****"); + } + @Test + public void originalHeadersDidNotChange(){ + System.out.println("Make sure HeaderUtility.maskAuth() does not change the map passed to function"); + Map maskedAuth = HeadersUtility.maskAuth(headers); + Assertions.assertThat(headers.get("Authorization")).isEqualTo("Basic som3R4ndOmStringK3y"); + } + + @Test + public void noAuthHeadersPassed(){ + System.out.println("Make sure HeaderUtility.maskAuth() works if headers are missing a Authorization field"); + headers.remove("Authorization"); + Map maskedAuth = HeadersUtility.maskAuth(headers); + Assertions.assertThat(maskedAuth).isEqualTo(headers); + } + + @Test + public void authKeyFormatHasNoSpace(){ + System.out.println("Make sure HeaderUtility.maskAuth() works if Authorization does not follow format 'Authorization: [Type] [Key]'"); + headers.put("Authorization", "Basicsom3R4ndOmStringK3y"); + Map maskedAuth = HeadersUtility.maskAuth(headers); + Assertions.assertThat(maskedAuth.get("Authorization")).isEqualTo("****"); + } + +} diff --git a/otf-camunda/src/test/resources/application-test.properties b/otf-camunda/src/test/resources/application-test.properties new file mode 100644 index 0000000..e69de29 diff --git a/otf-frontend/.dockerignore b/otf-frontend/.dockerignore new file mode 100644 index 0000000..ae84271 --- /dev/null +++ b/otf-frontend/.dockerignore @@ -0,0 +1 @@ +./node_modules \ No newline at end of file diff --git a/otf-frontend/.gitignore b/otf-frontend/.gitignore new file mode 100644 index 0000000..91cebbb --- /dev/null +++ b/otf-frontend/.gitignore @@ -0,0 +1,121 @@ + +# Created by https://www.gitignore.io/api/node,angular + +### Angular ### +## Angular ## +# compiled output +/dist +/tmp +/app/**/*.js +/app/**/*.js.map +package-lock.json + +# dependencies +/node_modules +/bower_components + +# IDEs and editors +/.idea +/.vscode + +# misc +/.sass-cache +/connect.lock +/coverage/* +/libpeerconnection.log +npm-debug.log +testem.log +/typings + +# e2e +/e2e/*.js +/e2e/*.map + +#System Files +.DS_Store + +### Node ### +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# TypeScript v1 declaration files +typings/ + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +.env + +# parcel-bundler cache (https://parceljs.org/) +.cache + +# next.js build output +.next + +# nuxt.js build output +.nuxt + +# vuepress build output +.vuepress/dist + +# Serverless directories +.serverless + + +# End of https://www.gitignore.io/api/node,angular +server/config/default.json + +# certs +server/config/cert/*.pem +server/config/cert/otf.pem +server/config/cert/privateKey.pem +# env script +envScript.sh diff --git a/otf-frontend/Dockerfile b/otf-frontend/Dockerfile new file mode 100644 index 0000000..a3fd845 --- /dev/null +++ b/otf-frontend/Dockerfile @@ -0,0 +1,31 @@ +FROM node:8.16-alpine + +ENV ENV=development +ENV NAMESPACE=namespace +ENV APP_NAME=otf-frontend +ENV APP_VERSION=1.0 +ENV OTF_URL=https://loaclhost:32524/ +ENV OTF_EMAIL=email@email.com +ENV AUTHENTICATION_SECRET=/ytoYB+iD5HUuDLmeqStcoUPwqw= +ENV SERVICEAPI_URL=https://localhost:32303/otf/api/ +ENV SERVICEAPI_URIEXECUTETESTINSTANCE=testInstance/execute/v1/id/ +ENV SERVICEAPI_AAFID=username +ENV SERVICEAPI_AAFPASSWORD=password +ENV CAMUNDAAPI_URL=https://localhost:31313/ +ENV CAMUNDAAPI_AAFID=username +ENV CAMUNDAAPI_AAFPASSWORD=password +ENV MONGO_BASEURL=localhost:27017/ +ENV MONGO_DBOTF=otf +ENV MONGO_REPLICASET=mongoOTF +ENV MONGO_USERNAME=username +ENV MONGO_PASSWORD=password + +COPY . /home/node +WORKDIR /home/node + +RUN mkdir -p /otf/logs + +RUN npm install --unsafe-perm +RUN npm run-script build + +ENTRYPOINT [ "npm", "start" ] diff --git a/otf-frontend/Jenkinsfile b/otf-frontend/Jenkinsfile new file mode 100644 index 0000000..0cc1a01 --- /dev/null +++ b/otf-frontend/Jenkinsfile @@ -0,0 +1,153 @@ +#!/usr/bin/env groovy + +properties([[$class: 'ParametersDefinitionProperty', parameterDefinitions: [ +[$class: 'hudson.model.StringParameterDefinition', name: 'PHASE', defaultValue: "BUILD"], +[$class: 'hudson.model.StringParameterDefinition', name: 'ENV', defaultValue: "dev"], +[$class: 'hudson.model.StringParameterDefinition', name: 'MECHID', defaultValue: "username"], +[$class: 'hudson.model.StringParameterDefinition', name: 'KUBE_CONFIG', defaultValue: "kubeConfig-dev"], +[$class: 'hudson.model.StringParameterDefinition', name: 'OTF_MONGO_DB', defaultValue: "otf_mongo_dev_db"], +[$class: 'hudson.model.StringParameterDefinition', name: 'OTF_CAMUNDA_DB', defaultValue: "otf_camunda_dev_db"], +[$class: 'hudson.model.StringParameterDefinition', name: 'TILLER_NAMESPACE', defaultValue: ""] +]]]) + +echo "Build branch: ${env.BRANCH_NAME}" + +node("docker"){ + stage 'Checkout' + checkout scm + PHASES=PHASE.tokenize( '_' ); + echo "PHASES : " + PHASES + + + ARTIFACT_ID="otf-frontend"; + VERSION="Camille.1.0.3"; + //TODO: deal with namespace and docker registry + NAMESPACE="" + DOCKER_REGISTRY="" + + if( ENV.equalsIgnoreCase("dev") ){ + IMAGE_NAME=DOCKER_REGISTRY + "/" + NAMESPACE + "/" + ARTIFACT_ID + ":" + VERSION + } + if( ENV.equalsIgnoreCase("prod") || ENV.equalsIgnoreCase("prod-dr")){ + IMAGE_NAME=DOCKER_REGISTRY + "/" + NAMESPACE + ".prod" + "/" + ARTIFACT_ID + ":" + VERSION + } + if( ENV.equalsIgnoreCase("st") ){ + IMAGE_NAME=DOCKER_REGISTRY + "/" + NAMESPACE + ".st" + "/" + ARTIFACT_ID + ":" + VERSION + } + echo "Artifact: " + IMAGE_NAME + + withEnv(["PATH=${env.PATH}:${env.WORKSPACE}/linux-amd64", "HELM_HOME=${env.WORKSPACE}"]) { + + echo "PATH=${env.PATH}" + echo "HELM_HOME=${env.HELM_HOME}" + + withCredentials([usernamePassword(credentialsId: MECHID, usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD')]) { + + // sh """ + // docker login $DOCKER_REGISTRY --username $USERNAME --password $PASSWORD + // """ + + if (PHASES.contains("BUILD")){ + stage 'Publish Artifact' + + + echo "Artifact: " + IMAGE_NAME + + sh """ + docker login $DOCKER_REGISTRY --username $USERNAME --password $PASSWORD + docker build --no-cache -t $IMAGE_NAME . + docker push $IMAGE_NAME + """ + + + } + } + + if (PHASES.contains("DEPLOY") || PHASES.contains("UNDEPLOY")) { + + stage 'Init Helm' + + //check if helm exists if not install + if(fileExists('linux-amd64/helm')){ + sh """ + echo "helm is already installed" + """ + } + else{ + //download helm + sh """ + echo "installing helm" + wget https://storage.googleapis.com/kubernetes-helm/helm-v2.8.2-linux-amd64.tar.gz + tar -xf helm-v2.8.2-linux-amd64.tar.gz + rm helm-v2.8.2-linux-amd64.tar.gz + """ + } + + withCredentials([file(credentialsId: KUBE_CONFIG, variable: 'KUBECONFIG')]) { + + dir('helm'){ + //check if charts are valid, and then perform dry run, if successful then upgrade/install charts + + if (PHASES.contains("UNDEPLOY") ) { + stage 'Undeploy' + + sh """ + helm delete --tiller-namespace=$TILLER_NAMESPACE --purge $ARTIFACT_ID + """ + } + + //NOTE Double quotes are used below to access groovy variables like artifact_id and tiller_namespace + if (PHASES.contains("DEPLOY") ){ + stage 'Deploy' + withCredentials([ + usernamePassword(credentialsId: OTF_MONGO_DB, usernameVariable: 'USERNAME_MONGO', passwordVariable: 'PASSWORD_MONGO'), + usernamePassword(credentialsId: 'FEATHERS_AUTH', usernameVariable: 'USER', passwordVariable: 'AUTHENTICATION_SECRET') + ]) { + + sh """ + echo "Validate Yaml" + helm lint $ARTIFACT_ID + + echo "View Helm Templates" + helm template $ARTIFACT_ID \ + --set appName=$ARTIFACT_ID \ + --set version=$VERSION \ + --set image=$IMAGE_NAME \ + --set namespace=$TILLER_NAMESPACE \ + --set env=$ENV \ + --set AUTHENTICATION_SECRET=$AUTHENTICATION_SECRET \ + --set mongo.username=$USERNAME_MONGO \ + --set mongo.password=$PASSWORD_MONGO + + echo "Perform Dry Run Of Install" + helm upgrade --tiller-namespace=$TILLER_NAMESPACE --install --dry-run $ARTIFACT_ID $ARTIFACT_ID \ + --set appName=$ARTIFACT_ID \ + --set version=$VERSION \ + --set image=$IMAGE_NAME \ + --set namespace=$TILLER_NAMESPACE \ + --set env=$ENV \ + --set AUTHENTICATION_SECRET=$AUTHENTICATION_SECRET \ + --set mongo.username=$USERNAME_MONGO \ + --set mongo.password=$PASSWORD_MONGO + + echo "Helm Install/Upgrade" + helm upgrade --tiller-namespace=$TILLER_NAMESPACE --install --timeout 1000 $ARTIFACT_ID $ARTIFACT_ID \ + --set appName=$ARTIFACT_ID \ + --set version=$VERSION \ + --set image=$IMAGE_NAME \ + --set namespace=$TILLER_NAMESPACE \ + --set env=$ENV \ + --set AUTHENTICATION_SECRET=$AUTHENTICATION_SECRET \ + --set mongo.username=$USERNAME_MONGO \ + --set mongo.password=$PASSWORD_MONGO + + """ + } + } + + } + } + } + + } +} diff --git a/otf-frontend/LICENSES.txt b/otf-frontend/LICENSES.txt new file mode 100644 index 0000000..695ac56 --- /dev/null +++ b/otf-frontend/LICENSES.txt @@ -0,0 +1,28 @@ +Unless otherwise specified, all software contained herein is licensed +under the Apache License, Version 2.0 (the "Software License"); +you may not use this software except in compliance with the Software +License. You may obtain a copy of the Software License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the Software License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the Software License for the specific language governing permissions +and limitations under the Software License. + + + +Unless otherwise specified, all documentation contained herein is licensed +under the Creative Commons License, Attribution 4.0 Intl. (the +"Documentation License"); you may not use this documentation except in +compliance with the Documentation License. You may obtain a copy of the +Documentation License at + +https://creativecommons.org/licenses/by/4.0/ + +Unless required by applicable law or agreed to in writing, documentation +distributed under the Documentation License is distributed on an "AS IS" +BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the Documentation License for the specific language governing +permissions and limitations under the Documentation License. diff --git a/otf-frontend/angular.json b/otf-frontend/angular.json new file mode 100644 index 0000000..53e96b5 --- /dev/null +++ b/otf-frontend/angular.json @@ -0,0 +1,147 @@ +{ + "$schema": "./node_modules/@angular/cli/lib/config/schema.json", + "version": 1, + "newProjectRoot": "projects", + "projects": { + "test-ng4": { + "root": "", + "sourceRoot": "client/src", + "projectType": "application", + "architect": { + "build": { + "builder": "@angular-devkit/build-angular:browser", + "options": { + "outputPath": "client/dist", + "index": "client/src/index.html", + "main": "client/src/main.ts", + "tsConfig": "client/src/tsconfig.app.json", + "polyfills": "client/src/polyfills.ts", + "assets": [ + "client/src/assets", + "client/src/favicon.ico" + ], + "scripts": [ + "node_modules/jquery/dist/jquery.js", + "node_modules/datatables.net/js/jquery.dataTables.js" + ], + "styles": [ + "node_modules/font-awesome/css/font-awesome.css", + "node_modules/material-design-icons/iconfont/material-icons.css", + "client/src/styles/app.scss", + "node_modules/bpmn-js/dist/assets/diagram-js.css", + "node_modules/bpmn-js/dist/assets/bpmn-font/css/bpmn-embedded.css", + "node_modules/bpmn-js-properties-panel/styles/properties.less", + "node_modules/bpmn-font/dist/css/bpmn.css", + "node_modules/diagram-js-minimap/assets/diagram-js-minimap.css", + "node_modules/datatables.net-dt/css/jquery.dataTables.css" + ] + }, + "configurations": { + "production": { + "optimization": false, + "outputHashing": "all", + "sourceMap": false, + "extractCss": true, + "namedChunks": false, + "aot": false, + "extractLicenses": true, + "vendorChunk": false, + "buildOptimizer": false, + "fileReplacements": [ + { + "replace": "client/src/environments/environment.ts", + "with": "client/src/environments/environment.prod.ts" + } + ] + } + } + }, + "serve": { + "builder": "@angular-devkit/build-angular:dev-server", + "options": { + "browserTarget": "test-ng4:build" + }, + "configurations": { + "production": { + "browserTarget": "test-ng4:build:production" + } + } + }, + "extract-i18n": { + "builder": "@angular-devkit/build-angular:extract-i18n", + "options": { + "browserTarget": "test-ng4:build" + } + }, + "test": { + "builder": "@angular-devkit/build-angular:karma", + "options": { + "main": "client/src/test.ts", + "karmaConfig": "./karma.conf.js", + "polyfills": "client/src/polyfills.ts", + "tsConfig": "client/src/tsconfig.spec.json", + "scripts": [ + "node_modules/chart.js/dist/Chart.js" + ], + "styles": [ + "node_modules/font-awesome/css/font-awesome.css", + "node_modules/material-design-icons/iconfont/material-icons.css", + "client/src/styles/app.scss" + ], + "assets": [ + "client/src/assets", + "client/src/favicon.ico" + ] + } + }, + "lint": { + "builder": "@angular-devkit/build-angular:tslint", + "options": { + "tsConfig": [ + "client/src/tsconfig.app.json", + "client/src/tsconfig.spec.json" + ], + "exclude": [ + "**/node_modules/**" + ] + } + } + } + }, + "test-ng4-e2e": { + "root": "", + "sourceRoot": "", + "projectType": "application", + "architect": { + "e2e": { + "builder": "@angular-devkit/build-angular:protractor", + "options": { + "protractorConfig": "./protractor.conf.js", + "devServerTarget": "test-ng4:serve" + } + }, + "lint": { + "builder": "@angular-devkit/build-angular:tslint", + "options": { + "tsConfig": [ + "client/e2e/tsconfig.e2e.json" + ], + "exclude": [ + "**/node_modules/**" + ] + } + } + } + } + }, + "defaultProject": "test-ng4", + "schematics": { + "@schematics/angular:component": { + "prefix": "app", + "styleext": "scss" + }, + "@schematics/angular:directive": { + "prefix": "app" + } + } +} diff --git a/otf-frontend/client/.gitignore b/otf-frontend/client/.gitignore new file mode 100644 index 0000000..f94aed4 --- /dev/null +++ b/otf-frontend/client/.gitignore @@ -0,0 +1,45 @@ +# See http://help.github.com/ignore-files/ for more about ignoring files. + +# compiled output +/tmp +/out-tsc +/dist +/test + +# dependencies +/node_modules +/test +package-lock.json + +# IDEs and editors +/.idea +.project +.classpath +.c9/ +*.launch +.settings/ +*.sublime-workspace + +# IDE - VSCode +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json + +# misc +/.sass-cache +/connect.lock +/coverage +/libpeerconnection.log +npm-debug.log +testem.log +/typings + +# e2e +/e2e/*.js +/e2e/*.map + +# System Files +.DS_Store +Thumbs.db diff --git a/otf-frontend/client/config/.editorconfig b/otf-frontend/client/config/.editorconfig new file mode 100644 index 0000000..a0e8f5a --- /dev/null +++ b/otf-frontend/client/config/.editorconfig @@ -0,0 +1,13 @@ +# Editor configuration, see http://editorconfig.org +root = true + +[*] +charset = utf-8 +indent_style = space +indent_size = 4 +insert_final_newline = true +trim_trailing_whitespace = true + +[*.md] +max_line_length = off +trim_trailing_whitespace = false diff --git a/otf-frontend/client/config/.travis.yml b/otf-frontend/client/config/.travis.yml new file mode 100644 index 0000000..01e3108 --- /dev/null +++ b/otf-frontend/client/config/.travis.yml @@ -0,0 +1,14 @@ +language: node_js +node_js: + - '9' + - '10' + +install: + - npm install + +script: + - npm run test-ci + +cache: + directories: + - node_modules diff --git a/otf-frontend/client/config/karma.conf.js b/otf-frontend/client/config/karma.conf.js new file mode 100644 index 0000000..3be39c4 --- /dev/null +++ b/otf-frontend/client/config/karma.conf.js @@ -0,0 +1,50 @@ +// Karma configuration file, see link for more information +// https://karma-runner.github.io/1.0/config/configuration-file.html + +module.exports = function (config) { + const defaults = { + basePath: '', + frameworks: ['jasmine', '@angular-devkit/build-angular'], + plugins: [ + require('karma-jasmine'), + require('karma-chrome-launcher'), + require('karma-jasmine-html-reporter'), + require('karma-coverage-istanbul-reporter'), + require('@angular-devkit/build-angular/plugins/karma') + ], + client:{ + clearContext: false // leave Jasmine Spec Runner output visible in browser + }, + coverageIstanbulReporter: { + dir: require('path').join(__dirname, 'coverage'), reports: [ 'html', 'lcovonly' ], + fixWebpackSourcePaths: true + }, + angularCli: { + environment: 'dev' + }, + reporters: ['progress', 'kjhtml'], + port: 9876, + colors: true, + logLevel: config.LOG_INFO, + autoWatch: true, + browsers: ['Chrome'], + singleRun: false, + } + + if (process.env.TEST_CI) { + Object.assign(defaults, { + autoWatch: false, + browsers: ['ChromeHeadlessNoSandbox'], + singleRun: true, + customLaunchers: { + ChromeHeadlessNoSandbox: { + base: 'ChromeHeadless', + flags: ['--no-sandbox'] + } + }, + browserNoActivityTimeout: 60000, + }) + } + + config.set(defaults) +}; diff --git a/otf-frontend/client/config/protractor.conf.js b/otf-frontend/client/config/protractor.conf.js new file mode 100644 index 0000000..b1a56c1 --- /dev/null +++ b/otf-frontend/client/config/protractor.conf.js @@ -0,0 +1,28 @@ +// Protractor configuration file, see link for more information +// https://github.com/angular/protractor/blob/master/lib/config.ts + +const { SpecReporter } = require('jasmine-spec-reporter'); + +exports.config = { + allScriptsTimeout: 11000, + specs: [ + './e2e/**/*.e2e-spec.ts' + ], + capabilities: { + 'browserName': 'chrome' + }, + directConnect: true, + baseUrl: 'http://localhost:4200/', + framework: 'jasmine', + jasmineNodeOpts: { + showColors: true, + defaultTimeoutInterval: 30000, + print: function() {} + }, + onPrepare() { + require('ts-node').register({ + project: 'e2e/tsconfig.e2e.json' + }); + jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } })); + } +}; diff --git a/otf-frontend/client/config/tsconfig.json b/otf-frontend/client/config/tsconfig.json new file mode 100644 index 0000000..bcd2543 --- /dev/null +++ b/otf-frontend/client/config/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compileOnSave": false, + "compilerOptions": { + "outDir": "./dist/out-tsc", + "sourceMap": true, + "declaration": false, + "moduleResolution": "node", + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "target": "es5", + "typeRoots": [ + "node_modules/@types" + ], + "lib": [ + "es2017", + "dom" + ] + } +} diff --git a/otf-frontend/client/config/tslint.json b/otf-frontend/client/config/tslint.json new file mode 100644 index 0000000..9e1157b --- /dev/null +++ b/otf-frontend/client/config/tslint.json @@ -0,0 +1,139 @@ +{ + "rulesDirectory": [ + "../../node_modules/codelyzer" + ], + "rules": { + "arrow-return-shorthand": true, + "callable-types": true, + "class-name": true, + "comment-format": [ + true, + "check-space" + ], + "curly": true, + "eofline": true, + "forin": true, + "import-blacklist": [ + true + ], + "import-spacing": true, + "indent": [ + true, + "spaces" + ], + "interface-over-type-literal": true, + "label-position": true, + "max-line-length": [ + true, + 140 + ], + "member-access": false, + "member-ordering": [ + true, + { + "order": [ + "static-field", + "instance-field", + "static-method", + "instance-method" + ] + } + ], + "no-arg": true, + "no-bitwise": true, + "no-console": [ + true, + "debug", + "info", + "time", + "timeEnd", + "trace" + ], + "no-construct": true, + "no-debugger": true, + "no-duplicate-super": true, + "no-empty": false, + "no-empty-interface": true, + "no-eval": true, + "no-inferrable-types": [ + true, + "ignore-params" + ], + "no-misused-new": true, + "no-non-null-assertion": true, + "no-shadowed-variable": true, + "no-string-literal": false, + "no-string-throw": true, + "no-switch-case-fall-through": true, + "no-trailing-whitespace": true, + "no-unnecessary-initializer": true, + "no-unused-expression": true, + "no-use-before-declare": true, + "no-var-keyword": true, + "object-literal-sort-keys": false, + "one-line": [ + true, + "check-open-brace", + "check-catch", + "check-else", + "check-whitespace" + ], + "prefer-const": true, + "quotemark": [ + true, + "single" + ], + "radix": true, + "semicolon": [ + true, + "always" + ], + "triple-equals": [ + true, + "allow-null-check" + ], + "typedef-whitespace": [ + true, + { + "call-signature": "nospace", + "index-signature": "nospace", + "parameter": "nospace", + "property-declaration": "nospace", + "variable-declaration": "nospace" + } + ], + "typeof-compare": true, + "unified-signatures": true, + "variable-name": false, + "whitespace": [ + true, + "check-branch", + "check-decl", + "check-operator", + "check-separator", + "check-type" + ], + "directive-selector": [ + true, + "attribute", + "app", + "camelCase" + ], + "component-selector": [ + true, + "element", + "app", + "kebab-case" + ], + "use-input-property-decorator": true, + "use-output-property-decorator": true, + "use-host-property-decorator": true, + "no-input-rename": true, + "no-output-rename": true, + "use-life-cycle-interface": true, + "use-pipe-transform-interface": true, + "component-class-suffix": true, + "directive-class-suffix": true, + "invoke-injectable": true + } +} diff --git a/otf-frontend/client/e2e/app.e2e-spec.ts b/otf-frontend/client/e2e/app.e2e-spec.ts new file mode 100644 index 0000000..64bb730 --- /dev/null +++ b/otf-frontend/client/e2e/app.e2e-spec.ts @@ -0,0 +1,14 @@ +import { AppPage } from './app.po'; + +describe('test-ng4 App', () => { + let page: AppPage; + + beforeEach(() => { + page = new AppPage(); + }); + + it('should display welcome message', () => { + page.navigateTo(); + expect(page.getParagraphText()).toEqual('SB Admin BS4 Angular5'); + }); +}); diff --git a/otf-frontend/client/e2e/app.po.ts b/otf-frontend/client/e2e/app.po.ts new file mode 100644 index 0000000..625420f --- /dev/null +++ b/otf-frontend/client/e2e/app.po.ts @@ -0,0 +1,11 @@ +import { browser, by, element } from 'protractor'; + +export class AppPage { + navigateTo() { + return browser.get('/'); + } + + getParagraphText() { + return element(by.css('app-root h1')).getText(); + } +} diff --git a/otf-frontend/client/e2e/tsconfig.e2e.json b/otf-frontend/client/e2e/tsconfig.e2e.json new file mode 100644 index 0000000..a7da750 --- /dev/null +++ b/otf-frontend/client/e2e/tsconfig.e2e.json @@ -0,0 +1,14 @@ +{ + "extends": "../config/tsconfig.json", + "compilerOptions": { + "outDir": "../out-tsc/e2e", + "baseUrl": "./", + "module": "commonjs", + "target": "es5", + "types": [ + "jasmine", + "jasminewd2", + "node" + ] + } +} diff --git a/otf-frontend/client/src/app/access-denied/access-denied-routing.module.ts b/otf-frontend/client/src/app/access-denied/access-denied-routing.module.ts new file mode 100644 index 0000000..23e7bcc --- /dev/null +++ b/otf-frontend/client/src/app/access-denied/access-denied-routing.module.ts @@ -0,0 +1,32 @@ +/* Copyright (c) 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. # +##############################################################################*/ + + +import { NgModule } from '@angular/core'; +import { Routes, RouterModule } from '@angular/router'; +import { AccessDeniedComponent } from './access-denied.component'; + +const routes: Routes = [ + { + path: '', component: AccessDeniedComponent + } +]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule] +}) +export class AccessDeniedRoutingModule { +} diff --git a/otf-frontend/client/src/app/access-denied/access-denied.component.html b/otf-frontend/client/src/app/access-denied/access-denied.component.html new file mode 100644 index 0000000..ba588bd --- /dev/null +++ b/otf-frontend/client/src/app/access-denied/access-denied.component.html @@ -0,0 +1,19 @@ + + + +

+ access-denied works! +

diff --git a/otf-frontend/client/src/app/access-denied/access-denied.component.scss b/otf-frontend/client/src/app/access-denied/access-denied.component.scss new file mode 100644 index 0000000..1571dc1 --- /dev/null +++ b/otf-frontend/client/src/app/access-denied/access-denied.component.scss @@ -0,0 +1,16 @@ +/* Copyright (c) 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. # +##############################################################################*/ + + diff --git a/otf-frontend/client/src/app/access-denied/access-denied.component.spec.ts b/otf-frontend/client/src/app/access-denied/access-denied.component.spec.ts new file mode 100644 index 0000000..249d493 --- /dev/null +++ b/otf-frontend/client/src/app/access-denied/access-denied.component.spec.ts @@ -0,0 +1,41 @@ +/* Copyright (c) 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. # +##############################################################################*/ + + +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { AccessDeniedComponent } from './access-denied.component'; + +describe('AccessDeniedComponent', () => { + let component: AccessDeniedComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ AccessDeniedComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(AccessDeniedComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/otf-frontend/client/src/app/access-denied/access-denied.component.ts b/otf-frontend/client/src/app/access-denied/access-denied.component.ts new file mode 100644 index 0000000..070c3e9 --- /dev/null +++ b/otf-frontend/client/src/app/access-denied/access-denied.component.ts @@ -0,0 +1,31 @@ +/* Copyright (c) 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. # +##############################################################################*/ + + +import { Component, OnInit } from '@angular/core'; + +@Component({ + selector: 'app-access-denied', + templateUrl: './access-denied.component.html', + styleUrls: ['./access-denied.component.scss'] +}) +export class AccessDeniedComponent implements OnInit { + + constructor() { } + + ngOnInit() { + } + +} diff --git a/otf-frontend/client/src/app/access-denied/access-denied.module.spec.ts b/otf-frontend/client/src/app/access-denied/access-denied.module.spec.ts new file mode 100644 index 0000000..e52e1ee --- /dev/null +++ b/otf-frontend/client/src/app/access-denied/access-denied.module.spec.ts @@ -0,0 +1,29 @@ +/* Copyright (c) 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. # +##############################################################################*/ + + +import { AccessDeniedModule } from './access-denied.module'; + +describe('AccessDeniedModule', () => { + let accessDeniedModule: AccessDeniedModule; + + beforeEach(() => { + accessDeniedModule = new AccessDeniedModule(); + }); + + it('should create an instance', () => { + expect(accessDeniedModule).toBeTruthy(); + }); +}); diff --git a/otf-frontend/client/src/app/access-denied/access-denied.module.ts b/otf-frontend/client/src/app/access-denied/access-denied.module.ts new file mode 100644 index 0000000..f914e1c --- /dev/null +++ b/otf-frontend/client/src/app/access-denied/access-denied.module.ts @@ -0,0 +1,30 @@ +/* Copyright (c) 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. # +##############################################################################*/ + + +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; + +import { AccessDeniedRoutingModule } from './access-denied-routing.module'; +import { AccessDeniedComponent } from './access-denied.component'; + +@NgModule({ + imports: [ + CommonModule, + AccessDeniedRoutingModule + ], + declarations: [AccessDeniedComponent] +}) +export class AccessDeniedModule { } diff --git a/otf-frontend/client/src/app/account/account-routing.module.ts b/otf-frontend/client/src/app/account/account-routing.module.ts new file mode 100644 index 0000000..695939d --- /dev/null +++ b/otf-frontend/client/src/app/account/account-routing.module.ts @@ -0,0 +1,32 @@ +/* Copyright (c) 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. # +##############################################################################*/ + + +import { NgModule } from '@angular/core'; +import { Routes, RouterModule } from '@angular/router'; +import { AccountComponent } from './account.component'; + + +const routes: Routes = [ + { + path: '', component: AccountComponent + } +]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule] +}) +export class AccountRoutingModule { } diff --git a/otf-frontend/client/src/app/account/account.component.html b/otf-frontend/client/src/app/account/account.component.html new file mode 100644 index 0000000..b7e38af --- /dev/null +++ b/otf-frontend/client/src/app/account/account.component.html @@ -0,0 +1,25 @@ + + + + diff --git a/otf-frontend/client/src/app/account/account.component.scss b/otf-frontend/client/src/app/account/account.component.scss new file mode 100644 index 0000000..0db25da --- /dev/null +++ b/otf-frontend/client/src/app/account/account.component.scss @@ -0,0 +1,115 @@ +/* Copyright (c) 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. # +##############################################################################*/ + + +$topnav-background-color: #222; +:host { + display: block; +} +.account-page { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + overflow: auto; + background: $topnav-background-color; + text-align: center; + color: #fff; + padding: 3em; + .col-lg-4 { + padding: 0; + } + .input-lg { + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; + border-radius: 0; + } + .input-underline { + background: 0 0; + border: none; + box-shadow: none; + border-bottom: 2px solid rgba(255, 255, 255, 0.5); + color: #fff; + border-radius: 0; + } + .input-underline:focus { + border-bottom: 2px solid #fff; + box-shadow: none; + } + .rounded-btn { + -webkit-border-radius: 50px; + border-radius: 50px; + color: rgba(255, 255, 255, 0.8); + background: $topnav-background-color; + border: 2px solid rgba(255, 255, 255, 0.8); + font-size: 18px; + line-height: 40px; + padding: 0 25px; + } + .rounded-btn:hover, + .rounded-btn:focus, + .rounded-btn:active, + .rounded-btn:visited { + color: rgba(255, 255, 255, 1); + border: 2px solid rgba(255, 255, 255, 1); + outline: none; + } + + h1 { + font-weight: 300; + margin-top: 20px; + margin-bottom: 10px; + font-size: 36px; + small { + color: rgba(255, 255, 255, 0.7); + } + } + + .form-group { + padding: 8px 0; + input::-webkit-input-placeholder { + color: rgba(255, 255, 255, 0.6) !important; + } + + input:-moz-placeholder { + /* Firefox 18- */ + color: rgba(255, 255, 255, 0.6) !important; + } + + input::-moz-placeholder { + /* Firefox 19+ */ + color: rgba(255, 255, 255, 0.6) !important; + } + + input:-ms-input-placeholder { + color: rgba(255, 255, 255, 0.6) !important; + } + } + .form-content { + padding: 30px 0; + } + .user-avatar { + -webkit-border-radius: 50%; + border-radius: 50%; + border: 2px solid #fff; + } + + #verifyMessage{ + margin-top: 100px + } +} diff --git a/otf-frontend/client/src/app/account/account.component.spec.ts b/otf-frontend/client/src/app/account/account.component.spec.ts new file mode 100644 index 0000000..b8b6b46 --- /dev/null +++ b/otf-frontend/client/src/app/account/account.component.spec.ts @@ -0,0 +1,41 @@ +/* Copyright (c) 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. # +##############################################################################*/ + + +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { AccountComponent } from './account.component'; + +describe('AccountComponent', () => { + let component: AccountComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ AccountComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(AccountComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/otf-frontend/client/src/app/account/account.component.ts b/otf-frontend/client/src/app/account/account.component.ts new file mode 100644 index 0000000..a285598 --- /dev/null +++ b/otf-frontend/client/src/app/account/account.component.ts @@ -0,0 +1,60 @@ +/* Copyright (c) 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. # +##############################################################################*/ + + +import { Component, OnInit } from '@angular/core'; +import {ActivatedRoute} from "@angular/router"; +import {AccountService} from "../shared/services/account.service"; +import { Router} from '@angular/router'; +import { routerTransition } from '../router.animations'; + + +@Component({ + selector: 'app-account', + templateUrl: './account.component.html', + styleUrls: ['./account.component.scss'], + animations: [routerTransition()] + +}) +export class AccountComponent implements OnInit { + private action: string; + private token: string; + public message: string; + constructor(private router: Router, private route: ActivatedRoute, private accountService: AccountService) { } + + ngOnInit() { + this.message = ""; + this.action = this.route.snapshot.paramMap.get("action"); + this.route.queryParamMap.subscribe(queryParams => { + this.token = queryParams.get("token"); + }); + if(this.action && this.token){ + this.accountService.verify(this.token) + .subscribe( + data => { + this.message = "Thanks for verifying your email. You will be notified when your account is enabled by an admin." + }, + error => { + this.router.navigate(['/dashboard']); + } + ); + } + else{ + this.router.navigate(['/dashboard']); + } + + } + +} diff --git a/otf-frontend/client/src/app/account/account.module.spec.ts b/otf-frontend/client/src/app/account/account.module.spec.ts new file mode 100644 index 0000000..3c1abda --- /dev/null +++ b/otf-frontend/client/src/app/account/account.module.spec.ts @@ -0,0 +1,29 @@ +/* Copyright (c) 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. # +##############################################################################*/ + + +import { AccountModule } from './account.module'; + +describe('AccountModule', () => { + let accountModule: AccountModule; + + beforeEach(() => { + accountModule = new AccountModule(); + }); + + it('should create an instance', () => { + expect(accountModule).toBeTruthy(); + }); +}); diff --git a/otf-frontend/client/src/app/account/account.module.ts b/otf-frontend/client/src/app/account/account.module.ts new file mode 100644 index 0000000..c744693 --- /dev/null +++ b/otf-frontend/client/src/app/account/account.module.ts @@ -0,0 +1,31 @@ +/* Copyright (c) 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. # +##############################################################################*/ + + +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { FormsModule } from '@angular/forms'; +import { AccountRoutingModule } from './account-routing.module'; +import { AccountComponent } from './account.component'; + +@NgModule({ + imports: [ + CommonModule, + AccountRoutingModule, + FormsModule + ], + declarations: [AccountComponent] +}) +export class AccountModule { } diff --git a/otf-frontend/client/src/app/app-routing.module.ts b/otf-frontend/client/src/app/app-routing.module.ts new file mode 100644 index 0000000..03f22df --- /dev/null +++ b/otf-frontend/client/src/app/app-routing.module.ts @@ -0,0 +1,39 @@ +/* Copyright (c) 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. # +##############################################################################*/ + + +import { NgModule } from '@angular/core'; +import { Routes, RouterModule } from '@angular/router'; +import { AppComponent } from './app.component'; +import { AuthGuard } from './shared'; + +const routes: Routes = [ + { path: '', loadChildren: './layout/layout.module#LayoutModule', canActivate: [AuthGuard] }, + { path: 'login', loadChildren: './login/login.module#LoginModule' }, + { path: 'signup', loadChildren: './signup/signup.module#SignupModule' }, + { path: 'error', loadChildren: './server-error/server-error.module#ServerErrorModule' }, + { path: 'access-denied', loadChildren: './access-denied/access-denied.module#AccessDeniedModule' }, + { path: 'not-found', loadChildren: './not-found/not-found.module#NotFoundModule' }, + { path: 'account/:action', loadChildren: './account/account.module#AccountModule' }, + { path: '**', redirectTo: 'not-found' } + + +]; + +@NgModule({ + imports: [RouterModule.forRoot(routes)], + exports: [RouterModule] +}) +export class AppRoutingModule {} diff --git a/otf-frontend/client/src/app/app.component.html b/otf-frontend/client/src/app/app.component.html new file mode 100644 index 0000000..9450cf2 --- /dev/null +++ b/otf-frontend/client/src/app/app.component.html @@ -0,0 +1,17 @@ + + + + \ No newline at end of file diff --git a/otf-frontend/client/src/app/app.component.scss b/otf-frontend/client/src/app/app.component.scss new file mode 100644 index 0000000..1571dc1 --- /dev/null +++ b/otf-frontend/client/src/app/app.component.scss @@ -0,0 +1,16 @@ +/* Copyright (c) 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. # +##############################################################################*/ + + diff --git a/otf-frontend/client/src/app/app.component.spec.ts b/otf-frontend/client/src/app/app.component.spec.ts new file mode 100644 index 0000000..4236461 --- /dev/null +++ b/otf-frontend/client/src/app/app.component.spec.ts @@ -0,0 +1,47 @@ +/* Copyright (c) 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. # +##############################################################################*/ + + +import { async, ComponentFixture, TestBed } from '@angular/core/testing' +import { APP_BASE_HREF } from '@angular/common' + +import { AppComponent } from './app.component' +import { AppModule } from './app.module' + +describe('AppComponent', () => { + let component: AppComponent + let fixture: ComponentFixture + + beforeEach( + async(() => { + TestBed.configureTestingModule({ + imports: [AppModule], + providers: [ + { provide: APP_BASE_HREF, useValue: '/' }, + ] + }).compileComponents() + }) + ) + + beforeEach(() => { + fixture = TestBed.createComponent(AppComponent) + component = fixture.componentInstance + fixture.detectChanges() + }) + + it('should create', () => { + expect(component).toBeTruthy() + }) +}) diff --git a/otf-frontend/client/src/app/app.component.ts b/otf-frontend/client/src/app/app.component.ts new file mode 100644 index 0000000..bdd0c1d --- /dev/null +++ b/otf-frontend/client/src/app/app.component.ts @@ -0,0 +1,35 @@ +/* Copyright (c) 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. # +##############################################################################*/ + + +import { Component, OnInit } from '@angular/core'; +import { AppGlobals } from './app.global'; + + +@Component({ + selector: 'app-root', + templateUrl: './app.component.html', + providers: [AppGlobals], + styleUrls: ['./app.component.scss'] +}) +export class AppComponent implements OnInit { + + constructor() { + + } + + ngOnInit() { + } +} diff --git a/otf-frontend/client/src/app/app.global.ts b/otf-frontend/client/src/app/app.global.ts new file mode 100644 index 0000000..5fde648 --- /dev/null +++ b/otf-frontend/client/src/app/app.global.ts @@ -0,0 +1,23 @@ +/* Copyright (c) 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. # +##############################################################################*/ + + +import { Injectable } from "@angular/core"; +import { HttpHeaders } from "@angular/common/http"; + +export class AppGlobals { + public static baseAPIUrl: string = '/otf/api/v1/'; + public static version: string = 'Camille.1.0'; +} diff --git a/otf-frontend/client/src/app/app.module.spec.ts b/otf-frontend/client/src/app/app.module.spec.ts new file mode 100644 index 0000000..eadbb3c --- /dev/null +++ b/otf-frontend/client/src/app/app.module.spec.ts @@ -0,0 +1,29 @@ +/* Copyright (c) 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. # +##############################################################################*/ + + +import { AppModule } from './app.module'; + +describe('AppModule', () => { + let appModule: AppModule; + + beforeEach(() => { + appModule = new AppModule(); + }); + + it('should create an instance', () => { + expect(appModule).toBeTruthy(); + }); +}); diff --git a/otf-frontend/client/src/app/app.module.ts b/otf-frontend/client/src/app/app.module.ts new file mode 100644 index 0000000..ff1baba --- /dev/null +++ b/otf-frontend/client/src/app/app.module.ts @@ -0,0 +1,90 @@ +/* Copyright (c) 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. # +##############################################################################*/ + + +import {CommonModule} from '@angular/common'; +import {HTTP_INTERCEPTORS, HttpClient, HttpClientModule} from '@angular/common/http'; +import {NgModule} from '@angular/core'; +import {BrowserModule} from '@angular/platform-browser'; +import {BrowserAnimationsModule} from '@angular/platform-browser/animations'; +import {TranslateLoader, TranslateModule} from '@ngx-translate/core'; +import {TranslateHttpLoader} from '@ngx-translate/http-loader'; +import {AppRoutingModule} from './app-routing.module'; +import {AppComponent} from './app.component'; +import {AuthGuard, AdminGuard, SharedPipesModule, PageHeaderModule} from './shared'; +import {FormsModule} from '@angular/forms'; +import {ListService} from './shared/services/list.service'; +import {MatButtonModule, MatDatepickerModule, MatDialogModule, MatIconModule, MatInputModule, MatRadioModule, MatMenu, MatMenuModule} from '@angular/material'; +import {AppGlobals} from './app.global'; +import {ErrorInterceptor} from './error.interceptor'; +import {CookieService} from 'ngx-cookie-service'; +import {NgxMaterialTimepickerModule} from 'ngx-material-timepicker'; +import { SocketIoModule, SocketIoConfig } from 'ngx-socket-io'; +import { FeathersService } from './shared/services/feathers.service'; +import { CoreModule } from './core/core.module'; +import { AbilityModule } from '@casl/angular' + + +const config: SocketIoConfig = { url: '/', options: {transports: ['websocket']} }; + +// AoT requires an exported function for factories +export const createTranslateLoader = (http: HttpClient) => { + /* for development + return new TranslateHttpLoader( + http, + '/start-angular/SB-Admin-BS4-Angular-6/master/dist/assets/i18n/', + '.json' + ); */ + return new TranslateHttpLoader(http, './assets/i18n/', '.json'); +}; + +@NgModule({ + imports: [ + CommonModule, + BrowserModule, + FormsModule, + PageHeaderModule, + BrowserAnimationsModule, + HttpClientModule, + TranslateModule.forRoot({ + loader: { + provide: TranslateLoader, + useFactory: createTranslateLoader, + deps: [HttpClient] + } + }), + AppRoutingModule, + SharedPipesModule, + NgxMaterialTimepickerModule.forRoot(), + MatButtonModule, + MatDialogModule, + MatRadioModule, + MatInputModule, + MatIconModule, + MatDatepickerModule, + SocketIoModule.forRoot(config), + CoreModule, + MatMenuModule, + AbilityModule.forRoot() + ], + declarations: [ + AppComponent, + ], + providers: [ + FeathersService, {provide: HTTP_INTERCEPTORS, useClass: ErrorInterceptor, multi: true}, AuthGuard, AdminGuard, ListService, AppGlobals, CookieService], + bootstrap: [AppComponent] +}) +export class AppModule { +} diff --git a/otf-frontend/client/src/app/core/core.module.spec.ts b/otf-frontend/client/src/app/core/core.module.spec.ts new file mode 100644 index 0000000..201e873 --- /dev/null +++ b/otf-frontend/client/src/app/core/core.module.spec.ts @@ -0,0 +1,29 @@ +/* Copyright (c) 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. # +##############################################################################*/ + + +import { CoreModule } from './core.module'; + +describe('CoreModule', () => { + let coreModule: CoreModule; + + beforeEach(() => { + coreModule = new CoreModule(); + }); + + it('should create an instance', () => { + expect(coreModule).toBeTruthy(); + }); +}); diff --git a/otf-frontend/client/src/app/core/core.module.ts b/otf-frontend/client/src/app/core/core.module.ts new file mode 100644 index 0000000..d050a07 --- /dev/null +++ b/otf-frontend/client/src/app/core/core.module.ts @@ -0,0 +1,56 @@ +/* Copyright (c) 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. # +##############################################################################*/ + + +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { FeathersService } from 'app/shared/services/feathers.service'; +import { ModelService } from 'app/shared/services/model.service'; +import { TestDefinitionService } from 'app/shared/services/test-definition.service'; +import { TestHeadService } from 'app/shared/services/test-head.service'; +import { TestInstanceService } from 'app/shared/services/test-instance.service'; +import { TestExecutionService } from 'app/shared/services/test-execution.service'; +import { AccountService } from 'app/shared/services/account.service'; +import { AuthService } from 'app/shared/services/auth.service'; +import { ExecuteService } from 'app/shared/services/execute.service'; +import { FeedbackService } from 'app/shared/services/feedback.service'; +import { FileTransferService } from 'app/shared/services/file-transfer.service'; +import { FileService } from 'app/shared/services/file.service'; +import { GroupService } from 'app/shared/services/group.service'; +import { SchedulingService } from 'app/shared/services/scheduling.service'; +import { UserService } from 'app/shared/services/user.service'; + +@NgModule({ + imports: [ + CommonModule + ], + providers: [ + TestDefinitionService, + TestHeadService, + TestInstanceService, + TestExecutionService, + AccountService, + AuthService, + ExecuteService, + FeedbackService, + FileTransferService, + FileService, + GroupService, + SchedulingService, + UserService + ], + declarations: [] +}) +export class CoreModule { } diff --git a/otf-frontend/client/src/app/error.interceptor.ts b/otf-frontend/client/src/app/error.interceptor.ts new file mode 100644 index 0000000..85f10d0 --- /dev/null +++ b/otf-frontend/client/src/app/error.interceptor.ts @@ -0,0 +1,41 @@ +/* Copyright (c) 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. # +##############################################################################*/ + + +import { Injectable } from '@angular/core'; +import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor } from '@angular/common/http'; +import { Observable, throwError } from 'rxjs'; +import { catchError } from 'rxjs/operators'; +import { Router } from '@angular/router'; +import { AuthService } from './shared/services/auth.service'; + + +@Injectable() +export class ErrorInterceptor implements HttpInterceptor { + constructor(private auth: AuthService, private router: Router) {} + + intercept(request: HttpRequest, next: HttpHandler): Observable> { + return next.handle(request).pipe(catchError(err => { + if (err.status === 401) { + // auto logout if 401 response returned from api + this.auth.logout(); + this.router.navigateByUrl('/login'); + } + + const error = err.error.message || err.statusText; + return throwError(error); + })) + } +} \ No newline at end of file diff --git a/otf-frontend/client/src/app/layout/components/header/header.component.html b/otf-frontend/client/src/app/layout/components/header/header.component.html new file mode 100644 index 0000000..81f8614 --- /dev/null +++ b/otf-frontend/client/src/app/layout/components/header/header.component.html @@ -0,0 +1,111 @@ + + + + + diff --git a/otf-frontend/client/src/app/layout/components/header/header.component.scss b/otf-frontend/client/src/app/layout/components/header/header.component.scss new file mode 100644 index 0000000..591097a --- /dev/null +++ b/otf-frontend/client/src/app/layout/components/header/header.component.scss @@ -0,0 +1,62 @@ +/* Copyright (c) 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. # +##############################################################################*/ + + +$topnav-background-color: #045C87; + +:host { + .navbar { + + background-color: $topnav-background-color; + .navbar-brand { + color: #fff; + font-size: 1.5em !important; + } + .nav-item > a { + color: #fff; + &:hover { + color: lighten($topnav-background-color, 50%); + } + } + } + .messages { + width: 300px; + .media { + border-bottom: 1px solid #ddd; + padding: 5px 10px; + &:last-child { + border-bottom: none; + } + } + .media-body { + h5 { + font-size: 13px; + font-weight: 600; + } + .small { + margin: 0; + } + .last { + font-size: 12px; + margin: 0; + } + } + } +} +.my-class{ + line-height: 25px; + height: 25px!important; + min-height: unset!important; +} \ No newline at end of file diff --git a/otf-frontend/client/src/app/layout/components/header/header.component.spec.ts b/otf-frontend/client/src/app/layout/components/header/header.component.spec.ts new file mode 100644 index 0000000..8d9d5ef --- /dev/null +++ b/otf-frontend/client/src/app/layout/components/header/header.component.spec.ts @@ -0,0 +1,48 @@ +/* Copyright (c) 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. # +##############################################################################*/ + + +import { async, ComponentFixture, TestBed } from '@angular/core/testing' +import { RouterTestingModule } from '@angular/router/testing' +import { TranslateModule } from '@ngx-translate/core' + +import { HeaderComponent } from './header.component' +import { LayoutModule } from '../../layout.module' + +describe('HeaderComponent', () => { + let component: HeaderComponent + let fixture: ComponentFixture + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [ + LayoutModule, + RouterTestingModule, + TranslateModule.forRoot(), + ], + }) + .compileComponents() + })) + + beforeEach(() => { + fixture = TestBed.createComponent(HeaderComponent) + component = fixture.componentInstance + fixture.detectChanges() + }) + + it('should create', () => { + expect(component).toBeTruthy() + }) +}) diff --git a/otf-frontend/client/src/app/layout/components/header/header.component.ts b/otf-frontend/client/src/app/layout/components/header/header.component.ts new file mode 100644 index 0000000..924d50e --- /dev/null +++ b/otf-frontend/client/src/app/layout/components/header/header.component.ts @@ -0,0 +1,205 @@ +/* Copyright (c) 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. # +##############################################################################*/ + + +import { Component, OnInit, ViewChild } from '@angular/core'; +import { Router, NavigationEnd } from '@angular/router'; +import { TranslateService } from '@ngx-translate/core'; +import { AuthService } from 'app/shared/services/auth.service'; +import { CookieService } from 'ngx-cookie-service'; +import { GroupService } from 'app/shared/services/group.service'; +import { UserService } from 'app/shared/services/user.service'; +//import { group } from '@angular/animations'; +import { CreateGroupModalComponent } from 'app/shared/modules/create-group-modal/create-group-modal.component'; +import { MatDialog } from '@angular/material/dialog'; +import { NavItem } from 'app/shared/components/menu-item/menu-item.component'; +import { MatMenuTrigger } from '@angular/material'; + + +@Component({ + selector: 'app-header', + templateUrl: './header.component.html', + styleUrls: ['./header.component.scss'] +}) + +export class HeaderComponent implements OnInit { + pushRightClass: string = 'push-right'; + myStyle: object = {}; + myParams: object = {}; + width: number = 100; + height: number = 100; + + public groups: Array; + public selectedGroup; + + @ViewChild('goupMenuTrigger') groupMenu: MatMenuTrigger; + + + constructor( + private translate: TranslateService, + public router: Router, + private auth: AuthService, + private cookie: CookieService, + public _groups: GroupService, + private user: UserService, + private modal: MatDialog + + ) { + + this.translate.addLangs(['en', 'fr', 'ur', 'es', 'it', 'fa', 'de', 'zh-CHS']); + this.translate.setDefaultLang('en'); + const browserLang = this.translate.getBrowserLang(); + this.translate.use(browserLang.match(/en|fr|ur|es|it|fa|de|zh-CHS/) ? browserLang : 'en'); + + + this.router.events.subscribe(val => { + if ( + val instanceof NavigationEnd && + window.innerWidth <= 992 && + this.isToggled() + ) { + this.toggleSidebar(); + } + }); + } + public currentUser;// = {}; + public username; + + + ngOnInit() { + + + this.currentUser = JSON.parse(this.cookie.get('currentUser')); + this.username = this.currentUser["firstName"] + " " + this.currentUser["lastName"]; + + + + this._groups.setUp(); + + this._groups.listChange().subscribe(res => { + this.groups = res; + }); + + // if (!window.localStorage.getItem("currentGroupId")) + // { + // if (!(this.currentUser.defaultGroup)){ + // let userPatch = { + // _id : this.currentUser._id, + // defaultGroup : this.currentUser.groups[0].groupId, + // defaultGroupEnabled: false + // }; + + // this.user.patch(userPatch).subscribe((res) => { + // console.log(res) + // console.log("Created first default group for user. Default group has been added!") + // }) + + // } + // else { + + // this._groups.setGroup({_id: this.currentUser.defaultGroup}) + + // } + // } + + //this._groups.setUp(); + + this._groups.listChange().subscribe(res => { + res = this._groups.format(res); + //set menu fields + this.setNavFields(res); + this.groups = res as Array; + }); + + this._groups.groupChange().subscribe(res => { + + this.selectedGroup = res; + }); + + } + + setNavFields(groups){ + groups.forEach((elem, val) => { + groups[val].displayName = elem.groupName; + this.setNavFields(groups[val].children); + }); + } + + print(){ + + } + + changeGroup(group) { + this.groupMenu.closeMenu(); + // Patch to add update Default Group + + // If the Default Group Enabled does not exist (users havent saved a default group) + if (!this.currentUser.defaultGroupEnabled) + { + let userPatch = { + _id : this.currentUser._id, + defaultGroup: group._id + }; + + this.user.patch(userPatch).subscribe((res) =>{ + + + }) + } + // If the default Group Enabled exists (Users saved a default group) + else{ + + //Take the default group from the user input + } + + + + this._groups.setGroup(group); + + } + + createGroup(){ + this.modal.open(CreateGroupModalComponent, { + width: '50%' + }).afterClosed().subscribe((result) => { + if(result){ + this.groups.push(result); + } + }); + } + + isToggled(): boolean { + const dom: Element = document.querySelector('body'); + return dom.classList.contains(this.pushRightClass); + } + + toggleSidebar() { + const dom: any = document.querySelector('body'); + dom.classList.toggle(this.pushRightClass); + } + + rltAndLtr() { + const dom: any = document.querySelector('body'); + dom.classList.toggle('rtl'); + } + + onLoggedout() { + this.auth.logout(); + } + + changeLang(language: string) { + this.translate.use(language); + } +} diff --git a/otf-frontend/client/src/app/layout/components/right-sidebar/right-sidebar.component.html b/otf-frontend/client/src/app/layout/components/right-sidebar/right-sidebar.component.html new file mode 100644 index 0000000..a664a3c --- /dev/null +++ b/otf-frontend/client/src/app/layout/components/right-sidebar/right-sidebar.component.html @@ -0,0 +1,26 @@ + + + + diff --git a/otf-frontend/client/src/app/layout/components/right-sidebar/right-sidebar.component.scss b/otf-frontend/client/src/app/layout/components/right-sidebar/right-sidebar.component.scss new file mode 100644 index 0000000..66102b3 --- /dev/null +++ b/otf-frontend/client/src/app/layout/components/right-sidebar/right-sidebar.component.scss @@ -0,0 +1,176 @@ +/* Copyright (c) 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. # +##############################################################################*/ + + +$topnav-background-color: #000; +.sidebar { + display: none; + font-size: 1em; + border-radius: 0; + position: fixed; + z-index: 1000; + top: 56px; + right: 235px; + width: 235px; + margin-right: -235px; + border: none; + border-radius: 0; + overflow-y: auto; + background-color: $topnav-background-color; + bottom: 43px; + overflow-x: hidden; + padding-bottom: 40px; + -webkit-transition: all 0.2s ease-in-out; + -moz-transition: all 0.2s ease-in-out; + -ms-transition: all 0.2s ease-in-out; + -o-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; + // border-top: 1px solid rgba(255,255,255,0.3); + .list-group { + a.list-group-item { + background: $topnav-background-color; + border: 0; + border-radius: 0; + color: #999; + text-decoration: none; + .fa { + margin-right: 10px; + } + } + a:hover { + background: lighten($topnav-background-color, 10%); + color: #fff; + } + a.router-link-active { + background: lighten($topnav-background-color, 10%); + color: #fff; + } + .header-fields { + padding-top: 10px; + + > .list-group-item:first-child { + border-top: 1px solid rgba(255, 255, 255, 0.2); + } + } + } + .sidebar-dropdown { + *:focus { + border-radius: none; + border: none; + } + .panel-title { + font-size: 1rem; + height: 50px; + margin-bottom: 0; + a { + color: #999; + text-decoration: none; + font-weight: 400; + background: $topnav-background-color; + span { + position: relative; + display: block; + padding: 0.75rem 1.5rem; + padding-top: 1rem; + } + } + a:hover, + a:focus { + color: #fff; + outline: none; + outline-offset: -2px; + } + } + .panel-title:hover { + background: lighten($topnav-background-color, 10%); + } + .panel-collapse { + border-radious: 0; + border: none; + .panel-body { + .list-group-item { + border-radius: 0; + background-color: $topnav-background-color; + border: 0 solid transparent; + a { + color: #999; + } + a:hover { + color: #fff; + } + } + .list-group-item:hover { + background: lighten($topnav-background-color, 10%); + } + } + } + } +} +.nested-menu { + .list-group-item { + cursor: pointer; + } + .nested { + list-style-type: none; + } + ul.submenu { + display: none; + height: 0; + } + & .expand { + ul.submenu { + display: block; + list-style-type: none; + height: auto; + li { + a { + color: #fff; + padding: 10px; + display: block; + } + } + } + } +} +@media screen and (max-width: 992px) { + .sidebar { + top: 54px; + left: 0px; + } +} +@media print { + .sidebar { + display: none !important; + } +} +@media (min-width: 992px) { + .header-fields { + display: none; + } +} + +::-webkit-scrollbar { + width: 8px; +} + +::-webkit-scrollbar-track { + -webkit-box-shadow: inset 0 0 0px rgba(255, 255, 255, 1); + border-radius: 3px; +} + +::-webkit-scrollbar-thumb { + border-radius: 3px; + -webkit-box-shadow: inset 0 0 3px rgba(255, 255, 255, 1); +} diff --git a/otf-frontend/client/src/app/layout/components/right-sidebar/right-sidebar.component.spec.ts b/otf-frontend/client/src/app/layout/components/right-sidebar/right-sidebar.component.spec.ts new file mode 100644 index 0000000..bce5b0d --- /dev/null +++ b/otf-frontend/client/src/app/layout/components/right-sidebar/right-sidebar.component.spec.ts @@ -0,0 +1,41 @@ +/* Copyright (c) 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. # +##############################################################################*/ + + +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { RightSidebarComponent } from './right-sidebar.component'; + +describe('RightSidebarComponent', () => { + let component: RightSidebarComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ RightSidebarComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(RightSidebarComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/otf-frontend/client/src/app/layout/components/right-sidebar/right-sidebar.component.ts b/otf-frontend/client/src/app/layout/components/right-sidebar/right-sidebar.component.ts new file mode 100644 index 0000000..cf800fa --- /dev/null +++ b/otf-frontend/client/src/app/layout/components/right-sidebar/right-sidebar.component.ts @@ -0,0 +1,31 @@ +/* Copyright (c) 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. # +##############################################################################*/ + + +import { Component, OnInit } from '@angular/core'; + +@Component({ + selector: 'app-right-sidebar', + templateUrl: './right-sidebar.component.html', + styleUrls: ['./right-sidebar.component.scss'] +}) +export class RightSidebarComponent implements OnInit { + + constructor() { } + + ngOnInit() { + } + +} diff --git a/otf-frontend/client/src/app/layout/components/sidebar/sidebar.component.html b/otf-frontend/client/src/app/layout/components/sidebar/sidebar.component.html new file mode 100644 index 0000000..8f38669 --- /dev/null +++ b/otf-frontend/client/src/app/layout/components/sidebar/sidebar.component.html @@ -0,0 +1,160 @@ + + + + diff --git a/otf-frontend/client/src/app/layout/components/sidebar/sidebar.component.scss b/otf-frontend/client/src/app/layout/components/sidebar/sidebar.component.scss new file mode 100644 index 0000000..427e2f4 --- /dev/null +++ b/otf-frontend/client/src/app/layout/components/sidebar/sidebar.component.scss @@ -0,0 +1,175 @@ +/* Copyright (c) 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. # +##############################################################################*/ + + +$topnav-background-color: #000; +.sidebar { + font-size: 1em; + border-radius: 0; + position: fixed; + z-index: 1000; + top: 56px; + left: 235px; + width: 235px; + margin-left: -235px; + border: none; + border-radius: 0; + overflow-y: auto; + background-color: $topnav-background-color; + bottom: 0; + overflow-x: hidden; + padding-bottom: 40px; + -webkit-transition: all 0.2s ease-in-out; + -moz-transition: all 0.2s ease-in-out; + -ms-transition: all 0.2s ease-in-out; + -o-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; + // border-top: 1px solid rgba(255,255,255,0.3); + .list-group { + a.list-group-item { + background: $topnav-background-color; + border: 0; + border-radius: 0; + color: #999; + text-decoration: none; + .fa { + margin-right: 10px; + } + } + a:hover { + background: lighten($topnav-background-color, 10%); + color: #fff; + } + a.router-link-active { + background: lighten($topnav-background-color, 10%); + color: #fff; + } + .header-fields { + padding-top: 10px; + + > .list-group-item:first-child { + border-top: 1px solid rgba(255, 255, 255, 0.2); + } + } + } + .sidebar-dropdown { + *:focus { + border-radius: none; + border: none; + } + .panel-title { + font-size: 1rem; + height: 50px; + margin-bottom: 0; + a { + color: #999; + text-decoration: none; + font-weight: 400; + background: $topnav-background-color; + span { + position: relative; + display: block; + padding: 0.75rem 1.5rem; + padding-top: 1rem; + } + } + a:hover, + a:focus { + color: #fff; + outline: none; + outline-offset: -2px; + } + } + .panel-title:hover { + background: lighten($topnav-background-color, 10%); + } + .panel-collapse { + border-radious: 0; + border: none; + .panel-body { + .list-group-item { + border-radius: 0; + background-color: $topnav-background-color; + border: 0 solid transparent; + a { + color: #999; + } + a:hover { + color: #fff; + } + } + .list-group-item:hover { + background: lighten($topnav-background-color, 10%); + } + } + } + } +} +.nested-menu { + .list-group-item { + cursor: pointer; + } + .nested { + list-style-type: none; + } + ul.submenu { + display: none; + height: 0; + } + & .expand { + ul.submenu { + display: block; + list-style-type: none; + height: auto; + li { + a { + color: #fff; + padding: 10px; + display: block; + } + } + } + } +} +@media screen and (max-width: 992px) { + .sidebar { + top: 54px; + left: 0px; + } +} +@media print { + .sidebar { + display: none !important; + } +} +@media (min-width: 992px) { + .header-fields { + display: none; + } +} + +::-webkit-scrollbar { + width: 8px; +} + +::-webkit-scrollbar-track { + -webkit-box-shadow: inset 0 0 0px rgba(255, 255, 255, 1); + border-radius: 3px; +} + +::-webkit-scrollbar-thumb { + border-radius: 3px; + -webkit-box-shadow: inset 0 0 3px rgba(255, 255, 255, 1); +} diff --git a/otf-frontend/client/src/app/layout/components/sidebar/sidebar.component.spec.ts b/otf-frontend/client/src/app/layout/components/sidebar/sidebar.component.spec.ts new file mode 100644 index 0000000..994bb5e --- /dev/null +++ b/otf-frontend/client/src/app/layout/components/sidebar/sidebar.component.spec.ts @@ -0,0 +1,48 @@ +/* Copyright (c) 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. # +##############################################################################*/ + + +import { async, ComponentFixture, TestBed } from '@angular/core/testing' +import { RouterTestingModule } from '@angular/router/testing' +import { TranslateModule } from '@ngx-translate/core' + +import { SidebarComponent } from './sidebar.component' +import { LayoutModule } from '../../layout.module' + +describe('SidebarComponent', () => { + let component: SidebarComponent + let fixture: ComponentFixture + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [ + LayoutModule, + RouterTestingModule, + TranslateModule.forRoot(), + ], + }) + .compileComponents() + })) + + beforeEach(() => { + fixture = TestBed.createComponent(SidebarComponent) + component = fixture.componentInstance + fixture.detectChanges() + }) + + it('should create', () => { + expect(component).toBeTruthy() + }) +}) diff --git a/otf-frontend/client/src/app/layout/components/sidebar/sidebar.component.ts b/otf-frontend/client/src/app/layout/components/sidebar/sidebar.component.ts new file mode 100644 index 0000000..8034055 --- /dev/null +++ b/otf-frontend/client/src/app/layout/components/sidebar/sidebar.component.ts @@ -0,0 +1,147 @@ +/* Copyright (c) 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. # +##############################################################################*/ + + +import { Component, OnInit } from '@angular/core'; +import { Router, NavigationEnd } from '@angular/router'; +import { TranslateService } from '@ngx-translate/core'; +import { AppGlobals } from 'app/app.global'; +import {CookieService} from "ngx-cookie-service"; +import { HealthService } from 'app/shared/services/health.service'; +import { UserService } from 'app/shared/services/user.service'; +import { GroupService } from 'app/shared/services/group.service'; +import { Group, Groups } from 'app/shared/models/group.model'; + +@Component({ + selector: 'app-sidebar', + templateUrl: './sidebar.component.html', + styleUrls: ['./sidebar.component.scss'] +}) +export class SidebarComponent implements OnInit { + isActive: boolean = false; + showMenu: string = ''; + pushRightClass: string = 'push-right'; + version = AppGlobals.version + tcuapi: boolean; + tcuengine: boolean; + isAdmin: boolean = false; + + canManageGroup = false; + + currentGroupId; + + constructor(private translate: TranslateService, public router: Router, public user: UserService, private health: HealthService, private cookie: CookieService, public group: GroupService) { + this.translate.addLangs(['en', 'fr', 'ur', 'es', 'it', 'fa', 'de']); + this.translate.setDefaultLang('en'); + const browserLang = this.translate.getBrowserLang(); + this.translate.use(browserLang.match(/en|fr|ur|es|it|fa|de/) ? browserLang : 'en'); + this.checkIsAdmin(); + this.router.events.subscribe(val => { + if ( + val instanceof NavigationEnd && + window.innerWidth <= 992 && + this.isToggled() + ) { + this.toggleSidebar(); + } + }); + } + + ngOnInit(){ + if(this.group.getGroup()){ + this.checkManage(this.group.getGroup()); + } + this.group.groupChange().subscribe(group => { + this.checkManage(group); + }) + this.setHealthStatus(); + } + + checkManage(group){ + this.canManageGroup = this.user.ability.can('management', new Groups(group)); + } + + setHealthStatus(){ + this.health.get('tcu-api').subscribe(res => { + if(res['code'] == 200 || res['statusCode'] == 200){ + this.tcuapi = true; + }else{ + this.tcuapi = false; + } + }, err => { + this.tcuapi = false; + }); + + this.health.get('tcu-engine').subscribe(res => { + + if(res['code'] == 200 || res['statusCode'] == 200){ + this.tcuengine = true; + }else{ + this.tcuengine = false; + } + }, err => { + + this.tcuengine = false; + }); + } + + eventCalled() { + this.isActive = !this.isActive; + } + + addExpandClass(element: any) { + if (element === this.showMenu) { + this.showMenu = '0'; + } else { + this.showMenu = element; + } + } + + isToggled(): boolean { + const dom: Element = document.querySelector('body'); + return dom.classList.contains(this.pushRightClass); + } + + toggleSidebar() { + const dom: any = document.querySelector('body'); + dom.classList.toggle(this.pushRightClass); + } + + rltAndLtr() { + const dom: any = document.querySelector('body'); + dom.classList.toggle('rtl'); + } + + changeLang(language: string) { + this.translate.use(language); + } + + onLoggedout() { + localStorage.removeItem('isLoggedin'); + } + + checkIsAdmin() { + if (this.cookie.get('access_token') && this.cookie.get('currentUser')) { + let currentUser = JSON.parse(this.cookie.get('currentUser')); + if (currentUser['permissions'].indexOf('admin') >= 0) { + this.isAdmin = true; + return true; + } + } + this.isAdmin = false; + return false; + } + +} diff --git a/otf-frontend/client/src/app/layout/components/stats/assets/icons/ProfessionalHeadshot(2).png b/otf-frontend/client/src/app/layout/components/stats/assets/icons/ProfessionalHeadshot(2).png new file mode 100644 index 0000000000000000000000000000000000000000..6fc07ef2edf5b38b355c76e0398f69712f38a564 GIT binary patch literal 529315 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

>)5 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%0D}gtIf0{ z13Cs#b&q!7Eh9|^`PEyT6)$DkO~d$!$}*}nM#|01a(4U@F~87YkcODz?x1wjp>39pVm{q zIuM*mP0c#zr1E^gFGyCs)Nd$U+#=i}^T*FwZ0lKQes17uk;Kg+Im;q3t<98M90bb`-1!Q!Tt$gH+EPZuCbk6#K3V(9ylX^9% zOgqtQOnCmO3r@!dh1t2%pz=-V(v{t;=iXAROhPa9ODlsb@wI@UKgM1!r8BZVJf@AS$+`7q=2kX$j-aMUfx{R6M^U-(v zu4!q?*nt-Ll4W_!2eI+)sJN@34%l1_0O(cDQk*dcK5=MxeR%(V_x{&kcb`6f%vqw` zGTXGDt6%9~eKhmp=lk|n@J9LN*M904&!KnoV%L+Jz;Z3(BLqIaAm zO__D=bHnj5lG0}N&bG6QMsxdl13WPj+`*C_TUB588y~Tc;u^=wxsk4qa_x--JiC=$W>lj-EEmvse)CR&=B7{a)yP0zn7t?}wZX*Z|(&kye zWvyhto7N{DBtRJ?7Qo<1YRS=gJ~Xg~G`}bvFCBZ}SYt3_XL;+GUvJ;oHg)w7Dy_y# zmj;#jUK|#?+LH3L20kjOM_p$eOC3Av&ghT&lyc_i-xyTEvvEV%!GD{!j-dm$dDb!A ziAbKwO;{)Vgyvf+oasZjfN%{Z&3HSf>1kWgw6)@`(@qRbaEh`MS%pJ7hE40ZQ&iq7 zfGFlB9T%bLl$DE%IIS!(c9nH(k1SG*)8wVSMT15aeL$K8jnEE)^w8Bwp0XHI%{R~b zO%IRtrlrsL7*q$>_+%NhUengAlI}C&MrPyX=X;m@aVt8YCVMu-`luM;yu-{%IIrVa z#+0tN?1XJS^?KXBlT4iVoC;7@jEC+A7uv$%RN9jvs+Fm7XI>s%-Ij2qB~Jpc=76pPj3llJNZr-wBLJ6 z!zZ{i~ zPg!qvjC9ps>G8JPabzSP>V@^CHMg%R`}FBkbjCXJEk5H=yt}@=iENdL#;9`0ZA#q8 z$F@gyrpKTfXS>3TTy^3xFAs3Q*?;<%zwG|}r$2C^a)Pm>OsbQYmlwNR`Y5jiSw6e7 z@a7X%H#b+iYYatca`#z=i@V04b3kZxcRmekcss{}pZQc{+-ljCbPO>EyHllsWvC&l z5h@SrntYC4#t~1cv3HD%k}2Sc3pSmp$3&K*hr+@KVeq}hs^It+I6rsL(nfQs0H@!7da@7?hp}zUnUBWY} zmpIY~Z^PoWElbXJM zKJ5xi5S(H%G~b}{6dQUw(XzD_h$xUpuZ}7cyV)Ho^R;|6u4*8dms=7mKRa7{Sz5oo zZ8wkpuV1-C&)!Ky$};X|ncnoygCCr(tC$ymoO0bQi@k1iLq4(~1|CBh9=$#H@#EF*)73S6u{eTLgXs!yd2c^HM|PiM za0z$g?Yu|N1^FUK`q1}_ot-DHagyVNZQY>m<7PW3td?dzAjfBDzH?*914A9q*RA1I+5IeK7Tcxlh>B7e@0^Qjp5_;`Jj z+b%xYE8&VD^EGW}7Lj@9O|sJmMC=pCN4}(i*N}3DDmzl}mh)5Sl(I9-;+eiJA9ctO zgh`3if5Wu2ytWa>iM8(tpy-QYpCv=f-NMybKfu9n ze8R->^H(G8z@rAoz)U^khML?$IX1?luuI&|21%yz`9o%8T{Ih2H6DLVcOr ze(iSV11kgrW8zQ$`Z6!}99O~&MO4IfZRmSftG$AWF=YsfS@fpN1{*T)af$L{-jt71 z_+_etGjWRBDXExz-543>6_3t3#C@SFp6qg<)sge!#R8kPd)3WAs1^yvuGy@ZHk}p zo`BTI!3jIi%~y4m8_d%xxQ})ZcfPRDg+e33Nsz&y(FKeKP?`>Ij6o;rHR(IR^W}Ob zd=~~6th|jG`rUE!43ZPQ-|*AW(s&v<7-k2+g$AC)8zXWtXJ|A!WSZ6>c9j7KtVWeP zR@EmL01O3~RX2>s;5I*b?Zqtm8m`s>#znvZuQXf~vMYlz;UZyqck0wZcRn=0YA{J} zX;H3@?=F^luOeIOdx%|~ z^&`o7&y}=8gE(Rk(Z$lCOr$|)T)y?fNt0#f&ra2p={yZ}{`_e7lLylO{D*wQ@9Pt2 zW)W0IUc4ASKX!Ku53cM~MP|qyoS$y4cel&%>-r;R%4y5_({r-Dz);*vE}46~IQqa- zcB7Eh9X@BM9z2L%p9ft8P8WfkI;Gzp6~Cdup`RwM&)C*M&$#KY#8cb6*4^&Pr2eWl z_^i>edHl5O8yFLVcOjVeCXEXn{yEnkvMD&s!{Y+G{1_e15*jG{D{?~T8eyG#ji}>> zt-q&jxouiH((cN#x_S@ z#xhy7%*JXoP)FtUPvzD*kr<>dWenC(zgGY{g{X|R16#b8w762YG}%US69h0`JdIms z;l!IZ%;XV;cYtnjG~S8F%oKcEu5=Btyk%z-j-93f1>4k>q4oSMZ26h8%sZsh9rL%T(HI4 zmM%|YWMI-RBJFDwHUn8oDy!)hno1W_i)Bv?6Dph;p3MNDUr%)OhW!Zf^mq8{NV33OeVSXy3Gp zi2TOLMW&e_4OLimb&U(D9hfm?yW@o^a>jDN(1yEbFb~%w~RdDkZMBn_TvK* z9TRyVfsDLM2t9E((=aSdlx~t z{VhLT0E6J*90*x}$QF%!$jn>~I3T0QD>Tn>yRWkdP&9ko3$8L-c{s(HKbi6m8ppsg zEo^aGu{d5+lcvTifU^*uqO4!x*FqOWPjPB4%q)bznDt!r;PHF?2(>)O675rc`&3 z*#^%c>o+cKCtPt7a}^-w^kc%(sE-cVK7}20Hc(yyldyeb-W+BeJu2DAFERteOyu~; z75#LPy*Rr}?$xKO7$v?gAWzN#<06oSLI~Ti&0yH&$tVw>+fhD_?%;HLJ#R4use4=M)AcR> zYInoJp2Zu!G!nAo6vIL9lSnQspJPO5O!<_S=YyWJP--CN@b!leS&Zc01=gLg2Nopr zu34ZSF=mvD`Y-*yS=+MIS^cxuA9!+6@8nduB~OEL@jMHu<@$l0J~M8(U2rq8+uy6K z<&~Qt(kL%}y!Y4l9}@Qix4K{8@7E9SBRj|A4g6O=8b&==C63<0gFbrPYbN`mAL{O_ z7d~Fy##r;<^DVNCkpqmkmwb#Kb947h!wdPK9LTXxcdG2tmxmzGt$qeeV^qUM9&ATS z9UP=(Q@N5-Hr+L}CGz2aryOtw>O!4 za;sMThfdq|wF{=-y?qx0{v&eC?w*5~rqsK%X+7X=-FDR#`PFc;-JH_`&at4Zh5g=* z9=MRby}a1HcyXF{PyP6Zx5)k1-Rb2C`v0)|@bSa$#mkrA`vP8!;8fO#R1e?XaH8`aFEym<_qqr&Y4sAT7;N`TcB!2Ma)y$= z7iRn{$ns~X%zJS!VZo4e=pxw*QS&KH-9-2E^0@DkxB_;a`mGap-4^#gv(%9G!gXs% zh3~lHopt708V`JalP|X`R8PkEl$Olj1wA;y%w9#svG|b;cdQbTE{qDp{NkXuf6Eb3 z7L`YhSy^lUkWSn@<*k=DADC+1^p~3e)*mq#s#7MNCn_JPBCHYR!w*skLe}-8KmP6I z-&;8>?Y(*W+35+4NUWSm&H?VExblS8u!y1ML}-QI;@jrQ)WJ0^V_KB$uvHXx4q=Tf zeUjj{&3YBV{FZgAJ28qfIYVD3Y2lp|jN4g7HVR_89VE`;?x!Y-JDtB|ql-W{KKEFa z52?MZG&C99ibkx99R?M7(IfFS%u{~=){wCCZ4aMHA}CGCU*%C65;0i(-+0Td!!IF? zt${c@4Caez@b$;Kt6iEz;_=2^thO$6MNzHTK1dd{Nay66xtA;SnjiU)q(nq!`eSM( zjXPNikxHZr;~6SZ1)i`^Neb=lJI^rL4=lngf*$M_sf(7JIC1)l2AvCo3&NaZ(eSce zuUztGX)0b|IQcTd%k#6{DT}G+S1!*lV|?YKtl)@BNG)}v%NkbTP+m1^)oHP{^a_g>J5If-}ZQ z;HXciap}`rjIX<)O+`;%5iSaC9iRd^G*xKJxWUjjHR;h&a7^zGbmgpIuPpn>qtdjk#;;UttWthn}lXpTMJG3XF1r zR~KuI=(Xx3PoXO(`>;u+Q>Wf$cLW_Wyt|)I!*tAP;9EyI_KoQna`2`sd_;TKkfU=}bSOpSpqh3SDn5 z&vyU$KmSX{p}SMZ7teOTe*AfNesP9QKJ5Pa^FL_kB)2A&wHFSyqa1zz+Ry5&yOoRw z^A9^w%26T8M}cKC?%AAszD&>!7} zTx%2Fen|E8>--SjleV6))O{ws0f{WrF8Ru>P9CIh@gm)Lu?+2LFmV1#rx*3zeN6k% zX_Kk=CW$^6bSN(Y7gAZRkg~>at3~5%{Bln!2@{E-RRr%5tn|~`FG-513Lw$|) z{hEZlkN)tt!w%KBcH9tTB_|9!s)+1ki^j)LphM>tMU`MR9vqF=05P2QB&`BA%Y{zH za=S-{Q}0keQE5=hVPwh->)M6_?^XZs(ZO<{uVsO3MZ$rN50A!Iv2eso?@Ht88oIl2 z|GOpVl_Z0gwj7dCGU%-m>8Gv}YPNC6B}}I_-ATauLYc-pAf!P8Rv3>$$aXDn=?gIb zhkjTHR@iv>Sa`DdFJ%w@376aFuXws)lMYu495l%b9ic_9l)l43wiH&zDa~XQJy^I5 zT1OA!=pc?d)*FMW{Y$?6HXc|%(W5$QPTNtK8-IZ@ zb;%@uady(r%$#t=PnmHSso9aq_A)Y!XUK$CW?V>OXs0NLTx;s@GThgmec^m7Rg~%to zTv%ODot*F2;_P=k{lv~AhK=$Nrei^)s`8qCY#DtkT~2m{%mm~S&18;Fsh`Sw>7)5E zAV1&lK4YlZ*O_>~b~mRJiaR=w(A3*GzBJOh8XupaU8BGqHE-G3?Y8&xufJmGn5Mn8 zXluv_=a|poX83Uz#oLL(oYH^3oUgY7-39b1K|g}4LDjd(yE~&%n|IDYLtaBb{FX)h z#vKw2Ip0+zA(p$?hi1HIwp{k?m*=#v&l7c#VAYV)!1euF%Fd5|>wH@D?Cd-Sle<(75BZm8 zWu7?=JR%qG(4p5EjuB9LO0Ri(X>$yOM*8>c^x5v!i;Laorx;i7Uhb}LKkc5M`@XEN zyX(6vXzaPH;J`Z;)E#NLMdt4@xV`0PfBDc!#)xx5W=_YRbvs8Ke2u8azomT~5~X%$ ziO5!d%>~AEF$1qCNN1|EAG3zZyM59yb4oe`Jl=M)EO6zE6zN0{G^}~);6z~gqB->A zlh-=pla@&*9*D;E5?#O*Qb9dPpwo@X5Afd z2@%RGd*2%+{)kuT)T<9ID^%X@0t$H0LkjFS7K-R-;$rEojhwStI0G9z4k)iYx$0kw zk+L{B@kN3syYuyK9d~SAytrfmI0>A)Rd3$B*`1%95wp zp(Tw|p7S_Ic}bju(kJg+)IAjK!X>r7-avy#L(7HQ!`Imc-FkzvcZf zuY7vz$iDFq`6C7r3oY`ALCD|0{Nv|;P#?U|kth1(8$PA;`1E-93bB>m+EyGT)4?-rQr%dAl%YvM4ju*u7fv`}om=>^l*DLTSyYm<^_OXWb7mN=0RnW^RPJLxbMBN51{h&IcT6-yyj|(LxzHQs#Mtv3onuhvnJahs?05CY`9P!A+i%K01{FrNyD%EkhG{Lj zk=Drnb|-4)70b5##00hhlEBYBl0B? z^|t~MUtmmuLpgIpp6W$5?HkLAXFAWM&H0-w$xH)gNf>nb8@S3?1}bNx%2K%($PkJ^ z5k!SiK}=DuSBBF^<*Uw?k}h-nw@h4_CoQ9|N;;)P^dy=lx|aI*;ts_rGh(w+(+?OE ziId3T$#r%WD6dA=uYZKnzu{pHtf!4a#QQo2Ss6Ibxd~I-LXB8!7kSNBCx`C3)~)Wa zd<3)UWCOQ10EO}Rj&cI8eQ@;CUtj!v&kW9Z{4zjvV}J-YzG=&6uynvAkI7<7pe}uF zn0)K$4xMS3XgV@@x5OPHwvjRgoAc@Dj%yX zycu6IAs)i4W<6kB_;lUs1U9LL>9}-c7tt-KNsIZG+rA<#L%iSE-$5X76e$)}y|#P@x_iFljWemeMy#CS>%1J5)+;cBJ% z4GDX>5{pkA2W=vin~)h9t51bf#sV8hE=iJZ-;M5R)YFGat_F(zC;j>U97fCyu*$}6bjT>vUw{3TdVRQ{Mq_z5w9Y>s(*qt{!g_JhWWXP0bG16Y}BWTg&6?HXzvzIgc}{CNA;+in^+_J?{QE<-Vi-?nWxMos#x2GxE%EIzjRm}Ly{$KC() z|Mmaa-9Fszo<4uFyLf$pPX9B;wYOr_-C;xxbnzDd9lCQ3ZP$!V<>`)KcHNLm=L9S1 z8fLx+RcTEY&b-n(w2jML6u0IH!bp_=l%Z!eEC6}p&bK<>Io;cL!Z-#T560=8Rli<% zmDRF+pW=l4*0tCZ3!ZlMTDCvkYJAz{r!nUk0O0%9FpneL9=*` z+MjKdKg(@;A5?N-ss6Q3obde;z6OD}K>SwO%NH+t)k*6)gnsH1a$j#nAxQsPZEI9(vwiUEw`j!*T&VmU|BBn#I&zr=#Oz7WLcgI{8?) zS3~Y7c(&zALxQp#lx9KkypcwLi;G5pJ5Ww0Ia{Rxg8?AT58i4c4yx>EX%P6mH{pDd zV$SYBvmb)aZjxTBj=JH~Ns72m?pJuCji_k2R#hEK>F^li z$}+l1`RIeYUK)R&=pW|+UplMshR%LN(Ob>l8WyYQ8jg#u`$JP+K&i*dTpi5ZVw}G5 z0Ssx#xitGoT~+U;2pG?TouJFkO&W>fla9*6+nv;fo;(rCpE{)Lu3_iAE{X>?>6s&D zd>rQD=Ba;vYUW@6%U^eAm*+W}QrCxtMEFNu`tZYeX_~%;kIdnOBlo6l zr||Nckg}d55(d;2;oci;(`nlPKzYkcN|RR{@*{tHzT-#!&Q^_gy-O@#Ojy5R6l71NeNi~eg+BW6&wXvexFPO9 zqXUKp$w=Ai(54~V33AHfEN|R!lu7}VDIlUyP3tDVe#KXPegmW1H?bF5JE}Ahk0G=? zamV!`4a_!=xOlt*GH-84ZR_9*FMql63W6xjH{FD60dkM~y6)}R_6T6C#DxSKb4 z6=4>Sm5wh2H0)yu7umR`bx~LqnfS=XgrY8)l~eMCKOmu>>@UOSx1X9HV+!J&OnuCn zMzR=dP??*-fq`S_;$EJe2y66eNNGITu2-C%k@DlnC(r3K%1=*EFgDJ2=e{n11zV%o zgVEWMp*#yG^}B1SZm|Gi7Z8Bc9m!`|1U_LD{NkrhSe&x|1N=3Mw7Vj=8d%82r}(Z} za5b7Vq+IkqVuWb~i9cs=;6Wq6cLv>g(3-T~MNb1Mx0oaX{gGeOF5=3~+kn=sVMG~t z&39+(_3Kx_Yf!L=S|1LCi}*;_;Ha^o8{KJtIIcQ3q`kE}Voxg9mSga^gXS$J+7Q-q z7jo%xY&yAVSb4BpJjz&u=H|M$)_!^aOK>^a+h^W-o2MMzneyOu-DC&v@w4Zkpi4c17JjQMgtp-!X?L=GL$^j;-r^3NI5oW8)ydf``b|SdS-9I1 zqY9WB)5@#{oU*&qAcj8iRR4VU5`9m)V=lx%LtW`2j56`#?xA!>uN|j{v79*vd=vxg zVsC!OoBT+NZ<2R6FYtI}$V_IV`yGA(c%-XPZ(lKLpLfym%9xd4Y z^wV4Le%bw}|N1YxpFjM(dz$AiKGT2pqdKY)4%qz2w{GFZg^m?hZ-Udm zg**5cz5`@k;0RMHLGg{J7m}3j&Jil~$ULKVHxCrrw!A4eDTE*FP*BNJ7mDMe^7{Ac@;*!2JfV&et1qD;gdnWSSyn~95A6F z<@mr?9_~uzEwjidhtUaV7th-tb3lErjA(H`A7mh|zG;6cfBfn*jcjkP%A@mtp7Nut za;yQaiyWX~^w%p)7wtT8X1i3D#8)p~?*8!854#taFH&{_j0^S&3(YZcpY+S*7@2@I z%=gnDd8s0FbYa!F!f^5_F%~ix2hY~L|MYQp?Q0QW!UNDQbRM>S|H1br^;S~qeEhWg zsL_Cd=-Df8S9z#CJ98*^b~tFnb3`uUK7FW*0p#S0tTYHde)@p%@hJw4@H+LeJ5qi? z`7|#qRX*aio-C>3*}Y-hkhu&4>XYAc4Tk1vz(5G&2>O&`V3c)b(}}D2Ef3Aq)3`F; zE7V<#9(Nz?A9o@?eE7%$s$qj+g<+$-efeVzr+eg!VMH6p#8=rcQH0A3j?kLYU_xywmVcscaUn*F8 zilFpJ8)Mt3ZMFd4u|SRLSy{lXI9?fbF2mdBkrDCnz&ts^m?F&FPG99LC9uw8@@IbP zu6ZnTPvoVye&_v>VUUU&5|ihIVmU;~kL=lRla^QmI}Rv+mQ%h{W(ny;%{VxDtlP>= zG|)?45K<>|ya+W9s?FE%$Uh$%)M0vwV|Jr6ki;W8iOpHYONgXcSg4K&P z8CL4JXxl?U3&J;9=|lP8&uP8#wh{!UUsk=5=W>U5%WES@LuqQh`qh3t`r%JCsO)H6 zh>Y7du$V~M%3rR8)_=#I})D$iwGAV#+3v-|l4S{RD{yLOuwLQugs$JhE`I z6!+i@O4?9&O&AKBL7a9}2xwGG1+bjKnmV+hq7=4r42=Lyf26(xI{fOu4P8Nmvv0-= zF;F71e%{)dL*6lJ zfTclYkQUM(G?RX^KiglS6_FVC{E=%tQ`%ZYTF-@F16hOCQv26O{j=jDKMSW5$Nn`4 z$l>JV`R>KV+3pn!-8nQ;44u#Vq@P#qq}^4>A_9CSTIhEn8AHmnFW>wXUn!^5=WBB0Cl!8*~8^UOhZR_R2y7!rPplaZ$f~wSlmn-}9-f zhn%zOLh2c)KEy%0_61?y&`pS1f(ygQxE-gkmW#Yu&NNi$AajU!w;{VO!cyNIA9tN{ z8x{F}`1NDtXWUzOK8Xkzy7D|SfTHMyMg*O)yZY#B6vXqG9Xxlnj7zV$qtDbakT(yk z=X?-);ZCIQ8ww$K`#3U{Z)qeua|HiFxtPkcvUbPowM?KpKeHi!AqQOB$JJ)1=YT*{)f$fGovo)>%C-}A1j z^u3-r4ba_>fBIo}eCp(df%_HRdP2X*ub&11pZ)at>m$ZT$CnoX_v#!tyqNG7x;wtP zwYu)0vuwqV*u_J&@7q)@2Ehv4?3e9>a^GjB+uISv@-zf565IOe*W{p^_` zb3Gu=d(WZynY+?t*atDn@V2zSP^7Wu*d%Z(uCqVmGQUZ8L)9kv)e>+zpG|wG|7&|l^|~D zc(b2$%|DbE+Fq!euzW@&@#P`1Uor^HQ*;)fEw5Ww8-R+s{oOfX@UbVlR@%PWa`cD4 zzW%#{3OvxQ;H1<^(h=MasoO-CQ^*x`T@}={hLk%VT|k8yAQ?E+$&Sl63@Jv5R|pbp z+UeKE2}6VfD#;9-EUuFKoevAb2phpH{0hS|QKVenmj`!wHVsfZve!>1pOgWH)X6B6aVvD@#< zc|VxqwreC{PHx64|14B#yrE0oS7^xYipZv%*}|Qq$UXz#`t*e}po82x;RSw?D-db| zFr5UGHViGrA3A8mtFj!xWq~<8J=Y$70F-DYw%oh*7ej#mV zyK@$yQ)oUV^nkj%2(y6f&r>jI9v`1(!K%(eAGkkUUGM(wKmKEP?JXu2qxTp`zD--& z-5v2Pjk_kk%D{IOxjSPQxR|+1Axv)_cX7%29~Qq~e*On_Kfu!+MvS+~SnRwtcJIp@ zdr;Pe(mv5p^PsPb{^j`va)mY)rW@e>ypFGd=pul@cufByvq#`v1RX>gp9r^oDsdz~ zf5z}o{+7$J{MZikVELuaR}D8q__dNUqFWqcStQM~|1!Cv&!V>69k4v*1z*be;jT~6 zX}mp>C*A6+c%}K?+f$U~br)bRU+QT53enreJOOXP}ICcR=`^Bp`pUfh|} zAX7eicdBBP(uO-=wy*xBU+80b_kVV?jCTxRM4$^X)G&5E`=zX&d+S)k4Em+rZz{s| z?gY9u`lU@{{Fpv*bZJ0jmk@k_S3iuCa974%X5%$nSlmIXH?9#Uyu2z`7ijCqgUB3< zKHSi=O5QTXFlU^22;K3SvtsVWsWb^GSOSQA1?L znY($;yB*USR$q3n-@V$MTr%d)$j9G4dePvMr_XXOPQ1M!S7&<5FNPByHnN)=e(>&M zWi9xe9-&Rz1wm*_PIa_t5R%RXACUeDk`SM##n#*wcrM&j41h8-S1a~+nIjTB#t-2>&khaDf=wBNBw;6CL;J>#pf!>z*eW5cH}8;EmA2*8 z1}CQq?%-E_6(IF+GttM(lf1!`i$mhgXRcc1okZ%p5N43*g#*ucT8WaHuOa15md2Dj zB>EF3GC6D=ZDlgHKu2Ah7Nzkv>lPm%NEcoKj8HpE(o`!Kv%u>cAABI0j$N z7vMF>A{Ai-L0*!wa?@rej)0e6ab{9obh-<5eqKZB-K)2|*Dqh~USGb%NV&kEI>%ta zfMG&Ed3IbmFah^gW_ht+`ZP}$LfNc7sQemRr3T58DSPAzi}I^TPE^mHU^GFSle7J@ z*xfxrpk8U3_Y6ILd5Q6KcABUDPEVghS7~~F@Z z)||KQZe5gF$UfclL%u)%@^fCY>4M)Kfu7NE;&E|z_oi<`$50~fLG6B0#a#jycHhx- zyI=6#IdaG5(epeSZ|n0R8d5nx&7!KXV%!j_I~rcf!K>;M_|sriXqBLE5_Y1mcs%=q z5ZkAeWhY9xI)*Tyl6E4(_u+ug`Np9}L~tT^$A-$`*{qz!2|cALeF|VWkgCB&-IHD^J@aqneGE=U~t7D;aab?)J0&?uxYs$*D!YgGOs2Xn4;TbaJ>ywV& zmek-=uFjDjjhMcZc5!RGiboiEF;6%1Q0eWMHQn*sU9;#M>NW0E@Q3;R?$;F*i6tOsp1zj4qOd8}m1%(G~8Zq6=NJZZ ziR1<`^$7#ZkFm;pc+s0CEIBv;mMc9t+R*s2Z1hYw<*`c=v)pv^>^pT!r)~|paia^B zIkMOI06e=T+#}F$dt>#A>Fbl8A_1tO$L+7 zmkB{diIN1-s?&OPhWIe>t&?zRNC(ABJj}K@9nfq<17jBNjiUH={P`qowHYM91Ky2l;daXx%Cx9l~2FdY>N!c;xEdi!MQR8(|~f) z$j;J67V;rK8d7gqT;9HZz5DU?yWQ&-FEOZI8L_YfQ?2<()=x_Eq0$ z(mqNaQP(^BFFA%}N}rUc+}9?o0rAxLhXDMTg-vFPJM@P3r@6wsgqD{WdKw1q;<&q` z;pA%&^5*Hpz1n6Hg4E+)BE9G^Udpy0gE9B)J5y&mIe!& zhn#(?%>}53nZ@H{_wLkmQPYsh!SO6oz2ZijgU8!5;OC8`e7UWji4g3BmZk{v%3+V(a9oe9_>h)22ysH7^C)q^xD?6r@Z?@P~`pTW7vE>6u^IU3!0RL@`>S(R~K^OL*9%@4N>WmUTNwRf;Fm~M>WjE z+uLwJ(QXV~;+KpG+fBYQQa?2Ilp8!`cPi~jm?G}@)z7@vbZL=G^GNLLopQlomO5kT zJD$`}FA}Wd?vJ`^Jum1CrF}J+z7S5gZ_mA*7#G!FX)TQN^wKYev_c6QAmW`5n{V8^2hQ<1`#EzR<@qKkX^I2uLP68u)u6IR?Gt2?2~)kQ@!5;flqRGw zJ|yD~$5xur`JFt1@uu7G@|Mec=m75ubvFNv1A*;ELc$JQ(D*a@lx*BSf+K%qnSin( z9K4B!Kq9FIRpKKI>iij+XIJ6bP;@q=%7&{}op@CUxevW?n%geke{d+I+hBkaiAM!dt>(|1&jEfo^DjbtU zuF?*Z%b|YbB}ReNP5j%ib#%6?Ggl+CahWyt^xv0kxU%TlRZy z-v;reqGYx%1rbFI%9aEcDi8Hc)3&Z#y$5+(rto^3kvM$YAyM4W4W^|B;SZiXcX4@f zzI%fq^^Pm{HyBcHE?({~SlIR6Qac8=lajnLF)d>%@)I|qw>rZQ?b);jU9TpjPkKuy z!-7fH#fmbsGDs{2hqnbtgijk)>0Sj$ z-O&l1GLT*uRS$`KrbgN{mZVn$BJ=`dUwZ2|XRhRpyoADHbO=9QeBPcNBTEBIBU+_x zedL%f_fYb~?%o|fZ?{2z+Q#Ve(R*>rV}N^Ow3M{yHf5XH(Y1%@P^7qI@C4$SpBI{{yZ|XEE0trY4d!X270V+cB4;nyh3qAP0<1M-F{Hk%H4AHqqotZnKq4kM#*w{(y5c; zwqg4?<4C;VGIY@it>}k+Xx;EB?a(XS+KRK_)?>>~QDv$|uTGN@m2$YLn$zN}P zQUHB{-h`QYX5jz;|MW>jK~#tQ0PT6x1s`n|?+Wpmd#yuU_~xfZ>K#IhjZ4fBe83+W zCs`Oe#3=HY5)fTV8TSdPz@xx7mg_0=(Pr49OH=<(e} z3erV4)bW!ZRt{*Fv}KZ;GgDt7PF?%bg(PRk#7Ep=r9t8@!znZS84Kf^*BE`TUhU3L zjxnlEa?VS7yagkV-llUGDV=FsS?Id!^x@+t7M_P3M*nriJ(qHF;@j81#Axu7G4_r1 z><@PWJg4JrEe#Q2+|lr@jj)pf;X0gbLZW(iN=GrPRh@%&45uyGel1QwYH>v%gR?*u(O&27D>xjpT9D9_4h zY}t;o|4Q32^pK0PbEnJpeG9p?39YxC7+)xOCT5huzA!Dkw=9*7I+lwqWT^fLq{a$g zS0l#$7ta{uj>n`eBXpruZpbx)oud;6YA~@h$@r;jv{KjR>fTZ4et^DXsYt!1lovTK+=2drA)4^|> zj9PF?Bcv!(>dKG1ohgrDSUz0eajcTk%Y5uOIQCB55LKPYBR%s%TnD^BUA_V^3o{|YmN_!Z{y<7 zlP7O$ViQPo2fD>A-5OAn7Jocx5rV^tp?CR1+Mnu~V20hLBDBv4?Zbi9=hHJqKK>v? z{Z^>)Dgl}D?(OUe3&xQxSjpa0i?=TinY7pFhg8;QJ@M zfOe4bDPg5AQOi{hKO@qs?)?NBs5;@CWYXEIF&LD(N;-x7`vi)(L9 z;D;RG!D_y!A_H=TCGG)KjVT|)fAg}&iT(w~)%i1w7G@;x0%`V!CtEg+>@~!^2FMq{ zZ7Z~PVw7JOFuhY#lw1DyI)cUn8(FPB@gvmkOu3$UPDQVgtn*Q9VcnH+fr~+Pdc1r4 z=GE@ii%Sftehk@z@){gIX(yo$DX-dd7A>+k!Vr4g{m*~?ynFAcF}oAKcv8AGo_sfwZ};|-Dzg)19p5OPT^WqWoFihPc2UlYC~rSvcwkVhvs8W5 z-yN(PJ@!)sOB*qSoCwBnB0mcOx*ENXti06;f25z#hE*eDaFLaIk-fa&a#;KRK8BQ` zMv<;^M?S!1M+U>$GbJ8`&5jeevrx>$H0i_%fypk(#=wdZg&cBz>0Ta@fo(rxOnK%9 z+BEWFTmnl)WCpE-AYMAvTe&$f46L`6y1QWCYeZ@M)Sx={0tfFm9itC1sxgS^@9dmX zKj)9s0*wxQ&zWi1D(goKuG72(Hak_)1O4q1exWHw2u=e)UgclivJZ}sn-3|Nr#u}1 zvoMmCu^l;Ag$tuVan{j^KQdMID9>3c!_>2n++BTy|K2)`5sxgLSG@K2c#n+X>zJ|H z-J$lchQ9se#e@3bn5aSJ0@U$o8@6r#&rW9Q(2lSgx)(3FpgKp!=RQmTt{pmr+?+dX zBLIp(b-xdcKsz;8`;Jxp+NHvniXlasVuZ4p^T>mQ)?axh8aG;<6T9hgBOje}M`VTW zOSjpX-{QSkQ^v~Gc<1mMQ~nPP#*{_F`7>_o&ONyx3{kK^dgxi*8CV^Zls0^6EPj<> zLTTHl%`!dkQ$BU5Z`!i(v@R6K@AFr^ur|1y9mb&A)2CaqUU8i*?YTe>txs9z>ha&Y z!7;E0oOPi-w8&#|W}RZaXd0Nr#UV_6^8E>p;{6_X^0GTo#GTd5H$jw1z{3oHU_n7gZsbf3&vpsPLSmeob z@tks-QHVO3AK!}2m)S%9ayAsV2*nFmx9TTvGOLjKDv*=h8Y~R@dea>^RjlRZk0~Hx z5#IXv#1V$eZDc@`=7mgU4;SyxQ+1=TkSmS}puIym|lwDrco$ zzSzAy$3XGWIfGX-BwD)RtF%}EeVKC9i6qx#>4fi9GaAknZOQ{jQr)p1q;d6St{ivh zT8t^r{ylNue=jvRWWsdoWAKRem|=;vn6dr;o*_-P=zIOLNeAjpeDVcw4%*U;GI zWu5>1-~I!9EC$fz0cv6Vmf-E}ecn#)6KF0N?i{!Sr4i*L{a*R&vdf7)eX=a?L;^<+ zp0nV28zeh3*Pm)Uv55Nya-X=vAivZKF3pOc17JK&Ek*# zx}&5Klv}^V-Ia0|%YNa1jc?ndUD|WUO9RXoz+R#&FFh0J)2n#fx9^mdax^VZH5wn# z5Bs+-vDA;@s8jD8cjl|h&(OCtd(^2-FivT zR~pN{Ja*pa^*OI{(6BmnR}~q1F3)=EdW;v2H{GP-1(9?xTJz2WO z#mxETGmI(>$WwVk500$Q;G~{DIQ>I6RFN^NXd2m>2hF5yFKsI}7D83k#J(;SqO-&U zM_qv&!vN;bFu`(>7pNv|-by>?0j!7{Zstw_ZF`{<0%?R+dq5O zCL$HaLOKf<{5G`Gk@JD1Z{tB$pZRB#KDgp*`zDR6YlhMa1*SdU>7$lLE%<<=mJubpjQN|9s^tvTzkaEvo9 zuD(ILI~UDQaNu)gjOrXzh!8qa7eI<%pK}2C9;~e~>0%pCy!Za?pUS;5knY8w@Gewq zVd@or&mOtRygWP4S)?;>wJ1k-5cqRJ4z1uTUTF1JjZS$1lQL;uyAD$Cu1)e(Xwsn} z^_{pqw*wFIhkTtp-Iek{s}r(tF4~dn>W|@b45~l=_(R@9<NfQt3hhfiUJ`}*Y}cvBb3K)XAJ?)~j8_%z>z5n|vW zqRu2@zgX(rBVBr7YJ{0kcAn2_ygI`ouYN#VuGGoXxc2N^UnS86Z0gufW+_VI=&$TR zWr2A>r!kb|6PUaSoA%@@w*V>Epfau(PjpdvLAz2=|1>lWPia3pkI_qLqdC1isR_B& zr=bjNcc;3GntbqA(rx9SxAh+dqU_IB{;?gD-AgW4%S#*h#_x{9V#7vs$N zz!u@lvEev#4pdft(nzDu^HZY_w(DyPG!T8craI^=4UlByB3`-^*KxQPr7F!&`jT+w zZ<V4WlEQ*Ys6K+%pD0luWvr&8^QytN-=@9gwEJBGd!%>Gkn?0@@HgDUeE`Qn^K zDE+_k>?6aDotbaG?#?cr?Ji%QFi%o;1kZ%sjkSJnr7Is7So1)=dt{RQ?3XVH$;MNr z8fi$GXLQk!+n4Br^6R1}Ea8glh$XC3RtHaVxzcWyu0_ahh2Da4?ntqn?tl7y+{6l_ z+%%}p#H_rY!RMKNgu<~k=!pY%&xbOpK ze`WDqo%C&|ruh}}lMa#k4dbyOfu)|4Uk#YjVb2tR{eqqOu8hFd+cFEM0jKP(Tl{N=1`87z$goX@4@i6J=ypjlibYi**T)o0; zJXDLDNyaM)ClMEPm)AZvOq_P0N=WMH(@N3~;P6gf=#;)Pl6GBmyfx=y;$o=W^F2Fh zX5ufudXP~qa)4&fpG;oTz|Z2E+ZL2xG8w;l`C|9_#U%#SMHZZ6ZzWRCTPEGHERQY} z!|Ty=_!o$OW#Ud;`wy-NSyFZnUwpA6brf+3(O0%H=z%j-UeBM=7FQa6ncg#do>Nl( zwkUjd0iajDHTvGXbSLe2_xja~ETYQh^!QZ3EM}f-@rg5ORM%p#LEiuS|NGx}rxzC) zjQ{-SFKNebrWtA^WU++S@I&8452PH@k!I+pGB9urjPEvb7b9nBD5b}<<8pR(90REf zJ|TR%AfG|k8GU(r0v{~&p8K&L#W5VR>w>qf7%51gMssxnbeRC1IGj!LN(awIDJOoN z{Jo`S*Ld48#*K?B`Rbx@8c-UW8dDnAVGyV8<~FOm(S{4H`1SUYL*LtFBd5fHQLxI% z-6vmD;HPtL?=VW;ZFIZQX8p-RsevdJ>WTTppsQ(r&9otR0zKPRLn;OivfBEbTS9P# zz8lGNbo(c7)fFxb-1YK9+3sLgPcS5CM=$T<&P4=er_?=1hkQkd--paQ*ccbSIMxR? ze6rOYJ?DytTR#wt&Vl#r{1nzSvVGAe^neTDWLG4&PvONK3cv&BJhDl@5?()Uy?&J(Po}rH{e)+tQJp@0}FTGVm+9zT>uSjTDlRpL$G-x;x zS0^G9$}+2@o@E0|9{(ywbUcZ=h+_HQ=6C*+ugvkp-LdW&T1V5uivuF?R#4hLo!4ep z9{r<1_3!{qDKF2?A=xSN!YGZk59!4fmmT_$BAv8^khDbxq4gVI*()y|6pkYcVoW6} zU+PQ8|M=vihpD&92UZSsdqXdL%Y%N&-5lbhZ{t!w4Hrw2<0rjp>}fOsp0KJElWALC z_&K+^ZULLMTSE$cgx8~$HnhBJvu()7L3FDH+OTih7x5bD_GR+bH*^oL+9Vygfv1f> zEQ9KMVcNh5ufBrY<_YJ(C%V!lcCJh&Uw?2*7{SkPgaFBVW^2Us0C)vzIGCRxu@8DAV5#P#1fB(lnckkb?PouCP zUR`;h+(oH%+;LFHbISpqW_Kk!Zp7UgV$|-Qz?-24lk&H1za{9cCygO#)SsUmWs%Oo zet12>P}OkC?FX80SH^e@25=d=;A>8KLozzN^3*UiD|AISBoUgFttG-`0oJ)_8{o50 zyQ>169jA`$^_F;aRs^~=KB|M%K~C*EF}2@J$7oAfL(Sd4oF8-dio6%nLn-PAXLps$v7yBAZo|S8;*GNkI6k~{dU!9>rWu6xxYG?2SAAEz@ zK29HL7?Jj(!`qC0381e7p`UyrP~%G(`3FtjmeRl#kGs0=fcer*$G7vW#;JNTPt{3F zc3I>{{&b3wpDaXrQijU6GG6%$zV!>E%*E}Fl;`{WD7SL=Hnd|hvkSZ^!|5Z(t^JvI zXW^9Rl$k$siOm_ePi)JwvvUnaboT;Toq*#A-J_h^Rj>4ybXPwzXT@+b-W}(_iB;ZQ z{4`uhYn=0INnoUD@Wi=5+E&ud8<~t7IW@mB&U#=-#}bX4$yhLvZbD<0Mbm6cS`SS} zUY-McATxZdLgfJ7h17*AALn3gd_cSCNo|+D>O?nbesg{}dyMFPj|JJQM znMrDXZI`m7iSsX*?QC&Oe6Ob~y@k;Y-Ma5#{B>>C5Kn(dYi{$IXI=3--zXbl4JRHH z&{ujh4i^1jYPLG&@PJ1RDu!Ot%~Qt+OG;q)-5veuKfV0B$g_I_Q6W&m{IlWZb=$NH zt<1W}StkoV^@^kMgD*_z1>V1bsiggvaYB&qm6nV=(MEdjZ5wDq(e+0+k=7lfD>*By z5-QMvkq-tv#+&@l8L8QI%DEw6vN)69cS!q$1#SFI}-U$-nCCK z!4rRq$G%EkaJ%bz&I0=S<>l_jw{LeZ{17q=oCZuMWfn;mM@2&<^!m;yZ%h5#zyCXF zuB_<@51#vtHW#T}Eh|sx^Z>bssa+f)5${gJSNegzfC8_kp3)9WM-4(`L}&5@~jW7yd1 z(QE3P))>l2Mi}-*cH6|e`p|_{+;)cY>G;8~abY}*Ky*|6BET7VCQ3s}S?8P?G~_i1 zj~+l*&h-P6^D%2d&rTHd8S31vh@RR2ZCPd;%0pUniP_JA=5-fPgKPDPe9J4oqtK`R9zv&W_3(Okzj8(jop2o9V%&Uq z|2_xQm6dODSBBSDpLXZohK9z-T3JS()q9DQh)L-2U3WriMI;XvGbLYs(^IdkOw()NbgVcBu6a-# z063o{3?J|$LfVv$QU+#eC{dx!_hGB-m)|oA5<~NJzuloKY?ut}!jb&K z=~nf9`cU6^y)Z{PL(hu1_CpwB z$S|}Y6m@tw$P4%wT`k+^Il&Q{c5=-G%Y?c0Cm0oZWSa%j$;zu*C*I0Xd``LLpw=&5 z+~#MHIkA+Z98AxZK9h@sH*C`J$R`6j)i)~s4ZRw7Yr(*Wc4fbs%z|gQa2Q5GlUZ3D z`rZXwBe+-NF8;nI!IyTv!kBu2F*Rqa+ON=*z6G}~{FOF|R=2WXl63n1^2FT;uk0SX zu(B9wP`Q}*Rz_we>Z?l~RLX>=;yiou?C4~7bH&y7r)wL`q--VW*U7gF2iQUKeH`J^#SM^Q+&PgU8#O`+SpcCc^XywB&5iJqrhM z4XIf)y=~_XlaJ$f7fCtRyQ9(DMJ(LJ-R1Dsl15ct0BirDuYU3(w`}bLaOjnnyty}k zWYeD+O6}H+0ZAjMQO-iD4t0X6Ork4#)09=m`YpE%;dyTiiHE+3!KIP3j4gGGtjJbF*;i9ocg}11 zbRkr>UA&8`3`o1q*9d5w>ug&ccOKD@mL4hR7IW zemn3!1}){_@Lg(tGRZm0SAK{h235vYp9&1VEH*4)$W$5kR-J8nfzll+ontdx*}>WFLcvEn5X zmwbO}P-TtKkU|Ym+ojj)ka^`z7-GAlKmO|r45|_Q!sahQeVL{T6;-U3n{FQE8v^wQ zToboIWh4k}^Yz2L28_l@c1Z9kOB^KD9lG=&sq!_$cX?#2$Rrt|jJ(K1W|Nj(;mPzr zQe{G?O`~Zm@peqWGI%CFzVfItLlyP*-ip>GbkcM(%S6lK=lhG!;`Va$-hi@{fxRK^`PB zk-G@6n6F8{7Cfy+ZYZEFh?1Z7hxjTB>(fx=kev^_27m{0UtRcAUw5YRZ9a^t>`Eyc z`3oNEtoH1v3~oD(Htk>A&wECUp?iM&O=b3$k5~3Nzq8KR)Sv<`Nce|=_Cfph*;9=U z+vf`V=3)2Y*H60#77srWqrjvqIz?MP)#U+WZ}+`@^&-Yhb{mAD9r3#$OUq|@rvH3` z?|=T|AGyWnt&;b@e#kfagp)TXes_QJ0>y_u^3QNZwV?st>}6%ALFB@k_Z=O(Fn^5! zrFZf3Qx|>eth*qytEi^X+t7BnVpE@8MWV0ZmyWoINI5$>xElq1$`2ZQ?qt=cExnNT zapb#vdd+?$U%B{!YxUS$$hkm3X3xV-Q8o@`il8^?1oRqG0Fu z9o?OaQHQrTY$J29T!XJN6}&Xo@KDqFvyq6&!}~qBt=Meu0X_DO{vJ}l!C1Pxe~dvT zjD4E7x`SUBor}D4oJ+$a#&~5kSN0ly%Gt41150^WM-t92x#)Vug~2)WKi8nTgJ8G` zy!xQQ44%vZG=Ofa0rIQw)L@^>%i_~UGuH`|f|Q4xEC|9iTbBzA*BA05yYK(9ZW)@g zT+9O(1e+9I+~()Ux!H_mQ1N5vg>Y{9p}RgwS$g=1lXqcjKs`RV8{hfeJo_l1&=b8> zkWI!N^5m;wT=)=f0cP9*qfBu7d?)@5T!YmnE^@?qNp0S$MH)WD8T!hnb9U54nB04NW61Bc?}&C-hTH2gS7xu!l?W4;B>uGqre8fG(yZ0dRfwO z4x8wfeHVYoOMf_hZeaF1R70f5#x>6d>e}flLCA zob(LMZGZ6?Pa3{ESx$NRbkg+7Ory!S9iQhZv9qL;=SOs(c@D$H`mk%0PLFT9c2pdE znBR`1W4*G0SJ_Jk;~m^-8=TS*$#uQFIR64Je^Rd#%opxq)j{VYEZ?c57ZT+@K+T4Y(-@8>3$!`oN79QUm--FM+t)#BXkGmimRQ6fUhsmG427R#Hki1MB_A8+- z`iYngZO2@1-K7jK{~bT3SGelhANgJ7(}z7kjXaRAVT=Q4b2rcniO>;0c)}yx*k<)nJi8S#nI+P33$qt#OuDYWh*#F%z(M!h|Qqrm!n;l~MQlnt< zCv6y7>2K?fEcW=&-RRYZx3=7|s+Sf5;Ol!)T7ErT@3}DZ)UO)G{3TvP>;fYyXWx`* zjHdfR}Q4_JF;8uHL-;;q~tH0{uRN)@PLO ze82;mn0xF`WhaULD5Dt8YfiApnQCB^yXn5E5>SeSCcJ9NeJ{ z&BSXIF=X+x4jYosn$8en?9dkF+9&a*-Ixdt=#-uiwb~&Vi^}CQs zM|Xo-?jSN8gKBoBd?Z>!>h!tiBx>YzGNwIoiJu9fSJEzzE`-h7@ zyV<3Dc_79!wxuE5w8YI-lQF!VWFg%?lvKBCk6OZ?$JN>5uAAy0_D{q zcQf2Y)S#-Nm2*47J87tU>MLR52w-%v`dO(vamT349(c()z2t?i89+~Vpq^+@**0`UHY<&Hch%iAVRK7Mc>8tZ!;5`I8673F_0kCQ zVZ~pv%&R7ws7ChT8gSX3dGHv$z)Qbn#K?tXX8g@QX(S2s5)^Mb~~ zYd`j^)m;oG+y(FDOkL z!q>v(pM7g#`olly>jC;4`!xCR1^{1?{5M?e`iTPE-vcCb(KZ zc$Qp318@$oEMzhlC*3trocu0WjD4iqotxb9O1qt4^?6zj++LW$S^qNW&jMgrelp2( zh3(>yD_ACbuk^Yzho zM-9bHn9?A>3IbPI0!v!M%|qrs{{0f;>GJ$?z0mM7#*|MEiqD#v80e(EXVNg7L1)}1 z6a{LVKd<8Mzq*iWMBT@*>g`P?CbgWpnQSwcL76;Izw#x$=+=;O5~Js#=VbTsgXf(- zLW8#;oY9nV2b~6w=cY6Ye|-A}1Mv)8;-m~i>q)+?W5&_$%0s&!uXa!A17+A3B0?+q z`D_YT`_@C{7@S2lvTdywciymZGPn`T1R>05Bl(LE**&p&x zXg!_bJPnGFk{8{JO!y~Dc*dzCJkhRgi_`ouEEPlW z3#(o)`5tJK8)bzDI5`WyuZD0(EC=_UOr;4UC`OBr{!d#7S1d8~C|6(i-zH>2PS1f~ znCKj1NIJabsV>{T?fQhMIP4>hc|-fua%oPZxL&ElM|jxuvph)C%7^RnuOMs#I^8{y zCSOP3>sMU(-F@`qn%&lC$LMy>Z>{#J<9RFbDRcP}r~N73_D2^X`LIlS&d<*< z(r(f>?|yi_dw$HAc+RSYAr)g~-%sGm9BBGLYaB4P83jgfQX2hH7nbheD;v^PVO-Ox zlX9ZaR}32&5stSmDoI?q3AIAo6Gj}?i6L)ldH&6BUv(G5c*bMsQ;y`VU5>2_{leiT z(-GF@{AoL*uhoINmN!h)A2OQVercXg9So3#{ztBRc;y=o_%)lK(6IEUFe#1;2*g&B z2WL*oCgf-9?ZVtO0ogu3@WrFtni9lzp+G&cE}`o7%pED`kzBm=%xn&%XKrzhtL|k^ zUE*qe^}u~<^39YG>5&M!&8ENlCVs{RL-1f+=~p~zMBj&SDj)snzr6l?t{hp`!?GRb zM3crKWGQve2uW}!@v;cg+%hPmk&Yqg#347Cti`Vo2(T5n(sBaEfO$^dGZ=bCJLX#s zTm%wffeVJABn)>U@SrV<=AT4}6lQ#(-w+mMpSU%X=Qg@ltOkvfQ_p$KIRx!J@K9+kx6)jMZG=ZWOw5Gbhwg!#U$xRgfB2QE>6y}qvO*@ z9<+^4pn0NDp7x}Zin^7_Q?UWY^ud)Iiw=G36GT4Ib%(!sxZB;_-|VjMZogN0@Pj6rE z{`#js?%uq9ky~vsIyGXDtBW-#cK7Jq{ewF>OpGjiF7`J*LC6)of`Yr$>kgA=qUa;v z4Rxx~VLMNDuW~!|xP}s5y;4p+cT{h?*+GeM+8ve3(KnJ)MqhM5)35YXc2hR}6@5zI zf;VFw*{lgey%Sf4&+7AxSN@&&?IVh;0aES=Kl!db^12p3Hcd%NT6 zJHQ-Yvk=Im-}eJs+LlHy5==|8Pv_m=`GI5%Ck&S?M)bMz_D$Xzaxnt%h#%TZ6F;HX z3lv&{PZw($aJ~QsVIE{q*CRGH`bB45Jkt+?KfwzbMyAK~EXjg0loF~}-Lr1bIUyQ`Et+57n_Mz(!tT?bO& zH2hC?r>DMv*0JU}COJ1Bxg-0?QQ6ouzslV<95?aEG`ds(Xj1m-^yBX8>eKGmPapEI zg}cG_wMLyn-xm+LhQfS-GXY0r_I@+|l;zx5yPdq0c;j?A!FINOi57vczq(vTu$CkmEy| z7$Z-ax6!wZm3_$i?z--SZo-3q#APeCEf2Hd_yQ0a5^1CkjY(emoIl0moM^J3Jof6Pq|B^QFRI*c?ALkL|%M4 zO@3`Bw=N_9PPp=&$L~*ij%$ps{h2B~bfGtuBVPG>yUGvzp0jAa@wVQDhNF+~FJ8&l zrwwq5OW(fGYg~aFrSBCRlMRbc&J^ICM6xr5=4x0O`Vry>Vd-%f0dU>@Xn_Mm zU3EYxR}~|wYec$zKMv8)>c{il?e+cc*Iz#EZttAVT*%vx%1qEM5t*uR}L^>Z)VO@%V@Vq{~=Q?=T3vy9Q2hWOvHgYS%^E zoga6C=C+>R2M|2llLNZwgE}c)@}f+F9~yF@lKl33KM90!hLP|X#lV0hP!_j2@80kgUv@v^-@kv4?}G)tHo&LdK7RBQL07r8`{6wX$1m?Op3VQ1H;DUL z7LAO&WS4%)JF;lkcb>W9qmJ}xAc?2%ASATHx3W^9)NK`21IqcTXCRSl<_jlrV3Y~C z+_@5y<1xl7K2J^JHJEI#eWI)nE^Xo3pDyO4SN~e#tyXXO`3C=6`oQy2UNm?%a9-e< z$H$@5TUnzsIS;1^0UmY3cI@w&m+f=Mg!BB%R~Nh2Z!dPw)((~WpQ96tR`oKAFzTUB z+27%Vusk)bJf*!H9m4V5;Sf$5%X__WxP7F~*4vJrcFZG`qRi8T>S``F!?!Z4+|th0 z+a7qvI5L!+L)b-Gx2KCd^HWCJ`7Ultlc74H3{q6ubPGD`uQW)BZ5NUp3xsb?=rH`= zwXKu`+pOQhHEWGG;z6DE#6OPuE8hxf4%wAjoOIj20ir#!N}~Ct-*%L_w-+_tlzmBv8-u^2z)|a z7%~(e?f&V%y#2caP({|Y(_~~BNaGTpin3Y9u%|AQRPb82`O<3K$v^`tJ2&3n46{yt zc;fDmZpQ{(V@<=*-9kF=2L*-#~Ut(ECeq$%f|sN>G0@>TW%&0=VKKFOCWDs@v&zt}%9K<$&&7wHfG>_ZjB z+O#LH&ynv_7F}Q8V0eVCJ=N3p6K0n?7IY`Yui$X*(7e%WT;z&aFD|@hl(Nh8hAix_ zDeF(K05hf>^9yctzT?+1rQSVT1_bht0k4s+UO&rAGKH6qUWhqtJGc1y4|kuu<>(Ga zUgSx5@A;x-Q03_%fV=oQ)`KZ}wO?4A{J`fcZH$w@zd?@8YAi+LHzvd zCv=W^2{~RcwqC#eVfVuy{=EC+pZ>D@!=L}Q`{Q5!b@$^R|GIno!=HC=-u*=RkHEdz zot?kfJ!f3rK-2ZZO+RdnA?Ev{K4FO6VtCzPgxz1?wE5}c6r+IMz-7p}f3VtK! z8Z3LmnoQ?2jVJX!dc?mnbC)$gm7BaMH^yZnXa)IdWj!G%1B7}iW0OwL}z@f zkG3(gjJ66M*{f~VgU(b|4v|FqDq-gLdS%mh<*B>%y|r6}p)fM+2#j3y#BEErz2K=1 zn7_sVQ6!i;d$;N}Yx2Qo)Sm@ggH!P0AGeQ3?$Bt5j$+O(;QA*ZKp z;Ug_85N}_NYdr9VdVcJWvfVz3y+Eh*tkldw#*qp6S(mA2ThnKIAI$ck{Fmk!xy%{4 z@I=>{ruW`;gCV?N%(L9SZC&*!x&$XjfBvs;`{|k0jLvi??u{ew8@JLx2Hxrk6%XMI z4i`-Y!CVT%E*>)9{G{Q!yCw(-BrbQQ$G$9%(vy}dha6(19m;!UBeXb#?L;(&PR<(H zjsuy={MmDN#aQg{Ne>-NV24FPo^1cHP$&*Vdnxouk9@6k^ARZcY|CAvJlRL6F(v*k z0OeGk%bleTiVo{M%CJ8|HLPSYA`z0J@wQ$EdiDjgb9(C&mjFGh5S zDrw4{)WtboTH@)e3~pLMhgs;oMM4~9bwYO$%|T=)@)%QSvy)J{l0NiEI>DvpbihV~ zf=4K)B^M{8#2_H|v%F(yTtBb?UhVF0)K@2duV&pI_Ei$kau&^ZXuV~TwGZVbi#2WK zDh4|I`{n&F*`ex7CRIy!XioAFg5P-amS4_zF(FkSmp)|*>@L+9@6jXLh-@@k2sP5` z?63N!(qn;lx6G#teOc)z7Vu9WKkYt#z<<1g)=nDxa{$Kqaq@`h&A_D>h^~2)wx!dn zv9_;F+hV+vnb5JwEo~i0)WfC%Y(=$6yyhgeG>|(tzsiTo;@g zs2WigUzYgc(!Bt5v4a6JR|z<(a9gYm85K*q~b|7o3cv zg!B`*AHQH8qT|(xXbSDx&nLwD(1-IwF07yWvFxMW+jm^3Tws(R`R*y7?t}6tTxh_? zR}3sy=zKF&(ygbiEndb;PmiZK4(xBanDI$H;$icvIs&|MBpu#U(0JtoMDVta8s~75 zJiM)$&blT%V@P}{ah6&5kW2n7!*{GXZ&l7|JAlR^Qe45&yao$qob!Wir$0Mxgs>{z zA158-rhJ^}R*k)(Vq7n6NrjF>s7rjGpWqv~#+Tl08Z7;jvBEu1);Ywt?X|4+DM>tZ z6Lp?3-uZ@k6q)ow*|a-V#__@lL!B|e5AD^ZPso~E!O{85jb6AAZg!#c9uYa@6Zc$| z`lX(c7JZCk+|ge!sG_J&Og0Wsl*$E)-zcjbDL4rTTc+z_fzaq8T!l-=%P^2KD#JN2 zW|;y2Kj>pz5o)7X0AiG|3MJ9RZ5oB#2q?yaf=g&!aW`z+tBqp}1dOOmM9*tf&8}39 zEGBn&@1oy{X%u%Bm84zxXdu?G@&SLZ)Gdc3yv9P#yU>=mzP#P1cl*BQSLl?**3fx+ zeg-@S9yH}D(|Q_HzINaZ6S)QyhE={^Pk4FpBD-ESWHe%WHYMB74r`TVLbSnlvcsg< z(r#&1&U6LNf$mgfA9TTwEd7JNxx&*h?T%B=Z1_1DpI|&cz1W>|b$^DJCcV2=7kJ~x z&)|uA`Z-ANVlX=sGl9<{D6PI0;Vwp$iw_Iyn!I$%tS=%(X2?0aU3PTzmi`hcUS-c& zEwP554xF!#3gT$@aQm?P^yzkYd*!V<@&I$7fj$P6yuEw#diM^4);E!>KXKr4Q4yDM z7s~D&(8AIWcc=8Ku(x}>^^;cB8Dd}Daa)Fh{Wfk*ZCR+iO7cvOboB|h&oSJ5DXHhQ z^0xPz+uc9^okg3)`{Rd?yDN++cSUX~ySusD-4lMI%>3(Bc2E8n42vi796q?(Qc96q z#Mn@JWRX}5;Wd$uR~n9Ub;mx4v8^$U&v;^7smI61>IFLPf-0Wq0Jz-glU>_Rs9e6} zJW>rRuN2|ib91CK3F-lkZmYAzy`Yff9AI{Uk#_g(!TR_+Cch8J?ER;kq)!IKF( zM%52LV08H)1G@A2?c3Zk^R*iPboYurvfr)eN3S&yQSRyzJRwZ*Rtt2|NA$^Yn8g@| zbAigdsT0~cD#j;9ntHZfjIHlHnjMn$=f7^?f)_uALr5W=^I-12p>yuSdMjJXa?2HO zb@i8?U_97Aool4WzC1!+&l&rUJJY@{!SAcl{kx0H=er+&dc8Zl#MpXzvwQN4x*AY1 zqyWe0@+FKJ*5H?a<*-mKKN0$bpl4x>7*7yy`<`!-_RcZ-RcQT%)4I8^A=$CqHj|If z9PY)yj0F%VH}R$&elpvTr|!;t6+=pI{>mFV4MPu={WCKdMJ9~IEZVY0yWS{=F}-$#Bxb(LXV=fCZi@C>J_GD1V?m`pf_EZoP-f$x#A^5sMElb^O_6$JnwC@RShp z6I>3QGOUtjD{dK2-IA*ykV__FnJ*2%i)cCV*~D~s1(+rp2Z0?gO!5G-9StQ9rnwEc zH=?|1_KFUF>;j4J&Xl2slgfJVp(Wn-^V1Mc6NVN%aq&2rr)}Gy-F#n-McD-=w{2)6 z_2@{$xl;F?F4C!Cb!XIGL!SGSFbZsyCda}(D~U#c879CNy9{*g2$bzF8ESN z3mMeuPx}?2X41>T6tJa`Du`O);#9umM>l;f9_8UeGdnNtO!+jQMn?=MXzH1vzN|Fg z>Lc{3w1@qNP7Ny;)ZT`mHQKAJos8^AjUaFLIf3`H9KzMmv!D7}0TyqJGT%}?SCVuH z;WC2d899qH2avs@2E7BrS0{+m0daTx8DryN_i(Qa%Ci%u29*ZUkMG{((=!^!wjY6b z#SL%`!LRG7KXm~5=*J9Z^@6{L^#V`SA~iJ@?)-ZH-5ta@=;sWX6KUIbvGTl)=T|)3 z{^`@FobNI0Cv#ZbFw!)*q~YT7RnF6?D{s)5ckh1Kz5C(Egg^YC;qY$v8l%wu%Ih=;$1)rnrw}E|4$T50> zoYd181TIL_6`A922|u!Ulon{3GgSFzpEANLA6SmTm0RW{gmWU!m<6xue2X#QxhRbp z-=(C1<@=_x(@THGkm5qcMLriuPSDOtvK{_o=fse=ud=h`87Ph5JOt5?Q`@iM7Fc=8 zF0EsL3yyOyfV^dl{2k-IZ|dgy3QzxIp!kHVe9Du)k|pl=T$7;rx{iQ`(RaLnF22ey zG~<+k@>dtf*>~wTeCDNf7Kts-dN(Z!p(Os!0Pd+m*JlVZ`eYX4I$5$9swD}BqKF5H{#W!Q(8Lb;V zHK;5jY8X1@j1b=Jrw}adj(hSAZTBmcs7<+i5(u}PBXw|X`5*Z>XPb_m)6vd3t|iKw ztdv<juT>`!Yw#_gt&U{AIk=`YkZhBAi1O@4 zQD2_3LE(A}l5El_2gPC!&V zSZ&}PtDpgoZIt4pzx}tL{$3`VfePi<|B9qaIu(|f>c^rCCo)17KK-2?DH@1j<&~9b z8E<)w8I{#eKDe)3nRF+L1U^>{ByyF)M3Gw|)^qW~XR>EfPhN~Cy|*Cn7)`l_cA^2r zf=Ax|qoivm$=h)qH2O~V-zbffQ{+?nDk~W@?twIT=Z#27$%v> zIEn#{?l3X=&LZR!b6zRG#F+Zw?GL-Ruix!1xSIB3!tMgO19Y<9VU^t;CoKkd-vC~k zqiE#WP8J@1ynSZ6O0;^C^eCnas=Ye-hO>Ajfm80@>hozu4Lkh>#+|n{4K=1bM|CO> z?o_#edYeZhOoNJ0A9{^DDbc>V5}8OJjcHi8*lSREi@`;+dP4i&q7fepwFhr~x~;|( z^dbB#{Dk6_@Nh(3^>ucX@}!UKI=C`0cDqj>STJuNVo)lN7~b{|efq=Oce_9Q^b@>S zS4wMlDfai#`E%jVQ#0|U*>CEBX7#<3$JgEc-Rl}8!-TnIO2Mj28HP9(!?3p?Zq_^2+`C<2p@CAm{rMD(8FLx*O(Ghz06q=$uLoZ%!|H~5Q$4p2&5NF+lYs|No^qi; zzn@}QYgF}O;SAYgz)+SmefAwbi@y!vH9m8YJAG3lrngem>%27bW&FY+&Tv@1A_74GiCh2MyI549%+?GXLfM``xd<{JgvR z)U#1P|Ks0x|MP$T`|jue_#eA}68{JBfBzrz5fVyS1!B#2?Zu$ z|C_fK&3e!HHLZaa{RxJ8h3Ps|L(2Am47$pwa|?21&4|7`PtyO-^uFXTsvMY#Z9XXxlah zmGw2Q{i85D(}4Re$1$MxA|+Cql)EW15pvc5bICT2dNY?epEwtI(dPVu?wd}&^P**r zP3r8+dV%Mdha?%_w~Imb7^2AGp+ zcc^Bd%tGHQyYbSH3CKYd`50CsRhF{D@)oI=9Y_jxeAwB95M}TPfnghi2OYS8h|-ew0-yVkn^*PSA#x z(M+dDv^ zGu!QDDCOQR+dt*Qf?(&lRqZ=QKK$ZN5RZDR~S z4Jr+G=@+@7Mu2=M+eb!f&i#=7`q^7Dz}XInEc2tc>ah#c&F#(Z>gpnlP_D$XkwrKUKJzuQ=c-ndQ zhX4arcj(f8PD`pZ_GpV@&$vHSSp*WLA}PrDCP>b?BKI|ZsbeS3yftGhV{OF)i_f?YO|4fM zHf_01x$z%^)w7GgVqC_cLNCqtwwbWrwwKRTTlhP^)eGmN&NBt!~;b`PPlwhYfz?03KK*Ph0fSYFqET zW4o1~Gg0B2*YP~*;Mq6Z{E3ICxRtkl7s%dypVk$B+nBV1nl_S71JHnM_b|AT@3cSp zc2ZtF`|4$LJTQF%NQ?SP{gpJa`YN2hZ}%O$O^0FA38RKc{=gq$Mp5d$`jUhi zD&$c&a*sh~o@y`N!$hf}lyL1-`Iv5Q`9XkJaM`ue$nk1&zgxAvs#}Uny!_FEjl@YK zzsf3vgj{%*SLt;^)0peWYtv2)CX5OOiuk;;v&}K6o|1O)^2+(m>vt@cKjvJ=@v}1~ zEpHdLuKl84(o&Vfcb)=5d5r5NMjG9QzxS3CJwAQ6pRAP~G`j%Z-rs^rvDznM=-23w!L65-*27xOk~A7^#*9C& ze&c+Z8N1}%mgkhN6rm$Blh5b}D`i>Dh5YT|T!{Km$5k=|Ow{KC5-Y-9+ zP@UN}ZG7-sjKC`H7ni;s;r()UPJhvVUNnFA;oWi$Prb#jLiLXH-+uia`|EQ4;cWTn z&LZv0r};*s*8ui*vyg)ggg1y zZw<+{f70@^oP0cF2?DJ_KRb|S@+?ABq zT`bwxl`|b@;5J zEbu9~^ows`#e)q66UORw64hnmG_$Z+FmsG$tji=4*5$sXjd!XEf2J|q;Oc~`Lgg+q z`6xHjQ$5D98)Nx2P!rjJG5@M9taxNDB&#ym1raDvR#~oxSO{ZY`#a+%u-9e>Yxp%{ zkT%km7C2XaOo&q3FrKw=?fls$b<(!7H+7GE%JayE^fmF*ra$xx7yUwdYP6!1w2y4A zkcCeY>-a1mO;AQUc0zsJh+3!U@$(io-!VH_R0+H2^ePMtAFsw&kiks{tDR0 zfieEh4F8CWB9^|#O{X^;CXMpsV6B_4sVClxWSzWwS=+(ninR(z-X}x2R{vd|C{lzI zXZ@p`VV~g3{i(P^sfq&Cl}3~(Cn2BkbC-&6c6>oN!g}qEt{m$_{l~CP#KCAWlYJ+H_)chiadde0C%Dk9th2L#2bmQT$z1xP_a+?|=uIyrrF$$JvJ~Cf4qfML^(+ z&-V7i<=KjQ-R!FEO9;e zjuaEI_jK|yP>jcUuV25$qD(z|u{=6?0$&{EUY$EpHkOsKeFV>)pE9vC;r;FtWgg2g z37&dv_4Zxr{RCZo0j0|Ie45OckP45CKrOjAZ=E~4zJzv zcnL)gz7LPbb~nP8&SobQe$Me4{E;!t!a+ALEFELam-jjo+TX%<_c%Fpq8&V;W$x|( zPo6Zx?<*jb^m+TeRhU(IMc+7~?;m+TY8%{)qED&g+Bi6lsJ?lVm?Q185r@Lbji@>Xbeu?D0fWEe$u)9;2)c@f;{o)SfwRgFw z+jPg3~9d}6N))+&7+?^ZwMw*6rn zw>R!^U87JPvp6__4;Y;rEG!<-rzlX_`Jw-zH1u{%i!1P~0QK(8h;wG2s&?&SMm- z!%S9rH=%6c0ypW!;EiGrm8|r76k_hUY5+uG7)+TNCmn=ul?xpi7PE8P2=cH zCxuLC{4}96aA$Xc3DTVgzc048)u;D%H}7_)g6pt3h6KJSQ_@NL40=Z4!_J)=t&E%} ziV)m^6^0eU)Zyey@V?v|jwhWwQBsEBkD?e-WN5`#?qyIA;d^sb1X8zyKZ2D6;<5s{ z`m~(AN7x(2xH9jt<-_I4qesh&XU`X3e-NPr+3nj59AK-m&ZN$y8fD7KAHNNQZ6I-{ zMFl||-GT9##J6c*UEbsyX@0uK9S;>pkMdr>{%U#k>h<#E$+PURsJPijPHtYX{`r^R zmLGrmIo}Wb<(FTVfBlz#S$_WMr{#yg{&o5J=bx9~iU08j@A>?cOVHl`dHeS5@&Tpm zDmy&B3H%aLsz^(xn(#Hh+<^l3><&vN=;lJfu@a@p@y0lo2GTQkcHH@euYE!_4=o%V zWQWZ=RGnB=sH$vN(Y7TURVwM?KqD0hB~|_HUv~rTFX`t5?!6qJ5DdK3JC98KB$M|N zcYKux?K-J?`CG*`m-|(sF3+>WbcWx%V=88!RSa1qTm#4X6@5gxYX-?V^ge@5r<8T& z>QkpG6dxUAwCh{DRp!Dr_=Q<{L6L}%B;aiTjjKp=Om z>|5jMl7zdfTV*M)E&(o&`=moIV1t`ZEI2Dm?ceMwr%eV4Z3bQ{?Q2=+SCppx{q5z= zS5KEG&yFagLIrdix44XVWQ2T>;tV!nvj6+)1k*+$Zj@);FwT&TrW5bTi$r9cCmfXR zAJWZ_q2}Qq<23V~bSBoiF&Pc1Q+mj!p>FcDXv6;C)cltQ-pdmHSzqZweb|;I9?+Cl z^R95yrI)SJ$NbEcerL>?AP}3 zw!aC)j&ie&DAvwB!$syh#YAC3q5AmIMKtkIqUe)MGv=d56Q{DpxNv6*T;s=@UM|tq zv|SXc=ieJF0s=b#9_|b$cRk4`Ub@gZ#Gdb+(%KJBqET>gm3a=BC{i%U4ioV%E3~|; zDfe-_z{<)Nf#{A$l&L69wF(XyuEN+!48c4Eb$6#ATiUaJ+Ii^2(6}fy#$`fK$*B^S za@K>gV*U15nOdCgI$tZ3_?xC_={-}WNSH4Z1=jkeLeu@>K$^RPnoV zcM>`}M48%S5<<9pZ^}B`ei^46gE1;xJYYZoI(Q6aSQ|xNFO(|0olvx{(6h54E@V<* z-l_n=B@qOvUtC*t1~>HaP0g-CJ@U(I5rEmZzS~c^k2VB*@P}@H9Gu$Fa}2iZKG0q! zOstBI%AK%8$&+jIH(cWLHt>-@7k3G}lR@kdx*-bWus7OM)?+bWr0DLH?ewS!8WATP zssHBw^7gm)qlZKK&CT?J&4{Zwc@!l69zppz5)~>xe>A^OC?qPd zPL$o1>WdQd=@KR?j~MguStefj@Y&O6%Xi=Xd3pXE1#TR_`EDuiRQ-s;r2XmFUzQ(# z{JAd5)4%`aFFCUEsL5j)<9{Ij?fZAj2PW{}-~Yb+_U>(Vuso9Tt>3=o+xuG5T4lwf z9O0EF_JP&~fZts6h|!%9(-he5`fLN6{j4G@j@e<&Z7;2lL; z3XOdD1(=#G)Hk|)aPxRjT#sW9z(r%vAV z>jWx;@8QEfz~C@zTjqBhW{fL0X>(MYI&x$z-00@8#&UGLm#6!-cbv$4YVZ&<*ZoyH^#U4-qVHXp@N;Tw;@+{Po2si@&H3W4LqKke9ftc9oR?)z87`pYdPXzzs>FdKfqA zwLS$~V=%%qZ1L9`J@8;)>$-3i?)5g-t?l7Sm6}y~k&mfs-gRS^Kbkw`wspq^52N%+ z1An2zDBleq-PXU#Z*b%hp2VjXFM{ysZ99=z!>pp=El1+)4w8|L6|?C?`ndcQGxOj--btf zDm%n^{O07lyWP)l9PIls-Tk~ty6-XSQ(~RWs!*vsN$g+=WGBaDK!T$^ zo&jJQajD8{AR3RfQg7Z|OL+cB&)>k$YVw_Q6& zm0C+)8A>giA;YAg62Zhhc0{^5X3|nv;^v+T=^bR&Z+m49{h@>Kt2kj*^n6Nd6J<}F zbXAt6za()W=Ovr^sUZrm1Stbivv73<9A${f#7SBD_ER$m>%>XekThl8@exKR+$dAJ z*1<0wL>v9tC5`LTNa86yK4l`vaiS{=CW@(80r7J0}?=P5t6 z(9(%TBb~{XT`;X^C(C#^KxIM%cJ!tPnTz3 zy;+{W`D!_N`f|C?0_XR)@0WMbyc2~WeS+t=!f*0o#+G~-K8P3%+%OiM{uw1}Q?qw>h2yD`sSk8(bSqJ(er(%8v1JU10M`KX=;v98Jb7 zt^X?(f}qC+q%la&oXdesTn^@QqLKx$p(e4R?BxCqfg5tN<&Y z37;>BB|wyuqXW>k#2bH@yZN2uR+A>_x=x0GLEqVb)@GVC38LxSv?3nFCLU{Cl#k$7 zxu%i6+3_=vaGF!c>QaXI__5|QY_8<3>s;wrXrJCGR@Nn+&1nCMW6O1Zg(kzcHIt=> zK||J1In;LX)BjOMh8usynNREQ;x z4M*u|7J^hZ+OTco(>Kan%8Rj6UlQzN>dykives*yC6zCsOKXai9|)@`-IC9psvKS4 z>erIRIS@iSAp1FGLO_$sP=slX-g%A)wi^pjKH9<)|jbC zC9IVT((AM;gH+I|Za9f}+1X;4tyuc+>K%K zl4kZvcHi7>3th!WWlB1hhPCxi0izIF9rfX_^7L`J79L@}62|V{qzs^>Jn8ESl@qIX zE$oJDhp!BcP_9%_=wqor$9-78DW`B%p>pM%dwtM)Yhyc4)V*giwGT6qQHc}3Z%U6s zMZY*4CtMMfW=_Yu+VM_T(}lCUYGc<8d{m^mOL!e+D#w2Ghs@)p^Y6aG5H9LVAB?*5v1eda;HwbH!-@t4*rvOd#7S$(kOhNnY;Wh7 z(p@S)In;Y~V}S&}gg;yg3)d&0s}$o;1^WhibysTkw{DIefs-zzeRqdgbYY`RG5&Kz zPrcIGqs&dwb0Ic}t# z{HMa|%UA73$D*%LxOCSLzj-~fR6%tNWsF$|cvhjRtE{XanuZUZOr#VR-i{JX+z?-h zj~l+d3wOk{UprnqR#m9np>nCFBIOR1@1s&4s-)>gsY^{RnB5&z{&?>W*i)Boht~D}h<6k!svzRDUZW06|7oS587zEC_JDzwNOEda$SMm>6yrhfP zc`Fa_Fs9~J32}Fx6t5@*j!essdS)HEn#%0TYuhkmR0jPqg|%?snZl#5@y;`?llc5^ zdm3GNP1mT@wU(xp#=&9SfU|sU@n~Kw!NwGN>uMK?->lDYayQ++ z#Xsw4y|!gd@&eS6H-;OY@c2&#Ph5FO{!x+YyyzlGo*r|TaYL!PYlGVD7n(7QLiKDY zRAv(3`U^IJK+L}YYRr0v;FtMh>6#7G92`|N=24vYm3+JQ(V^d?J6w+3-X@&gB?inx zlneze|M%J>RPyIVlSZ$G}3{8_uecb@dW4WlrhP;Dh5{H9Bf-Eiz;>s2#)}zjRMs7 zIeGb8g(~SX1NC*_Oq$!@#GzREyFV16?oimwtPZGQ5X*Q_m;1ic;(f;_oRY9ZO3JxN^>t1kG_zm z*`;y^kovC2lV?#L#StY%+?~JV#i z>6Xj#gZ{pnz+EtRRFp{`>)GGgaaF;Dep4~ci)Od)?oa7Pp&H6m_$EAEzL5UqYYgo| zuqdF}fwT_^=jk1cxLeM#=$Of8Y&_-z7nO=GSy2>KB!B!l?~qcl^W9Uv@%#YVzIgL> z?Ea%i%kJ^f9{jQaJooRRBtY%R z65!9`0oSpFP+6|Xw~HeA^y$;(4 zks>%tpIgcqmS|OY;5RejDo3(#CEfByi%1@YrmK@ml@<;VO5NPCj|T zBR_YjJo3~1;LaL~mHp72Fy*_v)&5j=Ssf!SFwu$WM`Ng(KG{T}dJKQ~uz)+D_vlA> z$FW5}35fJmL2*Y2>hGXX=xF~FPjVWpj>Q)cPy+~i!Kl}L?jN6h zpBJ1_p+piO3l$Ly7s(_gR3p%-59ZfJuC!9)@GE?Et6Xd>2MAd|pAuyXM#@eR&>(74 zzXm91v4bg!6$8qN&E2Tn-+>8pglD{p35@EUsUFc(fs68_C6893=DjEk#J*^5C{*N$ zA|)Xy8zz8=S>1qSR$>N11L7nqRPJOzh7f`>A)0OpEDU+uw#wg70y9ZNFNIgdR!Bw5PGH0Ligg}N;*aHS1Gl|xG=3J(w{n7kzKv1E3s@Jos+PE8kTmBhTUS>=hC4vr->@Di;9Lggbb zV~euW{uBOP=zX-y#0%_y`H%ltE-$Xa6Ami-&37q%_tjT9qK=RUc5xS{sZeD{(9uSn zK_7U;#a%D&Nr`8aS>W*-(CXJbS*JJbIG8`RiYQSbqHFm)v#oD9^WjKg_NY z^af5JvzMNJ_}I(Xpp`gx>{RL zUOju3&pG+Q@jrj_=j9*%{Ey53RLCQe~A}- z^CX{t_JQF+fD!&1E7Z^ndz-r5nLfAoRr1OIiCa?(8UZR3x|DknXQ zlQ|_aBs6Z66V_ReKYf{#`E}O{>qJf+{;ad~gKyvyT}SfWZf597=m`B>m~1o_*gB5BdvOwf-}AuoAdhg?9uv4ahSJ8CR+L6|kO_ zBg!emz{0Phv$v-*wU=YQgPr|lM*(Y=AST;FEbCGzFi3mkr(&Tpg_7Ye7D|!3Ax`Om zOJ<;M1zaqGVRexc#!Ox2r|jzTBE*|Ym32rcg?1-En5^H)!T~FF&0B`asx-|9 z>Kvj%aF zW-WyCM>-0e172mye(#;6&&#C~If78d%AJPu>&w+qg?Ff|Pvby#(({6R-Z&3TPFm7P zhHW~+-995OJYauE;lh$e1k5Cj1zBDY*Y>T0RjBFil`xhDxzhyKijzk@K5njcXJqEd zQ;NWvm*^2^ePZnt;W>7W0qKE{pKpkko+ul@q4IR?dqX@gkHP~zm>4`}lUG$ZJc9OK z+n)FK;GJK7`Xv*xZzJ#S;e$++-+l89io$lf*f!kd6pSeRqhGWtbl2Bcc}2l3xb=t+ zr52^iL3wpKcBfQS5UM`K_Xzv;^nCf}fB(z!o8Q_a|236wq2z3`_}G9a?$Iwy>&wpJ z(X!|6$Kxl<6>Yg=kljcX62K5X$DO?3>j7?n#a_^#9)JdUeFBrb3yddEpGC>oJ=k4t zDDNfhy~9K3G>8Kn4 zWx~pU9&7FG>@1I<*`MEhwY+)$V%bJs++18NXFgT=?$;<$Dx15z-jl>`qhz}Bgs+`M zkB^QPUrFJMN4-<(gCFu{a`0p`S_EUF_{44`h;xzLB&diN`5v@7<{n7s=ZffStmA2X2*>3xA5OR z@_vTihtTO;l-zG#eziP5e72nIK3R^opDrgm&zHUXN6Vw_XUnUTSHwSFHg2Ke`OR{l z@xAqMCvdonAul<}hJgzZs;8%w07ZI#+Du6Hr@hVeQl$`gXEa5LT z2>Ww9E8ipI>38KF$cnGBJIaOGEn!3E$DcU@nBMkg&wHU+qI%#iWS%NBR~lgBjc5g<2{0uy!Hcab09VQ&T< zn;Ljmd9qdDL4nerk9Wf(*`fOOA0K~jZDEX7n@s62U~A_QZ54@6*VUzRnV@IC0#6kE zW24!Qb`{1%?Cz8T;{ZYHheTzzepHaWR1<}U!4f*sjzq}!zs4%J!UCoP;2>sM+Ooa8 zwqd|E-AuU(4cuy?6oaUm)vE}|iBk{;W<4$K+ng|sqJEwRHdy)2CZEQMeM8?GyI zCuB zU3%}vi@ABS3uVR2zT)8O+`jRZ4IVjqkE@DZmAmXN08bR$2x?jicVU60M-5f10;PY# zZ59LMbHaC0yaCR*DnP~wFJTosVf47K_lw3c88F_UD5#VOv-u-f9JsbG(Wx`k48KVe z`@P$^*9`JpNGEUVq@8)ZX*nlxC#)UlzK=rdMD+Xb@0VYH{w+#bP^90y*Y@4FC{#>@ zX@mAM8DTO$u$Nco2o+#tQV;ClQ@1-+xsPOjfQx4T-~dJHadvTp?O*=&FN<&5cHnH$ z2l9eS!X=ZqFZpwq?Zj{LJ$aJP%Xmy_UBCbOI||}u`$f89HNEd4jobyi$yk|m`^4nt zv4;8>wBnrXmx( zoeG_OC*M2it>{ZylqSZaJIcw=Pfy0qC~s7FSPy2F&De#f+}XWmA)^xIBEVzoKFDIf zd?M^a46WO8$}weN6l3fLZHdz}X!q@_H_P9D{q6Gd@iWHT!LoI4YuUaJUY|FY-+%nD zT)e+rK3#v#t62PoseLHGKCPLLXe-l!FOwhr?NOf!l5*1VF30PdF8qMkco;|ik)J@Q z_!}QObWBu^C-{YNtWOgo%JAW#xRH~q(KAu^11@E)Rdoz@{Gd=h{k{Zg z11W3)Y%?`ul$6Aea9mgF6|4zF(3%EHbc7egy}%ry<{N^Ys0phbXM(d`ehN>u;kM~f zo!i~smr^KqpbDG$r@$3oxBQ(@0442PRsk!5!AIg!#;G)nY8fa{S3`HE=j%rEC8%v! z*-*+_PhA;v3{Gp27Wkr};?Hp-I4Zz(OCM-8;GFbRKpK~`bq1QsV=mMaH-%^FO*>Wn zbZt9fVNeSNhR}n2q9TL4E9HF$?@syHy>E4PqW7MPlZwjJJ`nl1SUa zt%9YJ;9I%v9~A*FYabs!%B5;Qb>ao;)3XbdI2GF-nRxfgw{m-T$+6+&;-v2P5dOul$@ za*`bsKMpNy?xeUe81QFxrxA2UgxsEoqP z@~6tQN@AX1q&}4Z>97NRvy+Yz^!Ul6<<09?*w@R~Ut`~Vy}W$!B7LEfDQ!-0J;JhI z+%>X(kMZ)EBHGdV^sYz$c@mklelXpgD#kr9OSkR-gM*VTHp&rYrH}PWG!=OlY8`is zNBzY4E;QxKxXUa$|H!2wAHT>i)ciS-=Z>TN4BvR{=W8U~X*J&QYIz}5 zdB{T9u}J>=nn2Hp;Do;@7)!zJXKN7C)da?e32L8BwVy(O^#^goQkde zA-IAd&grKFnE!;4U-Ou$_;hZt3Fit4WP65H`G%p6+%ZbB<+S=8f7C}p=N0N3_4>4` zIHnD(^CQkGJZ<2OUwEbEFvJssN4_TA#xdo+J2!1KBDrlpDT%~LKm8O}S}P;8QX_RR zHs<{)z#zUWZ`0DEdIGRTUM9W^HT_nrwLx9yumnhBm`rcSjA_KFqv(%9m9hirR^9=o zwe)PTM*oPnqEUHLKr%15#C5XG8_E$BuEt!I<@kufH;s&!RW#)l5(ae<0!&iKFEO%*ld|pHbi^n%ndDB9f)Sv$dCO#N(~6QWU6JmH zN%?UnLK^f*Hx)?*q_|Yjo4!7wC28YasD{R)G z(jcq~k-qO}+AVU^Xdv3R`v=$P!@zjJF65ZFX=_l!Wyh!RWoB`Fe+Q;YP`dLPa^1tkgH~ zU015oKTygZK{iM6Qb?yQEn(libVYsAOPc#eW?8@;g@dgD2owRJ3oukQi(GJ|X8$TiOLypZv-bcs|7i?Q?7e?cDYAbprP6ySHzb zUw`=}ccp~gNm$Rj_wQ0hp?l0k{f3pjleqnooj{wVU60u>&d>AhKVh182BXx{UKA(# zOr^g3tKeM%!wG%<==dbcvkLZ4KmCxmbxT(j>zB`-FE5|JjKZ+Dx5L==ZS}n;C4Z~% zd1>2mZ9ll`R)JD6$R%48hF-ee3;$0$`MnDYK>``d%agiUov-zCl;)yqX5uNtpJT^G zl$GQHww45O&fE6o8?4G~o>aVo$5>SOiUO6UDEqj+2g?5H5fJo(e%{Aax$y%sUANx!iWapPjHnM^I+09nb zLb1rj|NFE_p}?bJ!Gxup%^1u?tzyNP95l@iH*s3S>qdG*pf%dpuIEobteFgN^2jzS zH10@Eg(~mSVgcYoBq}M&39n*oxswJDYyzk|Q`^-2`0!|X^ZZ$k`cClszCrI&`2dpd zv6Ci|C-kc{igIWFdjyB;JmUQ~-wl>`$k7LaHWg|6SQzQbxUx%J>WlmyN>uK^#IL+i zHkr?MY+F0yNx zHldB&_k`D!;mR%7@o*;c&vfdioi;c7(Ya1ol)Z&Ja1DF{DXv3h0zc))oslj&&CoiK zqt-F#lX*7r!;-J_BX*^z{wH=ciub=`NEaafL~Y`AXIe13kor?+Yt_88Ot=_f{8ib_Q+W}{AG>R$vVkCWN2l+>>W-A(3p)p9-^84|UbtSO7mp|^ zsgJt-qu#8TgaJXBRVZ-ej*XKiZADO#@A@MOn|HIcR~Pi>NARP6JWj?wz<#=MqV#Rl zt>a(+^)JgAljDPpe)2}e+rBtanR@+d`G-IM-SP91VorhMQbUWLlzt0+?A$j>8tCl(*F=mJ73uMbY9&hRk(W#9C!n-iTAO_dxu zu#=ztE+0Cksz`ut>aY!&BfRGBCbW-|i+eR*OOOw6L+{dwy5PH8^T>P9@0Ky5qT~~P z*B9r@)rEBZu$+DPfWmZ|J6NZ`zgym;2wxC)O}%s`G*Wh|-2g=#O z%9C91L0(?0;tAcoGZlpj#la&&X{juX3~?Odc1OdD_|nXA2OSuzDr4E{aknFRk*cI+ z7YFMkLWFFU^vZPQ(2(nEY13H0bhVrlOcy0ps2uknpoQbZ#gE-*9lP$%0rT$mCOidx zz;=Xk{p9F)dGYwk^6dCgj=8qTQ>9g z4DAV@<6A{DWcP7wWp*Za(#a^S;TiI{gOW+V4C7zY3+jlP=WHT{JF9azE;ZHOyRlf zyTpd4Gp8~4`U_xKpi265l?yXH`Gdc%+}ifdsoVT*-wDpV<*ULlnizDnj@Dyq(~fFJ z-qy38K69lF0$H3}f2@D40dEa;=-1L({>ONXCr|r}ZZdKWf99#k9^?f6Yz$=#xN$*o zZSrG{z|6S113r_YJSjB?EJT_|eP@EcI`W%lcGw(vGbsgEMA0-~5GC4d*_lEqSSeIv zhsw*C*`-ozhrwi4ncSM1PhsQkNGBLC#rDW=Yt-8|g=MY)RJ2^3b_Yd2?Me^`XPGEb zG6Dh1{jDb5_*(xJSBVwnEe-llW13}#5*0JtkYsAf;17J_oflr}2i8f`iHG^aN>m~3 zj8=GLD;Po3yrqxE-1==B5iwxMFvujNBGIG1PU3k50Yd1S)wzlb(k25s$9(jI0?((B zazx=km*E1x3I_}rT2`n_7vm#f_=^mp&Fm1-es>G_3%#YCG}ofwksgJL_Eo67*OgZ! zAdua~@#TjXgg>ZEot-Ub#QCi?1!#7t5H?vMO`$;>uHtSLL{7Yhp+r`3)Z>cUJf^9* zxeF$(-L)`d?h{>qLg;TTNBhUi{?;D$kiPO8c@LN0e|v{LrO(`5c(@!L9W38{{WS`x zM}E*8VPDn90VHjN2iUOs?H7+Cd|y$&_oVdgv94oB1^1j4w|RT<|6v5HFuTG(d33TI zq3Fs#5IC&mr0VBn6nlB<44P~pJUz;CY}v0Kr5t)U>jcH=>GS2)OYHL(C{WLqzyIz} z%Qs${e)THHQ@dNfK-Z^@wlleV>}MTLJ~>{!rl0HwtRGtLPC#Fe;BJjGmaA-czvT5T zCQ^?w_ff{~?&IyDF!a?1PAPsMOjvZRR~&XXn|y$^-*FGbZ6r`Nw-yey-={x~~}d{1Lvf zee$b>@h@=rd8^b(dxy|oTBr!;qPW){NDsWYUO3K+Oke}tc;61q!O(J&UnRdymc53p2M^+N-yhKHA)*~ z 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

Ey@FPOE=*=38c|zP+bah^ja_pyo|J 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 z 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%0DXx&{H2oi-(mxeZm*BC&Q+cqdK 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≠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 literal 0 HcmV?d00001 diff --git a/otf-frontend/client/src/app/layout/components/stats/assets/icons/equalizer.gif b/otf-frontend/client/src/app/layout/components/stats/assets/icons/equalizer.gif new file mode 100644 index 0000000000000000000000000000000000000000..22ccbe3450f9a4fd566fc178d9e4f2ae70da2a25 GIT binary patch literal 90816 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 @%t*ywdtIVsb%B!!+udmK;s4jp_O+jN#;q5fl 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