├── .github
├── CODEOWNERS
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
└── PULL_REQUEST_TEMPLATE
│ ├── bug_fix.md
│ └── feature.md
├── .gitignore
├── .travis.yml
├── Backend
├── README.md
├── __init__.py
├── common-resource-files
│ ├── role.yml
│ └── serverless.yml
├── docker
│ └── serverless-deploy
│ │ ├── Dockerfile
│ │ └── src
│ │ ├── post_harden.sh
│ │ └── requirements.txt
├── emr-autoscaling
│ ├── README.md
│ ├── __init__.py
│ ├── serverless.yml
│ ├── serverless
│ │ ├── cfn
│ │ │ └── resource.yml
│ │ ├── lambdas
│ │ │ ├── add_autoscaling.yml
│ │ │ ├── delete_autoscaling.yml
│ │ │ └── list_autoscaling.yml
│ │ └── models
│ │ │ ├── EMRAutoScalingRequest.json
│ │ │ ├── EMRAutoScalingResponse.json
│ │ │ └── models.yml
│ ├── src
│ │ ├── __init__.py
│ │ ├── conf
│ │ │ └── autoscaling-config.json
│ │ ├── scripts
│ │ │ ├── __init__.py
│ │ │ ├── emr_add_autoscaling.py
│ │ │ ├── emr_delete_autoscaling.py
│ │ │ └── emr_list_autoscaling.py
│ │ └── util
│ │ │ ├── __init__.py
│ │ │ ├── commlib.py
│ │ │ ├── emrlib.py
│ │ │ ├── exceptions.py
│ │ │ └── log.py
│ └── tests
│ │ ├── __init__.py
│ │ ├── conftest.py
│ │ ├── pytest.ini
│ │ └── test_emr_asg_add.py
├── emr-cluster-ops
│ ├── README.md
│ ├── __init__.py
│ ├── ba_step_scripts
│ │ ├── install-dr-elephant.sh
│ │ ├── install-gradle-bootstrap.sh
│ │ ├── install-nodejs.sh
│ │ └── syslog-setup.sh
│ ├── serverless.yml
│ ├── serverless
│ │ ├── cfn
│ │ │ └── resource.yml
│ │ ├── lambdas
│ │ │ ├── cost_usage.yml
│ │ │ ├── create.yml
│ │ │ ├── custom_add_steps.yml
│ │ │ ├── dns_ops.yml
│ │ │ ├── precheck.yml
│ │ │ ├── protect.yml
│ │ │ ├── rm_proxy.yml
│ │ │ ├── status.yml
│ │ │ ├── steps.yml
│ │ │ ├── terminate.yml
│ │ │ ├── validate.yml
│ │ │ └── validate_steps.yml
│ │ └── models
│ │ │ ├── mapping_templates
│ │ │ ├── EMRClusterAddCustomStepRequest
│ │ │ ├── EMRClusterAddCustomStepResponse
│ │ │ ├── EMRStepValidateRequest
│ │ │ └── EMRStepValidateResponse
│ │ │ ├── models.yml
│ │ │ └── schemas
│ │ │ ├── 500ErrorResponse.json
│ │ │ ├── CreateEMRClusterRequest.json
│ │ │ ├── CreateEMRClusterResponse.json
│ │ │ ├── EMRClusterAddCustomStepRequest.json
│ │ │ ├── EMRClusterAddCustomStepResponse.json
│ │ │ ├── EMRClusterAddStepRequest.json
│ │ │ ├── EMRClusterAddStepResponse.json
│ │ │ ├── EMRDNSOperation.json
│ │ │ ├── EMRRMProxyRequest.json
│ │ │ ├── EMRRMProxyResponse.json
│ │ │ ├── EMRStepValidateRequest.json
│ │ │ ├── EMRStepValidateResponse.json
│ │ │ ├── ProtectEMRClusterRequest.json
│ │ │ ├── ProtectEMRClusterResponse.json
│ │ │ ├── TerminateEMRClusterRequest.json
│ │ │ ├── TerminateEMRClusterResponse.json
│ │ │ ├── ValidateEMRClusterRequest.json
│ │ │ └── ValidateEMRClusterResponse.json
│ ├── src
│ │ ├── __init__.py
│ │ ├── conf
│ │ │ ├── common
│ │ │ │ ├── autoscaling-config.json
│ │ │ │ ├── common-tags.json
│ │ │ │ ├── configurations.json
│ │ │ │ └── configurations_r5.json
│ │ │ └── example_account
│ │ │ │ ├── emr-metadata.json
│ │ │ │ └── emr-nonkerb-config.json
│ │ ├── scripts
│ │ │ ├── __init__.py
│ │ │ ├── emr_add_custom_steps.py
│ │ │ ├── emr_add_steps.py
│ │ │ ├── emr_cost_usage.py
│ │ │ ├── emr_create.py
│ │ │ ├── emr_create_nonkerb.py
│ │ │ ├── emr_dns_ops.py
│ │ │ ├── emr_precheck.py
│ │ │ ├── emr_protect.py
│ │ │ ├── emr_rm_proxy.py
│ │ │ ├── emr_status.py
│ │ │ ├── emr_terminate.py
│ │ │ ├── emr_validate.py
│ │ │ └── emr_validate_step.py
│ │ └── util
│ │ │ ├── __init__.py
│ │ │ ├── commlib.py
│ │ │ ├── constants.py
│ │ │ ├── dnslib.py
│ │ │ ├── emrlib.py
│ │ │ ├── exceptions.py
│ │ │ ├── log.py
│ │ │ └── rmlib.py
│ └── tests
│ │ ├── __init__.py
│ │ ├── conftest.py
│ │ ├── pytest.ini
│ │ ├── test_add_step.py
│ │ ├── test_custom_step.py
│ │ ├── test_emr_creation.py
│ │ ├── test_emr_precheck.py
│ │ ├── test_emr_protect.py
│ │ ├── test_emr_status.py
│ │ ├── test_emr_terminate.py
│ │ ├── test_emr_validate.py
│ │ └── test_validate_step.py
├── emr-testsuites
│ ├── README.md
│ ├── serverless.yml
│ ├── serverless
│ │ ├── cfn
│ │ │ └── resource.yml
│ │ ├── lambdas
│ │ │ ├── test_autoscaling.yml
│ │ │ ├── test_bootstrap.yml
│ │ │ ├── test_emr_app.yml
│ │ │ └── test_steps.yml
│ │ └── models
│ │ │ ├── EMRClusterTestAppRequest.json
│ │ │ ├── EMRClusterTestAppResponse.json
│ │ │ ├── EMRTestSuiteRequest.json
│ │ │ ├── EMRTestSuiteResponse.json
│ │ │ └── models.yml
│ ├── src
│ │ ├── __init__.py
│ │ ├── scripts
│ │ │ ├── __init__.py
│ │ │ ├── emr_test_app.py
│ │ │ ├── emr_test_autoscaling.py
│ │ │ ├── emr_test_bootstrap.py
│ │ │ └── emr_test_steps.py
│ │ └── util
│ │ │ ├── __init__.py
│ │ │ ├── constants.py
│ │ │ ├── emrlib.py
│ │ │ ├── exceptions.py
│ │ │ └── log.py
│ └── tests
│ │ ├── __init__.py
│ │ ├── conftest.py
│ │ ├── pytest.ini
│ │ ├── test_emr_app.py
│ │ ├── test_emr_asg.py
│ │ ├── test_emr_ba.py
│ │ └── test_emr_steps.py
├── pytest.ini
├── run_test.sh
├── serverless-deploy
│ ├── README.md
│ ├── logger.py
│ ├── plugin_install.py
│ ├── plugin_metadata.json
│ └── quickfabric_setup.py
├── setup.cfg
└── setup.py
├── DB
├── .gitignore
├── Dockerfile
├── QuickFabric_ER_Diagram.png
├── QuickFabric_ER_model.mwb
├── dcl.sql
├── ddl
│ ├── account_configurations.sql
│ ├── application_configurations.sql
│ ├── aws_account_profile.sql
│ ├── cluster_metrics.sql
│ ├── cluster_metrics_history.sql
│ ├── cluster_step_request.sql
│ ├── configuration_data_types.sql
│ ├── configuration_definitions.sql
│ ├── configuration_types.sql
│ ├── db_patch.sql
│ ├── emr_billing_component_cost.sql
│ ├── emr_billing_component_cost_hist.sql
│ ├── emr_cluster_metadata.sql
│ ├── emr_functional_testsuites.sql
│ ├── emr_functional_testsuites_status.sql
│ ├── emr_functional_testsuites_status_history.sql
│ ├── report_subscriptions.sql
│ ├── reports.sql
│ ├── roles.sql
│ ├── segments.sql
│ ├── services.sql
│ ├── user.sql
│ ├── user_account_segment_mapping.sql
│ ├── user_account_segment_role_mapping.sql
│ └── workflow.sql
├── dml
│ ├── application_configurations.sql
│ ├── aws_account_profile.sql
│ ├── cluster_metrics.sql
│ ├── cluster_metrics_history.sql
│ ├── configuration_data_types.sql
│ ├── configuration_definitions.sql
│ ├── configuration_types.sql
│ ├── emr_billing_component_cost.sql
│ ├── emr_billing_component_cost_hist.sql
│ ├── emr_cluster_metadata.sql
│ ├── reports.sql
│ ├── roles.sql
│ ├── segments.sql
│ ├── services.sql
│ ├── user.sql
│ ├── user_account_segment_mapping.sql
│ ├── user_account_segment_role_mapping.sql
│ └── workflow.sql
├── patch
│ ├── patch.sh
│ ├── v1.sql
│ └── v2.sql
└── quickfabric_bootstrap.sql
├── Frontend
├── .gitignore
├── Dockerfile
├── LICENSE
├── README.md
├── babel.config.js
├── build.sh
├── default.conf
├── nginx.conf
├── package.json
├── public
│ ├── Hive.png
│ ├── Vertica.png
│ ├── favicon.ico
│ ├── index.html
│ └── manifest.json
└── src
│ ├── __mocks__
│ ├── fileMock.js
│ └── styleMock.js
│ ├── __tests__
│ ├── components
│ │ ├── admin
│ │ │ ├── __snapshots__
│ │ │ │ └── admin.test.jsx.snap
│ │ │ └── admin.test.jsx
│ │ ├── emrcost
│ │ │ ├── EMRCost.test.jsx
│ │ │ └── __snapshots__
│ │ │ │ └── EMRCost.test.jsx.snap
│ │ ├── emrmanagement
│ │ │ ├── CreateCluster.test.jsx
│ │ │ ├── EMRManagement.test.jsx
│ │ │ └── __snapshots__
│ │ │ │ ├── CreateCluster.test.jsx.snap
│ │ │ │ └── EMRManagement.test.jsx.snap
│ │ └── utils
│ │ │ └── components
│ │ │ ├── ToggleSlider.test.jsx
│ │ │ └── __snapshots__
│ │ │ └── ToggleSlider.test.jsx.snap
│ ├── containers
│ │ ├── App.test.jsx
│ │ └── __snapshots__
│ │ │ └── App.test.jsx.snap
│ ├── reducers
│ │ ├── Admin.test.js
│ │ ├── EMRCost.test.js
│ │ ├── Profile.test.js
│ │ └── User.test.js
│ └── setup
│ │ └── setupEnzyme.js
│ ├── actions
│ ├── actionTypes
│ │ ├── AdminActionTypes.js
│ │ ├── EMRCostActionTypes.js
│ │ ├── EMRHealthActionTypes.js
│ │ ├── EMRManagementActionTypes.js
│ │ ├── ProfileActionTypes.js
│ │ └── UserActionTypes.js
│ ├── admin.js
│ ├── emrCost.js
│ ├── emrHealth.js
│ ├── emrManagement.js
│ ├── profile.js
│ └── user.js
│ ├── api-config.js
│ ├── assets
│ ├── help
│ │ ├── AccountConfig.png
│ │ ├── AccountSetup.gif
│ │ ├── Admin.png
│ │ ├── AppConfig.png
│ │ ├── ClusterCost.png
│ │ ├── Cluster_Details_1.png
│ │ ├── Cluster_Details_2.png
│ │ ├── Cluster_Operations.gif
│ │ ├── CreateClusterWorkflow.png
│ │ ├── Create_Cluster.gif
│ │ ├── EMRCost.png
│ │ ├── EMR_Graph.png
│ │ ├── Expert_Advice.png
│ │ ├── QuickFabric_ER_Diagram.png
│ │ ├── UserProfile.png
│ │ ├── ViewWorkflow.png
│ │ ├── addSteps.gif
│ │ ├── architecture.png
│ │ ├── autoPilot.gif
│ │ ├── cloneCluster.gif
│ │ ├── cluster_details.gif
│ │ ├── dnsFlip.gif
│ │ ├── drussotto.jpg
│ │ ├── gbagdi.jpg
│ │ ├── gdoon.jpg
│ │ ├── ktran7.jpg
│ │ ├── kverma.jpg
│ │ ├── nkk.jpg
│ │ ├── rotateAMI.gif
│ │ ├── suttamchandani.jpg
│ │ ├── terminateCluster.gif
│ │ └── vsood.jpg
│ ├── login
│ │ ├── data.jpg
│ │ ├── gitLogo.png
│ │ └── qf_black.svg
│ └── navbar
│ │ ├── qdlogo.png
│ │ └── qf_white.svg
│ ├── components
│ ├── Admin
│ │ ├── ConfigCustomCell.jsx
│ │ ├── ConfigDialogContainer.jsx
│ │ ├── ConfigManagement.jsx
│ │ ├── admin.scss
│ │ ├── detailGrids.js
│ │ └── index.jsx
│ ├── EMRCost
│ │ ├── emrCost.scss
│ │ └── index.jsx
│ ├── EMRHealth
│ │ ├── ToggleText.jsx
│ │ ├── emrHealth.css
│ │ ├── emrHealth1.scss
│ │ ├── emrHealthCell.js
│ │ ├── index.jsx
│ │ └── observabilityGraph
│ │ │ ├── Legends.jsx
│ │ │ ├── ObservabilityGraph.jsx
│ │ │ ├── RowData.jsx
│ │ │ ├── VisOptions.js
│ │ │ └── toggle.scss
│ ├── EMRManagement
│ │ ├── AMIRotationDays.jsx
│ │ ├── AddSteps.jsx
│ │ ├── CreateCluster.jsx
│ │ ├── CreateClusterConstants.js
│ │ ├── CreateClusterWorkflow.jsx
│ │ ├── CustomAlert.jsx
│ │ ├── DNSFlip.jsx
│ │ ├── Modal
│ │ │ ├── ModalCreateClusterDetail.jsx
│ │ │ └── ModalStepsStatusDetail.jsx
│ │ ├── RotateAMI.jsx
│ │ ├── RotateAMIWorkflow.jsx
│ │ ├── SubmitActionButtonCell.jsx
│ │ ├── TerminateCluster.jsx
│ │ ├── TestSuite.jsx
│ │ ├── emrManagement.css
│ │ ├── emrStatusCell.jsx
│ │ ├── emrStepStatusCell.jsx
│ │ └── index.jsx
│ ├── Help
│ │ ├── Help.scss
│ │ └── index.jsx
│ ├── NavBar
│ │ ├── index.jsx
│ │ └── navBar.scss
│ ├── Profile
│ │ ├── index.jsx
│ │ └── profile.scss
│ ├── SignIn
│ │ ├── SignIn.css
│ │ └── index.jsx
│ └── index.js
│ ├── containers
│ ├── AdminContainer.jsx
│ ├── AppContainer.jsx
│ ├── EMRCostContainer.jsx
│ ├── EMRHealthContainer.jsx
│ ├── EMRManagementContainer.jsx
│ ├── HelpContainer.jsx
│ ├── ProfileContainer.jsx
│ └── SignInContainer.jsx
│ ├── id_rsa-cert.pub
│ ├── index.js
│ ├── main.css
│ ├── reducers
│ ├── admin.js
│ ├── emrcost.js
│ ├── emrhealth.js
│ ├── emrmanagement.js
│ ├── index.js
│ ├── profile.js
│ └── user.js
│ ├── store
│ └── index.js
│ └── utils
│ ├── components
│ ├── CheckJiraEnabled.js
│ ├── MyCommandCell.jsx
│ ├── ToggleSlider.jsx
│ └── with-state.jsx
│ ├── styles
│ ├── shared.css
│ └── toggle.scss
│ └── utils
│ ├── action.js
│ └── convertStrToBoolean.js
├── LICENSE
├── Middleware
├── .gitignore
├── README.md
├── commons
│ ├── .gitignore
│ ├── .project
│ ├── pom.xml
│ └── src
│ │ └── main
│ │ └── java
│ │ └── com
│ │ └── intuit
│ │ └── quickfabric
│ │ └── commons
│ │ ├── constants
│ │ ├── ApiUrls.java
│ │ ├── ApplicationConstant.java
│ │ ├── HealthCheckConstants.java
│ │ ├── Roles.java
│ │ └── WorkflowConstants.java
│ │ ├── dao
│ │ ├── ConfigDao.java
│ │ ├── ConfigDaoImpl.java
│ │ ├── LoginRolesDao.java
│ │ └── LoginRolesDaoImpl.java
│ │ ├── domain
│ │ ├── QuickFabricAuthenticationToken.java
│ │ ├── Role.java
│ │ └── UserAccess.java
│ │ ├── exceptions
│ │ ├── QuickFabricBaseException.java
│ │ ├── QuickFabricClientException.java
│ │ ├── QuickFabricJsonException.java
│ │ ├── QuickFabricRestHandlerException.java
│ │ ├── QuickFabricSQLException.java
│ │ ├── QuickFabricServerException.java
│ │ ├── QuickFabricUnauthenticatedException.java
│ │ ├── QuickFabricUnauthorizedException.java
│ │ └── ServiceException.java
│ │ ├── helper
│ │ ├── ConfigHelper.java
│ │ └── LoginRolesHelper.java
│ │ ├── mapper
│ │ ├── AccountConfigMapper.java
│ │ ├── ApplicationConfigMapper.java
│ │ ├── ConfigDefinitionMapper.java
│ │ ├── LoginRolesMapper.java
│ │ └── UserAccessMapper.java
│ │ ├── model
│ │ └── LoginRolesModel.java
│ │ ├── security
│ │ ├── AccessControl.java
│ │ ├── JWTTokenProvider.java
│ │ ├── JwtAuthenticationSuccessHandler.java
│ │ ├── JwtTokenFilter.java
│ │ ├── JwtTokenFilterConfigurer.java
│ │ ├── RestAuthenticationEntryPoint.java
│ │ └── WebSecurityConfig.java
│ │ ├── service
│ │ ├── ConfigService.java
│ │ └── LoginService.java
│ │ ├── utils
│ │ ├── AWSEmailUtil.java
│ │ ├── ApiKeyRequestInterceptor.java
│ │ ├── AppConfig.java
│ │ ├── AuthorizationUtils.java
│ │ ├── CommonUtils.java
│ │ ├── EnableMethod.java
│ │ ├── EnableMethodAspect.java
│ │ ├── LoggingRequestInterceptor.java
│ │ ├── ReportBuilder.java
│ │ ├── RestTemplateResponseErrorHandler.java
│ │ └── SwaggerConfig.java
│ │ └── vo
│ │ ├── AccountSetupModel.java
│ │ ├── ApiErrorVO.java
│ │ ├── AppSeverity.java
│ │ ├── AppStatus.java
│ │ ├── AutoScalingTestResponse.java
│ │ ├── AwsAccountProfile.java
│ │ ├── BootstrapActionVO.java
│ │ ├── BootstrapParametersRequest.java
│ │ ├── BootstrapTestResponse.java
│ │ ├── ChangeRoleModel.java
│ │ ├── ChangeRoleVO.java
│ │ ├── ClusterError.java
│ │ ├── ClusterHealthCheckRequest.java
│ │ ├── ClusterHealthCheckStatusType.java
│ │ ├── ClusterHealthCheckStatusUpdate.java
│ │ ├── ClusterHealthStatus.java
│ │ ├── ClusterMessageResponseVO.java
│ │ ├── ClusterRequest.java
│ │ ├── ClusterStatus.java
│ │ ├── ClusterStep.java
│ │ ├── ClusterStepRequest.java
│ │ ├── ClusterTestSuitesDefinitionVO.java
│ │ ├── ClusterType.java
│ │ ├── ClusterVO.java
│ │ ├── ConfigDataType.java
│ │ ├── ConfigDefinitionVO.java
│ │ ├── ConfigType.java
│ │ ├── ConfigVO.java
│ │ ├── ConnectivityTestRequest.java
│ │ ├── ConnectivityTestResponse.java
│ │ ├── EMRAppVO.java
│ │ ├── EMRClusterHealthTestCase.java
│ │ ├── EMRClusterMetricsVO.java
│ │ ├── EMRGroupCostVO.java
│ │ ├── EMRTimeSeriesReportVO.java
│ │ ├── HadoopJarStep.java
│ │ ├── JobPerformanceAdviceVO.java
│ │ ├── JobSchedulingAdviceVO.java
│ │ ├── LoginRequest.java
│ │ ├── LoginRolesVO.java
│ │ ├── MonthlyCostVO.java
│ │ ├── ResetPasswordRequest.java
│ │ ├── SSODetailsVO.java
│ │ ├── SegmentVO.java
│ │ ├── ServiceType.java
│ │ ├── ServiceVO.java
│ │ ├── StepResponseVO.java
│ │ ├── StepStatus.java
│ │ ├── StepsValidateRequest.java
│ │ ├── SubscriptionVO.java
│ │ ├── UserAccountSegmentMapping.java
│ │ ├── UserRole.java
│ │ ├── UserVO.java
│ │ ├── Workflow.java
│ │ ├── WorkflowStatus.java
│ │ ├── WorkflowStep.java
│ │ ├── WorkflowType.java
│ │ └── YarnAppHeuristicVO.java
├── emr
│ ├── .project
│ ├── Dockerfile
│ ├── pom.xml
│ └── src
│ │ ├── main
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── intuit
│ │ │ │ └── quickfabric
│ │ │ │ └── emr
│ │ │ │ ├── EMRMainApplication.java
│ │ │ │ ├── dao
│ │ │ │ ├── AdminDao.java
│ │ │ │ ├── AdminDaoImpl.java
│ │ │ │ ├── EMRClusterCostDao.java
│ │ │ │ ├── EMRClusterCostDaoImpl.java
│ │ │ │ ├── EMRClusterHealthCheckDao.java
│ │ │ │ ├── EMRClusterHealthCheckDaoImpl.java
│ │ │ │ ├── EMRClusterMetadataDao.java
│ │ │ │ ├── EMRClusterMetadataDaoImpl.java
│ │ │ │ ├── EMRClusterMetricsDao.java
│ │ │ │ ├── EMRClusterMetricsDaoImpl.java
│ │ │ │ ├── EMRClusterStepsDao.java
│ │ │ │ ├── EMRClusterStepsDaoImpl.java
│ │ │ │ ├── EmailReportSubscriptionsDao.java
│ │ │ │ ├── EmailReportSubscriptionsDaoImpl.java
│ │ │ │ ├── WorkflowDao.java
│ │ │ │ └── WorkflowDaoImpl.java
│ │ │ │ ├── helper
│ │ │ │ ├── AdminHelper.java
│ │ │ │ ├── EMRAWSServiceCallerHelper.java
│ │ │ │ ├── EMRClusterAdviceHelper.java
│ │ │ │ ├── EMRClusterCostHelper.java
│ │ │ │ ├── EMRClusterHealthHelper.java
│ │ │ │ ├── EMRClusterManagementHelper.java
│ │ │ │ ├── EMRClusterMetadataHelper.java
│ │ │ │ ├── EMRClusterMetricsHelper.java
│ │ │ │ ├── EmailReportSubscriptionsHelper.java
│ │ │ │ ├── TicketValidationHelper.java
│ │ │ │ ├── ValidationHelper.java
│ │ │ │ └── WorkflowHelper.java
│ │ │ │ ├── mapper
│ │ │ │ ├── AMIRotationClusterMetadataMapper.java
│ │ │ │ ├── AWSAccountProfileMapper.java
│ │ │ │ ├── BootstrapActionMapper.java
│ │ │ │ ├── ClusterStepMapper.java
│ │ │ │ ├── ClusterStepResponseMapper.java
│ │ │ │ ├── EMRClusterHealthHistoryMapper.java
│ │ │ │ ├── EMRClusterHealthStatusMapper.java
│ │ │ │ ├── EMRClusterMetadataMapper.java
│ │ │ │ ├── EMRClusterMetadataRowMapper.java
│ │ │ │ ├── EMRClusterMetricsAggregateMapper.java
│ │ │ │ ├── EMRClusterMetricsMapper.java
│ │ │ │ ├── EMRClusterMetricsMultipleDaysHourlyMapper.java
│ │ │ │ ├── EMRClusterMetricsRmUrlMapper.java
│ │ │ │ ├── EMRClusterMetricsTimeSeriesMapper.java
│ │ │ │ ├── EMRClusterValidationMapper.java
│ │ │ │ ├── EMRCostTimeSeriesMapper.java
│ │ │ │ ├── SegmentsMapper.java
│ │ │ │ ├── TestSuiteDefinitionMapper.java
│ │ │ │ ├── UserAccountSegmentMappingMapper.java
│ │ │ │ └── WorkflowMapper.java
│ │ │ │ ├── model
│ │ │ │ ├── EMRAppsModel.java
│ │ │ │ ├── EMRClusterAdviceModel.java
│ │ │ │ ├── EMRClusterCostModel.java
│ │ │ │ ├── EMRClusterMetadataModel.java
│ │ │ │ ├── EMRClusterMetricsModel.java
│ │ │ │ └── UIPopulationModel.java
│ │ │ │ └── service
│ │ │ │ ├── AdminService.java
│ │ │ │ ├── EMRClusterAdviceService.java
│ │ │ │ ├── EMRClusterCostService.java
│ │ │ │ ├── EMRClusterHealthCheckService.java
│ │ │ │ ├── EMRClusterManagementService.java
│ │ │ │ ├── EMRClusterMetadataService.java
│ │ │ │ ├── EMRClusterMetricsService.java
│ │ │ │ ├── EmailReportSubscriptionService.java
│ │ │ │ └── WorkflowService.java
│ │ └── resources
│ │ │ ├── application.properties
│ │ │ └── log4j2.xml
│ │ └── test
│ │ └── java
│ │ ├── com
│ │ └── intuit
│ │ │ └── quickfabric
│ │ │ └── emr
│ │ │ └── tests
│ │ │ ├── helper
│ │ │ └── EMRClusterHealthHelperTests.java
│ │ │ └── service
│ │ │ └── EMRClusterHealthCheckServiceTests.java
│ │ └── resources
│ │ └── application.properties
├── pom.xml
└── schedulers
│ ├── .gitignore
│ ├── .project
│ ├── Dockerfile
│ ├── pom.xml
│ └── src
│ └── main
│ ├── java
│ └── com
│ │ └── intuit
│ │ └── quickfabric
│ │ └── schedulers
│ │ ├── SchedulersMainApplication.java
│ │ ├── dao
│ │ ├── ClusterHealthCheckDao.java
│ │ ├── ClusterHealthCheckDaoImpl.java
│ │ ├── EMRClusterMetadataDao.java
│ │ ├── EMRClusterMetadataDaoImpl.java
│ │ ├── EMRClusterMetricsDao.java
│ │ ├── EMRClusterMetricsDaoImpl.java
│ │ ├── EMRClusterStepsDao.java
│ │ └── EMRClusterStepsDaoImpl.java
│ │ ├── functions
│ │ ├── ClusterHealthCheckScheduler.java
│ │ ├── EMRClusterLifeCycleSchedulers.java
│ │ └── EMRClusterMetricsSchedulers.java
│ │ ├── helpers
│ │ ├── AutoScalingHealthCheckHelper.java
│ │ ├── BootstrapHealthCheckHelper.java
│ │ ├── ConnectivityHealthCheckHelper.java
│ │ ├── EMRAWSServiceCallerHelper.java
│ │ ├── EMRClusterManagementHelper.java
│ │ ├── EMRClusterMetadataHelper.java
│ │ ├── EMRClusterMetricsHelper.java
│ │ ├── HealthChecksHelper.java
│ │ └── ValidationHelper.java
│ │ └── mappers
│ │ ├── AMIRotationClusterMetadataMapper.java
│ │ ├── AddUserRequestMapper.java
│ │ ├── BootstrapActionMapper.java
│ │ ├── ClusterStepMapper.java
│ │ ├── EMRClusterDetailsMapper.java
│ │ ├── EMRClusterFetchMetricsMapper.java
│ │ ├── EMRClusterHealthStatusMapper.java
│ │ ├── EMRClusterMetadataRowMapper.java
│ │ ├── EMRClusterMetricsAMIReportMapper.java
│ │ ├── EMRClusterMetricsHourlyReportMapper.java
│ │ ├── EMRClusterMetricsMapper.java
│ │ ├── EMRClusterValidationMapper.java
│ │ └── TestSuiteDefinitionMapper.java
│ └── resources
│ ├── application.properties
│ └── log4j2.xml
├── README.md
├── docker-compose-rdsversion.yml
├── docker-compose.yml
├── terraform
├── .gitignore
├── LICENSE
├── input.tfvars.advanced.example
├── input.tfvars.basic.example
├── main.tf
├── main_qf.tf
├── modules
│ ├── container
│ │ ├── main.tf
│ │ └── variables.tf
│ ├── ec2
│ │ ├── files
│ │ │ ├── instance_policy.txt
│ │ │ └── instance_role.txt
│ │ ├── main.tf
│ │ ├── output.tf
│ │ └── variables.tf
│ ├── igw
│ │ ├── main.tf
│ │ └── variables.tf
│ ├── nat
│ │ ├── main.tf
│ │ └── variables.tf
│ ├── r53
│ │ ├── main.tf
│ │ ├── output.tf
│ │ └── variables.tf
│ ├── s3
│ │ ├── main.tf
│ │ ├── output.tf
│ │ └── variables.tf
│ ├── s3_uploads
│ │ ├── main.tf
│ │ └── variables.tf
│ ├── sg
│ │ ├── get_ip.sh
│ │ ├── main.tf
│ │ ├── output.tf
│ │ └── variables.tf
│ ├── subnet
│ │ ├── main.tf
│ │ ├── output.tf
│ │ └── variables.tf
│ └── vpc
│ │ ├── main.tf
│ │ ├── output.tf
│ │ └── variables.tf
├── modules_backend
│ └── s3_backend
│ │ ├── main.tf
│ │ └── variables.tf
├── output.tf
├── provider.tf
├── scripts
│ └── env.py
├── secrets.tfvars.example
├── templates
│ ├── qf
│ │ └── userdata.tpl
│ └── serverless
│ │ ├── emr-config.json
│ │ └── output.conf.tpl
├── terraform_wrapper.py
└── variables.tf
└── terraform_local
├── LICENSE
├── README.md
├── main.tf
├── modules
└── container
│ ├── main.tf
│ └── variables.tf
├── output.tf
├── provider.tf
├── secrets.tfvars.example
└── variables.tf
/.github/CODEOWNERS:
--------------------------------------------------------------------------------
1 | # To add a code owner, give a file pattern followed by the usernames or emails of the owner.
2 | * @khilawar4
3 | /DB/ @khilawar4 @gdrossi46 @drussotto @soodvarun
4 | /Backend/ @gdrossi46 @sandipnahak
5 | /Middleware/ @khilawar4 @gdrossi46 @drussotto @soodvarun
6 | /Frontend/ @nishakk
7 | /terraform/ @khilawar4 @sanoojm
8 | /terraform_local/ @khilawar4 @sanoojm
9 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 |
5 | ---
6 |
7 | **Describe the bug**
8 | A clear and concise description of what the bug is.
9 |
10 | **To Reproduce**
11 | Steps to reproduce the behavior. For example:
12 | 1. Launch using command '...'
13 | 2. Using this configuration '...' (i.e. your application.conf)
14 | 3. Send a request like '...'
15 | 4. See error
16 |
17 | **Expected behavior**
18 | A clear and concise description of what you expected to happen.
19 |
20 | **Screenshots**
21 | If applicable, add screenshots to help explain your problem.
22 |
23 | **Desktop (please complete the following information):**
24 | - OS: [e.g. MacOS]
25 | - Browser [e.g. chrome, safari]
26 | - Version [e.g. 22]
27 |
28 | **Additional context**
29 | Add any other context about the problem here.
30 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 |
5 | ---
6 |
7 | **Is your feature request related to a problem? Please describe.**
8 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
9 |
10 | **Describe the solution you'd like**
11 | A clear and concise description of what you want to happen.
12 |
13 | **Describe alternatives you've considered**
14 | A clear and concise description of any alternative solutions or features you've considered.
15 |
16 | **Additional context**
17 | Add any other context or screenshots about the feature request here.
18 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE/bug_fix.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug fix
3 | about: Fix an error or unexpected behavior
4 |
5 | ---
6 |
7 | **Describe the bug**
8 | Tell us what behavior you're fixing. If there's an open issue
9 | for it, feel free to link it here.
10 |
11 | **Example output before and after**
12 | Show us what was going wrong before, and what it does now that it's fixed.
13 | This might be a snippet from a console or a screenshot.
14 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE/feature.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature
3 | about: Implement a new feature for the project
4 |
5 | ---
6 |
7 | **Feature description or context**
8 | What problems does this feature solve? Feel free to link issues or other
9 | discussions about the feature.
10 |
11 | **How does this feature impact users?**
12 | Tell us any changes to the user interface this might have. This might
13 | include end-users (e.g. a UI feature), or it might impact programmatic
14 | clients or API consumers.
15 |
16 | **Code highlights or explanations**
17 | If there are any pieces of code you'd like to draw our attention to,
18 | point us to them and tell us about how they work.
19 |
20 | **New tests or modified tests**
21 | Tell us exactly how your code behaves by providing (or updating) some
22 | tests.
23 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.classpath
2 | *.lock.info
3 | *.tfstate
4 | *.tfstate.*
5 | *__pycache_*
6 | .DS_Store
7 | .idea
8 | .idea/
9 | .idea/**
10 | .idea/*.xml
11 | .idea/*configs.zip
12 | .settings/
13 | *.coverage*
14 | *id_rsa*
15 | Middleware/commons/bin/
16 | Middleware/emr/bin/
17 | Middleware/schedulers/bin/
18 |
19 | crash.log
20 | *package-lock.json*
21 | *cfn-stack-output.json*
22 | input.tfvars
23 | *dist/*
24 | *.pytest_cache*
25 | *.egg*
26 |
27 | .terraform
28 | terraform.tfstate
29 | terraform.tfstate.backup
30 | terraform.tfstate.d
31 | terraform_wrapper_*
32 | secrets.tfvars
33 |
34 | Backend/emr-autoscaling/node_modules
35 | Backend/serverless-deploy/config.yml
36 | Backend/emr-cluster-ops/.serverless/
37 | Backend/emr-testsuites/.serverless/
38 | Backend/emr-autoscaling/.serverless/
39 | Backend/emr-cluster-ops/.pytest_cache
40 | /Backend/tests/build/
41 | /Backend/tests/dist/
42 | /Backend/tests/quickfabric_test.egg-info/
43 |
--------------------------------------------------------------------------------
/Backend/README.md:
--------------------------------------------------------------------------------
1 | # quickfabric
--------------------------------------------------------------------------------
/Backend/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/intuit/QuickFabric/a7200cfdde42a033fbed04384028833b8b100a6f/Backend/__init__.py
--------------------------------------------------------------------------------
/Backend/docker/serverless-deploy/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM node:lts-alpine
2 |
3 | LABEL Description="Serverless Docker image for deploying quickfabric"
4 | LABEL MAINTAINER="opensource@intuit.com"
5 |
6 | COPY src ./
7 | ENV SERVERLESS_VERSION=1.60.4
8 | RUN apk upgrade --no-cache && apk add python3
9 |
10 | RUN pip3 install --upgrade pip && \
11 | pip3 install -r requirements.txt
12 |
13 | # Skip serverless version upgrade check https://github.com/serverless/serverless/issues/4319
14 | RUN npm install -g try-thread-sleep && \
15 | npm install --global serverless@${SERVERLESS_VERSION} --ignore-scripts spawn-sync
16 |
17 | RUN chmod +x post_harden.sh && ./post_harden.sh
18 |
19 | ENTRYPOINT ["/bin/sh", "-c"]
20 |
--------------------------------------------------------------------------------
/Backend/docker/serverless-deploy/src/requirements.txt:
--------------------------------------------------------------------------------
1 | awscli
2 | boto3
3 | pyyaml
4 | coloredlogs
--------------------------------------------------------------------------------
/Backend/emr-autoscaling/README.md:
--------------------------------------------------------------------------------
1 | # emr-autoscaling
2 |
3 | | Plugin | README |
4 | | ------ | ------ |
5 | | Dropbox | [plugins/dropbox/README.md][PlDb] |
6 | | GitHub | [plugins/github/README.md][PlGh] |
7 | | Google Drive | [plugins/googledrive/README.md][PlGd] |
8 | | OneDrive | [plugins/onedrive/README.md][PlOd] |
9 | | Medium | [plugins/medium/README.md][PlMe] |
10 | | Google Analytics | [plugins/googleanalytics/README.md][PlGa] |
--------------------------------------------------------------------------------
/Backend/emr-autoscaling/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/intuit/QuickFabric/a7200cfdde42a033fbed04384028833b8b100a6f/Backend/emr-autoscaling/__init__.py
--------------------------------------------------------------------------------
/Backend/emr-autoscaling/serverless.yml:
--------------------------------------------------------------------------------
1 | service: emr-autoscaling-ops
2 |
3 | provider:
4 | name: aws
5 | apiGateway:
6 | restApiId:
7 | 'Fn::ImportValue': RestApiId
8 | restApiRootResourceId:
9 | 'Fn::ImportValue': RootResourceId
10 | deploymentBucket:
11 | name: quickfabric-serverless-${self:custom.config.account-id}-${self:provider.region}-deploys
12 | deploymentPrefix: ${self:service.name} # The S3 prefix under which deployed artifacts should be stored. Default is serverless
13 |
14 | custom:
15 | parent:
16 | path: "../common-resource-files/serverless.yml"
17 |
18 | RequestParameterValidator:
19 | 'Fn::ImportValue': EmrRequestValidatorParams
20 |
21 | RequestBodyValidator:
22 | 'Fn::ImportValue': EmrRequestValidatorBody
23 |
24 | documentation: ${file(serverless/models/models.yml)}
25 |
26 | functions:
27 | emr-add-autoscaling: ${file(serverless/lambdas/add_autoscaling.yml)}
28 | emr-list-autoscaling: ${file(serverless/lambdas/list_autoscaling.yml)}
29 | emr-delete-autoscaling: ${file(serverless/lambdas/delete_autoscaling.yml)}
30 |
31 | plugins:
32 | - serverless-deployment-bucket
33 | - serverless-pseudo-parameters
34 | - serverless-add-api-key
35 | - serverless-aws-documentation
36 | - serverless-reqvalidator-plugin
37 | - serverless-jetpack
38 | - serverless-plugin-parent
--------------------------------------------------------------------------------
/Backend/emr-autoscaling/serverless/cfn/resource.yml:
--------------------------------------------------------------------------------
1 | Resources:
2 | ApiGatewayStage:
3 | Type: AWS::ApiGateway::Stage
4 | Properties:
5 | MethodSettings:
6 | - DataTraceEnabled: true
7 | HttpMethod: "*"
8 | LoggingLevel: INFO
9 | ResourcePath: "/*"
10 | MetricsEnabled: true
11 | RestApiId: ${self:provider.apiGateway.restApiId}
12 | EmrRequestValidatorParams:
13 | Type: "AWS::ApiGateway::RequestValidator"
14 | Properties:
15 | Name: 'emr-req-validator-params'
16 | RestApiId: ${self:provider.apiGateway.restApiId}
17 | ValidateRequestBody: false
18 | ValidateRequestParameters: true
19 | EmrRequestValidatorBody:
20 | Type: "AWS::ApiGateway::RequestValidator"
21 | Properties:
22 | Name: 'emr-req-validator-body'
23 | RestApiId: ${self:provider.apiGateway.restApiId}
24 | ValidateRequestBody: true
25 | ValidateRequestParameters: true
26 |
--------------------------------------------------------------------------------
/Backend/emr-autoscaling/serverless/models/EMRAutoScalingRequest.json:
--------------------------------------------------------------------------------
1 | {
2 | "required": [
3 | "clusterId"
4 | ],
5 | "properties": {
6 | "clusterId": {
7 | "type": "string"
8 | }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/Backend/emr-autoscaling/serverless/models/EMRAutoScalingResponse.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "object",
3 | "properties": {
4 | "status": {
5 | "type": "string"
6 | }
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/Backend/emr-autoscaling/serverless/models/models.yml:
--------------------------------------------------------------------------------
1 | api:
2 | info:
3 | version: '1.0.0'
4 | title: EMR cluster Ops APIs
5 | description: APIs to perform EMR autoscaling operations
6 | models:
7 | - name: EMRAutoScalingRequest
8 | contentType: "application/json"
9 | schema: ${file(serverless/models/EMRAutoScalingRequest.json)}
10 | - name: EMRAutoScalingResponse
11 | contentType: "application/json"
12 | schema: ${file(serverless/models/EMRAutoScalingResponse.json)}
--------------------------------------------------------------------------------
/Backend/emr-autoscaling/src/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/intuit/QuickFabric/a7200cfdde42a033fbed04384028833b8b100a6f/Backend/emr-autoscaling/src/__init__.py
--------------------------------------------------------------------------------
/Backend/emr-autoscaling/src/scripts/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/intuit/QuickFabric/a7200cfdde42a033fbed04384028833b8b100a6f/Backend/emr-autoscaling/src/scripts/__init__.py
--------------------------------------------------------------------------------
/Backend/emr-autoscaling/src/util/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/intuit/QuickFabric/a7200cfdde42a033fbed04384028833b8b100a6f/Backend/emr-autoscaling/src/util/__init__.py
--------------------------------------------------------------------------------
/Backend/emr-autoscaling/src/util/commlib.py:
--------------------------------------------------------------------------------
1 |
2 | def construct_error_response(context, api_request_id):
3 | """
4 | Construct error response dict
5 | :param context: AWS Context object, containing properties about the invocation, function, and execution environment.
6 | :param api_request_id:
7 | :return: dict, a dict object containing information about the aws loggroup name, stream name and lambda request id
8 | :rtype:
9 | """
10 |
11 | error_response = {
12 | "statusCode": 500,
13 | "lambda_function_name": context.function_name,
14 | "log_group_name": context.log_group_name,
15 | "log_stream_name": context.log_stream_name,
16 | "api_request_id": api_request_id,
17 | "lambda_request_id": context.aws_request_id
18 | }
19 |
20 | return error_response
21 |
--------------------------------------------------------------------------------
/Backend/emr-autoscaling/src/util/log.py:
--------------------------------------------------------------------------------
1 | """
2 | Base script for logging Lambda functions
3 | """
4 |
5 | import logging
6 | import sys
7 |
8 |
9 | def setup_logging(api_request_id, lambda_request_id):
10 | logger = logging.getLogger()
11 | for handler in logger.handlers:
12 | logger.removeHandler(handler)
13 |
14 | handler = logging.StreamHandler(sys.stdout)
15 |
16 | log_format = f"[%(asctime)s] [api_request_id={api_request_id} lambda_request_id={lambda_request_id}] %(levelname)s: %(message)s"
17 | handler.setFormatter(logging.Formatter(log_format, "%Y-%m-%d %H:%M:%S"))
18 | logger.addHandler(handler)
19 | logger.setLevel(logging.INFO)
20 |
21 | return logger
22 |
--------------------------------------------------------------------------------
/Backend/emr-autoscaling/tests/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/intuit/QuickFabric/a7200cfdde42a033fbed04384028833b8b100a6f/Backend/emr-autoscaling/tests/__init__.py
--------------------------------------------------------------------------------
/Backend/emr-autoscaling/tests/pytest.ini:
--------------------------------------------------------------------------------
1 | [pytest]
2 | addopts = -p no:warnings
3 | norecursedirs = build docs/_build *.egg .tox *.venv *__init__* *site-packages*
4 |
--------------------------------------------------------------------------------
/Backend/emr-autoscaling/tests/test_emr_asg_add.py:
--------------------------------------------------------------------------------
1 | from src.scripts.emr_add_autoscaling import lambda_handler as asg_add
2 | from pprint import pprint
3 |
4 |
5 | def test_emr_asg_add(create_cluster, lambda_context):
6 | cluster_id = create_cluster.get('JobFlowId')
7 | assert 'j-' in cluster_id
8 |
9 | asg_add_request = {
10 | "api_request_id": "test_asg_add",
11 | "cluster_id": cluster_id,
12 | "autoscaling_profile": "Default",
13 | "instance_group": "CORE",
14 | "min": "1",
15 | "max": "3"
16 | }
17 | try:
18 | response = asg_add(asg_add_request, lambda_context)
19 | except Exception as error:
20 | assert 'NotImplementedError' not in error.args
21 | pass
22 |
--------------------------------------------------------------------------------
/Backend/emr-cluster-ops/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/intuit/QuickFabric/a7200cfdde42a033fbed04384028833b8b100a6f/Backend/emr-cluster-ops/__init__.py
--------------------------------------------------------------------------------
/Backend/emr-cluster-ops/ba_step_scripts/install-nodejs.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | is_aml=`uname -r | grep amzn1.x86_64 | wc -l`
4 |
5 | if [ ${is_aml} == 1 ]; then
6 | # install node through yum
7 | sudo yum -y install nodejs npm --enablerepo=epel
8 |
9 | # install nvm and update to Node v 0.12
10 | curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.29.0/install.sh | bash
11 | . ~/.nvm/nvm.sh
12 | nvm install 0.12
13 | nvm alias default 0.12
14 | else
15 | echo "Unsupported OS"
16 | fi
--------------------------------------------------------------------------------
/Backend/emr-cluster-ops/serverless/models/mapping_templates/EMRClusterAddCustomStepRequest:
--------------------------------------------------------------------------------
1 | #set($inputRoot = $input.path('$'))
2 | {
3 | "api_request_id": "$context.requestId",
4 | "cluster_name": "$inputRoot.clusterName",
5 | "cluster_id": "$inputRoot.clusterId",
6 | "steps": [
7 | #foreach($elem in $inputRoot.steps)
8 | {
9 | "Name": "$elem.name",
10 | "ActionOnFailure": "$elem.actionOnFailure",
11 | "HadoopJarStep": {
12 | "MainClass": "$elem.hadoopJarStep.mainClass",
13 | "Jar": "$elem.hadoopJarStep.jar",
14 | "Args": $elem.hadoopJarStep.stepArgs
15 | }
16 | }#if($foreach.hasNext), #end
17 | #end
18 | ]
19 | }
--------------------------------------------------------------------------------
/Backend/emr-cluster-ops/serverless/models/mapping_templates/EMRClusterAddCustomStepResponse:
--------------------------------------------------------------------------------
1 | #set($inputRoot = $input.path('$'))
2 | {
3 | "statusCode": 201,
4 | "clusterName": "$input.path('$.cluster_name')",
5 | "clusterId": "$input.path('$.cluster_id')",
6 | "steps": [
7 | #foreach($elem in $inputRoot.steps)
8 | {
9 | "name": "$elem.step_name",
10 | "stepId": "$elem.step_id"
11 | }#if($foreach.hasNext), #end
12 | #end
13 | ],
14 | "apiRequestId": "$input.path('$.api_request_id')",
15 | "lambdaRequestId": "$input.path('$.lambda_request_id')"
16 | }
17 |
--------------------------------------------------------------------------------
/Backend/emr-cluster-ops/serverless/models/mapping_templates/EMRStepValidateRequest:
--------------------------------------------------------------------------------
1 | #set($inputRoot = $input.path('$'))
2 | {
3 | "api_request_id": "$context.requestId",
4 | "cluster_name": "$input.path('clusterName')",
5 | "cluster_id": "$input.path('$.clusterId')",
6 | "step_ids": [
7 | #foreach($elem in $inputRoot.stepIds)
8 | "$elem"#if($foreach.hasNext), #end
9 | #end
10 | ]
11 | }
12 |
--------------------------------------------------------------------------------
/Backend/emr-cluster-ops/serverless/models/mapping_templates/EMRStepValidateResponse:
--------------------------------------------------------------------------------
1 | #set($inputRoot = $input.path('$'))
2 | {
3 | "statusCode": 201,
4 | "clusterName": "$input.path('$.cluster_name')",
5 | "clusterId": "$input.path('$.cluster_id')",
6 | "steps": [
7 | #foreach($elem in $inputRoot.steps)
8 | {
9 | "name": "$elem.step_name",
10 | "stepId": "$elem.step_id",
11 | "status": "$elem.status"
12 | }#if($foreach.hasNext), #end
13 | #end
14 | ],
15 | "apiRequestId": "$input.path('$.api_request_id')",
16 | "lambdaRequestId": "$input.path('$.lambda_request_id')"
17 | }
18 |
--------------------------------------------------------------------------------
/Backend/emr-cluster-ops/serverless/models/schemas/500ErrorResponse.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "object",
3 | "properties": {
4 | "errorType": {
5 | "type": "string"
6 | },
7 | "statusCode": {
8 | "type": "number"
9 | },
10 | "errorMessage": {
11 | "type": "string"
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/Backend/emr-cluster-ops/serverless/models/schemas/CreateEMRClusterRequest.json:
--------------------------------------------------------------------------------
1 | {
2 | "required": [
3 | "subType",
4 | "segment",
5 | "account"
6 | ],
7 | "properties": {
8 | "segment": {
9 | "type": "string"
10 | },
11 | "subType": {
12 | "type": "string"
13 | },
14 | "account": {
15 | "type": "string"
16 | }
17 | }
18 | }
--------------------------------------------------------------------------------
/Backend/emr-cluster-ops/serverless/models/schemas/CreateEMRClusterResponse.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "object",
3 | "properties": {
4 | "clusterName": {
5 | "type": "string"
6 | },
7 | "subType": {
8 | "type": "string"
9 | },
10 | "role": {
11 | "type": "string"
12 | },
13 | "account": {
14 | "type": "string"
15 | },
16 | "status": {
17 | "type": "string"
18 | },
19 | "message": {
20 | "type": "string"
21 | },
22 | "statusCode": {
23 | "type": "number"
24 | },
25 | "dnsName": {
26 | "type": "string"
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Backend/emr-cluster-ops/serverless/models/schemas/EMRClusterAddCustomStepRequest.json:
--------------------------------------------------------------------------------
1 | {
2 | "required": [
3 | "clusterName",
4 | "clusterId",
5 | "steps"
6 | ],
7 | "properties": {
8 | "clusterName": {
9 | "type": "string"
10 | },
11 | "clusterId": {
12 | "type": "string"
13 | },
14 | "steps": {
15 | "type": "array",
16 | "items": {
17 | "type": "object",
18 | "properties": {
19 | "name": {
20 | "type": "string"
21 | },
22 | "actionOnFailure": {
23 | "type": "string"
24 | },
25 | "hadoopJarStep": {
26 | "type": "object",
27 | "properties": {
28 | "mainClass": {
29 | "type": "string"
30 | },
31 | "jar": {
32 | "type": "string"
33 | },
34 | "stepArgs": {
35 | "type": "array",
36 | "items": {
37 | "type": "string"
38 | }
39 | }
40 | }
41 | }
42 | }
43 | }
44 | }
45 | }
46 | }
--------------------------------------------------------------------------------
/Backend/emr-cluster-ops/serverless/models/schemas/EMRClusterAddCustomStepResponse.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "object",
3 | "properties": {
4 | "clusterName": {
5 | "type": "string"
6 | },
7 | "steps": {
8 | "type": "array",
9 | "items": {
10 | "type": "object",
11 | "properties": {
12 | "name": {
13 | "type": "string"
14 | },
15 | "stepId": {
16 | "type": "string"
17 | }
18 | }
19 | }
20 | },
21 | "clusterId": {
22 | "type": "string"
23 | },
24 | "statusCode": {
25 | "type": "number"
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/Backend/emr-cluster-ops/serverless/models/schemas/EMRClusterAddStepRequest.json:
--------------------------------------------------------------------------------
1 | {
2 | "required": [
3 | "clusterName",
4 | "clusterId",
5 | "account",
6 | "step",
7 | "subType"
8 | ],
9 | "properties": {
10 | "clusterName": {
11 | "type": "string"
12 | },
13 | "clusterId": {
14 | "type": "string"
15 | },
16 | "account": {
17 | "type": "string"
18 | },
19 | "step": {
20 | "type": "string"
21 | },
22 | "subType": {
23 | "type": "string"
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Backend/emr-cluster-ops/serverless/models/schemas/EMRClusterAddStepResponse.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "object",
3 | "properties": {
4 | "clusterName": {
5 | "type": "string"
6 | },
7 | "subType": {
8 | "type": "string"
9 | },
10 | "status": {
11 | "type": "string"
12 | },
13 | "account": {
14 | "type": "string"
15 | },
16 | "clusterId": {
17 | "type": "string"
18 | },
19 | "statusCode": {
20 | "type": "number"
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Backend/emr-cluster-ops/serverless/models/schemas/EMRDNSOperation.json:
--------------------------------------------------------------------------------
1 | {
2 | "required": [
3 | "account",
4 | "dnsName",
5 | "clusterName",
6 | "action",
7 | "masterIp"
8 | ],
9 | "properties": {
10 | "account": {
11 | "type": "string"
12 | },
13 | "clusterName": {
14 | "type": "string"
15 | },
16 | "action": {
17 | "type": "string"
18 | },
19 | "dnsName": {
20 | "type": "string"
21 | },
22 | "masterIp": {
23 | "type": "string"
24 | }
25 | }
26 | }
--------------------------------------------------------------------------------
/Backend/emr-cluster-ops/serverless/models/schemas/EMRRMProxyRequest.json:
--------------------------------------------------------------------------------
1 | {
2 | "required": [
3 | "rmUrl",
4 | "metricType"
5 | ],
6 | "properties": {
7 | "rmUrl": {
8 | "type": "string"
9 | },
10 | "metricType": {
11 | "type": "string"
12 | }
13 | }
14 | }
--------------------------------------------------------------------------------
/Backend/emr-cluster-ops/serverless/models/schemas/EMRRMProxyResponse.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "object",
3 | "properties": {
4 | "metricType": {
5 | "type": "string"
6 | },
7 | "metricStats": {
8 | "type": "string"
9 | },
10 | "statusCode": {
11 | "type": "number"
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/Backend/emr-cluster-ops/serverless/models/schemas/EMRStepValidateRequest.json:
--------------------------------------------------------------------------------
1 | {
2 | "required": [
3 | "clusterName",
4 | "clusterId",
5 | "stepIds"
6 | ],
7 | "properties": {
8 | "clusterName": {
9 | "type": "string"
10 | },
11 | "clusterId": {
12 | "type": "string"
13 | },
14 | "stepIds": {
15 | "type": "array",
16 | "items": {
17 | "type": "string"
18 | }
19 | }
20 | }
21 | }
--------------------------------------------------------------------------------
/Backend/emr-cluster-ops/serverless/models/schemas/EMRStepValidateResponse.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "object",
3 | "properties": {
4 | "clusterName": {
5 | "type": "string"
6 | },
7 | "steps": {
8 | "type": "array",
9 | "items": {
10 | "type": "object",
11 | "properties": {
12 | "name": {
13 | "type": "string"
14 | },
15 | "stepId": {
16 | "type": "string"
17 | },
18 | "status": {
19 | "type": "string"
20 | }
21 | }
22 | }
23 | },
24 | "clusterId": {
25 | "type": "string"
26 | },
27 | "statusCode": {
28 | "type": "number"
29 | }
30 | }
31 | }
--------------------------------------------------------------------------------
/Backend/emr-cluster-ops/serverless/models/schemas/ProtectEMRClusterRequest.json:
--------------------------------------------------------------------------------
1 | {
2 | "required": [
3 | "clusterName",
4 | "clusterId",
5 | "terminationProtected"
6 | ],
7 | "properties": {
8 | "clusterName": {
9 | "type": "string"
10 | },
11 | "clusterId": {
12 | "type": "string"
13 | },
14 | "terminationProtected": {
15 | "type": "string"
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/Backend/emr-cluster-ops/serverless/models/schemas/ProtectEMRClusterResponse.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "object",
3 | "properties": {
4 | "clusterName": {
5 | "type": "string"
6 | },
7 | "clusterId": {
8 | "type": "string"
9 | },
10 | "status": {
11 | "type": "string"
12 | },
13 | "terminationProtected": {
14 | "type": "string"
15 | },
16 | "message": {
17 | "type": "string"
18 | },
19 | "statusCode": {
20 | "type": "number"
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Backend/emr-cluster-ops/serverless/models/schemas/TerminateEMRClusterRequest.json:
--------------------------------------------------------------------------------
1 | {
2 | "required": [
3 | "clusterName",
4 | "clusterId"
5 | ],
6 | "properties": {
7 | "clusterName": {
8 | "type": "string"
9 | },
10 | "clusterId": {
11 | "type": "string"
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/Backend/emr-cluster-ops/serverless/models/schemas/TerminateEMRClusterResponse.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "object",
3 | "properties": {
4 | "clusterName": {
5 | "type": "string"
6 | },
7 | "clusterId": {
8 | "type": "string"
9 | },
10 | "status": {
11 | "type": "string"
12 | },
13 | "message": {
14 | "type": "string"
15 | },
16 | "statusCode": {
17 | "type": "number"
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Backend/emr-cluster-ops/serverless/models/schemas/ValidateEMRClusterRequest.json:
--------------------------------------------------------------------------------
1 | {
2 | "required": [
3 | "clusterId"
4 | ],
5 | "properties": {
6 | "clusterId": {
7 | "type": "string"
8 | }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/Backend/emr-cluster-ops/serverless/models/schemas/ValidateEMRClusterResponse.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "object",
3 | "properties": {
4 | "clusterName": {
5 | "type": "string"
6 | },
7 | "status": {
8 | "type": "string"
9 | },
10 | "clusterId": {
11 | "type": "string"
12 | },
13 | "rmUrl": {
14 | "type": "string"
15 | },
16 | "masterIp": {
17 | "type": "string"
18 | }
19 | }
20 | }
--------------------------------------------------------------------------------
/Backend/emr-cluster-ops/src/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/intuit/QuickFabric/a7200cfdde42a033fbed04384028833b8b100a6f/Backend/emr-cluster-ops/src/__init__.py
--------------------------------------------------------------------------------
/Backend/emr-cluster-ops/src/conf/common/common-tags.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "Key": "intuit:billing:component",
4 | "Value": "__role__"
5 | },
6 | {
7 | "Key": "intuit:billing:user-app",
8 | "Value": "__name__"
9 | },
10 | {
11 | "Key": "intuit:billing:appenv",
12 | "Value": "prd"
13 | },
14 | {
15 | "Key": "bu",
16 | "Value": "sbseg"
17 | },
18 | {
19 | "Key": "env",
20 | "Value": "prod"
21 | },
22 | {
23 | "Key": "app",
24 | "Value": "__name__"
25 | },
26 | {
27 | "Key": "Name",
28 | "Value": "__name__-EMR"
29 | },
30 | {
31 | "Key": "type",
32 | "Value": "__type__"
33 | },
34 | {
35 | "Key": "ami:restack:date",
36 | "Value": "__restack__"
37 | }
38 | ]
--------------------------------------------------------------------------------
/Backend/emr-cluster-ops/src/scripts/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/intuit/QuickFabric/a7200cfdde42a033fbed04384028833b8b100a6f/Backend/emr-cluster-ops/src/scripts/__init__.py
--------------------------------------------------------------------------------
/Backend/emr-cluster-ops/src/scripts/emr_create.py:
--------------------------------------------------------------------------------
1 | """
2 | Lambda function to launch EMR cluster using Boto3 SDK
3 | """
4 |
5 | from src.scripts.emr_create_nonkerb import lambda_handler as emr_nonkerb
6 | from src.util.commlib import construct_error_response
7 | from src.util import exceptions
8 |
9 |
10 | def lambda_handler(event, context):
11 | cluster_type = event.get('sub_type', 'unknown').lower()
12 | if cluster_type in {"nonkerb"}:
13 | return emr_nonkerb(event, context)
14 | else:
15 | # Throw an exception for unsupported cluster type passed
16 | api_request_id = event.get('api_request_id')
17 | error_response = construct_error_response(context, api_request_id)
18 | raise exceptions.EMRClusterCreationException(error_response)
--------------------------------------------------------------------------------
/Backend/emr-cluster-ops/src/util/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/intuit/QuickFabric/a7200cfdde42a033fbed04384028833b8b100a6f/Backend/emr-cluster-ops/src/util/__init__.py
--------------------------------------------------------------------------------
/Backend/emr-cluster-ops/tests/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/intuit/QuickFabric/a7200cfdde42a033fbed04384028833b8b100a6f/Backend/emr-cluster-ops/tests/__init__.py
--------------------------------------------------------------------------------
/Backend/emr-cluster-ops/tests/pytest.ini:
--------------------------------------------------------------------------------
1 | [pytest]
2 | addopts = -p no:warnings
3 | norecursedirs = build docs/_build *.eggs .tox *.venv *__init__*
4 | testpaths = ./tests
5 |
6 |
--------------------------------------------------------------------------------
/Backend/emr-cluster-ops/tests/test_add_step.py:
--------------------------------------------------------------------------------
1 | from pprint import pprint
2 | from src.scripts.emr_add_steps import lambda_handler as emr_add_step
3 |
4 |
5 | def test_emr_cluster_add_step(create_cluster, lambda_context):
6 | cluster_id = create_cluster.get('cluster_id')
7 | cluster_name = create_cluster.get('cluster_name')
8 | cluster_type = create_cluster.get('cluster_type')
9 |
10 | assert 'j-' in cluster_id
11 |
12 | print(f"Cluster id {create_cluster.get('cluster_id')}")
13 |
14 | emr_add_step_request = {
15 | "cluster_name": cluster_name,
16 | "account": create_cluster.get('account'),
17 | "step": "Setup Syslog",
18 | "cluster_id": cluster_id,
19 | "cluster_type": cluster_type}
20 |
21 | response = emr_add_step(emr_add_step_request, lambda_context)
22 |
23 | assert 'step_id' in response
24 | print(f"step id {response.get('step_id')}")
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Backend/emr-cluster-ops/tests/test_emr_creation.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from pprint import pprint
3 |
4 |
5 | def test_emr_create_cluster(create_cluster):
6 | print("\n")
7 | pprint(create_cluster, indent=4, compact=True)
8 | assert 'j-' in create_cluster.get('cluster_id')
9 |
--------------------------------------------------------------------------------
/Backend/emr-cluster-ops/tests/test_emr_precheck.py:
--------------------------------------------------------------------------------
1 | from src.scripts.emr_precheck import lambda_handler as emr_precheck
2 | from pprint import pprint
3 |
4 |
5 | def test_emr_prechcek_cluster_notpresent(lambda_context):
6 | cluster_precheck_request = {
7 | "api_request_id": "test_emr_precheck",
8 | "cluster_name": "nonkerb-testing-tes"
9 | }
10 | response = emr_precheck(cluster_precheck_request, lambda_context)
11 | assert 'status' in response
12 | print('Cluster status ::', response.get('status'))
13 |
14 |
15 | def test_emr_prechcek_cluster_present(create_cluster, lambda_context):
16 | assert 'j-' in create_cluster.get('cluster_id')
17 | print('Cluster id', create_cluster.get('cluster_id'))
18 |
19 | cluster_name = create_cluster.get('cluster_name')
20 |
21 | cluster_precheck_request = {
22 | "api_request_id": "test_emr_precheck",
23 | "cluster_name": cluster_name
24 | }
25 |
26 | response = emr_precheck(cluster_precheck_request,lambda_context )
27 | assert 'status' in response
28 | print('Cluster status ::', response.get('status'))
29 |
--------------------------------------------------------------------------------
/Backend/emr-cluster-ops/tests/test_emr_protect.py:
--------------------------------------------------------------------------------
1 | from src.scripts.emr_protect import lambda_handler as emr_protect
2 |
3 |
4 | def test_emr_cluster_protect(create_cluster, lambda_context):
5 | cluster_id = create_cluster.get('cluster_id')
6 | cluster_name = create_cluster.get('cluster_name')
7 | cluster_type = create_cluster.get('cluster_type')
8 |
9 | assert 'j-' in cluster_id
10 | print(f"Cluster ID :: {cluster_id}")
11 |
12 | emr_protect_request = {
13 | "api_request_id": "test_terminate_cluster",
14 | "cluster_name": cluster_name,
15 | "cluster_type": cluster_type,
16 | "cluster_id": cluster_id,
17 | "termination_protected": "status"
18 | }
19 |
20 | response = emr_protect(emr_protect_request, lambda_context)
21 | assert response.get('terminationProtected') in ['enabled', 'disabled']
22 |
23 | print(f"Cluster termination protection status :: {response.get('terminationProtected')}")
24 |
--------------------------------------------------------------------------------
/Backend/emr-cluster-ops/tests/test_emr_status.py:
--------------------------------------------------------------------------------
1 | from src.scripts.emr_status import lambda_handler as emr_status
2 | from pprint import pprint
3 |
4 |
5 | def test_emr_cluster_status_check(create_cluster, lambda_context):
6 | print("\n")
7 | pprint(create_cluster, indent=4, compact=True)
8 | assert 'j-' in create_cluster.get('cluster_id')
9 |
10 | cluster_id = create_cluster.get('cluster_id')
11 |
12 | cluster_status_request = {
13 | "api_request_id": "test_emr_status_check",
14 | "cluster_id": cluster_id
15 | }
16 |
17 | response = emr_status(cluster_status_request,lambda_context )
18 | assert 'status' in response
19 | print("\n")
20 | pprint(response)
--------------------------------------------------------------------------------
/Backend/emr-cluster-ops/tests/test_emr_terminate.py:
--------------------------------------------------------------------------------
1 | from src.scripts.emr_terminate import lambda_handler as emr_terminate
2 |
3 |
4 | def test_terminate_emr_cluster(create_cluster, lambda_context):
5 | cluster_id = create_cluster.get('cluster_id')
6 | cluster_name = create_cluster.get('cluster_name')
7 | cluster_type = create_cluster.get('cluster_type')
8 |
9 | assert 'j-' in cluster_id
10 | print(f"Cluster ID :: {cluster_id}")
11 |
12 | emr_terminate_request = {
13 | "api_request_id": "test_terminate_cluster",
14 | "cluster_name": cluster_name,
15 | "cluster_type": cluster_type,
16 | "cluster_id": cluster_id,
17 | "force": True
18 | }
19 |
20 | response = emr_terminate(emr_terminate_request, lambda_context)
21 |
22 | assert 'TERMINATION' in response.get('status')
23 |
24 | print(f"Cluster termination status :: {response.get('status')}")
25 |
--------------------------------------------------------------------------------
/Backend/emr-cluster-ops/tests/test_emr_validate.py:
--------------------------------------------------------------------------------
1 | from src.scripts.emr_validate import lambda_handler as emr_validate
2 | from pprint import pprint
3 |
4 |
5 | def test_emr_cluster_validate(create_cluster, lambda_context):
6 | cluster_id = create_cluster.get('cluster_id')
7 | assert 'j-' in cluster_id
8 |
9 | cluster_validate_request = {
10 | "api_request_id": "test_emr_validation",
11 | "cluster_name": create_cluster.get('cluster_name'),
12 | "cluster_type": create_cluster.get('cluster_type')
13 | }
14 |
15 | try:
16 | response = emr_validate(cluster_validate_request, lambda_context)
17 | except Exception as error:
18 | assert 'NotImplementedError' not in error.args
19 | pass
20 |
--------------------------------------------------------------------------------
/Backend/emr-testsuites/README.md:
--------------------------------------------------------------------------------
1 | # emr-autoscaling
2 |
--------------------------------------------------------------------------------
/Backend/emr-testsuites/serverless/cfn/resource.yml:
--------------------------------------------------------------------------------
1 | Resources:
2 | ApiGatewayStage:
3 | Type: AWS::ApiGateway::Stage
4 | Properties:
5 | MethodSettings:
6 | - DataTraceEnabled: true
7 | HttpMethod: "*"
8 | LoggingLevel: INFO
9 | ResourcePath: "/*"
10 | MetricsEnabled: true
11 | RestApiId: ${self:provider.apiGateway.restApiId}
12 | EmrRequestValidatorParams:
13 | Type: "AWS::ApiGateway::RequestValidator"
14 | Properties:
15 | Name: 'emr-req-validator-params'
16 | RestApiId: ${self:provider.apiGateway.restApiId}
17 | ValidateRequestBody: false
18 | ValidateRequestParameters: true
19 | EmrRequestValidatorBody:
20 | Type: "AWS::ApiGateway::RequestValidator"
21 | Properties:
22 | Name: 'emr-req-validator-body'
23 | RestApiId: ${self:provider.apiGateway.restApiId}
24 | ValidateRequestBody: true
25 | ValidateRequestParameters: true
26 |
--------------------------------------------------------------------------------
/Backend/emr-testsuites/serverless/models/EMRClusterTestAppRequest.json:
--------------------------------------------------------------------------------
1 | {
2 | "required": [
3 | "clusterName",
4 | "clusterId",
5 | "app"
6 | ],
7 | "properties": {
8 | "clusterName": {
9 | "type": "string"
10 | },
11 | "clusterId": {
12 | "type": "string"
13 | },
14 | "app": {
15 | "type": "string"
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/Backend/emr-testsuites/serverless/models/EMRClusterTestAppResponse.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "object",
3 | "properties": {
4 | "clusterName": {
5 | "type": "string"
6 | },
7 | "app": {
8 | "type": "string"
9 | },
10 | "status": {
11 | "type": "string"
12 | },
13 | "stepId": {
14 | "type": "string"
15 | },
16 | "clusterId": {
17 | "type": "string"
18 | },
19 | "statusCode": {
20 | "type": "number"
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Backend/emr-testsuites/serverless/models/EMRTestSuiteRequest.json:
--------------------------------------------------------------------------------
1 | {
2 | "required": [
3 | "clusterId"
4 | ],
5 | "properties": {
6 | "clusterId": {
7 | "type": "string"
8 | }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/Backend/emr-testsuites/serverless/models/EMRTestSuiteResponse.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "object",
3 | "properties": {
4 | "status": {
5 | "type": "string"
6 | }
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/Backend/emr-testsuites/serverless/models/models.yml:
--------------------------------------------------------------------------------
1 | api:
2 | info:
3 | version: '1.0.0'
4 | title: EMR cluster Ops APIs
5 | description: APIs to perform EMR Test Suite operations
6 | models:
7 | - name: EMRTestSuiteRequest
8 | contentType: "application/json"
9 | schema: ${file(serverless/models/EMRTestSuiteRequest.json)}
10 | - name: EMRTestSuiteResponse
11 | contentType: "application/json"
12 | schema: ${file(serverless/models/EMRTestSuiteResponse.json)}
13 | - name: EMRClusterTestAppRequest
14 | contentType: "application/json"
15 | schema: ${file(serverless/models/EMRClusterTestAppRequest.json)}
16 | - name: EMRClusterTestAppResponse
17 | contentType: "application/json"
18 | schema: ${file(serverless/models/EMRClusterTestAppResponse.json)}
--------------------------------------------------------------------------------
/Backend/emr-testsuites/src/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/intuit/QuickFabric/a7200cfdde42a033fbed04384028833b8b100a6f/Backend/emr-testsuites/src/__init__.py
--------------------------------------------------------------------------------
/Backend/emr-testsuites/src/scripts/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/intuit/QuickFabric/a7200cfdde42a033fbed04384028833b8b100a6f/Backend/emr-testsuites/src/scripts/__init__.py
--------------------------------------------------------------------------------
/Backend/emr-testsuites/src/scripts/emr_test_steps.py:
--------------------------------------------------------------------------------
1 | """
2 | Lambda function to get list of steps executed on emr cluster.
3 | """
4 |
5 | from src.util import exceptions
6 | from src.util.log import setup_logging
7 | from src.util.emrlib import get_emr_steps
8 |
9 |
10 | def lambda_handler(event, context):
11 | api_request_id = event.get('api_request_id')
12 | logger = setup_logging(api_request_id, context.aws_request_id)
13 | cluster_id = event.get('cluster_id')
14 |
15 | success_response = {
16 | 'statusCode': 201,
17 | "api_request_id": api_request_id,
18 | "lambda_request_id": context.aws_request_id,
19 | 'cluster_id': cluster_id,
20 | 'steps_count': 0
21 | }
22 |
23 | error_response = {
24 | "statusCode": 500,
25 | "errorType": "NoClusterFound",
26 | "errorMessage": "Unable to fetch cluster step details."
27 | }
28 |
29 | logger.info("Getting steps by cluster_id")
30 | try:
31 | response = get_emr_steps(cluster_id)
32 | except Exception as e:
33 | logger.error(e)
34 | raise exceptions.EMRTestRunException(error_response)
35 | else:
36 | success_response.update(steps_count=len(response))
37 | success_response.update(steps=response)
38 |
39 | return success_response
40 |
--------------------------------------------------------------------------------
/Backend/emr-testsuites/src/util/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/intuit/QuickFabric/a7200cfdde42a033fbed04384028833b8b100a6f/Backend/emr-testsuites/src/util/__init__.py
--------------------------------------------------------------------------------
/Backend/emr-testsuites/src/util/log.py:
--------------------------------------------------------------------------------
1 | """
2 | Base script for logging Lambda functions
3 | """
4 |
5 | import logging
6 | import sys
7 |
8 |
9 | def setup_logging(api_request_id, lambda_request_id):
10 | logger = logging.getLogger()
11 | for handler in logger.handlers:
12 | logger.removeHandler(handler)
13 |
14 | handler = logging.StreamHandler(sys.stdout)
15 |
16 | log_format = f"[%(asctime)s] [api_request_id={api_request_id} lambda_request_id={lambda_request_id}] %(levelname)s: %(message)s"
17 | handler.setFormatter(logging.Formatter(log_format, "%Y-%m-%d %H:%M:%S"))
18 | logger.addHandler(handler)
19 | logger.setLevel(logging.INFO)
20 |
21 | return logger
22 |
--------------------------------------------------------------------------------
/Backend/emr-testsuites/tests/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/intuit/QuickFabric/a7200cfdde42a033fbed04384028833b8b100a6f/Backend/emr-testsuites/tests/__init__.py
--------------------------------------------------------------------------------
/Backend/emr-testsuites/tests/pytest.ini:
--------------------------------------------------------------------------------
1 | [pytest]
2 | addopts = -p no:warnings
3 | norecursedirs = build docs/_build *.egg .tox *.venv *__init__*
4 |
--------------------------------------------------------------------------------
/Backend/emr-testsuites/tests/test_emr_app.py:
--------------------------------------------------------------------------------
1 | from src.scripts.emr_test_app import lambda_handler as emr_app
2 |
3 |
4 | def test_emr_test_app(create_cluster, lambda_context):
5 | cluster_id = create_cluster.get('JobFlowId')
6 | assert 'j-' in cluster_id
7 |
8 | cluster_name = create_cluster.get('Name')
9 |
10 | test_app_request = {
11 | "api_request_id": "test_app_hive",
12 | "cluster_name": cluster_name,
13 | "cluster_id": cluster_id,
14 | "app": "hive"
15 | }
16 |
17 | try:
18 | response = emr_app(test_app_request, lambda_context)
19 | except Exception as error:
20 | print(error)
21 | else:
22 | assert 'step_id' in response
23 | print(f"Testing Hive app via step id {response.get('step_id')}")
--------------------------------------------------------------------------------
/Backend/emr-testsuites/tests/test_emr_asg.py:
--------------------------------------------------------------------------------
1 | from src.scripts.emr_test_autoscaling import lambda_handler as list_asg
2 | from pprint import pprint
3 |
4 |
5 | def test_emr_list_asg(create_cluster, lambda_context):
6 | cluster_id = create_cluster.get('JobFlowId')
7 | assert 'j-' in cluster_id
8 |
9 | cluster_name = create_cluster.get('Name')
10 |
11 | list_asg_request = {
12 | "api_request_id": "test_list_asg",
13 | "cluster_name": cluster_name,
14 | "cluster_id": cluster_id,
15 | "instance_group": "CORE"
16 | }
17 |
18 | try:
19 | response = list_asg(list_asg_request, lambda_context)
20 | except Exception as error:
21 | print(error)
22 | else:
23 | assert 'state' in response
24 | print("Autoscaling details", response)
--------------------------------------------------------------------------------
/Backend/emr-testsuites/tests/test_emr_ba.py:
--------------------------------------------------------------------------------
1 | from src.scripts.emr_test_bootstrap import lambda_handler as emr_bas
2 |
3 |
4 | def test_emr_bas(create_cluster, lambda_context):
5 | cluster_id = create_cluster.get('JobFlowId')
6 | assert 'j-' in cluster_id
7 |
8 | cluster_name = create_cluster.get('Name')
9 |
10 | bas_request = {
11 | "api_request_id": "test_bootstrap_actions",
12 | "cluster_id": cluster_id,
13 | "cluster_name": cluster_name
14 | }
15 | try:
16 | response = emr_bas(bas_request, lambda_context)
17 | except Exception as error:
18 | print(error)
19 | else:
20 | assert 2 == response.get('bootstrap_count')
21 | print("bootstrap count", response.get('bootstrap_count') )
22 | print("bootstraps", response.get('bootstrap_names') )
--------------------------------------------------------------------------------
/Backend/emr-testsuites/tests/test_emr_steps.py:
--------------------------------------------------------------------------------
1 | from src.scripts.emr_test_steps import lambda_handler as emr_steps
2 |
3 |
4 | def test_emr_steps(create_cluster, lambda_context):
5 | cluster_id = create_cluster.get('JobFlowId')
6 | assert 'j-' in cluster_id
7 |
8 | cluster_name = create_cluster.get('Name')
9 |
10 | steps_request = {
11 | "api_request_id": "test_bootstrap_actions",
12 | "cluster_id": cluster_id,
13 | "cluster_name": cluster_name
14 | }
15 |
16 | try:
17 | response = emr_steps(steps_request, lambda_context)
18 | except Exception as error:
19 | print(error)
20 | else:
21 | assert 2 == response.get('steps_count') and 'steps' in response
22 | print("Step count", response.get('steps_count') )
23 | print("Steps", response.get('steps'))
--------------------------------------------------------------------------------
/Backend/pytest.ini:
--------------------------------------------------------------------------------
1 | [pytest]
2 | addopts = -p no:warnings
3 | norecursedirs = build docs/_build *.eggs* *.eggs *.egg .tox *.venv *__init__* *site-packages*
4 |
5 |
--------------------------------------------------------------------------------
/Backend/serverless-deploy/README.md:
--------------------------------------------------------------------------------
1 | # emr-ci-deploy
--------------------------------------------------------------------------------
/Backend/serverless-deploy/logger.py:
--------------------------------------------------------------------------------
1 | import logging
2 | import sys
3 |
4 |
5 | def setup_logger(debug=False):
6 | """
7 | Configure logger
8 | :return: logger handler
9 | """
10 |
11 | level = logging.DEBUG if debug else logging.INFO
12 | logger = logging.getLogger("Quickfabric Deploy")
13 | logger.handlers = []
14 | logger.propagate = False
15 | handler = logging.StreamHandler(sys.stdout)
16 | formatter = logging.Formatter("%(asctime)s - %(name)s %(levelname)s [%(filename)s:%(lineno)d] %(message)s")
17 | handler.setFormatter(formatter)
18 | logger.addHandler(handler)
19 |
20 | logger.setLevel(level)
21 |
22 | return logger
23 |
--------------------------------------------------------------------------------
/Backend/serverless-deploy/plugin_metadata.json:
--------------------------------------------------------------------------------
1 | {
2 | "serverless-pseudo-parameters": "2.5.0",
3 | "serverless-add-api-key": "4.0.2",
4 | "serverless-aws-documentation": "1.1.0",
5 | "serverless-deployment-bucket": "1.1.0",
6 | "serverless-jetpack": "0.7.0",
7 | "serverless-plugin-stage-variables": "1.9.5",
8 | "serverless-reqvalidator-plugin": "1.0.3",
9 | "serverless-plugin-parent": "latest",
10 | "serverless-s3-sync": "latest",
11 | "serverless-plugin-existing-s3": "latest",
12 | "serverless-api-stage": "latest"
13 | }
--------------------------------------------------------------------------------
/Backend/setup.cfg:
--------------------------------------------------------------------------------
1 | [aliases]
2 | test=pytest
--------------------------------------------------------------------------------
/Backend/setup.py:
--------------------------------------------------------------------------------
1 | from setuptools import setup
2 |
3 | test_requirements = ['pytest','pytest-sugar',
4 | 'boto3', 'aws_lambda_context', 'coverage',
5 | 'pytest-cov', 'moto']
6 |
7 |
8 | setup(
9 | setup_requires=['pyyaml', 'pytest-runner', 'pytest'],
10 | dependency_links=[
11 | 'git+https://github.com/sandipnahak/moto.git@master#egg=moto'
12 | ],
13 | install_requires=['pytest'] + test_requirements,
14 | tests_require=['pytest'] + test_requirements
15 | )
--------------------------------------------------------------------------------
/DB/.gitignore:
--------------------------------------------------------------------------------
1 | Dump20200107.sql
2 |
--------------------------------------------------------------------------------
/DB/Dockerfile:
--------------------------------------------------------------------------------
1 | # Derived from official mysql image (our base image)
2 | FROM mysql
3 | # Add a database
4 | #ENV MYSQL_DATABASE company
5 | # Add the content of the sql-scripts/ directory to your image
6 | # All scripts in docker-entrypoint-initdb.d/ are automatically
7 | # executed during container startup
8 | COPY quickfabric_bootstrap.sql /docker-entrypoint-initdb.d/
9 | COPY patch /patch
10 | RUN chmod 755 /patch/patch.sh
11 |
--------------------------------------------------------------------------------
/DB/QuickFabric_ER_Diagram.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/intuit/QuickFabric/a7200cfdde42a033fbed04384028833b8b100a6f/DB/QuickFabric_ER_Diagram.png
--------------------------------------------------------------------------------
/DB/QuickFabric_ER_model.mwb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/intuit/QuickFabric/a7200cfdde42a033fbed04384028833b8b100a6f/DB/QuickFabric_ER_model.mwb
--------------------------------------------------------------------------------
/DB/dcl.sql:
--------------------------------------------------------------------------------
1 | CREATE USER 'qf_admin'@'%' IDENTIFIED BY 'supersecret';
2 | GRANT ALL PRIVILEGES ON * . * TO 'qf_admin'@'%';
3 | FLUSH PRIVILEGES;
--------------------------------------------------------------------------------
/DB/ddl/account_configurations.sql:
--------------------------------------------------------------------------------
1 | --
2 | -- Table structure for table `account_configurations`
3 | --
4 | CREATE TABLE IF NOT EXISTS `account_configurations` (
5 | `int` int(11) NOT NULL AUTO_INCREMENT,
6 | `config_id` int(11) NOT NULL,
7 | `account_id` varchar(128) NOT NULL,
8 | `config_value` varchar(128) NOT NULL,
9 | `is_encrypted` varchar(45) NOT NULL DEFAULT '0',
10 | PRIMARY KEY (`int`),
11 | UNIQUE KEY `composite_unique_config_id_and_account_id` (`config_id`,`account_id`),
12 | KEY `fk_configuration_id_idx` (`config_id`),
13 | KEY `fk_account_id_idx` (`account_id`),
14 | CONSTRAINT `fk_account_id` FOREIGN KEY (`account_id`) REFERENCES `aws_account_profile` (`account_id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
15 | CONSTRAINT `fk_configuration_id` FOREIGN KEY (`config_id`) REFERENCES `configuration_definitions` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
16 | );
17 |
--------------------------------------------------------------------------------
/DB/ddl/application_configurations.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE `application_configurations` (
2 | `id` int(11) NOT NULL AUTO_INCREMENT,
3 | `config_id` int(11) NOT NULL,
4 | `config_value` varchar(128) NOT NULL,
5 | `is_encrypted` tinyint(4) NOT NULL DEFAULT '0',
6 | PRIMARY KEY (`id`),
7 | UNIQUE KEY `config_id_UNIQUE` (`config_id`),
8 | KEY `fk_configuration_id_idx` (`config_id`),
9 | CONSTRAINT `fk_global_configuration_id` FOREIGN KEY (`config_id`) REFERENCES `configuration_definitions` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
10 | );
--------------------------------------------------------------------------------
/DB/ddl/aws_account_profile.sql:
--------------------------------------------------------------------------------
1 | --
2 | -- Table structure for table `aws_account_profile`
3 | --
4 |
5 | CREATE TABLE IF NOT EXISTS `aws_account_profile` (
6 | `id` int(11) NOT NULL AUTO_INCREMENT,
7 | `account_id` varchar(256) NOT NULL,
8 | `account_env` varchar(256) NOT NULL,
9 | `account_owner` varchar(256) NOT NULL,
10 | PRIMARY KEY (`id`),
11 | UNIQUE KEY `account_id_UNIQUE` (`account_id`)
12 | ) AUTO_INCREMENT=200000;
13 |
--------------------------------------------------------------------------------
/DB/ddl/cluster_metrics.sql:
--------------------------------------------------------------------------------
1 | --
2 | -- Table structure for table `cluster_metrics`
3 | --
4 |
5 | CREATE TABLE IF NOT EXISTS `cluster_metrics` (
6 | `emr_id` varchar(512) NOT NULL DEFAULT '',
7 | `rm_url` varchar(1024) DEFAULT NULL,
8 | `refresh_timestamp` datetime DEFAULT NULL,
9 | `metrics_json` text,
10 | `emr_status` varchar(100) DEFAULT NULL,
11 | `cost` float DEFAULT '100',
12 | `available_memory_perc` float DEFAULT NULL,
13 | `available_cores_perc` float DEFAULT NULL,
14 | `emr_name` varchar(255) DEFAULT NULL,
15 | `total_nodes` int(11) DEFAULT NULL,
16 | `containers_pending` int(11) DEFAULT NULL,
17 | `apps_pending` int(11) DEFAULT NULL,
18 | `apps_running` int(11) DEFAULT NULL,
19 | `apps_succeeded` int(11) DEFAULT NULL,
20 | `apps_failed` int(11) DEFAULT NULL,
21 | `created_by` varchar(45) DEFAULT NULL,
22 | `account` varchar(45) DEFAULT NULL,
23 | `type` varchar(100) DEFAULT NULL,
24 | `cluster_create_timestamp` datetime DEFAULT NULL,
25 | `segment` varchar(100) DEFAULT NULL
26 | );
27 |
--------------------------------------------------------------------------------
/DB/ddl/cluster_metrics_history.sql:
--------------------------------------------------------------------------------
1 | --
2 | -- Table structure for table `cluster_metrics_history`
3 | --
4 |
5 | CREATE TABLE IF NOT EXISTS `cluster_metrics_history` (
6 | `emr_id` varchar(512) NOT NULL DEFAULT '',
7 | `rm_url` varchar(1024) DEFAULT NULL,
8 | `refresh_timestamp` datetime DEFAULT NULL,
9 | `metrics_json` text,
10 | `emr_status` varchar(100) DEFAULT NULL,
11 | `cost` float DEFAULT '100',
12 | `available_memory_perc` float DEFAULT NULL,
13 | `available_cores_perc` float DEFAULT NULL,
14 | `emr_name` varchar(255) DEFAULT NULL,
15 | `total_nodes` int(11) DEFAULT NULL,
16 | `containers_pending` int(11) DEFAULT NULL,
17 | `apps_pending` int(11) DEFAULT NULL,
18 | `apps_running` int(11) DEFAULT NULL,
19 | `apps_succeeded` int(11) DEFAULT NULL,
20 | `apps_failed` int(11) DEFAULT NULL,
21 | `created_by` varchar(45) DEFAULT NULL,
22 | `account` varchar(45) DEFAULT NULL,
23 | `cluster_create_timestamp` datetime DEFAULT NULL,
24 | `type` varchar(100) DEFAULT NULL,
25 | `segment` varchar(50) DEFAULT NULL
26 | );
27 |
--------------------------------------------------------------------------------
/DB/ddl/cluster_step_request.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE IF NOT EXISTS `cluster_step_request` (
2 | `cluster_name` varchar(100) DEFAULT NULL,
3 | `cluster_id` varchar(45) DEFAULT NULL,
4 | `step_id` varchar(45) DEFAULT NULL,
5 | `api_request_id` varchar(45) DEFAULT NULL,
6 | `lambda_request_id` varchar(45) DEFAULT NULL,
7 | `updated_ts` datetime DEFAULT NULL,
8 | `step_arg` varchar(3000) DEFAULT NULL,
9 | `created_ts` datetime DEFAULT NULL,
10 | `name` varchar(45) DEFAULT NULL,
11 | `action_on_failure` varchar(200) DEFAULT NULL,
12 | `main_class` varchar(45) DEFAULT NULL,
13 | `jar` varchar(100) DEFAULT NULL,
14 | `status` varchar(45) DEFAULT NULL,
15 | `created_by` varchar(55) DEFAULT NULL,
16 | `step_type` varchar(50) NOT NULL DEFAULT 'Custom'
17 | );
18 |
--------------------------------------------------------------------------------
/DB/ddl/configuration_data_types.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE IF NOT EXISTS `configuration_data_types` (
2 | `id` int(11) NOT NULL AUTO_INCREMENT,
3 | `data_type_name` varchar(45) NOT NULL,
4 | PRIMARY KEY (`id`),
5 | UNIQUE KEY `data_type_name_UNIQUE` (`data_type_name`)
6 | );
--------------------------------------------------------------------------------
/DB/ddl/configuration_definitions.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE IF NOT EXISTS `configuration_definitions` (
2 | `id` int(11) NOT NULL AUTO_INCREMENT,
3 | `config_name` varchar(128) NOT NULL,
4 | `config_description` varchar(256) NOT NULL,
5 | `config_type` int(11) NOT NULL,
6 | `data_type` int(11) NOT NULL DEFAULT '1',
7 | `encryption_required` tinyint(4) NOT NULL DEFAULT '0',
8 | `is_mandatory` tinyint(4) NOT NULL DEFAULT '0',
9 | `is_user_accessible` tinyint(4) NOT NULL DEFAULT '0',
10 | PRIMARY KEY (`id`),
11 | UNIQUE KEY `config_name_UNIQUE` (`config_name`),
12 | KEY `configuration_type_idx` (`config_type`),
13 | KEY `fk_data_type_idx` (`data_type`),
14 | CONSTRAINT `fk_configuration_type` FOREIGN KEY (`config_type`) REFERENCES `configuration_types` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
15 | CONSTRAINT `fk_configurations_definition_configuration_data_type` FOREIGN KEY (`data_type`) REFERENCES `configuration_data_types` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
16 | );
17 |
--------------------------------------------------------------------------------
/DB/ddl/configuration_types.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE IF NOT EXISTS `configuration_types` (
2 | `id` int(11) NOT NULL AUTO_INCREMENT,
3 | `config_type` varchar(45) NOT NULL,
4 | PRIMARY KEY (`id`),
5 | UNIQUE KEY `config_type_UNIQUE` (`config_type`)
6 | );
7 |
--------------------------------------------------------------------------------
/DB/ddl/db_patch.sql:
--------------------------------------------------------------------------------
1 | --
2 | -- Table structure for table `db_patch`
3 | --
4 | CREATE TABLE `db_patch` (
5 | `id` int(11) NOT NULL AUTO_INCREMENT,
6 | `patch_name` varchar(128) NOT NULL,
7 | `patch_status` varchar(45) NOT NULL,
8 | PRIMARY KEY (`id`),
9 | UNIQUE KEY `patch_name_UNIQUE` (`patch_name`)
10 | );
11 |
--------------------------------------------------------------------------------
/DB/ddl/emr_billing_component_cost.sql:
--------------------------------------------------------------------------------
1 | --
2 | -- Table structure for table `emr_billing_component_cost`
3 | --
4 | CREATE TABLE IF NOT EXISTS `emr_billing_component_cost` (
5 | `emr_name` varchar(45) NOT NULL,
6 | `emr_cost` int(11) DEFAULT NULL,
7 | PRIMARY KEY (`emr_name`)
8 | );
9 |
--------------------------------------------------------------------------------
/DB/ddl/emr_billing_component_cost_hist.sql:
--------------------------------------------------------------------------------
1 | --
2 | -- Table structure for table `emr_billing_component_cost_hist`
3 | --
4 | CREATE TABLE IF NOT EXISTS `emr_billing_component_cost_hist` (
5 | `emr_name` varchar(45) NOT NULL,
6 | `emr_cost` int(11) DEFAULT NULL,
7 | `created_date` datetime DEFAULT CURRENT_TIMESTAMP
8 | );
9 |
--------------------------------------------------------------------------------
/DB/ddl/emr_functional_testsuites.sql:
--------------------------------------------------------------------------------
1 | --
2 | -- Table structure for table `emr_functional_testsuites`
3 | --
4 | CREATE TABLE IF NOT EXISTS `emr_functional_testsuites` (
5 | `id` int(11) NOT NULL AUTO_INCREMENT,
6 | `name` varchar(767) NOT NULL,
7 | `description` varchar(256) DEFAULT NULL,
8 | `criteria` varchar(256) DEFAULT NULL,
9 | `cluster_type` varchar(256) NOT NULL,
10 | `cluster_segment` varchar(256) NOT NULL,
11 | `timeout` int(11) NOT NULL DEFAULT '60',
12 | `expires_minutes` int(11) NOT NULL DEFAULT '60',
13 | `mandatory` tinyint(1) NOT NULL DEFAULT '0',
14 | `disabled` tinyint(1) NOT NULL DEFAULT '0',
15 | PRIMARY KEY (`id`),
16 | UNIQUE KEY `TestName_ClusterSegment_ClusterType_Unique_Constraint` (`name`,`cluster_type`,`cluster_segment`)
17 | );
18 |
--------------------------------------------------------------------------------
/DB/ddl/emr_functional_testsuites_status.sql:
--------------------------------------------------------------------------------
1 | --
2 | -- Table structure for table `emr_functional_testsuites_status`
3 | --
4 | CREATE TABLE IF NOT EXISTS `emr_functional_testsuites_status` (
5 | `execution_id` int(11) NOT NULL AUTO_INCREMENT,
6 | `name` varchar(1024) NOT NULL,
7 | `status` varchar(256) NOT NULL,
8 | `cluster_id` varchar(256) NOT NULL,
9 | `cluster_name` varchar(256) NOT NULL,
10 | `cluster_type` varchar(256) NOT NULL,
11 | `cluster_segment` varchar(256) NOT NULL,
12 | `execution_start_time` datetime NOT NULL,
13 | `execution_end_time` datetime DEFAULT NULL,
14 | `executed_by` varchar(256) NOT NULL,
15 | `remark` varchar(1024) DEFAULT NULL,
16 | `expires_minutes` int(11) NOT NULL DEFAULT '60',
17 | `mandatory` tinyint(1) NOT NULL DEFAULT '0',
18 | `disabled` tinyint(1) NOT NULL DEFAULT '0',
19 | PRIMARY KEY (`execution_id`)
20 | );
21 |
--------------------------------------------------------------------------------
/DB/ddl/emr_functional_testsuites_status_history.sql:
--------------------------------------------------------------------------------
1 | --
2 | -- Table structure for table `emr_functional_testsuites_status_history`
3 | --
4 | CREATE TABLE IF NOT EXISTS `emr_functional_testsuites_status_history` (
5 | `execution_id` int(11) NOT NULL AUTO_INCREMENT,
6 | `name` varchar(1024) NOT NULL,
7 | `status` varchar(256) NOT NULL,
8 | `cluster_id` varchar(256) NOT NULL,
9 | `cluster_name` varchar(256) NOT NULL,
10 | `cluster_type` varchar(256) NOT NULL,
11 | `cluster_segment` varchar(256) NOT NULL,
12 | `execution_start_time` datetime NOT NULL,
13 | `execution_end_time` datetime DEFAULT NULL,
14 | `executed_by` varchar(256) NOT NULL,
15 | `remark` varchar(1024) DEFAULT NULL,
16 | `expires_minutes` int(11) NOT NULL DEFAULT '60',
17 | `mandatory` tinyint(1) NOT NULL DEFAULT '0',
18 | `disabled` tinyint(1) NOT NULL DEFAULT '0',
19 | PRIMARY KEY (`execution_id`)
20 | );
21 |
--------------------------------------------------------------------------------
/DB/ddl/report_subscriptions.sql:
--------------------------------------------------------------------------------
1 | --
2 | -- Table structure for table `report_subscriptions`
3 | --
4 | CREATE TABLE IF NOT EXISTS `report_subscriptions` (
5 | `report_subscription_id` int(11) NOT NULL AUTO_INCREMENT,
6 | `report_id` int(11) NOT NULL,
7 | `user_id` int(11) NOT NULL,
8 | PRIMARY KEY (`report_subscription_id`)
9 | );
10 |
--------------------------------------------------------------------------------
/DB/ddl/reports.sql:
--------------------------------------------------------------------------------
1 | --
2 | -- Table structure for table `reports`
3 | --
4 |
5 | CREATE TABLE IF NOT EXISTS `reports` (
6 | `report_id` int(11) NOT NULL AUTO_INCREMENT,
7 | `report_name` varchar(256) NOT NULL,
8 | PRIMARY KEY (`report_id`)
9 | );
10 |
--------------------------------------------------------------------------------
/DB/ddl/roles.sql:
--------------------------------------------------------------------------------
1 | --
2 | -- Table structure for table `roles`
3 | --
4 | CREATE TABLE IF NOT EXISTS `roles` (
5 | `role_id` int(11) NOT NULL AUTO_INCREMENT,
6 | `role_name` varchar(128) NOT NULL,
7 | `service_id` int(11) NOT NULL,
8 | PRIMARY KEY (`role_id`),
9 | KEY `role_service_foreign_key_idx` (`service_id`),
10 | CONSTRAINT `role_to_services_foreign_key` FOREIGN KEY (`service_id`) REFERENCES `services` (`service_id`) ON DELETE NO ACTION ON UPDATE NO ACTION
11 | ) AUTO_INCREMENT=400000;
12 |
--------------------------------------------------------------------------------
/DB/ddl/segments.sql:
--------------------------------------------------------------------------------
1 | --
2 | -- Table structure for table `segments`
3 | --
4 | CREATE TABLE IF NOT EXISTS `segments` (
5 | `segment_id` int(11) NOT NULL AUTO_INCREMENT,
6 | `segment_name` varchar(128) NOT NULL,
7 | `business_owner` varchar(128) DEFAULT NULL,
8 | `business_owner_email` varchar(128) DEFAULT NULL,
9 | PRIMARY KEY (`segment_id`)
10 | ) AUTO_INCREMENT=300000;
11 |
--------------------------------------------------------------------------------
/DB/ddl/services.sql:
--------------------------------------------------------------------------------
1 | --
2 | -- Table structure for table `services`
3 | --
4 | CREATE TABLE IF NOT EXISTS `services` (
5 | `service_id` int(11) NOT NULL AUTO_INCREMENT,
6 | `service_type` varchar(45) NOT NULL,
7 | PRIMARY KEY (`service_id`)
8 | ) AUTO_INCREMENT 500000;
9 |
--------------------------------------------------------------------------------
/DB/ddl/user.sql:
--------------------------------------------------------------------------------
1 | --
2 | -- Table structure for table `user`
3 | --
4 | CREATE TABLE IF NOT EXISTS `user` (
5 | `user_id` int(11) NOT NULL AUTO_INCREMENT,
6 | `email_id` varchar(50) NOT NULL,
7 | `first_name` varchar(20) NOT NULL,
8 | `last_name` varchar(20) NOT NULL,
9 | `creation_date` varchar(50) NOT NULL,
10 | `passcode` varchar(60) NOT NULL,
11 | `super_admin` tinyint(1) NOT NULL DEFAULT '0',
12 | PRIMARY KEY (`user_id`)
13 | );
14 |
--------------------------------------------------------------------------------
/DB/ddl/user_account_segment_mapping.sql:
--------------------------------------------------------------------------------
1 | --
2 | -- Table structure for table `user_account_segment_mapping`
3 | --
4 | CREATE TABLE IF NOT EXISTS `user_account_segment_mapping` (
5 | `user_account_segment_mapping_id` int(11) NOT NULL AUTO_INCREMENT,
6 | `user_id` int(11) NOT NULL,
7 | `aws_account_id` int(11) NOT NULL,
8 | `segment_id` int(11) NOT NULL,
9 | PRIMARY KEY (`user_account_segment_mapping_id`),
10 | UNIQUE KEY `unique_user_account_segment` (`user_id`,`aws_account_id`,`segment_id`),
11 | KEY `user_foreign_key_idx` (`user_id`),
12 | KEY `account_foreign_key_idx` (`aws_account_id`),
13 | KEY `segment_foregin_key_idx` (`segment_id`),
14 | CONSTRAINT `aws_account_foreign_key` FOREIGN KEY (`aws_account_id`) REFERENCES `aws_account_profile` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
15 | CONSTRAINT `segment_foregin_key` FOREIGN KEY (`segment_id`) REFERENCES `segments` (`segment_id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
16 | CONSTRAINT `user_foreign_key` FOREIGN KEY (`user_id`) REFERENCES `user` (`user_id`) ON DELETE NO ACTION ON UPDATE NO ACTION
17 | ) AUTO_INCREMENT=600000;
18 |
--------------------------------------------------------------------------------
/DB/ddl/user_account_segment_role_mapping.sql:
--------------------------------------------------------------------------------
1 | --
2 | -- Table structure for table `user_account_segment_role_mapping`
3 | --
4 | CREATE TABLE IF NOT EXISTS `user_account_segment_role_mapping` (
5 | `user_account_segment_role_mapping_id` int(11) NOT NULL AUTO_INCREMENT,
6 | `user_account_segment_mapping_id` int(11) NOT NULL,
7 | `role_id` int(11) NOT NULL,
8 | PRIMARY KEY (`user_account_segment_role_mapping_id`),
9 | KEY `action_mapping_key_idx` (`role_id`),
10 | KEY `account_segment_mapping_reference_key_idx` (`user_account_segment_mapping_id`),
11 | CONSTRAINT `roles_reference_key` FOREIGN KEY (`role_id`) REFERENCES `roles` (`role_id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
12 | CONSTRAINT `user_account_segment_mapping_reference_key` FOREIGN KEY (`user_account_segment_mapping_id`) REFERENCES `user_account_segment_mapping` (`user_account_segment_mapping_id`) ON DELETE NO ACTION ON UPDATE NO ACTION
13 | ) AUTO_INCREMENT 1000000;
14 |
--------------------------------------------------------------------------------
/DB/ddl/workflow.sql:
--------------------------------------------------------------------------------
1 | --
2 | -- Table structure for table `workflow`
3 | --
4 | CREATE TABLE IF NOT EXISTS `workflow` (
5 | `id` int(11) NOT NULL AUTO_INCREMENT,
6 | `workflow_name` varchar(45) NOT NULL,
7 | `workflow_step` varchar(45) NOT NULL,
8 | `lookup_table` varchar(45) NOT NULL,
9 | PRIMARY KEY (`id`)
10 | );
11 |
--------------------------------------------------------------------------------
/DB/dml/application_configurations.sql:
--------------------------------------------------------------------------------
1 | INSERT INTO `application_configurations` (`id`, `config_id`, `config_value`, `is_encrypted`) VALUES
2 | (1,39,'noreply@company.com',0),
3 | (2,34,'true',0),
4 | (3,1,'true',0),
5 | (4,4,'true',0),
6 | (5,5,'true',0),
7 | (6,6,'true',0),
8 | (7,24,'true',0),
9 | (8,27,'true',0),
10 | (9,28,'true',0),
11 | (10,29,'true',0),
12 | (11,37,'true',0),
13 | (12,26,'2',0),
14 | (14,3,'true',0),
15 | (15,13,'true',0),
16 | (16,2,'true',0),
17 | (17,7,'false',0),
18 | (18,8,'true',0),
19 | (19,9,'true',0),
20 | (20,10,'true',0),
21 | (21,12,'true',0),
22 | (22,14,'true',0),
23 | (23,15,'true',0),
24 | (24,22,'true',0),
25 | (25,30,'true',0),
26 | (26,31,'false',0),
27 | (27,32,'true',0),
28 | (28,40,'true',0),
29 | (29,52,'false',0),
30 | (30,23,'true',0),
31 | (31,33,'noreply@company.com',0),
32 | (32,51,'noreply@company.com',0);
33 |
--------------------------------------------------------------------------------
/DB/dml/aws_account_profile.sql:
--------------------------------------------------------------------------------
1 | INSERT INTO `aws_account_profile` (`id`, `account_id`, `account_env`, `account_owner`) VALUES
2 | (200000, '100000000000','Prod','Socrates'),
3 | (200001, '200000000000','Prod','Plato'),
4 | (200002, '300000000000','Dev','Aristotle');
5 |
--------------------------------------------------------------------------------
/DB/dml/cluster_metrics.sql:
--------------------------------------------------------------------------------
1 | INSERT INTO `cluster_metrics` (
2 | `emr_id`,
3 | `rm_url`,
4 | `refresh_timestamp`,
5 | `emr_status`,
6 | `available_memory_perc`,
7 | `available_cores_perc`,
8 | `emr_name`,
9 | `total_nodes`,
10 | `containers_pending`,
11 | `apps_pending`,
12 | `apps_running`,
13 | `apps_succeeded`,
14 | `apps_failed`,
15 | `created_by`,
16 | `account`,
17 | `type`,
18 | `cluster_create_timestamp`,
19 | `segment`) VALUES
20 | ('j-123ABC1IABCX1','http://ip-00-00-000-00.us-west-2.compute.internal:8088',CURRENT_TIMESTAMP(),'WAITING',1,1,'exploratory-sales',20,0,0,0,0,0,'QuickFabric User','100000000000','exploratory','2020-01-01 15:13:32','sales'),
21 | ('j-234XYZ2HXYZY2','http://ip-11-11-111-11.us-west-2.compute.internal:8088',CURRENT_TIMESTAMP(),'WAITING',0.17,0.31,'scheduled-sales',37,1000,1,5,2,1,'QuickFabric User','100000000000','scheduled','2020-01-02 20:14:20','sales'),
22 | ('j-456QWE3JQWEZ3','http://ip-22-22-222-22.us-west-2.compute.internal:8088',CURRENT_TIMESTAMP(),'WAITING',0.23,0.40,'exploratory-sales-test1',17,0,0,0,0,0,'QuickFabric User','200000000000','exploratory','2020-01-03 08:00:17','sales');
23 |
--------------------------------------------------------------------------------
/DB/dml/configuration_data_types.sql:
--------------------------------------------------------------------------------
1 | --
2 | -- Dumping data for table `configuration_data_types`
3 | --
4 | INSERT INTO `configuration_data_types` (`id`, `data_type_name`) VALUES
5 | (3,'boolean'),
6 | (4,'date'),
7 | (5,'datetime'),
8 | (6,'decimal'),
9 | (2,'int'),
10 | (7, 'long'),
11 | (1,'string');
12 |
--------------------------------------------------------------------------------
/DB/dml/configuration_types.sql:
--------------------------------------------------------------------------------
1 | INSERT INTO `configuration_types` (`id`, `config_type`) VALUES
2 | (2,'Account'),
3 | (1,'Application');
--------------------------------------------------------------------------------
/DB/dml/emr_billing_component_cost.sql:
--------------------------------------------------------------------------------
1 | INSERT INTO `emr_billing_component_cost` (`emr_name`, `emr_cost`) VALUES
2 | ('exploratory-sales',700),
3 | ('scheduled-sales',1000),
4 | ('exploratory-sales-test1',500);
5 |
--------------------------------------------------------------------------------
/DB/dml/reports.sql:
--------------------------------------------------------------------------------
1 | INSERT INTO `reports` (`report_name`) VALUES
2 | ('AMI Rotation'),
3 | ('Cluster Metrics');
4 |
--------------------------------------------------------------------------------
/DB/dml/roles.sql:
--------------------------------------------------------------------------------
1 |
2 | INSERT INTO `roles` (`role_id`, `role_name`, `service_id`) VALUES
3 | (400000,'CreateCluster',500000),
4 | (400001,'TerminateCluster',500000),
5 | (400002,'AddStep',500000),
6 | (400003,'RotateAMI',500000),
7 | (400004,'FlipDNS',500000),
8 | (400005,'CloneCluster',500000),
9 | (400006,'Admin',500000),
10 | (400007,'Read',500000),
11 | (400008,'runclusterhealthchecks',500000);
12 |
--------------------------------------------------------------------------------
/DB/dml/segments.sql:
--------------------------------------------------------------------------------
1 |
2 | INSERT INTO `segments` (`segment_id`, `segment_name`, `business_owner`, `business_owner_email`) VALUES
3 | (300000, 'sales','The Boss','theboss@company.com')
4 |
--------------------------------------------------------------------------------
/DB/dml/services.sql:
--------------------------------------------------------------------------------
1 |
2 | INSERT INTO `services` (`service_id`,`service_type`) VALUES
3 | (500000,'EMR');
4 |
--------------------------------------------------------------------------------
/DB/dml/user.sql:
--------------------------------------------------------------------------------
1 |
2 | INSERT INTO `user` (`user_id`, `email_id`, `first_name`, `last_name`, `creation_date`,`passcode`, `super_admin`) VALUES
3 | (1,'user@company.com','QuickFabric','User','2019-06-11 17:41:06','$2a$10$nGJMv4QsvfqBxW269wvgSepuzpJNX0IbZatlGjvEVXfsjkdDCCRsK',1);
4 |
--------------------------------------------------------------------------------
/DB/dml/user_account_segment_mapping.sql:
--------------------------------------------------------------------------------
1 | INSERT INTO user_account_segment_mapping(`user_account_segment_mapping_id`, `user_id`, `aws_account_id`, `segment_id`) VALUES
2 | (600000, 1, 200000, 300000), -- QuickFabric User to all acounts for sales segment
3 | (600001, 1, 200001, 300000),
4 | (600002, 1, 200002, 300000);
5 |
--------------------------------------------------------------------------------
/DB/dml/user_account_segment_role_mapping.sql:
--------------------------------------------------------------------------------
1 |
2 | INSERT INTO user_account_segment_role_mapping(`user_account_segment_role_mapping_id`, `role_id`, `user_account_segment_mapping_id`) VALUES
3 | (1000000, 9, 1000000), -- READ access for QuickFabric User for sales segment under all accounts
4 | (1000001, 9, 1000001),
5 | (1000002, 9, 1000002);
6 |
--------------------------------------------------------------------------------
/DB/dml/workflow.sql:
--------------------------------------------------------------------------------
1 | INSERT INTO `workflow` (`id`, `workflow_name`, `workflow_step`, `lookup_table`)VALUES
2 | (1,'CreateCluster','create_new_cluster','emr_cluster_metadata'),
3 | (2,'CreateCluster','cluster_bootstraps','cluster_step_request'),
4 | (3,'CreateCluster','cluster_custom_steps','cluster_step_request'),
5 | (4,'CreateCluster','health_check','emr_functional_testsuites_status'),
6 | (5,'RotateAMI-NonHA','terminate_current_cluster','emr_cluster_metadata'),
7 | (6,'RotateAMI-NonHA','create_new_cluster','emr_cluster_metadata'),
8 | (7,'RotateAMI-NonHA','cluster_bootstraps','cluster_step_request'),
9 | (8,'RotateAMI-NonHA','cluster_custom_steps','cluster_step_request'),
10 | (9,'RotateAMI-NonHA','health_check','emr_functional_testsuites_status'),
11 | (10,'RotateAMI-HA','create_new_cluster','emr_cluster_metadata'),
12 | (11,'RotateAMI-HA','cluster_bootstraps','cluster_step_request'),
13 | (12,'RotateAMI-HA','cluster_custom_steps','cluster_step_request'),
14 | (13,'RotateAMI-HA','health_check','emr_functional_testsuites_status'),
15 | (14,'RotateAMi-HA','mark_current_cluster_for_termination','emr_cluster_metadata');
--------------------------------------------------------------------------------
/DB/patch/patch.sh:
--------------------------------------------------------------------------------
1 | # connection="mysql -w -u root -p$MYSQL_ROOT_PASSWORD -D quickfabric"
2 | # $connection
15 | `;
16 |
--------------------------------------------------------------------------------
/Frontend/src/__tests__/components/admin/admin.test.jsx:
--------------------------------------------------------------------------------
1 | import { shallow } from 'enzyme';
2 | import toJson from 'enzyme-to-json';
3 | import React from 'react';
4 | import { Provider } from 'react-redux';
5 | import configureMockStore from "redux-mock-store";
6 |
7 | import { Admin } from '../../../components';
8 |
9 | const initialState = {
10 | uiListArray: {
11 | roles: [],
12 | accounts: [],
13 | response: {
14 | segments: []
15 | }
16 | }
17 | }
18 |
19 | const mockStore = configureMockStore();
20 | const store = mockStore(initialState);
21 | const component = shallow(
22 |