├── .gitignore ├── requirements-gdal2.4.txt ├── scripts ├── build.sh ├── list.py ├── create-lambda-layer.sh └── deploy.py ├── requirements-gdal3.1.txt ├── requirements-gdal3.2.txt ├── Dockerfile ├── .github └── workflows │ ├── cron.yml │ └── ci.yml ├── README.md └── arns.json /.gitignore: -------------------------------------------------------------------------------- 1 | *.zip 2 | __pycache__/ 3 | .mypy_cache/ -------------------------------------------------------------------------------- /requirements-gdal2.4.txt: -------------------------------------------------------------------------------- 1 | numpy 2 | 3 | pygeos==0.8 4 | shapely==1.7.1 5 | rasterio==1.1.8 6 | 7 | mercantile==1.1.6 8 | supermercado==0.2.0 9 | 10 | # HACK, those package are in the docker image but not in the lambda env 11 | requests 12 | pyyaml 13 | jinja2 14 | -------------------------------------------------------------------------------- /scripts/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | GDAL_VERSION=$1 4 | RUNTIME=$2 5 | 6 | # Base Image 7 | docker build \ 8 | --build-arg VERSION=${GDAL_VERSION} \ 9 | --build-arg RUNTIME=${RUNTIME} \ 10 | -t lambgeo/lambda-gdal:${GDAL_VERSION}-${RUNTIME}-geo . 11 | -------------------------------------------------------------------------------- /requirements-gdal3.1.txt: -------------------------------------------------------------------------------- 1 | numpy 2 | 3 | pygeos==0.8 4 | shapely==1.7.1 5 | rasterio==1.1.8 6 | pyproj==2.6.1 7 | 8 | mercantile==1.1.6 9 | supermercado==0.2.0 10 | 11 | # HACK, those package are in the docker image but not in the lambda env 12 | requests 13 | pyyaml 14 | jinja2 15 | -------------------------------------------------------------------------------- /requirements-gdal3.2.txt: -------------------------------------------------------------------------------- 1 | numpy 2 | 3 | pygeos==0.8 4 | shapely==1.7.1 5 | rasterio==1.1.8 6 | pyproj==3.0.0 7 | 8 | mercantile==1.1.6 9 | supermercado==0.2.0 10 | 11 | # HACK, those package are in the docker image but not in the lambda env 12 | requests 13 | pyyaml 14 | jinja2 15 | 16 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | ARG VERSION 2 | ARG RUNTIME 3 | 4 | FROM lambgeo/lambda-gdal:${VERSION}-${RUNTIME} 5 | 6 | ARG VERSION 7 | ENV VERSION $VERSION 8 | 9 | COPY requirements-gdal${VERSION}.txt requirements.txt 10 | RUN pip install -r requirements.txt --no-cache-dir --no-binary :all: -t $PREFIX/python 11 | RUN rm requirements.txt 12 | 13 | ENV PYTHONPATH=$PYTHONPATH:$PREFIX/python 14 | ENV PATH=$PREFIX/python/bin:$PATH 15 | -------------------------------------------------------------------------------- /.github/workflows/cron.yml: -------------------------------------------------------------------------------- 1 | name: CRON 2 | 3 | on: 4 | schedule: 5 | - cron: '0 0 1 * *' 6 | 7 | jobs: 8 | build: 9 | runs-on: ubuntu-latest 10 | strategy: 11 | matrix: 12 | runtimes: ['python3.7', 'python3.8'] 13 | gdal-version: [2.4, 3.1, 3.2] 14 | steps: 15 | - uses: actions/checkout@v2 16 | - name: Login to DockerHub 17 | uses: docker/login-action@v1 18 | with: 19 | username: ${{ secrets.DOCKERHUB_USERNAME }} 20 | password: ${{ secrets.DOCKERHUB_TOKEN }} 21 | 22 | - name: Pull GDAL Images 23 | run: docker pull lambgeo/lambda-gdal:${{ matrix.gdal-version }}-${{ matrix.runtimes }}-geo 24 | -------------------------------------------------------------------------------- /scripts/list.py: -------------------------------------------------------------------------------- 1 | 2 | import json 3 | from boto3.session import Session as boto3_session 4 | 5 | AWS_REGIONS = [ 6 | "ap-northeast-1", 7 | "ap-northeast-2", 8 | "ap-south-1", 9 | "ap-southeast-1", 10 | "ap-southeast-2", 11 | "ca-central-1", 12 | "eu-central-1", 13 | "eu-north-1", 14 | "eu-west-1", 15 | "eu-west-2", 16 | "eu-west-3", 17 | "sa-east-1", 18 | "us-east-1", 19 | "us-east-2", 20 | "us-west-1", 21 | "us-west-2", 22 | ] 23 | layers = [ 24 | "gdal24-python37-geo", 25 | "gdal31-python37-geo", 26 | "gdal32-python37-geo", 27 | "gdal24-python38-geo", 28 | "gdal31-python38-geo", 29 | "gdal32-python38-geo", 30 | ] 31 | 32 | 33 | def main(): 34 | results = [] 35 | for region in AWS_REGIONS: 36 | res = {"region": region, "layers": []} 37 | 38 | session = boto3_session(region_name=region) 39 | client = session.client("lambda") 40 | for layer in layers: 41 | response = client.list_layer_versions(LayerName=layer) 42 | latest = response["LayerVersions"][0] 43 | res["layers"].append(dict( 44 | name=layer, 45 | arn=latest["LayerVersionArn"], 46 | version=latest["Version"] 47 | )) 48 | results.append(res) 49 | 50 | print(json.dumps(results)) 51 | 52 | 53 | if __name__ == '__main__': 54 | main() 55 | -------------------------------------------------------------------------------- /scripts/create-lambda-layer.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo "-----------------------" 3 | echo "Creating lambda layer" 4 | echo "-----------------------" 5 | 6 | echo "Remove lambda python packages" 7 | rm -rdf $PREFIX/python/boto3* \ 8 | && rm -rdf $PREFIX/python/botocore* \ 9 | && rm -rdf $PREFIX/python/docutils* \ 10 | && rm -rdf $PREFIX/python/dateutil* \ 11 | && rm -rdf $PREFIX/python/jmespath* \ 12 | && rm -rdf $PREFIX/python/s3transfer* \ 13 | && rm -rdf $PREFIX/python/numpy/doc/ 14 | 15 | echo "Remove useless files" 16 | rm -rdf $PREFIX/share/doc \ 17 | && rm -rdf $PREFIX/share/man \ 18 | && rm -rdf $PREFIX/share/hdf* 19 | 20 | find $PREFIX/python -type d -a -name 'tests' -print0 | xargs -0 rm -rf 21 | 22 | echo "Remove uncompiled python scripts" 23 | find $PREFIX/python -type f -name '*.pyc' | while read f; do n=$(echo $f | sed 's/__pycache__\///' | sed 's/.cpython-[2-3][0-9]//'); cp $f $n; done; 24 | find $PREFIX/python -type d -a -name '__pycache__' -print0 | xargs -0 rm -rf 25 | find $PREFIX/python -type f -a -name '*.py' -print0 | xargs -0 rm -f 26 | 27 | echo "Strip shared libraries" 28 | cd $PREFIX && find lib -name \*.so\* -exec strip {} \; 29 | 30 | echo "Create archives" 31 | cd $PREFIX && zip -r9q /tmp/package.zip python 32 | cd $PREFIX && zip -r9q --symlinks /tmp/package.zip lib/*.so* 33 | cd $PREFIX && zip -r9q --symlinks /tmp/package.zip share 34 | cd $PREFIX && zip -r9q --symlinks /tmp/package.zip bin/gdal* bin/ogr* bin/geos* bin/nearblack bin/postgres bin/pg_* bin/proj* 35 | 36 | cp /tmp/package.zip /local/package.zip 37 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: [push] 4 | 5 | jobs: 6 | build: 7 | runs-on: ubuntu-latest 8 | if: "!contains(github.event.head_commit.message, '[skip ci]')" 9 | strategy: 10 | matrix: 11 | runtimes: ['python3.7', 'python3.8'] 12 | gdal-version: [2.4, 3.1, 3.2] 13 | steps: 14 | - uses: actions/checkout@v2 15 | 16 | - name: Set up Python 3.8 17 | uses: actions/setup-python@v2 18 | with: 19 | python-version: 3.8 20 | 21 | - name: Install dependencies 22 | run: | 23 | python -m pip install --upgrade pip 24 | python -m pip install docker boto3 click 25 | 26 | - name: Login to DockerHub 27 | uses: docker/login-action@v1 28 | with: 29 | username: ${{ secrets.DOCKERHUB_USERNAME }} 30 | password: ${{ secrets.DOCKERHUB_TOKEN }} 31 | 32 | - name: Configure AWS Credentials 33 | uses: aws-actions/configure-aws-credentials@v1 34 | with: 35 | aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} 36 | aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} 37 | aws-region: us-east-1 38 | 39 | - name: Build layers 40 | if: "!contains(github.ref, 'tags')" 41 | run: python scripts/deploy.py ${{ matrix.gdal-version }} ${{ matrix.runtimes }} geo 42 | 43 | - name: Build and Deploy layers 44 | if: contains(github.ref, 'tags') 45 | run: python scripts/deploy.py ${{ matrix.gdal-version }} ${{ matrix.runtimes }} geo --deploy 46 | -------------------------------------------------------------------------------- /scripts/deploy.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | import os 4 | import click 5 | 6 | import docker 7 | 8 | from boto3.session import Session as boto3_session 9 | from botocore.client import Config 10 | 11 | AWS_REGIONS = [ 12 | "ap-northeast-1", 13 | "ap-northeast-2", 14 | "ap-south-1", 15 | "ap-southeast-1", 16 | "ap-southeast-2", 17 | "ca-central-1", 18 | "eu-central-1", 19 | "eu-north-1", 20 | "eu-west-1", 21 | "eu-west-2", 22 | "eu-west-3", 23 | "sa-east-1", 24 | "us-east-1", 25 | "us-east-2", 26 | "us-west-1", 27 | "us-west-2", 28 | ] 29 | 30 | 31 | @click.command() 32 | @click.argument('gdalversion', type=str) 33 | @click.argument('runtime', type=str) 34 | @click.argument('name', type=str) 35 | @click.option('--deploy', is_flag=True) 36 | def main(gdalversion, runtime, name, deploy): 37 | """Build and Deploy Layers.""" 38 | client = docker.from_env() 39 | 40 | docker_name = f"lambgeo/lambda-gdal:{gdalversion}-{runtime}-geo" 41 | click.echo(f"Building image: {docker_name}...") 42 | client.images.build( 43 | path="./", 44 | dockerfile="Dockerfile", 45 | tag=docker_name, 46 | buildargs={ 47 | "VERSION": gdalversion, 48 | "RUNTIME": runtime, 49 | }, 50 | rm=True, 51 | ) 52 | 53 | if deploy: 54 | for line in client.images.push(docker_name, stream=True, decode=True): 55 | print(line) 56 | 57 | click.echo("Create Package") 58 | client.containers.run( 59 | image=docker_name, 60 | command="/bin/sh /local/scripts/create-lambda-layer.sh", 61 | remove=True, 62 | volumes={os.path.abspath("./"): {"bind": "/local/", "mode": "rw"}}, 63 | user=0, 64 | ) 65 | 66 | gdalversion_nodot = gdalversion.replace(".", "") 67 | runtime_nodot = runtime.replace(".", "") 68 | 69 | layer_name = f"gdal{gdalversion_nodot}-{runtime_nodot}-{name}" 70 | description = f"Lambda Layer with GDAL{gdalversion} for {runtime}" 71 | 72 | if deploy: 73 | session = boto3_session() 74 | 75 | # Increase connection timeout to work around timeout errors 76 | config = Config(connect_timeout=6000, retries={'max_attempts': 5}) 77 | 78 | click.echo(f"Deploying {layer_name}", err=True) 79 | for region in AWS_REGIONS: 80 | click.echo(f"AWS Region: {region}", err=True) 81 | client = session.client("lambda", region_name=region, config=config) 82 | 83 | click.echo("Publishing new version", err=True) 84 | with open("package.zip", 'rb') as zf: 85 | res = client.publish_layer_version( 86 | LayerName=layer_name, 87 | Content={"ZipFile": zf.read()}, 88 | CompatibleRuntimes=[runtime], 89 | Description=description, 90 | LicenseInfo="MIT" 91 | ) 92 | 93 | click.echo("Adding permission", err=True) 94 | client.add_layer_version_permission( 95 | LayerName=layer_name, 96 | VersionNumber=res["Version"], 97 | StatementId='make_public', 98 | Action='lambda:GetLayerVersion', 99 | Principal='*', 100 | ) 101 | 102 | 103 | if __name__ == '__main__': 104 | main() 105 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GDAL based AWS Lambda Layers 2 | 3 |

