diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index a3e9ff2..54eddf3 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,2 +1,4 @@ ## :warning: Checklist if your PR is changing anything else than documentation -- [ ] The manual deployment workflow ran successfully \ No newline at end of file +- [ ] Posted the link to a successful manually triggered deployment workflow (successful including the resources destruction) + +## Merge request description \ No newline at end of file diff --git a/.github/workflows/deploy.yaml b/.github/workflows/deploy.yaml index f2b2eff..0455e7b 100644 --- a/.github/workflows/deploy.yaml +++ b/.github/workflows/deploy.yaml @@ -44,9 +44,16 @@ jobs: deactivate cd - + # use short commit SHA to name stacks + - uses: benjlevesque/short-sha@v3.0 + id: short-sha + with: + length: 6 - name: Deploy test stack id: deploy_step + env: + PROJECT_ID: ${{ steps.short-sha.outputs.sha }} run: | source .deployment_venv/bin/activate @@ -61,6 +68,8 @@ jobs: - name: Tear down any infrastructure if: always() + env: + PROJECT_ID: ${{ steps.short-sha.outputs.sha }} run: | cd integration_tests/cdk # run this only if we find a 'cdk.out' directory, which means there might be things to tear down diff --git a/integration_tests/cdk/README.md b/integration_tests/cdk/README.md index 18232d4..abc32f6 100644 --- a/integration_tests/cdk/README.md +++ b/integration_tests/cdk/README.md @@ -1,7 +1,7 @@ # Deployment CDK code for eoapi-cdk deployment tests -This is a wrapper CDK code that is used to test a deployment of the `eoapi-cdk` constructs before a release happens. +This is a wrapper CDK code that is used to test a deployment of the `eoapi-cdk` constructs. ## Requirements diff --git a/integration_tests/cdk/app.py b/integration_tests/cdk/app.py index f86c201..da66306 100644 --- a/integration_tests/cdk/app.py +++ b/integration_tests/cdk/app.py @@ -1,17 +1,154 @@ -from aws_cdk import App +from config import build_app_config, AppConfig +from aws_cdk import ( + Stack, + aws_ec2, + aws_rds, + App, + RemovalPolicy +) +from constructs import Construct +from eoapi_cdk import ( + PgStacApiLambda, + PgStacDatabase, + TitilerPgstacApiLambda, + TiPgApiLambda, +) + + +class VpcStack(Stack): + def __init__(self, scope: Construct, app_config: AppConfig, id: str, **kwargs) -> None: + super().__init__( + scope, + id=id, + tags=app_config.tags, + **kwargs + ) + + self.vpc = aws_ec2.Vpc( + self, + "vpc", + subnet_configuration=[ + aws_ec2.SubnetConfiguration( + name="ingress", subnet_type=aws_ec2.SubnetType.PUBLIC, cidr_mask=24 + ), + ] + ) + + self.vpc.add_interface_endpoint( + "SecretsManagerEndpoint", + service=aws_ec2.InterfaceVpcEndpointAwsService.SECRETS_MANAGER, + ) + + self.vpc.add_interface_endpoint( + "CloudWatchEndpoint", + service=aws_ec2.InterfaceVpcEndpointAwsService.CLOUDWATCH_LOGS, + ) + + self.vpc.add_gateway_endpoint( + "S3", service=aws_ec2.GatewayVpcEndpointAwsService.S3 + ) + + self.export_value( + self.vpc.select_subnets(subnet_type=aws_ec2.SubnetType.PUBLIC) + .subnets[0] + .subnet_id + ) + self.export_value( + self.vpc.select_subnets(subnet_type=aws_ec2.SubnetType.PUBLIC) + .subnets[1] + .subnet_id + ) + + +class pgStacInfraStack(Stack): + def __init__( + self, + scope: Construct, + vpc: aws_ec2.Vpc, + id: str, + app_config: AppConfig, + **kwargs, + ) -> None: + super().__init__( + scope, + id=id, + tags=app_config.tags, + **kwargs, + ) + + pgstac_db = PgStacDatabase( + self, + "pgstac-db", + vpc=vpc, + engine=aws_rds.DatabaseInstanceEngine.postgres( + version=aws_rds.PostgresEngineVersion.VER_14 + ), + vpc_subnets=aws_ec2.SubnetSelection( + subnet_type=aws_ec2.SubnetType.PUBLIC, + ), + allocated_storage=app_config.db_allocated_storage, + instance_type=aws_ec2.InstanceType(app_config.db_instance_type), + removal_policy=RemovalPolicy.DESTROY + ) + + pgstac_db.db.connections.allow_default_port_from_any_ipv4() + + PgStacApiLambda( + self, + "pgstac-api", + api_env={ + "NAME": app_config.build_service_name("STAC API"), + "description": f"{app_config.stage} STAC API", + }, + db=pgstac_db.db, + db_secret=pgstac_db.pgstac_secret + ) + + TitilerPgstacApiLambda( + self, + "titiler-pgstac-api", + api_env={ + "NAME": app_config.build_service_name("titiler pgSTAC API"), + "description": f"{app_config.stage} titiler pgstac API", + }, + db=pgstac_db.db, + db_secret=pgstac_db.pgstac_secret, + buckets=[], + lambda_function_options={ + "allow_public_subnet": True, + }, + ) + + TiPgApiLambda( + self, + "tipg-api", + db=pgstac_db.db, + db_secret=pgstac_db.pgstac_secret, + api_env={ + "NAME": app_config.build_service_name("tipg API"), + "description": f"{app_config.stage} tipg API", + }, + lambda_function_options={ + "allow_public_subnet": True, + }, + ) -from config import build_app_config -from eoapi_template import pgStacInfra, vpc app = App() app_config = build_app_config() -vpc_stack = vpc.VpcStack(scope=app, app_config=app_config) +vpc_stack_id = f"vpc{app_config.project_id}" + +vpc_stack = VpcStack(scope=app, app_config=app_config, id=vpc_stack_id) -pgstac_infra_stack = pgStacInfra.pgStacInfraStack( +pgstac_infra_stack_id = f"pgstac{app_config.project_id}" + +pgstac_infra_stack = pgStacInfraStack( scope=app, vpc=vpc_stack.vpc, app_config=app_config, + id=pgstac_infra_stack_id ) + app.synth() diff --git a/integration_tests/cdk/config.py b/integration_tests/cdk/config.py index 729aa8c..cf4dedd 100644 --- a/integration_tests/cdk/config.py +++ b/integration_tests/cdk/config.py @@ -14,7 +14,7 @@ class AppConfig(BaseSettings): description="AWS account ID" ) project_id: str = pydantic.Field( - description="Project ID", default="eoapi-cdk" + description="Project ID", default="eoapicdk" ) stage: str = pydantic.Field(description="Stage of deployment", default="test") # because of its validator, `tags` should always come after `project_id` and `stage` diff --git a/integration_tests/cdk/eoapi_template/__init__.py b/integration_tests/cdk/eoapi_template/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/integration_tests/cdk/eoapi_template/pgStacInfra.py b/integration_tests/cdk/eoapi_template/pgStacInfra.py deleted file mode 100644 index cbb5491..0000000 --- a/integration_tests/cdk/eoapi_template/pgStacInfra.py +++ /dev/null @@ -1,71 +0,0 @@ -from aws_cdk import ( - Stack, - aws_ec2, - aws_rds -) -from constructs import Construct -from eoapi_cdk import ( - PgStacApiLambda, - PgStacDatabase, - TitilerPgstacApiLambda, -) - -from config import AppConfig - - -class pgStacInfraStack(Stack): - def __init__( - self, - scope: Construct, - vpc: aws_ec2.Vpc, - app_config: AppConfig, - **kwargs, - ) -> None: - super().__init__( - scope, - id=app_config.build_service_name("pgSTAC-infra"), - tags=app_config.tags, - **kwargs, - ) - - pgstac_db = PgStacDatabase( - self, - "pgstac-db", - vpc=vpc, - engine=aws_rds.DatabaseInstanceEngine.postgres( - version=aws_rds.PostgresEngineVersion.VER_14 - ), - vpc_subnets=aws_ec2.SubnetSelection( - subnet_type=aws_ec2.SubnetType.PUBLIC, - ), - allocated_storage=app_config.db_allocated_storage, - instance_type=aws_ec2.InstanceType(app_config.db_instance_type) - ) - - pgstac_db.db.connections.allow_default_port_from_any_ipv4() - - PgStacApiLambda( - self, - "pgstac-api", - api_env={ - "NAME": app_config.build_service_name("STAC API"), - "description": f"{app_config.stage} STAC API", - }, - db=pgstac_db.db, - db_secret=pgstac_db.pgstac_secret - ) - - TitilerPgstacApiLambda( - self, - "titiler-pgstac-api", - api_env={ - "NAME": app_config.build_service_name("titiler pgSTAC API"), - "description": f"{app_config.stage} titiler pgstac API", - }, - db=pgstac_db.db, - db_secret=pgstac_db.pgstac_secret, - buckets=[], - lambda_function_options={ - "allow_public_subnet": True, - }, - ) diff --git a/integration_tests/cdk/eoapi_template/vpc.py b/integration_tests/cdk/eoapi_template/vpc.py deleted file mode 100644 index d17967f..0000000 --- a/integration_tests/cdk/eoapi_template/vpc.py +++ /dev/null @@ -1,49 +0,0 @@ -from aws_cdk import Stack, aws_ec2 -from constructs import Construct - -from config import AppConfig - - -class VpcStack(Stack): - def __init__(self, scope: Construct, app_config: AppConfig, **kwargs) -> None: - super().__init__( - scope, - id=app_config.build_service_name("pgSTAC-vpc"), - tags=app_config.tags, - **kwargs - ) - - self.vpc = aws_ec2.Vpc( - self, - "vpc", - subnet_configuration=[ - aws_ec2.SubnetConfiguration( - name="ingress", subnet_type=aws_ec2.SubnetType.PUBLIC, cidr_mask=24 - ), - ] - ) - - self.vpc.add_interface_endpoint( - "SecretsManagerEndpoint", - service=aws_ec2.InterfaceVpcEndpointAwsService.SECRETS_MANAGER, - ) - - self.vpc.add_interface_endpoint( - "CloudWatchEndpoint", - service=aws_ec2.InterfaceVpcEndpointAwsService.CLOUDWATCH_LOGS, - ) - - self.vpc.add_gateway_endpoint( - "S3", service=aws_ec2.GatewayVpcEndpointAwsService.S3 - ) - - self.export_value( - self.vpc.select_subnets(subnet_type=aws_ec2.SubnetType.PUBLIC) - .subnets[0] - .subnet_id - ) - self.export_value( - self.vpc.select_subnets(subnet_type=aws_ec2.SubnetType.PUBLIC) - .subnets[1] - .subnet_id - ) diff --git a/integration_tests/cdk/package-lock.json b/integration_tests/cdk/package-lock.json index 5fa908a..50ea4e4 100644 --- a/integration_tests/cdk/package-lock.json +++ b/integration_tests/cdk/package-lock.json @@ -12,9 +12,9 @@ } }, "node_modules/aws-cdk": { - "version": "2.128.0", - "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.128.0.tgz", - "integrity": "sha512-epOAr/0WKqmyaKqBc7N0Ky5++93pu+v6yVN9jNOa4JYkAkGbeTS3vR9bj/W0o94jnlgWevG3HNHr83jtRvw/4A==", + "version": "2.129.0", + "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.129.0.tgz", + "integrity": "sha512-Gh/dG2aY0cvlLumYUXalg28/knVI/TrN6NZMBpRWe4gGJe/RH5JROIVB2GOEMMajkew9EiFH0ZeoC+pQ57diaQ==", "bin": { "cdk": "bin/cdk" },