44"""
55
66import json
7+ import logging
78
89import boto3
910import httpx
1314from pypgstac .db import PgstacDB
1415from pypgstac .migrate import Migrate
1516
17+ logger = logging .getLogger ("eoapi-bootstrap" )
18+
1619
1720def send (
1821 event ,
@@ -36,10 +39,6 @@ def send(
3639 It isn't available for source code that's stored in Amazon S3 buckets.
3740 For code in buckets, you must write your own functions to send responses.
3841 """
39- responseUrl = event ["ResponseURL" ]
40-
41- print (responseUrl )
42-
4342 responseBody = {}
4443 responseBody ["Status" ] = responseStatus
4544 responseBody ["Reason" ] = (
@@ -53,21 +52,21 @@ def send(
5352 responseBody ["Data" ] = responseData
5453
5554 json_responseBody = json .dumps (responseBody )
56-
57- print ("Response body:\n " + json_responseBody )
58-
59- headers = {"content-type" : "" , "content-length" : str (len (json_responseBody ))}
55+ print ("Response body:\n " + json_responseBody )
6056
6157 try :
6258 response = httpx .put (
63- responseUrl ,
59+ event [ "ResponseURL" ] ,
6460 data = json_responseBody ,
65- headers = headers ,
61+ headers = { "content-type" : "" , "content-length" : str ( len ( json_responseBody ))} ,
6662 timeout = 30 ,
6763 )
68- print ("Status code: " + response .status_code )
64+ print ("Status code: " , response .status_code )
65+ logger .debug (f"OK - Status code: { response .status_code } " )
66+
6967 except Exception as e :
7068 print ("send(..) failed executing httpx.put(..): " + str (e ))
69+ logger .debug (f"NOK - failed executing PUT requests: { e } " )
7170
7271
7372def get_secret (secret_name ):
@@ -84,9 +83,9 @@ def create_db(cursor, db_name: str) -> None:
8483 sql .SQL ("SELECT 1 FROM pg_catalog.pg_database " "WHERE datname = %s" ), [db_name ]
8584 )
8685 if cursor .fetchone ():
87- print (f"database { db_name } exists, not creating DB" )
86+ print (f" database { db_name } exists, not creating DB" )
8887 else :
89- print (f"database { db_name } not found, creating..." )
88+ print (f" database { db_name } not found, creating..." )
9089 cursor .execute (
9190 sql .SQL ("CREATE DATABASE {db_name}" ).format (db_name = sql .Identifier (db_name ))
9291 )
@@ -114,8 +113,8 @@ def create_user(cursor, username: str, password: str) -> None:
114113 )
115114
116115
117- def create_permissions (cursor , db_name : str , username : str ) -> None :
118- """Add permissions."""
116+ def update_user_permissions (cursor , db_name : str , username : str ) -> None :
117+ """Update eoAPI user permissions."""
119118 cursor .execute (
120119 sql .SQL (
121120 "GRANT CONNECT ON DATABASE {db_name} TO {username};"
@@ -140,6 +139,33 @@ def register_extensions(cursor) -> None:
140139 cursor .execute (sql .SQL ("CREATE EXTENSION IF NOT EXISTS postgis;" ))
141140
142141
142+ ###############################################################################
143+ # PgSTAC Customization
144+ ###############################################################################
145+ def customization (cursor , params ) -> None :
146+ """
147+ CUSTOMIZED YOUR PGSTAC DATABASE
148+
149+ ref: https://github.com/stac-utils/pgstac/blob/main/docs/src/pgstac.md
150+
151+ """
152+ if str (params .get ("context" , "FALSE" )).upper () == "TRUE" :
153+ # Add CONTEXT=ON
154+ pgstac_settings = """
155+ INSERT INTO pgstac_settings (name, value)
156+ VALUES ('context', 'on')
157+ ON CONFLICT ON CONSTRAINT pgstac_settings_pkey DO UPDATE SET value = excluded.value;"""
158+ cursor .execute (sql .SQL (pgstac_settings ))
159+
160+ if str (params .get ("mosaic_index" , "TRUE" )).upper () == "TRUE" :
161+ # Create index of searches with `mosaic`` type
162+ cursor .execute (
163+ sql .SQL (
164+ "CREATE INDEX IF NOT EXISTS searches_mosaic ON searches ((true)) WHERE metadata->>'type'='mosaic';"
165+ )
166+ )
167+
168+
143169def handler (event , context ):
144170 """Lambda Handler."""
145171 print (f"Handling { event } " )
@@ -149,88 +175,90 @@ def handler(event, context):
149175
150176 try :
151177 params = event ["ResourceProperties" ]
152- connection_params = get_secret (params ["conn_secret_arn" ])
153- user_params = get_secret (params ["new_user_secret_arn" ])
154-
155- print ("Connecting to admin DB..." )
156- admin_db_conninfo = make_conninfo (
157- dbname = connection_params .get ("dbname" , "postgres" ),
158- user = connection_params ["username" ],
159- password = connection_params ["password" ],
160- host = connection_params ["host" ],
161- port = connection_params ["port" ],
178+
179+ # Admin (AWS RDS) user/password/dbname parameters
180+ admin_params = get_secret (params ["conn_secret_arn" ])
181+
182+ # Custom eoAPI user/password/dbname parameters
183+ eoapi_params = get_secret (params ["new_user_secret_arn" ])
184+
185+ print ("Connecting to RDS..." )
186+ rds_conninfo = make_conninfo (
187+ dbname = admin_params .get ("dbname" , "postgres" ),
188+ user = admin_params ["username" ],
189+ password = admin_params ["password" ],
190+ host = admin_params ["host" ],
191+ port = admin_params ["port" ],
162192 )
163- with psycopg .connect (admin_db_conninfo , autocommit = True ) as conn :
193+ with psycopg .connect (rds_conninfo , autocommit = True ) as conn :
164194 with conn .cursor () as cur :
165- print ("Creating database..." )
195+ print (f "Creating eoAPI ' { eoapi_params [ 'dbname' ] } ' database..." )
166196 create_db (
167197 cursor = cur ,
168- db_name = user_params ["dbname" ],
198+ db_name = eoapi_params ["dbname" ],
169199 )
170200
171- print ("Creating user..." )
201+ print (f "Creating eoAPI ' { eoapi_params [ 'username' ] } ' user..." )
172202 create_user (
173203 cursor = cur ,
174- username = user_params ["username" ],
175- password = user_params ["password" ],
204+ username = eoapi_params ["username" ],
205+ password = eoapi_params ["password" ],
176206 )
177207
178- # Install extensions on the user DB with
179- # superuser permissions, since they will
180- # otherwise fail to install when run as
181- # the non-superuser within the pgstac
182- # migrations.
183- print ("Connecting to STAC DB..." )
184- stac_db_conninfo = make_conninfo (
185- dbname = user_params ["dbname" ],
186- user = connection_params ["username" ],
187- password = connection_params ["password" ],
188- host = connection_params ["host" ],
189- port = connection_params ["port" ],
208+ # Install postgis and pgstac on the eoapi database with
209+ # superuser permissions
210+ print (f"Connecting to eoAPI '{ eoapi_params ['dbname' ]} ' database..." )
211+ eoapi_db_admin_conninfo = make_conninfo (
212+ dbname = eoapi_params ["dbname" ],
213+ user = admin_params ["username" ],
214+ password = admin_params ["password" ],
215+ host = admin_params ["host" ],
216+ port = admin_params ["port" ],
190217 )
191- with psycopg .connect (stac_db_conninfo , autocommit = True ) as conn :
218+ with psycopg .connect (eoapi_db_admin_conninfo , autocommit = True ) as conn :
192219 with conn .cursor () as cur :
193- print ("Registering PostGIS ..." )
220+ print (
221+ f"Registering Extension in '{ eoapi_params ['dbname' ]} ' database..."
222+ )
194223 register_extensions (cursor = cur )
195224
196- stac_db_admin_dsn = (
197- "postgresql://{user}:{password}@{host}:{port}/{dbname}" .format (
198- dbname = user_params .get ("dbname" , "postgres" ),
199- user = connection_params ["username" ],
200- password = connection_params ["password" ],
201- host = connection_params ["host" ],
202- port = connection_params ["port" ],
203- )
204- )
205-
206- pgdb = PgstacDB (dsn = stac_db_admin_dsn , debug = True )
207- print (f"Current { pgdb .version = } " )
225+ print ("Starting PgSTAC Migration " )
226+ with PgstacDB (connection = conn , debug = True ) as pgdb :
227+ print (f"Current PgSTAC Version: { pgdb .version } " )
208228
209- # As admin, run migrations
210- print ("Running migrations..." )
211- Migrate (pgdb ).run_migration (params ["pgstac_version" ])
212-
213- # Assign appropriate permissions to user (requires pgSTAC migrations to have run)
214- with psycopg .connect (admin_db_conninfo , autocommit = True ) as conn :
215- with conn .cursor () as cur :
216- print ("Setting permissions..." )
217- create_permissions (
218- cursor = cur ,
219- db_name = user_params ["dbname" ],
220- username = user_params ["username" ],
221- )
229+ print (f"Running migrations to PgSTAC { params ['pgstac_version' ]} ..." )
230+ Migrate (pgdb ).run_migration (params ["pgstac_version" ])
222231
223- print ("Adding mosaic index..." )
224232 with psycopg .connect (
225- stac_db_admin_dsn ,
233+ eoapi_db_admin_conninfo ,
226234 autocommit = True ,
227235 options = "-c search_path=pgstac,public -c application_name=pgstac" ,
228236 ) as conn :
229- conn .execute (
230- sql .SQL (
231- "CREATE INDEX IF NOT EXISTS searches_mosaic ON searches ((true)) WHERE metadata->>'type'='mosaic';"
237+ print ("Customize PgSTAC database..." )
238+ # Update permissions to eoAPI user to assume pgstac_* roles
239+ with conn .cursor () as cur :
240+ print (f"Update '{ eoapi_params ['username' ]} ' permissions..." )
241+ update_user_permissions (
242+ cursor = cur ,
243+ db_name = eoapi_params ["dbname" ],
244+ username = eoapi_params ["username" ],
232245 )
246+
247+ customization (cursor = cur , params = params )
248+
249+ # Make sure the user can access the database
250+ eoapi_user_dsn = (
251+ "postgresql://{user}:{password}@{host}:{port}/{dbname}" .format (
252+ dbname = eoapi_params ["dbname" ],
253+ user = eoapi_params ["username" ],
254+ password = eoapi_params ["password" ],
255+ host = admin_params ["host" ],
256+ port = admin_params ["port" ],
233257 )
258+ )
259+ print ("Checking eoAPI user access to the PgSTAC database..." )
260+ with PgstacDB (dsn = eoapi_user_dsn , debug = True ) as pgdb :
261+ print (f" OK - User has access to pgstac db, pgstac schema version: { pgdb .version } " )
234262
235263 except Exception as e :
236264 print (f"Unable to bootstrap database with exception={ e } " )
0 commit comments