├── .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 |
5 |
6 |
7 | AWS lambda (Amazonlinux) Layers and Docker images.
8 |
9 |
10 |
11 |
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 |
--------------------------------------------------------------------------------