diff --git a/.github/workflows/deploy-prod-staging.yml b/.github/workflows/deploy-prod-staging.yml index 6ff897a..6bc9b34 100644 --- a/.github/workflows/deploy-prod-staging.yml +++ b/.github/workflows/deploy-prod-staging.yml @@ -78,6 +78,7 @@ jobs: with: aws-account-id: ${{ secrets.AWS_ACCOUNT_ID }} staging: true + maturity: prod-staging run-prod-staging-integration-tests: needs: [deploy-prod-staging] diff --git a/.github/workflows/deploy-prod.yml b/.github/workflows/deploy-prod.yml index 20f5d0c..a1ed741 100644 --- a/.github/workflows/deploy-prod.yml +++ b/.github/workflows/deploy-prod.yml @@ -40,4 +40,5 @@ jobs: uses: ./.github/workflows/search-api-composite with: aws-account-id: ${{ secrets.AWS_ACCOUNT_ID }} + maturity: prod diff --git a/.github/workflows/deploy-test-staging.yml b/.github/workflows/deploy-test-staging.yml index 14c9df0..14d83ee 100644 --- a/.github/workflows/deploy-test-staging.yml +++ b/.github/workflows/deploy-test-staging.yml @@ -77,7 +77,7 @@ jobs: uses: ./.github/workflows/search-api-composite with: aws-account-id: ${{ secrets.AWS_ACCOUNT_ID }} - staging: true + maturity: test-staging run-test-staging-integration-tests: needs: [deploy-test-staging] diff --git a/.github/workflows/deploy-test.yml b/.github/workflows/deploy-test.yml index 24372eb..1073b73 100644 --- a/.github/workflows/deploy-test.yml +++ b/.github/workflows/deploy-test.yml @@ -40,3 +40,4 @@ jobs: uses: ./.github/workflows/search-api-composite with: aws-account-id: ${{ secrets.AWS_ACCOUNT_ID }} + maturity: test diff --git a/.github/workflows/search-api-composite/action.yml b/.github/workflows/search-api-composite/action.yml index 51d1dcb..c9bafa6 100644 --- a/.github/workflows/search-api-composite/action.yml +++ b/.github/workflows/search-api-composite/action.yml @@ -13,10 +13,9 @@ inputs: security-group: required: true type: string - - staging: - required: false - type: boolean + maturity: + required: true + type: string runs: using: "composite" @@ -57,5 +56,4 @@ runs: --context vpc_id=${{ inputs.vpc-id }} \ --context subnet_ids=${{ inputs.subnet-ids }} \ --context security_group=${{ inputs.security-group }} \ - --context staging=${{ inputs.staging }} - + --context api_stage=${{ inputs.maturity }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 3ba673f..4df4baa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,7 +32,7 @@ and uses [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ### Fixed - boolean values are properly capitalized in `python` output file - +- API maturity set for each level of deployment stage ------ ## [1.0.7](https://github.com/asfadmin/Discovery-SearchAPI-v3/compare/v1.0.6...v1.0.7) ### Changed diff --git a/Dockerfile b/Dockerfile index a5ffcaf..f8726e6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,6 +2,8 @@ FROM public.ecr.aws/docker/library/python:3.12 COPY --from=public.ecr.aws/awsguru/aws-lambda-adapter:0.8.3 /lambda-adapter /opt/extensions/lambda-adapter COPY --from=ghcr.io/astral-sh/uv:latest /uv /bin/uv +ARG MATURITY="local" +ENV MATURITY=${MATURITY} ARG HOST=0.0.0.0 ENV HOST=${HOST} ARG PORT=8080 diff --git a/cdk/app.py b/cdk/app.py index 9868486..8781e2a 100644 --- a/cdk/app.py +++ b/cdk/app.py @@ -8,12 +8,12 @@ app = cdk.App() -staging = app.node.try_get_context('staging') -if staging is None: - staging = False - +staging = False suffix = '' -if staging: +api_stage = app.node.try_get_context('api_stage') + +if api_stage.endswith('staging'): + staging = True suffix = '-Staging' SearchAPIStack(app, f"SearchAPIStack{suffix}", @@ -24,6 +24,7 @@ # Uncomment the next line to specialize this stack for the AWS Account # and Region that are implied by the current CLI configuration. staging=staging, + api_stage=api_stage, env=cdk.Environment( account=os.getenv('CDK_DEFAULT_ACCOUNT'), region=os.getenv('CDK_DEFAULT_REGION') diff --git a/cdk/cdk/cdk_stack.py b/cdk/cdk/cdk_stack.py index bd46d7a..80999df 100644 --- a/cdk/cdk/cdk_stack.py +++ b/cdk/cdk/cdk_stack.py @@ -12,7 +12,7 @@ class SearchAPIStack(Stack): - def __init__(self, scope: Construct, construct_id: str, staging: bool = False, **kwargs) -> None: + def __init__(self, scope: Construct, construct_id: str, api_stage: str, staging: bool = False, **kwargs) -> None: super().__init__(scope, construct_id, **kwargs) try: @@ -60,7 +60,7 @@ def __init__(self, scope: Construct, construct_id: str, staging: bool = False, * memory_size=5308, code=lambda_.DockerImageCode.from_image_asset( directory='..', - # build_args={'MATURITY': } + build_args={'MATURITY': api_stage}, ), **lambda_vpc_kwargs, ) diff --git a/requirements.txt b/requirements.txt index 277371a..4d17867 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,13 +1,13 @@ anyio==3.6.2 certifi>=2023.7.22 click==8.1.3 -dnspython==2.3.0 +dnspython>=2.6.1 email-validator>=2.0 -fastapi>=0.115.12 -h11==0.14.0 +fastapi>=0.116.1 +h11<0.15.0 httpcore==0.16.3 -httpx==0.23.3 -idna==3.4 +httpx<0.29.0 +idna==3.10 itsdangerous==2.1.2 jinja2>=3.1.3 orjson>=3.9.15 diff --git a/src/SearchAPI/application/application.py b/src/SearchAPI/application/application.py index 2e88347..596ca89 100644 --- a/src/SearchAPI/application/application.py +++ b/src/SearchAPI/application/application.py @@ -1,13 +1,11 @@ -from datetime import datetime import json import os -from typing import Optional import dateparser import asf_search as asf from fastapi import Depends, FastAPI, Request, HTTPException, APIRouter, UploadFile -from fastapi.responses import RedirectResponse, Response, JSONResponse +from fastapi.responses import Response, JSONResponse from fastapi.middleware.cors import CORSMiddleware from .log_router import LoggingRoute @@ -228,17 +226,19 @@ async def file_to_wkt(files: list[UploadFile]): headers=constants.DEFAULT_HEADERS ) -# @router.get('/redirect/{shortName}') -# async def nisar_static_layer(shortName: str, granule_id: str, cmr_token: Optional[str], cmr_host: Optional[str]='uat'): +# @router.get('/redirect/{short_name}/{granule_id}') +# async def nisar_static_layer(environment: Literal['prod', 'test'], short_name: str, granule_id: str): +# """ +# environment: 'prod' or 'test' (whether to search the cmr prod or uat record) +# short_name: the CMR static layer collection short name to search +# granule_id: the granule id of the product to find the static layer for + +# returns: redirect to file url +# """ # opts = asf.ASFSearchOptions() -# if cmr_token is not None: -# if cmr_host == 'uat': -# host = asf.INTERNAL.CMR_HOST_UAT -# else: -# host = asf.INTERNAL.CMR_HOST -# session = asf.ASFSession(cmr_host=host).auth_with_token(cmr_token) -# opts.session = session -# opts.host = host +# if environment == 'test': +# opts.host = asf.INTERNAL.CMR_HOST_UAT + # try: # granule = asf.search( # granule_list=[granule_id], @@ -247,7 +247,7 @@ async def file_to_wkt(files: list[UploadFile]): # except IndexError: # raise HTTPException(status_code=400, detail=f'Unable to find static layer, provided scene named "{granule_id}" not found in CMR record') -# static_layer = granule.get_static_layer(opts=asf.ASFSearchOptions(shortName=shortName)) +# static_layer = granule.get_static_layer(opts=asf.ASFSearchOptions(shortName=short_name)) # if static_layer is None: # raise HTTPException(status_code=500, detail=f'Static layer not found for scene named "{granule_id}"') diff --git a/tests/requirements.txt b/tests/requirements.txt index ee0d43c..d8c1b5f 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -1,9 +1,9 @@ -pytest -boto3 -requests -requests-mock -httpx -pytest-automation -pytest-xdist -pytest-cov -pytest-rerunfailures +pytest==8.4.1 +boto3==1.39.4 +requests==2.32.4 +requests-mock==1.12.1 +httpx==0.23.3 +pytest-automation==3.0.0 +pytest-xdist==3.8.0 +pytest-cov==6.2.1 +pytest-rerunfailures==15.1