From a0d30d83ae9412842385e46f93b11bbf66e7cac0 Mon Sep 17 00:00:00 2001 From: drduhe Date: Fri, 9 Aug 2024 13:20:17 -0600 Subject: [PATCH] fix: optimizing deploymnets --- .gitignore | 1 + lib/index.ts | 3 - lib/osml/authorizer/authorizor_function.ts | 44 +++- lib/osml/data_catalog/dc_dataplane.ts | 30 +-- lib/osml/data_intake/di_dataplane.ts | 18 +- lib/osml/model_endpoint/me_sm_endpoint.ts | 13 +- lib/osml/model_endpoint/me_test_endpoints.ts | 38 ++- lib/osml/model_runner/mr_dataplane.ts | 26 +- .../model_runner/roles/mr_execution_role.ts | 14 -- lib/osml/osml_container.ts | 160 +++++++----- lib/osml/osml_ecr_deployment.ts | 160 ------------ lib/osml/osml_restapi.ts | 17 +- .../tile_server/testing/ts_test_runner.ts | 69 ----- .../testing/ts_test_runner_container.ts | 149 ----------- lib/osml/tile_server/ts_dataplane.ts | 136 ++++++++-- package-lock.json | 235 +++++++++++------- .../authorizor/authorizor_function.test.ts | 11 +- test/osml/data_catalog/dc_dataplane.test.ts | 2 +- .../model_endpoint/me_test_endpoints.test.ts | 2 +- test/osml/model_runner/mr_dataplane.test.ts | 7 +- test/osml/model_runner/mr_monitoring.test.ts | 2 +- test/osml/osml_container.test.ts | 15 +- test/osml/osml_restapi.test.ts | 10 +- test/osml/osml_roles.test.ts | 2 +- test/osml/osml_vpc.test.ts | 2 +- .../testing/ts_test_runner.test.ts | 69 ----- .../testing/ts_test_runner_container.test.ts | 61 ----- test/osml/tile_server/ts_dataplane.test.ts | 7 +- 28 files changed, 500 insertions(+), 803 deletions(-) delete mode 100644 lib/osml/osml_ecr_deployment.ts delete mode 100644 lib/osml/tile_server/testing/ts_test_runner.ts delete mode 100644 lib/osml/tile_server/testing/ts_test_runner_container.ts delete mode 100644 test/osml/tile_server/testing/ts_test_runner.test.ts delete mode 100644 test/osml/tile_server/testing/ts_test_runner_container.test.ts diff --git a/.gitignore b/.gitignore index 0a4c449..5e9e828 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ dist/ dist-electron/ release/ dist-ssr/ +Dockerfile.tmp # macOS system files .DS_Store diff --git a/lib/index.ts b/lib/index.ts index 8685d24..898f904 100644 --- a/lib/index.ts +++ b/lib/index.ts @@ -14,7 +14,6 @@ export * from "./osml/osml_account"; export * from "./osml/osml_bucket"; export * from "./osml/osml_queue"; export * from "./osml/osml_repository"; -export * from "./osml/osml_ecr_deployment"; export * from "./osml/model_endpoint/me_test_endpoints"; export * from "./osml/model_endpoint/me_sm_endpoint"; export * from "./osml/model_endpoint/me_http_endpoint"; @@ -30,5 +29,3 @@ export * from "./osml/data_catalog/dc_dataplane"; export * from "./osml/data_catalog/roles/dc_lambda_role"; export * from "./osml/tile_server/ts_dataplane"; export * from "./osml/tile_server/roles/ts_task_role"; -export * from "./osml/tile_server/testing/ts_test_runner_container"; -export * from "./osml/tile_server/testing/ts_test_runner"; diff --git a/lib/osml/authorizer/authorizor_function.ts b/lib/osml/authorizer/authorizor_function.ts index ce2b5fc..4ca260b 100644 --- a/lib/osml/authorizer/authorizor_function.ts +++ b/lib/osml/authorizer/authorizor_function.ts @@ -1,10 +1,13 @@ /* * Copyright 2024 Amazon.com, Inc. or its affiliates. */ +import { SecurityGroup } from "aws-cdk-lib/aws-ec2"; +import { IRole } from "aws-cdk-lib/aws-iam"; import { Code, Function, Runtime } from "aws-cdk-lib/aws-lambda"; import { Construct } from "constructs"; import { OSMLAuth } from "../osml_auth"; +import { OSMLVpc } from "../osml_vpc"; /** * Represents the properties required to configure the OSMLAuthorizer Construct. @@ -24,15 +27,42 @@ export interface OSMLAuthorizerProps { * @type {string} */ name: string; + + /** + * The OSML VPC (Virtual Private Cloud) configuration for the Dataplane. + * @type {OSMLVpc} + */ + osmlVpc: OSMLVpc; + + /** + * The optional security group ID to use for this resource. + * @type {string} + */ + securityGroup?: string; + + /** + * The optional IAM role for the Lambda function. + */ + lambdaRole?: IRole; } /** * Represents the construct that creates Authorizer Lambda function */ export class OSMLAuthorizer extends Construct { + /** + * The Lambda function used as the Authorizer. + * @type {Function} + */ // eslint-disable-next-line @typescript-eslint/ban-types public authorizerFunction: Function; + /** + * The ID of the security group associated with the Authorizer function. + * @type {string} + */ + public securityGroupId: string; + /** * Creates an instance of OSMLAuthorizer Lambda Function * @param {Construct} scope - The scope/stack in which to define this construct. @@ -42,11 +72,23 @@ export class OSMLAuthorizer extends Construct { constructor(scope: Construct, id: string, props: OSMLAuthorizerProps) { super(scope, id); + this.securityGroupId = + props.securityGroup ?? props.osmlVpc.vpcDefaultSecurityGroup; this.authorizerFunction = new Function(this, `AuthorizerFunction${id}`, { functionName: `${props.name}-AuthorizerFunction`, runtime: Runtime.PYTHON_3_11, + vpc: props.osmlVpc.vpc, + securityGroups: [ + SecurityGroup.fromSecurityGroupId( + this, + "AuthorizorImportSecurityGroup", + this.securityGroupId + ) + ], + vpcSubnets: props.osmlVpc.selectedSubnets, + role: props.lambdaRole, code: Code.fromAsset( - "lib/osml-cdk-constructs/lib/osml/osml_authorizer/lambda", + "lib/osml-cdk-constructs/lib/osml/authorizer/lambda", { bundling: { image: Runtime.PYTHON_3_11.bundlingImage, diff --git a/lib/osml/data_catalog/dc_dataplane.ts b/lib/osml/data_catalog/dc_dataplane.ts index fab10aa..31a8fed 100644 --- a/lib/osml/data_catalog/dc_dataplane.ts +++ b/lib/osml/data_catalog/dc_dataplane.ts @@ -174,7 +174,7 @@ export class DCDataplaneConfig extends BaseConfig { public STAC_CONTAINER_BUILD_TARGET: string; /** - * The relative Dockerfile to use to build the STAC API Lambda container. + * The relative Dockerfile.stac to use to build the STAC API Lambda container. * @default "docker/Dockerfile.stac" */ public STAC_CONTAINER_DOCKERFILE: string; @@ -185,6 +185,12 @@ export class DCDataplaneConfig extends BaseConfig { */ public STAC_CONTAINER_REPOSITORY: string; + /** + * Whether to build container resources from source. + * @default "false" + */ + public BUILD_FROM_SOURCE: boolean; + /** * Creates an instance of DCDataplaneConfig. * @param config - The configuration object for DCDataplane. @@ -213,12 +219,11 @@ export class DCDataplaneConfig extends BaseConfig { CONTAINER_BUILD_PATH: "lib/osml-data-intake/", INGEST_CONTAINER_URI: "awsosml/osml-data-intake-ingest:latest", INGEST_CONTAINER_BUILD_TARGET: "ingest", - INGEST_CONTAINER_REPOSITORY: "data-intake-ingest", INGEST_CONTAINER_DOCKERFILE: "docker/Dockerfile.ingest", STAC_CONTAINER_URI: "awsosml/osml-data-intake-stac:latest", STAC_CONTAINER_BUILD_TARGET: "stac", - STAC_CONTAINER_REPOSITORY: "data-intake-stac", STAC_CONTAINER_DOCKERFILE: "docker/Dockerfile.stac", + BUILD_FROM_SOURCE: false, ...config }); } @@ -263,11 +268,6 @@ export interface DCDataplaneProps { */ auth?: OSMLAuth; - /** - * Optional flag to instruct building data intake container from source. - */ - buildFromSource?: boolean; - /** * Custom configuration for the DCDataplane Construct (optional). * @type {DCDataplaneConfig | undefined} @@ -354,13 +354,12 @@ export class DCDataplane extends Construct { // Build the ingest Lambda container this.ingestContainer = new OSMLContainer(this, "DCIngestContainer", { account: props.account, - buildFromSource: props.buildFromSource, - osmlVpc: props.osmlVpc, + buildDockerImageCode: true, + buildFromSource: this.config.BUILD_FROM_SOURCE, config: { CONTAINER_URI: this.config.INGEST_CONTAINER_URI, CONTAINER_BUILD_PATH: this.config.CONTAINER_BUILD_PATH, CONTAINER_BUILD_TARGET: this.config.INGEST_CONTAINER_BUILD_TARGET, - CONTAINER_REPOSITORY: this.config.INGEST_CONTAINER_REPOSITORY, CONTAINER_DOCKERFILE: this.config.INGEST_CONTAINER_DOCKERFILE } }); @@ -368,13 +367,12 @@ export class DCDataplane extends Construct { // Build the STAC API Lambda container this.stacContainer = new OSMLContainer(this, "DCSTACContainer", { account: props.account, - buildFromSource: props.buildFromSource, - osmlVpc: props.osmlVpc, + buildDockerImageCode: true, + buildFromSource: this.config.BUILD_FROM_SOURCE, config: { CONTAINER_URI: this.config.STAC_CONTAINER_URI, CONTAINER_BUILD_PATH: this.config.CONTAINER_BUILD_PATH, CONTAINER_BUILD_TARGET: this.config.STAC_CONTAINER_BUILD_TARGET, - CONTAINER_REPOSITORY: this.config.STAC_CONTAINER_REPOSITORY, CONTAINER_DOCKERFILE: this.config.STAC_CONTAINER_DOCKERFILE } }); @@ -448,7 +446,9 @@ export class DCDataplane extends Construct { name: this.config.SERVICE_NAME_ABBREVIATION, apiStageName: this.config.STAC_FASTAPI_ROOT_PATH, integration: new LambdaIntegration(this.stacFunction), - auth: props.auth + auth: props.auth, + osmlVpc: props.osmlVpc, + lambdaRole: this.lambdaRole }); } diff --git a/lib/osml/data_intake/di_dataplane.ts b/lib/osml/data_intake/di_dataplane.ts index ab01a3f..30155bb 100644 --- a/lib/osml/data_intake/di_dataplane.ts +++ b/lib/osml/data_intake/di_dataplane.ts @@ -95,10 +95,10 @@ export class DIDataplaneConfig extends BaseConfig { public CONTAINER_DOCKERFILE: string; /** - * The repository name for the TileServer. - * @default "data-intake" + * Whether to build container resources from source. + * @default "false" */ - public CONTAINER_REPOSITORY: string; + public BUILD_FROM_SOURCE: boolean; /** * Constructor for DIDataplane Construct. @@ -120,7 +120,7 @@ export class DIDataplaneConfig extends BaseConfig { CONTAINER_BUILD_PATH: "lib/osml-data-intake", CONTAINER_BUILD_TARGET: "intake", CONTAINER_DOCKERFILE: "docker/Dockerfile.intake", - CONTAINER_REPOSITORY: "data-intake", + BUILD_FROM_SOURCE: false, ...config }); } @@ -166,11 +166,6 @@ export interface DIDataplaneProps { */ stacTopic?: ITopic; - /** - * Optional flag to instruct building data intake container from source. - */ - buildFromSource?: boolean; - /** * Custom configuration for the DIDataplane Construct (optional). * @type {DIDataplaneConfig | undefined} @@ -257,13 +252,12 @@ export class DIDataplane extends Construct { // Build the lambda container image this.diContainer = new OSMLContainer(this, "DIContainer", { account: props.account, - buildFromSource: props.buildFromSource, - osmlVpc: props.osmlVpc, + buildDockerImageCode: true, + buildFromSource: this.config.BUILD_FROM_SOURCE, config: { CONTAINER_URI: this.config.CONTAINER_SOURCE_URI, CONTAINER_BUILD_PATH: this.config.CONTAINER_BUILD_PATH, CONTAINER_BUILD_TARGET: this.config.CONTAINER_BUILD_TARGET, - CONTAINER_REPOSITORY: this.config.CONTAINER_REPOSITORY, CONTAINER_DOCKERFILE: this.config.CONTAINER_DOCKERFILE } }); diff --git a/lib/osml/model_endpoint/me_sm_endpoint.ts b/lib/osml/model_endpoint/me_sm_endpoint.ts index 148ed80..c8b0c85 100644 --- a/lib/osml/model_endpoint/me_sm_endpoint.ts +++ b/lib/osml/model_endpoint/me_sm_endpoint.ts @@ -38,16 +38,15 @@ export class MESMEndpointConfig extends BaseConfig { */ public SECURITY_GROUP_ID: string; - /** - * The access mode for the model repository (e.g., "ReadWrite" or "ReadOnly"). - */ - public REPOSITORY_ACCESS_MODE: string; - /** * A JSON object which includes ENV variables to be put into the model container. */ public CONTAINER_ENV: Record; + /** + * The repository access mode to use for the SageMaker endpoint container. + */ + public REPOSITORY_ACCESS_MODE: string; /** * Creates an instance of MESMEndpointConfig. * @param config - The configuration object for MESMEndpoint. @@ -82,7 +81,7 @@ export interface MESMEndpointProps { * * @type {string} */ - ecrContainerUri: string; + containerImageUri: string; /** * The name of the machine learning model. @@ -156,7 +155,7 @@ export class MESMEndpoint extends Construct { executionRoleArn: props.roleArn, containers: [ { - image: props.ecrContainerUri, + image: props.containerImageUri, environment: this.config.CONTAINER_ENV, imageConfig: { repositoryAccessMode: this.config.REPOSITORY_ACCESS_MODE diff --git a/lib/osml/model_endpoint/me_test_endpoints.ts b/lib/osml/model_endpoint/me_test_endpoints.ts index 0632485..de09057 100644 --- a/lib/osml/model_endpoint/me_test_endpoints.ts +++ b/lib/osml/model_endpoint/me_test_endpoints.ts @@ -151,15 +151,15 @@ export class METestEndpointsConfig extends BaseConfig { public CONTAINER_BUILD_TARGET: string; /** - * The repository name for the container. - * @default "model-container" + * The Dockerfile to build the container. */ - public CONTAINER_REPOSITORY: string; + public CONTAINER_DOCKERFILE?: string; /** - * The Dockerfile to build the container. + * Whether to build container resources from source. + * @default "false" */ - public CONTAINER_DOCKERFILE?: string; + public BUILD_FROM_SOURCE: false; /** * Constructor for METestEndpointsConfig. @@ -192,8 +192,8 @@ export class METestEndpointsConfig extends BaseConfig { CONTAINER_URI: "awsosml/osml-models:latest", CONTAINER_BUILD_PATH: "lib/osml-models", CONTAINER_BUILD_TARGET: "osml_model", - CONTAINER_REPOSITORY: "model-container", CONTAINER_DOCKERFILE: "Dockerfile", + BUILD_FROM_SOURCE: false, ...config }); } @@ -233,13 +233,6 @@ export interface METestEndpointsProps { */ smRole?: IRole; - /** - * Optional flag to instruct building model container from source. - * - * @type {boolean} - */ - buildFromSource?: boolean; - /** * (Optional) Configuration settings for test model endpoints. * @@ -342,13 +335,11 @@ export class METestEndpoints extends Construct { ) { this.modelContainer = new OSMLContainer(this, "MEContainer", { account: props.account, - osmlVpc: props.osmlVpc, - buildFromSource: props.buildFromSource, + buildFromSource: this.config.BUILD_FROM_SOURCE, config: new OSMLContainerConfig({ CONTAINER_URI: this.config.CONTAINER_URI, CONTAINER_BUILD_PATH: this.config.CONTAINER_BUILD_PATH, CONTAINER_BUILD_TARGET: this.config.CONTAINER_BUILD_TARGET, - CONTAINER_REPOSITORY: this.config.CONTAINER_REPOSITORY, CONTAINER_DOCKERFILE: this.config.CONTAINER_DOCKERFILE }) }); @@ -405,7 +396,7 @@ export class METestEndpoints extends Construct { this, "OSMLCenterPointModelEndpoint", { - ecrContainerUri: this.modelContainer.containerUri, + containerImageUri: this.modelContainer.containerUri, modelName: this.config.SM_CENTER_POINT_MODEL, roleArn: this.smRole.roleArn, instanceType: this.config.SM_CPU_INSTANCE_TYPE, @@ -414,7 +405,8 @@ export class METestEndpoints extends Construct { CONTAINER_ENV: { MODEL_SELECTION: this.config.SM_CENTER_POINT_MODEL }, - SECURITY_GROUP_ID: this.securityGroupId + SECURITY_GROUP_ID: this.securityGroupId, + REPOSITORY_ACCESS_MODE: this.modelContainer.repositoryAccessMode }) } ); @@ -427,7 +419,7 @@ export class METestEndpoints extends Construct { this, "OSMLFloodModelEndpoint", { - ecrContainerUri: this.modelContainer.containerUri, + containerImageUri: this.modelContainer.containerUri, modelName: this.config.SM_FLOOD_MODEL, roleArn: this.smRole.roleArn, instanceType: this.config.SM_CPU_INSTANCE_TYPE, @@ -436,7 +428,8 @@ export class METestEndpoints extends Construct { CONTAINER_ENV: { MODEL_SELECTION: this.config.SM_FLOOD_MODEL }, - SECURITY_GROUP_ID: this.securityGroupId + SECURITY_GROUP_ID: this.securityGroupId, + REPOSITORY_ACCESS_MODE: this.modelContainer.repositoryAccessMode }) } ); @@ -449,7 +442,7 @@ export class METestEndpoints extends Construct { this, "OSMLAircraftModelEndpoint", { - ecrContainerUri: this.modelContainer.containerUri, + containerImageUri: this.modelContainer.containerUri, modelName: this.config.SM_AIRCRAFT_MODEL, roleArn: this.smRole.roleArn, instanceType: @@ -461,7 +454,8 @@ export class METestEndpoints extends Construct { ENABLE_SEGMENTATION: "true", MODEL_SELECTION: this.config.SM_AIRCRAFT_MODEL }, - SECURITY_GROUP_ID: this.securityGroupId + SECURITY_GROUP_ID: this.securityGroupId, + REPOSITORY_ACCESS_MODE: this.modelContainer.repositoryAccessMode }) } ); diff --git a/lib/osml/model_runner/mr_dataplane.ts b/lib/osml/model_runner/mr_dataplane.ts index 971dfd0..afc168d 100644 --- a/lib/osml/model_runner/mr_dataplane.ts +++ b/lib/osml/model_runner/mr_dataplane.ts @@ -209,7 +209,7 @@ export class MRDataplaneConfig extends BaseConfig { /** * Whether to deploy a kinesis output sink stream. - * @default false + * @default true */ public MR_ENABLE_KINESIS_SINK: boolean; @@ -285,18 +285,18 @@ export class MRDataplaneConfig extends BaseConfig { */ public MR_CONTAINER_BUILD_TARGET: string; - /** - * The repository for the container image. - * @default "model-runner-container" - */ - public MR_CONTAINER_REPOSITORY: string; - /** * The relative Dockerfile to use to build the container. * @default "Dockerfile" */ public MR_CONTAINER_DOCKERFILE: string; + /** + * Whether to build container resources from source. + * @default "false" + */ + public BUILD_FROM_SOURCE: boolean; + /** * Constructor for MRDataplaneConfig. * @param config - The configuration object for MRDataplane. @@ -329,7 +329,7 @@ export class MRDataplaneConfig extends BaseConfig { MR_ENABLE_IMAGE_STATUS: true, MR_ENABLE_REGION_STATUS: false, MR_ENABLE_MONITORING: true, - MR_ENABLE_KINESIS_SINK: false, + MR_ENABLE_KINESIS_SINK: true, MR_ENABLE_S3_SINK: true, MR_AUTOSCALING_TASK_MAX_COUNT: 40, MR_AUTOSCALING_TASK_MIN_COUNT: 3, @@ -344,6 +344,7 @@ export class MRDataplaneConfig extends BaseConfig { MR_CONTAINER_BUILD_TARGET: "model_runner", MR_CONTAINER_REPOSITORY: "model-runner-container", MR_CONTAINER_DOCKERFILE: "Dockerfile", + BUILD_FROM_SOURCE: false, ...config }); } @@ -389,11 +390,6 @@ export interface MRDataplaneProps { */ executionRole?: IRole; - /** - * Optional flag to instruct building model runner container from source. - */ - buildFromSource?: boolean; - /** * Custom configuration for the MRDataplane Construct (optional). * @type {MRDataplaneConfig | undefined} @@ -696,13 +692,11 @@ export class MRDataplane extends Construct { // Build the container for model runner this.mrContainer = new OSMLContainer(this, "MRContainer", { account: props.account, - buildFromSource: props.buildFromSource, - osmlVpc: props.osmlVpc, + buildFromSource: this.config.BUILD_FROM_SOURCE, config: { CONTAINER_URI: this.config.MR_DEFAULT_CONTAINER, CONTAINER_BUILD_PATH: this.config.MR_CONTAINER_BUILD_PATH, CONTAINER_BUILD_TARGET: this.config.MR_CONTAINER_BUILD_TARGET, - CONTAINER_REPOSITORY: this.config.MR_CONTAINER_REPOSITORY, CONTAINER_DOCKERFILE: this.config.MR_CONTAINER_DOCKERFILE } }); diff --git a/lib/osml/model_runner/roles/mr_execution_role.ts b/lib/osml/model_runner/roles/mr_execution_role.ts index 38f65be..ce4a180 100644 --- a/lib/osml/model_runner/roles/mr_execution_role.ts +++ b/lib/osml/model_runner/roles/mr_execution_role.ts @@ -59,8 +59,6 @@ export class MRExecutionRole extends Construct { constructor(scope: Construct, id: string, props: MRExecutionRoleProps) { super(scope, id); - const containerRepositoryName = new MRDataplaneConfig() - .MR_CONTAINER_REPOSITORY; const firelensLogGroupName = `/aws/${ new MRDataplaneConfig().METRICS_NAMESPACE }/MRFireLens`; @@ -91,18 +89,6 @@ export class MRExecutionRole extends Construct { actions: ["ecr:GetAuthorizationToken"], resources: ["*"] }), - new PolicyStatement({ - effect: Effect.ALLOW, - actions: [ - "ecr:BatchCheckLayerAvailability", - "ecr:GetDownloadUrlForLayer", - "ecr:BatchGetImage", - "ecr:DescribeRepositories" - ], - resources: [ - `arn:${this.partition}:ecr:${props.account.region}:${props.account.id}:repository/${containerRepositoryName}` - ] - }), new PolicyStatement({ effect: Effect.ALLOW, actions: [ diff --git a/lib/osml/osml_container.ts b/lib/osml/osml_container.ts index 7dc9ea6..1a5dcc6 100644 --- a/lib/osml/osml_container.ts +++ b/lib/osml/osml_container.ts @@ -3,16 +3,15 @@ */ import { RemovalPolicy, SymlinkFollowMode } from "aws-cdk-lib"; -import { Repository } from "aws-cdk-lib/aws-ecr"; +import { IRepository, Repository } from "aws-cdk-lib/aws-ecr"; import { DockerImageAsset } from "aws-cdk-lib/aws-ecr-assets"; -import { ContainerImage, EcrImage } from "aws-cdk-lib/aws-ecs"; +import { ContainerImage } from "aws-cdk-lib/aws-ecs"; import { DockerImageCode } from "aws-cdk-lib/aws-lambda"; -import { DockerImageName, ECRDeployment } from "cdk-ecr-deployment"; import { Construct } from "constructs"; +import * as fs from "fs"; +import * as path from "path"; import { OSMLAccount } from "./osml_account"; -import { OSMLRepository } from "./osml_repository"; -import { OSMLVpc } from "./osml_vpc"; import { BaseConfig, ConfigType } from "./utils/base_config"; import { RegionalConfig, RegionConfig } from "./utils/regional_config"; @@ -40,11 +39,6 @@ export class OSMLContainerConfig extends BaseConfig { */ public CONTAINER_BUILD_TARGET?: string; - /** - * The repository name for the container. - */ - public CONTAINER_REPOSITORY?: string; - /** * The Dockerfile to build the container. */ @@ -76,12 +70,12 @@ export interface OSMLContainerProps { account: OSMLAccount; /** - * The OSML VPC to deploy into. + * (Optional) Flag to instruct building the Docker image code for the container. */ - osmlVpc: OSMLVpc; + buildDockerImageCode?: boolean; /** - * Optional flag to instruct building the model container from source. + * (Optional) Flag to instruct building the model container from source. */ buildFromSource?: boolean; @@ -119,17 +113,7 @@ export class OSMLContainer extends Construct { /** * The ECR repository for the container image. */ - public repository: Repository; - - /** - * The ECR image for the container. - */ - public ecrImage: EcrImage; - - /** - * The ECR deployment for the container image. - */ - public ecrDeployment: ECRDeployment; + public repository: IRepository; /** * The Docker image code for Lambda functions. @@ -146,6 +130,16 @@ export class OSMLContainer extends Construct { */ public regionConfig: RegionConfig; + /** + * The repository access mode to assign when building model containers for SageMaker. + */ + public repositoryAccessMode: string = "Platform"; + + /** + * The repository access mode to assign when building model containers for SageMaker. + */ + public buildDockerImageCode?: boolean | undefined; + /** * Creates an instance of OSMLContainer. * @param {Construct} scope - The scope/stack in which to define this construct. @@ -161,6 +155,9 @@ export class OSMLContainer extends Construct { ? RemovalPolicy.RETAIN : RemovalPolicy.DESTROY; + // Set whether to build Docker image code for this resource + this.buildDockerImageCode = props.buildDockerImageCode; + // Check if a custom configuration was provided this.config = props.config ?? new OSMLContainerConfig(); @@ -171,17 +168,18 @@ export class OSMLContainer extends Construct { if (props.buildFromSource) { this.buildFromSource(); } else { - this.buildFromRepository(props.osmlVpc); + this.buildFromRepository(); } } /** - * Builds the container from source using Dockerfile and build path specified in the config. + * Builds the container from source using the Dockerfile and build path specified in the config. * Validates the configuration to ensure that the necessary parameters are provided. * * @throws {Error} If CONTAINER_DOCKERFILE or CONTAINER_BUILD_PATH are not set in the configuration. */ private buildFromSource(): void { + // Validate that both the Dockerfile and build path are provided in the configuration. if ( !this.config.CONTAINER_DOCKERFILE || !this.config.CONTAINER_BUILD_PATH @@ -191,6 +189,7 @@ export class OSMLContainer extends Construct { ); } + // Create a DockerImageAsset, which builds a Docker image from the specified Dockerfile and build path. this.dockerImageAsset = new DockerImageAsset(this, `DockerImageAsset`, { directory: this.config.CONTAINER_BUILD_PATH, file: this.config.CONTAINER_DOCKERFILE, @@ -198,64 +197,95 @@ export class OSMLContainer extends Construct { target: this.config.CONTAINER_BUILD_TARGET }); + // Create a ContainerImage object from the DockerImageAsset, which will be used by ECS services. this.containerImage = ContainerImage.fromDockerImageAsset( this.dockerImageAsset ); - this.dockerImageCode = DockerImageCode.fromImageAsset( - this.config.CONTAINER_BUILD_PATH, - { - file: this.config.CONTAINER_DOCKERFILE, - followSymlinks: SymlinkFollowMode.ALWAYS, - target: this.config.CONTAINER_BUILD_TARGET - } - ); - + // Store the URI of the built Docker image in the containerUri property for later use. this.containerUri = this.dockerImageAsset.imageUri; + + if (this.buildDockerImageCode) { + // Create a DockerImageCode object for Lambda using the same Docker image built from the source. + this.dockerImageCode = DockerImageCode.fromImageAsset( + this.config.CONTAINER_BUILD_PATH, + { + file: this.config.CONTAINER_DOCKERFILE, + followSymlinks: SymlinkFollowMode.ALWAYS, + target: this.config.CONTAINER_BUILD_TARGET + } + ); + } } /** - * Builds the container from an existing repository using the specified repository name and URI in the config. + * Builds the container from an existing repository using the specified repository URI in the config. * Validates the configuration to ensure that the necessary parameters are provided. * - * @param {OSMLVpc} osmlVpc - The VPC to deploy the container in. - * @throws {Error} If CONTAINER_REPOSITORY or CONTAINER_URI are not set in the configuration. + * @throws {Error} If CONTAINER_URI is not set in the configuration. */ - private buildFromRepository(osmlVpc: OSMLVpc): void { - if (!this.config.CONTAINER_REPOSITORY || !this.config.CONTAINER_URI) { + private buildFromRepository(): void { + // Validate that the CONTAINER_URI is provided in the configuration. + if (!this.config.CONTAINER_URI) { throw new Error( - "CONTAINER_REPOSITORY and CONTAINER_URI must be set in the configuration to build from a repository." + "CONTAINER_URI must be set in the configuration to use a pre-built container image." ); } - this.repository = new OSMLRepository(this, `ECRRepository`, { - repositoryName: this.config.CONTAINER_REPOSITORY, - removalPolicy: this.removalPolicy - }).repository; + // Determine the tag to use for the container image, defaulting to "latest" if not provided. + const tag = this.config.CONTAINER_TAG ?? "latest"; - this.ecrImage = new EcrImage( - this.repository, - this.config.CONTAINER_TAG - ); + // Check if the CONTAINER_URI indicates an Amazon ECR repository by checking the ARN format. + if (this.config.CONTAINER_URI.startsWith("arn:aws:ecr:")) { + // Import the existing ECR repository using the ARN provided in the CONTAINER_URI. + this.repository = Repository.fromRepositoryArn( + this, + "ImportedECRRepo", + this.config.CONTAINER_URI + ); - this.ecrDeployment = new ECRDeployment(this, `ECRDeployment`, { - src: new DockerImageName(this.config.CONTAINER_URI), - dest: new DockerImageName(this.ecrImage.imageName), - memoryLimit: 10240, - vpc: osmlVpc.vpc, - vpcSubnets: osmlVpc.selectedSubnets, - lambdaRuntime: this.regionConfig.ecrCdkDeployRuntime - }); + // Create a ContainerImage object from the imported ECR repository and specified tag. + this.containerImage = ContainerImage.fromEcrRepository( + this.repository, + tag + ); - this.containerImage = ContainerImage.fromEcrRepository( - this.repository, - this.config.CONTAINER_TAG - ); + // Set the containerUri to the full URI of the container image in ECR. + this.containerUri = this.repository.repositoryUriForTag(tag); - this.containerUri = this.repository.repositoryUriForTag( - this.config.CONTAINER_TAG - ); + if (this.buildDockerImageCode) { + // Create a DockerImageCode object for Lambda using the imported ECR repository. + this.dockerImageCode = DockerImageCode.fromEcr(this.repository); + } + } else { + // If the CONTAINER_URI does not indicate an ECR repository, assume it is a public or private Docker registry. + this.repositoryAccessMode = "Vpc"; + + // Create a ContainerImage object from the provided Docker registry URI and tag. + this.containerImage = ContainerImage.fromRegistry( + this.config.CONTAINER_URI + ); + + // Set the containerUri to the full URI of the container image in the Docker registry. + this.containerUri = this.config.CONTAINER_URI; + + if (this.buildDockerImageCode) { + // Define the Dockerfile content dynamically based on containerUri + const dockerfileContent = `FROM ${this.config.CONTAINER_URI}`; - this.dockerImageCode = DockerImageCode.fromEcr(this.repository); + // Create a temporary Dockerfile to build the Docker image with + const tmpDockerfile = "Dockerfile.tmp"; + + // Write the temp Dockerfile to the build directory + const dockerfilePath = path.join(__dirname, tmpDockerfile); + fs.writeFileSync(dockerfilePath, dockerfileContent); + + // Create a DockerImageCode object for Lambda using the DockerImageAsset + this.dockerImageCode = DockerImageCode.fromImageAsset(__dirname, { + file: tmpDockerfile, + followSymlinks: SymlinkFollowMode.ALWAYS + }); + } + } } } diff --git a/lib/osml/osml_ecr_deployment.ts b/lib/osml/osml_ecr_deployment.ts deleted file mode 100644 index ea5231c..0000000 --- a/lib/osml/osml_ecr_deployment.ts +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright 2023-2024 Amazon.com, Inc. or its affiliates. - */ - -import { RemovalPolicy } from "aws-cdk-lib"; -import { IVpc, SubnetSelection } from "aws-cdk-lib/aws-ec2"; -import { Repository } from "aws-cdk-lib/aws-ecr"; -import { ContainerImage, EcrImage } from "aws-cdk-lib/aws-ecs"; -import { Runtime } from "aws-cdk-lib/aws-lambda"; -import { DockerImageName, ECRDeployment } from "cdk-ecr-deployment"; -import { Construct } from "constructs"; - -import { OSMLAccount } from "./osml_account"; -import { OSMLRepository } from "./osml_repository"; -import { RegionalConfig } from "./utils/regional_config"; - -/** - * Interface representing the properties for the OSMLECRDeployment Construct. - * - * @interface OSMLECRDeploymentProps - */ -export interface OSMLECRDeploymentProps { - /** - * The OSML account associated with this VPC. - * - * @type {OSMLAccount} - */ - account: OSMLAccount; - - /** - * The URI of the source for the container image. - * - * @type {string} - */ - sourceUri: string; - - /** - * The name of the repository where the container image is stored. - * - * @type {string} - */ - repositoryName: string; - - /** - * The removal policy for the container. Specifies what happens when the resource is deleted. - * - * @type {RemovalPolicy} - */ - removalPolicy: RemovalPolicy; - - /** - * An optional VPC (Virtual Private Cloud) configuration for the container. - * - * @type {IVpc | undefined} - */ - vpc?: IVpc; - - /** - * An optional selection of VPC subnets for the container deployment. - * - * @type {SubnetSelection | undefined} - */ - vpcSubnets?: SubnetSelection; - - /** - * An optional lambdaRuntime for copying Docker images into ECR. - * - * @type {Runtime | undefined} - */ - lambdaRuntime?: Runtime; - - /** - * An optional tag for identifying the container. - * - * @type {string | undefined} - */ - tag?: string; -} - -/** - * Represents an AWS CDK construct for deploying a Docker container to Amazon Elastic Container Registry (ECR). - */ -export class OSMLECRDeployment extends Construct { - /** - * The tag of the Docker image. - */ - public tag: string; - - /** - * The ECR repository where the Docker image is stored. - */ - public ecrRepository: Repository; - - /** - * The ECR image object. - */ - public ecrImage: EcrImage; - - /** - * The ECR deployment object responsible for copying the Docker image asset to the repository. - */ - public ecrDeployment: ECRDeployment; - - /** - * The container image object created from the ECR repository. - */ - public containerImage: EcrImage; - - /** - * The URI of the Docker image in the ECR repository with the specified tag. - */ - public ecrContainerUri: string; - - /** - * Creates a new OSMLECRDeployment construct. - * This construct takes a Docker repository and copies it to a Docker image asset - * and deploys it to an ECR repository with the specified tag if a repository is provided. - * - * @param {Construct} scope - The scope/stack in which to define this construct. - * @param {string} id - The ID of this construct within the current scope. - * @param {OSMLECRDeploymentProps} props - The properties of this construct. - * @returns {OSMLECRDeployment} The OSMLECRDeployment construct. - */ - constructor(scope: Construct, id: string, props: OSMLECRDeploymentProps) { - super(scope, id); - - const regionConfig = RegionalConfig.getConfig(props.account.region); - - // Check if a tag is provided, otherwise set it to "latest". - this.tag = props.tag ? props.tag : "latest"; - - // Build an ECR repository for the model runner container. - this.ecrRepository = new OSMLRepository(this, `ECRRepository${id}`, { - repositoryName: props.repositoryName, - removalPolicy: props.removalPolicy - }).repository; - - // Get the latest image associated with the repository. - this.ecrImage = new EcrImage(this.ecrRepository, this.tag); - - // Copy from CDK Docker image asset to the given repository. - this.ecrDeployment = new ECRDeployment(this, `ECRDeploy${id}`, { - src: new DockerImageName(props.sourceUri), - dest: new DockerImageName(this.ecrImage.imageName), - memoryLimit: 10240, - vpc: props.vpc, - vpcSubnets: props.vpcSubnets, - lambdaRuntime: props.lambdaRuntime ?? regionConfig.ecrCdkDeployRuntime - }); - - // Build a container image object to vend. - this.containerImage = ContainerImage.fromEcrRepository( - this.ecrRepository, - this.tag - ); - - // Set the tag for the latest URI. - this.ecrContainerUri = this.ecrRepository.repositoryUriForTag(this.tag); - } -} diff --git a/lib/osml/osml_restapi.ts b/lib/osml/osml_restapi.ts index 45a7bec..45d8e63 100644 --- a/lib/osml/osml_restapi.ts +++ b/lib/osml/osml_restapi.ts @@ -11,11 +11,13 @@ import { RequestAuthorizer, RestApi } from "aws-cdk-lib/aws-apigateway"; +import { IRole } from "aws-cdk-lib/aws-iam"; import { Construct } from "constructs"; import { OSMLAuthorizer } from "./authorizer/authorizor_function"; import { OSMLAccount } from "./osml_account"; import { OSMLAuth } from "./osml_auth"; +import { OSMLVpc } from "./osml_vpc"; /** * Represents the properties required to configure the OSMLRestApi Construct. @@ -56,6 +58,17 @@ export interface OSMLRestApiProps { * @type {OSMLAuth} */ auth: OSMLAuth; + + /** + * The OSML VPC (Virtual Private Cloud) configuration for the Dataplane. + * @type {OSMLVpc} + */ + osmlVpc: OSMLVpc; + + /** + * The IAM role for the Lambda function. + */ + lambdaRole?: IRole; } /** @@ -76,7 +89,9 @@ export class OSMLRestApi extends Construct { const osmlAuthorizer = new OSMLAuthorizer(this, `Authorizer${id}`, { auth: props.auth, - name: props.name + name: props.name, + osmlVpc: props.osmlVpc, + lambdaRole: props.lambdaRole }); this.requestAuthorizer = new RequestAuthorizer( diff --git a/lib/osml/tile_server/testing/ts_test_runner.ts b/lib/osml/tile_server/testing/ts_test_runner.ts deleted file mode 100644 index 14f5337..0000000 --- a/lib/osml/tile_server/testing/ts_test_runner.ts +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2024 Amazon.com, Inc. or its affiliates. - */ - -import { Duration, RemovalPolicy } from "aws-cdk-lib"; -import { IRole } from "aws-cdk-lib/aws-iam"; -import { DockerImageCode, DockerImageFunction } from "aws-cdk-lib/aws-lambda"; -import { Construct } from "constructs"; - -import { OSMLAccount } from "../../osml_account"; -import { OSMLVpc } from "../../osml_vpc"; - -/** - * Interface representing the properties for the TSTestRunner construct. - */ -export interface TSTestRunnerProps { - /** - * The OSML deployment account. - */ - account: OSMLAccount; - - /** - * The OSML vpc to deploy into - */ - osmlVpc: OSMLVpc; - - /** - * The Docker image code to use for the lambda function - */ - dockerImageCode: DockerImageCode; - - /** - * Optional task role to be used by the TSTestContainer. - */ - taskRole?: IRole; -} - -/** - * Represents a construct responsible for deploying an ECR container image - * for the tile server test. - */ -export class TSTestRunner extends Construct { - public removalPolicy: RemovalPolicy; - public lambdaIntegRunner: DockerImageFunction; - /** - * Creates an instance of TSTestRunner. - * @param {Construct} scope - The scope/stack in which to define this construct. - * @param {string} id - The id of this construct within the current scope. - * @param {TSTestRunnerProps} props - The properties of this construct. - * @returns TSTestRunner - The TSTestContainer instance. - */ - constructor(scope: Construct, id: string, props: TSTestRunnerProps) { - super(scope, id); - - // Set the removal policy based on the provided properties - this.removalPolicy = props.account.prodLike - ? RemovalPolicy.RETAIN - : RemovalPolicy.DESTROY; - - this.lambdaIntegRunner = new DockerImageFunction(this, "TSTestRunner", { - code: props.dockerImageCode, - vpc: props.osmlVpc.vpc, - role: props.taskRole, - timeout: Duration.minutes(10), - memorySize: 1024, - functionName: "TSTestRunner" - }); - } -} diff --git a/lib/osml/tile_server/testing/ts_test_runner_container.ts b/lib/osml/tile_server/testing/ts_test_runner_container.ts deleted file mode 100644 index 9ba4c09..0000000 --- a/lib/osml/tile_server/testing/ts_test_runner_container.ts +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright 2024 Amazon.com, Inc. or its affiliates. - */ - -import { RemovalPolicy, SymlinkFollowMode } from "aws-cdk-lib"; -import { IRole } from "aws-cdk-lib/aws-iam"; -import { DockerImageCode } from "aws-cdk-lib/aws-lambda"; -import { Construct } from "constructs"; - -import { OSMLAccount } from "../../osml_account"; -import { OSMLECRDeployment } from "../../osml_ecr_deployment"; -import { OSMLVpc } from "../../osml_vpc"; - -/** - * Represents the configuration for the TSTestContainer Construct. - */ -export class TSTestRunnerContainerConfig { - /** - * Creates an instance of TSContainerConfig. - * @param {string} [TS_TEST_CONTAINER="awsosml/osml-tile-server-test:latest"] - The container image to use for the TileServer test. - * @param {string} [TS_TEST_BUILD_PATH="lib/osml-tile-server-test"] - The build path for the TileServer test. - * @param {string} [TS_TEST_BUILD_TARGET="osml_tile_sever_test"] - The build target for the TileServer test. - * @param {string} [TS_TEST_REPOSITORY="tile-server-test-container"] - The repository name for the TileServer test. - */ - constructor( - public TS_TEST_CONTAINER: string = "awsosml/osml-tile-server-test:latest", - public TS_TEST_BUILD_PATH: string = "lib/osml-tile-server-test", - public TS_TEST_BUILD_TARGET: string = "osml_tile_server_test", - public TS_TEST_REPOSITORY: string = "tile-server-test-container" - ) {} -} - -/** - * Interface representing the properties for the TSTestRunnerContainer construct. - */ -export interface TSTestRunnerContainerProps { - /** - * The OSML deployment account. - */ - account: OSMLAccount; - - /** - * The OSML vpc to deploy into - */ - osmlVpc: OSMLVpc; - - /** - * The DNS name of the Tile Server load balancer endpoint - */ - tsEndpoint: string; - - /** - * The S3 bucket name that contains test images for Tile Server - */ - tsTestImageBucket: string; - - /** - * Optional task role to be used by the TSTestContainer. - */ - taskRole?: IRole; - - /** - * Optional flag to instruct building tile server test container from source. - */ - buildFromSource?: boolean; - - /** - * Optional configuration for the TSTestContainer Construct - */ - config?: TSTestRunnerContainerConfig; -} - -/** - * Represents a construct responsible for deploying an ECR container image - * for the tile server test. - */ -export class TSTestRunnerContainer extends Construct { - public removalPolicy: RemovalPolicy; - public config: TSTestRunnerContainerConfig; - public dockerImageCode: DockerImageCode; - /** - * Creates an instance of TSTestRunnerContainer. - * @param {Construct} scope - The scope/stack in which to define this construct. - * @param {string} id - The id of this construct within the current scope. - * @param {TSTestRunnerContainerProps} props - The properties of this construct. - * @returns TSTestRunnerContainer - The TSTestRunnerContainer instance. - */ - constructor(scope: Construct, id: string, props: TSTestRunnerContainerProps) { - super(scope, id); - - // Set the removal policy based on the provided properties - this.removalPolicy = props.account.prodLike - ? RemovalPolicy.RETAIN - : RemovalPolicy.DESTROY; - - // Check if a custom configuration was provided: otherwise, create a new default configuration. - if (props.config != undefined) { - // Import the existing TSTest configuration - this.config = props.config; - } else { - // Create a new default configuration - this.config = new TSTestRunnerContainerConfig(); - } - - let ecrDeployment: OSMLECRDeployment | undefined = undefined; - const testEntrypoint: string[] = [ - "python", - "src/aws/osml/run_test.py", - "--endpoint", - props.tsEndpoint, - "--source_image_bucket", - props.tsTestImageBucket, - "-v" - ]; - - if (props.buildFromSource == true) { - // Create a container image from a Docker image asset for development environment. - this.dockerImageCode = DockerImageCode.fromImageAsset( - this.config.TS_TEST_BUILD_PATH, - { - file: "Dockerfile", - followSymlinks: SymlinkFollowMode.ALWAYS, - target: this.config.TS_TEST_BUILD_TARGET, - entrypoint: testEntrypoint - } - ); - } else { - // Create an ECR deployment for production environment. - ecrDeployment = new OSMLECRDeployment( - this, - "TSTestContainerECRDeployment", - { - account: props.account, - sourceUri: this.config.TS_TEST_CONTAINER, - repositoryName: this.config.TS_TEST_REPOSITORY, - removalPolicy: this.removalPolicy, - vpc: props.osmlVpc.vpc, - vpcSubnets: props.osmlVpc.selectedSubnets - } - ); - this.dockerImageCode = DockerImageCode.fromEcr( - ecrDeployment.ecrRepository, - { - entrypoint: testEntrypoint - } - ); - } - } -} diff --git a/lib/osml/tile_server/ts_dataplane.ts b/lib/osml/tile_server/ts_dataplane.ts index b66c2d1..c8723ce 100644 --- a/lib/osml/tile_server/ts_dataplane.ts +++ b/lib/osml/tile_server/ts_dataplane.ts @@ -39,6 +39,7 @@ import { } from "aws-cdk-lib/aws-elasticloadbalancingv2"; import { AlbTarget } from "aws-cdk-lib/aws-elasticloadbalancingv2-targets"; import { AnyPrincipal, IRole, PolicyStatement } from "aws-cdk-lib/aws-iam"; +import { DockerImageFunction } from "aws-cdk-lib/aws-lambda"; import { LogGroup, RetentionDays } from "aws-cdk-lib/aws-logs"; import { Construct } from "constructs"; @@ -60,7 +61,7 @@ import { TSTaskRole } from "./roles/ts_task_role"; */ export class TSDataplaneConfig extends BaseConfig { /** - * The name of the SQS queue for image status. + * The name of the SQS queues for image status. * @default "TSJobQueue" */ public SQS_JOB_QUEUE: string; @@ -187,15 +188,15 @@ export class TSDataplaneConfig extends BaseConfig { /** * The build target for the TileServer. - * @default "osml_tile_server" + * @default "tile_server" */ public CONTAINER_BUILD_TARGET: string; /** - * The repository name for the TileServer. - * @default "tile-server-container" + * The path to Dockerfile.tile_server to use to build the container. + * @default "docker/Dockerfile.tile_server" */ - public CONTAINER_REPOSITORY: string; + public CONTAINER_DOCKERFILE: string; /** * The default API path to use if auth was configured. @@ -203,6 +204,48 @@ export class TSDataplaneConfig extends BaseConfig { */ public API_DEFAULT_PATH: string; + /** + * Flag to determine whether to deploy the test-related components. + * @default false + */ + public DEPLOY_TEST_COMPONENTS: boolean; + + /** + * The Docker image to use for the test container. + * @default "awsosml/osml-tile-server-test:latest" + */ + public TEST_CONTAINER_URI: string; + + /** + * The build path for the test container. + * @default "lib/osml-tile-server-test" + */ + public TEST_CONTAINER_BUILD_PATH: string; + + /** + * The build target for the test container. + * @default "osml_tile_server_test" + */ + public TEST_CONTAINER_BUILD_TARGET: string; + + /** + * The repository name for the test container. + * @default "tile-server-test-container" + */ + public TEST_CONTAINER_REPOSITORY: string; + + /** + * The path to Dockerfile.ts to use to build the container. + * @default "docker/Dockerfile.integ" + */ + public TEST_CONTAINER_DOCKERFILE: string; + + /** + * Whether to build container resources from source. + * @default "false" + */ + public BUILD_FROM_SOURCE: boolean; + /** * Constructor for TSDataplaneConfig. * @param config - The configuration object for TSDataplane. @@ -229,9 +272,17 @@ export class TSDataplaneConfig extends BaseConfig { NETWORK_LOAD_BALANCER_PORT: 80, CONTAINER_URI: "awsosml/osml-tile-server:latest", CONTAINER_BUILD_PATH: "lib/osml-tile-server", - CONTAINER_BUILD_TARGET: "osml_tile_server", + CONTAINER_BUILD_TARGET: "tile_server", CONTAINER_REPOSITORY: "tile-server-container", + CONTAINER_DOCKERFILE: "docker/Dockerfile.tile_server", API_DEFAULT_PATH: "latest/viewpoints", + DEPLOY_TEST_COMPONENTS: false, + TEST_CONTAINER_URI: "awsosml/osml-tile-server-test:latest", + TEST_CONTAINER_BUILD_PATH: "lib/osml-tile-server-test", + TEST_CONTAINER_BUILD_TARGET: "integ", + TEST_CONTAINER_REPOSITORY: "tile-server-test", + TEST_CONTAINER_DOCKERFILE: "docker/Dockerfile.integ", + BUILD_FROM_SOURCE: false, ...config }); } @@ -295,11 +346,6 @@ export interface TSDataplaneProps { * @type {OSMLAuth} */ auth?: OSMLAuth; - - /** - * Optional flag to instruct building model runner container from source. - */ - buildFromSource?: boolean; } /** @@ -396,7 +442,7 @@ export class TSDataplane extends Construct { /** * Container built to power the service. */ - public container: OSMLContainer; + public tsContainer: OSMLContainer; /** * The Rest API constructed if auth was provided for this construct. @@ -408,6 +454,16 @@ export class TSDataplane extends Construct { */ public nlb: NetworkLoadBalancer; + /** + * The container to use for integration tests for this component. + */ + public testContainer: OSMLContainer; + + /** + * The Docker Lamda image to run the integration tests for this component. + */ + public lambdaIntegRunner: DockerImageFunction; + /** * Constructs an instance of TSDataplane. * @@ -499,16 +555,15 @@ export class TSDataplane extends Construct { } }); - // Build the container for model runner - this.container = new OSMLContainer(this, "TSContainer", { + // Build the container for the tile server component + this.tsContainer = new OSMLContainer(this, "TSContainer", { account: props.account, - buildFromSource: props.buildFromSource, - osmlVpc: props.osmlVpc, + buildFromSource: this.config.BUILD_FROM_SOURCE, config: { CONTAINER_URI: this.config.CONTAINER_URI, CONTAINER_BUILD_PATH: this.config.CONTAINER_BUILD_PATH, CONTAINER_BUILD_TARGET: this.config.CONTAINER_BUILD_TARGET, - CONTAINER_REPOSITORY: this.config.CONTAINER_REPOSITORY + CONTAINER_DOCKERFILE: this.config.CONTAINER_DOCKERFILE } }); @@ -547,7 +602,7 @@ export class TSDataplane extends Construct { "TSContainerDefinition", { containerName: this.config.ECS_CONTAINER_NAME, - image: this.container.containerImage, + image: this.tsContainer.containerImage, memoryLimitMiB: this.config.ECS_CONTAINER_MEMORY, cpu: this.config.ECS_CONTAINER_CPU, environment: this.buildContainerEnv(props), @@ -596,7 +651,7 @@ export class TSDataplane extends Construct { publicLoadBalancer: false } ); - this.fargateService.node.addDependency(this.container); + this.fargateService.node.addDependency(this.tsContainer); // Allow access to EFS from Fargate ECS this.fileSystem.grantRootAccess( @@ -608,8 +663,11 @@ export class TSDataplane extends Construct { this.fargateService.service.connections ); - // If we have auth enabled deploy it + // If we have auth enabled, deploy it this.buildApi(props); + + // If we have testing enabled, deploy it + this.buildTesting(props); } /** @@ -699,8 +757,44 @@ export class TSDataplane extends Construct { name: this.config.SERVICE_NAME_ABBREVIATION, apiStageName: this.config.FASTAPI_ROOT_PATH, integration: proxyIntegration, - auth: props.auth + auth: props.auth, + osmlVpc: props.osmlVpc, + lambdaRole: this.lambdaRole + }); + } + } + + /** + * Builds the configured integration testing resources the tile server. + * + * @param {TSDataplaneProps} props - The properties for configuring the MRDataplane Construct. + */ + private buildTesting(props: TSDataplaneProps): void { + if (this.config.DEPLOY_TEST_COMPONENTS) { + this.testContainer = new OSMLContainer(this, "TSTestContainer", { + account: props.account, + buildDockerImageCode: true, + buildFromSource: this.config.BUILD_FROM_SOURCE, + config: { + CONTAINER_URI: this.config.TEST_CONTAINER_URI, + CONTAINER_BUILD_PATH: this.config.TEST_CONTAINER_BUILD_PATH, + CONTAINER_BUILD_TARGET: this.config.TEST_CONTAINER_BUILD_TARGET, + CONTAINER_DOCKERFILE: this.config.TEST_CONTAINER_DOCKERFILE + } + }); + + this.lambdaIntegRunner = new DockerImageFunction(this, "TSTestRunner", { + code: this.testContainer.dockerImageCode, + vpc: props.osmlVpc.vpc, + role: props.taskRole, + timeout: Duration.minutes(10), + memorySize: 1024, + functionName: "TSTestRunner", + environment: { + TS_ENDPOINT: `http://${this.fargateService.loadBalancer.loadBalancerDnsName}/latest` + } }); + this.lambdaIntegRunner.node.addDependency(this.testContainer); } } diff --git a/package-lock.json b/package-lock.json index c67532a..223ee36 100644 --- a/package-lock.json +++ b/package-lock.json @@ -195,17 +195,17 @@ } }, "node_modules/@aws-sdk/client-iam": { - "version": "3.624.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-iam/-/client-iam-3.624.0.tgz", - "integrity": "sha512-a3Qy7AIht2nHiZPJ/HiMdyiOLiDN+iKp1R916SEbgFi9MiOyRHFeLCCPQHMf1O8YXfb0hbHr5IFnfZLfUcJaWQ==", + "version": "3.629.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-iam/-/client-iam-3.629.0.tgz", + "integrity": "sha512-MZiumI+zxArmbYQc2qzk7pbV26KZ5OTKwbRjXe9IQ91MOR21CmBf79d+WksvFRBmx6iifuoAQnQzc4I2pU1lrw==", "dev": true, "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/client-sso-oidc": "3.624.0", - "@aws-sdk/client-sts": "3.624.0", - "@aws-sdk/core": "3.624.0", - "@aws-sdk/credential-provider-node": "3.624.0", + "@aws-sdk/client-sso-oidc": "3.629.0", + "@aws-sdk/client-sts": "3.629.0", + "@aws-sdk/core": "3.629.0", + "@aws-sdk/credential-provider-node": "3.629.0", "@aws-sdk/middleware-host-header": "3.620.0", "@aws-sdk/middleware-logger": "3.609.0", "@aws-sdk/middleware-recursion-detection": "3.620.0", @@ -248,14 +248,14 @@ } }, "node_modules/@aws-sdk/client-sso": { - "version": "3.624.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.624.0.tgz", - "integrity": "sha512-EX6EF+rJzMPC5dcdsu40xSi2To7GSvdGQNIpe97pD9WvZwM9tRNQnNM4T6HA4gjV1L6Jwk8rBlG/CnveXtLEMw==", + "version": "3.629.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.629.0.tgz", + "integrity": "sha512-2w8xU4O0Grca5HmT2dXZ5fF0g39RxODtmoqHJDsK5DSt750LqDG4w3ktmBvQs3+SrpkkJOjlX5v/hb2PCxVbww==", "dev": true, "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.624.0", + "@aws-sdk/core": "3.629.0", "@aws-sdk/middleware-host-header": "3.620.0", "@aws-sdk/middleware-logger": "3.609.0", "@aws-sdk/middleware-recursion-detection": "3.620.0", @@ -297,15 +297,15 @@ } }, "node_modules/@aws-sdk/client-sso-oidc": { - "version": "3.624.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.624.0.tgz", - "integrity": "sha512-Ki2uKYJKKtfHxxZsiMTOvJoVRP6b2pZ1u3rcUb2m/nVgBPUfLdl8ZkGpqE29I+t5/QaS/sEdbn6cgMUZwl+3Dg==", + "version": "3.629.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.629.0.tgz", + "integrity": "sha512-3if0LauNJPqubGYf8vnlkp+B3yAeKRuRNxfNbHlE6l510xWGcKK/ZsEmiFmfePzKKSRrDh/cxMFMScgOrXptNg==", "dev": true, "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.624.0", - "@aws-sdk/credential-provider-node": "3.624.0", + "@aws-sdk/core": "3.629.0", + "@aws-sdk/credential-provider-node": "3.629.0", "@aws-sdk/middleware-host-header": "3.620.0", "@aws-sdk/middleware-logger": "3.609.0", "@aws-sdk/middleware-recursion-detection": "3.620.0", @@ -346,20 +346,20 @@ "node": ">=16.0.0" }, "peerDependencies": { - "@aws-sdk/client-sts": "^3.624.0" + "@aws-sdk/client-sts": "^3.629.0" } }, "node_modules/@aws-sdk/client-sts": { - "version": "3.624.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.624.0.tgz", - "integrity": "sha512-k36fLZCb2nfoV/DKK3jbRgO/Yf7/R80pgYfMiotkGjnZwDmRvNN08z4l06L9C+CieazzkgRxNUzyppsYcYsQaw==", + "version": "3.629.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.629.0.tgz", + "integrity": "sha512-RjOs371YwnSVGxhPjuluJKaxl4gcPYTAky0nPjwBime0i9/iS9nI8R8l5j7k7ec9tpFWjBPvNnThCU07pvjdzw==", "dev": true, "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/client-sso-oidc": "3.624.0", - "@aws-sdk/core": "3.624.0", - "@aws-sdk/credential-provider-node": "3.624.0", + "@aws-sdk/client-sso-oidc": "3.629.0", + "@aws-sdk/core": "3.629.0", + "@aws-sdk/credential-provider-node": "3.629.0", "@aws-sdk/middleware-host-header": "3.620.0", "@aws-sdk/middleware-logger": "3.609.0", "@aws-sdk/middleware-recursion-detection": "3.620.0", @@ -401,13 +401,14 @@ } }, "node_modules/@aws-sdk/core": { - "version": "3.624.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.624.0.tgz", - "integrity": "sha512-WyFmPbhRIvtWi7hBp8uSFy+iPpj8ccNV/eX86hwF4irMjfc/FtsGVIAeBXxXM/vGCjkdfEzOnl+tJ2XACD4OXg==", + "version": "3.629.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.629.0.tgz", + "integrity": "sha512-+/ShPU/tyIBM3oY1cnjgNA/tFyHtlWq+wXF9xEKRv19NOpYbWQ+xzNwVjGq8vR07cCRqy/sDQLWPhxjtuV/FiQ==", "dev": true, "dependencies": { "@smithy/core": "^2.3.2", "@smithy/node-config-provider": "^3.1.4", + "@smithy/property-provider": "^3.1.3", "@smithy/protocol-http": "^4.1.0", "@smithy/signature-v4": "^4.1.0", "@smithy/smithy-client": "^3.1.12", @@ -456,15 +457,15 @@ } }, "node_modules/@aws-sdk/credential-provider-ini": { - "version": "3.624.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.624.0.tgz", - "integrity": "sha512-mMoNIy7MO2WTBbdqMyLpbt6SZpthE6e0GkRYpsd0yozPt0RZopcBhEh+HG1U9Y1PVODo+jcMk353vAi61CfnhQ==", + "version": "3.629.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.629.0.tgz", + "integrity": "sha512-r9fI7BABARvVDp77DBUImQzYdvarAIdhbvpCEZib0rlpvfWu3zxE9KZcapCAAi0MPjxeDfb7RMehFQIkAP7mYw==", "dev": true, "dependencies": { "@aws-sdk/credential-provider-env": "3.620.1", "@aws-sdk/credential-provider-http": "3.622.0", "@aws-sdk/credential-provider-process": "3.620.1", - "@aws-sdk/credential-provider-sso": "3.624.0", + "@aws-sdk/credential-provider-sso": "3.629.0", "@aws-sdk/credential-provider-web-identity": "3.621.0", "@aws-sdk/types": "3.609.0", "@smithy/credential-provider-imds": "^3.2.0", @@ -477,20 +478,20 @@ "node": ">=16.0.0" }, "peerDependencies": { - "@aws-sdk/client-sts": "^3.624.0" + "@aws-sdk/client-sts": "^3.629.0" } }, "node_modules/@aws-sdk/credential-provider-node": { - "version": "3.624.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.624.0.tgz", - "integrity": "sha512-vYyGK7oNpd81BdbH5IlmQ6zfaQqU+rPwsKTDDBeLRjshtrGXOEpfoahVpG9PX0ibu32IOWp4ZyXBNyVrnvcMOw==", + "version": "3.629.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.629.0.tgz", + "integrity": "sha512-868hnVOLlXOBHk91Rl0jZIRgr/M4WJCa0nOrW9A9yidsQxuZp9P0vshDmm4hMvNZadmPIfo0Rra2MpA4RELoCw==", "dev": true, "dependencies": { "@aws-sdk/credential-provider-env": "3.620.1", "@aws-sdk/credential-provider-http": "3.622.0", - "@aws-sdk/credential-provider-ini": "3.624.0", + "@aws-sdk/credential-provider-ini": "3.629.0", "@aws-sdk/credential-provider-process": "3.620.1", - "@aws-sdk/credential-provider-sso": "3.624.0", + "@aws-sdk/credential-provider-sso": "3.629.0", "@aws-sdk/credential-provider-web-identity": "3.621.0", "@aws-sdk/types": "3.609.0", "@smithy/credential-provider-imds": "^3.2.0", @@ -520,12 +521,12 @@ } }, "node_modules/@aws-sdk/credential-provider-sso": { - "version": "3.624.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.624.0.tgz", - "integrity": "sha512-A02bayIjU9APEPKr3HudrFHEx0WfghoSPsPopckDkW7VBqO4wizzcxr75Q9A3vNX+cwg0wCN6UitTNe6pVlRaQ==", + "version": "3.629.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.629.0.tgz", + "integrity": "sha512-Lf4XOuj6jamxgGZGrVojERh5S+NS2t2S4CUOnAu6tJ5U0GPlpjhINUKlcVxJBpsIXudMGW1nkumAd3+kazCPig==", "dev": true, "dependencies": { - "@aws-sdk/client-sso": "3.624.0", + "@aws-sdk/client-sso": "3.629.0", "@aws-sdk/token-providers": "3.614.0", "@aws-sdk/types": "3.609.0", "@smithy/property-provider": "^3.1.3", @@ -1057,6 +1058,36 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.24.7.tgz", + "integrity": "sha512-hbX+lKKeUMGihnK8nvKqmXBInriT3GVjzXKFriV3YC6APGxMbP8RZNFwy91+hocLXq90Mta+HshoB31802bb8A==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-syntax-import-meta": { "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", @@ -1168,6 +1199,21 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-syntax-top-level-await": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", @@ -2374,9 +2420,9 @@ } }, "node_modules/@shikijs/core": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.12.1.tgz", - "integrity": "sha512-biCz/mnkMktImI6hMfMX3H9kOeqsInxWEyCHbSlL8C/2TR1FqfmGxTLRNwYCKsyCyxWLbB8rEqXRVZuyxuLFmA==", + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.13.0.tgz", + "integrity": "sha512-Mj5NVfbAXcD1GnwOTSPl8hBn/T8UDpfFQTptp+p41n/CbUcJtOq98WaRD7Lz3hCglYotUTHUWtzu3JhK6XlkAA==", "dev": true, "dependencies": { "@types/hast": "^3.0.4" @@ -2572,6 +2618,19 @@ "node": ">=16.0.0" } }, + "node_modules/@smithy/middleware-retry/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "dev": true, + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/@smithy/middleware-serde": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-3.0.3.tgz", @@ -3071,12 +3130,12 @@ "dev": true }, "node_modules/@types/node": { - "version": "22.1.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.1.0.tgz", - "integrity": "sha512-AOmuRF0R2/5j1knA3c6G3HOk523Ga+l+ZXltX8SF1+5oqcXijjfTd8fY3XRZqSihEu9XhtQnKYLmkFaoxgsJHw==", + "version": "22.3.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.3.0.tgz", + "integrity": "sha512-nrWpWVaDZuaVc5X84xJ0vNrLvomM205oQyLsRt7OHNZbSHslcWsvgFR7O7hire2ZonjLrWBbedmotmIlJDVd6g==", "dev": true, "dependencies": { - "undici-types": "~6.13.0" + "undici-types": "~6.18.2" } }, "node_modules/@types/stack-utils": { @@ -4018,23 +4077,26 @@ } }, "node_modules/babel-preset-current-node-syntax": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", - "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.1.0.tgz", + "integrity": "sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==", "dev": true, "dependencies": { "@babel/plugin-syntax-async-generators": "^7.8.4", "@babel/plugin-syntax-bigint": "^7.8.3", - "@babel/plugin-syntax-class-properties": "^7.8.3", - "@babel/plugin-syntax-import-meta": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", "@babel/plugin-syntax-object-rest-spread": "^7.8.3", "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-top-level-await": "^7.8.3" + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5" }, "peerDependencies": { "@babel/core": "^7.0.0" @@ -4206,9 +4268,9 @@ ] }, "node_modules/cdk-ecr-deployment": { - "version": "3.0.80", - "resolved": "https://registry.npmjs.org/cdk-ecr-deployment/-/cdk-ecr-deployment-3.0.80.tgz", - "integrity": "sha512-PmlQszz6E2KyC5GTfOZZx/jTxHK3AK9Bk/8WaYmS7/dZX1OGGX3wyN38YoCig3OP2kiVn/z5Kbsp3drAf9hJ1w==", + "version": "3.0.81", + "resolved": "https://registry.npmjs.org/cdk-ecr-deployment/-/cdk-ecr-deployment-3.0.81.tgz", + "integrity": "sha512-1xjGo5pEpm3NYGm3Cb2MTeZKcPmSS12guqLeI85XyaMHdnP6CuldQIlY9Gb2IVWNloYn1oMDCcU64u646bY8ZA==", "bundleDependencies": [ "got", "hpagent" @@ -4262,7 +4324,7 @@ } }, "node_modules/cdk-ecr-deployment/node_modules/@types/cacheable-request/node_modules/@types/node": { - "version": "22.1.0", + "version": "22.2.0", "dev": true, "inBundle": true, "license": "MIT", @@ -4292,7 +4354,7 @@ } }, "node_modules/cdk-ecr-deployment/node_modules/@types/keyv/node_modules/@types/node": { - "version": "22.1.0", + "version": "22.2.0", "dev": true, "inBundle": true, "license": "MIT", @@ -4316,7 +4378,7 @@ } }, "node_modules/cdk-ecr-deployment/node_modules/@types/responselike/node_modules/@types/node": { - "version": "22.1.0", + "version": "22.2.0", "dev": true, "inBundle": true, "license": "MIT", @@ -4589,9 +4651,9 @@ "license": "ISC" }, "node_modules/cdk-nag": { - "version": "2.28.175", - "resolved": "https://registry.npmjs.org/cdk-nag/-/cdk-nag-2.28.175.tgz", - "integrity": "sha512-8CdL5D2/56E9ieEnY1e479wcJ6rIX58ZarEdq2gkpRXWFWJ/JVVfdcc4eWPVE6YL7dyPea+V/XsktyrPIDoOuw==", + "version": "2.28.179", + "resolved": "https://registry.npmjs.org/cdk-nag/-/cdk-nag-2.28.179.tgz", + "integrity": "sha512-xFT2yDqpPkM0eIV9oTSH9hhfYDug8WOI/oUur9/PLnNoj1asPdbg0xnVWWKwXL30jFKe/3NZtjk2nq9xRlo9OQ==", "dev": true, "peerDependencies": { "aws-cdk-lib": "^2.116.0", @@ -5029,9 +5091,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.5.tgz", - "integrity": "sha512-QR7/A7ZkMS8tZuoftC/jfqNkZLQO779SSW3YuZHP4eXpj3EffGLFcB/Xu9AAZQzLccTiCV+EmUo3ha4mQ9wnlA==", + "version": "1.5.7", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.7.tgz", + "integrity": "sha512-6FTNWIWMxMy/ZY6799nBlPtF1DFDQ6VQJ7yyDP27SJNt5lwtQ5ufqVvHylb3fdQefvRcgA3fKcFMJi9OLwBRNw==", "dev": true }, "node_modules/emittery": { @@ -6306,9 +6368,9 @@ } }, "node_modules/ignore": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", - "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "dev": true, "engines": { "node": ">= 4" @@ -7502,9 +7564,9 @@ } }, "node_modules/lint-staged": { - "version": "15.2.8", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.8.tgz", - "integrity": "sha512-PUWFf2zQzsd9EFU+kM1d7UP+AZDbKFKuj+9JNVTBkhUFhbg4MAt6WfyMMwBfM4lYqd4D2Jwac5iuTu9rVj4zCQ==", + "version": "15.2.9", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.9.tgz", + "integrity": "sha512-BZAt8Lk3sEnxw7tfxM7jeZlPRuT4M68O0/CwZhhaw6eeWu0Lz5eERE3m386InivXB64fp/mDID452h48tvKlRQ==", "dev": true, "dependencies": { "chalk": "~5.3.0", @@ -8786,12 +8848,12 @@ } }, "node_modules/shiki": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-1.12.1.tgz", - "integrity": "sha512-nwmjbHKnOYYAe1aaQyEBHvQymJgfm86ZSS7fT8OaPRr4sbAcBNz7PbfAikMEFSDQ6se2j2zobkXvVKcBOm0ysg==", + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-1.13.0.tgz", + "integrity": "sha512-e0dWfnONbEv6xl7FJy3XIhsVHQ/65XHDZl92+6H9+4xWjfdo7pmkqG7Kg47KWtDiEtzM5Z+oEfb4vtRvoZ/X9w==", "dev": true, "dependencies": { - "@shikijs/core": "1.12.1", + "@shikijs/core": "1.13.0", "@types/hast": "^3.0.4" } }, @@ -9489,9 +9551,9 @@ } }, "node_modules/undici-types": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.13.0.tgz", - "integrity": "sha512-xtFJHudx8S2DSoujjMd1WeWvn7KKWFRESZTMeL1RptAYERu29D6jphMjjY+vn96jvN3kVPDNxU/E13VTaXj6jg==", + "version": "6.18.2", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.18.2.tgz", + "integrity": "sha512-5ruQbENj95yDYJNS3TvcaxPMshV7aizdv/hWYjGIKoANWKjhWNBsr2YEuYZKodQulB1b8l7ILOuDQep3afowQQ==", "dev": true }, "node_modules/universalify": { @@ -9542,19 +9604,6 @@ "punycode": "^2.1.0" } }, - "node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "dev": true, - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "bin": { - "uuid": "dist/bin/uuid" - } - }, "node_modules/v8-to-istanbul": { "version": "9.3.0", "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", diff --git a/test/osml/authorizor/authorizor_function.test.ts b/test/osml/authorizor/authorizor_function.test.ts index 38b77a8..b048d6c 100644 --- a/test/osml/authorizor/authorizor_function.test.ts +++ b/test/osml/authorizor/authorizor_function.test.ts @@ -5,24 +5,29 @@ import { App, Stack } from "aws-cdk-lib"; import { Code } from "aws-cdk-lib/aws-lambda"; -import { OSMLAuthorizer } from "../../../lib"; +import { OSMLAuthorizer, OSMLVpc } from "../../../lib"; +import { test_account } from "../../test_account"; describe("OSMLAuthorizer constructor", () => { let app: App; let stack: Stack; let authorizer: OSMLAuthorizer; + let osmlVpc: OSMLVpc; describe("OSMLAuthorizer", () => { beforeAll(() => { app = new App(); stack = new Stack(app, "OSMLAuthorizerStack"); - + osmlVpc = new OSMLVpc(stack, "OSMLVpc", { + account: test_account + }); authorizer = new OSMLAuthorizer(stack, "TestOSMLAuthorizer", { auth: { authority: "https://example.com/authority", audience: "example-audience" }, - name: "example-authorizer" + name: "example-authorizer", + osmlVpc: osmlVpc }); }); diff --git a/test/osml/data_catalog/dc_dataplane.test.ts b/test/osml/data_catalog/dc_dataplane.test.ts index 43dede0..65f49e2 100644 --- a/test/osml/data_catalog/dc_dataplane.test.ts +++ b/test/osml/data_catalog/dc_dataplane.test.ts @@ -14,7 +14,7 @@ describe("DCDataplane constructor", () => { let dcDataplane: DCDataplane; describe("DCDataplane", () => { - beforeAll(() => { + beforeEach(() => { app = new App(); stack = new Stack(app, "DCDataplaneStack"); diff --git a/test/osml/model_endpoint/me_test_endpoints.test.ts b/test/osml/model_endpoint/me_test_endpoints.test.ts index 4d5357c..f96c5a6 100644 --- a/test/osml/model_endpoint/me_test_endpoints.test.ts +++ b/test/osml/model_endpoint/me_test_endpoints.test.ts @@ -14,7 +14,7 @@ describe("METestEndpoints constructor", () => { let testEndpoints: METestEndpoints; describe("METestEndpoints", () => { - beforeEach(() => { + beforeAll(() => { app = new App(); stack = new Stack(app, "METestEndpointsStack"); diff --git a/test/osml/model_runner/mr_dataplane.test.ts b/test/osml/model_runner/mr_dataplane.test.ts index 0be8065..794f0fd 100644 --- a/test/osml/model_runner/mr_dataplane.test.ts +++ b/test/osml/model_runner/mr_dataplane.test.ts @@ -4,7 +4,7 @@ import { App, Stack } from "aws-cdk-lib"; -import { MRDataplane, OSMLVpc } from "../../../lib"; +import { MRDataplane, MRDataplaneConfig, OSMLVpc } from "../../../lib"; import { test_account } from "../../test_account"; describe("MRDataplane constructor", () => { @@ -25,7 +25,10 @@ describe("MRDataplane constructor", () => { mrDataplane = new MRDataplane(stack, "MRDataplane", { account: test_account, taskRole: undefined, - osmlVpc: osmlVpc + osmlVpc: osmlVpc, + config: new MRDataplaneConfig({ + ENABLE_REGION_STATUS: true + }) }); }); diff --git a/test/osml/model_runner/mr_monitoring.test.ts b/test/osml/model_runner/mr_monitoring.test.ts index 44d52f9..92e456a 100644 --- a/test/osml/model_runner/mr_monitoring.test.ts +++ b/test/osml/model_runner/mr_monitoring.test.ts @@ -15,7 +15,7 @@ describe("OSMLMonitoring constructor", () => { let mrMonitoring: MRMonitoring; describe("MRMonitoring", () => { - beforeEach(() => { + beforeAll(() => { app = new App(); stack = new Stack(app, "MRMonitoringStack"); diff --git a/test/osml/osml_container.test.ts b/test/osml/osml_container.test.ts index db2b92c..cd3eb43 100644 --- a/test/osml/osml_container.test.ts +++ b/test/osml/osml_container.test.ts @@ -4,31 +4,25 @@ import { App, Stack } from "aws-cdk-lib"; -import { OSMLContainer, OSMLVpc } from "../../lib"; +import { OSMLContainer } from "../../lib"; import { test_account } from "../test_account"; describe("MEContainer", () => { let app: App; let stack: Stack; - let osmlVpc: OSMLVpc; let container: OSMLContainer; beforeEach(() => { app = new App(); stack = new Stack(app, "MEContainerStack"); - osmlVpc = new OSMLVpc(stack, "OSMLVpc", { - account: test_account - }); - // Mock dependencies container = new OSMLContainer(stack, "OSMLContainer", { account: test_account, + buildDockerImageCode: true, buildFromSource: false, - osmlVpc: osmlVpc, config: { - CONTAINER_REPOSITORY: "test-repository", - CONTAINER_URI: "test-uri" + CONTAINER_URI: "awsosml/test-uri" } }); }); @@ -42,7 +36,8 @@ describe("MEContainer", () => { }); it("sets container image", () => { - expect(container.containerUri).toContain("ecr"); expect(container.containerImage).toBeDefined(); + expect(container.config).toBeDefined(); + expect(container.dockerImageCode).toBeDefined(); }); }); diff --git a/test/osml/osml_restapi.test.ts b/test/osml/osml_restapi.test.ts index 085a710..2dc7a4e 100644 --- a/test/osml/osml_restapi.test.ts +++ b/test/osml/osml_restapi.test.ts @@ -6,7 +6,7 @@ import { App, Stack } from "aws-cdk-lib"; import { Integration, LambdaIntegration } from "aws-cdk-lib/aws-apigateway"; import { Code, Function, Runtime } from "aws-cdk-lib/aws-lambda"; -import { OSMLRestApi } from "../../lib"; +import { OSMLRestApi, OSMLVpc } from "../../lib"; import { test_account } from "../test_account"; describe("OSMLRestApi constructor", () => { @@ -16,12 +16,15 @@ describe("OSMLRestApi constructor", () => { // eslint-disable-next-line @typescript-eslint/ban-types let mockHandler: Function; let restApi: OSMLRestApi; + let osmlVpc: OSMLVpc; describe("OSMLRestApi", () => { beforeAll(() => { app = new App(); stack = new Stack(app, "OSMLRestApiStack"); - + osmlVpc = new OSMLVpc(stack, "OSMLVpc", { + account: test_account + }); mockHandler = new Function(stack, "MockHandler", { runtime: Runtime.NODEJS_LATEST, handler: "index.handler", @@ -38,7 +41,8 @@ describe("OSMLRestApi constructor", () => { audience: "example-audience" }, integration: mockIntegration, - name: "test-api" + name: "test-api", + osmlVpc: osmlVpc }); }); diff --git a/test/osml/osml_roles.test.ts b/test/osml/osml_roles.test.ts index 1e3c0f0..6e93c85 100644 --- a/test/osml/osml_roles.test.ts +++ b/test/osml/osml_roles.test.ts @@ -14,7 +14,7 @@ describe("OSMLRolesStack", () => { let meSMRole: MESMRole; let meHTTPRole: MEHTTPRole; - beforeEach(() => { + beforeAll(() => { app = new App(); stack = new Stack(app, "OSMLRolesStack"); diff --git a/test/osml/osml_vpc.test.ts b/test/osml/osml_vpc.test.ts index 4bc2112..981a387 100644 --- a/test/osml/osml_vpc.test.ts +++ b/test/osml/osml_vpc.test.ts @@ -13,7 +13,7 @@ describe("OSMLVpc", () => { let app: App; let stack: Stack; - beforeEach(() => { + beforeAll(() => { app = new App(); stack = new Stack(app, "OSMLVpcStack"); diff --git a/test/osml/tile_server/testing/ts_test_runner.test.ts b/test/osml/tile_server/testing/ts_test_runner.test.ts deleted file mode 100644 index 577a72a..0000000 --- a/test/osml/tile_server/testing/ts_test_runner.test.ts +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2024 Amazon.com, Inc. or its affiliates. - */ - -import { App, RemovalPolicy, Stack } from "aws-cdk-lib"; - -import { - OSMLTestImagery, - OSMLTestImageryConfig, - OSMLVpc, - TSTestRunner, - TSTestRunnerContainer -} from "../../../../lib"; -import { test_account } from "../../../test_account"; - -describe("TSDataplane constructor", () => { - let app: App; - let stack: Stack; - let osmlVpc: OSMLVpc; - let tsTestRunnerContainer: TSTestRunnerContainer; - let tsTestRunner: TSTestRunner; - let config: OSMLTestImageryConfig; - let tsImagery: OSMLTestImagery; - - beforeEach(() => { - app = new App(); - stack = new Stack(app, "TSDataplaneStack"); - - osmlVpc = new OSMLVpc(stack, "OSMLVpc", { - account: test_account - }); - - config = new OSMLTestImageryConfig(); - config.S3_IMAGE_BUCKET_PREFIX = "jest-buckets"; - config.S3_TEST_IMAGES_PATH = "lib/"; - - tsImagery = new OSMLTestImagery(stack, "TSImagery", { - account: test_account, - vpc: osmlVpc.vpc, - config: config - }); - - tsTestRunnerContainer = new TSTestRunnerContainer( - stack, - "TSTestRunnerContainer", - { - account: test_account, - osmlVpc: osmlVpc, - tsEndpoint: "https://localhost/latest", - tsTestImageBucket: tsImagery.imageBucket.bucket.bucketName, - buildFromSource: false - } - ); - - tsTestRunner = new TSTestRunner(stack, "TSDataplane", { - account: test_account, - osmlVpc: osmlVpc, - dockerImageCode: tsTestRunnerContainer.dockerImageCode - }); - }); - - it("sets removal policy based on prodLike flag", () => { - expect(tsImagery.removalPolicy).toEqual(RemovalPolicy.RETAIN); - }); - - it("check of the ts integ runner is defined", () => { - expect(tsTestRunner.lambdaIntegRunner.functionArn).toBeDefined(); - }); -}); diff --git a/test/osml/tile_server/testing/ts_test_runner_container.test.ts b/test/osml/tile_server/testing/ts_test_runner_container.test.ts deleted file mode 100644 index 952142b..0000000 --- a/test/osml/tile_server/testing/ts_test_runner_container.test.ts +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2024 Amazon.com, Inc. or its affiliates. - */ - -import { App, RemovalPolicy, Stack } from "aws-cdk-lib"; - -import { - OSMLTestImagery, - OSMLTestImageryConfig, - OSMLVpc, - TSTestRunnerContainer -} from "../../../../lib"; -import { test_account } from "../../../test_account"; - -describe("TSDataplane constructor", () => { - let app: App; - let stack: Stack; - let osmlVpc: OSMLVpc; - let tsTestRunnerContainer: TSTestRunnerContainer; - let config: OSMLTestImageryConfig; - let tsImagery: OSMLTestImagery; - - beforeEach(() => { - app = new App(); - stack = new Stack(app, "TSDataplaneStack"); - - osmlVpc = new OSMLVpc(stack, "OSMLVpc", { - account: test_account - }); - - config = new OSMLTestImageryConfig(); - config.S3_IMAGE_BUCKET_PREFIX = "jest-buckets"; - config.S3_TEST_IMAGES_PATH = "lib/"; - - tsImagery = new OSMLTestImagery(stack, "TSImagery", { - account: test_account, - vpc: osmlVpc.vpc, - config: config - }); - - tsTestRunnerContainer = new TSTestRunnerContainer( - stack, - "TSTestRunnerContainer", - { - account: test_account, - osmlVpc: osmlVpc, - tsEndpoint: "https://localhost/latest", - tsTestImageBucket: tsImagery.imageBucket.bucket.bucketName, - buildFromSource: false - } - ); - }); - - it("sets removal policy based on prodLike flag", () => { - expect(tsImagery.removalPolicy).toEqual(RemovalPolicy.RETAIN); - }); - - it("check of the ts test runner docker image code is defined", () => { - expect(tsTestRunnerContainer.dockerImageCode).toBeDefined(); - }); -}); diff --git a/test/osml/tile_server/ts_dataplane.test.ts b/test/osml/tile_server/ts_dataplane.test.ts index 88eeb4c..9334f9d 100644 --- a/test/osml/tile_server/ts_dataplane.test.ts +++ b/test/osml/tile_server/ts_dataplane.test.ts @@ -4,7 +4,7 @@ import { App, Stack } from "aws-cdk-lib"; -import { OSMLVpc, TSDataplane } from "../../../lib"; +import { OSMLVpc, TSDataplane, TSDataplaneConfig } from "../../../lib"; import { test_account } from "../../test_account"; describe("TSDataplane constructor", () => { @@ -24,7 +24,10 @@ describe("TSDataplane constructor", () => { tsDataplane = new TSDataplane(stack, "TSDataplane", { account: test_account, taskRole: undefined, - osmlVpc: osmlVpc + osmlVpc: osmlVpc, + config: new TSDataplaneConfig({ + DEPLOY_TEST_COMPONENTS: true + }) }); });