From a48e46522d3b67b89452e5d71858e88b238d6d9e Mon Sep 17 00:00:00 2001 From: alexiswl <8197659+alexiswl@users.noreply.github.com> Date: Mon, 25 Mar 2024 15:03:31 +1100 Subject: [PATCH 01/16] Create TES Basespace Upload manager service --- .../bs_runs_upload_manager/Readme.md | 93 ++ .../bs_runs_upload_manager/deploy/.gitignore | 8 + .../bs_runs_upload_manager/deploy/.npmignore | 6 + .../bs_runs_upload_manager/deploy/README.md | 14 + .../deploy/bin/deploy.ts | 19 + .../bs_runs_upload_manager/deploy/cdk.json | 66 ++ .../deploy/constants.ts | 3 + .../deploy/jest.config.js | 8 + .../bs_runs_upload_manager_stack.ts | 146 +++ .../deploy/lib/constructs/lambda_layer.ts | 44 + .../stacks/bs_runs_upload_manager_stack.ts | 29 + .../deploy/package.json | 27 + .../deploy/test/deploy.test.ts | 17 + .../deploy/tsconfig.json | 31 + .../bs_runs_upload_manager_step_functions.png | Bin 0 -> 53309 bytes .../launch_bs_runs_upload_tes/handler.py | 127 ++ .../handler.py | 115 ++ .../bs_runs_upload_manager/layers/poetry.lock | 1034 +++++++++++++++++ .../layers/pyproject.toml | 38 + .../bs_runs_upload_manager_tools/__init__.py | 0 .../utils/__init__.py | 0 .../utils/aws_s3_helpers.py | 53 + .../utils/aws_secrets_manager_helpers.py | 28 + .../utils/gds_helpers.py | 112 ++ .../utils/ica_config_helpers.py | 59 + .../utils/portal_helpers.py | 29 + .../utils/samplesheet_helpers.py | 43 + .../utils/tes_helpers.py | 93 ++ ...s_runs_upload_step_functions_template.json | 77 ++ 29 files changed, 2319 insertions(+) create mode 100644 lib/workload/stateless/bs_runs_upload_manager/Readme.md create mode 100644 lib/workload/stateless/bs_runs_upload_manager/deploy/.gitignore create mode 100644 lib/workload/stateless/bs_runs_upload_manager/deploy/.npmignore create mode 100644 lib/workload/stateless/bs_runs_upload_manager/deploy/README.md create mode 100644 lib/workload/stateless/bs_runs_upload_manager/deploy/bin/deploy.ts create mode 100644 lib/workload/stateless/bs_runs_upload_manager/deploy/cdk.json create mode 100644 lib/workload/stateless/bs_runs_upload_manager/deploy/constants.ts create mode 100644 lib/workload/stateless/bs_runs_upload_manager/deploy/jest.config.js create mode 100644 lib/workload/stateless/bs_runs_upload_manager/deploy/lib/constructs/bs_runs_upload_manager_stack.ts create mode 100644 lib/workload/stateless/bs_runs_upload_manager/deploy/lib/constructs/lambda_layer.ts create mode 100644 lib/workload/stateless/bs_runs_upload_manager/deploy/lib/stacks/bs_runs_upload_manager_stack.ts create mode 100644 lib/workload/stateless/bs_runs_upload_manager/deploy/package.json create mode 100644 lib/workload/stateless/bs_runs_upload_manager/deploy/test/deploy.test.ts create mode 100644 lib/workload/stateless/bs_runs_upload_manager/deploy/tsconfig.json create mode 100755 lib/workload/stateless/bs_runs_upload_manager/images/bs_runs_upload_manager_step_functions.png create mode 100644 lib/workload/stateless/bs_runs_upload_manager/lambdas/launch_bs_runs_upload_tes/handler.py create mode 100644 lib/workload/stateless/bs_runs_upload_manager/lambdas/upload_v2_samplesheet_to_gds_bssh/handler.py create mode 100644 lib/workload/stateless/bs_runs_upload_manager/layers/poetry.lock create mode 100644 lib/workload/stateless/bs_runs_upload_manager/layers/pyproject.toml create mode 100644 lib/workload/stateless/bs_runs_upload_manager/layers/src/bs_runs_upload_manager_tools/__init__.py create mode 100644 lib/workload/stateless/bs_runs_upload_manager/layers/src/bs_runs_upload_manager_tools/utils/__init__.py create mode 100644 lib/workload/stateless/bs_runs_upload_manager/layers/src/bs_runs_upload_manager_tools/utils/aws_s3_helpers.py create mode 100644 lib/workload/stateless/bs_runs_upload_manager/layers/src/bs_runs_upload_manager_tools/utils/aws_secrets_manager_helpers.py create mode 100644 lib/workload/stateless/bs_runs_upload_manager/layers/src/bs_runs_upload_manager_tools/utils/gds_helpers.py create mode 100644 lib/workload/stateless/bs_runs_upload_manager/layers/src/bs_runs_upload_manager_tools/utils/ica_config_helpers.py create mode 100644 lib/workload/stateless/bs_runs_upload_manager/layers/src/bs_runs_upload_manager_tools/utils/portal_helpers.py create mode 100644 lib/workload/stateless/bs_runs_upload_manager/layers/src/bs_runs_upload_manager_tools/utils/samplesheet_helpers.py create mode 100644 lib/workload/stateless/bs_runs_upload_manager/layers/src/bs_runs_upload_manager_tools/utils/tes_helpers.py create mode 100644 lib/workload/stateless/bs_runs_upload_manager/step_functions_templates/bs_runs_upload_step_functions_template.json diff --git a/lib/workload/stateless/bs_runs_upload_manager/Readme.md b/lib/workload/stateless/bs_runs_upload_manager/Readme.md new file mode 100644 index 000000000..fc2bbfe9e --- /dev/null +++ b/lib/workload/stateless/bs_runs_upload_manager/Readme.md @@ -0,0 +1,93 @@ +# BS Runs Upload Manager + + +* [BS Runs Upload Manager](#bs-runs-upload-manager) + * [Summary](#summary) + + +## Summary + +Quick and dirty hack to push our runs from ICAv1 to our V2 BaseSpace server domain + +Once we move from V1 to V2 we probably won't need this. + +This statemachine will copy data from v1 to v2 via bs runs upload. + +The bs runs upload will trigger an Autolaunch of BCLConvert in ICAv2. + +The two steps of the statemachine are: + +1. Generate a V2 Samplesheet and reupload it +2. Launch an ICAv1 tes task that runs the bs runs upload command + +![](images/bs_runs_upload_manager.png) + +## Inputs + +The AWS Step functions takes in the following parameters + +* gdsFolderPath: The path to the run folder in GDS +* gdsVolumeName: The GDS volume name +* sampleSheetName: The name of the sample sheet file + +### Example input + +```json +{ + "gdsFolderPath": "/Runs/231109_A01052_0171_BHLJW7DSX7_r.NULhvzxcSEWmqZw8QljXfQ", + "gdsVolumeName": "bssh.acddbfda498038ed99fa94fe79523959", + "sampleSheetName": "SampleSheet.csv" +} +``` + +### Lambdas in this directory + +#### Upload V2 SampleSheet to GDS Bssh + +This lambda will take in an existing v1 samplesheet and convert it to a v2 samplesheet. It will then upload the v2 samplesheet to the GDS volume. + +This uses the ssbackend API in order to generate the V2 samplesheet since some metadata is required to create V2 samplesheets not present in the V1 samplesheet. + +**Example Input** + +```json +{ + "gds_folder_path": "/Runs/240315_A01052_0186_AH5HM5DSXC_r.YpC_0U_7-06Oom1cFl9Y5A", + "gds_volume_name": "bssh.acddbfda498038ed99fa94fe79523959", + "samplesheet_name": "SampleSheet.csv", +} +``` + +**Example Output** + +```json +{ + "gds_folder_path": "/Runs/240315_A01052_0186_AH5HM5DSXC_r.YpC_0U_7-06Oom1cFl9Y5A", + "gds_volume_name": "bssh.acddbfda498038ed99fa94fe79523959", + "samplesheet_name": "SampleSheet.V2..csv", + "instrument_run_id": "240315_A01052_0186_AH5HM5DSXC" +} +``` + +#### Launch BS Runs Upload Tes + +This lambda will launch a tes task that will run the bs runs upload command. + +**Example Input** + +```json +{ + "gds_folder_path": "/Runs/240315_A01052_0186_AH5HM5DSXC_r.YpC_0U_7-06Oom1cFl9Y5A", + "gds_volume_name": "bssh.acddbfda498038ed99fa94fe79523959", + "samplesheet_name": "SampleSheet.V2..csv", + "instrument_run_id": "240315_A01052_0186_AH5HM5DSXC" +} +``` + +**Example Output** + +```json +{ + "task_run_id": "trn.4fd3414f98fe47c3a6cfc31a67b7418a" +} +``` \ No newline at end of file diff --git a/lib/workload/stateless/bs_runs_upload_manager/deploy/.gitignore b/lib/workload/stateless/bs_runs_upload_manager/deploy/.gitignore new file mode 100644 index 000000000..f60797b6a --- /dev/null +++ b/lib/workload/stateless/bs_runs_upload_manager/deploy/.gitignore @@ -0,0 +1,8 @@ +*.js +!jest.config.js +*.d.ts +node_modules + +# CDK asset staging directory +.cdk.staging +cdk.out diff --git a/lib/workload/stateless/bs_runs_upload_manager/deploy/.npmignore b/lib/workload/stateless/bs_runs_upload_manager/deploy/.npmignore new file mode 100644 index 000000000..c1d6d45dc --- /dev/null +++ b/lib/workload/stateless/bs_runs_upload_manager/deploy/.npmignore @@ -0,0 +1,6 @@ +*.ts +!*.d.ts + +# CDK asset staging directory +.cdk.staging +cdk.out diff --git a/lib/workload/stateless/bs_runs_upload_manager/deploy/README.md b/lib/workload/stateless/bs_runs_upload_manager/deploy/README.md new file mode 100644 index 000000000..9315fe5b9 --- /dev/null +++ b/lib/workload/stateless/bs_runs_upload_manager/deploy/README.md @@ -0,0 +1,14 @@ +# Welcome to your CDK TypeScript project + +This is a blank project for CDK development with TypeScript. + +The `cdk.json` file tells the CDK Toolkit how to execute your app. + +## Useful commands + +* `npm run build` compile typescript to js +* `npm run watch` watch for changes and compile +* `npm run test` perform the jest unit tests +* `npx cdk deploy` deploy this stack to your default AWS account/region +* `npx cdk diff` compare deployed stack with current state +* `npx cdk synth` emits the synthesized CloudFormation template diff --git a/lib/workload/stateless/bs_runs_upload_manager/deploy/bin/deploy.ts b/lib/workload/stateless/bs_runs_upload_manager/deploy/bin/deploy.ts new file mode 100644 index 000000000..9ca63e52d --- /dev/null +++ b/lib/workload/stateless/bs_runs_upload_manager/deploy/bin/deploy.ts @@ -0,0 +1,19 @@ +#!/usr/bin/env node +import 'source-map-support/register'; +import * as cdk from 'aws-cdk-lib'; +import { BsRunsUploadManagerStack } from '../lib/stacks/bs_runs_upload_manager_stack'; +import { GDS_DEV_TEMP_PATH, ICA_TOKEN_SECRET_ID } from '../constants'; + +const app = new cdk.App(); +new BsRunsUploadManagerStack( + app, + 'BsRunsUploadManagerStack', + { + ica_token_secret_id: ICA_TOKEN_SECRET_ID, // ICASecretsPortal + gds_system_files_path: GDS_DEV_TEMP_PATH, // gds://development/primary_data/temp/bs_runs_upload_tes/ + env: { + account: process.env.CDK_DEFAULT_ACCOUNT, + region: process.env.CDK_DEFAULT_REGION, + } + } + ) \ No newline at end of file diff --git a/lib/workload/stateless/bs_runs_upload_manager/deploy/cdk.json b/lib/workload/stateless/bs_runs_upload_manager/deploy/cdk.json new file mode 100644 index 000000000..e8f04c654 --- /dev/null +++ b/lib/workload/stateless/bs_runs_upload_manager/deploy/cdk.json @@ -0,0 +1,66 @@ +{ + "app": "npx ts-node --prefer-ts-exts bin/deploy.ts", + "watch": { + "include": [ + "**" + ], + "exclude": [ + "README.md", + "cdk*.json", + "**/*.d.ts", + "**/*.js", + "tsconfig.json", + "package*.json", + "yarn.lock", + "node_modules", + "test" + ] + }, + "context": { + "@aws-cdk/aws-lambda:recognizeLayerVersion": true, + "@aws-cdk/core:checkSecretUsage": true, + "@aws-cdk/core:target-partitions": [ + "aws", + "aws-cn" + ], + "@aws-cdk-containers/ecs-service-extensions:enableDefaultLogDriver": true, + "@aws-cdk/aws-ec2:uniqueImdsv2TemplateName": true, + "@aws-cdk/aws-ecs:arnFormatIncludesClusterName": true, + "@aws-cdk/aws-iam:minimizePolicies": true, + "@aws-cdk/core:validateSnapshotRemovalPolicy": true, + "@aws-cdk/aws-codepipeline:crossAccountKeyAliasStackSafeResourceName": true, + "@aws-cdk/aws-s3:createDefaultLoggingPolicy": true, + "@aws-cdk/aws-sns-subscriptions:restrictSqsDescryption": true, + "@aws-cdk/aws-apigateway:disableCloudWatchRole": true, + "@aws-cdk/core:enablePartitionLiterals": true, + "@aws-cdk/aws-events:eventsTargetQueueSameAccount": true, + "@aws-cdk/aws-iam:standardizedServicePrincipals": true, + "@aws-cdk/aws-ecs:disableExplicitDeploymentControllerForCircuitBreaker": true, + "@aws-cdk/aws-iam:importedRoleStackSafeDefaultPolicyName": true, + "@aws-cdk/aws-s3:serverAccessLogsUseBucketPolicy": true, + "@aws-cdk/aws-route53-patters:useCertificate": true, + "@aws-cdk/customresources:installLatestAwsSdkDefault": false, + "@aws-cdk/aws-rds:databaseProxyUniqueResourceName": true, + "@aws-cdk/aws-codedeploy:removeAlarmsFromDeploymentGroup": true, + "@aws-cdk/aws-apigateway:authorizerChangeDeploymentLogicalId": true, + "@aws-cdk/aws-ec2:launchTemplateDefaultUserData": true, + "@aws-cdk/aws-secretsmanager:useAttachedSecretResourcePolicyForSecretTargetAttachments": true, + "@aws-cdk/aws-redshift:columnId": true, + "@aws-cdk/aws-stepfunctions-tasks:enableEmrServicePolicyV2": true, + "@aws-cdk/aws-ec2:restrictDefaultSecurityGroup": true, + "@aws-cdk/aws-apigateway:requestValidatorUniqueId": true, + "@aws-cdk/aws-kms:aliasNameRef": true, + "@aws-cdk/aws-autoscaling:generateLaunchTemplateInsteadOfLaunchConfig": true, + "@aws-cdk/core:includePrefixInUniqueNameGeneration": true, + "@aws-cdk/aws-efs:denyAnonymousAccess": true, + "@aws-cdk/aws-opensearchservice:enableOpensearchMultiAzWithStandby": true, + "@aws-cdk/aws-lambda-nodejs:useLatestRuntimeVersion": true, + "@aws-cdk/aws-efs:mountTargetOrderInsensitiveLogicalId": true, + "@aws-cdk/aws-rds:auroraClusterChangeScopeOfInstanceParameterGroupWithEachParameters": true, + "@aws-cdk/aws-appsync:useArnForSourceApiAssociationIdentifier": true, + "@aws-cdk/aws-rds:preventRenderingDeprecatedCredentials": true, + "@aws-cdk/aws-codepipeline-actions:useNewDefaultBranchForCodeCommitSource": true, + "@aws-cdk/aws-cloudwatch-actions:changeLambdaPermissionLogicalIdForLambdaAction": true, + "@aws-cdk/aws-codepipeline:crossAccountKeysDefaultValueToFalse": true + } +} diff --git a/lib/workload/stateless/bs_runs_upload_manager/deploy/constants.ts b/lib/workload/stateless/bs_runs_upload_manager/deploy/constants.ts new file mode 100644 index 000000000..ab88f5a04 --- /dev/null +++ b/lib/workload/stateless/bs_runs_upload_manager/deploy/constants.ts @@ -0,0 +1,3 @@ +export const ICA_TOKEN_SECRET_ID = 'IcaSecretsPortal' + +export const GDS_DEV_TEMP_PATH = 'gds://development/primary_data/temp/bs_runs_upload_tes/' \ No newline at end of file diff --git a/lib/workload/stateless/bs_runs_upload_manager/deploy/jest.config.js b/lib/workload/stateless/bs_runs_upload_manager/deploy/jest.config.js new file mode 100644 index 000000000..08263b895 --- /dev/null +++ b/lib/workload/stateless/bs_runs_upload_manager/deploy/jest.config.js @@ -0,0 +1,8 @@ +module.exports = { + testEnvironment: 'node', + roots: ['/test'], + testMatch: ['**/*.test.ts'], + transform: { + '^.+\\.tsx?$': 'ts-jest' + } +}; diff --git a/lib/workload/stateless/bs_runs_upload_manager/deploy/lib/constructs/bs_runs_upload_manager_stack.ts b/lib/workload/stateless/bs_runs_upload_manager/deploy/lib/constructs/bs_runs_upload_manager_stack.ts new file mode 100644 index 000000000..7ba0bb1b4 --- /dev/null +++ b/lib/workload/stateless/bs_runs_upload_manager/deploy/lib/constructs/bs_runs_upload_manager_stack.ts @@ -0,0 +1,146 @@ +import { Duration } from 'aws-cdk-lib'; +import { Construct } from 'constructs'; +import * as lambda from 'aws-cdk-lib/aws-lambda'; +import * as iam from 'aws-cdk-lib/aws-iam'; +import * as sfn from 'aws-cdk-lib/aws-stepfunctions'; +import * as secretsManager from 'aws-cdk-lib/aws-secretsmanager'; +import { DefinitionBody } from 'aws-cdk-lib/aws-stepfunctions'; + +import { PythonFunction } from '@aws-cdk/aws-lambda-python-alpha'; +import { LambdaLayerConstruct } from './lambda_layer'; +import { IRole } from 'aws-cdk-lib/aws-iam'; + +interface BsRunsUploadManagerConstructProps { + lambdas_layer_path: string; // __dirname + '/../../../layers + upload_v2_samplesheet_to_gds_bssh_lambda_path: string; // __dirname + '/../../../lambdas/upload_v2_samplesheet_to_gds_bssh' + launch_bs_runs_upload_tes_lambda_path: string; // __dirname + '/../../../lambdas/launch_bs_runs_upload_tes' + ica_token_secret_id: string; // IcaSecretsPortal + gds_system_files_path: string; // gds://development/primary_data/temp/bs_runs_upload_tes/ + workflow_definition_body_path: string; // __dirname + '/../../../step_functions_templates/bs_runs_upload_step_functions_template.json' +} + +export class BsRunsUploadManagerConstruct extends Construct { + + public readonly bs_runs_upload_event_state_machine_arn: string; + + constructor(scope: Construct, id: string, props: BsRunsUploadManagerConstructProps) { + super(scope, id); + + // Set lambda layer arn object + const lambda_layer = new LambdaLayerConstruct( + this, 'lambda_layer', { + layer_directory: props.lambdas_layer_path, + }); + + const ica_access_token_secret_obj = secretsManager.Secret.fromSecretNameV2( + this, 'IcaSecretsPortalSecretObject', + props.ica_token_secret_id, + ); + + const portal_secret_obj = secretsManager.Secret.fromSecretNameV2( + this, 'PortalSecret', + 'PortalSecret4BsshUploads', + ); // FIXME: This is a temp hack and has to be updated every half-hour + + const basespace_secret_obj = new secretsManager.Secret( + this, 'BaseSpaceAccessTokenSecret', + { + secretName: 'BaseSpaceAccessTokenSecret' + } + ) + + // V2 Upload lambda + const upload_v2_samplesheet_to_gds_bssh_lambda = new PythonFunction(this, 'upload_v2_samplesheet_to_gds_bssh_lambda', { + entry: props.upload_v2_samplesheet_to_gds_bssh_lambda_path, + runtime: lambda.Runtime.PYTHON_3_11, + index: 'handler.py', + handler: 'handler', + memorySize: 1024, + // @ts-ignore + layers: [lambda_layer.lambda_layer_version_obj], + // @ts-ignore + timeout: Duration.seconds(60), + environment: { + ICA_BASE_URL: "https://aps2.platform.illumina.com", + ICA_ACCESS_TOKEN_SECRET_ID: ica_access_token_secret_obj.secretName, + PORTAL_TOKEN_SECRET_ID: portal_secret_obj.secretName, + } + }); + + // Launch BS Runs Upload TES lambda + const launch_bs_runs_upload_tes_lambda = new PythonFunction(this, 'launch_bs_runs_upload_tes_lambda', + { + entry: props.launch_bs_runs_upload_tes_lambda_path, + runtime: lambda.Runtime.PYTHON_3_11, + index: 'handler.py', + handler: 'handler', + memorySize: 1024, + // @ts-ignore + layers: [lambda_layer.lambda_layer_version_obj], + // @ts-ignore + timeout: Duration.seconds(60), + environment: { + BASESPACE_API_SERVER: "https://api.aps2.sh.basespace.illumina.com", + BASESPACE_ACCESS_TOKEN_SECRET_ID: basespace_secret_obj.secretName, + ICA_BASE_URL: "https://aps2.platform.illumina.com", + ICA_ACCESS_TOKEN_SECRET_ID: ica_access_token_secret_obj.secretName, + GDS_SYSTEM_FILES_PATH: props.gds_system_files_path, + } + } + + ) + + // Give the lambda permission to read the ICA ACCESS TOKEN secret + ica_access_token_secret_obj.grantRead( + // @ts-ignore + launch_bs_runs_upload_tes_lambda.role + ); + ica_access_token_secret_obj.grantRead( + // @ts-ignore + upload_v2_samplesheet_to_gds_bssh_lambda.role + ); + + // Give the lambda permission to read the PORTAL TOKEN secret + // FIXME - remove once we have a better way of collecting the portal token + portal_secret_obj.grantRead( + // @ts-ignore + upload_v2_samplesheet_to_gds_bssh_lambda.role + ); + + // Give basespace upload lambda permission to read the basespace access token secret + basespace_secret_obj.grantRead( + // @ts-ignore + launch_bs_runs_upload_tes_lambda.role + ); + + // Specify the statemachine and replace the arn placeholders with the lambda arns defined above + const stateMachine = new sfn.StateMachine(this, 'bs_runs_upload_state_machine', { + // defintiontemplate + definitionBody: DefinitionBody.fromFile(props.workflow_definition_body_path), + // definitionSubstitutions + definitionSubstitutions: { + '__upload_v2_samplesheet_to_gds_bssh_function_arn__': upload_v2_samplesheet_to_gds_bssh_lambda.functionArn, + '__launch_bs_runs_upload_tes_function_arn__': launch_bs_runs_upload_tes_lambda.functionArn, + }, + }); + + // Add execution permissions to stateMachine role + stateMachine.addToRolePolicy( + new iam.PolicyStatement( + { + resources: [ + upload_v2_samplesheet_to_gds_bssh_lambda.functionArn, + launch_bs_runs_upload_tes_lambda.functionArn, + ], + actions: [ + 'lambda:InvokeFunction', + ], + }, + ), + ); + + // Set outputs + this.bs_runs_upload_event_state_machine_arn = stateMachine.stateMachineArn; + } + +} diff --git a/lib/workload/stateless/bs_runs_upload_manager/deploy/lib/constructs/lambda_layer.ts b/lib/workload/stateless/bs_runs_upload_manager/deploy/lib/constructs/lambda_layer.ts new file mode 100644 index 000000000..4fd2b81e0 --- /dev/null +++ b/lib/workload/stateless/bs_runs_upload_manager/deploy/lib/constructs/lambda_layer.ts @@ -0,0 +1,44 @@ + +import { Construct } from 'constructs' +import { PythonLayerVersion } from '@aws-cdk/aws-lambda-python-alpha'; +import * as lambda from 'aws-cdk-lib/aws-lambda'; + +export interface LambdaLayerConstructProps { + layer_directory: string +} + +export class LambdaLayerConstruct extends Construct { + + public readonly lambda_layer_arn: string; + public readonly lambda_layer_version_obj: PythonLayerVersion; + + constructor(scope: Construct, id: string, props: LambdaLayerConstructProps) { + super(scope, id); + + this.lambda_layer_version_obj = new PythonLayerVersion( + this, + 'bs_runs_upload_layer', + { + entry: props.layer_directory, + compatibleRuntimes: [lambda.Runtime.PYTHON_3_11], + compatibleArchitectures: [lambda.Architecture.X86_64], + license: 'GPL3', + description: 'A layer to enable the bssh manager tools layer', + bundling: { + commandHooks: { + beforeBundling(inputDir: string, outputDir: string): string[] { + return []; + }, + afterBundling(inputDir: string, outputDir: string): string[] { + return [ + `python -m pip install ${inputDir} -t ${outputDir}`, + ]; + }, + }, + }, + }); + + // Set outputs + this.lambda_layer_arn = this.lambda_layer_version_obj.layerVersionArn; + } +} \ No newline at end of file diff --git a/lib/workload/stateless/bs_runs_upload_manager/deploy/lib/stacks/bs_runs_upload_manager_stack.ts b/lib/workload/stateless/bs_runs_upload_manager/deploy/lib/stacks/bs_runs_upload_manager_stack.ts new file mode 100644 index 000000000..e55e61e7a --- /dev/null +++ b/lib/workload/stateless/bs_runs_upload_manager/deploy/lib/stacks/bs_runs_upload_manager_stack.ts @@ -0,0 +1,29 @@ +import * as cdk from 'aws-cdk-lib'; +import { Construct } from 'constructs'; +import { BsRunsUploadManagerConstruct } from '../constructs/bs_runs_upload_manager_stack'; +// import * as sqs from 'aws-cdk-lib/aws-sqs'; + +export interface BsRunsUploadManagerStackProps extends cdk.StackProps { + // Define construct properties here + ica_token_secret_id: string; // IcaSecretsPortal + gds_system_files_path: string; // gds://development/primary_data/temp/bs_runs_upload_tes/ +} + +export class BsRunsUploadManagerStack extends cdk.Stack { + constructor(scope: Construct, id: string, props: BsRunsUploadManagerStackProps) { + super(scope, id, props); + + new BsRunsUploadManagerConstruct( + this, + 'bs-runs-upload-manager', + { + lambdas_layer_path: __dirname + '/../../../layers', + upload_v2_samplesheet_to_gds_bssh_lambda_path: __dirname + '/../../../lambdas/upload_v2_samplesheet_to_gds_bssh', + launch_bs_runs_upload_tes_lambda_path: __dirname + '/../../../lambdas/launch_bs_runs_upload_tes', + ica_token_secret_id: props.ica_token_secret_id, + gds_system_files_path: props.gds_system_files_path, + workflow_definition_body_path: __dirname + '/../../../step_functions_templates/bs_runs_upload_step_functions_template.json' + } + ) + } +} diff --git a/lib/workload/stateless/bs_runs_upload_manager/deploy/package.json b/lib/workload/stateless/bs_runs_upload_manager/deploy/package.json new file mode 100644 index 000000000..c6928fbd0 --- /dev/null +++ b/lib/workload/stateless/bs_runs_upload_manager/deploy/package.json @@ -0,0 +1,27 @@ +{ + "name": "deploy", + "version": "0.1.0", + "bin": { + "deploy": "bin/deploy.js" + }, + "scripts": { + "build": "tsc", + "watch": "tsc -w", + "test": "jest", + "cdk": "cdk" + }, + "devDependencies": { + "@types/jest": "^29.5.12", + "@types/node": "20.11.16", + "jest": "^29.7.0", + "ts-jest": "^29.1.2", + "aws-cdk": "2.128.0", + "ts-node": "^10.9.2", + "typescript": "~5.3.3" + }, + "dependencies": { + "aws-cdk-lib": "2.128.0", + "constructs": "^10.0.0", + "source-map-support": "^0.5.21" + } +} \ No newline at end of file diff --git a/lib/workload/stateless/bs_runs_upload_manager/deploy/test/deploy.test.ts b/lib/workload/stateless/bs_runs_upload_manager/deploy/test/deploy.test.ts new file mode 100644 index 000000000..e7b5dbd29 --- /dev/null +++ b/lib/workload/stateless/bs_runs_upload_manager/deploy/test/deploy.test.ts @@ -0,0 +1,17 @@ +// import * as cdk from 'aws-cdk-lib'; +// import { Template } from 'aws-cdk-lib/assertions'; +// import * as Deploy from '../lib/deploy-stack'; + +// example test. To run these tests, uncomment this file along with the +// example resource in lib/bs_runs_upload_manager_stack.ts +test('SQS Queue Created', () => { +// const app = new cdk.App(); +// // WHEN +// const stack = new Deploy.Bs_runs_upload_manager_stack(app, 'MyTestStack'); +// // THEN +// const template = Template.fromStack(stack); + +// template.hasResourceProperties('AWS::SQS::Queue', { +// VisibilityTimeout: 300 +// }); +}); diff --git a/lib/workload/stateless/bs_runs_upload_manager/deploy/tsconfig.json b/lib/workload/stateless/bs_runs_upload_manager/deploy/tsconfig.json new file mode 100644 index 000000000..aaa7dc510 --- /dev/null +++ b/lib/workload/stateless/bs_runs_upload_manager/deploy/tsconfig.json @@ -0,0 +1,31 @@ +{ + "compilerOptions": { + "target": "ES2020", + "module": "commonjs", + "lib": [ + "es2020", + "dom" + ], + "declaration": true, + "strict": true, + "noImplicitAny": true, + "strictNullChecks": true, + "noImplicitThis": true, + "alwaysStrict": true, + "noUnusedLocals": false, + "noUnusedParameters": false, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": false, + "inlineSourceMap": true, + "inlineSources": true, + "experimentalDecorators": true, + "strictPropertyInitialization": false, + "typeRoots": [ + "./node_modules/@types" + ] + }, + "exclude": [ + "node_modules", + "cdk.out" + ] +} diff --git a/lib/workload/stateless/bs_runs_upload_manager/images/bs_runs_upload_manager_step_functions.png b/lib/workload/stateless/bs_runs_upload_manager/images/bs_runs_upload_manager_step_functions.png new file mode 100755 index 0000000000000000000000000000000000000000..44731356110e832cd8f4cdf7e81afe8ee240e3e4 GIT binary patch literal 53309 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 O00K`}KbLh*2~7aypP this should be renamed from SampleSheet.csv to SampleSheet.V2..csv + +The lambda should fail on the following conditions + +1. If the SampleSheet.csv is not found in the gdsFolderPath +2. If the SampleSheet.csv cannot be converted to a v2 samplesheet via the sscheck backend lambda +3. If the ICAv2 SampleSheet cannot be uploaded back to the gdsFolderPath + +Returns the following object: + +{ + "samplesheet_name": "SampleSheet.V2.timestamp.csv" +} +""" +from pathlib import Path + +from bs_runs_upload_manager_tools.utils.gds_helpers import upload_file_to_gds, download_file_from_gds +from datetime import datetime, timezone +from tempfile import NamedTemporaryFile + +from bs_runs_upload_manager_tools.utils.ica_config_helpers import set_ica_env_vars +from bs_runs_upload_manager_tools.utils.portal_helpers import set_portal_token +from bs_runs_upload_manager_tools.utils.samplesheet_helpers import generate_v2_samplesheet + + +def download_samplesheet_to_temp_dir(samplesheet_path: str) -> Path: + """ + Downloads the samplesheet from the gds path to a temporary directory + """ + named_temp_file_obj = NamedTemporaryFile(suffix=".csv", delete=False) + local_samplesheet_path = Path(named_temp_file_obj.name) + + download_file_from_gds( + gds_path=samplesheet_path, + local_path=local_samplesheet_path + ) + + return local_samplesheet_path + + +def handler(event, context): + # Set environment variables ICA_BASE_URL and ICA_ACCESS_TOKEN + set_ica_env_vars() + set_portal_token() + + # Get the event parameters + gds_folder_path = event["gds_folder_path"] + gds_volume_name = event["gds_volume_name"] + samplesheet_name = event["samplesheet_name"] + + # Download samplesheet + samplesheet_file = download_samplesheet_to_temp_dir( + samplesheet_path=f"gds://{gds_volume_name}{gds_folder_path}/{samplesheet_name}", + ) + + # Collect v2 from ss backend lambda + v2_samplesheet = generate_v2_samplesheet( + v1_samplesheet_file=samplesheet_file, + ) + + # Get current time + timestamp = datetime.now(timezone.utc).timestamp() + + samplesheet_name = f"SampleSheet.V2.{timestamp}.csv" + + # Upload v2 samplesheet + upload_file_to_gds( + local_path=v2_samplesheet, + gds_path=f"gds://{gds_volume_name}{gds_folder_path}/{samplesheet_name}", + ) + + return { + "samplesheet_name": samplesheet_name, + "samplesheet_gds_path": f"gds://{gds_volume_name}{gds_folder_path}/{samplesheet_name}" + } + + +# if __name__ == "__main__": +# import json +# print( +# json.dumps( +# handler( +# { +# "gds_folder_path": "/Runs/231109_A01052_0171_BHLJW7DSX7_r.NULhvzxcSEWmqZw8QljXfQ", +# "samplesheet_name": "SampleSheet.csv", +# "gds_volume_name": "bssh.acddbfda498038ed99fa94fe79523959" +# }, +# None +# ), +# indent=2 +# ) +# ) diff --git a/lib/workload/stateless/bs_runs_upload_manager/layers/poetry.lock b/lib/workload/stateless/bs_runs_upload_manager/layers/poetry.lock new file mode 100644 index 000000000..e06705a65 --- /dev/null +++ b/lib/workload/stateless/bs_runs_upload_manager/layers/poetry.lock @@ -0,0 +1,1034 @@ +# This file is automatically @generated by Poetry 1.8.1 and should not be changed by hand. + +[[package]] +name = "annotated-types" +version = "0.6.0" +description = "Reusable constraint types to use with typing.Annotated" +optional = false +python-versions = ">=3.8" +files = [ + {file = "annotated_types-0.6.0-py3-none-any.whl", hash = "sha256:0641064de18ba7a25dee8f96403ebc39113d0cb953a01429249d5c7564666a43"}, + {file = "annotated_types-0.6.0.tar.gz", hash = "sha256:563339e807e53ffd9c267e99fc6d9ea23eb8443c08f112651963e24e22f84a5d"}, +] + +[[package]] +name = "aws-requests-auth" +version = "0.4.3" +description = "AWS signature version 4 signing process for the python requests module" +optional = false +python-versions = "*" +files = [ + {file = "aws-requests-auth-0.4.3.tar.gz", hash = "sha256:33593372018b960a31dbbe236f89421678b885c35f0b6a7abfae35bb77e069b2"}, + {file = "aws_requests_auth-0.4.3-py2.py3-none-any.whl", hash = "sha256:646bc37d62140ea1c709d20148f5d43197e6bd2d63909eb36fa4bb2345759977"}, +] + +[package.dependencies] +requests = ">=0.14.0" + +[[package]] +name = "beautifulsoup4" +version = "4.12.3" +description = "Screen-scraping library" +optional = false +python-versions = ">=3.6.0" +files = [ + {file = "beautifulsoup4-4.12.3-py3-none-any.whl", hash = "sha256:b80878c9f40111313e55da8ba20bdba06d8fa3969fc68304167741bbf9e082ed"}, + {file = "beautifulsoup4-4.12.3.tar.gz", hash = "sha256:74e3d1928edc070d21748185c46e3fb33490f22f52a3addee9aee0f4f7781051"}, +] + +[package.dependencies] +soupsieve = ">1.2" + +[package.extras] +cchardet = ["cchardet"] +chardet = ["chardet"] +charset-normalizer = ["charset-normalizer"] +html5lib = ["html5lib"] +lxml = ["lxml"] + +[[package]] +name = "boto3" +version = "1.34.68" +description = "The AWS SDK for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "boto3-1.34.68-py3-none-any.whl", hash = "sha256:14f1e23b3f83ec365628a6ef849f1038b4c7338c4fabff159007c711b8147efc"}, + {file = "boto3-1.34.68.tar.gz", hash = "sha256:00a7cff4887e8a46c8b2ce438f33d5f87cf7812f303227adc0266f28338af6d5"}, +] + +[package.dependencies] +botocore = ">=1.34.68,<1.35.0" +jmespath = ">=0.7.1,<2.0.0" +s3transfer = ">=0.10.0,<0.11.0" + +[package.extras] +crt = ["botocore[crt] (>=1.21.0,<2.0a0)"] + +[[package]] +name = "botocore" +version = "1.34.68" +description = "Low-level, data-driven core of boto 3." +optional = false +python-versions = ">=3.8" +files = [ + {file = "botocore-1.34.68-py3-none-any.whl", hash = "sha256:3ad0ec67f78beecc039c3c31c93a83181e30b6f789261bdbb9f5c8e8dc551812"}, + {file = "botocore-1.34.68.tar.gz", hash = "sha256:e7ae9d69cc3e7b31d926e6a1a9ae673ba02da263e35cf12ff2bae35a21755cc6"}, +] + +[package.dependencies] +jmespath = ">=0.7.1,<2.0.0" +python-dateutil = ">=2.1,<3.0.0" +urllib3 = {version = ">=1.25.4,<2.2.0 || >2.2.0,<3", markers = "python_version >= \"3.10\""} + +[package.extras] +crt = ["awscrt (==0.19.19)"] + +[[package]] +name = "certifi" +version = "2024.2.2" +description = "Python package for providing Mozilla's CA Bundle." +optional = false +python-versions = ">=3.6" +files = [ + {file = "certifi-2024.2.2-py3-none-any.whl", hash = "sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1"}, + {file = "certifi-2024.2.2.tar.gz", hash = "sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f"}, +] + +[[package]] +name = "charset-normalizer" +version = "3.3.2" +description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." +optional = false +python-versions = ">=3.7.0" +files = [ + {file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-win32.whl", hash = "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-win32.whl", hash = "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-win32.whl", hash = "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-win32.whl", hash = "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d"}, + {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"}, +] + +[[package]] +name = "colorama" +version = "0.4.6" +description = "Cross-platform colored terminal text." +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +files = [ + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, +] + +[[package]] +name = "docopt" +version = "0.6.2" +description = "Pythonic argument parser, that will make you smile" +optional = false +python-versions = "*" +files = [ + {file = "docopt-0.6.2.tar.gz", hash = "sha256:49b3a825280bd66b3aa83585ef59c4a8c82f2c8a522dbe754a8bc8d08c85c491"}, +] + +[[package]] +name = "idna" +version = "3.6" +description = "Internationalized Domain Names in Applications (IDNA)" +optional = false +python-versions = ">=3.5" +files = [ + {file = "idna-3.6-py3-none-any.whl", hash = "sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f"}, + {file = "idna-3.6.tar.gz", hash = "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca"}, +] + +[[package]] +name = "iniconfig" +version = "2.0.0" +description = "brain-dead simple config-ini parsing" +optional = false +python-versions = ">=3.7" +files = [ + {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, + {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, +] + +[[package]] +name = "jmespath" +version = "1.0.1" +description = "JSON Matching Expressions" +optional = false +python-versions = ">=3.7" +files = [ + {file = "jmespath-1.0.1-py3-none-any.whl", hash = "sha256:02e2e4cc71b5bcab88332eebf907519190dd9e6e82107fa7f83b1003a6252980"}, + {file = "jmespath-1.0.1.tar.gz", hash = "sha256:90261b206d6defd58fdd5e85f478bf633a2901798906be2ad389150c5c60edbe"}, +] + +[[package]] +name = "libica" +version = "2.4.0" +description = "Python SDK for Illumina Connected Analytics" +optional = false +python-versions = ">=3.7" +files = [ + {file = "libica-2.4.0-py3-none-any.whl", hash = "sha256:c80927a1f4aa3f60b2c9faf6e8c22f72000bfdf096429d065ebabfce9928120a"}, + {file = "libica-2.4.0.tar.gz", hash = "sha256:436098a5d5c5e843428e9b1592db33bcd2dbc09b47ed83b9ca1d533f65803189"}, +] + +[package.dependencies] +boto3 = "*" +botocore = "*" +certifi = "*" +python-dateutil = "*" +PyYAML = "*" +requests = "*" +six = "*" +urllib3 = "*" + +[package.extras] +dev = ["black", "build", "detect-secrets", "ggshield", "mkdocs", "mkdocs-material", "openapi-spec-validator", "pdoc3", "pipdeptree", "pre-commit", "setuptools", "twine", "wheel"] +test = ["flake8", "mockito", "nose2", "pytest", "pytest-cov", "tox"] + +[[package]] +name = "mypy-boto3-s3" +version = "1.34.65" +description = "Type annotations for boto3.S3 1.34.65 service generated with mypy-boto3-builder 7.23.2" +optional = false +python-versions = ">=3.8" +files = [ + {file = "mypy-boto3-s3-1.34.65.tar.gz", hash = "sha256:2fcdf412ce2924b2f0b34db59abf06a9c0bbe4cd3361f14f0d2c1e211c0f7ddd"}, + {file = "mypy_boto3_s3-1.34.65-py3-none-any.whl", hash = "sha256:2aecfbe1c00654bc21f839068218d60123366954bf43a708baa50f9543e3f205"}, +] + +[package.dependencies] +typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.12\""} + +[[package]] +name = "mypy-boto3-secretsmanager" +version = "1.34.63" +description = "Type annotations for boto3.SecretsManager 1.34.63 service generated with mypy-boto3-builder 7.23.2" +optional = false +python-versions = ">=3.8" +files = [ + {file = "mypy-boto3-secretsmanager-1.34.63.tar.gz", hash = "sha256:a193373d718f747d53878b5cc7fef2e9b8fde3892e4788ac690fd2b16a35564c"}, + {file = "mypy_boto3_secretsmanager-1.34.63-py3-none-any.whl", hash = "sha256:3ed3587f9b5a5eb4e8c81edeeaa0b4a9118d8f07cfc4915c137f8edc315028ab"}, +] + +[package.dependencies] +typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.12\""} + +[[package]] +name = "mypy-boto3-ssm" +version = "1.34.61" +description = "Type annotations for boto3.SSM 1.34.61 service generated with mypy-boto3-builder 7.23.2" +optional = false +python-versions = ">=3.8" +files = [ + {file = "mypy-boto3-ssm-1.34.61.tar.gz", hash = "sha256:4cbc99f42b6913c536c6cc41c02d3f165920d1e7babb9bb17782b410556cde00"}, + {file = "mypy_boto3_ssm-1.34.61-py3-none-any.whl", hash = "sha256:8ce8d6fc185c07161b5cc3a589df10130d6bbe3182aeeb01549eb95b5580f51c"}, +] + +[package.dependencies] +typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.12\""} + +[[package]] +name = "mypy-boto3-stepfunctions" +version = "1.34.0" +description = "Type annotations for boto3.SFN 1.34.0 service generated with mypy-boto3-builder 7.21.0" +optional = false +python-versions = ">=3.7" +files = [ + {file = "mypy-boto3-stepfunctions-1.34.0.tar.gz", hash = "sha256:06d2296cee750d17cb62171420eea4614f20f29be45ee361854f8b599a6e8110"}, + {file = "mypy_boto3_stepfunctions-1.34.0-py3-none-any.whl", hash = "sha256:ecc1e674c1c89e0559e8dbf3fda81295642b13766db30d42968a986ae6a5e952"}, +] + +[package.dependencies] +typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.12\""} + +[[package]] +name = "numpy" +version = "1.26.4" +description = "Fundamental package for array computing in Python" +optional = false +python-versions = ">=3.9" +files = [ + {file = "numpy-1.26.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9ff0f4f29c51e2803569d7a51c2304de5554655a60c5d776e35b4a41413830d0"}, + {file = "numpy-1.26.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2e4ee3380d6de9c9ec04745830fd9e2eccb3e6cf790d39d7b98ffd19b0dd754a"}, + {file = "numpy-1.26.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d209d8969599b27ad20994c8e41936ee0964e6da07478d6c35016bc386b66ad4"}, + {file = "numpy-1.26.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ffa75af20b44f8dba823498024771d5ac50620e6915abac414251bd971b4529f"}, + {file = "numpy-1.26.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:62b8e4b1e28009ef2846b4c7852046736bab361f7aeadeb6a5b89ebec3c7055a"}, + {file = "numpy-1.26.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a4abb4f9001ad2858e7ac189089c42178fcce737e4169dc61321660f1a96c7d2"}, + {file = "numpy-1.26.4-cp310-cp310-win32.whl", hash = "sha256:bfe25acf8b437eb2a8b2d49d443800a5f18508cd811fea3181723922a8a82b07"}, + {file = "numpy-1.26.4-cp310-cp310-win_amd64.whl", hash = "sha256:b97fe8060236edf3662adfc2c633f56a08ae30560c56310562cb4f95500022d5"}, + {file = "numpy-1.26.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4c66707fabe114439db9068ee468c26bbdf909cac0fb58686a42a24de1760c71"}, + {file = "numpy-1.26.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:edd8b5fe47dab091176d21bb6de568acdd906d1887a4584a15a9a96a1dca06ef"}, + {file = "numpy-1.26.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7ab55401287bfec946ced39700c053796e7cc0e3acbef09993a9ad2adba6ca6e"}, + {file = "numpy-1.26.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:666dbfb6ec68962c033a450943ded891bed2d54e6755e35e5835d63f4f6931d5"}, + {file = "numpy-1.26.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:96ff0b2ad353d8f990b63294c8986f1ec3cb19d749234014f4e7eb0112ceba5a"}, + {file = "numpy-1.26.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:60dedbb91afcbfdc9bc0b1f3f402804070deed7392c23eb7a7f07fa857868e8a"}, + {file = "numpy-1.26.4-cp311-cp311-win32.whl", hash = "sha256:1af303d6b2210eb850fcf03064d364652b7120803a0b872f5211f5234b399f20"}, + {file = "numpy-1.26.4-cp311-cp311-win_amd64.whl", hash = "sha256:cd25bcecc4974d09257ffcd1f098ee778f7834c3ad767fe5db785be9a4aa9cb2"}, + {file = "numpy-1.26.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b3ce300f3644fb06443ee2222c2201dd3a89ea6040541412b8fa189341847218"}, + {file = "numpy-1.26.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:03a8c78d01d9781b28a6989f6fa1bb2c4f2d51201cf99d3dd875df6fbd96b23b"}, + {file = "numpy-1.26.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9fad7dcb1aac3c7f0584a5a8133e3a43eeb2fe127f47e3632d43d677c66c102b"}, + {file = "numpy-1.26.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:675d61ffbfa78604709862923189bad94014bef562cc35cf61d3a07bba02a7ed"}, + {file = "numpy-1.26.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ab47dbe5cc8210f55aa58e4805fe224dac469cde56b9f731a4c098b91917159a"}, + {file = "numpy-1.26.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:1dda2e7b4ec9dd512f84935c5f126c8bd8b9f2fc001e9f54af255e8c5f16b0e0"}, + {file = "numpy-1.26.4-cp312-cp312-win32.whl", hash = "sha256:50193e430acfc1346175fcbdaa28ffec49947a06918b7b92130744e81e640110"}, + {file = "numpy-1.26.4-cp312-cp312-win_amd64.whl", hash = "sha256:08beddf13648eb95f8d867350f6a018a4be2e5ad54c8d8caed89ebca558b2818"}, + {file = "numpy-1.26.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7349ab0fa0c429c82442a27a9673fc802ffdb7c7775fad780226cb234965e53c"}, + {file = "numpy-1.26.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:52b8b60467cd7dd1e9ed082188b4e6bb35aa5cdd01777621a1658910745b90be"}, + {file = "numpy-1.26.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d5241e0a80d808d70546c697135da2c613f30e28251ff8307eb72ba696945764"}, + {file = "numpy-1.26.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f870204a840a60da0b12273ef34f7051e98c3b5961b61b0c2c1be6dfd64fbcd3"}, + {file = "numpy-1.26.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:679b0076f67ecc0138fd2ede3a8fd196dddc2ad3254069bcb9faf9a79b1cebcd"}, + {file = "numpy-1.26.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:47711010ad8555514b434df65f7d7b076bb8261df1ca9bb78f53d3b2db02e95c"}, + {file = "numpy-1.26.4-cp39-cp39-win32.whl", hash = "sha256:a354325ee03388678242a4d7ebcd08b5c727033fcff3b2f536aea978e15ee9e6"}, + {file = "numpy-1.26.4-cp39-cp39-win_amd64.whl", hash = "sha256:3373d5d70a5fe74a2c1bb6d2cfd9609ecf686d47a2d7b1d37a8f3b6bf6003aea"}, + {file = "numpy-1.26.4-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:afedb719a9dcfc7eaf2287b839d8198e06dcd4cb5d276a3df279231138e83d30"}, + {file = "numpy-1.26.4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95a7476c59002f2f6c590b9b7b998306fba6a5aa646b1e22ddfeaf8f78c3a29c"}, + {file = "numpy-1.26.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7e50d0a0cc3189f9cb0aeb3a6a6af18c16f59f004b866cd2be1c14b36134a4a0"}, + {file = "numpy-1.26.4.tar.gz", hash = "sha256:2a02aba9ed12e4ac4eb3ea9421c420301a0c6460d9830d74a9df87efa4912010"}, +] + +[[package]] +name = "packaging" +version = "24.0" +description = "Core utilities for Python packages" +optional = false +python-versions = ">=3.7" +files = [ + {file = "packaging-24.0-py3-none-any.whl", hash = "sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5"}, + {file = "packaging-24.0.tar.gz", hash = "sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9"}, +] + +[[package]] +name = "pandas" +version = "2.2.1" +description = "Powerful data structures for data analysis, time series, and statistics" +optional = false +python-versions = ">=3.9" +files = [ + {file = "pandas-2.2.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8df8612be9cd1c7797c93e1c5df861b2ddda0b48b08f2c3eaa0702cf88fb5f88"}, + {file = "pandas-2.2.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0f573ab277252ed9aaf38240f3b54cfc90fff8e5cab70411ee1d03f5d51f3944"}, + {file = "pandas-2.2.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f02a3a6c83df4026e55b63c1f06476c9aa3ed6af3d89b4f04ea656ccdaaaa359"}, + {file = "pandas-2.2.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c38ce92cb22a4bea4e3929429aa1067a454dcc9c335799af93ba9be21b6beb51"}, + {file = "pandas-2.2.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:c2ce852e1cf2509a69e98358e8458775f89599566ac3775e70419b98615f4b06"}, + {file = "pandas-2.2.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:53680dc9b2519cbf609c62db3ed7c0b499077c7fefda564e330286e619ff0dd9"}, + {file = "pandas-2.2.1-cp310-cp310-win_amd64.whl", hash = "sha256:94e714a1cca63e4f5939cdce5f29ba8d415d85166be3441165edd427dc9f6bc0"}, + {file = "pandas-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f821213d48f4ab353d20ebc24e4faf94ba40d76680642fb7ce2ea31a3ad94f9b"}, + {file = "pandas-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c70e00c2d894cb230e5c15e4b1e1e6b2b478e09cf27cc593a11ef955b9ecc81a"}, + {file = "pandas-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e97fbb5387c69209f134893abc788a6486dbf2f9e511070ca05eed4b930b1b02"}, + {file = "pandas-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:101d0eb9c5361aa0146f500773395a03839a5e6ecde4d4b6ced88b7e5a1a6403"}, + {file = "pandas-2.2.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:7d2ed41c319c9fb4fd454fe25372028dfa417aacb9790f68171b2e3f06eae8cd"}, + {file = "pandas-2.2.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:af5d3c00557d657c8773ef9ee702c61dd13b9d7426794c9dfeb1dc4a0bf0ebc7"}, + {file = "pandas-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:06cf591dbaefb6da9de8472535b185cba556d0ce2e6ed28e21d919704fef1a9e"}, + {file = "pandas-2.2.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:88ecb5c01bb9ca927ebc4098136038519aa5d66b44671861ffab754cae75102c"}, + {file = "pandas-2.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:04f6ec3baec203c13e3f8b139fb0f9f86cd8c0b94603ae3ae8ce9a422e9f5bee"}, + {file = "pandas-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a935a90a76c44fe170d01e90a3594beef9e9a6220021acfb26053d01426f7dc2"}, + {file = "pandas-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c391f594aae2fd9f679d419e9a4d5ba4bce5bb13f6a989195656e7dc4b95c8f0"}, + {file = "pandas-2.2.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:9d1265545f579edf3f8f0cb6f89f234f5e44ba725a34d86535b1a1d38decbccc"}, + {file = "pandas-2.2.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:11940e9e3056576ac3244baef2fedade891977bcc1cb7e5cc8f8cc7d603edc89"}, + {file = "pandas-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:4acf681325ee1c7f950d058b05a820441075b0dd9a2adf5c4835b9bc056bf4fb"}, + {file = "pandas-2.2.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9bd8a40f47080825af4317d0340c656744f2bfdb6819f818e6ba3cd24c0e1397"}, + {file = "pandas-2.2.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:df0c37ebd19e11d089ceba66eba59a168242fc6b7155cba4ffffa6eccdfb8f16"}, + {file = "pandas-2.2.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:739cc70eaf17d57608639e74d63387b0d8594ce02f69e7a0b046f117974b3019"}, + {file = "pandas-2.2.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f9d3558d263073ed95e46f4650becff0c5e1ffe0fc3a015de3c79283dfbdb3df"}, + {file = "pandas-2.2.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:4aa1d8707812a658debf03824016bf5ea0d516afdea29b7dc14cf687bc4d4ec6"}, + {file = "pandas-2.2.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:76f27a809cda87e07f192f001d11adc2b930e93a2b0c4a236fde5429527423be"}, + {file = "pandas-2.2.1-cp39-cp39-win_amd64.whl", hash = "sha256:1ba21b1d5c0e43416218db63037dbe1a01fc101dc6e6024bcad08123e48004ab"}, + {file = "pandas-2.2.1.tar.gz", hash = "sha256:0ab90f87093c13f3e8fa45b48ba9f39181046e8f3317d3aadb2fffbb1b978572"}, +] + +[package.dependencies] +numpy = [ + {version = ">=1.23.2,<2", markers = "python_version == \"3.11\""}, + {version = ">=1.26.0,<2", markers = "python_version >= \"3.12\""}, +] +python-dateutil = ">=2.8.2" +pytz = ">=2020.1" +tzdata = ">=2022.7" + +[package.extras] +all = ["PyQt5 (>=5.15.9)", "SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-driver-sqlite (>=0.8.0)", "beautifulsoup4 (>=4.11.2)", "bottleneck (>=1.3.6)", "dataframe-api-compat (>=0.1.7)", "fastparquet (>=2022.12.0)", "fsspec (>=2022.11.0)", "gcsfs (>=2022.11.0)", "html5lib (>=1.1)", "hypothesis (>=6.46.1)", "jinja2 (>=3.1.2)", "lxml (>=4.9.2)", "matplotlib (>=3.6.3)", "numba (>=0.56.4)", "numexpr (>=2.8.4)", "odfpy (>=1.4.1)", "openpyxl (>=3.1.0)", "pandas-gbq (>=0.19.0)", "psycopg2 (>=2.9.6)", "pyarrow (>=10.0.1)", "pymysql (>=1.0.2)", "pyreadstat (>=1.2.0)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)", "python-calamine (>=0.1.7)", "pyxlsb (>=1.0.10)", "qtpy (>=2.3.0)", "s3fs (>=2022.11.0)", "scipy (>=1.10.0)", "tables (>=3.8.0)", "tabulate (>=0.9.0)", "xarray (>=2022.12.0)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.5)", "zstandard (>=0.19.0)"] +aws = ["s3fs (>=2022.11.0)"] +clipboard = ["PyQt5 (>=5.15.9)", "qtpy (>=2.3.0)"] +compression = ["zstandard (>=0.19.0)"] +computation = ["scipy (>=1.10.0)", "xarray (>=2022.12.0)"] +consortium-standard = ["dataframe-api-compat (>=0.1.7)"] +excel = ["odfpy (>=1.4.1)", "openpyxl (>=3.1.0)", "python-calamine (>=0.1.7)", "pyxlsb (>=1.0.10)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.5)"] +feather = ["pyarrow (>=10.0.1)"] +fss = ["fsspec (>=2022.11.0)"] +gcp = ["gcsfs (>=2022.11.0)", "pandas-gbq (>=0.19.0)"] +hdf5 = ["tables (>=3.8.0)"] +html = ["beautifulsoup4 (>=4.11.2)", "html5lib (>=1.1)", "lxml (>=4.9.2)"] +mysql = ["SQLAlchemy (>=2.0.0)", "pymysql (>=1.0.2)"] +output-formatting = ["jinja2 (>=3.1.2)", "tabulate (>=0.9.0)"] +parquet = ["pyarrow (>=10.0.1)"] +performance = ["bottleneck (>=1.3.6)", "numba (>=0.56.4)", "numexpr (>=2.8.4)"] +plot = ["matplotlib (>=3.6.3)"] +postgresql = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "psycopg2 (>=2.9.6)"] +pyarrow = ["pyarrow (>=10.0.1)"] +spss = ["pyreadstat (>=1.2.0)"] +sql-other = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-driver-sqlite (>=0.8.0)"] +test = ["hypothesis (>=6.46.1)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)"] +xml = ["lxml (>=4.9.2)"] + +[[package]] +name = "pluggy" +version = "1.4.0" +description = "plugin and hook calling mechanisms for python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pluggy-1.4.0-py3-none-any.whl", hash = "sha256:7db9f7b503d67d1c5b95f59773ebb58a8c1c288129a88665838012cfb07b8981"}, + {file = "pluggy-1.4.0.tar.gz", hash = "sha256:8c85c2876142a764e5b7548e7d9a0e0ddb46f5185161049a79b7e974454223be"}, +] + +[package.extras] +dev = ["pre-commit", "tox"] +testing = ["pytest", "pytest-benchmark"] + +[[package]] +name = "pyarrow" +version = "15.0.2" +description = "Python library for Apache Arrow" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pyarrow-15.0.2-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:88b340f0a1d05b5ccc3d2d986279045655b1fe8e41aba6ca44ea28da0d1455d8"}, + {file = "pyarrow-15.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:eaa8f96cecf32da508e6c7f69bb8401f03745c050c1dd42ec2596f2e98deecac"}, + {file = "pyarrow-15.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:23c6753ed4f6adb8461e7c383e418391b8d8453c5d67e17f416c3a5d5709afbd"}, + {file = "pyarrow-15.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f639c059035011db8c0497e541a8a45d98a58dbe34dc8fadd0ef128f2cee46e5"}, + {file = "pyarrow-15.0.2-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:290e36a59a0993e9a5224ed2fb3e53375770f07379a0ea03ee2fce2e6d30b423"}, + {file = "pyarrow-15.0.2-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:06c2bb2a98bc792f040bef31ad3e9be6a63d0cb39189227c08a7d955db96816e"}, + {file = "pyarrow-15.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:f7a197f3670606a960ddc12adbe8075cea5f707ad7bf0dffa09637fdbb89f76c"}, + {file = "pyarrow-15.0.2-cp311-cp311-macosx_10_15_x86_64.whl", hash = "sha256:5f8bc839ea36b1f99984c78e06e7a06054693dc2af8920f6fb416b5bca9944e4"}, + {file = "pyarrow-15.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f5e81dfb4e519baa6b4c80410421528c214427e77ca0ea9461eb4097c328fa33"}, + {file = "pyarrow-15.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3a4f240852b302a7af4646c8bfe9950c4691a419847001178662a98915fd7ee7"}, + {file = "pyarrow-15.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e7d9cfb5a1e648e172428c7a42b744610956f3b70f524aa3a6c02a448ba853e"}, + {file = "pyarrow-15.0.2-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:2d4f905209de70c0eb5b2de6763104d5a9a37430f137678edfb9a675bac9cd98"}, + {file = "pyarrow-15.0.2-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:90adb99e8ce5f36fbecbbc422e7dcbcbed07d985eed6062e459e23f9e71fd197"}, + {file = "pyarrow-15.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:b116e7fd7889294cbd24eb90cd9bdd3850be3738d61297855a71ac3b8124ee38"}, + {file = "pyarrow-15.0.2-cp312-cp312-macosx_10_15_x86_64.whl", hash = "sha256:25335e6f1f07fdaa026a61c758ee7d19ce824a866b27bba744348fa73bb5a440"}, + {file = "pyarrow-15.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:90f19e976d9c3d8e73c80be84ddbe2f830b6304e4c576349d9360e335cd627fc"}, + {file = "pyarrow-15.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a22366249bf5fd40ddacc4f03cd3160f2d7c247692945afb1899bab8a140ddfb"}, + {file = "pyarrow-15.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c2a335198f886b07e4b5ea16d08ee06557e07db54a8400cc0d03c7f6a22f785f"}, + {file = "pyarrow-15.0.2-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:3e6d459c0c22f0b9c810a3917a1de3ee704b021a5fb8b3bacf968eece6df098f"}, + {file = "pyarrow-15.0.2-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:033b7cad32198754d93465dcfb71d0ba7cb7cd5c9afd7052cab7214676eec38b"}, + {file = "pyarrow-15.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:29850d050379d6e8b5a693098f4de7fd6a2bea4365bfd073d7c57c57b95041ee"}, + {file = "pyarrow-15.0.2-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:7167107d7fb6dcadb375b4b691b7e316f4368f39f6f45405a05535d7ad5e5058"}, + {file = "pyarrow-15.0.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:e85241b44cc3d365ef950432a1b3bd44ac54626f37b2e3a0cc89c20e45dfd8bf"}, + {file = "pyarrow-15.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:248723e4ed3255fcd73edcecc209744d58a9ca852e4cf3d2577811b6d4b59818"}, + {file = "pyarrow-15.0.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ff3bdfe6f1b81ca5b73b70a8d482d37a766433823e0c21e22d1d7dde76ca33f"}, + {file = "pyarrow-15.0.2-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:f3d77463dee7e9f284ef42d341689b459a63ff2e75cee2b9302058d0d98fe142"}, + {file = "pyarrow-15.0.2-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:8c1faf2482fb89766e79745670cbca04e7018497d85be9242d5350cba21357e1"}, + {file = "pyarrow-15.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:28f3016958a8e45a1069303a4a4f6a7d4910643fc08adb1e2e4a7ff056272ad3"}, + {file = "pyarrow-15.0.2-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:89722cb64286ab3d4daf168386f6968c126057b8c7ec3ef96302e81d8cdb8ae4"}, + {file = "pyarrow-15.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:cd0ba387705044b3ac77b1b317165c0498299b08261d8122c96051024f953cd5"}, + {file = "pyarrow-15.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ad2459bf1f22b6a5cdcc27ebfd99307d5526b62d217b984b9f5c974651398832"}, + {file = "pyarrow-15.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58922e4bfece8b02abf7159f1f53a8f4d9f8e08f2d988109126c17c3bb261f22"}, + {file = "pyarrow-15.0.2-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:adccc81d3dc0478ea0b498807b39a8d41628fa9210729b2f718b78cb997c7c91"}, + {file = "pyarrow-15.0.2-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:8bd2baa5fe531571847983f36a30ddbf65261ef23e496862ece83bdceb70420d"}, + {file = "pyarrow-15.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:6669799a1d4ca9da9c7e06ef48368320f5856f36f9a4dd31a11839dda3f6cc8c"}, + {file = "pyarrow-15.0.2.tar.gz", hash = "sha256:9c9bc803cb3b7bfacc1e96ffbfd923601065d9d3f911179d81e72d99fd74a3d9"}, +] + +[package.dependencies] +numpy = ">=1.16.6,<2" + +[[package]] +name = "pydantic" +version = "2.6.4" +description = "Data validation using Python type hints" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pydantic-2.6.4-py3-none-any.whl", hash = "sha256:cc46fce86607580867bdc3361ad462bab9c222ef042d3da86f2fb333e1d916c5"}, + {file = "pydantic-2.6.4.tar.gz", hash = "sha256:b1704e0847db01817624a6b86766967f552dd9dbf3afba4004409f908dcc84e6"}, +] + +[package.dependencies] +annotated-types = ">=0.4.0" +pydantic-core = "2.16.3" +typing-extensions = ">=4.6.1" + +[package.extras] +email = ["email-validator (>=2.0.0)"] + +[[package]] +name = "pydantic-core" +version = "2.16.3" +description = "" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pydantic_core-2.16.3-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:75b81e678d1c1ede0785c7f46690621e4c6e63ccd9192af1f0bd9d504bbb6bf4"}, + {file = "pydantic_core-2.16.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9c865a7ee6f93783bd5d781af5a4c43dadc37053a5b42f7d18dc019f8c9d2bd1"}, + {file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:162e498303d2b1c036b957a1278fa0899d02b2842f1ff901b6395104c5554a45"}, + {file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2f583bd01bbfbff4eaee0868e6fc607efdfcc2b03c1c766b06a707abbc856187"}, + {file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b926dd38db1519ed3043a4de50214e0d600d404099c3392f098a7f9d75029ff8"}, + {file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:716b542728d4c742353448765aa7cdaa519a7b82f9564130e2b3f6766018c9ec"}, + {file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc4ad7f7ee1a13d9cb49d8198cd7d7e3aa93e425f371a68235f784e99741561f"}, + {file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bd87f48924f360e5d1c5f770d6155ce0e7d83f7b4e10c2f9ec001c73cf475c99"}, + {file = "pydantic_core-2.16.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0df446663464884297c793874573549229f9eca73b59360878f382a0fc085979"}, + {file = "pydantic_core-2.16.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4df8a199d9f6afc5ae9a65f8f95ee52cae389a8c6b20163762bde0426275b7db"}, + {file = "pydantic_core-2.16.3-cp310-none-win32.whl", hash = "sha256:456855f57b413f077dff513a5a28ed838dbbb15082ba00f80750377eed23d132"}, + {file = "pydantic_core-2.16.3-cp310-none-win_amd64.whl", hash = "sha256:732da3243e1b8d3eab8c6ae23ae6a58548849d2e4a4e03a1924c8ddf71a387cb"}, + {file = "pydantic_core-2.16.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:519ae0312616026bf4cedc0fe459e982734f3ca82ee8c7246c19b650b60a5ee4"}, + {file = "pydantic_core-2.16.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b3992a322a5617ded0a9f23fd06dbc1e4bd7cf39bc4ccf344b10f80af58beacd"}, + {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8d62da299c6ecb04df729e4b5c52dc0d53f4f8430b4492b93aa8de1f541c4aac"}, + {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2acca2be4bb2f2147ada8cac612f8a98fc09f41c89f87add7256ad27332c2fda"}, + {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1b662180108c55dfbf1280d865b2d116633d436cfc0bba82323554873967b340"}, + {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e7c6ed0dc9d8e65f24f5824291550139fe6f37fac03788d4580da0d33bc00c97"}, + {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a6b1bb0827f56654b4437955555dc3aeeebeddc47c2d7ed575477f082622c49e"}, + {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e56f8186d6210ac7ece503193ec84104da7ceb98f68ce18c07282fcc2452e76f"}, + {file = "pydantic_core-2.16.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:936e5db01dd49476fa8f4383c259b8b1303d5dd5fb34c97de194560698cc2c5e"}, + {file = "pydantic_core-2.16.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:33809aebac276089b78db106ee692bdc9044710e26f24a9a2eaa35a0f9fa70ba"}, + {file = "pydantic_core-2.16.3-cp311-none-win32.whl", hash = "sha256:ded1c35f15c9dea16ead9bffcde9bb5c7c031bff076355dc58dcb1cb436c4721"}, + {file = "pydantic_core-2.16.3-cp311-none-win_amd64.whl", hash = "sha256:d89ca19cdd0dd5f31606a9329e309d4fcbb3df860960acec32630297d61820df"}, + {file = "pydantic_core-2.16.3-cp311-none-win_arm64.whl", hash = "sha256:6162f8d2dc27ba21027f261e4fa26f8bcb3cf9784b7f9499466a311ac284b5b9"}, + {file = "pydantic_core-2.16.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:0f56ae86b60ea987ae8bcd6654a887238fd53d1384f9b222ac457070b7ac4cff"}, + {file = "pydantic_core-2.16.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c9bd22a2a639e26171068f8ebb5400ce2c1bc7d17959f60a3b753ae13c632975"}, + {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4204e773b4b408062960e65468d5346bdfe139247ee5f1ca2a378983e11388a2"}, + {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f651dd19363c632f4abe3480a7c87a9773be27cfe1341aef06e8759599454120"}, + {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aaf09e615a0bf98d406657e0008e4a8701b11481840be7d31755dc9f97c44053"}, + {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8e47755d8152c1ab5b55928ab422a76e2e7b22b5ed8e90a7d584268dd49e9c6b"}, + {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:500960cb3a0543a724a81ba859da816e8cf01b0e6aaeedf2c3775d12ee49cade"}, + {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cf6204fe865da605285c34cf1172879d0314ff267b1c35ff59de7154f35fdc2e"}, + {file = "pydantic_core-2.16.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d33dd21f572545649f90c38c227cc8631268ba25c460b5569abebdd0ec5974ca"}, + {file = "pydantic_core-2.16.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:49d5d58abd4b83fb8ce763be7794d09b2f50f10aa65c0f0c1696c677edeb7cbf"}, + {file = "pydantic_core-2.16.3-cp312-none-win32.whl", hash = "sha256:f53aace168a2a10582e570b7736cc5bef12cae9cf21775e3eafac597e8551fbe"}, + {file = "pydantic_core-2.16.3-cp312-none-win_amd64.whl", hash = "sha256:0d32576b1de5a30d9a97f300cc6a3f4694c428d956adbc7e6e2f9cad279e45ed"}, + {file = "pydantic_core-2.16.3-cp312-none-win_arm64.whl", hash = "sha256:ec08be75bb268473677edb83ba71e7e74b43c008e4a7b1907c6d57e940bf34b6"}, + {file = "pydantic_core-2.16.3-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:b1f6f5938d63c6139860f044e2538baeee6f0b251a1816e7adb6cbce106a1f01"}, + {file = "pydantic_core-2.16.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2a1ef6a36fdbf71538142ed604ad19b82f67b05749512e47f247a6ddd06afdc7"}, + {file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:704d35ecc7e9c31d48926150afada60401c55efa3b46cd1ded5a01bdffaf1d48"}, + {file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d937653a696465677ed583124b94a4b2d79f5e30b2c46115a68e482c6a591c8a"}, + {file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c9803edf8e29bd825f43481f19c37f50d2b01899448273b3a7758441b512acf8"}, + {file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:72282ad4892a9fb2da25defeac8c2e84352c108705c972db82ab121d15f14e6d"}, + {file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f752826b5b8361193df55afcdf8ca6a57d0232653494ba473630a83ba50d8c9"}, + {file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4384a8f68ddb31a0b0c3deae88765f5868a1b9148939c3f4121233314ad5532c"}, + {file = "pydantic_core-2.16.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:a4b2bf78342c40b3dc830880106f54328928ff03e357935ad26c7128bbd66ce8"}, + {file = "pydantic_core-2.16.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:13dcc4802961b5f843a9385fc821a0b0135e8c07fc3d9949fd49627c1a5e6ae5"}, + {file = "pydantic_core-2.16.3-cp38-none-win32.whl", hash = "sha256:e3e70c94a0c3841e6aa831edab1619ad5c511199be94d0c11ba75fe06efe107a"}, + {file = "pydantic_core-2.16.3-cp38-none-win_amd64.whl", hash = "sha256:ecdf6bf5f578615f2e985a5e1f6572e23aa632c4bd1dc67f8f406d445ac115ed"}, + {file = "pydantic_core-2.16.3-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:bda1ee3e08252b8d41fa5537413ffdddd58fa73107171a126d3b9ff001b9b820"}, + {file = "pydantic_core-2.16.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:21b888c973e4f26b7a96491c0965a8a312e13be108022ee510248fe379a5fa23"}, + {file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:be0ec334369316fa73448cc8c982c01e5d2a81c95969d58b8f6e272884df0074"}, + {file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b5b6079cc452a7c53dd378c6f881ac528246b3ac9aae0f8eef98498a75657805"}, + {file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7ee8d5f878dccb6d499ba4d30d757111847b6849ae07acdd1205fffa1fc1253c"}, + {file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7233d65d9d651242a68801159763d09e9ec96e8a158dbf118dc090cd77a104c9"}, + {file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c6119dc90483a5cb50a1306adb8d52c66e447da88ea44f323e0ae1a5fcb14256"}, + {file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:578114bc803a4c1ff9946d977c221e4376620a46cf78da267d946397dc9514a8"}, + {file = "pydantic_core-2.16.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d8f99b147ff3fcf6b3cc60cb0c39ea443884d5559a30b1481e92495f2310ff2b"}, + {file = "pydantic_core-2.16.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4ac6b4ce1e7283d715c4b729d8f9dab9627586dafce81d9eaa009dd7f25dd972"}, + {file = "pydantic_core-2.16.3-cp39-none-win32.whl", hash = "sha256:e7774b570e61cb998490c5235740d475413a1f6de823169b4cf94e2fe9e9f6b2"}, + {file = "pydantic_core-2.16.3-cp39-none-win_amd64.whl", hash = "sha256:9091632a25b8b87b9a605ec0e61f241c456e9248bfdcf7abdf344fdb169c81cf"}, + {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:36fa178aacbc277bc6b62a2c3da95226520da4f4e9e206fdf076484363895d2c"}, + {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:dcca5d2bf65c6fb591fff92da03f94cd4f315972f97c21975398bd4bd046854a"}, + {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2a72fb9963cba4cd5793854fd12f4cfee731e86df140f59ff52a49b3552db241"}, + {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b60cc1a081f80a2105a59385b92d82278b15d80ebb3adb200542ae165cd7d183"}, + {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cbcc558401de90a746d02ef330c528f2e668c83350f045833543cd57ecead1ad"}, + {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:fee427241c2d9fb7192b658190f9f5fd6dfe41e02f3c1489d2ec1e6a5ab1e04a"}, + {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f4cb85f693044e0f71f394ff76c98ddc1bc0953e48c061725e540396d5c8a2e1"}, + {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:b29eeb887aa931c2fcef5aa515d9d176d25006794610c264ddc114c053bf96fe"}, + {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:a425479ee40ff021f8216c9d07a6a3b54b31c8267c6e17aa88b70d7ebd0e5e5b"}, + {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:5c5cbc703168d1b7a838668998308018a2718c2130595e8e190220238addc96f"}, + {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:99b6add4c0b39a513d323d3b93bc173dac663c27b99860dd5bf491b240d26137"}, + {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75f76ee558751746d6a38f89d60b6228fa174e5172d143886af0f85aa306fd89"}, + {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:00ee1c97b5364b84cb0bd82e9bbf645d5e2871fb8c58059d158412fee2d33d8a"}, + {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:287073c66748f624be4cef893ef9174e3eb88fe0b8a78dc22e88eca4bc357ca6"}, + {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:ed25e1835c00a332cb10c683cd39da96a719ab1dfc08427d476bce41b92531fc"}, + {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:86b3d0033580bd6bbe07590152007275bd7af95f98eaa5bd36f3da219dcd93da"}, + {file = "pydantic_core-2.16.3.tar.gz", hash = "sha256:1cac689f80a3abab2d3c0048b29eea5751114054f032a941a32de4c852c59cad"}, +] + +[package.dependencies] +typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" + +[[package]] +name = "pyjwt" +version = "2.8.0" +description = "JSON Web Token implementation in Python" +optional = false +python-versions = ">=3.7" +files = [ + {file = "PyJWT-2.8.0-py3-none-any.whl", hash = "sha256:59127c392cc44c2da5bb3192169a91f429924e17aff6534d70fdc02ab3e04320"}, + {file = "PyJWT-2.8.0.tar.gz", hash = "sha256:57e28d156e3d5c10088e0c68abb90bfac3df82b40a71bd0daa20c65ccd5c23de"}, +] + +[package.extras] +crypto = ["cryptography (>=3.4.0)"] +dev = ["coverage[toml] (==5.0.4)", "cryptography (>=3.4.0)", "pre-commit", "pytest (>=6.0.0,<7.0.0)", "sphinx (>=4.5.0,<5.0.0)", "sphinx-rtd-theme", "zope.interface"] +docs = ["sphinx (>=4.5.0,<5.0.0)", "sphinx-rtd-theme", "zope.interface"] +tests = ["coverage[toml] (==5.0.4)", "pytest (>=6.0.0,<7.0.0)"] + +[[package]] +name = "pytest" +version = "7.4.4" +description = "pytest: simple powerful testing with Python" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pytest-7.4.4-py3-none-any.whl", hash = "sha256:b090cdf5ed60bf4c45261be03239c2c1c22df034fbffe691abe93cd80cea01d8"}, + {file = "pytest-7.4.4.tar.gz", hash = "sha256:2cf0005922c6ace4a3e2ec8b4080eb0d9753fdc93107415332f50ce9e7994280"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "sys_platform == \"win32\""} +iniconfig = "*" +packaging = "*" +pluggy = ">=0.12,<2.0" + +[package.extras] +testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] + +[[package]] +name = "python-dateutil" +version = "2.9.0.post0" +description = "Extensions to the standard Python datetime module" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +files = [ + {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, + {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, +] + +[package.dependencies] +six = ">=1.5" + +[[package]] +name = "pytz" +version = "2024.1" +description = "World timezone definitions, modern and historical" +optional = false +python-versions = "*" +files = [ + {file = "pytz-2024.1-py2.py3-none-any.whl", hash = "sha256:328171f4e3623139da4983451950b28e95ac706e13f3f2630a879749e7a8b319"}, + {file = "pytz-2024.1.tar.gz", hash = "sha256:2a29735ea9c18baf14b448846bde5a48030ed267578472d8955cd0e7443a9812"}, +] + +[[package]] +name = "pyyaml" +version = "6.0.1" +description = "YAML parser and emitter for Python" +optional = false +python-versions = ">=3.6" +files = [ + {file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"}, + {file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, + {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, + {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, + {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, + {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, + {file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, + {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, + {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, + {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, + {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, + {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, + {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, + {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd"}, + {file = "PyYAML-6.0.1-cp36-cp36m-win32.whl", hash = "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585"}, + {file = "PyYAML-6.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa"}, + {file = "PyYAML-6.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c"}, + {file = "PyYAML-6.0.1-cp37-cp37m-win32.whl", hash = "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba"}, + {file = "PyYAML-6.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867"}, + {file = "PyYAML-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, + {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, + {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, + {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, + {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, + {file = "PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, + {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, + {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, + {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, + {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, +] + +[[package]] +name = "requests" +version = "2.31.0" +description = "Python HTTP for Humans." +optional = false +python-versions = ">=3.7" +files = [ + {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"}, + {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"}, +] + +[package.dependencies] +certifi = ">=2017.4.17" +charset-normalizer = ">=2,<4" +idna = ">=2.5,<4" +urllib3 = ">=1.21.1,<3" + +[package.extras] +socks = ["PySocks (>=1.5.6,!=1.5.7)"] +use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] + +[[package]] +name = "ruamel-base" +version = "1.0.0" +description = "common routines for ruamel packages" +optional = false +python-versions = "*" +files = [ + {file = "ruamel.base-1.0.0-py2-none-any.whl", hash = "sha256:ff7fe471b3d715fe4f2c4663d9e6d82efbeb3cea8e72accb99fd4fa90df7e5f9"}, + {file = "ruamel.base-1.0.0-py3-none-any.whl", hash = "sha256:3613a90afcf0735540804af2a693f630a0bccebefec9b4023a39e88950bb294e"}, + {file = "ruamel.base-1.0.0.tar.gz", hash = "sha256:c041333a0f0f00cd6593eb36aa83abb1a9e7544e83ba7a42aa7ac7476cee5cf3"}, +] + +[[package]] +name = "ruamel-yaml" +version = "0.18.6" +description = "ruamel.yaml is a YAML parser/emitter that supports roundtrip preservation of comments, seq/map flow style, and map key order" +optional = false +python-versions = ">=3.7" +files = [ + {file = "ruamel.yaml-0.18.6-py3-none-any.whl", hash = "sha256:57b53ba33def16c4f3d807c0ccbc00f8a6081827e81ba2491691b76882d0c636"}, + {file = "ruamel.yaml-0.18.6.tar.gz", hash = "sha256:8b27e6a217e786c6fbe5634d8f3f11bc63e0f80f6a5890f28863d9c45aac311b"}, +] + +[package.dependencies] +"ruamel.yaml.clib" = {version = ">=0.2.7", markers = "platform_python_implementation == \"CPython\" and python_version < \"3.13\""} + +[package.extras] +docs = ["mercurial (>5.7)", "ryd"] +jinja2 = ["ruamel.yaml.jinja2 (>=0.2)"] + +[[package]] +name = "ruamel-yaml-clib" +version = "0.2.8" +description = "C version of reader, parser and emitter for ruamel.yaml derived from libyaml" +optional = false +python-versions = ">=3.6" +files = [ + {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:b42169467c42b692c19cf539c38d4602069d8c1505e97b86387fcf7afb766e1d"}, + {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-macosx_13_0_arm64.whl", hash = "sha256:07238db9cbdf8fc1e9de2489a4f68474e70dffcb32232db7c08fa61ca0c7c462"}, + {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:fff3573c2db359f091e1589c3d7c5fc2f86f5bdb6f24252c2d8e539d4e45f412"}, + {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-manylinux_2_24_aarch64.whl", hash = "sha256:aa2267c6a303eb483de8d02db2871afb5c5fc15618d894300b88958f729ad74f"}, + {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:840f0c7f194986a63d2c2465ca63af8ccbbc90ab1c6001b1978f05119b5e7334"}, + {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:024cfe1fc7c7f4e1aff4a81e718109e13409767e4f871443cbff3dba3578203d"}, + {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-win32.whl", hash = "sha256:c69212f63169ec1cfc9bb44723bf2917cbbd8f6191a00ef3410f5a7fe300722d"}, + {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-win_amd64.whl", hash = "sha256:cabddb8d8ead485e255fe80429f833172b4cadf99274db39abc080e068cbcc31"}, + {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:bef08cd86169d9eafb3ccb0a39edb11d8e25f3dae2b28f5c52fd997521133069"}, + {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-macosx_13_0_arm64.whl", hash = "sha256:b16420e621d26fdfa949a8b4b47ade8810c56002f5389970db4ddda51dbff248"}, + {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:25c515e350e5b739842fc3228d662413ef28f295791af5e5110b543cf0b57d9b"}, + {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-manylinux_2_24_aarch64.whl", hash = "sha256:1707814f0d9791df063f8c19bb51b0d1278b8e9a2353abbb676c2f685dee6afe"}, + {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:46d378daaac94f454b3a0e3d8d78cafd78a026b1d71443f4966c696b48a6d899"}, + {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:09b055c05697b38ecacb7ac50bdab2240bfca1a0c4872b0fd309bb07dc9aa3a9"}, + {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-win32.whl", hash = "sha256:53a300ed9cea38cf5a2a9b069058137c2ca1ce658a874b79baceb8f892f915a7"}, + {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-win_amd64.whl", hash = "sha256:c2a72e9109ea74e511e29032f3b670835f8a59bbdc9ce692c5b4ed91ccf1eedb"}, + {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:ebc06178e8821efc9692ea7544aa5644217358490145629914d8020042c24aa1"}, + {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-macosx_13_0_arm64.whl", hash = "sha256:edaef1c1200c4b4cb914583150dcaa3bc30e592e907c01117c08b13a07255ec2"}, + {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d176b57452ab5b7028ac47e7b3cf644bcfdc8cacfecf7e71759f7f51a59e5c92"}, + {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-manylinux_2_24_aarch64.whl", hash = "sha256:1dc67314e7e1086c9fdf2680b7b6c2be1c0d8e3a8279f2e993ca2a7545fecf62"}, + {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:3213ece08ea033eb159ac52ae052a4899b56ecc124bb80020d9bbceeb50258e9"}, + {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:aab7fd643f71d7946f2ee58cc88c9b7bfc97debd71dcc93e03e2d174628e7e2d"}, + {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-win32.whl", hash = "sha256:5c365d91c88390c8d0a8545df0b5857172824b1c604e867161e6b3d59a827eaa"}, + {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-win_amd64.whl", hash = "sha256:1758ce7d8e1a29d23de54a16ae867abd370f01b5a69e1a3ba75223eaa3ca1a1b"}, + {file = "ruamel.yaml.clib-0.2.8-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:a5aa27bad2bb83670b71683aae140a1f52b0857a2deff56ad3f6c13a017a26ed"}, + {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c58ecd827313af6864893e7af0a3bb85fd529f862b6adbefe14643947cfe2942"}, + {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-macosx_12_0_arm64.whl", hash = "sha256:f481f16baec5290e45aebdc2a5168ebc6d35189ae6fea7a58787613a25f6e875"}, + {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-manylinux_2_24_aarch64.whl", hash = "sha256:77159f5d5b5c14f7c34073862a6b7d34944075d9f93e681638f6d753606c6ce6"}, + {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:7f67a1ee819dc4562d444bbafb135832b0b909f81cc90f7aa00260968c9ca1b3"}, + {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:4ecbf9c3e19f9562c7fdd462e8d18dd902a47ca046a2e64dba80699f0b6c09b7"}, + {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:87ea5ff66d8064301a154b3933ae406b0863402a799b16e4a1d24d9fbbcbe0d3"}, + {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-win32.whl", hash = "sha256:75e1ed13e1f9de23c5607fe6bd1aeaae21e523b32d83bb33918245361e9cc51b"}, + {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-win_amd64.whl", hash = "sha256:3f215c5daf6a9d7bbed4a0a4f760f3113b10e82ff4c5c44bec20a68c8014f675"}, + {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1b617618914cb00bf5c34d4357c37aa15183fa229b24767259657746c9077615"}, + {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-macosx_12_0_arm64.whl", hash = "sha256:a6a9ffd280b71ad062eae53ac1659ad86a17f59a0fdc7699fd9be40525153337"}, + {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-manylinux_2_24_aarch64.whl", hash = "sha256:305889baa4043a09e5b76f8e2a51d4ffba44259f6b4c72dec8ca56207d9c6fe1"}, + {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:700e4ebb569e59e16a976857c8798aee258dceac7c7d6b50cab63e080058df91"}, + {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:e2b4c44b60eadec492926a7270abb100ef9f72798e18743939bdbf037aab8c28"}, + {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:e79e5db08739731b0ce4850bed599235d601701d5694c36570a99a0c5ca41a9d"}, + {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-win32.whl", hash = "sha256:955eae71ac26c1ab35924203fda6220f84dce57d6d7884f189743e2abe3a9fbe"}, + {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-win_amd64.whl", hash = "sha256:56f4252222c067b4ce51ae12cbac231bce32aee1d33fbfc9d17e5b8d6966c312"}, + {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:03d1162b6d1df1caa3a4bd27aa51ce17c9afc2046c31b0ad60a0a96ec22f8001"}, + {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:bba64af9fa9cebe325a62fa398760f5c7206b215201b0ec825005f1b18b9bccf"}, + {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-manylinux_2_24_aarch64.whl", hash = "sha256:a1a45e0bb052edf6a1d3a93baef85319733a888363938e1fc9924cb00c8df24c"}, + {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:da09ad1c359a728e112d60116f626cc9f29730ff3e0e7db72b9a2dbc2e4beed5"}, + {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:184565012b60405d93838167f425713180b949e9d8dd0bbc7b49f074407c5a8b"}, + {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a75879bacf2c987c003368cf14bed0ffe99e8e85acfa6c0bfffc21a090f16880"}, + {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-win32.whl", hash = "sha256:84b554931e932c46f94ab306913ad7e11bba988104c5cff26d90d03f68258cd5"}, + {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-win_amd64.whl", hash = "sha256:25ac8c08322002b06fa1d49d1646181f0b2c72f5cbc15a85e80b4c30a544bb15"}, + {file = "ruamel.yaml.clib-0.2.8.tar.gz", hash = "sha256:beb2e0404003de9a4cab9753a8805a8fe9320ee6673136ed7f04255fe60bb512"}, +] + +[[package]] +name = "s3transfer" +version = "0.10.1" +description = "An Amazon S3 Transfer Manager" +optional = false +python-versions = ">= 3.8" +files = [ + {file = "s3transfer-0.10.1-py3-none-any.whl", hash = "sha256:ceb252b11bcf87080fb7850a224fb6e05c8a776bab8f2b64b7f25b969464839d"}, + {file = "s3transfer-0.10.1.tar.gz", hash = "sha256:5683916b4c724f799e600f41dd9e10a9ff19871bf87623cc8f491cb4f5fa0a19"}, +] + +[package.dependencies] +botocore = ">=1.33.2,<2.0a.0" + +[package.extras] +crt = ["botocore[crt] (>=1.33.2,<2.0a.0)"] + +[[package]] +name = "six" +version = "1.16.0" +description = "Python 2 and 3 compatibility utilities" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +files = [ + {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, + {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, +] + +[[package]] +name = "soupsieve" +version = "2.5" +description = "A modern CSS selector implementation for Beautiful Soup." +optional = false +python-versions = ">=3.8" +files = [ + {file = "soupsieve-2.5-py3-none-any.whl", hash = "sha256:eaa337ff55a1579b6549dc679565eac1e3d000563bcb1c8ab0d0fefbc0c2cdc7"}, + {file = "soupsieve-2.5.tar.gz", hash = "sha256:5663d5a7b3bfaeee0bc4372e7fc48f9cff4940b3eec54a6451cc5299f1097690"}, +] + +[[package]] +name = "typing-extensions" +version = "4.10.0" +description = "Backported and Experimental Type Hints for Python 3.8+" +optional = false +python-versions = ">=3.8" +files = [ + {file = "typing_extensions-4.10.0-py3-none-any.whl", hash = "sha256:69b1a937c3a517342112fb4c6df7e72fc39a38e7891a5730ed4985b5214b5475"}, + {file = "typing_extensions-4.10.0.tar.gz", hash = "sha256:b0abd7c89e8fb96f98db18d86106ff1d90ab692004eb746cf6eda2682f91b3cb"}, +] + +[[package]] +name = "tzdata" +version = "2024.1" +description = "Provider of IANA time zone data" +optional = false +python-versions = ">=2" +files = [ + {file = "tzdata-2024.1-py2.py3-none-any.whl", hash = "sha256:9068bc196136463f5245e51efda838afa15aaeca9903f49050dfa2679db4d252"}, + {file = "tzdata-2024.1.tar.gz", hash = "sha256:2674120f8d891909751c38abcdfd386ac0a5a1127954fbc332af6b5ceae07efd"}, +] + +[[package]] +name = "urllib3" +version = "2.2.1" +description = "HTTP library with thread-safe connection pooling, file post, and more." +optional = false +python-versions = ">=3.8" +files = [ + {file = "urllib3-2.2.1-py3-none-any.whl", hash = "sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d"}, + {file = "urllib3-2.2.1.tar.gz", hash = "sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19"}, +] + +[package.extras] +brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] +h2 = ["h2 (>=4,<5)"] +socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] +zstd = ["zstandard (>=0.18.0)"] + +[[package]] +name = "v2-samplesheet-maker" +version = "4.2.4.post20240305101119" +description = "v2 SampleSheet maker" +optional = false +python-versions = ">=3.10" +files = [ + {file = "v2_samplesheet_maker-4.2.4.post20240305101119-py3-none-any.whl", hash = "sha256:c07ac4d64a7a75965dc6d97151be6900f73aafe869949f9b6b847a3d627298ef"}, + {file = "v2_samplesheet_maker-4.2.4.post20240305101119.tar.gz", hash = "sha256:c54788f2c79c4773c91ee3e2e80fdb7fee602d4a60352bc52a3174b915efa9e7"}, +] + +[package.dependencies] +docopt = ">=0.6.2,<1" +pandas = ">=2.1.2,<3" +pydantic = ">=2.4.2,<3" +verboselogs = ">=1.7,<2" +xmltodict = ">=0.12.0,<1" + +[package.extras] +build = ["build"] +deploy = ["twine"] +test = ["pytest", "pytest-cov"] +toml = ["tomli-w (>=1.0.0,<2)"] + +[[package]] +name = "verboselogs" +version = "1.7" +description = "Verbose logging level for Python's logging module" +optional = false +python-versions = "*" +files = [ + {file = "verboselogs-1.7-py2.py3-none-any.whl", hash = "sha256:d63f23bf568295b95d3530c6864a0b580cec70e7ff974177dead1e4ffbc6ff49"}, + {file = "verboselogs-1.7.tar.gz", hash = "sha256:e33ddedcdfdafcb3a174701150430b11b46ceb64c2a9a26198c76a156568e427"}, +] + +[[package]] +name = "websocket-client" +version = "1.7.0" +description = "WebSocket client for Python with low level API options" +optional = false +python-versions = ">=3.8" +files = [ + {file = "websocket-client-1.7.0.tar.gz", hash = "sha256:10e511ea3a8c744631d3bd77e61eb17ed09304c413ad42cf6ddfa4c7787e8fe6"}, + {file = "websocket_client-1.7.0-py3-none-any.whl", hash = "sha256:f4c3d22fec12a2461427a29957ff07d35098ee2d976d3ba244e688b8b4057588"}, +] + +[package.extras] +docs = ["Sphinx (>=6.0)", "sphinx-rtd-theme (>=1.1.0)"] +optional = ["python-socks", "wsaccel"] +test = ["websockets"] + +[[package]] +name = "wrapica" +version = "1.0.3" +description = "Secondary level functions for ICAv2 based off libica" +optional = false +python-versions = ">=3.11" +files = [ + {file = "wrapica-1.0.3-py3-none-any.whl", hash = "sha256:87b57d517caf7dc261cee437486777d899deda80a66f130465b8c0b0130d95f5"}, + {file = "wrapica-1.0.3.tar.gz", hash = "sha256:fa293627aac30d333a5c1e786d70cfb7884ec765757c4cc4bd1e30f63b050dee"}, +] + +[package.dependencies] +beautifulsoup4 = ">=4.10.0,<5" +libica = ">=2.4.0,<3" +PyJWT = ">=2.8.0,<3" +"ruamel.base" = ">=1.0.0,<2" +"ruamel.yaml" = ">=0.18.0,<0.19" +verboselogs = ">=1.7,<2" +websocket-client = ">=1.4.2,<2" + +[package.extras] +build = ["build"] +docs = ["sphinx (>=7.2.6,<8)", "sphinx-autodoc-typehints", "sphinx-rtd-theme (>=2.0.0,<3)", "toml-to-requirements"] +test = ["pytest", "pytest-mock"] +toml = ["tomli-w (>=1.0.0,<2)"] + +[[package]] +name = "xmltodict" +version = "0.13.0" +description = "Makes working with XML feel like you are working with JSON" +optional = false +python-versions = ">=3.4" +files = [ + {file = "xmltodict-0.13.0-py2.py3-none-any.whl", hash = "sha256:aa89e8fd76320154a40d19a0df04a4695fb9dc5ba977cbb68ab3e4eb225e7852"}, + {file = "xmltodict-0.13.0.tar.gz", hash = "sha256:341595a488e3e01a85a9d8911d8912fd922ede5fecc4dce437eb4b6c8d037e56"}, +] + +[metadata] +lock-version = "2.0" +python-versions = "^3.11" +content-hash = "e501ed3c450d2b41879a2798d3f9864c374f58f2b39425957838394341e4ae35" diff --git a/lib/workload/stateless/bs_runs_upload_manager/layers/pyproject.toml b/lib/workload/stateless/bs_runs_upload_manager/layers/pyproject.toml new file mode 100644 index 000000000..b3b0310c7 --- /dev/null +++ b/lib/workload/stateless/bs_runs_upload_manager/layers/pyproject.toml @@ -0,0 +1,38 @@ +[build-system] +requires = ["poetry-core>=1.0.0"] +build-backend = "poetry.core.masonry.api" + +[tool.poetry] +name = "bs_runs_upload_manager_tools" +version = "0.0.1" +description = "BSSH Manager Lambda Layers" +license = "GPL-3.0-or-later" +authors = [ + "Alexis Lucattini" +] +homepage = "https://github.com/umccr/orcabus" +repository = "https://github.com/umccr/orcabus" + +[tool.poetry.dependencies] +python = "^3.11" +libica = "^2.3.0" +boto3 = "^1.28" +botocore = "^1.31" +verboselogs = "^1.7" +aws_requests_auth = "^0.4.3" +xmltodict = "^0.13.0" +pandas = "^2.2.0" +v2_samplesheet_maker = "^4.2.4" +wrapica = ">=1.0.0" + +[tool.poetry.group.dev] +optional = true + +[tool.poetry.group.dev.dependencies] +pyarrow = "^15.0.0" # Pandas throws a warning if this is not installed +pytest = "^7.0.0" # For testing only +# For typehinting only, not required at runtime +mypy-boto3-ssm = "^1.34" +mypy-boto3-secretsmanager = "^1.34" +mypy-boto3-stepfunctions = "^1.34" +mypy-boto3-s3 = "^1.34" \ No newline at end of file diff --git a/lib/workload/stateless/bs_runs_upload_manager/layers/src/bs_runs_upload_manager_tools/__init__.py b/lib/workload/stateless/bs_runs_upload_manager/layers/src/bs_runs_upload_manager_tools/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/lib/workload/stateless/bs_runs_upload_manager/layers/src/bs_runs_upload_manager_tools/utils/__init__.py b/lib/workload/stateless/bs_runs_upload_manager/layers/src/bs_runs_upload_manager_tools/utils/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/lib/workload/stateless/bs_runs_upload_manager/layers/src/bs_runs_upload_manager_tools/utils/aws_s3_helpers.py b/lib/workload/stateless/bs_runs_upload_manager/layers/src/bs_runs_upload_manager_tools/utils/aws_s3_helpers.py new file mode 100644 index 000000000..59f6d2c7a --- /dev/null +++ b/lib/workload/stateless/bs_runs_upload_manager/layers/src/bs_runs_upload_manager_tools/utils/aws_s3_helpers.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python3 + +""" + +""" + +import boto3 +from pathlib import Path +import typing + +from boto3.s3.transfer import S3Transfer + +if typing.TYPE_CHECKING: + from mypy_boto3_s3 import S3Client + + +def get_s3_client( + aws_access_key_id: str, + aws_secret_access_key: str, + aws_session_token: str +) -> 'S3Client': + return boto3.client( + 's3', + aws_access_key_id=aws_access_key_id, + aws_secret_access_key=aws_secret_access_key, + aws_session_token=aws_session_token + ) + + +def upload_file_to_s3( + local_path: Path, + access_key_id: str, + secret_access_key: str, + session_token: str, + bucket_name: str, + key_prefix: str +): + # Create an S3 client + s3_client: S3Client = get_s3_client( + access_key_id, + secret_access_key, + session_token + ) + + # Transfer file with upload + transfer = S3Transfer(s3_client) + + transfer.upload_file( + filename=local_path, + bucket=bucket_name, + key=key_prefix, + extra_args={'ServerSideEncryption': "AES256"} + ) diff --git a/lib/workload/stateless/bs_runs_upload_manager/layers/src/bs_runs_upload_manager_tools/utils/aws_secrets_manager_helpers.py b/lib/workload/stateless/bs_runs_upload_manager/layers/src/bs_runs_upload_manager_tools/utils/aws_secrets_manager_helpers.py new file mode 100644 index 000000000..db2dec0d3 --- /dev/null +++ b/lib/workload/stateless/bs_runs_upload_manager/layers/src/bs_runs_upload_manager_tools/utils/aws_secrets_manager_helpers.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python3 + +""" +Tools to handle secrets manager in AWS +""" + +import typing +import boto3 +import logging + +if typing.TYPE_CHECKING: + from mypy_boto3_secretsmanager import (SecretsManagerClient) + +# Set up logging +logging.basicConfig(level=logging.INFO) +logger = logging.getLogger(__name__) + + +def get_secrets_manager_client() -> 'SecretsManagerClient': + return boto3.client('secretsmanager') + + +def get_secret_string(secret_id: str) -> str: + client: SecretsManagerClient = get_secrets_manager_client() + + response = client.get_secret_value(SecretId=str(secret_id)) + + return response['SecretString'] diff --git a/lib/workload/stateless/bs_runs_upload_manager/layers/src/bs_runs_upload_manager_tools/utils/gds_helpers.py b/lib/workload/stateless/bs_runs_upload_manager/layers/src/bs_runs_upload_manager_tools/utils/gds_helpers.py new file mode 100644 index 000000000..f605adc0e --- /dev/null +++ b/lib/workload/stateless/bs_runs_upload_manager/layers/src/bs_runs_upload_manager_tools/utils/gds_helpers.py @@ -0,0 +1,112 @@ +#!/usr/bin/env python3 + +""" + +""" +from pathlib import Path +from urllib.parse import urlparse + +from libica.openapi.libgds import ( + ApiClient, FilesApi, CreateFileRequest, ApiException, FileWriteableResponse, ObjectStoreAccess, FileResponse +) + +import logging + + +logging.basicConfig(level=logging.INFO) + +logger = logging.getLogger(__name__) + + +def get_file_obj_from_file_path(gds_path: str) -> FileResponse: + from .ica_config_helpers import get_ica_gds_configuration + + with ApiClient(get_ica_gds_configuration()) as api_client: + # Create an instance of the API class + api_instance = FilesApi(api_client) + + try: + # Get file entry in GDS + api_response = api_instance.list_files( + volume_name=[urlparse(gds_path).netloc], + path=[str(Path(urlparse(gds_path).path))], + recursive=False, + include="PresignedUrl" + ) + + except ApiException as e: + logger.error("Exception when calling FilesApi->get_file_by_path: %s\n" % e) + raise e + + if not len(api_response.items) == 1: + raise ValueError(f"File not found: {gds_path}") + + return api_response.items[0] + + +def get_new_file_access_credentials(gds_path: str) -> ObjectStoreAccess: + from .ica_config_helpers import get_ica_gds_configuration + + with ApiClient(get_ica_gds_configuration()) as api_client: + # Create an instance of the API class + api_instance = FilesApi(api_client) + + body = CreateFileRequest( + name=Path(urlparse(gds_path).path).name, + volume_name=urlparse(gds_path).netloc, + folder_path=str(Path(urlparse(gds_path).path).parent) + "/", + type="text/plain" + ) # CreateFileRequest | + include = 'ObjectStoreAccess' # str | Optionally include additional fields in the response. Possible values: ObjectStoreAccess (optional) + + try: + # Create a file entry in GDS and get temporary credentials for upload + api_response: FileWriteableResponse = api_instance.create_file(body, include=include) + except ApiException as e: + logger.error("Exception when calling FilesApi->create_file: %s\n" % e) + raise e + + return api_response.object_store_access + + +def upload_file_to_gds(local_path: Path, gds_path: str): + from .aws_s3_helpers import upload_file_to_s3 + + access_credentials: ObjectStoreAccess = get_new_file_access_credentials(gds_path) + access_key_id = access_credentials.aws_s3_temporary_upload_credentials.access_key_id + secret_access_key = access_credentials.aws_s3_temporary_upload_credentials.secret_access_key + session_token = access_credentials.aws_s3_temporary_upload_credentials.session_token + bucket_name = access_credentials.aws_s3_temporary_upload_credentials.bucket_name + key_prefix = access_credentials.aws_s3_temporary_upload_credentials.key_prefix + + upload_file_to_s3( + local_path=local_path, + access_key_id=access_key_id, + secret_access_key=secret_access_key, + session_token=session_token, + bucket_name=bucket_name, + key_prefix=key_prefix + ) + + +def download_file_from_gds( + gds_path: str, + local_path: Path, +): + # Generate the presigned url + file_presigned_url = get_file_obj_from_file_path(gds_path).presigned_url + + # Download file from GDS using the requests library + import requests + with open(local_path, 'wb') as f_h: + f_h.write(requests.get(file_presigned_url).content) + + +# if __name__ == '__main__': +# os.environ["ICA_ACCESS_TOKEN_SECRET_ID"] = "IcaSecretsPortal" +# os.environ["ICA_BASE_URL"] = "https://aps2.platform.illumina.com" +# set_ica_env_vars() +# download_file_from_gds( +# "gds://development/temp/alexis/_tags.json", +# Path("foo.txt") +# ) diff --git a/lib/workload/stateless/bs_runs_upload_manager/layers/src/bs_runs_upload_manager_tools/utils/ica_config_helpers.py b/lib/workload/stateless/bs_runs_upload_manager/layers/src/bs_runs_upload_manager_tools/utils/ica_config_helpers.py new file mode 100644 index 000000000..dc6282218 --- /dev/null +++ b/lib/workload/stateless/bs_runs_upload_manager/layers/src/bs_runs_upload_manager_tools/utils/ica_config_helpers.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python + +""" +Set environment variables by collecting secrets from AWS Secrets Manager + +The secret ids should be in the environment + +""" + +import os +import logging + +from .aws_secrets_manager_helpers import get_secret_string + + +logging.basicConfig(level=logging.INFO) + +logger = logging.getLogger(__name__) + + +def set_ica_env_vars(): + os.environ["ICA_BASE_URL"] = os.environ.get("ICA_BASE_URL", "https://aps2.platform.illumina.com") + os.environ["ICA_ACCESS_TOKEN"] = get_ica_access_token_from_aws_secrets_manager() + + +def get_ica_access_token_from_aws_secrets_manager(): + secret_id = os.environ.get("ICA_ACCESS_TOKEN_SECRET_ID", None) + + if secret_id is None: + logger.error("ICA_ACCESS_TOKEN_SECRET_ID env var is not set") + raise EnvironmentError + + return get_secret_string(secret_id) + + +def get_ica_tes_configuration(): + from libica.openapi.libtes import Configuration + return Configuration( + host=os.environ.get("ICA_BASE_URL"), + api_key_prefix={ + "Authorization": "Bearer" + }, + api_key={ + "Authorization": os.environ.get("ICA_ACCESS_TOKEN") + } + ) + + +def get_ica_gds_configuration(): + from libica.openapi.libgds import Configuration + return Configuration( + host=os.environ.get("ICA_BASE_URL"), + api_key={ + "Authorization": os.environ.get("ICA_ACCESS_TOKEN") + }, + api_key_prefix={ + "Authorization": "Bearer" + } + ) diff --git a/lib/workload/stateless/bs_runs_upload_manager/layers/src/bs_runs_upload_manager_tools/utils/portal_helpers.py b/lib/workload/stateless/bs_runs_upload_manager/layers/src/bs_runs_upload_manager_tools/utils/portal_helpers.py new file mode 100644 index 000000000..7c3453675 --- /dev/null +++ b/lib/workload/stateless/bs_runs_upload_manager/layers/src/bs_runs_upload_manager_tools/utils/portal_helpers.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python +import os + +from bs_runs_upload_manager_tools.utils.aws_secrets_manager_helpers import get_secret_string + +import logging +logging.basicConfig(level=logging.INFO) + +logger = logging.getLogger(__name__) + + +def set_portal_token(): + os.environ["PORTAL_TOKEN"] = get_portal_token_from_aws_secrets_manager() + + +def get_portal_token_from_aws_secrets_manager(): + secret_id = os.environ.get("PORTAL_TOKEN_SECRET_ID", None) + + if secret_id is None: + logger.error("PORTAL_TOKEN_SECRET_ID env var is not set") + raise EnvironmentError + + return get_secret_string(secret_id) + + +def get_api_url(): + return os.environ.get("API_URL", "https://api.sscheck.dev.umccr.org") + + diff --git a/lib/workload/stateless/bs_runs_upload_manager/layers/src/bs_runs_upload_manager_tools/utils/samplesheet_helpers.py b/lib/workload/stateless/bs_runs_upload_manager/layers/src/bs_runs_upload_manager_tools/utils/samplesheet_helpers.py new file mode 100644 index 000000000..b0bd6da32 --- /dev/null +++ b/lib/workload/stateless/bs_runs_upload_manager/layers/src/bs_runs_upload_manager_tools/utils/samplesheet_helpers.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python3 + +""" +Generate samplesheet +""" +from pathlib import Path +import os +import requests +from tempfile import NamedTemporaryFile +import json + + +def generate_v2_samplesheet(v1_samplesheet_file: Path) -> Path: + """ + Generate a v2 samplesheet object + Returns: + + """ + from .portal_helpers import get_api_url + + get_api_url() + + headers = { + 'Authorization': f"Bearer {os.getenv('PORTAL_TOKEN', '')}", + } + + files = { + 'logLevel': (None, 'ERROR'), + 'file': open(v1_samplesheet_file, 'r'), + } + + response = requests.post( + url=get_api_url(), + headers=headers, + files=files + ) + + samplesheet_v2_path = Path(NamedTemporaryFile(prefix="SampleSheet", suffix=".csv", delete=False).name) + + with open(samplesheet_v2_path, 'wb') as f: + f.write(json.loads(response.text).get("v2_samplesheet_str").encode()) + + return samplesheet_v2_path diff --git a/lib/workload/stateless/bs_runs_upload_manager/layers/src/bs_runs_upload_manager_tools/utils/tes_helpers.py b/lib/workload/stateless/bs_runs_upload_manager/layers/src/bs_runs_upload_manager_tools/utils/tes_helpers.py new file mode 100644 index 000000000..4fe45c610 --- /dev/null +++ b/lib/workload/stateless/bs_runs_upload_manager/layers/src/bs_runs_upload_manager_tools/utils/tes_helpers.py @@ -0,0 +1,93 @@ +#!/usr/bin/env python3 + +""" +Launch tes task +""" +import json +from typing import Dict + +from libica.openapi.libtes import ( + ApiClient, TaskRunsApi, CreateTaskRunRequest, ApiException, TaskRun +) + +import logging +logging.basicConfig(level=logging.INFO) + +logger = logging.getLogger(__name__) + + +def get_bs_runs_upload_tes_template_json() -> str: + return """ + {{ + "name": "orcabus__automated_gds_bs_transfer_{__EXPERIMENT_NAME__}", + "execution": {{ + "image": {{ + "name": "ghcr.io/umccr/bssh-cli", + "tag": "1.5.4" + }}, + "command": "bash", + "args": [ + "-c", + "BASESPACE_API_SERVER=\\"${{SECURE_BASESPACE_API_SERVER}}\\" BASESPACE_ACCESS_TOKEN=\\"${{SECURE_BASESPACE_ACCESS_TOKEN}}\\" bs runs upload --verbose --samplesheet {__SAMPLESHEET_NAME__} /mount/mount/media/inputs/{__INPUT_RUN_NAME__} --name {__EXPERIMENT_NAME__} --instrument {__INSTRUMENT__}" + ], + "inputs": [ + {{ + "mode": "stream", + "type": "Folder", + "url": "{__INPUT_RUN_GDS_PATH__}", + "path": "/mount/mount/media/inputs/{__INPUT_RUN_NAME__}" + }} + ], + "outputs": [], + "systemFiles": {{ + "url": "{__GDS_SYSTEM_FILES_PATH__}" + }}, + "environment": {{ + "variables": {{ + "SECURE_BASESPACE_API_SERVER": "{__BASESPACE_API_SERVER__}", + "SECURE_BASESPACE_ACCESS_TOKEN": "{__BASESPACE_ACCESS_TOKEN__}" + }}, + "resources": {{ + "type": "standardhicpu", + "size": "medium" + }} + }}, + "retryLimit": 0 + }} + }} + """ + + +def populate_bs_runs_upload_template(**kwargs) -> Dict: + return json.loads( + get_bs_runs_upload_tes_template_json().format( + **kwargs, + ) + ) + + +def launch_tes_task( + tes_launch_json: Dict +) -> TaskRun: + """ + Launch TES task + """ + from .ica_config_helpers import get_ica_tes_configuration + + with ApiClient(get_ica_tes_configuration()) as api_client: + # Create an instance of the API class + api_instance = TaskRunsApi(api_client) + body = CreateTaskRunRequest( + **tes_launch_json + ) # CreateTaskRunRequest | (optional) + + try: + # Create and launch a task run + api_response = api_instance.create_task_run(body=body) + except ApiException as e: + logger.error("Exception when calling TaskRunsApi->create_task_run: %s\n" % e) + raise e + + return api_response + + diff --git a/lib/workload/stateless/bs_runs_upload_manager/step_functions_templates/bs_runs_upload_step_functions_template.json b/lib/workload/stateless/bs_runs_upload_manager/step_functions_templates/bs_runs_upload_step_functions_template.json new file mode 100644 index 000000000..a9a5c0df3 --- /dev/null +++ b/lib/workload/stateless/bs_runs_upload_manager/step_functions_templates/bs_runs_upload_step_functions_template.json @@ -0,0 +1,77 @@ +{ + "Comment": "A description of my state machine", + "StartAt": "move_workflow_inputs", + "States": { + "move_workflow_inputs": { + "Type": "Pass", + "Next": "upload_v2_samplesheet_to_gds_bssh", + "Parameters": { + "workflow_inputs.$": "$" + } + }, + "upload_v2_samplesheet_to_gds_bssh": { + "Type": "Task", + "Resource": "arn:aws:states:::lambda:invoke", + "ResultPath": "$.upload_v2_samplesheet_to_gds_bssh_step", + "Parameters": { + "FunctionName": "${__upload_v2_samplesheet_to_gds_bssh_function_arn__}", + "Payload": { + "gds_folder_path.$": "$.workflow_inputs.gdsFolderPath", + "gds_volume_name.$": "$.workflow_inputs.gdsVolumeName", + "samplesheet_name.$": "$.workflow_inputs.sampleSheetName" + } + }, + "Retry": [ + { + "ErrorEquals": [ + "Lambda.ServiceException", + "Lambda.AWSLambdaException", + "Lambda.SdkClientException", + "Lambda.TooManyRequestsException" + ], + "IntervalSeconds": 1, + "MaxAttempts": 3, + "BackoffRate": 2 + } + ], + "Next": "launch_bs_runs_upload_tes", + "ResultSelector": { + "samplesheet_name.$": "$.Payload.samplesheet_name" + }, + "TimeoutSeconds": 60 + }, + "launch_bs_runs_upload_tes": { + "Type": "Task", + "Resource": "arn:aws:states:::lambda:invoke", + "ResultPath": "$.launch_bs_runs_upload_tes_step", + "Parameters": { + "FunctionName": "${__launch_bs_runs_upload_tes_function_arn__}", + "Payload": { + "gds_folder_path.$": "$.workflow_inputs.gds_folder_path", + "gds_volume_name.$": "$.workflow_inputs.gds_volume_name", + "samplesheet_name.$": "$.upload_v2_samplesheet_to_gds_bssh_step.samplesheet_name" + } + }, + "ResultSelector": { + "task_run_id.$": "$.Payload.task_run_id" + }, + "Retry": [ + { + "ErrorEquals": [ + "Lambda.ServiceException", + "Lambda.AWSLambdaException", + "Lambda.SdkClientException", + "Lambda.TooManyRequestsException" + ], + "IntervalSeconds": 1, + "MaxAttempts": 3, + "BackoffRate": 2 + } + ], + "Next": "Success" + }, + "Success": { + "Type": "Succeed" + } + } +} \ No newline at end of file From 4902a160e09a6e22e276136cfd692a87af8056f2 Mon Sep 17 00:00:00 2001 From: alexiswl <8197659+alexiswl@users.noreply.github.com> Date: Mon, 25 Mar 2024 15:09:01 +1100 Subject: [PATCH 02/16] Update ReadMe TOC --- lib/workload/stateless/bs_runs_upload_manager/Readme.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/workload/stateless/bs_runs_upload_manager/Readme.md b/lib/workload/stateless/bs_runs_upload_manager/Readme.md index fc2bbfe9e..c31e898fc 100644 --- a/lib/workload/stateless/bs_runs_upload_manager/Readme.md +++ b/lib/workload/stateless/bs_runs_upload_manager/Readme.md @@ -3,6 +3,11 @@ * [BS Runs Upload Manager](#bs-runs-upload-manager) * [Summary](#summary) + * [Inputs](#inputs) + * [Example input](#example-input) + * [Lambdas in this directory](#lambdas-in-this-directory) + * [Upload V2 SampleSheet to GDS Bssh](#upload-v2-samplesheet-to-gds-bssh) + * [Launch BS Runs Upload Tes](#launch-bs-runs-upload-tes) ## Summary From 848f1395d05bba5456de80e5c716de284848a616 Mon Sep 17 00:00:00 2001 From: alexiswl <8197659+alexiswl@users.noreply.github.com> Date: Wed, 27 Mar 2024 12:39:49 +1100 Subject: [PATCH 03/16] Miscellaneous fixes to bs runs upload lambdas --- .../lambdas/launch_bs_runs_upload_tes/handler.py | 2 +- .../lambdas/upload_v2_samplesheet_to_gds_bssh/handler.py | 2 +- .../bs_runs_upload_step_functions_template.json | 7 ++++--- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/workload/stateless/bs_runs_upload_manager/lambdas/launch_bs_runs_upload_tes/handler.py b/lib/workload/stateless/bs_runs_upload_manager/lambdas/launch_bs_runs_upload_tes/handler.py index 9694034f6..e35278b28 100644 --- a/lib/workload/stateless/bs_runs_upload_manager/lambdas/launch_bs_runs_upload_tes/handler.py +++ b/lib/workload/stateless/bs_runs_upload_manager/lambdas/launch_bs_runs_upload_tes/handler.py @@ -76,7 +76,7 @@ def handler(event, context): "instrument_run_id" ]: assert ( - event.get(event_key), + event.get(event_key, None) is not None, f"{event_key} key is not set in the event" ) diff --git a/lib/workload/stateless/bs_runs_upload_manager/lambdas/upload_v2_samplesheet_to_gds_bssh/handler.py b/lib/workload/stateless/bs_runs_upload_manager/lambdas/upload_v2_samplesheet_to_gds_bssh/handler.py index 5d58fc035..f3cdf43bd 100644 --- a/lib/workload/stateless/bs_runs_upload_manager/lambdas/upload_v2_samplesheet_to_gds_bssh/handler.py +++ b/lib/workload/stateless/bs_runs_upload_manager/lambdas/upload_v2_samplesheet_to_gds_bssh/handler.py @@ -82,7 +82,7 @@ def handler(event, context): ) # Get current time - timestamp = datetime.now(timezone.utc).timestamp() + timestamp = str(int(datetime.now(timezone.utc).timestamp())) samplesheet_name = f"SampleSheet.V2.{timestamp}.csv" diff --git a/lib/workload/stateless/bs_runs_upload_manager/step_functions_templates/bs_runs_upload_step_functions_template.json b/lib/workload/stateless/bs_runs_upload_manager/step_functions_templates/bs_runs_upload_step_functions_template.json index a9a5c0df3..73cc4be7c 100644 --- a/lib/workload/stateless/bs_runs_upload_manager/step_functions_templates/bs_runs_upload_step_functions_template.json +++ b/lib/workload/stateless/bs_runs_upload_manager/step_functions_templates/bs_runs_upload_step_functions_template.json @@ -47,9 +47,10 @@ "Parameters": { "FunctionName": "${__launch_bs_runs_upload_tes_function_arn__}", "Payload": { - "gds_folder_path.$": "$.workflow_inputs.gds_folder_path", - "gds_volume_name.$": "$.workflow_inputs.gds_volume_name", - "samplesheet_name.$": "$.upload_v2_samplesheet_to_gds_bssh_step.samplesheet_name" + "gds_folder_path.$": "$.workflow_inputs.gdsFolderPath", + "gds_volume_name.$": "$.workflow_inputs.gdsVolumeName", + "samplesheet_name.$": "$.upload_v2_samplesheet_to_gds_bssh_step.samplesheet_name", + "instrument_run_id.$": "$.workflow_inputs.instrumentRunId" } }, "ResultSelector": { From fbdc220619b92a3d72d9d26227c762d95ca81ae4 Mon Sep 17 00:00:00 2001 From: Alexis Lucattini Date: Tue, 16 Apr 2024 10:28:48 +1000 Subject: [PATCH 04/16] Generate stack objects before construct Use jwt portal token from secrets maanger --- .../bs_runs_upload_manager/Readme.md | 2 +- .../deploy/bin/deploy.ts | 10 +- .../deploy/constants.ts | 5 + .../bs_runs_upload_manager_stack.ts | 92 +++++++++---------- .../stacks/bs_runs_upload_manager_stack.ts | 56 ++++++++++- .../utils/portal_helpers.py | 6 +- 6 files changed, 112 insertions(+), 59 deletions(-) diff --git a/lib/workload/stateless/bs_runs_upload_manager/Readme.md b/lib/workload/stateless/bs_runs_upload_manager/Readme.md index c31e898fc..e8250914c 100644 --- a/lib/workload/stateless/bs_runs_upload_manager/Readme.md +++ b/lib/workload/stateless/bs_runs_upload_manager/Readme.md @@ -59,7 +59,7 @@ This uses the ssbackend API in order to generate the V2 samplesheet since some m { "gds_folder_path": "/Runs/240315_A01052_0186_AH5HM5DSXC_r.YpC_0U_7-06Oom1cFl9Y5A", "gds_volume_name": "bssh.acddbfda498038ed99fa94fe79523959", - "samplesheet_name": "SampleSheet.csv", + "samplesheet_name": "SampleSheet.csv" } ``` diff --git a/lib/workload/stateless/bs_runs_upload_manager/deploy/bin/deploy.ts b/lib/workload/stateless/bs_runs_upload_manager/deploy/bin/deploy.ts index 9ca63e52d..1dbfd7582 100644 --- a/lib/workload/stateless/bs_runs_upload_manager/deploy/bin/deploy.ts +++ b/lib/workload/stateless/bs_runs_upload_manager/deploy/bin/deploy.ts @@ -2,14 +2,22 @@ import 'source-map-support/register'; import * as cdk from 'aws-cdk-lib'; import { BsRunsUploadManagerStack } from '../lib/stacks/bs_runs_upload_manager_stack'; -import { GDS_DEV_TEMP_PATH, ICA_TOKEN_SECRET_ID } from '../constants'; +import { + BASESPACE_TOKEN_SECRET_ID, EVENTBUS_NAME_SSM_PARAMETER_PATH, + GDS_DEV_TEMP_PATH, + ICA_TOKEN_SECRET_ID, + PORTAL_TOKEN_SECRET_ID, +} from '../constants'; const app = new cdk.App(); new BsRunsUploadManagerStack( app, 'BsRunsUploadManagerStack', { + basespace_token_secret_id: BASESPACE_TOKEN_SECRET_ID, // BaseSpaceAccessTokenSecret + eventbus_name_ssm_parameter_path: EVENTBUS_NAME_SSM_PARAMETER_PATH, // /umccr/orcabus/stateful/eventbridge ica_token_secret_id: ICA_TOKEN_SECRET_ID, // ICASecretsPortal + portal_token_secret_id: PORTAL_TOKEN_SECRET_ID, // orcabus/token-service-jwt gds_system_files_path: GDS_DEV_TEMP_PATH, // gds://development/primary_data/temp/bs_runs_upload_tes/ env: { account: process.env.CDK_DEFAULT_ACCOUNT, diff --git a/lib/workload/stateless/bs_runs_upload_manager/deploy/constants.ts b/lib/workload/stateless/bs_runs_upload_manager/deploy/constants.ts index ab88f5a04..7adbabbea 100644 --- a/lib/workload/stateless/bs_runs_upload_manager/deploy/constants.ts +++ b/lib/workload/stateless/bs_runs_upload_manager/deploy/constants.ts @@ -1,3 +1,8 @@ export const ICA_TOKEN_SECRET_ID = 'IcaSecretsPortal' +export const PORTAL_TOKEN_SECRET_ID = 'orcabus/token-service-jwt' + +export const BASESPACE_TOKEN_SECRET_ID = 'BaseSpaceAccessTokenSecret' + +export const EVENTBUS_NAME_SSM_PARAMETER_PATH = '/umccr/orcabus/stateful/eventbridge' export const GDS_DEV_TEMP_PATH = 'gds://development/primary_data/temp/bs_runs_upload_tes/' \ No newline at end of file diff --git a/lib/workload/stateless/bs_runs_upload_manager/deploy/lib/constructs/bs_runs_upload_manager_stack.ts b/lib/workload/stateless/bs_runs_upload_manager/deploy/lib/constructs/bs_runs_upload_manager_stack.ts index 7ba0bb1b4..7b9e8cfbb 100644 --- a/lib/workload/stateless/bs_runs_upload_manager/deploy/lib/constructs/bs_runs_upload_manager_stack.ts +++ b/lib/workload/stateless/bs_runs_upload_manager/deploy/lib/constructs/bs_runs_upload_manager_stack.ts @@ -3,19 +3,26 @@ import { Construct } from 'constructs'; import * as lambda from 'aws-cdk-lib/aws-lambda'; import * as iam from 'aws-cdk-lib/aws-iam'; import * as sfn from 'aws-cdk-lib/aws-stepfunctions'; -import * as secretsManager from 'aws-cdk-lib/aws-secretsmanager'; +import * as events from 'aws-cdk-lib/aws-events'; import { DefinitionBody } from 'aws-cdk-lib/aws-stepfunctions'; - +import * as secretsManager from 'aws-cdk-lib/aws-secretsmanager'; import { PythonFunction } from '@aws-cdk/aws-lambda-python-alpha'; import { LambdaLayerConstruct } from './lambda_layer'; import { IRole } from 'aws-cdk-lib/aws-iam'; interface BsRunsUploadManagerConstructProps { - lambdas_layer_path: string; // __dirname + '/../../../layers + /* Stack objects */ + lambda_layer_obj: LambdaLayerConstruct, + ica_token_secret_obj: secretsManager.ISecret, + portal_token_secret_obj: secretsManager.ISecret, + basespace_secret_obj: secretsManager.ISecret, + event_bus_obj: events.IEventBus, + /* Lambda layer paths */ upload_v2_samplesheet_to_gds_bssh_lambda_path: string; // __dirname + '/../../../lambdas/upload_v2_samplesheet_to_gds_bssh' launch_bs_runs_upload_tes_lambda_path: string; // __dirname + '/../../../lambdas/launch_bs_runs_upload_tes' - ica_token_secret_id: string; // IcaSecretsPortal + /* Step function templates */ gds_system_files_path: string; // gds://development/primary_data/temp/bs_runs_upload_tes/ + /* Miscell */ workflow_definition_body_path: string; // __dirname + '/../../../step_functions_templates/bs_runs_upload_step_functions_template.json' } @@ -26,28 +33,6 @@ export class BsRunsUploadManagerConstruct extends Construct { constructor(scope: Construct, id: string, props: BsRunsUploadManagerConstructProps) { super(scope, id); - // Set lambda layer arn object - const lambda_layer = new LambdaLayerConstruct( - this, 'lambda_layer', { - layer_directory: props.lambdas_layer_path, - }); - - const ica_access_token_secret_obj = secretsManager.Secret.fromSecretNameV2( - this, 'IcaSecretsPortalSecretObject', - props.ica_token_secret_id, - ); - - const portal_secret_obj = secretsManager.Secret.fromSecretNameV2( - this, 'PortalSecret', - 'PortalSecret4BsshUploads', - ); // FIXME: This is a temp hack and has to be updated every half-hour - - const basespace_secret_obj = new secretsManager.Secret( - this, 'BaseSpaceAccessTokenSecret', - { - secretName: 'BaseSpaceAccessTokenSecret' - } - ) // V2 Upload lambda const upload_v2_samplesheet_to_gds_bssh_lambda = new PythonFunction(this, 'upload_v2_samplesheet_to_gds_bssh_lambda', { @@ -61,10 +46,10 @@ export class BsRunsUploadManagerConstruct extends Construct { // @ts-ignore timeout: Duration.seconds(60), environment: { - ICA_BASE_URL: "https://aps2.platform.illumina.com", - ICA_ACCESS_TOKEN_SECRET_ID: ica_access_token_secret_obj.secretName, - PORTAL_TOKEN_SECRET_ID: portal_secret_obj.secretName, - } + ICA_BASE_URL: 'https://aps2.platform.illumina.com', + ICA_ACCESS_TOKEN_SECRET_ID: props.ica_token_secret_obj.secretName, + PORTAL_TOKEN_SECRET_ID: props.portal_token_secret_obj.secretName, + }, }); // Launch BS Runs Upload TES lambda @@ -80,37 +65,42 @@ export class BsRunsUploadManagerConstruct extends Construct { // @ts-ignore timeout: Duration.seconds(60), environment: { - BASESPACE_API_SERVER: "https://api.aps2.sh.basespace.illumina.com", - BASESPACE_ACCESS_TOKEN_SECRET_ID: basespace_secret_obj.secretName, - ICA_BASE_URL: "https://aps2.platform.illumina.com", - ICA_ACCESS_TOKEN_SECRET_ID: ica_access_token_secret_obj.secretName, + BASESPACE_API_SERVER: 'https://api.aps2.sh.basespace.illumina.com', + BASESPACE_ACCESS_TOKEN_SECRET_ID: props.basespace_secret_obj.secretName, + ICA_BASE_URL: 'https://aps2.platform.illumina.com', + ICA_ACCESS_TOKEN_SECRET_ID: props.ica_token_secret_obj.secretName, GDS_SYSTEM_FILES_PATH: props.gds_system_files_path, - } - } - - ) + }, + }, + ); // Give the lambda permission to read the ICA ACCESS TOKEN secret - ica_access_token_secret_obj.grantRead( - // @ts-ignore - launch_bs_runs_upload_tes_lambda.role - ); - ica_access_token_secret_obj.grantRead( - // @ts-ignore - upload_v2_samplesheet_to_gds_bssh_lambda.role + [ + launch_bs_runs_upload_tes_lambda, + upload_v2_samplesheet_to_gds_bssh_lambda, + ].forEach( + (lambda_obj) => { + props.ica_token_secret_obj.grantRead( + // @ts-ignore + lambda_obj.role, + ); + props.portal_token_secret_obj.grantRead( + // @ts-ignore + lambda_obj.role, + ); + }, ); // Give the lambda permission to read the PORTAL TOKEN secret - // FIXME - remove once we have a better way of collecting the portal token - portal_secret_obj.grantRead( + props.portal_token_secret_obj.grantRead( // @ts-ignore - upload_v2_samplesheet_to_gds_bssh_lambda.role + upload_v2_samplesheet_to_gds_bssh_lambda.role, ); // Give basespace upload lambda permission to read the basespace access token secret - basespace_secret_obj.grantRead( + props.basespace_secret_obj.grantRead( // @ts-ignore - launch_bs_runs_upload_tes_lambda.role + launch_bs_runs_upload_tes_lambda.role, ); // Specify the statemachine and replace the arn placeholders with the lambda arns defined above @@ -138,7 +128,7 @@ export class BsRunsUploadManagerConstruct extends Construct { }, ), ); - + // Set outputs this.bs_runs_upload_event_state_machine_arn = stateMachine.stateMachineArn; } diff --git a/lib/workload/stateless/bs_runs_upload_manager/deploy/lib/stacks/bs_runs_upload_manager_stack.ts b/lib/workload/stateless/bs_runs_upload_manager/deploy/lib/stacks/bs_runs_upload_manager_stack.ts index e55e61e7a..810c3dde8 100644 --- a/lib/workload/stateless/bs_runs_upload_manager/deploy/lib/stacks/bs_runs_upload_manager_stack.ts +++ b/lib/workload/stateless/bs_runs_upload_manager/deploy/lib/stacks/bs_runs_upload_manager_stack.ts @@ -1,28 +1,78 @@ import * as cdk from 'aws-cdk-lib'; import { Construct } from 'constructs'; import { BsRunsUploadManagerConstruct } from '../constructs/bs_runs_upload_manager_stack'; +import { LambdaLayerConstruct } from '../constructs/lambda_layer'; +import * as secretsManager from 'aws-cdk-lib/aws-secretsmanager'; +import * as events from 'aws-cdk-lib/aws-events'; +import * as ssm from 'aws-cdk-lib/aws-ssm'; // import * as sqs from 'aws-cdk-lib/aws-sqs'; export interface BsRunsUploadManagerStackProps extends cdk.StackProps { // Define construct properties here ica_token_secret_id: string; // IcaSecretsPortal + portal_token_secret_id: string; // orcabus/token-service-jwt + basespace_token_secret_id: string; // BaseSpaceAccessTokenSecret gds_system_files_path: string; // gds://development/primary_data/temp/bs_runs_upload_tes/ + eventbus_name_ssm_parameter_path: string; // /umccr/orcabus/stateful/eventbridge } export class BsRunsUploadManagerStack extends cdk.Stack { constructor(scope: Construct, id: string, props: BsRunsUploadManagerStackProps) { super(scope, id, props); + + // Set lambda layer arn object + const lambda_layer_obj = new LambdaLayerConstruct( + this, 'lambda_layer', { + layer_directory: __dirname + '/../../../layers', + }); + + const ica_access_token_secret_obj = secretsManager.Secret.fromSecretNameV2( + this, 'IcaSecretsPortalSecretObject', + props.ica_token_secret_id, + ); + + const portal_secret_obj = secretsManager.Secret.fromSecretNameV2( + this, 'PortalSecret', + props.portal_token_secret_id, + ); + + const basespace_secret_obj = new secretsManager.Secret( + this, 'BaseSpaceAccessTokenSecret', + { + secretName: props.basespace_token_secret_id + } + ) + + /* Get event bus construct */ + const event_bus_name_str = ssm.StringParameter.fromStringParameterName( + this, + 'event_bus_name', + props.eventbus_name_ssm_parameter_path + ).stringValue; + const event_bus_obj = events.EventBus.fromEventBusName( + this, 'event_bus', + event_bus_name_str + ); + + new BsRunsUploadManagerConstruct( this, 'bs-runs-upload-manager', { - lambdas_layer_path: __dirname + '/../../../layers', + /* Stack objects */ + lambda_layer_obj: lambda_layer_obj, + ica_token_secret_obj: ica_access_token_secret_obj, + portal_token_secret_obj: portal_secret_obj, + basespace_secret_obj: basespace_secret_obj, + event_bus_obj: event_bus_obj, + /* Lambda paths */ upload_v2_samplesheet_to_gds_bssh_lambda_path: __dirname + '/../../../lambdas/upload_v2_samplesheet_to_gds_bssh', launch_bs_runs_upload_tes_lambda_path: __dirname + '/../../../lambdas/launch_bs_runs_upload_tes', - ica_token_secret_id: props.ica_token_secret_id, + /* Step functions templates */ + workflow_definition_body_path: __dirname + '/../../../step_functions_templates/bs_runs_upload_step_functions_template.json', + /* Miscell */ gds_system_files_path: props.gds_system_files_path, - workflow_definition_body_path: __dirname + '/../../../step_functions_templates/bs_runs_upload_step_functions_template.json' } ) } diff --git a/lib/workload/stateless/bs_runs_upload_manager/layers/src/bs_runs_upload_manager_tools/utils/portal_helpers.py b/lib/workload/stateless/bs_runs_upload_manager/layers/src/bs_runs_upload_manager_tools/utils/portal_helpers.py index 7c3453675..d0458939f 100644 --- a/lib/workload/stateless/bs_runs_upload_manager/layers/src/bs_runs_upload_manager_tools/utils/portal_helpers.py +++ b/lib/workload/stateless/bs_runs_upload_manager/layers/src/bs_runs_upload_manager_tools/utils/portal_helpers.py @@ -4,6 +4,8 @@ from bs_runs_upload_manager_tools.utils.aws_secrets_manager_helpers import get_secret_string import logging +import json + logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) @@ -20,10 +22,8 @@ def get_portal_token_from_aws_secrets_manager(): logger.error("PORTAL_TOKEN_SECRET_ID env var is not set") raise EnvironmentError - return get_secret_string(secret_id) + return json.loads(get_secret_string(secret_id))['id_token'] def get_api_url(): return os.environ.get("API_URL", "https://api.sscheck.dev.umccr.org") - - From ba56665a08f4b29122dab6d0efe7ebadba3153ce Mon Sep 17 00:00:00 2001 From: alexiswl <8197659+alexiswl@users.noreply.github.com> Date: Wed, 17 Apr 2024 16:41:06 +1000 Subject: [PATCH 05/16] Update bs constructs Remove bs access token from stage, new custom id --- .../deploy/bin/deploy.ts | 5 +++-- .../bs_runs_upload_manager/deploy/constants.ts | 4 ++-- .../constructs/bs_runs_upload_manager_stack.ts | 13 +++++++++++-- .../lib/stacks/bs_runs_upload_manager_stack.ts | 18 +++++------------- 4 files changed, 21 insertions(+), 19 deletions(-) diff --git a/lib/workload/stateless/bs_runs_upload_manager/deploy/bin/deploy.ts b/lib/workload/stateless/bs_runs_upload_manager/deploy/bin/deploy.ts index 1dbfd7582..b3239b4f2 100644 --- a/lib/workload/stateless/bs_runs_upload_manager/deploy/bin/deploy.ts +++ b/lib/workload/stateless/bs_runs_upload_manager/deploy/bin/deploy.ts @@ -3,7 +3,8 @@ import 'source-map-support/register'; import * as cdk from 'aws-cdk-lib'; import { BsRunsUploadManagerStack } from '../lib/stacks/bs_runs_upload_manager_stack'; import { - BASESPACE_TOKEN_SECRET_ID, EVENTBUS_NAME_SSM_PARAMETER_PATH, + BASESPACE_TOKEN_SECRET_ID, + EVENTBUS_NAME, GDS_DEV_TEMP_PATH, ICA_TOKEN_SECRET_ID, PORTAL_TOKEN_SECRET_ID, @@ -15,7 +16,7 @@ new BsRunsUploadManagerStack( 'BsRunsUploadManagerStack', { basespace_token_secret_id: BASESPACE_TOKEN_SECRET_ID, // BaseSpaceAccessTokenSecret - eventbus_name_ssm_parameter_path: EVENTBUS_NAME_SSM_PARAMETER_PATH, // /umccr/orcabus/stateful/eventbridge + eventbus_name: EVENTBUS_NAME, // OrcabusMain ica_token_secret_id: ICA_TOKEN_SECRET_ID, // ICASecretsPortal portal_token_secret_id: PORTAL_TOKEN_SECRET_ID, // orcabus/token-service-jwt gds_system_files_path: GDS_DEV_TEMP_PATH, // gds://development/primary_data/temp/bs_runs_upload_tes/ diff --git a/lib/workload/stateless/bs_runs_upload_manager/deploy/constants.ts b/lib/workload/stateless/bs_runs_upload_manager/deploy/constants.ts index 7adbabbea..05f8c4989 100644 --- a/lib/workload/stateless/bs_runs_upload_manager/deploy/constants.ts +++ b/lib/workload/stateless/bs_runs_upload_manager/deploy/constants.ts @@ -1,8 +1,8 @@ export const ICA_TOKEN_SECRET_ID = 'IcaSecretsPortal' export const PORTAL_TOKEN_SECRET_ID = 'orcabus/token-service-jwt' -export const BASESPACE_TOKEN_SECRET_ID = 'BaseSpaceAccessTokenSecret' +export const BASESPACE_TOKEN_SECRET_ID = '/manual/BaseSpaceAccessTokenSecret' -export const EVENTBUS_NAME_SSM_PARAMETER_PATH = '/umccr/orcabus/stateful/eventbridge' +export const EVENTBUS_NAME = 'OrcaBusMain' export const GDS_DEV_TEMP_PATH = 'gds://development/primary_data/temp/bs_runs_upload_tes/' \ No newline at end of file diff --git a/lib/workload/stateless/bs_runs_upload_manager/deploy/lib/constructs/bs_runs_upload_manager_stack.ts b/lib/workload/stateless/bs_runs_upload_manager/deploy/lib/constructs/bs_runs_upload_manager_stack.ts index 7b9e8cfbb..93685bb28 100644 --- a/lib/workload/stateless/bs_runs_upload_manager/deploy/lib/constructs/bs_runs_upload_manager_stack.ts +++ b/lib/workload/stateless/bs_runs_upload_manager/deploy/lib/constructs/bs_runs_upload_manager_stack.ts @@ -42,7 +42,7 @@ export class BsRunsUploadManagerConstruct extends Construct { handler: 'handler', memorySize: 1024, // @ts-ignore - layers: [lambda_layer.lambda_layer_version_obj], + layers: [props.lambda_layer_obj.lambda_layer_version_obj], // @ts-ignore timeout: Duration.seconds(60), environment: { @@ -61,7 +61,7 @@ export class BsRunsUploadManagerConstruct extends Construct { handler: 'handler', memorySize: 1024, // @ts-ignore - layers: [lambda_layer.lambda_layer_version_obj], + layers: [props.lambda_layer_obj.lambda_layer_version_obj], // @ts-ignore timeout: Duration.seconds(60), environment: { @@ -129,6 +129,15 @@ export class BsRunsUploadManagerConstruct extends Construct { ), ); + // Trigger state machine on event + const rule = new events.Rule(this, 'bs_runs_upload_event_rule', { + eventBus: props.event_bus_obj, + eventPattern: { + source: ['orcabus.srm'], + detailType: ['SequenceRunStateChange'], + }, + }); + // Set outputs this.bs_runs_upload_event_state_machine_arn = stateMachine.stateMachineArn; } diff --git a/lib/workload/stateless/bs_runs_upload_manager/deploy/lib/stacks/bs_runs_upload_manager_stack.ts b/lib/workload/stateless/bs_runs_upload_manager/deploy/lib/stacks/bs_runs_upload_manager_stack.ts index 810c3dde8..dc6845883 100644 --- a/lib/workload/stateless/bs_runs_upload_manager/deploy/lib/stacks/bs_runs_upload_manager_stack.ts +++ b/lib/workload/stateless/bs_runs_upload_manager/deploy/lib/stacks/bs_runs_upload_manager_stack.ts @@ -11,9 +11,9 @@ export interface BsRunsUploadManagerStackProps extends cdk.StackProps { // Define construct properties here ica_token_secret_id: string; // IcaSecretsPortal portal_token_secret_id: string; // orcabus/token-service-jwt - basespace_token_secret_id: string; // BaseSpaceAccessTokenSecret + basespace_token_secret_id: string; // /manual/BaseSpaceAccessTokenSecret gds_system_files_path: string; // gds://development/primary_data/temp/bs_runs_upload_tes/ - eventbus_name_ssm_parameter_path: string; // /umccr/orcabus/stateful/eventbridge + eventbus_name: string; // /umccr/orcabus/stateful/eventbridge } export class BsRunsUploadManagerStack extends cdk.Stack { @@ -37,22 +37,14 @@ export class BsRunsUploadManagerStack extends cdk.Stack { props.portal_token_secret_id, ); - const basespace_secret_obj = new secretsManager.Secret( + const basespace_secret_obj = secretsManager.Secret.fromSecretNameV2( this, 'BaseSpaceAccessTokenSecret', - { - secretName: props.basespace_token_secret_id - } + props.basespace_token_secret_id ) - /* Get event bus construct */ - const event_bus_name_str = ssm.StringParameter.fromStringParameterName( - this, - 'event_bus_name', - props.eventbus_name_ssm_parameter_path - ).stringValue; const event_bus_obj = events.EventBus.fromEventBusName( this, 'event_bus', - event_bus_name_str + props.eventbus_name ); From 6654e231aebe9d16b61fa6a5b0efcbde234acd04 Mon Sep 17 00:00:00 2001 From: alexiswl <8197659+alexiswl@users.noreply.github.com> Date: Wed, 17 Apr 2024 18:51:50 +1000 Subject: [PATCH 06/16] Added event target being the State Machine --- .../stateless/bs_runs_upload_manager/Readme.md | 16 +++++++++++++++- .../constructs/bs_runs_upload_manager_stack.ts | 11 +++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/lib/workload/stateless/bs_runs_upload_manager/Readme.md b/lib/workload/stateless/bs_runs_upload_manager/Readme.md index e8250914c..e582f6440 100644 --- a/lib/workload/stateless/bs_runs_upload_manager/Readme.md +++ b/lib/workload/stateless/bs_runs_upload_manager/Readme.md @@ -25,6 +25,8 @@ The two steps of the statemachine are: 1. Generate a V2 Samplesheet and reupload it 2. Launch an ICAv1 tes task that runs the bs runs upload command +This statemachine will subscribe to the orcabus.srm events and trigger the statemachine when a new run is detected. + ![](images/bs_runs_upload_manager.png) ## Inputs @@ -95,4 +97,16 @@ This lambda will launch a tes task that will run the bs runs upload command. { "task_run_id": "trn.4fd3414f98fe47c3a6cfc31a67b7418a" } -``` \ No newline at end of file +``` + +#### External parameters + +The following properites are required in order to deploy the statemachine / stack: + +* SecretsManager: + * ICA Access Token: `IcaSecretsPortal` + * Portal Token: `orcabus/token-service-jwt` + * BaseSpace Token Secret ID: `/manual/BaseSpaceAccessTokenSecret` +* Strings + * gds system files path root (where to do the TES logs go?) + * EventBus Name: `OrcabusMain` \ No newline at end of file diff --git a/lib/workload/stateless/bs_runs_upload_manager/deploy/lib/constructs/bs_runs_upload_manager_stack.ts b/lib/workload/stateless/bs_runs_upload_manager/deploy/lib/constructs/bs_runs_upload_manager_stack.ts index 93685bb28..e104beb11 100644 --- a/lib/workload/stateless/bs_runs_upload_manager/deploy/lib/constructs/bs_runs_upload_manager_stack.ts +++ b/lib/workload/stateless/bs_runs_upload_manager/deploy/lib/constructs/bs_runs_upload_manager_stack.ts @@ -4,6 +4,7 @@ import * as lambda from 'aws-cdk-lib/aws-lambda'; import * as iam from 'aws-cdk-lib/aws-iam'; import * as sfn from 'aws-cdk-lib/aws-stepfunctions'; import * as events from 'aws-cdk-lib/aws-events'; +import * as events_targets from 'aws-cdk-lib/aws-events-targets'; import { DefinitionBody } from 'aws-cdk-lib/aws-stepfunctions'; import * as secretsManager from 'aws-cdk-lib/aws-secretsmanager'; import { PythonFunction } from '@aws-cdk/aws-lambda-python-alpha'; @@ -138,6 +139,16 @@ export class BsRunsUploadManagerConstruct extends Construct { }, }); + // Add target of event to be the state machine + rule.addTarget( + new events_targets.SfnStateMachine( + stateMachine, + { + input: events.RuleTargetInput.fromEventPath('$.detail') + } + ) + ) + // Set outputs this.bs_runs_upload_event_state_machine_arn = stateMachine.stateMachineArn; } From 8507c6ce9f6415242af4167e604b217449037e35 Mon Sep 17 00:00:00 2001 From: alexiswl <8197659+alexiswl@users.noreply.github.com> Date: Thu, 18 Apr 2024 12:32:11 +1000 Subject: [PATCH 07/16] Added bsRunsManager uploader to configuration --- config/config.ts | 6 ++-- config/constants.ts | 4 +++ config/stacks/bsRunsUploadManager.ts | 34 +++++++++++++++++++ .../stacks/bs_runs_upload_manager_stack.ts | 4 ++- .../statelessStackCollectionClass.ts | 2 ++ 5 files changed, 47 insertions(+), 3 deletions(-) create mode 100644 config/stacks/bsRunsUploadManager.ts diff --git a/config/config.ts b/config/config.ts index 84dc9c60d..b691f5ae6 100644 --- a/config/config.ts +++ b/config/config.ts @@ -8,6 +8,7 @@ import { getPostgresManagerStackProps } from './stacks/postgresManager'; import { getMetadataManagerStackProps } from './stacks/metadataManager'; import { getSequenceRunManagerStackProps } from './stacks/sequenceRunManager'; import { getFileManagerStackProps } from './stacks/fileManager'; +import { getBsRunsUploadManagerStackProps } from './stacks/bsRunsUploadManager'; interface EnvironmentConfig { name: string; @@ -45,10 +46,10 @@ export const getEnvironmentConfig = ( metadataManagerStackProps: getMetadataManagerStackProps(), sequenceRunManagerStackProps: getSequenceRunManagerStackProps(), fileManagerStackProps: getFileManagerStackProps(accountName), + bsRunsUploadManagerStackProps: getBsRunsUploadManagerStackProps(accountName), }, }, }; - break; case 'gamma': return { @@ -66,10 +67,10 @@ export const getEnvironmentConfig = ( metadataManagerStackProps: getMetadataManagerStackProps(), sequenceRunManagerStackProps: getSequenceRunManagerStackProps(), fileManagerStackProps: getFileManagerStackProps(accountName), + bsRunsUploadManagerStackProps: getBsRunsUploadManagerStackProps(accountName), }, }, }; - break; case 'prod': return { @@ -87,6 +88,7 @@ export const getEnvironmentConfig = ( metadataManagerStackProps: getMetadataManagerStackProps(), sequenceRunManagerStackProps: getSequenceRunManagerStackProps(), fileManagerStackProps: getFileManagerStackProps(accountName), + bsRunsUploadManagerStackProps: getBsRunsUploadManagerStackProps(accountName), }, }, }; diff --git a/config/constants.ts b/config/constants.ts index 9f1900c11..bf4b3d6ac 100644 --- a/config/constants.ts +++ b/config/constants.ts @@ -28,6 +28,10 @@ export const devBucket = 'umccr-temp-dev'; export const stgBucket = 'umccr-temp-stg'; export const prodBucket = 'org.umccr.data.oncoanalyser'; +export const devGdsBsRunsUploadLogPath = 'gds://development/primary_data/temp/bs_runs_upload_tes/'; +export const stgGdsBsRunsUploadLogPath = 'gds://staging/primary_data/temp/bs_runs_upload_tes/'; +export const prodGdsBsRunsUploadLogPath = 'gds://production/primary_data/temp/bs_runs_upload_tes/'; + /** * Validate the secret name so that it doesn't end with 6 characters and a hyphen. * diff --git a/config/stacks/bsRunsUploadManager.ts b/config/stacks/bsRunsUploadManager.ts new file mode 100644 index 000000000..35971fd1e --- /dev/null +++ b/config/stacks/bsRunsUploadManager.ts @@ -0,0 +1,34 @@ +import { BsRunsUploadManagerConfig } from '../../lib/workload/stateless/bs_runs_upload_manager/deploy/lib/stacks/bs_runs_upload_manager_stack'; +import { + devGdsBsRunsUploadLogPath, + stgGdsBsRunsUploadLogPath, + prodGdsBsRunsUploadLogPath, + AccountName, +} from '../constants'; + +export const getBsRunsUploadManagerStackProps = (n: AccountName): BsRunsUploadManagerConfig => { + const baseConfig = { + ica_token_secret_id: 'IcaSecretsPortal', + portal_token_secret_id: 'orcabus/token-service-jwt', + basespace_token_secret_id: '/manual/BaseSpaceAccessTokenSecret', + eventbus_name: '/umccr/orcabus/stateful/eventbridge', + }; + + switch (n) { + case 'beta': + return { + ...baseConfig, + gds_system_files_path: devGdsBsRunsUploadLogPath, + }; + case 'gamma': + return { + ...baseConfig, + gds_system_files_path: stgGdsBsRunsUploadLogPath, + }; + case 'prod': + return { + ...baseConfig, + gds_system_files_path: prodGdsBsRunsUploadLogPath, + }; + } +}; diff --git a/lib/workload/stateless/bs_runs_upload_manager/deploy/lib/stacks/bs_runs_upload_manager_stack.ts b/lib/workload/stateless/bs_runs_upload_manager/deploy/lib/stacks/bs_runs_upload_manager_stack.ts index dc6845883..18176b0f1 100644 --- a/lib/workload/stateless/bs_runs_upload_manager/deploy/lib/stacks/bs_runs_upload_manager_stack.ts +++ b/lib/workload/stateless/bs_runs_upload_manager/deploy/lib/stacks/bs_runs_upload_manager_stack.ts @@ -7,7 +7,7 @@ import * as events from 'aws-cdk-lib/aws-events'; import * as ssm from 'aws-cdk-lib/aws-ssm'; // import * as sqs from 'aws-cdk-lib/aws-sqs'; -export interface BsRunsUploadManagerStackProps extends cdk.StackProps { +export interface BsRunsUploadManagerConfig { // Define construct properties here ica_token_secret_id: string; // IcaSecretsPortal portal_token_secret_id: string; // orcabus/token-service-jwt @@ -16,6 +16,8 @@ export interface BsRunsUploadManagerStackProps extends cdk.StackProps { eventbus_name: string; // /umccr/orcabus/stateful/eventbridge } +export type BsRunsUploadManagerStackProps = BsRunsUploadManagerConfig & cdk.StackProps + export class BsRunsUploadManagerStack extends cdk.Stack { constructor(scope: Construct, id: string, props: BsRunsUploadManagerStackProps) { super(scope, id, props); diff --git a/lib/workload/stateless/statelessStackCollectionClass.ts b/lib/workload/stateless/statelessStackCollectionClass.ts index 862c7688f..46d5b3254 100644 --- a/lib/workload/stateless/statelessStackCollectionClass.ts +++ b/lib/workload/stateless/statelessStackCollectionClass.ts @@ -14,12 +14,14 @@ import { SequenceRunManagerStack, SequenceRunManagerStackProps, } from './stacks/sequence-run-manager/deploy/stack'; +import { BsRunsUploadManagerStackProps } from './bs_runs_upload_manager/deploy/lib/stacks/bs_runs_upload_manager_stack'; export interface StatelessStackCollectionProps { postgresManagerStackProps: PostgresManagerStackProps; metadataManagerStackProps: MetadataManagerStackProps; sequenceRunManagerStackProps: SequenceRunManagerStackProps; fileManagerStackProps: FilemanagerProps; + bsRunsUploadManagerStackProps: BsRunsUploadManagerStackProps; } export class StatelessStackCollection { From 624155a676082a7e0120f6fc04bb978717e1a14e Mon Sep 17 00:00:00 2001 From: alexiswl <8197659+alexiswl@users.noreply.github.com> Date: Thu, 18 Apr 2024 12:37:02 +1000 Subject: [PATCH 08/16] Move bsRunsUploadManager to new stacks directory --- config/stacks/bsRunsUploadManager.ts | 2 +- .../bs-runs-upload-manager}/Readme.md | 0 .../bs-runs-upload-manager}/deploy/.gitignore | 0 .../bs-runs-upload-manager}/deploy/.npmignore | 0 .../bs-runs-upload-manager}/deploy/README.md | 0 .../bs-runs-upload-manager}/deploy/bin/deploy.ts | 0 .../bs-runs-upload-manager}/deploy/cdk.json | 0 .../bs-runs-upload-manager}/deploy/constants.ts | 0 .../bs-runs-upload-manager}/deploy/jest.config.js | 0 .../lib/constructs/bs_runs_upload_manager_stack.ts | 0 .../deploy/lib/constructs/lambda_layer.ts | 0 .../lib/stacks/bs_runs_upload_manager_stack.ts | 0 .../bs-runs-upload-manager}/deploy/package.json | 0 .../deploy/test/deploy.test.ts | 0 .../bs-runs-upload-manager}/deploy/tsconfig.json | 0 .../bs_runs_upload_manager_step_functions.png | Bin .../lambdas/launch_bs_runs_upload_tes/handler.py | 0 .../upload_v2_samplesheet_to_gds_bssh/handler.py | 0 .../bs-runs-upload-manager}/layers/poetry.lock | 0 .../bs-runs-upload-manager}/layers/pyproject.toml | 0 .../src/bs_runs_upload_manager_tools/__init__.py | 0 .../bs_runs_upload_manager_tools/utils/__init__.py | 0 .../utils/aws_s3_helpers.py | 0 .../utils/aws_secrets_manager_helpers.py | 0 .../utils/gds_helpers.py | 0 .../utils/ica_config_helpers.py | 0 .../utils/portal_helpers.py | 0 .../utils/samplesheet_helpers.py | 0 .../utils/tes_helpers.py | 0 .../bs_runs_upload_step_functions_template.json | 0 30 files changed, 1 insertion(+), 1 deletion(-) rename lib/workload/stateless/{bs_runs_upload_manager => stacks/bs-runs-upload-manager}/Readme.md (100%) rename lib/workload/stateless/{bs_runs_upload_manager => stacks/bs-runs-upload-manager}/deploy/.gitignore (100%) rename lib/workload/stateless/{bs_runs_upload_manager => stacks/bs-runs-upload-manager}/deploy/.npmignore (100%) rename lib/workload/stateless/{bs_runs_upload_manager => stacks/bs-runs-upload-manager}/deploy/README.md (100%) rename lib/workload/stateless/{bs_runs_upload_manager => stacks/bs-runs-upload-manager}/deploy/bin/deploy.ts (100%) rename lib/workload/stateless/{bs_runs_upload_manager => stacks/bs-runs-upload-manager}/deploy/cdk.json (100%) rename lib/workload/stateless/{bs_runs_upload_manager => stacks/bs-runs-upload-manager}/deploy/constants.ts (100%) rename lib/workload/stateless/{bs_runs_upload_manager => stacks/bs-runs-upload-manager}/deploy/jest.config.js (100%) rename lib/workload/stateless/{bs_runs_upload_manager => stacks/bs-runs-upload-manager}/deploy/lib/constructs/bs_runs_upload_manager_stack.ts (100%) rename lib/workload/stateless/{bs_runs_upload_manager => stacks/bs-runs-upload-manager}/deploy/lib/constructs/lambda_layer.ts (100%) rename lib/workload/stateless/{bs_runs_upload_manager => stacks/bs-runs-upload-manager}/deploy/lib/stacks/bs_runs_upload_manager_stack.ts (100%) rename lib/workload/stateless/{bs_runs_upload_manager => stacks/bs-runs-upload-manager}/deploy/package.json (100%) rename lib/workload/stateless/{bs_runs_upload_manager => stacks/bs-runs-upload-manager}/deploy/test/deploy.test.ts (100%) rename lib/workload/stateless/{bs_runs_upload_manager => stacks/bs-runs-upload-manager}/deploy/tsconfig.json (100%) rename lib/workload/stateless/{bs_runs_upload_manager => stacks/bs-runs-upload-manager}/images/bs_runs_upload_manager_step_functions.png (100%) rename lib/workload/stateless/{bs_runs_upload_manager => stacks/bs-runs-upload-manager}/lambdas/launch_bs_runs_upload_tes/handler.py (100%) rename lib/workload/stateless/{bs_runs_upload_manager => stacks/bs-runs-upload-manager}/lambdas/upload_v2_samplesheet_to_gds_bssh/handler.py (100%) rename lib/workload/stateless/{bs_runs_upload_manager => stacks/bs-runs-upload-manager}/layers/poetry.lock (100%) rename lib/workload/stateless/{bs_runs_upload_manager => stacks/bs-runs-upload-manager}/layers/pyproject.toml (100%) rename lib/workload/stateless/{bs_runs_upload_manager => stacks/bs-runs-upload-manager}/layers/src/bs_runs_upload_manager_tools/__init__.py (100%) rename lib/workload/stateless/{bs_runs_upload_manager => stacks/bs-runs-upload-manager}/layers/src/bs_runs_upload_manager_tools/utils/__init__.py (100%) rename lib/workload/stateless/{bs_runs_upload_manager => stacks/bs-runs-upload-manager}/layers/src/bs_runs_upload_manager_tools/utils/aws_s3_helpers.py (100%) rename lib/workload/stateless/{bs_runs_upload_manager => stacks/bs-runs-upload-manager}/layers/src/bs_runs_upload_manager_tools/utils/aws_secrets_manager_helpers.py (100%) rename lib/workload/stateless/{bs_runs_upload_manager => stacks/bs-runs-upload-manager}/layers/src/bs_runs_upload_manager_tools/utils/gds_helpers.py (100%) rename lib/workload/stateless/{bs_runs_upload_manager => stacks/bs-runs-upload-manager}/layers/src/bs_runs_upload_manager_tools/utils/ica_config_helpers.py (100%) rename lib/workload/stateless/{bs_runs_upload_manager => stacks/bs-runs-upload-manager}/layers/src/bs_runs_upload_manager_tools/utils/portal_helpers.py (100%) rename lib/workload/stateless/{bs_runs_upload_manager => stacks/bs-runs-upload-manager}/layers/src/bs_runs_upload_manager_tools/utils/samplesheet_helpers.py (100%) rename lib/workload/stateless/{bs_runs_upload_manager => stacks/bs-runs-upload-manager}/layers/src/bs_runs_upload_manager_tools/utils/tes_helpers.py (100%) rename lib/workload/stateless/{bs_runs_upload_manager => stacks/bs-runs-upload-manager}/step_functions_templates/bs_runs_upload_step_functions_template.json (100%) diff --git a/config/stacks/bsRunsUploadManager.ts b/config/stacks/bsRunsUploadManager.ts index 35971fd1e..7a3ce1b04 100644 --- a/config/stacks/bsRunsUploadManager.ts +++ b/config/stacks/bsRunsUploadManager.ts @@ -1,4 +1,4 @@ -import { BsRunsUploadManagerConfig } from '../../lib/workload/stateless/bs_runs_upload_manager/deploy/lib/stacks/bs_runs_upload_manager_stack'; +import { BsRunsUploadManagerConfig } from '../../lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/lib/stacks/bs_runs_upload_manager_stack'; import { devGdsBsRunsUploadLogPath, stgGdsBsRunsUploadLogPath, diff --git a/lib/workload/stateless/bs_runs_upload_manager/Readme.md b/lib/workload/stateless/stacks/bs-runs-upload-manager/Readme.md similarity index 100% rename from lib/workload/stateless/bs_runs_upload_manager/Readme.md rename to lib/workload/stateless/stacks/bs-runs-upload-manager/Readme.md diff --git a/lib/workload/stateless/bs_runs_upload_manager/deploy/.gitignore b/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/.gitignore similarity index 100% rename from lib/workload/stateless/bs_runs_upload_manager/deploy/.gitignore rename to lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/.gitignore diff --git a/lib/workload/stateless/bs_runs_upload_manager/deploy/.npmignore b/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/.npmignore similarity index 100% rename from lib/workload/stateless/bs_runs_upload_manager/deploy/.npmignore rename to lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/.npmignore diff --git a/lib/workload/stateless/bs_runs_upload_manager/deploy/README.md b/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/README.md similarity index 100% rename from lib/workload/stateless/bs_runs_upload_manager/deploy/README.md rename to lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/README.md diff --git a/lib/workload/stateless/bs_runs_upload_manager/deploy/bin/deploy.ts b/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/bin/deploy.ts similarity index 100% rename from lib/workload/stateless/bs_runs_upload_manager/deploy/bin/deploy.ts rename to lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/bin/deploy.ts diff --git a/lib/workload/stateless/bs_runs_upload_manager/deploy/cdk.json b/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/cdk.json similarity index 100% rename from lib/workload/stateless/bs_runs_upload_manager/deploy/cdk.json rename to lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/cdk.json diff --git a/lib/workload/stateless/bs_runs_upload_manager/deploy/constants.ts b/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/constants.ts similarity index 100% rename from lib/workload/stateless/bs_runs_upload_manager/deploy/constants.ts rename to lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/constants.ts diff --git a/lib/workload/stateless/bs_runs_upload_manager/deploy/jest.config.js b/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/jest.config.js similarity index 100% rename from lib/workload/stateless/bs_runs_upload_manager/deploy/jest.config.js rename to lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/jest.config.js diff --git a/lib/workload/stateless/bs_runs_upload_manager/deploy/lib/constructs/bs_runs_upload_manager_stack.ts b/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/lib/constructs/bs_runs_upload_manager_stack.ts similarity index 100% rename from lib/workload/stateless/bs_runs_upload_manager/deploy/lib/constructs/bs_runs_upload_manager_stack.ts rename to lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/lib/constructs/bs_runs_upload_manager_stack.ts diff --git a/lib/workload/stateless/bs_runs_upload_manager/deploy/lib/constructs/lambda_layer.ts b/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/lib/constructs/lambda_layer.ts similarity index 100% rename from lib/workload/stateless/bs_runs_upload_manager/deploy/lib/constructs/lambda_layer.ts rename to lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/lib/constructs/lambda_layer.ts diff --git a/lib/workload/stateless/bs_runs_upload_manager/deploy/lib/stacks/bs_runs_upload_manager_stack.ts b/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/lib/stacks/bs_runs_upload_manager_stack.ts similarity index 100% rename from lib/workload/stateless/bs_runs_upload_manager/deploy/lib/stacks/bs_runs_upload_manager_stack.ts rename to lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/lib/stacks/bs_runs_upload_manager_stack.ts diff --git a/lib/workload/stateless/bs_runs_upload_manager/deploy/package.json b/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/package.json similarity index 100% rename from lib/workload/stateless/bs_runs_upload_manager/deploy/package.json rename to lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/package.json diff --git a/lib/workload/stateless/bs_runs_upload_manager/deploy/test/deploy.test.ts b/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/test/deploy.test.ts similarity index 100% rename from lib/workload/stateless/bs_runs_upload_manager/deploy/test/deploy.test.ts rename to lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/test/deploy.test.ts diff --git a/lib/workload/stateless/bs_runs_upload_manager/deploy/tsconfig.json b/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/tsconfig.json similarity index 100% rename from lib/workload/stateless/bs_runs_upload_manager/deploy/tsconfig.json rename to lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/tsconfig.json diff --git a/lib/workload/stateless/bs_runs_upload_manager/images/bs_runs_upload_manager_step_functions.png b/lib/workload/stateless/stacks/bs-runs-upload-manager/images/bs_runs_upload_manager_step_functions.png similarity index 100% rename from lib/workload/stateless/bs_runs_upload_manager/images/bs_runs_upload_manager_step_functions.png rename to lib/workload/stateless/stacks/bs-runs-upload-manager/images/bs_runs_upload_manager_step_functions.png diff --git a/lib/workload/stateless/bs_runs_upload_manager/lambdas/launch_bs_runs_upload_tes/handler.py b/lib/workload/stateless/stacks/bs-runs-upload-manager/lambdas/launch_bs_runs_upload_tes/handler.py similarity index 100% rename from lib/workload/stateless/bs_runs_upload_manager/lambdas/launch_bs_runs_upload_tes/handler.py rename to lib/workload/stateless/stacks/bs-runs-upload-manager/lambdas/launch_bs_runs_upload_tes/handler.py diff --git a/lib/workload/stateless/bs_runs_upload_manager/lambdas/upload_v2_samplesheet_to_gds_bssh/handler.py b/lib/workload/stateless/stacks/bs-runs-upload-manager/lambdas/upload_v2_samplesheet_to_gds_bssh/handler.py similarity index 100% rename from lib/workload/stateless/bs_runs_upload_manager/lambdas/upload_v2_samplesheet_to_gds_bssh/handler.py rename to lib/workload/stateless/stacks/bs-runs-upload-manager/lambdas/upload_v2_samplesheet_to_gds_bssh/handler.py diff --git a/lib/workload/stateless/bs_runs_upload_manager/layers/poetry.lock b/lib/workload/stateless/stacks/bs-runs-upload-manager/layers/poetry.lock similarity index 100% rename from lib/workload/stateless/bs_runs_upload_manager/layers/poetry.lock rename to lib/workload/stateless/stacks/bs-runs-upload-manager/layers/poetry.lock diff --git a/lib/workload/stateless/bs_runs_upload_manager/layers/pyproject.toml b/lib/workload/stateless/stacks/bs-runs-upload-manager/layers/pyproject.toml similarity index 100% rename from lib/workload/stateless/bs_runs_upload_manager/layers/pyproject.toml rename to lib/workload/stateless/stacks/bs-runs-upload-manager/layers/pyproject.toml diff --git a/lib/workload/stateless/bs_runs_upload_manager/layers/src/bs_runs_upload_manager_tools/__init__.py b/lib/workload/stateless/stacks/bs-runs-upload-manager/layers/src/bs_runs_upload_manager_tools/__init__.py similarity index 100% rename from lib/workload/stateless/bs_runs_upload_manager/layers/src/bs_runs_upload_manager_tools/__init__.py rename to lib/workload/stateless/stacks/bs-runs-upload-manager/layers/src/bs_runs_upload_manager_tools/__init__.py diff --git a/lib/workload/stateless/bs_runs_upload_manager/layers/src/bs_runs_upload_manager_tools/utils/__init__.py b/lib/workload/stateless/stacks/bs-runs-upload-manager/layers/src/bs_runs_upload_manager_tools/utils/__init__.py similarity index 100% rename from lib/workload/stateless/bs_runs_upload_manager/layers/src/bs_runs_upload_manager_tools/utils/__init__.py rename to lib/workload/stateless/stacks/bs-runs-upload-manager/layers/src/bs_runs_upload_manager_tools/utils/__init__.py diff --git a/lib/workload/stateless/bs_runs_upload_manager/layers/src/bs_runs_upload_manager_tools/utils/aws_s3_helpers.py b/lib/workload/stateless/stacks/bs-runs-upload-manager/layers/src/bs_runs_upload_manager_tools/utils/aws_s3_helpers.py similarity index 100% rename from lib/workload/stateless/bs_runs_upload_manager/layers/src/bs_runs_upload_manager_tools/utils/aws_s3_helpers.py rename to lib/workload/stateless/stacks/bs-runs-upload-manager/layers/src/bs_runs_upload_manager_tools/utils/aws_s3_helpers.py diff --git a/lib/workload/stateless/bs_runs_upload_manager/layers/src/bs_runs_upload_manager_tools/utils/aws_secrets_manager_helpers.py b/lib/workload/stateless/stacks/bs-runs-upload-manager/layers/src/bs_runs_upload_manager_tools/utils/aws_secrets_manager_helpers.py similarity index 100% rename from lib/workload/stateless/bs_runs_upload_manager/layers/src/bs_runs_upload_manager_tools/utils/aws_secrets_manager_helpers.py rename to lib/workload/stateless/stacks/bs-runs-upload-manager/layers/src/bs_runs_upload_manager_tools/utils/aws_secrets_manager_helpers.py diff --git a/lib/workload/stateless/bs_runs_upload_manager/layers/src/bs_runs_upload_manager_tools/utils/gds_helpers.py b/lib/workload/stateless/stacks/bs-runs-upload-manager/layers/src/bs_runs_upload_manager_tools/utils/gds_helpers.py similarity index 100% rename from lib/workload/stateless/bs_runs_upload_manager/layers/src/bs_runs_upload_manager_tools/utils/gds_helpers.py rename to lib/workload/stateless/stacks/bs-runs-upload-manager/layers/src/bs_runs_upload_manager_tools/utils/gds_helpers.py diff --git a/lib/workload/stateless/bs_runs_upload_manager/layers/src/bs_runs_upload_manager_tools/utils/ica_config_helpers.py b/lib/workload/stateless/stacks/bs-runs-upload-manager/layers/src/bs_runs_upload_manager_tools/utils/ica_config_helpers.py similarity index 100% rename from lib/workload/stateless/bs_runs_upload_manager/layers/src/bs_runs_upload_manager_tools/utils/ica_config_helpers.py rename to lib/workload/stateless/stacks/bs-runs-upload-manager/layers/src/bs_runs_upload_manager_tools/utils/ica_config_helpers.py diff --git a/lib/workload/stateless/bs_runs_upload_manager/layers/src/bs_runs_upload_manager_tools/utils/portal_helpers.py b/lib/workload/stateless/stacks/bs-runs-upload-manager/layers/src/bs_runs_upload_manager_tools/utils/portal_helpers.py similarity index 100% rename from lib/workload/stateless/bs_runs_upload_manager/layers/src/bs_runs_upload_manager_tools/utils/portal_helpers.py rename to lib/workload/stateless/stacks/bs-runs-upload-manager/layers/src/bs_runs_upload_manager_tools/utils/portal_helpers.py diff --git a/lib/workload/stateless/bs_runs_upload_manager/layers/src/bs_runs_upload_manager_tools/utils/samplesheet_helpers.py b/lib/workload/stateless/stacks/bs-runs-upload-manager/layers/src/bs_runs_upload_manager_tools/utils/samplesheet_helpers.py similarity index 100% rename from lib/workload/stateless/bs_runs_upload_manager/layers/src/bs_runs_upload_manager_tools/utils/samplesheet_helpers.py rename to lib/workload/stateless/stacks/bs-runs-upload-manager/layers/src/bs_runs_upload_manager_tools/utils/samplesheet_helpers.py diff --git a/lib/workload/stateless/bs_runs_upload_manager/layers/src/bs_runs_upload_manager_tools/utils/tes_helpers.py b/lib/workload/stateless/stacks/bs-runs-upload-manager/layers/src/bs_runs_upload_manager_tools/utils/tes_helpers.py similarity index 100% rename from lib/workload/stateless/bs_runs_upload_manager/layers/src/bs_runs_upload_manager_tools/utils/tes_helpers.py rename to lib/workload/stateless/stacks/bs-runs-upload-manager/layers/src/bs_runs_upload_manager_tools/utils/tes_helpers.py diff --git a/lib/workload/stateless/bs_runs_upload_manager/step_functions_templates/bs_runs_upload_step_functions_template.json b/lib/workload/stateless/stacks/bs-runs-upload-manager/step_functions_templates/bs_runs_upload_step_functions_template.json similarity index 100% rename from lib/workload/stateless/bs_runs_upload_manager/step_functions_templates/bs_runs_upload_step_functions_template.json rename to lib/workload/stateless/stacks/bs-runs-upload-manager/step_functions_templates/bs_runs_upload_step_functions_template.json From 1bd8db150f6093f6ceaca5904c77e217a91c6dd0 Mon Sep 17 00:00:00 2001 From: alexiswl <8197659+alexiswl@users.noreply.github.com> Date: Thu, 18 Apr 2024 13:34:35 +1000 Subject: [PATCH 09/16] Linted and filtered Filtered event and updated step function inputs to match sequence. Ran `yarn run prettier --write` to update linting for ts files --- .../stacks/bs-runs-upload-manager/Readme.md | 6 +- .../deploy/bin/deploy.ts | 26 ++--- .../deploy/constants.ts | 10 +- .../deploy/jest.config.js | 4 +- .../bs_runs_upload_manager_stack.ts | 107 +++++++++--------- .../deploy/lib/constructs/lambda_layer.ts | 43 +++---- .../stacks/bs_runs_upload_manager_stack.ts | 67 ++++++----- .../deploy/package.json | 2 +- .../deploy/test/deploy.test.ts | 17 ++- ...s_runs_upload_step_functions_template.json | 14 +-- 10 files changed, 139 insertions(+), 157 deletions(-) diff --git a/lib/workload/stateless/stacks/bs-runs-upload-manager/Readme.md b/lib/workload/stateless/stacks/bs-runs-upload-manager/Readme.md index e582f6440..67d40964a 100644 --- a/lib/workload/stateless/stacks/bs-runs-upload-manager/Readme.md +++ b/lib/workload/stateless/stacks/bs-runs-upload-manager/Readme.md @@ -41,9 +41,9 @@ The AWS Step functions takes in the following parameters ```json { - "gdsFolderPath": "/Runs/231109_A01052_0171_BHLJW7DSX7_r.NULhvzxcSEWmqZw8QljXfQ", - "gdsVolumeName": "bssh.acddbfda498038ed99fa94fe79523959", - "sampleSheetName": "SampleSheet.csv" + "run_folder_path": "/Runs/231109_A01052_0171_BHLJW7DSX7_r.NULhvzxcSEWmqZw8QljXfQ", + "run_volume_name": "bssh.acddbfda498038ed99fa94fe79523959", + "sample_sheet_name": "SampleSheet.csv" } ``` diff --git a/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/bin/deploy.ts b/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/bin/deploy.ts index b3239b4f2..aee4f54a7 100644 --- a/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/bin/deploy.ts +++ b/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/bin/deploy.ts @@ -11,18 +11,14 @@ import { } from '../constants'; const app = new cdk.App(); -new BsRunsUploadManagerStack( - app, - 'BsRunsUploadManagerStack', - { - basespace_token_secret_id: BASESPACE_TOKEN_SECRET_ID, // BaseSpaceAccessTokenSecret - eventbus_name: EVENTBUS_NAME, // OrcabusMain - ica_token_secret_id: ICA_TOKEN_SECRET_ID, // ICASecretsPortal - portal_token_secret_id: PORTAL_TOKEN_SECRET_ID, // orcabus/token-service-jwt - gds_system_files_path: GDS_DEV_TEMP_PATH, // gds://development/primary_data/temp/bs_runs_upload_tes/ - env: { - account: process.env.CDK_DEFAULT_ACCOUNT, - region: process.env.CDK_DEFAULT_REGION, - } - } - ) \ No newline at end of file +new BsRunsUploadManagerStack(app, 'BsRunsUploadManagerStack', { + basespace_token_secret_id: BASESPACE_TOKEN_SECRET_ID, // BaseSpaceAccessTokenSecret + eventbus_name: EVENTBUS_NAME, // OrcabusMain + ica_token_secret_id: ICA_TOKEN_SECRET_ID, // ICASecretsPortal + portal_token_secret_id: PORTAL_TOKEN_SECRET_ID, // orcabus/token-service-jwt + gds_system_files_path: GDS_DEV_TEMP_PATH, // gds://development/primary_data/temp/bs_runs_upload_tes/ + env: { + account: process.env.CDK_DEFAULT_ACCOUNT, + region: process.env.CDK_DEFAULT_REGION, + }, +}); diff --git a/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/constants.ts b/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/constants.ts index 05f8c4989..4ff8cf1e9 100644 --- a/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/constants.ts +++ b/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/constants.ts @@ -1,8 +1,8 @@ -export const ICA_TOKEN_SECRET_ID = 'IcaSecretsPortal' -export const PORTAL_TOKEN_SECRET_ID = 'orcabus/token-service-jwt' +export const ICA_TOKEN_SECRET_ID = 'IcaSecretsPortal'; +export const PORTAL_TOKEN_SECRET_ID = 'orcabus/token-service-jwt'; -export const BASESPACE_TOKEN_SECRET_ID = '/manual/BaseSpaceAccessTokenSecret' +export const BASESPACE_TOKEN_SECRET_ID = '/manual/BaseSpaceAccessTokenSecret'; -export const EVENTBUS_NAME = 'OrcaBusMain' +export const EVENTBUS_NAME = 'OrcaBusMain'; -export const GDS_DEV_TEMP_PATH = 'gds://development/primary_data/temp/bs_runs_upload_tes/' \ No newline at end of file +export const GDS_DEV_TEMP_PATH = 'gds://development/primary_data/temp/bs_runs_upload_tes/'; diff --git a/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/jest.config.js b/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/jest.config.js index 08263b895..44ead8540 100644 --- a/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/jest.config.js +++ b/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/jest.config.js @@ -3,6 +3,6 @@ module.exports = { roots: ['/test'], testMatch: ['**/*.test.ts'], transform: { - '^.+\\.tsx?$': 'ts-jest' - } + '^.+\\.tsx?$': 'ts-jest', + }, }; diff --git a/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/lib/constructs/bs_runs_upload_manager_stack.ts b/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/lib/constructs/bs_runs_upload_manager_stack.ts index e104beb11..2d670442c 100644 --- a/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/lib/constructs/bs_runs_upload_manager_stack.ts +++ b/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/lib/constructs/bs_runs_upload_manager_stack.ts @@ -13,11 +13,11 @@ import { IRole } from 'aws-cdk-lib/aws-iam'; interface BsRunsUploadManagerConstructProps { /* Stack objects */ - lambda_layer_obj: LambdaLayerConstruct, - ica_token_secret_obj: secretsManager.ISecret, - portal_token_secret_obj: secretsManager.ISecret, - basespace_secret_obj: secretsManager.ISecret, - event_bus_obj: events.IEventBus, + lambda_layer_obj: LambdaLayerConstruct; + ica_token_secret_obj: secretsManager.ISecret; + portal_token_secret_obj: secretsManager.ISecret; + basespace_secret_obj: secretsManager.ISecret; + event_bus_obj: events.IEventBus; /* Lambda layer paths */ upload_v2_samplesheet_to_gds_bssh_lambda_path: string; // __dirname + '/../../../lambdas/upload_v2_samplesheet_to_gds_bssh' launch_bs_runs_upload_tes_lambda_path: string; // __dirname + '/../../../lambdas/launch_bs_runs_upload_tes' @@ -28,33 +28,37 @@ interface BsRunsUploadManagerConstructProps { } export class BsRunsUploadManagerConstruct extends Construct { - public readonly bs_runs_upload_event_state_machine_arn: string; constructor(scope: Construct, id: string, props: BsRunsUploadManagerConstructProps) { super(scope, id); - // V2 Upload lambda - const upload_v2_samplesheet_to_gds_bssh_lambda = new PythonFunction(this, 'upload_v2_samplesheet_to_gds_bssh_lambda', { - entry: props.upload_v2_samplesheet_to_gds_bssh_lambda_path, - runtime: lambda.Runtime.PYTHON_3_11, - index: 'handler.py', - handler: 'handler', - memorySize: 1024, - // @ts-ignore - layers: [props.lambda_layer_obj.lambda_layer_version_obj], - // @ts-ignore - timeout: Duration.seconds(60), - environment: { - ICA_BASE_URL: 'https://aps2.platform.illumina.com', - ICA_ACCESS_TOKEN_SECRET_ID: props.ica_token_secret_obj.secretName, - PORTAL_TOKEN_SECRET_ID: props.portal_token_secret_obj.secretName, - }, - }); + const upload_v2_samplesheet_to_gds_bssh_lambda = new PythonFunction( + this, + 'upload_v2_samplesheet_to_gds_bssh_lambda', + { + entry: props.upload_v2_samplesheet_to_gds_bssh_lambda_path, + runtime: lambda.Runtime.PYTHON_3_11, + index: 'handler.py', + handler: 'handler', + memorySize: 1024, + // @ts-ignore + layers: [props.lambda_layer_obj.lambda_layer_version_obj], + // @ts-ignore + timeout: Duration.seconds(60), + environment: { + ICA_BASE_URL: 'https://aps2.platform.illumina.com', + ICA_ACCESS_TOKEN_SECRET_ID: props.ica_token_secret_obj.secretName, + PORTAL_TOKEN_SECRET_ID: props.portal_token_secret_obj.secretName, + }, + } + ); // Launch BS Runs Upload TES lambda - const launch_bs_runs_upload_tes_lambda = new PythonFunction(this, 'launch_bs_runs_upload_tes_lambda', + const launch_bs_runs_upload_tes_lambda = new PythonFunction( + this, + 'launch_bs_runs_upload_tes_lambda', { entry: props.launch_bs_runs_upload_tes_lambda_path, runtime: lambda.Runtime.PYTHON_3_11, @@ -72,36 +76,33 @@ export class BsRunsUploadManagerConstruct extends Construct { ICA_ACCESS_TOKEN_SECRET_ID: props.ica_token_secret_obj.secretName, GDS_SYSTEM_FILES_PATH: props.gds_system_files_path, }, - }, + } ); // Give the lambda permission to read the ICA ACCESS TOKEN secret - [ - launch_bs_runs_upload_tes_lambda, - upload_v2_samplesheet_to_gds_bssh_lambda, - ].forEach( + [launch_bs_runs_upload_tes_lambda, upload_v2_samplesheet_to_gds_bssh_lambda].forEach( (lambda_obj) => { props.ica_token_secret_obj.grantRead( // @ts-ignore - lambda_obj.role, + lambda_obj.role ); props.portal_token_secret_obj.grantRead( // @ts-ignore - lambda_obj.role, + lambda_obj.role ); - }, + } ); // Give the lambda permission to read the PORTAL TOKEN secret props.portal_token_secret_obj.grantRead( // @ts-ignore - upload_v2_samplesheet_to_gds_bssh_lambda.role, + upload_v2_samplesheet_to_gds_bssh_lambda.role ); // Give basespace upload lambda permission to read the basespace access token secret props.basespace_secret_obj.grantRead( // @ts-ignore - launch_bs_runs_upload_tes_lambda.role, + launch_bs_runs_upload_tes_lambda.role ); // Specify the statemachine and replace the arn placeholders with the lambda arns defined above @@ -110,24 +111,21 @@ export class BsRunsUploadManagerConstruct extends Construct { definitionBody: DefinitionBody.fromFile(props.workflow_definition_body_path), // definitionSubstitutions definitionSubstitutions: { - '__upload_v2_samplesheet_to_gds_bssh_function_arn__': upload_v2_samplesheet_to_gds_bssh_lambda.functionArn, - '__launch_bs_runs_upload_tes_function_arn__': launch_bs_runs_upload_tes_lambda.functionArn, + __upload_v2_samplesheet_to_gds_bssh_function_arn__: + upload_v2_samplesheet_to_gds_bssh_lambda.functionArn, + __launch_bs_runs_upload_tes_function_arn__: launch_bs_runs_upload_tes_lambda.functionArn, }, }); // Add execution permissions to stateMachine role stateMachine.addToRolePolicy( - new iam.PolicyStatement( - { - resources: [ - upload_v2_samplesheet_to_gds_bssh_lambda.functionArn, - launch_bs_runs_upload_tes_lambda.functionArn, - ], - actions: [ - 'lambda:InvokeFunction', - ], - }, - ), + new iam.PolicyStatement({ + resources: [ + upload_v2_samplesheet_to_gds_bssh_lambda.functionArn, + launch_bs_runs_upload_tes_lambda.functionArn, + ], + actions: ['lambda:InvokeFunction'], + }) ); // Trigger state machine on event @@ -136,21 +134,20 @@ export class BsRunsUploadManagerConstruct extends Construct { eventPattern: { source: ['orcabus.srm'], detailType: ['SequenceRunStateChange'], + detail: { + status: ['succeeded'], + }, }, }); // Add target of event to be the state machine rule.addTarget( - new events_targets.SfnStateMachine( - stateMachine, - { - input: events.RuleTargetInput.fromEventPath('$.detail') - } - ) - ) + new events_targets.SfnStateMachine(stateMachine, { + input: events.RuleTargetInput.fromEventPath('$.detail'), + }) + ); // Set outputs this.bs_runs_upload_event_state_machine_arn = stateMachine.stateMachineArn; } - } diff --git a/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/lib/constructs/lambda_layer.ts b/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/lib/constructs/lambda_layer.ts index 4fd2b81e0..e9eb71528 100644 --- a/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/lib/constructs/lambda_layer.ts +++ b/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/lib/constructs/lambda_layer.ts @@ -1,44 +1,37 @@ - -import { Construct } from 'constructs' +import { Construct } from 'constructs'; import { PythonLayerVersion } from '@aws-cdk/aws-lambda-python-alpha'; import * as lambda from 'aws-cdk-lib/aws-lambda'; export interface LambdaLayerConstructProps { - layer_directory: string + layer_directory: string; } export class LambdaLayerConstruct extends Construct { - public readonly lambda_layer_arn: string; public readonly lambda_layer_version_obj: PythonLayerVersion; constructor(scope: Construct, id: string, props: LambdaLayerConstructProps) { super(scope, id); - this.lambda_layer_version_obj = new PythonLayerVersion( - this, - 'bs_runs_upload_layer', - { - entry: props.layer_directory, - compatibleRuntimes: [lambda.Runtime.PYTHON_3_11], - compatibleArchitectures: [lambda.Architecture.X86_64], - license: 'GPL3', - description: 'A layer to enable the bssh manager tools layer', - bundling: { - commandHooks: { - beforeBundling(inputDir: string, outputDir: string): string[] { - return []; - }, - afterBundling(inputDir: string, outputDir: string): string[] { - return [ - `python -m pip install ${inputDir} -t ${outputDir}`, - ]; - }, + this.lambda_layer_version_obj = new PythonLayerVersion(this, 'bs_runs_upload_layer', { + entry: props.layer_directory, + compatibleRuntimes: [lambda.Runtime.PYTHON_3_11], + compatibleArchitectures: [lambda.Architecture.X86_64], + license: 'GPL3', + description: 'A layer to enable the bssh manager tools layer', + bundling: { + commandHooks: { + beforeBundling(inputDir: string, outputDir: string): string[] { + return []; + }, + afterBundling(inputDir: string, outputDir: string): string[] { + return [`python -m pip install ${inputDir} -t ${outputDir}`]; }, }, - }); + }, + }); // Set outputs this.lambda_layer_arn = this.lambda_layer_version_obj.layerVersionArn; } -} \ No newline at end of file +} diff --git a/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/lib/stacks/bs_runs_upload_manager_stack.ts b/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/lib/stacks/bs_runs_upload_manager_stack.ts index 18176b0f1..c8d457bb5 100644 --- a/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/lib/stacks/bs_runs_upload_manager_stack.ts +++ b/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/lib/stacks/bs_runs_upload_manager_stack.ts @@ -16,58 +16,55 @@ export interface BsRunsUploadManagerConfig { eventbus_name: string; // /umccr/orcabus/stateful/eventbridge } -export type BsRunsUploadManagerStackProps = BsRunsUploadManagerConfig & cdk.StackProps +export type BsRunsUploadManagerStackProps = BsRunsUploadManagerConfig & cdk.StackProps; export class BsRunsUploadManagerStack extends cdk.Stack { constructor(scope: Construct, id: string, props: BsRunsUploadManagerStackProps) { super(scope, id, props); - // Set lambda layer arn object - const lambda_layer_obj = new LambdaLayerConstruct( - this, 'lambda_layer', { - layer_directory: __dirname + '/../../../layers', - }); + const lambda_layer_obj = new LambdaLayerConstruct(this, 'lambda_layer', { + layer_directory: __dirname + '/../../../layers', + }); const ica_access_token_secret_obj = secretsManager.Secret.fromSecretNameV2( - this, 'IcaSecretsPortalSecretObject', - props.ica_token_secret_id, + this, + 'IcaSecretsPortalSecretObject', + props.ica_token_secret_id ); const portal_secret_obj = secretsManager.Secret.fromSecretNameV2( - this, 'PortalSecret', - props.portal_token_secret_id, + this, + 'PortalSecret', + props.portal_token_secret_id ); const basespace_secret_obj = secretsManager.Secret.fromSecretNameV2( - this, 'BaseSpaceAccessTokenSecret', + this, + 'BaseSpaceAccessTokenSecret', props.basespace_token_secret_id - ) - - const event_bus_obj = events.EventBus.fromEventBusName( - this, 'event_bus', - props.eventbus_name ); + const event_bus_obj = events.EventBus.fromEventBusName(this, 'event_bus', props.eventbus_name); - new BsRunsUploadManagerConstruct( - this, - 'bs-runs-upload-manager', - { - /* Stack objects */ - lambda_layer_obj: lambda_layer_obj, - ica_token_secret_obj: ica_access_token_secret_obj, - portal_token_secret_obj: portal_secret_obj, - basespace_secret_obj: basespace_secret_obj, - event_bus_obj: event_bus_obj, - /* Lambda paths */ - upload_v2_samplesheet_to_gds_bssh_lambda_path: __dirname + '/../../../lambdas/upload_v2_samplesheet_to_gds_bssh', - launch_bs_runs_upload_tes_lambda_path: __dirname + '/../../../lambdas/launch_bs_runs_upload_tes', - /* Step functions templates */ - workflow_definition_body_path: __dirname + '/../../../step_functions_templates/bs_runs_upload_step_functions_template.json', - /* Miscell */ - gds_system_files_path: props.gds_system_files_path, - } - ) + new BsRunsUploadManagerConstruct(this, 'bs-runs-upload-manager', { + /* Stack objects */ + lambda_layer_obj: lambda_layer_obj, + ica_token_secret_obj: ica_access_token_secret_obj, + portal_token_secret_obj: portal_secret_obj, + basespace_secret_obj: basespace_secret_obj, + event_bus_obj: event_bus_obj, + /* Lambda paths */ + upload_v2_samplesheet_to_gds_bssh_lambda_path: + __dirname + '/../../../lambdas/upload_v2_samplesheet_to_gds_bssh', + launch_bs_runs_upload_tes_lambda_path: + __dirname + '/../../../lambdas/launch_bs_runs_upload_tes', + /* Step functions templates */ + workflow_definition_body_path: + __dirname + + '/../../../step_functions_templates/bs_runs_upload_step_functions_template.json', + /* Miscell */ + gds_system_files_path: props.gds_system_files_path, + }); } } diff --git a/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/package.json b/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/package.json index c6928fbd0..f5839b2f0 100644 --- a/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/package.json +++ b/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/package.json @@ -24,4 +24,4 @@ "constructs": "^10.0.0", "source-map-support": "^0.5.21" } -} \ No newline at end of file +} diff --git a/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/test/deploy.test.ts b/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/test/deploy.test.ts index e7b5dbd29..464ee85ae 100644 --- a/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/test/deploy.test.ts +++ b/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/test/deploy.test.ts @@ -5,13 +5,12 @@ // example test. To run these tests, uncomment this file along with the // example resource in lib/bs_runs_upload_manager_stack.ts test('SQS Queue Created', () => { -// const app = new cdk.App(); -// // WHEN -// const stack = new Deploy.Bs_runs_upload_manager_stack(app, 'MyTestStack'); -// // THEN -// const template = Template.fromStack(stack); - -// template.hasResourceProperties('AWS::SQS::Queue', { -// VisibilityTimeout: 300 -// }); + // const app = new cdk.App(); + // // WHEN + // const stack = new Deploy.Bs_runs_upload_manager_stack(app, 'MyTestStack'); + // // THEN + // const template = Template.fromStack(stack); + // template.hasResourceProperties('AWS::SQS::Queue', { + // VisibilityTimeout: 300 + // }); }); diff --git a/lib/workload/stateless/stacks/bs-runs-upload-manager/step_functions_templates/bs_runs_upload_step_functions_template.json b/lib/workload/stateless/stacks/bs-runs-upload-manager/step_functions_templates/bs_runs_upload_step_functions_template.json index 73cc4be7c..34e6e9c7a 100644 --- a/lib/workload/stateless/stacks/bs-runs-upload-manager/step_functions_templates/bs_runs_upload_step_functions_template.json +++ b/lib/workload/stateless/stacks/bs-runs-upload-manager/step_functions_templates/bs_runs_upload_step_functions_template.json @@ -16,9 +16,9 @@ "Parameters": { "FunctionName": "${__upload_v2_samplesheet_to_gds_bssh_function_arn__}", "Payload": { - "gds_folder_path.$": "$.workflow_inputs.gdsFolderPath", - "gds_volume_name.$": "$.workflow_inputs.gdsVolumeName", - "samplesheet_name.$": "$.workflow_inputs.sampleSheetName" + "gds_folder_path.$": "$.workflow_inputs.run_folder_path", + "gds_volume_name.$": "$.workflow_inputs.run_folder_name", + "samplesheet_name.$": "$.workflow_inputs.sample_sheet_name" } }, "Retry": [ @@ -47,10 +47,10 @@ "Parameters": { "FunctionName": "${__launch_bs_runs_upload_tes_function_arn__}", "Payload": { - "gds_folder_path.$": "$.workflow_inputs.gdsFolderPath", - "gds_volume_name.$": "$.workflow_inputs.gdsVolumeName", + "gds_folder_path.$": "$.workflow_inputs.run_folder_path", + "gds_volume_name.$": "$.workflow_inputs.run_folder_name", "samplesheet_name.$": "$.upload_v2_samplesheet_to_gds_bssh_step.samplesheet_name", - "instrument_run_id.$": "$.workflow_inputs.instrumentRunId" + "instrument_run_id.$": "$.workflow_inputs.instrument_run_id" } }, "ResultSelector": { @@ -75,4 +75,4 @@ "Type": "Succeed" } } -} \ No newline at end of file +} From 9a09df93606179eedfc08a980feeaf6d3f83d132 Mon Sep 17 00:00:00 2001 From: alexiswl <8197659+alexiswl@users.noreply.github.com> Date: Thu, 18 Apr 2024 20:37:22 +1000 Subject: [PATCH 10/16] Descaled standalone cdk construct, integrate stack be to within orcabus only Updated orcabus pipeline stack collection class --- .../bs-runs-upload-manager/deploy/.gitignore | 8 --- .../bs-runs-upload-manager/deploy/.npmignore | 6 -- .../deploy/bin/deploy.ts | 24 ------- .../bs-runs-upload-manager/deploy/cdk.json | 66 ------------------- .../deploy/constants.ts | 8 --- .../bs_runs_upload_manager_stack.ts | 0 .../{lib => }/constructs/lambda_layer.ts | 0 .../deploy/jest.config.js | 8 --- .../deploy/package.json | 27 -------- .../stacks/bs_runs_upload_manager_stack.ts | 11 ++-- .../deploy/test/deploy.test.ts | 16 ----- .../deploy/tsconfig.json | 31 --------- .../statelessStackCollectionClass.ts | 13 +++- 13 files changed, 17 insertions(+), 201 deletions(-) delete mode 100644 lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/.gitignore delete mode 100644 lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/.npmignore delete mode 100644 lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/bin/deploy.ts delete mode 100644 lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/cdk.json delete mode 100644 lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/constants.ts rename lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/{lib => }/constructs/bs_runs_upload_manager_stack.ts (100%) rename lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/{lib => }/constructs/lambda_layer.ts (100%) delete mode 100644 lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/jest.config.js delete mode 100644 lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/package.json rename lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/{lib => }/stacks/bs_runs_upload_manager_stack.ts (89%) delete mode 100644 lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/test/deploy.test.ts delete mode 100644 lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/tsconfig.json diff --git a/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/.gitignore b/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/.gitignore deleted file mode 100644 index f60797b6a..000000000 --- a/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -*.js -!jest.config.js -*.d.ts -node_modules - -# CDK asset staging directory -.cdk.staging -cdk.out diff --git a/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/.npmignore b/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/.npmignore deleted file mode 100644 index c1d6d45dc..000000000 --- a/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/.npmignore +++ /dev/null @@ -1,6 +0,0 @@ -*.ts -!*.d.ts - -# CDK asset staging directory -.cdk.staging -cdk.out diff --git a/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/bin/deploy.ts b/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/bin/deploy.ts deleted file mode 100644 index aee4f54a7..000000000 --- a/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/bin/deploy.ts +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env node -import 'source-map-support/register'; -import * as cdk from 'aws-cdk-lib'; -import { BsRunsUploadManagerStack } from '../lib/stacks/bs_runs_upload_manager_stack'; -import { - BASESPACE_TOKEN_SECRET_ID, - EVENTBUS_NAME, - GDS_DEV_TEMP_PATH, - ICA_TOKEN_SECRET_ID, - PORTAL_TOKEN_SECRET_ID, -} from '../constants'; - -const app = new cdk.App(); -new BsRunsUploadManagerStack(app, 'BsRunsUploadManagerStack', { - basespace_token_secret_id: BASESPACE_TOKEN_SECRET_ID, // BaseSpaceAccessTokenSecret - eventbus_name: EVENTBUS_NAME, // OrcabusMain - ica_token_secret_id: ICA_TOKEN_SECRET_ID, // ICASecretsPortal - portal_token_secret_id: PORTAL_TOKEN_SECRET_ID, // orcabus/token-service-jwt - gds_system_files_path: GDS_DEV_TEMP_PATH, // gds://development/primary_data/temp/bs_runs_upload_tes/ - env: { - account: process.env.CDK_DEFAULT_ACCOUNT, - region: process.env.CDK_DEFAULT_REGION, - }, -}); diff --git a/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/cdk.json b/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/cdk.json deleted file mode 100644 index e8f04c654..000000000 --- a/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/cdk.json +++ /dev/null @@ -1,66 +0,0 @@ -{ - "app": "npx ts-node --prefer-ts-exts bin/deploy.ts", - "watch": { - "include": [ - "**" - ], - "exclude": [ - "README.md", - "cdk*.json", - "**/*.d.ts", - "**/*.js", - "tsconfig.json", - "package*.json", - "yarn.lock", - "node_modules", - "test" - ] - }, - "context": { - "@aws-cdk/aws-lambda:recognizeLayerVersion": true, - "@aws-cdk/core:checkSecretUsage": true, - "@aws-cdk/core:target-partitions": [ - "aws", - "aws-cn" - ], - "@aws-cdk-containers/ecs-service-extensions:enableDefaultLogDriver": true, - "@aws-cdk/aws-ec2:uniqueImdsv2TemplateName": true, - "@aws-cdk/aws-ecs:arnFormatIncludesClusterName": true, - "@aws-cdk/aws-iam:minimizePolicies": true, - "@aws-cdk/core:validateSnapshotRemovalPolicy": true, - "@aws-cdk/aws-codepipeline:crossAccountKeyAliasStackSafeResourceName": true, - "@aws-cdk/aws-s3:createDefaultLoggingPolicy": true, - "@aws-cdk/aws-sns-subscriptions:restrictSqsDescryption": true, - "@aws-cdk/aws-apigateway:disableCloudWatchRole": true, - "@aws-cdk/core:enablePartitionLiterals": true, - "@aws-cdk/aws-events:eventsTargetQueueSameAccount": true, - "@aws-cdk/aws-iam:standardizedServicePrincipals": true, - "@aws-cdk/aws-ecs:disableExplicitDeploymentControllerForCircuitBreaker": true, - "@aws-cdk/aws-iam:importedRoleStackSafeDefaultPolicyName": true, - "@aws-cdk/aws-s3:serverAccessLogsUseBucketPolicy": true, - "@aws-cdk/aws-route53-patters:useCertificate": true, - "@aws-cdk/customresources:installLatestAwsSdkDefault": false, - "@aws-cdk/aws-rds:databaseProxyUniqueResourceName": true, - "@aws-cdk/aws-codedeploy:removeAlarmsFromDeploymentGroup": true, - "@aws-cdk/aws-apigateway:authorizerChangeDeploymentLogicalId": true, - "@aws-cdk/aws-ec2:launchTemplateDefaultUserData": true, - "@aws-cdk/aws-secretsmanager:useAttachedSecretResourcePolicyForSecretTargetAttachments": true, - "@aws-cdk/aws-redshift:columnId": true, - "@aws-cdk/aws-stepfunctions-tasks:enableEmrServicePolicyV2": true, - "@aws-cdk/aws-ec2:restrictDefaultSecurityGroup": true, - "@aws-cdk/aws-apigateway:requestValidatorUniqueId": true, - "@aws-cdk/aws-kms:aliasNameRef": true, - "@aws-cdk/aws-autoscaling:generateLaunchTemplateInsteadOfLaunchConfig": true, - "@aws-cdk/core:includePrefixInUniqueNameGeneration": true, - "@aws-cdk/aws-efs:denyAnonymousAccess": true, - "@aws-cdk/aws-opensearchservice:enableOpensearchMultiAzWithStandby": true, - "@aws-cdk/aws-lambda-nodejs:useLatestRuntimeVersion": true, - "@aws-cdk/aws-efs:mountTargetOrderInsensitiveLogicalId": true, - "@aws-cdk/aws-rds:auroraClusterChangeScopeOfInstanceParameterGroupWithEachParameters": true, - "@aws-cdk/aws-appsync:useArnForSourceApiAssociationIdentifier": true, - "@aws-cdk/aws-rds:preventRenderingDeprecatedCredentials": true, - "@aws-cdk/aws-codepipeline-actions:useNewDefaultBranchForCodeCommitSource": true, - "@aws-cdk/aws-cloudwatch-actions:changeLambdaPermissionLogicalIdForLambdaAction": true, - "@aws-cdk/aws-codepipeline:crossAccountKeysDefaultValueToFalse": true - } -} diff --git a/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/constants.ts b/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/constants.ts deleted file mode 100644 index 4ff8cf1e9..000000000 --- a/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/constants.ts +++ /dev/null @@ -1,8 +0,0 @@ -export const ICA_TOKEN_SECRET_ID = 'IcaSecretsPortal'; -export const PORTAL_TOKEN_SECRET_ID = 'orcabus/token-service-jwt'; - -export const BASESPACE_TOKEN_SECRET_ID = '/manual/BaseSpaceAccessTokenSecret'; - -export const EVENTBUS_NAME = 'OrcaBusMain'; - -export const GDS_DEV_TEMP_PATH = 'gds://development/primary_data/temp/bs_runs_upload_tes/'; diff --git a/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/lib/constructs/bs_runs_upload_manager_stack.ts b/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/constructs/bs_runs_upload_manager_stack.ts similarity index 100% rename from lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/lib/constructs/bs_runs_upload_manager_stack.ts rename to lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/constructs/bs_runs_upload_manager_stack.ts diff --git a/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/lib/constructs/lambda_layer.ts b/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/constructs/lambda_layer.ts similarity index 100% rename from lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/lib/constructs/lambda_layer.ts rename to lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/constructs/lambda_layer.ts diff --git a/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/jest.config.js b/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/jest.config.js deleted file mode 100644 index 44ead8540..000000000 --- a/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/jest.config.js +++ /dev/null @@ -1,8 +0,0 @@ -module.exports = { - testEnvironment: 'node', - roots: ['/test'], - testMatch: ['**/*.test.ts'], - transform: { - '^.+\\.tsx?$': 'ts-jest', - }, -}; diff --git a/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/package.json b/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/package.json deleted file mode 100644 index f5839b2f0..000000000 --- a/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/package.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "name": "deploy", - "version": "0.1.0", - "bin": { - "deploy": "bin/deploy.js" - }, - "scripts": { - "build": "tsc", - "watch": "tsc -w", - "test": "jest", - "cdk": "cdk" - }, - "devDependencies": { - "@types/jest": "^29.5.12", - "@types/node": "20.11.16", - "jest": "^29.7.0", - "ts-jest": "^29.1.2", - "aws-cdk": "2.128.0", - "ts-node": "^10.9.2", - "typescript": "~5.3.3" - }, - "dependencies": { - "aws-cdk-lib": "2.128.0", - "constructs": "^10.0.0", - "source-map-support": "^0.5.21" - } -} diff --git a/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/lib/stacks/bs_runs_upload_manager_stack.ts b/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/stacks/bs_runs_upload_manager_stack.ts similarity index 89% rename from lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/lib/stacks/bs_runs_upload_manager_stack.ts rename to lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/stacks/bs_runs_upload_manager_stack.ts index c8d457bb5..db8f9b6db 100644 --- a/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/lib/stacks/bs_runs_upload_manager_stack.ts +++ b/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/stacks/bs_runs_upload_manager_stack.ts @@ -4,8 +4,7 @@ import { BsRunsUploadManagerConstruct } from '../constructs/bs_runs_upload_manag import { LambdaLayerConstruct } from '../constructs/lambda_layer'; import * as secretsManager from 'aws-cdk-lib/aws-secretsmanager'; import * as events from 'aws-cdk-lib/aws-events'; -import * as ssm from 'aws-cdk-lib/aws-ssm'; -// import * as sqs from 'aws-cdk-lib/aws-sqs'; +import path from 'path'; export interface BsRunsUploadManagerConfig { // Define construct properties here @@ -56,13 +55,13 @@ export class BsRunsUploadManagerStack extends cdk.Stack { event_bus_obj: event_bus_obj, /* Lambda paths */ upload_v2_samplesheet_to_gds_bssh_lambda_path: - __dirname + '/../../../lambdas/upload_v2_samplesheet_to_gds_bssh', + path.join(__dirname, '/../../../lambdas/upload_v2_samplesheet_to_gds_bssh'), launch_bs_runs_upload_tes_lambda_path: - __dirname + '/../../../lambdas/launch_bs_runs_upload_tes', + path.join(__dirname, '/../../../lambdas/launch_bs_runs_upload_tes'), /* Step functions templates */ workflow_definition_body_path: - __dirname + - '/../../../step_functions_templates/bs_runs_upload_step_functions_template.json', + path.join(__dirname, + '/../../../step_functions_templates/bs_runs_upload_step_functions_template.json'), /* Miscell */ gds_system_files_path: props.gds_system_files_path, }); diff --git a/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/test/deploy.test.ts b/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/test/deploy.test.ts deleted file mode 100644 index 464ee85ae..000000000 --- a/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/test/deploy.test.ts +++ /dev/null @@ -1,16 +0,0 @@ -// import * as cdk from 'aws-cdk-lib'; -// import { Template } from 'aws-cdk-lib/assertions'; -// import * as Deploy from '../lib/deploy-stack'; - -// example test. To run these tests, uncomment this file along with the -// example resource in lib/bs_runs_upload_manager_stack.ts -test('SQS Queue Created', () => { - // const app = new cdk.App(); - // // WHEN - // const stack = new Deploy.Bs_runs_upload_manager_stack(app, 'MyTestStack'); - // // THEN - // const template = Template.fromStack(stack); - // template.hasResourceProperties('AWS::SQS::Queue', { - // VisibilityTimeout: 300 - // }); -}); diff --git a/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/tsconfig.json b/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/tsconfig.json deleted file mode 100644 index aaa7dc510..000000000 --- a/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/tsconfig.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2020", - "module": "commonjs", - "lib": [ - "es2020", - "dom" - ], - "declaration": true, - "strict": true, - "noImplicitAny": true, - "strictNullChecks": true, - "noImplicitThis": true, - "alwaysStrict": true, - "noUnusedLocals": false, - "noUnusedParameters": false, - "noImplicitReturns": true, - "noFallthroughCasesInSwitch": false, - "inlineSourceMap": true, - "inlineSources": true, - "experimentalDecorators": true, - "strictPropertyInitialization": false, - "typeRoots": [ - "./node_modules/@types" - ] - }, - "exclude": [ - "node_modules", - "cdk.out" - ] -} diff --git a/lib/workload/stateless/statelessStackCollectionClass.ts b/lib/workload/stateless/statelessStackCollectionClass.ts index 46d5b3254..5a7ab69e7 100644 --- a/lib/workload/stateless/statelessStackCollectionClass.ts +++ b/lib/workload/stateless/statelessStackCollectionClass.ts @@ -14,7 +14,8 @@ import { SequenceRunManagerStack, SequenceRunManagerStackProps, } from './stacks/sequence-run-manager/deploy/stack'; -import { BsRunsUploadManagerStackProps } from './bs_runs_upload_manager/deploy/lib/stacks/bs_runs_upload_manager_stack'; +import { BsRunsUploadManagerStackProps } from './stacks/bs-runs-upload-manager/deploy/stacks/bs_runs_upload_manager_stack'; +import { BsRunsUploadManagerStack } from './stacks/bs-runs-upload-manager/deploy/stacks/bs_runs_upload_manager_stack'; export interface StatelessStackCollectionProps { postgresManagerStackProps: PostgresManagerStackProps; @@ -30,6 +31,7 @@ export class StatelessStackCollection { readonly fileManagerStack: Stack; readonly metadataManagerStack: Stack; readonly sequenceRunManagerStack: Stack; + readonly bsRunsUploadManagerStack: Stack; constructor( scope: Construct, @@ -55,6 +57,15 @@ export class StatelessStackCollection { ...this.createTemplateProps(env, 'SequenceRunManagerStack'), ...statelessConfiguration.sequenceRunManagerStackProps, }); + + this.bsRunsUploadManagerStack = new BsRunsUploadManagerStack( + scope, + 'BsRunsUploadManagerStack', + { + ...this.createTemplateProps(env, 'BsRunsUploadManagerStack'), + ...statefulConfiguration.bsRunsUploadManagerStackProps, + } + ); } /** From 96bac5148f6fec1209d4d2a25f3cd3ea530d5ee4 Mon Sep 17 00:00:00 2001 From: alexiswl <8197659+alexiswl@users.noreply.github.com> Date: Thu, 18 Apr 2024 20:40:59 +1000 Subject: [PATCH 11/16] Lint stack file --- .../stacks/bs_runs_upload_manager_stack.ts | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/stacks/bs_runs_upload_manager_stack.ts b/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/stacks/bs_runs_upload_manager_stack.ts index db8f9b6db..3daa31791 100644 --- a/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/stacks/bs_runs_upload_manager_stack.ts +++ b/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/stacks/bs_runs_upload_manager_stack.ts @@ -54,14 +54,19 @@ export class BsRunsUploadManagerStack extends cdk.Stack { basespace_secret_obj: basespace_secret_obj, event_bus_obj: event_bus_obj, /* Lambda paths */ - upload_v2_samplesheet_to_gds_bssh_lambda_path: - path.join(__dirname, '/../../../lambdas/upload_v2_samplesheet_to_gds_bssh'), - launch_bs_runs_upload_tes_lambda_path: - path.join(__dirname, '/../../../lambdas/launch_bs_runs_upload_tes'), + upload_v2_samplesheet_to_gds_bssh_lambda_path: path.join( + __dirname, + '/../../../lambdas/upload_v2_samplesheet_to_gds_bssh' + ), + launch_bs_runs_upload_tes_lambda_path: path.join( + __dirname, + '/../../../lambdas/launch_bs_runs_upload_tes' + ), /* Step functions templates */ - workflow_definition_body_path: - path.join(__dirname, - '/../../../step_functions_templates/bs_runs_upload_step_functions_template.json'), + workflow_definition_body_path: path.join( + __dirname, + '/../../../step_functions_templates/bs_runs_upload_step_functions_template.json' + ), /* Miscell */ gds_system_files_path: props.gds_system_files_path, }); From 41c7384e0902351549b4d3c12b59d1099bb8c55d Mon Sep 17 00:00:00 2001 From: alexiswl <8197659+alexiswl@users.noreply.github.com> Date: Thu, 18 Apr 2024 20:42:08 +1000 Subject: [PATCH 12/16] Renamed stateful/stateless configuration from #232 --- lib/workload/stateless/statelessStackCollectionClass.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/workload/stateless/statelessStackCollectionClass.ts b/lib/workload/stateless/statelessStackCollectionClass.ts index 5a7ab69e7..90caba3d5 100644 --- a/lib/workload/stateless/statelessStackCollectionClass.ts +++ b/lib/workload/stateless/statelessStackCollectionClass.ts @@ -63,7 +63,7 @@ export class StatelessStackCollection { 'BsRunsUploadManagerStack', { ...this.createTemplateProps(env, 'BsRunsUploadManagerStack'), - ...statefulConfiguration.bsRunsUploadManagerStackProps, + ...statelessConfiguration.bsRunsUploadManagerStackProps, } ); } From 726b365d6195f97dbabfa8ac8ec74a7d50d9d353 Mon Sep 17 00:00:00 2001 From: alexiswl <8197659+alexiswl@users.noreply.github.com> Date: Thu, 18 Apr 2024 20:46:26 +1000 Subject: [PATCH 13/16] Use values in constants to populate stack parameters --- config/constants.ts | 3 +++ config/stacks/bsRunsUploadManager.ts | 11 +++++++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/config/constants.ts b/config/constants.ts index bf4b3d6ac..28b19a91c 100644 --- a/config/constants.ts +++ b/config/constants.ts @@ -68,6 +68,9 @@ export const eventSourceQueueName = 'orcabus-event-source-queue'; export const serviceUserSecretName = 'orcabus/token-service-user'; // pragma: allowlist secret export const jwtSecretName = 'orcabus/token-service-jwt'; // pragma: allowlist secret +export const icaAccessTokenSecretName = 'IcaSecretsPortal'; // pragma: allowlist secret + +export const basespaceAccessTokenSecretName = '/manual/BaseSpaceAccessTokenSecret'; // pragma: allowlist secret // const statelessConfig = { // multiSchemaConstructProps: { diff --git a/config/stacks/bsRunsUploadManager.ts b/config/stacks/bsRunsUploadManager.ts index 7a3ce1b04..88f0994d9 100644 --- a/config/stacks/bsRunsUploadManager.ts +++ b/config/stacks/bsRunsUploadManager.ts @@ -4,14 +4,17 @@ import { stgGdsBsRunsUploadLogPath, prodGdsBsRunsUploadLogPath, AccountName, + icaAccessTokenSecretName, + jwtSecretName, basespaceAccessTokenSecretName, + eventBusName, } from '../constants'; export const getBsRunsUploadManagerStackProps = (n: AccountName): BsRunsUploadManagerConfig => { const baseConfig = { - ica_token_secret_id: 'IcaSecretsPortal', - portal_token_secret_id: 'orcabus/token-service-jwt', - basespace_token_secret_id: '/manual/BaseSpaceAccessTokenSecret', - eventbus_name: '/umccr/orcabus/stateful/eventbridge', + ica_token_secret_id: icaAccessTokenSecretName, + portal_token_secret_id: jwtSecretName, + basespace_token_secret_id: basespaceAccessTokenSecretName, + eventbus_name: eventBusName, }; switch (n) { From 53ca7280583a6bb600d47d20bb2f0039a1f2bac3 Mon Sep 17 00:00:00 2001 From: alexiswl <8197659+alexiswl@users.noreply.github.com> Date: Thu, 18 Apr 2024 20:48:28 +1000 Subject: [PATCH 14/16] Fix configuration import --- config/stacks/bsRunsUploadManager.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/config/stacks/bsRunsUploadManager.ts b/config/stacks/bsRunsUploadManager.ts index 88f0994d9..9d0683ec7 100644 --- a/config/stacks/bsRunsUploadManager.ts +++ b/config/stacks/bsRunsUploadManager.ts @@ -1,13 +1,14 @@ -import { BsRunsUploadManagerConfig } from '../../lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/lib/stacks/bs_runs_upload_manager_stack'; import { devGdsBsRunsUploadLogPath, stgGdsBsRunsUploadLogPath, prodGdsBsRunsUploadLogPath, AccountName, icaAccessTokenSecretName, - jwtSecretName, basespaceAccessTokenSecretName, + jwtSecretName, + basespaceAccessTokenSecretName, eventBusName, } from '../constants'; +import { BsRunsUploadManagerConfig } from '../../lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/stacks/bs_runs_upload_manager_stack'; export const getBsRunsUploadManagerStackProps = (n: AccountName): BsRunsUploadManagerConfig => { const baseConfig = { From d5ec8dbca4c8b9f443688c8ac38c1f373fac95be Mon Sep 17 00:00:00 2001 From: Alexis Lucattini Date: Mon, 22 Apr 2024 11:12:36 +1000 Subject: [PATCH 15/16] Refactor python lambda construct Import path fixes after refactor Deleted blank deployment readme --- config/stacks/bsRunsUploadManager.ts | 2 +- .../python-lambda-layer/index.ts} | 13 +- .../bs-runs-upload-manager/deploy/README.md | 14 - .../index.ts} | 4 +- ..._runs_upload_manager_stack.ts => stack.ts} | 19 +- .../statelessStackCollectionClass.ts | 4 +- yarn.lock | 498 ++++++++++-------- 7 files changed, 302 insertions(+), 252 deletions(-) rename lib/workload/stateless/{stacks/bs-runs-upload-manager/deploy/constructs/lambda_layer.ts => constructs/python-lambda-layer/index.ts} (73%) delete mode 100644 lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/README.md rename lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/constructs/{bs_runs_upload_manager_stack.ts => bs-runs-upload-manager/index.ts} (97%) rename lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/{stacks/bs_runs_upload_manager_stack.ts => stack.ts} (78%) diff --git a/config/stacks/bsRunsUploadManager.ts b/config/stacks/bsRunsUploadManager.ts index 9d0683ec7..aafa0b576 100644 --- a/config/stacks/bsRunsUploadManager.ts +++ b/config/stacks/bsRunsUploadManager.ts @@ -8,7 +8,7 @@ import { basespaceAccessTokenSecretName, eventBusName, } from '../constants'; -import { BsRunsUploadManagerConfig } from '../../lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/stacks/bs_runs_upload_manager_stack'; +import { BsRunsUploadManagerConfig } from '../../lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/stack'; export const getBsRunsUploadManagerStackProps = (n: AccountName): BsRunsUploadManagerConfig => { const baseConfig = { diff --git a/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/constructs/lambda_layer.ts b/lib/workload/stateless/constructs/python-lambda-layer/index.ts similarity index 73% rename from lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/constructs/lambda_layer.ts rename to lib/workload/stateless/constructs/python-lambda-layer/index.ts index e9eb71528..e01987a8e 100644 --- a/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/constructs/lambda_layer.ts +++ b/lib/workload/stateless/constructs/python-lambda-layer/index.ts @@ -2,23 +2,26 @@ import { Construct } from 'constructs'; import { PythonLayerVersion } from '@aws-cdk/aws-lambda-python-alpha'; import * as lambda from 'aws-cdk-lib/aws-lambda'; -export interface LambdaLayerConstructProps { +export interface PythonLambdaLayerConstructProps { + layer_name: string; layer_directory: string; + layer_description: string; } -export class LambdaLayerConstruct extends Construct { +export class PythonLambdaLayerConstruct extends Construct { public readonly lambda_layer_arn: string; public readonly lambda_layer_version_obj: PythonLayerVersion; - constructor(scope: Construct, id: string, props: LambdaLayerConstructProps) { + constructor(scope: Construct, id: string, props: PythonLambdaLayerConstructProps) { super(scope, id); - this.lambda_layer_version_obj = new PythonLayerVersion(this, 'bs_runs_upload_layer', { + this.lambda_layer_version_obj = new PythonLayerVersion(this, 'python_lambda_layer', { + layerVersionName: props.layer_name, entry: props.layer_directory, compatibleRuntimes: [lambda.Runtime.PYTHON_3_11], compatibleArchitectures: [lambda.Architecture.X86_64], license: 'GPL3', - description: 'A layer to enable the bssh manager tools layer', + description: props.layer_description, bundling: { commandHooks: { beforeBundling(inputDir: string, outputDir: string): string[] { diff --git a/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/README.md b/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/README.md deleted file mode 100644 index 9315fe5b9..000000000 --- a/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/README.md +++ /dev/null @@ -1,14 +0,0 @@ -# Welcome to your CDK TypeScript project - -This is a blank project for CDK development with TypeScript. - -The `cdk.json` file tells the CDK Toolkit how to execute your app. - -## Useful commands - -* `npm run build` compile typescript to js -* `npm run watch` watch for changes and compile -* `npm run test` perform the jest unit tests -* `npx cdk deploy` deploy this stack to your default AWS account/region -* `npx cdk diff` compare deployed stack with current state -* `npx cdk synth` emits the synthesized CloudFormation template diff --git a/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/constructs/bs_runs_upload_manager_stack.ts b/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/constructs/bs-runs-upload-manager/index.ts similarity index 97% rename from lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/constructs/bs_runs_upload_manager_stack.ts rename to lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/constructs/bs-runs-upload-manager/index.ts index 2d670442c..6022f9a2a 100644 --- a/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/constructs/bs_runs_upload_manager_stack.ts +++ b/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/constructs/bs-runs-upload-manager/index.ts @@ -8,12 +8,12 @@ import * as events_targets from 'aws-cdk-lib/aws-events-targets'; import { DefinitionBody } from 'aws-cdk-lib/aws-stepfunctions'; import * as secretsManager from 'aws-cdk-lib/aws-secretsmanager'; import { PythonFunction } from '@aws-cdk/aws-lambda-python-alpha'; -import { LambdaLayerConstruct } from './lambda_layer'; import { IRole } from 'aws-cdk-lib/aws-iam'; +import { PythonLambdaLayerConstruct } from '../../../../../constructs/python-lambda-layer'; interface BsRunsUploadManagerConstructProps { /* Stack objects */ - lambda_layer_obj: LambdaLayerConstruct; + lambda_layer_obj: PythonLambdaLayerConstruct; ica_token_secret_obj: secretsManager.ISecret; portal_token_secret_obj: secretsManager.ISecret; basespace_secret_obj: secretsManager.ISecret; diff --git a/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/stacks/bs_runs_upload_manager_stack.ts b/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/stack.ts similarity index 78% rename from lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/stacks/bs_runs_upload_manager_stack.ts rename to lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/stack.ts index 3daa31791..a87c3c987 100644 --- a/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/stacks/bs_runs_upload_manager_stack.ts +++ b/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/stack.ts @@ -1,10 +1,10 @@ import * as cdk from 'aws-cdk-lib'; import { Construct } from 'constructs'; -import { BsRunsUploadManagerConstruct } from '../constructs/bs_runs_upload_manager_stack'; -import { LambdaLayerConstruct } from '../constructs/lambda_layer'; +import { BsRunsUploadManagerConstruct } from './constructs/bs-runs-upload-manager'; import * as secretsManager from 'aws-cdk-lib/aws-secretsmanager'; import * as events from 'aws-cdk-lib/aws-events'; import path from 'path'; +import { PythonLambdaLayerConstruct } from '../../../constructs/python-lambda-layer'; export interface BsRunsUploadManagerConfig { // Define construct properties here @@ -22,8 +22,13 @@ export class BsRunsUploadManagerStack extends cdk.Stack { super(scope, id, props); // Set lambda layer arn object - const lambda_layer_obj = new LambdaLayerConstruct(this, 'lambda_layer', { - layer_directory: __dirname + '/../../../layers', + const lambda_layer_obj = new PythonLambdaLayerConstruct( + this, + 'bssh_tools_lambda_layer', + { + layer_name: "BSSHToolsLambdaLayer", + layer_description: 'layer to enable the manager tools layer', + layer_directory: path.join(__dirname, '../layers') }); const ica_access_token_secret_obj = secretsManager.Secret.fromSecretNameV2( @@ -56,16 +61,16 @@ export class BsRunsUploadManagerStack extends cdk.Stack { /* Lambda paths */ upload_v2_samplesheet_to_gds_bssh_lambda_path: path.join( __dirname, - '/../../../lambdas/upload_v2_samplesheet_to_gds_bssh' + '../lambdas/upload_v2_samplesheet_to_gds_bssh' ), launch_bs_runs_upload_tes_lambda_path: path.join( __dirname, - '/../../../lambdas/launch_bs_runs_upload_tes' + '../lambdas/launch_bs_runs_upload_tes' ), /* Step functions templates */ workflow_definition_body_path: path.join( __dirname, - '/../../../step_functions_templates/bs_runs_upload_step_functions_template.json' + '../step_functions_templates/bs_runs_upload_step_functions_template.json' ), /* Miscell */ gds_system_files_path: props.gds_system_files_path, diff --git a/lib/workload/stateless/statelessStackCollectionClass.ts b/lib/workload/stateless/statelessStackCollectionClass.ts index 90caba3d5..65bc2ba1a 100644 --- a/lib/workload/stateless/statelessStackCollectionClass.ts +++ b/lib/workload/stateless/statelessStackCollectionClass.ts @@ -14,8 +14,8 @@ import { SequenceRunManagerStack, SequenceRunManagerStackProps, } from './stacks/sequence-run-manager/deploy/stack'; -import { BsRunsUploadManagerStackProps } from './stacks/bs-runs-upload-manager/deploy/stacks/bs_runs_upload_manager_stack'; -import { BsRunsUploadManagerStack } from './stacks/bs-runs-upload-manager/deploy/stacks/bs_runs_upload_manager_stack'; +import { BsRunsUploadManagerStackProps } from './stacks/bs-runs-upload-manager/deploy/stack'; +import { BsRunsUploadManagerStack } from './stacks/bs-runs-upload-manager/deploy/stack'; export interface StatelessStackCollectionProps { postgresManagerStackProps: PostgresManagerStackProps; diff --git a/yarn.lock b/yarn.lock index 233adae6a..ea107c612 100644 --- a/yarn.lock +++ b/yarn.lock @@ -74,7 +74,7 @@ __metadata: languageName: node linkType: hard -"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.12.13, @babel/code-frame@npm:^7.22.13, @babel/code-frame@npm:^7.23.5": +"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.12.13, @babel/code-frame@npm:^7.23.5": version: 7.23.5 resolution: "@babel/code-frame@npm:7.23.5" dependencies: @@ -92,25 +92,25 @@ __metadata: linkType: hard "@babel/core@npm:^7.11.6, @babel/core@npm:^7.12.3": - version: 7.23.6 - resolution: "@babel/core@npm:7.23.6" + version: 7.23.9 + resolution: "@babel/core@npm:7.23.9" dependencies: "@ampproject/remapping": ^2.2.0 "@babel/code-frame": ^7.23.5 "@babel/generator": ^7.23.6 "@babel/helper-compilation-targets": ^7.23.6 "@babel/helper-module-transforms": ^7.23.3 - "@babel/helpers": ^7.23.6 - "@babel/parser": ^7.23.6 - "@babel/template": ^7.22.15 - "@babel/traverse": ^7.23.6 - "@babel/types": ^7.23.6 + "@babel/helpers": ^7.23.9 + "@babel/parser": ^7.23.9 + "@babel/template": ^7.23.9 + "@babel/traverse": ^7.23.9 + "@babel/types": ^7.23.9 convert-source-map: ^2.0.0 debug: ^4.1.0 gensync: ^1.0.0-beta.2 json5: ^2.2.3 semver: ^6.3.1 - checksum: 4bddd1b80394a64b2ee33eeb216e8a2a49ad3d74f0ca9ba678c84a37f4502b2540662d72530d78228a2a349fda837fa852eea5cd3ae28465d1188acc6055868e + checksum: 634a511f74db52a5f5a283c1121f25e2227b006c095b84a02a40a9213842489cd82dc7d61cdc74e10b5bcd9bb0a4e28bab47635b54c7e2256d47ab57356e2a76 languageName: node linkType: hard @@ -235,14 +235,14 @@ __metadata: languageName: node linkType: hard -"@babel/helpers@npm:^7.23.6": - version: 7.23.6 - resolution: "@babel/helpers@npm:7.23.6" +"@babel/helpers@npm:^7.23.9": + version: 7.23.9 + resolution: "@babel/helpers@npm:7.23.9" dependencies: - "@babel/template": ^7.22.15 - "@babel/traverse": ^7.23.6 - "@babel/types": ^7.23.6 - checksum: c5ba62497e1d717161d107c4b3de727565c68b6b9f50f59d6298e613afeca8895799b227c256e06d362e565aec34e26fb5c675b9c3d25055c52b945a21c21e21 + "@babel/template": ^7.23.9 + "@babel/traverse": ^7.23.9 + "@babel/types": ^7.23.9 + checksum: 2678231192c0471dbc2fc403fb19456cc46b1afefcfebf6bc0f48b2e938fdb0fef2e0fe90c8c8ae1f021dae5012b700372e4b5d15867f1d7764616532e4a6324 languageName: node linkType: hard @@ -257,12 +257,12 @@ __metadata: languageName: node linkType: hard -"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.22.15, @babel/parser@npm:^7.23.6": - version: 7.23.6 - resolution: "@babel/parser@npm:7.23.6" +"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.23.9": + version: 7.23.9 + resolution: "@babel/parser@npm:7.23.9" bin: parser: ./bin/babel-parser.js - checksum: 140801c43731a6c41fd193f5c02bc71fd647a0360ca616b23d2db8be4b9739b9f951a03fc7c2db4f9b9214f4b27c1074db0f18bc3fa653783082d5af7c8860d5 + checksum: e7cd4960ac8671774e13803349da88d512f9292d7baa952173260d3e8f15620a28a3701f14f709d769209022f9e7b79965256b8be204fc550cfe783cdcabe7c7 languageName: node linkType: hard @@ -421,29 +421,29 @@ __metadata: linkType: hard "@babel/runtime-corejs3@npm:^7.16.5": - version: 7.24.0 - resolution: "@babel/runtime-corejs3@npm:7.24.0" + version: 7.24.4 + resolution: "@babel/runtime-corejs3@npm:7.24.4" dependencies: core-js-pure: ^3.30.2 regenerator-runtime: ^0.14.0 - checksum: cd4f2cde0878c911b2eeebf1cb48df819c862492da163bb9001ba690c82e9addd1d14087a8b0dd87fb1da2d916fa3b85d9a8cece4d46f8e5c51d734acda5a8bd + checksum: 0c2e7c477de3dbf5cc6f2434cee3d78a34d87e8f1e2ea65840eb948d00f7d6968e0ef055449adf372a39d6214f8b9b2532506149b9d0e7ea3d09b1b84678ae6c languageName: node linkType: hard -"@babel/template@npm:^7.22.15, @babel/template@npm:^7.3.3": - version: 7.22.15 - resolution: "@babel/template@npm:7.22.15" +"@babel/template@npm:^7.22.15, @babel/template@npm:^7.23.9, @babel/template@npm:^7.3.3": + version: 7.23.9 + resolution: "@babel/template@npm:7.23.9" dependencies: - "@babel/code-frame": ^7.22.13 - "@babel/parser": ^7.22.15 - "@babel/types": ^7.22.15 - checksum: 1f3e7dcd6c44f5904c184b3f7fe280394b191f2fed819919ffa1e529c259d5b197da8981b6ca491c235aee8dbad4a50b7e31304aa531271cb823a4a24a0dd8fd + "@babel/code-frame": ^7.23.5 + "@babel/parser": ^7.23.9 + "@babel/types": ^7.23.9 + checksum: 6e67414c0f7125d7ecaf20c11fab88085fa98a96c3ef10da0a61e962e04fdf3a18a496a66047005ddd1bb682a7cc7842d556d1db2f3f3f6ccfca97d5e445d342 languageName: node linkType: hard -"@babel/traverse@npm:^7.23.6": - version: 7.23.6 - resolution: "@babel/traverse@npm:7.23.6" +"@babel/traverse@npm:^7.23.9": + version: 7.23.9 + resolution: "@babel/traverse@npm:7.23.9" dependencies: "@babel/code-frame": ^7.23.5 "@babel/generator": ^7.23.6 @@ -451,22 +451,33 @@ __metadata: "@babel/helper-function-name": ^7.23.0 "@babel/helper-hoist-variables": ^7.22.5 "@babel/helper-split-export-declaration": ^7.22.6 - "@babel/parser": ^7.23.6 - "@babel/types": ^7.23.6 + "@babel/parser": ^7.23.9 + "@babel/types": ^7.23.9 debug: ^4.3.1 globals: ^11.1.0 - checksum: 48f2eac0e86b6cb60dab13a5ea6a26ba45c450262fccdffc334c01089e75935f7546be195e260e97f6e43cea419862eda095018531a2718fef8189153d479f88 + checksum: a932f7aa850e158c00c97aad22f639d48c72805c687290f6a73e30c5c4957c07f5d28310c9bf59648e2980fe6c9d16adeb2ff92a9ca0f97fa75739c1328fc6c3 languageName: node linkType: hard -"@babel/types@npm:^7.0.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.22.15, @babel/types@npm:^7.22.5, @babel/types@npm:^7.23.0, @babel/types@npm:^7.23.6, @babel/types@npm:^7.3.3, @babel/types@npm:^7.8.3": - version: 7.23.6 - resolution: "@babel/types@npm:7.23.6" +"@babel/types@npm:^7.0.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.22.15, @babel/types@npm:^7.22.5, @babel/types@npm:^7.23.0, @babel/types@npm:^7.23.6, @babel/types@npm:^7.23.9, @babel/types@npm:^7.3.3": + version: 7.23.9 + resolution: "@babel/types@npm:7.23.9" dependencies: "@babel/helper-string-parser": ^7.23.4 "@babel/helper-validator-identifier": ^7.22.20 to-fast-properties: ^2.0.0 - checksum: 68187dbec0d637f79bc96263ac95ec8b06d424396678e7e225492be866414ce28ebc918a75354d4c28659be6efe30020b4f0f6df81cc418a2d30645b690a8de0 + checksum: 0a9b008e9bfc89beb8c185e620fa0f8ed6c771f1e1b2e01e1596870969096fec7793898a1d64a035176abf1dd13e2668ee30bf699f2d92c210a8128f4b151e65 + languageName: node + linkType: hard + +"@babel/types@npm:^7.8.3": + version: 7.24.0 + resolution: "@babel/types@npm:7.24.0" + dependencies: + "@babel/helper-string-parser": ^7.23.4 + "@babel/helper-validator-identifier": ^7.22.20 + to-fast-properties: ^2.0.0 + checksum: 4b574a37d490f621470ff36a5afaac6deca5546edcb9b5e316d39acbb20998e9c2be42f3fc0bf2b55906fc49ff2a5a6a097e8f5a726ee3f708a0b0ca93aed807 languageName: node linkType: hard @@ -571,13 +582,13 @@ __metadata: linkType: hard "@humanwhocodes/config-array@npm:^0.11.13": - version: 0.11.13 - resolution: "@humanwhocodes/config-array@npm:0.11.13" + version: 0.11.14 + resolution: "@humanwhocodes/config-array@npm:0.11.14" dependencies: - "@humanwhocodes/object-schema": ^2.0.1 - debug: ^4.1.1 + "@humanwhocodes/object-schema": ^2.0.2 + debug: ^4.3.1 minimatch: ^3.0.5 - checksum: f8ea57b0d7ed7f2d64cd3944654976829d9da91c04d9c860e18804729a33f7681f78166ef4c761850b8c324d362f7d53f14c5c44907a6b38b32c703ff85e4805 + checksum: 861ccce9eaea5de19546653bccf75bf09fe878bc39c3aab00aeee2d2a0e654516adad38dd1098aab5e3af0145bbcbf3f309bdf4d964f8dab9dcd5834ae4c02f2 languageName: node linkType: hard @@ -588,10 +599,10 @@ __metadata: languageName: node linkType: hard -"@humanwhocodes/object-schema@npm:^2.0.1": - version: 2.0.1 - resolution: "@humanwhocodes/object-schema@npm:2.0.1" - checksum: 24929487b1ed48795d2f08346a0116cc5ee4634848bce64161fb947109352c562310fd159fc64dda0e8b853307f5794605191a9547f7341158559ca3c8262a45 +"@humanwhocodes/object-schema@npm:^2.0.2": + version: 2.0.2 + resolution: "@humanwhocodes/object-schema@npm:2.0.2" + checksum: 2fc11503361b5fb4f14714c700c02a3f4c7c93e9acd6b87a29f62c522d90470f364d6161b03d1cc618b979f2ae02aed1106fd29d302695d8927e2fc8165ba8ee languageName: node linkType: hard @@ -902,12 +913,12 @@ __metadata: linkType: hard "@jridgewell/trace-mapping@npm:^0.3.12, @jridgewell/trace-mapping@npm:^0.3.17, @jridgewell/trace-mapping@npm:^0.3.18, @jridgewell/trace-mapping@npm:^0.3.9": - version: 0.3.20 - resolution: "@jridgewell/trace-mapping@npm:0.3.20" + version: 0.3.22 + resolution: "@jridgewell/trace-mapping@npm:0.3.22" dependencies: "@jridgewell/resolve-uri": ^3.1.0 "@jridgewell/sourcemap-codec": ^1.4.14 - checksum: cd1a7353135f385909468ff0cf20bdd37e59f2ee49a13a966dedf921943e222082c583ade2b579ff6cd0d8faafcb5461f253e1bf2a9f48fec439211fdbe788f5 + checksum: ac7dd2cfe0b479aa1b81776d40d789243131cc792dc8b6b6a028c70fcd6171958ae1a71bf67b618ffe3c0c3feead9870c095ee46a5e30319410d92976b28f498 languageName: node linkType: hard @@ -939,15 +950,15 @@ __metadata: linkType: hard "@npmcli/agent@npm:^2.0.0": - version: 2.2.0 - resolution: "@npmcli/agent@npm:2.2.0" + version: 2.2.2 + resolution: "@npmcli/agent@npm:2.2.2" dependencies: agent-base: ^7.1.0 http-proxy-agent: ^7.0.0 https-proxy-agent: ^7.0.1 lru-cache: ^10.0.1 - socks-proxy-agent: ^8.0.1 - checksum: 3b25312edbdfaa4089af28e2d423b6f19838b945e47765b0c8174c1395c79d43c3ad6d23cb364b43f59fd3acb02c93e3b493f72ddbe3dfea04c86843a7311fc4 + socks-proxy-agent: ^8.0.3 + checksum: 67de7b88cc627a79743c88bab35e023e23daf13831a8aa4e15f998b92f5507b644d8ffc3788afc8e64423c612e0785a6a92b74782ce368f49a6746084b50d874 languageName: node linkType: hard @@ -982,11 +993,11 @@ __metadata: linkType: hard "@sinonjs/commons@npm:^3.0.0": - version: 3.0.0 - resolution: "@sinonjs/commons@npm:3.0.0" + version: 3.0.1 + resolution: "@sinonjs/commons@npm:3.0.1" dependencies: type-detect: 4.0.8 - checksum: b4b5b73d4df4560fb8c0c7b38c7ad4aeabedd362f3373859d804c988c725889cde33550e4bcc7cd316a30f5152a2d1d43db71b6d0c38f5feef71fd8d016763f8 + checksum: a7c3e7cc612352f4004873747d9d8b2d4d90b13a6d483f685598c945a70e734e255f1ca5dc49702515533c403b32725defff148177453b3f3915bcb60e9d4601 languageName: node linkType: hard @@ -1060,11 +1071,11 @@ __metadata: linkType: hard "@types/babel__traverse@npm:*, @types/babel__traverse@npm:^7.0.6": - version: 7.20.4 - resolution: "@types/babel__traverse@npm:7.20.4" + version: 7.20.5 + resolution: "@types/babel__traverse@npm:7.20.5" dependencies: "@babel/types": ^7.20.7 - checksum: f044ba80e00d07e46ee917c44f96cfc268fcf6d3871f7dfb8db8d3c6dab1508302f3e6bc508352a4a3ae627d2522e3fc500fa55907e0410a08e2e0902a8f3576 + checksum: 608e0ab4fc31cd47011d98942e6241b34d461608c0c0e153377c5fd822c436c475f1ded76a56bfa76a1adf8d9266b727bbf9bfac90c4cb152c97f30dadc5b7e8 languageName: node linkType: hard @@ -1120,18 +1131,18 @@ __metadata: linkType: hard "@types/node@npm:*, @types/node@npm:^20.4.0": - version: 20.10.5 - resolution: "@types/node@npm:20.10.5" + version: 20.11.10 + resolution: "@types/node@npm:20.11.10" dependencies: undici-types: ~5.26.4 - checksum: e216b679f545a8356960ce985a0e53c3a58fff0eacd855e180b9e223b8db2b5bd07b744a002b8c1f0c37f9194648ab4578533b5c12df2ec10cc02f61d20948d2 + checksum: 58544f52c14d839cc5fca7a9f001303016aefa85fea684de9aa3c24a1340a55a03a6744fa20f601ca032a9f9d08b32c1ff074ccb75dcd57d61a1a65c50a949b1 languageName: node linkType: hard "@types/semver@npm:^7.5.0": - version: 7.5.6 - resolution: "@types/semver@npm:7.5.6" - checksum: 563a0120ec0efcc326567db2ed920d5d98346f3638b6324ea6b50222b96f02a8add3c51a916b6897b51523aad8ac227d21d3dcf8913559f1bfc6c15b14d23037 + version: 7.5.8 + resolution: "@types/semver@npm:7.5.8" + checksum: ea6f5276f5b84c55921785a3a27a3cd37afee0111dfe2bcb3e03c31819c197c782598f17f0b150a69d453c9584cd14c4c4d7b9a55d2c5e6cacd4d66fdb3b3663 languageName: node linkType: hard @@ -1159,14 +1170,14 @@ __metadata: linkType: hard "@typescript-eslint/eslint-plugin@npm:^6.19.1": - version: 6.19.1 - resolution: "@typescript-eslint/eslint-plugin@npm:6.19.1" + version: 6.21.0 + resolution: "@typescript-eslint/eslint-plugin@npm:6.21.0" dependencies: "@eslint-community/regexpp": ^4.5.1 - "@typescript-eslint/scope-manager": 6.19.1 - "@typescript-eslint/type-utils": 6.19.1 - "@typescript-eslint/utils": 6.19.1 - "@typescript-eslint/visitor-keys": 6.19.1 + "@typescript-eslint/scope-manager": 6.21.0 + "@typescript-eslint/type-utils": 6.21.0 + "@typescript-eslint/utils": 6.21.0 + "@typescript-eslint/visitor-keys": 6.21.0 debug: ^4.3.4 graphemer: ^1.4.0 ignore: ^5.2.4 @@ -1179,44 +1190,44 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: ad04000cd6c15d864ff92655baa3aec99bb0ccf4714fedd145fedde60a27590a5feafe480beb2f0f3864b416098bde1e9431bada7480eb7ca4efad891e1d2f6f + checksum: 5ef2c502255e643e98051e87eb682c2a257e87afd8ec3b9f6274277615e1c2caf3131b352244cfb1987b8b2c415645eeacb9113fa841fc4c9b2ac46e8aed6efd languageName: node linkType: hard "@typescript-eslint/parser@npm:^6.19.1": - version: 6.19.1 - resolution: "@typescript-eslint/parser@npm:6.19.1" + version: 6.21.0 + resolution: "@typescript-eslint/parser@npm:6.21.0" dependencies: - "@typescript-eslint/scope-manager": 6.19.1 - "@typescript-eslint/types": 6.19.1 - "@typescript-eslint/typescript-estree": 6.19.1 - "@typescript-eslint/visitor-keys": 6.19.1 + "@typescript-eslint/scope-manager": 6.21.0 + "@typescript-eslint/types": 6.21.0 + "@typescript-eslint/typescript-estree": 6.21.0 + "@typescript-eslint/visitor-keys": 6.21.0 debug: ^4.3.4 peerDependencies: eslint: ^7.0.0 || ^8.0.0 peerDependenciesMeta: typescript: optional: true - checksum: cd29619da08a2d9b7123ba4d8240989c747f8e0d5672179d8b147e413ee1334d1fa48570b0c37cf0ae4e26a275fd2d268cbe702c6fed639d3331abbb3292570a + checksum: 162fe3a867eeeffda7328bce32dae45b52283c68c8cb23258fb9f44971f761991af61f71b8c9fe1aa389e93dfe6386f8509c1273d870736c507d76dd40647b68 languageName: node linkType: hard -"@typescript-eslint/scope-manager@npm:6.19.1": - version: 6.19.1 - resolution: "@typescript-eslint/scope-manager@npm:6.19.1" +"@typescript-eslint/scope-manager@npm:6.21.0": + version: 6.21.0 + resolution: "@typescript-eslint/scope-manager@npm:6.21.0" dependencies: - "@typescript-eslint/types": 6.19.1 - "@typescript-eslint/visitor-keys": 6.19.1 - checksum: 848cdebc16a3803e8a6d6035a7067605309a652bb2425f475f755b5ace4d80d2c17c8c8901f0f4759556da8d0a5b71024d472b85c3f3c70d0e6dcfe2a972ef35 + "@typescript-eslint/types": 6.21.0 + "@typescript-eslint/visitor-keys": 6.21.0 + checksum: 71028b757da9694528c4c3294a96cc80bc7d396e383a405eab3bc224cda7341b88e0fc292120b35d3f31f47beac69f7083196c70616434072fbcd3d3e62d3376 languageName: node linkType: hard -"@typescript-eslint/type-utils@npm:6.19.1": - version: 6.19.1 - resolution: "@typescript-eslint/type-utils@npm:6.19.1" +"@typescript-eslint/type-utils@npm:6.21.0": + version: 6.21.0 + resolution: "@typescript-eslint/type-utils@npm:6.21.0" dependencies: - "@typescript-eslint/typescript-estree": 6.19.1 - "@typescript-eslint/utils": 6.19.1 + "@typescript-eslint/typescript-estree": 6.21.0 + "@typescript-eslint/utils": 6.21.0 debug: ^4.3.4 ts-api-utils: ^1.0.1 peerDependencies: @@ -1224,23 +1235,23 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: eab1a30f8d85f7c6e2545de5963fbec2f3bb91913d59623069b4b0db372a671ab048c7018376fc853c3af06ea39417f3e7b27dd665027dd812347a5e64cecd77 + checksum: 77025473f4d80acf1fafcce99c5c283e557686a61861febeba9c9913331f8a41e930bf5cd8b7a54db502a57b6eb8ea6d155cbd4f41349ed00e3d7aeb1f477ddc languageName: node linkType: hard -"@typescript-eslint/types@npm:6.19.1": - version: 6.19.1 - resolution: "@typescript-eslint/types@npm:6.19.1" - checksum: 598ce222b59c20432d06f60703d0c2dd16d9b2151569c192852136c57b8188e3ef6ef9fddaa2c136c9a756fcc7d873c0e29ec41cfd340564842287ef7b4571cd +"@typescript-eslint/types@npm:6.21.0": + version: 6.21.0 + resolution: "@typescript-eslint/types@npm:6.21.0" + checksum: 9501b47d7403417af95fc1fb72b2038c5ac46feac0e1598a46bcb43e56a606c387e9dcd8a2a0abe174c91b509f2d2a8078b093786219eb9a01ab2fbf9ee7b684 languageName: node linkType: hard -"@typescript-eslint/typescript-estree@npm:6.19.1": - version: 6.19.1 - resolution: "@typescript-eslint/typescript-estree@npm:6.19.1" +"@typescript-eslint/typescript-estree@npm:6.21.0": + version: 6.21.0 + resolution: "@typescript-eslint/typescript-estree@npm:6.21.0" dependencies: - "@typescript-eslint/types": 6.19.1 - "@typescript-eslint/visitor-keys": 6.19.1 + "@typescript-eslint/types": 6.21.0 + "@typescript-eslint/visitor-keys": 6.21.0 debug: ^4.3.4 globby: ^11.1.0 is-glob: ^4.0.3 @@ -1250,34 +1261,34 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: fb71a14aeee0468780219c5b8d39075f85d360b04ccd0ee88f4f0a615d2c232a6d3016e36d8c6eda2d9dfda86b4f4cc2c3d7582940fb29d33c7cf305e124d4e2 + checksum: dec02dc107c4a541e14fb0c96148f3764b92117c3b635db3a577b5a56fc48df7a556fa853fb82b07c0663b4bf2c484c9f245c28ba3e17e5cb0918ea4cab2ea21 languageName: node linkType: hard -"@typescript-eslint/utils@npm:6.19.1": - version: 6.19.1 - resolution: "@typescript-eslint/utils@npm:6.19.1" +"@typescript-eslint/utils@npm:6.21.0": + version: 6.21.0 + resolution: "@typescript-eslint/utils@npm:6.21.0" dependencies: "@eslint-community/eslint-utils": ^4.4.0 "@types/json-schema": ^7.0.12 "@types/semver": ^7.5.0 - "@typescript-eslint/scope-manager": 6.19.1 - "@typescript-eslint/types": 6.19.1 - "@typescript-eslint/typescript-estree": 6.19.1 + "@typescript-eslint/scope-manager": 6.21.0 + "@typescript-eslint/types": 6.21.0 + "@typescript-eslint/typescript-estree": 6.21.0 semver: ^7.5.4 peerDependencies: eslint: ^7.0.0 || ^8.0.0 - checksum: fe72e75c3ea17a85772b83f148555ea94ff5d55d13586f3fc038833197a74f8071e14c2bbf1781c40eec20005f052f4be2513a725eea82a15da3cb9af3046c70 + checksum: b129b3a4aebec8468259f4589985cb59ea808afbfdb9c54f02fad11e17d185e2bf72bb332f7c36ec3c09b31f18fc41368678b076323e6e019d06f74ee93f7bf2 languageName: node linkType: hard -"@typescript-eslint/visitor-keys@npm:6.19.1": - version: 6.19.1 - resolution: "@typescript-eslint/visitor-keys@npm:6.19.1" +"@typescript-eslint/visitor-keys@npm:6.21.0": + version: 6.21.0 + resolution: "@typescript-eslint/visitor-keys@npm:6.21.0" dependencies: - "@typescript-eslint/types": 6.19.1 + "@typescript-eslint/types": 6.21.0 eslint-visitor-keys: ^3.4.1 - checksum: bdf057a42e776970a89cdd568e493e3ea7ec085544d8f318d33084da63c3395ad2c0fb9cef9f61ceeca41f5dab54ab064b7078fe596889005e412ec74d2d1ae4 + checksum: 67c7e6003d5af042d8703d11538fca9d76899f0119130b373402819ae43f0bc90d18656aa7add25a24427ccf1a0efd0804157ba83b0d4e145f06107d7d1b7433 languageName: node linkType: hard @@ -1305,27 +1316,27 @@ __metadata: linkType: hard "acorn-walk@npm:^8.1.1": - version: 8.3.1 - resolution: "acorn-walk@npm:8.3.1" - checksum: 5c8926ddb5400bc825b6baca782931f9df4ace603ba1a517f5243290fd9cdb089d52877840687b5d5c939591ebc314e2e63721514feaa37c6829c828f2b940ce + version: 8.3.2 + resolution: "acorn-walk@npm:8.3.2" + checksum: 3626b9d26a37b1b427796feaa5261faf712307a8920392c8dce9a5739fb31077667f4ad2ec71c7ac6aaf9f61f04a9d3d67ff56f459587206fc04aa31c27ef392 languageName: node linkType: hard "acorn@npm:^8.4.1, acorn@npm:^8.9.0": - version: 8.11.2 - resolution: "acorn@npm:8.11.2" + version: 8.11.3 + resolution: "acorn@npm:8.11.3" bin: acorn: bin/acorn - checksum: 818450408684da89423e3daae24e4dc9b68692db8ab49ea4569c7c5abb7a3f23669438bf129cc81dfdada95e1c9b944ee1bfca2c57a05a4dc73834a612fbf6a7 + checksum: 76d8e7d559512566b43ab4aadc374f11f563f0a9e21626dd59cb2888444e9445923ae9f3699972767f18af61df89cd89f5eaaf772d1327b055b45cb829b4a88c languageName: node linkType: hard -"agent-base@npm:^7.0.2, agent-base@npm:^7.1.0": - version: 7.1.0 - resolution: "agent-base@npm:7.1.0" +"agent-base@npm:^7.0.2, agent-base@npm:^7.1.0, agent-base@npm:^7.1.1": + version: 7.1.1 + resolution: "agent-base@npm:7.1.1" dependencies: debug: ^4.3.4 - checksum: f7828f991470a0cc22cb579c86a18cbae83d8a3cbed39992ab34fc7217c4d126017f1c74d0ab66be87f71455318a8ea3e757d6a37881b8d0f2a2c6aa55e5418f + checksum: 51c158769c5c051482f9ca2e6e1ec085ac72b5a418a9b31b4e82fe6c0a6699adb94c1c42d246699a587b3335215037091c79e0de512c516f73b6ea844202f037 languageName: node linkType: hard @@ -1473,8 +1484,8 @@ __metadata: linkType: hard "aws-cdk-lib@npm:^2.133.0": - version: 2.133.0 - resolution: "aws-cdk-lib@npm:2.133.0" + version: 2.137.0 + resolution: "aws-cdk-lib@npm:2.137.0" dependencies: "@aws-cdk/asset-awscli-v1": ^2.2.202 "@aws-cdk/asset-kubectl-v20": ^2.1.2 @@ -1488,17 +1499,17 @@ __metadata: minimatch: ^3.1.2 punycode: ^2.3.1 semver: ^7.6.0 - table: ^6.8.1 + table: ^6.8.2 yaml: 1.10.2 peerDependencies: constructs: ^10.0.0 - checksum: a9be8aef427573f0a89cecf34e13048b86ec1082f714a984df8088da485a4496e50f75a367b85035a22193fa4f8768d2557a9e2041be0b47c7a623b0665f15c0 + checksum: 384d3c2f1660c109d499cdb8aa617749ac83f41eb2384377cbf908ad1c5167c184dfe6d124d648ed89b937431d9f4a5c932917e8fa2df646fc19fe69ed8fd4d8 languageName: node linkType: hard "aws-cdk@npm:^2.133.0": - version: 2.133.0 - resolution: "aws-cdk@npm:2.133.0" + version: 2.137.0 + resolution: "aws-cdk@npm:2.137.0" dependencies: fsevents: 2.3.2 dependenciesMeta: @@ -1506,11 +1517,11 @@ __metadata: optional: true bin: cdk: bin/cdk - checksum: bdeaf2b0d9246a07e21a13f23d04a189a84d7d7a9352765754c99563ee8199b2543cf35a35804c5e3ff0ca834eb090a43504a716957d87c0123ef2da6659b823 + checksum: dde8e9962013e4c41bc74cdd4442a21bc216af1cf5dad00243599135286c378fa7113abc44ef25bc904f9ea5b4acc927c69220571704bb8ccb40f6e2405f7302 languageName: node linkType: hard -"axios@npm:^1.6.7": +"axios@npm:^1.6.8": version: 1.6.8 resolution: "axios@npm:1.6.8" dependencies: @@ -1633,16 +1644,16 @@ __metadata: linkType: hard "browserslist@npm:^4.22.2": - version: 4.22.2 - resolution: "browserslist@npm:4.22.2" + version: 4.22.3 + resolution: "browserslist@npm:4.22.3" dependencies: - caniuse-lite: ^1.0.30001565 - electron-to-chromium: ^1.4.601 + caniuse-lite: ^1.0.30001580 + electron-to-chromium: ^1.4.648 node-releases: ^2.0.14 update-browserslist-db: ^1.0.13 bin: browserslist: cli.js - checksum: 33ddfcd9145220099a7a1ac533cecfe5b7548ffeb29b313e1b57be6459000a1f8fa67e781cf4abee97268ac594d44134fcc4a6b2b4750ceddc9796e3a22076d9 + checksum: e62b17348e92143fe58181b02a6a97c4a98bd812d1dc9274673a54f73eec53dbed1c855ebf73e318ee00ee039f23c9a6d0e7629d24f3baef08c7a5b469742d57 languageName: node linkType: hard @@ -1672,8 +1683,8 @@ __metadata: linkType: hard "cacache@npm:^18.0.0": - version: 18.0.1 - resolution: "cacache@npm:18.0.1" + version: 18.0.2 + resolution: "cacache@npm:18.0.2" dependencies: "@npmcli/fs": ^3.1.0 fs-minipass: ^3.0.0 @@ -1687,7 +1698,7 @@ __metadata: ssri: ^10.0.0 tar: ^6.1.11 unique-filename: ^3.0.0 - checksum: 5a0b3b2ea451a0379814dc1d3c81af48c7c6db15cd8f7d72e028501ae0036a599a99bbac9687bfec307afb2760808d1c7708e9477c8c70d2b166e7d80b162a23 + checksum: 0250df80e1ad0c828c956744850c5f742c24244e9deb5b7dc81bca90f8c10e011e132ecc58b64497cc1cad9a98968676147fb6575f4f94722f7619757b17a11b languageName: node linkType: hard @@ -1712,10 +1723,10 @@ __metadata: languageName: node linkType: hard -"caniuse-lite@npm:^1.0.30001565": - version: 1.0.30001570 - resolution: "caniuse-lite@npm:1.0.30001570" - checksum: 460be2c7a9b1c8a83b6aae4226661c276d9dada6c84209dee547699cf4b28030b9d1fc29ddd7626acee77412b6401993878ea0ef3eadbf3a63ded9034896ae20 +"caniuse-lite@npm:^1.0.30001580": + version: 1.0.30001581 + resolution: "caniuse-lite@npm:1.0.30001581" + checksum: ca4e2cd9d0acf5e3c71fa2e7cd65561e4532d32b640145f634c333792074bb63de1239b35abfb6b6d372f97caf26f8d97faac7ba51ef190717ad2d3ae9c0d7a2 languageName: node linkType: hard @@ -1739,12 +1750,12 @@ __metadata: linkType: hard "cdk-nag@npm:^2.28.27": - version: 2.28.27 - resolution: "cdk-nag@npm:2.28.27" + version: 2.28.92 + resolution: "cdk-nag@npm:2.28.92" peerDependencies: aws-cdk-lib: ^2.116.0 constructs: ^10.0.5 - checksum: 208a704f021ebf695bee215d29b51fb5b0a49128371d56a2f35052fbbb61393f9fcb28baac2a0899ba10bf9857e8f079f8ba1dc5d1e86fea0664f9e722d3ea24 + checksum: b8f36d45cf9e0d42d30a8f3caaa90a7917266b768f3c323872a905b73596a1e151078cf04a06d29345dfc89150ba85544be40297e6675b80070c16cc74fef7a7 languageName: node linkType: hard @@ -1906,9 +1917,9 @@ __metadata: linkType: hard "core-js-pure@npm:^3.30.2": - version: 3.36.0 - resolution: "core-js-pure@npm:3.36.0" - checksum: 12a0588981efdc710426c688f6d5f6abaee76858ff32d21c6d7b81bc81c39b7cebb2733f8e822862b2a7f329f8fe37065a33ff6c4fd9253b3a1ad3cf636e483e + version: 3.37.0 + resolution: "core-js-pure@npm:3.37.0" + checksum: 206797d88046f4f5a62ecb9a7158bc6ba38127db2239bcbd1e85b2c8cf3cfb9bb3bbc6a312ecf0f87702f87659959d10625aeac74de6336a9303866f7010d364 languageName: node linkType: hard @@ -2032,9 +2043,9 @@ __metadata: linkType: hard "dotenv@npm:^16.3.1": - version: 16.3.1 - resolution: "dotenv@npm:16.3.1" - checksum: 15d75e7279018f4bafd0ee9706593dd14455ddb71b3bcba9c52574460b7ccaf67d5cf8b2c08a5af1a9da6db36c956a04a1192b101ee102a3e0cf8817bbcf3dfd + version: 16.4.1 + resolution: "dotenv@npm:16.4.1" + checksum: a343f0a1d156deef8c60034f797969867af4dbccfacedd4ac15fad04547e7ffe0553b58fc3b27a5837950f0d977e38e9234943fbcec4aeced4e3d044309a76ab languageName: node linkType: hard @@ -2045,10 +2056,10 @@ __metadata: languageName: node linkType: hard -"electron-to-chromium@npm:^1.4.601": - version: 1.4.615 - resolution: "electron-to-chromium@npm:1.4.615" - checksum: 9ffb1d0dac11c629bd8aa38efa7d2e3f41de943cf81fb41ab05e960e954c464c168d1f2f7e571813805e85b895279f2882bcafa551a2f23089646008d7a5bd06 +"electron-to-chromium@npm:^1.4.648": + version: 1.4.650 + resolution: "electron-to-chromium@npm:1.4.650" + checksum: cec3f3b4ec844f175d7802731f91fd6e40c85065796706dd7719a238f7ec08d057ba67dd44da89a6b349b58d9e5e082c53f0d8cbc34f5765e4910cb757a265d9 languageName: node linkType: hard @@ -2368,11 +2379,11 @@ __metadata: linkType: hard "fastq@npm:^1.6.0": - version: 1.16.0 - resolution: "fastq@npm:1.16.0" + version: 1.17.0 + resolution: "fastq@npm:1.17.0" dependencies: reusify: ^1.0.4 - checksum: 1d40ed1f100ae625e5720484e8602b7ad07649370f1cbc3e34a6b9630a0bfed6946bab0322d8a368a1e3cde87bb9bbb8d3bc2ae01a0c1f022fac1d07c04e4feb + checksum: a1c88c357a220bdc666c2df5ec6071d49bdf79ea827d92f9a9559da3ff1b4288eecca3ecbb7b6ddf0ba016eb0a4bf756bf17c411a6d10c814aecd26e939cbd06 languageName: node linkType: hard @@ -2508,7 +2519,7 @@ __metadata: languageName: node linkType: hard -"fsevents@npm:2.3.2, fsevents@npm:^2.3.2": +"fsevents@npm:2.3.2": version: 2.3.2 resolution: "fsevents@npm:2.3.2" dependencies: @@ -2518,7 +2529,17 @@ __metadata: languageName: node linkType: hard -"fsevents@patch:fsevents@2.3.2#~builtin, fsevents@patch:fsevents@^2.3.2#~builtin": +"fsevents@npm:^2.3.2": + version: 2.3.3 + resolution: "fsevents@npm:2.3.3" + dependencies: + node-gyp: latest + checksum: 11e6ea6fea15e42461fc55b4b0e4a0a3c654faa567f1877dbd353f39156f69def97a69936d1746619d656c4b93de2238bf731f6085a03a50cabf287c9d024317 + conditions: os=darwin + languageName: node + linkType: hard + +"fsevents@patch:fsevents@2.3.2#~builtin": version: 2.3.2 resolution: "fsevents@patch:fsevents@npm%3A2.3.2#~builtin::version=2.3.2&hash=df0bf1" dependencies: @@ -2527,6 +2548,15 @@ __metadata: languageName: node linkType: hard +"fsevents@patch:fsevents@^2.3.2#~builtin": + version: 2.3.3 + resolution: "fsevents@patch:fsevents@npm%3A2.3.3#~builtin::version=2.3.3&hash=df0bf1" + dependencies: + node-gyp: latest + conditions: os=darwin + languageName: node + linkType: hard + "function-bind@npm:^1.1.2": version: 1.1.2 resolution: "function-bind@npm:1.1.2" @@ -2581,17 +2611,17 @@ __metadata: linkType: hard "glob@npm:^10.2.2, glob@npm:^10.3.10": - version: 10.3.10 - resolution: "glob@npm:10.3.10" + version: 10.3.12 + resolution: "glob@npm:10.3.12" dependencies: foreground-child: ^3.1.0 - jackspeak: ^2.3.5 + jackspeak: ^2.3.6 minimatch: ^9.0.1 - minipass: ^5.0.0 || ^6.0.2 || ^7.0.0 - path-scurry: ^1.10.1 + minipass: ^7.0.4 + path-scurry: ^1.10.2 bin: glob: dist/esm/bin.mjs - checksum: 4f2fe2511e157b5a3f525a54092169a5f92405f24d2aed3142f4411df328baca13059f4182f1db1bf933e2c69c0bd89e57ae87edd8950cba8c7ccbe84f721cf3 + checksum: 2b0949d6363021aaa561b108ac317bf5a97271b8a5d7a5fac1a176e40e8068ecdcccc992f8a7e958593d501103ac06d673de92adc1efcbdab45edefe35f8d7c6 languageName: node linkType: hard @@ -2691,22 +2721,22 @@ __metadata: linkType: hard "http-proxy-agent@npm:^7.0.0": - version: 7.0.0 - resolution: "http-proxy-agent@npm:7.0.0" + version: 7.0.2 + resolution: "http-proxy-agent@npm:7.0.2" dependencies: agent-base: ^7.1.0 debug: ^4.3.4 - checksum: 48d4fac997917e15f45094852b63b62a46d0c8a4f0b9c6c23ca26d27b8df8d178bed88389e604745e748bd9a01f5023e25093722777f0593c3f052009ff438b6 + checksum: 670858c8f8f3146db5889e1fa117630910101db601fff7d5a8aa637da0abedf68c899f03d3451cac2f83bcc4c3d2dabf339b3aa00ff8080571cceb02c3ce02f3 languageName: node linkType: hard "https-proxy-agent@npm:^7.0.1": - version: 7.0.2 - resolution: "https-proxy-agent@npm:7.0.2" + version: 7.0.4 + resolution: "https-proxy-agent@npm:7.0.4" dependencies: agent-base: ^7.0.2 debug: 4 - checksum: 088969a0dd476ea7a0ed0a2cf1283013682b08f874c3bc6696c83fa061d2c157d29ef0ad3eb70a2046010bb7665573b2388d10fdcb3e410a66995e5248444292 + checksum: daaab857a967a2519ddc724f91edbbd388d766ff141b9025b629f92b9408fc83cee8a27e11a907aede392938e9c398e240d643e178408a59e4073539cde8cfe9 languageName: node linkType: hard @@ -2793,10 +2823,13 @@ __metadata: languageName: node linkType: hard -"ip@npm:^2.0.0": - version: 2.0.1 - resolution: "ip@npm:2.0.1" - checksum: d765c9fd212b8a99023a4cde6a558a054c298d640fec1020567494d257afd78ca77e37126b1a3ef0e053646ced79a816bf50621d38d5e768cdde0431fa3b0d35 +"ip-address@npm:^9.0.5": + version: 9.0.5 + resolution: "ip-address@npm:9.0.5" + dependencies: + jsbn: 1.1.0 + sprintf-js: ^1.1.3 + checksum: aa15f12cfd0ef5e38349744e3654bae649a34c3b10c77a674a167e99925d1549486c5b14730eebce9fea26f6db9d5e42097b00aa4f9f612e68c79121c71652dc languageName: node linkType: hard @@ -2953,7 +2986,7 @@ __metadata: languageName: node linkType: hard -"jackspeak@npm:^2.3.5": +"jackspeak@npm:^2.3.6": version: 2.3.6 resolution: "jackspeak@npm:2.3.6" dependencies: @@ -3457,6 +3490,13 @@ __metadata: languageName: node linkType: hard +"jsbn@npm:1.1.0": + version: 1.1.0 + resolution: "jsbn@npm:1.1.0" + checksum: 944f924f2bd67ad533b3850eee47603eed0f6ae425fd1ee8c760f477e8c34a05f144c1bd4f5a5dd1963141dc79a2c55f89ccc5ab77d039e7077f3ad196b64965 + languageName: node + linkType: hard + "jsesc@npm:^2.5.1": version: 2.5.2 resolution: "jsesc@npm:2.5.2" @@ -3616,10 +3656,10 @@ __metadata: languageName: node linkType: hard -"lru-cache@npm:^10.0.1, lru-cache@npm:^9.1.1 || ^10.0.0": - version: 10.1.0 - resolution: "lru-cache@npm:10.1.0" - checksum: 58056d33e2500fbedce92f8c542e7c11b50d7d086578f14b7074d8c241422004af0718e08a6eaae8705cee09c77e39a61c1c79e9370ba689b7010c152e6a76ab +"lru-cache@npm:^10.0.1, lru-cache@npm:^10.2.0": + version: 10.2.0 + resolution: "lru-cache@npm:10.2.0" + checksum: eee7ddda4a7475deac51ac81d7dd78709095c6fa46e8350dc2d22462559a1faa3b81ed931d5464b13d48cbd7e08b46100b6f768c76833912bc444b99c37e25db languageName: node linkType: hard @@ -3732,7 +3772,7 @@ __metadata: languageName: node linkType: hard -"minimatch@npm:9.0.3, minimatch@npm:^9.0.1": +"minimatch@npm:9.0.3": version: 9.0.3 resolution: "minimatch@npm:9.0.3" dependencies: @@ -3750,6 +3790,15 @@ __metadata: languageName: node linkType: hard +"minimatch@npm:^9.0.1": + version: 9.0.4 + resolution: "minimatch@npm:9.0.4" + dependencies: + brace-expansion: ^2.0.1 + checksum: cf717f597ec3eed7dabc33153482a2e8d49f4fd3c26e58fd9c71a94c5029a0838728841b93f46bf1263b65a8010e2ee800d0dc9b004ab8ba8b6d1ec07cc115b5 + languageName: node + linkType: hard + "minipass-collect@npm:^2.0.1": version: 2.0.1 resolution: "minipass-collect@npm:2.0.1" @@ -3817,7 +3866,7 @@ __metadata: languageName: node linkType: hard -"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.2, minipass@npm:^7.0.3": +"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.2, minipass@npm:^7.0.3, minipass@npm:^7.0.4": version: 7.0.4 resolution: "minipass@npm:7.0.4" checksum: 87585e258b9488caf2e7acea242fd7856bbe9a2c84a7807643513a338d66f368c7d518200ad7b70a508664d408aa000517647b2930c259a8b1f9f0984f344a21 @@ -3865,8 +3914,8 @@ __metadata: linkType: hard "node-gyp@npm:latest": - version: 10.0.1 - resolution: "node-gyp@npm:10.0.1" + version: 10.1.0 + resolution: "node-gyp@npm:10.1.0" dependencies: env-paths: ^2.2.0 exponential-backoff: ^3.1.1 @@ -3880,7 +3929,7 @@ __metadata: which: ^4.0.0 bin: node-gyp: bin/node-gyp.js - checksum: 60a74e66d364903ce02049966303a57f898521d139860ac82744a5fdd9f7b7b3b61f75f284f3bfe6e6add3b8f1871ce305a1d41f775c7482de837b50c792223f + checksum: 72e2ab4b23fc32007a763da94018f58069fc0694bf36115d49a2b195c8831e12cf5dd1e7a3718fa85c06969aedf8fc126722d3b672ec1cb27e06ed33caee3c60 languageName: node linkType: hard @@ -4089,13 +4138,13 @@ __metadata: languageName: node linkType: hard -"path-scurry@npm:^1.10.1": - version: 1.10.1 - resolution: "path-scurry@npm:1.10.1" +"path-scurry@npm:^1.10.2": + version: 1.10.2 + resolution: "path-scurry@npm:1.10.2" dependencies: - lru-cache: ^9.1.1 || ^10.0.0 + lru-cache: ^10.2.0 minipass: ^5.0.0 || ^6.0.2 || ^7.0.0 - checksum: e2557cff3a8fb8bc07afdd6ab163a92587884f9969b05bbbaf6fe7379348bfb09af9ed292af12ed32398b15fb443e81692047b786d1eeb6d898a51eb17ed7d90 + checksum: 6739b4290f7d1a949c61c758b481c07ac7d1a841964c68cf5e1fa153d7e18cbde4872b37aadf9c5173c800d627f219c47945859159de36c977dd82419997b9b8 languageName: node linkType: hard @@ -4153,11 +4202,11 @@ __metadata: linkType: hard "prettier@npm:^3.2.4": - version: 3.2.4 - resolution: "prettier@npm:3.2.4" + version: 3.2.5 + resolution: "prettier@npm:3.2.5" bin: prettier: bin/prettier.cjs - checksum: 6ec9385a836e0b9bac549e585101c086d1521c31d7b882d5c8bb7d7646da0693da5f31f4fff6dc080710e5e2d34c85e6fb2f8766876b3645c8be2f33b9c3d1a3 + checksum: 2ee4e1417572372afb7a13bb446b34f20f1bf1747db77cf6ccaf57a9be005f2f15c40f903d41a6b79eec3f57fff14d32a20fb6dee1f126da48908926fe43c311 languageName: node linkType: hard @@ -4432,24 +4481,24 @@ __metadata: languageName: node linkType: hard -"socks-proxy-agent@npm:^8.0.1": - version: 8.0.2 - resolution: "socks-proxy-agent@npm:8.0.2" +"socks-proxy-agent@npm:^8.0.3": + version: 8.0.3 + resolution: "socks-proxy-agent@npm:8.0.3" dependencies: - agent-base: ^7.0.2 + agent-base: ^7.1.1 debug: ^4.3.4 socks: ^2.7.1 - checksum: 4fb165df08f1f380881dcd887b3cdfdc1aba3797c76c1e9f51d29048be6e494c5b06d68e7aea2e23df4572428f27a3ec22b3d7c75c570c5346507433899a4b6d + checksum: 8fab38821c327c190c28f1658087bc520eb065d55bc07b4a0fdf8d1e0e7ad5d115abbb22a95f94f944723ea969dd771ad6416b1e3cde9060c4c71f705c8b85c5 languageName: node linkType: hard "socks@npm:^2.7.1": - version: 2.7.1 - resolution: "socks@npm:2.7.1" + version: 2.8.3 + resolution: "socks@npm:2.8.3" dependencies: - ip: ^2.0.0 + ip-address: ^9.0.5 smart-buffer: ^4.2.0 - checksum: 259d9e3e8e1c9809a7f5c32238c3d4d2a36b39b83851d0f573bfde5f21c4b1288417ce1af06af1452569cd1eb0841169afd4998f0e04ba04656f6b7f0e46d748 + checksum: 7a6b7f6eedf7482b9e4597d9a20e09505824208006ea8f2c49b71657427f3c137ca2ae662089baa73e1971c62322d535d9d0cf1c9235cf6f55e315c18203eadd languageName: node linkType: hard @@ -4480,6 +4529,13 @@ __metadata: languageName: node linkType: hard +"sprintf-js@npm:^1.1.3": + version: 1.1.3 + resolution: "sprintf-js@npm:1.1.3" + checksum: a3fdac7b49643875b70864a9d9b469d87a40dfeaf5d34d9d0c5b1cda5fd7d065531fcb43c76357d62254c57184a7b151954156563a4d6a747015cfb41021cad0 + languageName: node + linkType: hard + "sprintf-js@npm:~1.0.2": version: 1.0.3 resolution: "sprintf-js@npm:1.0.3" @@ -4488,14 +4544,14 @@ __metadata: linkType: hard "sqs-dlq-monitoring@npm:^1.2.0": - version: 1.2.0 - resolution: "sqs-dlq-monitoring@npm:1.2.0" + version: 1.2.4 + resolution: "sqs-dlq-monitoring@npm:1.2.4" dependencies: - axios: ^1.6.7 + axios: ^1.6.8 peerDependencies: aws-cdk-lib: ^2.60.0 constructs: ^10.0.5 - checksum: f892160824f2d539048ea13bdf66d2f04d47e2149ea60b61ce266b34d181e988aa24e6596b79d03c00eb87da36ceb2570ae185c167c35c993d69daabaf19c0ce + checksum: 375579c54c58d49c31a4fe0f86386606d366c2458e09a1350533217d3313d1404ded3ddbe037883e644e528118b71e5811e598d2b2d10703d018ff5a14f4c26c languageName: node linkType: hard @@ -4632,16 +4688,16 @@ __metadata: languageName: node linkType: hard -"table@npm:^6.8.1": - version: 6.8.1 - resolution: "table@npm:6.8.1" +"table@npm:^6.8.2": + version: 6.8.2 + resolution: "table@npm:6.8.2" dependencies: ajv: ^8.0.1 lodash.truncate: ^4.4.2 slice-ansi: ^4.0.0 string-width: ^4.2.3 strip-ansi: ^6.0.1 - checksum: 08249c7046125d9d0a944a6e96cfe9ec66908d6b8a9db125531be6eb05fa0de047fd5542e9d43b4f987057f00a093b276b8d3e19af162a9c40db2681058fd306 + checksum: 61188652f53a980d1759ca460ca8dea5c5322aece3210457e7084882f053c2b6a870041295e08a82cb1d676e31b056406845d94b0abf3c79a4b104777bec413b languageName: node linkType: hard @@ -4701,17 +4757,17 @@ __metadata: linkType: hard "ts-api-utils@npm:^1.0.1": - version: 1.0.3 - resolution: "ts-api-utils@npm:1.0.3" + version: 1.3.0 + resolution: "ts-api-utils@npm:1.3.0" peerDependencies: typescript: ">=4.2.0" - checksum: 441cc4489d65fd515ae6b0f4eb8690057add6f3b6a63a36073753547fb6ce0c9ea0e0530220a0b282b0eec535f52c4dfc315d35f8a4c9a91c0def0707a714ca6 + checksum: c746ddabfdffbf16cb0b0db32bb287236a19e583057f8649ee7c49995bb776e1d3ef384685181c11a1a480369e022ca97512cb08c517b2d2bd82c83754c97012 languageName: node linkType: hard "ts-jest@npm:^29.1.1": - version: 29.1.1 - resolution: "ts-jest@npm:29.1.1" + version: 29.1.2 + resolution: "ts-jest@npm:29.1.2" dependencies: bs-logger: 0.x fast-json-stable-stringify: 2.x @@ -4738,7 +4794,7 @@ __metadata: optional: true bin: ts-jest: cli.js - checksum: a8c9e284ed4f819526749f6e4dc6421ec666f20ab44d31b0f02b4ed979975f7580b18aea4813172d43e39b29464a71899f8893dd29b06b4a351a3af8ba47b402 + checksum: a0ce0affc1b716c78c9ab55837829c42cb04b753d174a5c796bb1ddf9f0379fc20647b76fbe30edb30d9b23181908138d6b4c51ef2ae5e187b66635c295cefd5 languageName: node linkType: hard From 1ff4353884d5c63c791fdb2d92d4371804cf4ec2 Mon Sep 17 00:00:00 2001 From: alexiswl <8197659+alexiswl@users.noreply.github.com> Date: Mon, 22 Apr 2024 11:50:43 +1000 Subject: [PATCH 16/16] Move python-lambda-layer ESLint ignore for beforeBinding command Run prettier --write for bssh tools lambda layer --- .../python-lambda-layer/index.ts | 1 + .../constructs/bs-runs-upload-manager/index.ts | 2 +- .../stacks/bs-runs-upload-manager/deploy/stack.ts | 13 +++++-------- .../stateless/statelessStackCollectionClass.ts | 6 ++++-- 4 files changed, 11 insertions(+), 11 deletions(-) rename lib/workload/{stateless/constructs => components}/python-lambda-layer/index.ts (94%) diff --git a/lib/workload/stateless/constructs/python-lambda-layer/index.ts b/lib/workload/components/python-lambda-layer/index.ts similarity index 94% rename from lib/workload/stateless/constructs/python-lambda-layer/index.ts rename to lib/workload/components/python-lambda-layer/index.ts index e01987a8e..0f6d67bef 100644 --- a/lib/workload/stateless/constructs/python-lambda-layer/index.ts +++ b/lib/workload/components/python-lambda-layer/index.ts @@ -24,6 +24,7 @@ export class PythonLambdaLayerConstruct extends Construct { description: props.layer_description, bundling: { commandHooks: { + // eslint-disable-next-line @typescript-eslint/no-unused-vars beforeBundling(inputDir: string, outputDir: string): string[] { return []; }, diff --git a/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/constructs/bs-runs-upload-manager/index.ts b/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/constructs/bs-runs-upload-manager/index.ts index 6022f9a2a..95d6f03a1 100644 --- a/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/constructs/bs-runs-upload-manager/index.ts +++ b/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/constructs/bs-runs-upload-manager/index.ts @@ -9,7 +9,7 @@ import { DefinitionBody } from 'aws-cdk-lib/aws-stepfunctions'; import * as secretsManager from 'aws-cdk-lib/aws-secretsmanager'; import { PythonFunction } from '@aws-cdk/aws-lambda-python-alpha'; import { IRole } from 'aws-cdk-lib/aws-iam'; -import { PythonLambdaLayerConstruct } from '../../../../../constructs/python-lambda-layer'; +import { PythonLambdaLayerConstruct } from '../../../../../../components/python-lambda-layer'; interface BsRunsUploadManagerConstructProps { /* Stack objects */ diff --git a/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/stack.ts b/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/stack.ts index a87c3c987..cd4fc777e 100644 --- a/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/stack.ts +++ b/lib/workload/stateless/stacks/bs-runs-upload-manager/deploy/stack.ts @@ -4,7 +4,7 @@ import { BsRunsUploadManagerConstruct } from './constructs/bs-runs-upload-manage import * as secretsManager from 'aws-cdk-lib/aws-secretsmanager'; import * as events from 'aws-cdk-lib/aws-events'; import path from 'path'; -import { PythonLambdaLayerConstruct } from '../../../constructs/python-lambda-layer'; +import { PythonLambdaLayerConstruct } from '../../../../components/python-lambda-layer'; export interface BsRunsUploadManagerConfig { // Define construct properties here @@ -22,13 +22,10 @@ export class BsRunsUploadManagerStack extends cdk.Stack { super(scope, id, props); // Set lambda layer arn object - const lambda_layer_obj = new PythonLambdaLayerConstruct( - this, - 'bssh_tools_lambda_layer', - { - layer_name: "BSSHToolsLambdaLayer", - layer_description: 'layer to enable the manager tools layer', - layer_directory: path.join(__dirname, '../layers') + const lambda_layer_obj = new PythonLambdaLayerConstruct(this, 'bssh_tools_lambda_layer', { + layer_name: 'BSSHToolsLambdaLayer', + layer_description: 'layer to enable the manager tools layer', + layer_directory: path.join(__dirname, '../layers'), }); const ica_access_token_secret_obj = secretsManager.Secret.fromSecretNameV2( diff --git a/lib/workload/stateless/statelessStackCollectionClass.ts b/lib/workload/stateless/statelessStackCollectionClass.ts index 65bc2ba1a..8f3f8f36d 100644 --- a/lib/workload/stateless/statelessStackCollectionClass.ts +++ b/lib/workload/stateless/statelessStackCollectionClass.ts @@ -14,8 +14,10 @@ import { SequenceRunManagerStack, SequenceRunManagerStackProps, } from './stacks/sequence-run-manager/deploy/stack'; -import { BsRunsUploadManagerStackProps } from './stacks/bs-runs-upload-manager/deploy/stack'; -import { BsRunsUploadManagerStack } from './stacks/bs-runs-upload-manager/deploy/stack'; +import { + BsRunsUploadManagerStack, + BsRunsUploadManagerStackProps, +} from './stacks/bs-runs-upload-manager/deploy/stack'; export interface StatelessStackCollectionProps { postgresManagerStackProps: PostgresManagerStackProps;