Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ deployment/*
docs/*

deployment/aws/**
!deployment/aws/lambda/handler.py
26 changes: 26 additions & 0 deletions build-lambda.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#!/usr/bin/env bash

# This script compiles the service into a Python Lambda build artifact

set -ex

PROJ_DIR=$(git rev-parse --show-toplevel)
BUILD_DIR=${PROJ_DIR}/build
DOCKER_TAG=titiler_build
LAMBDA_PATH=${PROJ_DIR}/package.zip

cd ${PROJ_DIR}

# Clean out old build relics
rm -rf ${BUILD_DIR}
mkdir -p $(dirname ${BUILD_DIR})
rm -f ${LAMBDA_PATH}
mkdir -p $(dirname ${LAMBDA_PATH})

# Build Docker image and copy build assets out:
docker build --no-cache -f ${PROJ_DIR}/deployment/aws/lambda/Dockerfile -t ${DOCKER_TAG} .
docker run --rm -it -v ${BUILD_DIR}:/asset-output --entrypoint /bin/bash ${DOCKER_TAG} -c 'cp -R /asset/. /asset-output/.'

# Package up into .zip:
cd ${BUILD_DIR}
zip -r ${LAMBDA_PATH} .
10 changes: 7 additions & 3 deletions deployment/aws/lambda/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
ARG PYTHON_VERSION=3.11
ARG PYTHON_VERSION=3.10

FROM --platform=linux/amd64 public.ecr.aws/lambda/python:${PYTHON_VERSION}

WORKDIR /tmp

RUN pip install pip -U
RUN pip install "titiler.application==0.14.1" "mangum>=0.10.0" -t /asset --no-binary pydantic
# Install TiTiler from local source. This is necessary because
# pyproject.toml refers to TiTiler dependencies (core, extensions,
# mosaic, and application) that also use filesystem paths.
COPY . /titiler
RUN pip install "/titiler/src/titiler/application" "mangum>=0.10.0" -t /asset --no-binary pydantic

# Reduce package size and remove useless files
RUN cd /asset && find . -type f -name '*.pyc' | while read f; do n=$(echo $f | sed 's/__pycache__\///' | sed 's/.cpython-[0-9]*//'); cp $f $n; done;
Expand All @@ -14,6 +18,6 @@ RUN cd /asset && find . -type f -a -name '*.py' -print0 | xargs -0 rm -f
RUN find /asset -type d -a -name 'tests' -print0 | xargs -0 rm -rf
RUN rm -rdf /asset/numpy/doc/ /asset/boto3* /asset/botocore* /asset/bin /asset/geos_license /asset/Misc

COPY lambda/handler.py /asset/handler.py
COPY deployment/aws/lambda/handler.py /asset/handler.py

CMD ["echo", "hello world"]
5 changes: 4 additions & 1 deletion deployment/aws/lambda/handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@
from mangum import Mangum

from titiler.application.main import app
from titiler.application.settings import ApiSettings

logging.getLogger("mangum.lifespan").setLevel(logging.ERROR)
logging.getLogger("mangum.http").setLevel(logging.ERROR)

handler = Mangum(app, lifespan="auto")
api_settings = ApiSettings()

handler = Mangum(app, api_gateway_base_path=api_settings.root_path, lifespan="auto")
10 changes: 6 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,12 @@ classifiers = [
]
version="0.14.1"
dependencies = [
"titiler.core==0.14.1",
"titiler.extensions==0.14.1",
"titiler.mosaic==0.14.1",
"titiler.application==0.14.1",
# Configured for volume-mount path of Lambda Dockerfile. For local
# development, update accordingly for your local filesystem path:
"titiler.core @ file:///titiler/src/titiler/core",
"titiler.extensions @ file:///titiler/src/titiler/extensions",
"titiler.mosaic @ file:///titiler/src/titiler/mosaic",
"titiler.application @ file:///titiler/src/titiler/application",
]