4 | geo-layer 5 |

6 |

7 | AWS lambda (Amazonlinux) Layers and Docker images. 8 |

9 |

10 | 11 | Test 12 | 13 |

14 | 15 | ## Python package 16 | 17 | ``` 18 | numpy 19 | 20 | pygeos==0.8 21 | shapely==1.7.1 22 | rasterio==1.1.8 23 | 24 | pyproj==2.4.1 # Only for GDAL>=3.1 25 | 26 | mercantile==1.1.6 27 | supermercado==0.2.0 28 | 29 | # HACK, those package are in the docker image but not in the lambda env 30 | requests 31 | pyyaml 32 | 33 | ``` 34 | 35 | ## Available layers 36 | 37 | gdal | size (Mb)| unzipped size (Mb)| arn 38 | ---| ---| ---| --- 39 | 3.2 | 43.8| 138.8| arn:aws:lambda:{REGION}:524387336408:layer:gdal32-python37-geo:{VERSION} 40 | 3.1 | 43.7| 128.4| arn:aws:lambda:{REGION}:524387336408:layer:gdal31-python37-geo:{VERSION} 41 | 2.4 | 36.3| 121.3| arn:aws:lambda:{REGION}:524387336408:layer:gdal24-python37-geo:{VERSION} 42 | ---| ---| ---| --- 43 | 3.2 | 44.4| 140| arn:aws:lambda:{REGION}:524387336408:layer:gdal32-python38-geo:{VERSION} 44 | 3.1 | 44.3| 139.7| arn:aws:lambda:{REGION}:524387336408:layer:gdal31-python38-geo:{VERSION} 45 | 2.4 | 36.7| 130| arn:aws:lambda:{REGION}:524387336408:layer:gdal24-python38-geo:{VERSION} 46 | 47 | See [full list of ARN](/arns.json) 48 | 49 | ### Arns format 50 | 51 | - `arn:aws:lambda:${region}:524387336408:layer:gdal(24|31|32)-python(37|38)-geo:${version}` 52 | 53 | ### Regions 54 | - ap-northeast-1 55 | - ap-northeast-2 56 | - ap-south-1 57 | - ap-southeast-1 58 | - ap-southeast-2 59 | - ca-central-1 60 | - eu-central-1 61 | - eu-north-1 62 | - eu-west-1 63 | - eu-west-2 64 | - eu-west-3 65 | - sa-east-1 66 | - us-east-1 67 | - us-east-2 68 | - us-west-1 69 | - us-west-2 70 | 71 | ### Layer content 72 | 73 | ``` 74 | layer.zip 75 | | 76 | |___ bin/ # Binaries 77 | |___ lib/ # Shared libraries (GDAL, PROJ, GEOS...) 78 | |___ share/ # GDAL/PROJ data directories 79 | |___ python/ # Python modules 80 | ``` 81 | 82 | The layer content will be unzip in `/opt` directory in AWS Lambda. For the python libs to be able to use the C libraries you have to make sure to set 2 important environment variables: 83 | 84 | - **GDAL_DATA:** /opt/share/gdal 85 | - **PROJ_LIB:** /opt/share/proj 86 | 87 | # How To 88 | 89 | There are 2 ways to use the layers: 90 | 91 | ## 1. Simple (No dependencies) 92 | 93 | If you don't need to add more python module (dependencies), you can just create a lambda package (zip file) with you lambda handler. 94 | 95 | ```bash 96 | zip -r9q package.zip handler.py 97 | ``` 98 | 99 | **Content:** 100 | 101 | ``` 102 | package.zip 103 | |___ handler.py # aws lambda python handler 104 | ``` 105 | 106 | **AWS Lambda Config:** 107 | - arn: `arn:aws:lambda:us-east-1:524387336408:layer:gdal32-python38-geo:1` (example) 108 | - env: 109 | - **GDAL_DATA:** /opt/share/gdal 110 | - **PROJ_LIB:** /opt/share/proj 111 | - lambda handler: `handler.handler` 112 | 113 | 114 | ## 2. Advanced (need other python dependencies) 115 | 116 | If your lambda handler needs more dependencies you'll have to use the exact same environment. To ease this you can find the docker images for each lambda on docker hub. 117 | 118 | - Create a docker file 119 | 120 | ```dockerfile 121 | FROM lambgeo/lambda-gdal:3.2-python3.8-geo 122 | 123 | ENV PYTHONUSERBASE=/var/task 124 | 125 | # Install dependencies 126 | COPY handler.py $PYTHONUSERBASE/handler.py 127 | 128 | # Here we use the `--user` option to make sure to not replicate modules. 129 | RUN pip install rio-tiler --user 130 | 131 | # Move some files around 132 | RUN mv ${PYTHONUSERBASE}/lib/python3.8/site-packages/* ${PYTHONUSERBASE}/ 133 | RUN rm -rf ${PYTHONUSERBASE}/lib 134 | 135 | echo "Create archive" 136 | RUN cd $PYTHONUSERBASE && zip -r9q /tmp/package.zip * 137 | ``` 138 | 139 | - create package 140 | ```bash 141 | docker build --tag package:latest . 142 | docker run --name lambda -w /var/task -itd package:latest bash 143 | docker cp lambda:/tmp/package.zip package.zip 144 | docker stop lambda 145 | docker rm lambda 146 | ``` 147 | 148 | **Content:** 149 | 150 | ``` 151 | package.zip 152 | |___ handler.py # aws lambda python handler 153 | |___ module1/ # dependencies 154 | |___ module2/ 155 | |___ module3/ 156 | |___ ... 157 | ``` 158 | 159 | **AWS Lambda Config:** 160 | - arn: `arn:aws:lambda:us-east-1:524387336408:layer:gdal32-python38-geo:1` (example) 161 | - env: 162 | - **GDAL_DATA:** /opt/share/gdal 163 | - **PROJ_LIB:** /opt/share/proj 164 | - lambda handler: `handler.handler` 165 | 166 | ### Refactor 167 | 168 | We recently refactored the repo, to see old documentation please refer to https://github.com/lambgeo/geo-layer/tree/60c9cf69a4529e14d4394a0a3e78dd5f84d9e6ec 169 | -------------------------------------------------------------------------------- /arns.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "region": "ap-northeast-1", 4 | "layers": [ 5 | { 6 | "name": "gdal24-python37-geo", 7 | "arn": "arn:aws:lambda:ap-northeast-1:524387336408:layer:gdal24-python37-geo:2", 8 | "version": 2 9 | }, 10 | { 11 | "name": "gdal31-python37-geo", 12 | "arn": "arn:aws:lambda:ap-northeast-1:524387336408:layer:gdal31-python37-geo:2", 13 | "version": 2 14 | }, 15 | { 16 | "name": "gdal32-python37-geo", 17 | "arn": "arn:aws:lambda:ap-northeast-1:524387336408:layer:gdal32-python37-geo:2", 18 | "version": 2 19 | }, 20 | { 21 | "name": "gdal24-python38-geo", 22 | "arn": "arn:aws:lambda:ap-northeast-1:524387336408:layer:gdal24-python38-geo:2", 23 | "version": 2 24 | }, 25 | { 26 | "name": "gdal31-python38-geo", 27 | "arn": "arn:aws:lambda:ap-northeast-1:524387336408:layer:gdal31-python38-geo:2", 28 | "version": 2 29 | }, 30 | { 31 | "name": "gdal32-python38-geo", 32 | "arn": "arn:aws:lambda:ap-northeast-1:524387336408:layer:gdal32-python38-geo:2", 33 | "version": 2 34 | } 35 | ] 36 | }, 37 | { 38 | "region": "ap-northeast-2", 39 | "layers": [ 40 | { 41 | "name": "gdal24-python37-geo", 42 | "arn": "arn:aws:lambda:ap-northeast-2:524387336408:layer:gdal24-python37-geo:2", 43 | "version": 2 44 | }, 45 | { 46 | "name": "gdal31-python37-geo", 47 | "arn": "arn:aws:lambda:ap-northeast-2:524387336408:layer:gdal31-python37-geo:2", 48 | "version": 2 49 | }, 50 | { 51 | "name": "gdal32-python37-geo", 52 | "arn": "arn:aws:lambda:ap-northeast-2:524387336408:layer:gdal32-python37-geo:2", 53 | "version": 2 54 | }, 55 | { 56 | "name": "gdal24-python38-geo", 57 | "arn": "arn:aws:lambda:ap-northeast-2:524387336408:layer:gdal24-python38-geo:2", 58 | "version": 2 59 | }, 60 | { 61 | "name": "gdal31-python38-geo", 62 | "arn": "arn:aws:lambda:ap-northeast-2:524387336408:layer:gdal31-python38-geo:2", 63 | "version": 2 64 | }, 65 | { 66 | "name": "gdal32-python38-geo", 67 | "arn": "arn:aws:lambda:ap-northeast-2:524387336408:layer:gdal32-python38-geo:2", 68 | "version": 2 69 | } 70 | ] 71 | }, 72 | { 73 | "region": "ap-south-1", 74 | "layers": [ 75 | { 76 | "name": "gdal24-python37-geo", 77 | "arn": "arn:aws:lambda:ap-south-1:524387336408:layer:gdal24-python37-geo:2", 78 | "version": 2 79 | }, 80 | { 81 | "name": "gdal31-python37-geo", 82 | "arn": "arn:aws:lambda:ap-south-1:524387336408:layer:gdal31-python37-geo:2", 83 | "version": 2 84 | }, 85 | { 86 | "name": "gdal32-python37-geo", 87 | "arn": "arn:aws:lambda:ap-south-1:524387336408:layer:gdal32-python37-geo:2", 88 | "version": 2 89 | }, 90 | { 91 | "name": "gdal24-python38-geo", 92 | "arn": "arn:aws:lambda:ap-south-1:524387336408:layer:gdal24-python38-geo:2", 93 | "version": 2 94 | }, 95 | { 96 | "name": "gdal31-python38-geo", 97 | "arn": "arn:aws:lambda:ap-south-1:524387336408:layer:gdal31-python38-geo:2", 98 | "version": 2 99 | }, 100 | { 101 | "name": "gdal32-python38-geo", 102 | "arn": "arn:aws:lambda:ap-south-1:524387336408:layer:gdal32-python38-geo:2", 103 | "version": 2 104 | } 105 | ] 106 | }, 107 | { 108 | "region": "ap-southeast-1", 109 | "layers": [ 110 | { 111 | "name": "gdal24-python37-geo", 112 | "arn": "arn:aws:lambda:ap-southeast-1:524387336408:layer:gdal24-python37-geo:2", 113 | "version": 2 114 | }, 115 | { 116 | "name": "gdal31-python37-geo", 117 | "arn": "arn:aws:lambda:ap-southeast-1:524387336408:layer:gdal31-python37-geo:2", 118 | "version": 2 119 | }, 120 | { 121 | "name": "gdal32-python37-geo", 122 | "arn": "arn:aws:lambda:ap-southeast-1:524387336408:layer:gdal32-python37-geo:2", 123 | "version": 2 124 | }, 125 | { 126 | "name": "gdal24-python38-geo", 127 | "arn": "arn:aws:lambda:ap-southeast-1:524387336408:layer:gdal24-python38-geo:2", 128 | "version": 2 129 | }, 130 | { 131 | "name": "gdal31-python38-geo", 132 | "arn": "arn:aws:lambda:ap-southeast-1:524387336408:layer:gdal31-python38-geo:2", 133 | "version": 2 134 | }, 135 | { 136 | "name": "gdal32-python38-geo", 137 | "arn": "arn:aws:lambda:ap-southeast-1:524387336408:layer:gdal32-python38-geo:2", 138 | "version": 2 139 | } 140 | ] 141 | }, 142 | { 143 | "region": "ap-southeast-2", 144 | "layers": [ 145 | { 146 | "name": "gdal24-python37-geo", 147 | "arn": "arn:aws:lambda:ap-southeast-2:524387336408:layer:gdal24-python37-geo:2", 148 | "version": 2 149 | }, 150 | { 151 | "name": "gdal31-python37-geo", 152 | "arn": "arn:aws:lambda:ap-southeast-2:524387336408:layer:gdal31-python37-geo:2", 153 | "version": 2 154 | }, 155 | { 156 | "name": "gdal32-python37-geo", 157 | "arn": "arn:aws:lambda:ap-southeast-2:524387336408:layer:gdal32-python37-geo:2", 158 | "version": 2 159 | }, 160 | { 161 | "name": "gdal24-python38-geo", 162 | "arn": "arn:aws:lambda:ap-southeast-2:524387336408:layer:gdal24-python38-geo:2", 163 | "version": 2 164 | }, 165 | { 166 | "name": "gdal31-python38-geo", 167 | "arn": "arn:aws:lambda:ap-southeast-2:524387336408:layer:gdal31-python38-geo:2", 168 | "version": 2 169 | }, 170 | { 171 | "name": "gdal32-python38-geo", 172 | "arn": "arn:aws:lambda:ap-southeast-2:524387336408:layer:gdal32-python38-geo:2", 173 | "version": 2 174 | } 175 | ] 176 | }, 177 | { 178 | "region": "ca-central-1", 179 | "layers": [ 180 | { 181 | "name": "gdal24-python37-geo", 182 | "arn": "arn:aws:lambda:ca-central-1:524387336408:layer:gdal24-python37-geo:2", 183 | "version": 2 184 | }, 185 | { 186 | "name": "gdal31-python37-geo", 187 | "arn": "arn:aws:lambda:ca-central-1:524387336408:layer:gdal31-python37-geo:2", 188 | "version": 2 189 | }, 190 | { 191 | "name": "gdal32-python37-geo", 192 | "arn": "arn:aws:lambda:ca-central-1:524387336408:layer:gdal32-python37-geo:2", 193 | "version": 2 194 | }, 195 | { 196 | "name": "gdal24-python38-geo", 197 | "arn": "arn:aws:lambda:ca-central-1:524387336408:layer:gdal24-python38-geo:2", 198 | "version": 2 199 | }, 200 | { 201 | "name": "gdal31-python38-geo", 202 | "arn": "arn:aws:lambda:ca-central-1:524387336408:layer:gdal31-python38-geo:2", 203 | "version": 2 204 | }, 205 | { 206 | "name": "gdal32-python38-geo", 207 | "arn": "arn:aws:lambda:ca-central-1:524387336408:layer:gdal32-python38-geo:2", 208 | "version": 2 209 | } 210 | ] 211 | }, 212 | { 213 | "region": "eu-central-1", 214 | "layers": [ 215 | { 216 | "name": "gdal24-python37-geo", 217 | "arn": "arn:aws:lambda:eu-central-1:524387336408:layer:gdal24-python37-geo:2", 218 | "version": 2 219 | }, 220 | { 221 | "name": "gdal31-python37-geo", 222 | "arn": "arn:aws:lambda:eu-central-1:524387336408:layer:gdal31-python37-geo:2", 223 | "version": 2 224 | }, 225 | { 226 | "name": "gdal32-python37-geo", 227 | "arn": "arn:aws:lambda:eu-central-1:524387336408:layer:gdal32-python37-geo:2", 228 | "version": 2 229 | }, 230 | { 231 | "name": "gdal24-python38-geo", 232 | "arn": "arn:aws:lambda:eu-central-1:524387336408:layer:gdal24-python38-geo:2", 233 | "version": 2 234 | }, 235 | { 236 | "name": "gdal31-python38-geo", 237 | "arn": "arn:aws:lambda:eu-central-1:524387336408:layer:gdal31-python38-geo:2", 238 | "version": 2 239 | }, 240 | { 241 | "name": "gdal32-python38-geo", 242 | "arn": "arn:aws:lambda:eu-central-1:524387336408:layer:gdal32-python38-geo:2", 243 | "version": 2 244 | } 245 | ] 246 | }, 247 | { 248 | "region": "eu-north-1", 249 | "layers": [ 250 | { 251 | "name": "gdal24-python37-geo", 252 | "arn": "arn:aws:lambda:eu-north-1:524387336408:layer:gdal24-python37-geo:2", 253 | "version": 2 254 | }, 255 | { 256 | "name": "gdal31-python37-geo", 257 | "arn": "arn:aws:lambda:eu-north-1:524387336408:layer:gdal31-python37-geo:2", 258 | "version": 2 259 | }, 260 | { 261 | "name": "gdal32-python37-geo", 262 | "arn": "arn:aws:lambda:eu-north-1:524387336408:layer:gdal32-python37-geo:2", 263 | "version": 2 264 | }, 265 | { 266 | "name": "gdal24-python38-geo", 267 | "arn": "arn:aws:lambda:eu-north-1:524387336408:layer:gdal24-python38-geo:2", 268 | "version": 2 269 | }, 270 | { 271 | "name": "gdal31-python38-geo", 272 | "arn": "arn:aws:lambda:eu-north-1:524387336408:layer:gdal31-python38-geo:2", 273 | "version": 2 274 | }, 275 | { 276 | "name": "gdal32-python38-geo", 277 | "arn": "arn:aws:lambda:eu-north-1:524387336408:layer:gdal32-python38-geo:2", 278 | "version": 2 279 | } 280 | ] 281 | }, 282 | { 283 | "region": "eu-west-1", 284 | "layers": [ 285 | { 286 | "name": "gdal24-python37-geo", 287 | "arn": "arn:aws:lambda:eu-west-1:524387336408:layer:gdal24-python37-geo:2", 288 | "version": 2 289 | }, 290 | { 291 | "name": "gdal31-python37-geo", 292 | "arn": "arn:aws:lambda:eu-west-1:524387336408:layer:gdal31-python37-geo:2", 293 | "version": 2 294 | }, 295 | { 296 | "name": "gdal32-python37-geo", 297 | "arn": "arn:aws:lambda:eu-west-1:524387336408:layer:gdal32-python37-geo:2", 298 | "version": 2 299 | }, 300 | { 301 | "name": "gdal24-python38-geo", 302 | "arn": "arn:aws:lambda:eu-west-1:524387336408:layer:gdal24-python38-geo:2", 303 | "version": 2 304 | }, 305 | { 306 | "name": "gdal31-python38-geo", 307 | "arn": "arn:aws:lambda:eu-west-1:524387336408:layer:gdal31-python38-geo:2", 308 | "version": 2 309 | }, 310 | { 311 | "name": "gdal32-python38-geo", 312 | "arn": "arn:aws:lambda:eu-west-1:524387336408:layer:gdal32-python38-geo:2", 313 | "version": 2 314 | } 315 | ] 316 | }, 317 | { 318 | "region": "eu-west-2", 319 | "layers": [ 320 | { 321 | "name": "gdal24-python37-geo", 322 | "arn": "arn:aws:lambda:eu-west-2:524387336408:layer:gdal24-python37-geo:2", 323 | "version": 2 324 | }, 325 | { 326 | "name": "gdal31-python37-geo", 327 | "arn": "arn:aws:lambda:eu-west-2:524387336408:layer:gdal31-python37-geo:2", 328 | "version": 2 329 | }, 330 | { 331 | "name": "gdal32-python37-geo", 332 | "arn": "arn:aws:lambda:eu-west-2:524387336408:layer:gdal32-python37-geo:2", 333 | "version": 2 334 | }, 335 | { 336 | "name": "gdal24-python38-geo", 337 | "arn": "arn:aws:lambda:eu-west-2:524387336408:layer:gdal24-python38-geo:2", 338 | "version": 2 339 | }, 340 | { 341 | "name": "gdal31-python38-geo", 342 | "arn": "arn:aws:lambda:eu-west-2:524387336408:layer:gdal31-python38-geo:2", 343 | "version": 2 344 | }, 345 | { 346 | "name": "gdal32-python38-geo", 347 | "arn": "arn:aws:lambda:eu-west-2:524387336408:layer:gdal32-python38-geo:2", 348 | "version": 2 349 | } 350 | ] 351 | }, 352 | { 353 | "region": "eu-west-3", 354 | "layers": [ 355 | { 356 | "name": "gdal24-python37-geo", 357 | "arn": "arn:aws:lambda:eu-west-3:524387336408:layer:gdal24-python37-geo:2", 358 | "version": 2 359 | }, 360 | { 361 | "name": "gdal31-python37-geo", 362 | "arn": "arn:aws:lambda:eu-west-3:524387336408:layer:gdal31-python37-geo:2", 363 | "version": 2 364 | }, 365 | { 366 | "name": "gdal32-python37-geo", 367 | "arn": "arn:aws:lambda:eu-west-3:524387336408:layer:gdal32-python37-geo:2", 368 | "version": 2 369 | }, 370 | { 371 | "name": "gdal24-python38-geo", 372 | "arn": "arn:aws:lambda:eu-west-3:524387336408:layer:gdal24-python38-geo:2", 373 | "version": 2 374 | }, 375 | { 376 | "name": "gdal31-python38-geo", 377 | "arn": "arn:aws:lambda:eu-west-3:524387336408:layer:gdal31-python38-geo:2", 378 | "version": 2 379 | }, 380 | { 381 | "name": "gdal32-python38-geo", 382 | "arn": "arn:aws:lambda:eu-west-3:524387336408:layer:gdal32-python38-geo:2", 383 | "version": 2 384 | } 385 | ] 386 | }, 387 | { 388 | "region": "sa-east-1", 389 | "layers": [ 390 | { 391 | "name": "gdal24-python37-geo", 392 | "arn": "arn:aws:lambda:sa-east-1:524387336408:layer:gdal24-python37-geo:2", 393 | "version": 2 394 | }, 395 | { 396 | "name": "gdal31-python37-geo", 397 | "arn": "arn:aws:lambda:sa-east-1:524387336408:layer:gdal31-python37-geo:2", 398 | "version": 2 399 | }, 400 | { 401 | "name": "gdal32-python37-geo", 402 | "arn": "arn:aws:lambda:sa-east-1:524387336408:layer:gdal32-python37-geo:2", 403 | "version": 2 404 | }, 405 | { 406 | "name": "gdal24-python38-geo", 407 | "arn": "arn:aws:lambda:sa-east-1:524387336408:layer:gdal24-python38-geo:2", 408 | "version": 2 409 | }, 410 | { 411 | "name": "gdal31-python38-geo", 412 | "arn": "arn:aws:lambda:sa-east-1:524387336408:layer:gdal31-python38-geo:2", 413 | "version": 2 414 | }, 415 | { 416 | "name": "gdal32-python38-geo", 417 | "arn": "arn:aws:lambda:sa-east-1:524387336408:layer:gdal32-python38-geo:2", 418 | "version": 2 419 | } 420 | ] 421 | }, 422 | { 423 | "region": "us-east-1", 424 | "layers": [ 425 | { 426 | "name": "gdal24-python37-geo", 427 | "arn": "arn:aws:lambda:us-east-1:524387336408:layer:gdal24-python37-geo:2", 428 | "version": 2 429 | }, 430 | { 431 | "name": "gdal31-python37-geo", 432 | "arn": "arn:aws:lambda:us-east-1:524387336408:layer:gdal31-python37-geo:2", 433 | "version": 2 434 | }, 435 | { 436 | "name": "gdal32-python37-geo", 437 | "arn": "arn:aws:lambda:us-east-1:524387336408:layer:gdal32-python37-geo:2", 438 | "version": 2 439 | }, 440 | { 441 | "name": "gdal24-python38-geo", 442 | "arn": "arn:aws:lambda:us-east-1:524387336408:layer:gdal24-python38-geo:2", 443 | "version": 2 444 | }, 445 | { 446 | "name": "gdal31-python38-geo", 447 | "arn": "arn:aws:lambda:us-east-1:524387336408:layer:gdal31-python38-geo:2", 448 | "version": 2 449 | }, 450 | { 451 | "name": "gdal32-python38-geo", 452 | "arn": "arn:aws:lambda:us-east-1:524387336408:layer:gdal32-python38-geo:2", 453 | "version": 2 454 | } 455 | ] 456 | }, 457 | { 458 | "region": "us-east-2", 459 | "layers": [ 460 | { 461 | "name": "gdal24-python37-geo", 462 | "arn": "arn:aws:lambda:us-east-2:524387336408:layer:gdal24-python37-geo:2", 463 | "version": 2 464 | }, 465 | { 466 | "name": "gdal31-python37-geo", 467 | "arn": "arn:aws:lambda:us-east-2:524387336408:layer:gdal31-python37-geo:2", 468 | "version": 2 469 | }, 470 | { 471 | "name": "gdal32-python37-geo", 472 | "arn": "arn:aws:lambda:us-east-2:524387336408:layer:gdal32-python37-geo:2", 473 | "version": 2 474 | }, 475 | { 476 | "name": "gdal24-python38-geo", 477 | "arn": "arn:aws:lambda:us-east-2:524387336408:layer:gdal24-python38-geo:2", 478 | "version": 2 479 | }, 480 | { 481 | "name": "gdal31-python38-geo", 482 | "arn": "arn:aws:lambda:us-east-2:524387336408:layer:gdal31-python38-geo:2", 483 | "version": 2 484 | }, 485 | { 486 | "name": "gdal32-python38-geo", 487 | "arn": "arn:aws:lambda:us-east-2:524387336408:layer:gdal32-python38-geo:2", 488 | "version": 2 489 | } 490 | ] 491 | }, 492 | { 493 | "region": "us-west-1", 494 | "layers": [ 495 | { 496 | "name": "gdal24-python37-geo", 497 | "arn": "arn:aws:lambda:us-west-1:524387336408:layer:gdal24-python37-geo:2", 498 | "version": 2 499 | }, 500 | { 501 | "name": "gdal31-python37-geo", 502 | "arn": "arn:aws:lambda:us-west-1:524387336408:layer:gdal31-python37-geo:2", 503 | "version": 2 504 | }, 505 | { 506 | "name": "gdal32-python37-geo", 507 | "arn": "arn:aws:lambda:us-west-1:524387336408:layer:gdal32-python37-geo:2", 508 | "version": 2 509 | }, 510 | { 511 | "name": "gdal24-python38-geo", 512 | "arn": "arn:aws:lambda:us-west-1:524387336408:layer:gdal24-python38-geo:2", 513 | "version": 2 514 | }, 515 | { 516 | "name": "gdal31-python38-geo", 517 | "arn": "arn:aws:lambda:us-west-1:524387336408:layer:gdal31-python38-geo:2", 518 | "version": 2 519 | }, 520 | { 521 | "name": "gdal32-python38-geo", 522 | "arn": "arn:aws:lambda:us-west-1:524387336408:layer:gdal32-python38-geo:2", 523 | "version": 2 524 | } 525 | ] 526 | }, 527 | { 528 | "region": "us-west-2", 529 | "layers": [ 530 | { 531 | "name": "gdal24-python37-geo", 532 | "arn": "arn:aws:lambda:us-west-2:524387336408:layer:gdal24-python37-geo:2", 533 | "version": 2 534 | }, 535 | { 536 | "name": "gdal31-python37-geo", 537 | "arn": "arn:aws:lambda:us-west-2:524387336408:layer:gdal31-python37-geo:2", 538 | "version": 2 539 | }, 540 | { 541 | "name": "gdal32-python37-geo", 542 | "arn": "arn:aws:lambda:us-west-2:524387336408:layer:gdal32-python37-geo:2", 543 | "version": 2 544 | }, 545 | { 546 | "name": "gdal24-python38-geo", 547 | "arn": "arn:aws:lambda:us-west-2:524387336408:layer:gdal24-python38-geo:2", 548 | "version": 2 549 | }, 550 | { 551 | "name": "gdal31-python38-geo", 552 | "arn": "arn:aws:lambda:us-west-2:524387336408:layer:gdal31-python38-geo:2", 553 | "version": 2 554 | }, 555 | { 556 | "name": "gdal32-python38-geo", 557 | "arn": "arn:aws:lambda:us-west-2:524387336408:layer:gdal32-python38-geo:2", 558 | "version": 2 559 | } 560 | ] 561 | } 562 | ] 563 | --------------------------------------------------------------------------------