[project.optional-dependencies]
Expand Down
8 changes: 5 additions & 3 deletions src/titiler/application/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,11 @@ classifiers = [
]
dynamic = ["version"]
dependencies = [
"titiler.core==0.14.1",
"titiler.extensions[cogeo,stac]==0.14.1",
"titiler.mosaic==0.14.1",
# Configured for volume-mount path of Lambda Dockerfile. For local
# development, update accordingly for your local filesystem path:
"titiler.core @ file:///titiler/src/titiler/core",
"titiler.extensions[cogeo,stac] @ file:///titiler/src/titiler/extensions",
"titiler.mosaic @ file:///titiler/src/titiler/mosaic",
"starlette-cramjam>=0.3,<0.4",
"pydantic-settings~=2.0",
]
Expand Down
19 changes: 18 additions & 1 deletion src/titiler/application/titiler/application/main.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""titiler app."""

import logging
import os

import jinja2
from fastapi import FastAPI
Expand Down Expand Up @@ -35,16 +36,32 @@
from titiler.mosaic.errors import MOSAIC_STATUS_CODES
from titiler.mosaic.factory import MosaicTilerFactory

LEVELS = {
"debug": logging.DEBUG,
"info": logging.INFO,
"warning": logging.WARNING,
"error": logging.ERROR,
"critical": logging.CRITICAL,
}
# Remove any AWS-injected logger handlers to fix Lambda logging to CloudWatch
# https://stackoverflow.com/a/45624044
base = logging.getLogger()
if base.handlers:
for handler in base.handlers:
base.removeHandler(handler)
logging.basicConfig(level=LEVELS.get(os.environ.get("LOGLEVEL", "info")))
logging.getLogger("botocore.credentials").disabled = True
logging.getLogger("botocore.utils").disabled = True
logging.getLogger("rio-tiler").setLevel(logging.ERROR)

logger = logging.getLogger(__name__)
logger.info("TiTiler")

templates = Jinja2Templates(
directory="",
loader=jinja2.ChoiceLoader([jinja2.PackageLoader(__package__, "templates")]),
) # type:ignore


api_settings = ApiSettings()

app = FastAPI(
Expand Down
2 changes: 1 addition & 1 deletion src/titiler/core/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ dependencies = [
"numpy",
"pydantic~=2.0",
"rasterio",
"rio-tiler>=6.0,<7.0",
"rio-tiler@https://github.com/SenteraLLC/rio-tiler/archive/refs/heads/6.1.0-sentera-changes-dev.tar.gz",
Copy link
Author

@DanSchoppe DanSchoppe Sep 28, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚨 Commit after merging SenteraLLC/rio-tiler#3 and creating a 6.1.0-0 release 🚨

Suggested change
"rio-tiler@https://github.com/SenteraLLC/rio-tiler/archive/refs/heads/6.1.0-sentera-changes-dev.tar.gz",
"rio-tiler@https://github.com/SenteraLLC/rio-tiler/archive/refs/tags/6.1.0-0.tar.gz",

"morecantile>=5.0,<6.0",
"simplejson",
"typing_extensions>=4.6.1",
Expand Down
9 changes: 8 additions & 1 deletion src/titiler/core/titiler/core/dependencies.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from rasterio.crs import CRS
from rio_tiler.colormap import cmap, parse_color
from rio_tiler.errors import MissingAssets, MissingBands
from rio_tiler.types import ColorMapType, RIOResampling
from rio_tiler.types import ColorMapType, RIOResampling, WarpResampling
from typing_extensions import Annotated

ColorMapName = Enum( # type: ignore
Expand Down Expand Up @@ -345,6 +345,13 @@ class DatasetParams(DefaultDependency):
description="Resampling method.",
),
] = "nearest"
reproject_method: Annotated[
WarpResampling,
Query(
alias="reproject",
description="Reprojection method.",
),
] = "nearest"

def __post_init__(self):
"""Post Init."""
Expand Down
13 changes: 13 additions & 0 deletions src/titiler/core/titiler/core/factory.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
"""TiTiler Router factories."""

import abc
import json
from base64 import b64decode
from dataclasses import dataclass, field
from typing import Any, Callable, Dict, List, Literal, Optional, Tuple, Type, Union
from urllib.parse import urlencode
Expand Down Expand Up @@ -249,6 +251,11 @@ def add_route_dependencies(
route.dependencies.extend(dependencies) # type: ignore


def get_feature(aoi: str) -> Feature:
"""Base64 encoded GeoJSON Feature."""
return json.loads(b64decode(aoi))


@dataclass
class TilerFactory(BaseTilerFactory):
"""Tiler Factory.
Expand Down Expand Up @@ -510,6 +517,10 @@ def tile(
description="Row (Y) index of the tile on the selected TileMatrix. It cannot exceed the MatrixWidth-1 for the selected TileMatrix.",
),
],
aoi: Annotated[
Union[str, None],
"Area of interest to crop the tile.",
] = None,
tileMatrixSetId: Annotated[
Literal[tuple(self.supported_tms.list())],
f"Identifier selecting one of the TileMatrixSetId supported (default: '{self.default_tms}')",
Expand All @@ -534,6 +545,7 @@ def tile(
env=Depends(self.environment_dependency),
):
"""Create map tile from a dataset."""
feature = get_feature(aoi) if aoi else None
tms = self.supported_tms.get(tileMatrixSetId)
with rasterio.Env(**env):
with self.reader(src_path, tms=tms, **reader_params) as src_dst:
Expand All @@ -542,6 +554,7 @@ def tile(
y,
z,
tilesize=scale * 256,
aoi=feature,
buffer=buffer,
**layer_params,
**dataset_params,
Expand Down
4 changes: 3 additions & 1 deletion src/titiler/extensions/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ classifiers = [
]
dynamic = ["version"]
dependencies = [
"titiler.core==0.14.1"
# Configured for volume-mount path of Lambda Dockerfile. For local
# development, update accordingly for your local filesystem path:
"titiler.core @ file:///titiler/src/titiler/core",
]

[project.optional-dependencies]
Expand Down
4 changes: 3 additions & 1 deletion src/titiler/mosaic/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ classifiers = [
]
dynamic = ["version"]
dependencies = [
"titiler.core==0.14.1",
# Configured for volume-mount path of Lambda Dockerfile. For local
# development, update accordingly for your local filesystem path:
"titiler.core @ file:///titiler/src/titiler/core",
"cogeo-mosaic>=7.0,<8.0",
]

Expand Down