Skip to content

Commit 463fab9

Browse files
committed
tested
1 parent 3946c04 commit 463fab9

3 files changed

Lines changed: 274 additions & 313 deletions

File tree

infra/scripts/data_scripts/_tested_locally_run_psql_load_tables_script.py

Lines changed: 0 additions & 114 deletions
This file was deleted.
Lines changed: 274 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,274 @@
1+
# version 1.2
2+
from azure.identity import DefaultAzureCredential
3+
from azure.keyvault.secrets import SecretClient
4+
import psycopg2
5+
from psycopg2 import sql
6+
import logging
7+
import sys
8+
9+
10+
################################################################################################
11+
# Initialization:
12+
# Parameters and logging
13+
# Retrieve secrets from Azure Key Vault
14+
################################################################################################
15+
16+
17+
key_vault_name = None
18+
19+
# Below parameters will be retrieve from Key Vault
20+
postgresql_end_point = None
21+
postgresql_admin_login = None
22+
mid_name = None
23+
postgresql_db_name = None
24+
25+
26+
# postgresql_admin_password = "YourValue" # Only used for local testing.
27+
# key_vault_name = "yourKeyVaultNameOnly" # if test locally
28+
29+
30+
31+
# Configure logging
32+
logging.basicConfig(
33+
level=logging.INFO,
34+
format="%(asctime)s - %(levelname)s - %(message)s",
35+
handlers=[logging.StreamHandler(sys.stdout)]
36+
)
37+
logging.info("Starting the script...")
38+
# Retrieve secrets from Key Vault
39+
40+
try:
41+
logging.info(f"Retrieving secrets from Key Vault '{key_vault_name}'...")
42+
key_vault_uri = f"https://{key_vault_name}.vault.azure.net/"
43+
credential = DefaultAzureCredential()
44+
secret_client = SecretClient(vault_url=key_vault_uri, credential=credential)
45+
postgresql_end_point = secret_client.get_secret("postgresql-server-end-point").value
46+
postgresql_admin_login = secret_client.get_secret("postgresql-admin-login").value
47+
mid_name = secret_client.get_secret("mid-name").value
48+
postgresql_db_name = secret_client.get_secret("postgresql-db-name").value
49+
50+
logging.info(f"Retrieved values from Key Vault:")
51+
logging.info(f"PostgreSql End Point: {postgresql_end_point}")
52+
logging.info(f"Admin Principal Name: {postgresql_admin_login}")
53+
logging.info(f"Managed Identity Name: {mid_name}")
54+
logging.info(f"Database Name: {postgresql_db_name}")
55+
56+
except Exception as e:
57+
logging.error(f"An error occurred while retrieving secrets: {e}")
58+
sys.exit(1)
59+
60+
# The rest of your script (e.g., database connection and table creation) goes here...
61+
62+
# Grant Permission Function
63+
def grant_permissions(cursor, db_name, schema_name, principal_name):
64+
"""
65+
Grants database and schema-level permissions to a specified principal.
66+
"""
67+
try:
68+
logging.info(f"Granting permissions to principal: {principal_name}")
69+
70+
# Check if the principal exists in the database
71+
cursor.execute(
72+
sql.SQL("SELECT 1 FROM pg_roles WHERE rolname = {principal}").format(
73+
principal=sql.Literal(principal_name)
74+
)
75+
)
76+
if cursor.fetchone() is None:
77+
logging.info(f"Principal '{principal_name}' does not exist. Creating it...")
78+
add_principal_user_query = sql.SQL(
79+
"SELECT * FROM pgaadauth_create_principal({principal}, false, false)"
80+
)
81+
cursor.execute(
82+
add_principal_user_query.format(
83+
principal=sql.Literal(principal_name),
84+
)
85+
)
86+
87+
# Grant CONNECT on database
88+
grant_connect_query = sql.SQL("GRANT CONNECT ON DATABASE {database} TO {principal}")
89+
cursor.execute(
90+
grant_connect_query.format(
91+
database=sql.Identifier(db_name),
92+
principal=sql.Identifier(principal_name),
93+
)
94+
)
95+
logging.info(f"Granted CONNECT on database '{db_name}' to '{principal_name}'")
96+
97+
# Grant SELECT, INSERT, UPDATE, DELETE on schema tables
98+
grant_permissions_query = sql.SQL(
99+
"GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA {schema} TO {principal}"
100+
)
101+
cursor.execute(
102+
grant_permissions_query.format(
103+
schema=sql.Identifier(schema_name),
104+
principal=sql.Identifier(principal_name),
105+
)
106+
)
107+
logging.info(f"Granted table-level permissions on schema '{schema_name}' to '{principal_name}'")
108+
109+
except Exception as e:
110+
logging.error(f"Error granting permissions to '{principal_name}': {e}")
111+
raise
112+
113+
#####################################################################################################
114+
# Main Program
115+
#####################################################################################################
116+
try:
117+
# Acquire the access token
118+
logging.info("Acquiring access token...")
119+
cred = DefaultAzureCredential()
120+
access_token = cred.get_token("https://ossrdbms-aad.database.windows.net/.default")
121+
logging.info("Access token acquired successfully.")
122+
123+
# Combine the token with the connection string to establish the connection
124+
logging.info("Establishing connection to the PostgreSQL server...")
125+
conn_string = "host={0} user={1} dbname={2} password={3} sslmode=require".format(
126+
postgresql_end_point, mid_name, postgresql_db_name, access_token.token
127+
)
128+
129+
# Below can be used for local testing.
130+
# conn_string = "host={0} user={1} dbname={2} password={3} sslmode=require".format(
131+
# postgresql_end_point, postgresql_admin_login, postgresql_db_name, postgresql_admin_password
132+
# )
133+
134+
conn = psycopg2.connect(conn_string)
135+
cursor = conn.cursor()
136+
logging.info("Connection established successfully.")
137+
138+
# Drop and recreate the products table
139+
logging.info("Dropping and recreating the 'products' table...")
140+
cursor.execute("DROP TABLE IF EXISTS products")
141+
conn.commit()
142+
143+
create_products_sql = """
144+
CREATE TABLE IF NOT EXISTS products
145+
(
146+
id integer,
147+
product_name character varying(100),
148+
price numeric(10,2) NOT NULL,
149+
category character varying(50),
150+
brand character varying(50),
151+
product_description text
152+
);
153+
"""
154+
cursor.execute(create_products_sql)
155+
conn.commit()
156+
logging.info("'products' table created successfully.")
157+
158+
# Drop and recreate the customers table
159+
logging.info("Dropping and recreating the 'customers' table...")
160+
cursor.execute("DROP TABLE IF EXISTS customers")
161+
conn.commit()
162+
163+
create_customers_sql = """
164+
CREATE TABLE customers
165+
(
166+
id integer,
167+
first_name character varying(50),
168+
last_name character varying(50),
169+
gender character varying(10),
170+
date_of_birth date,
171+
age integer,
172+
email character varying(100),
173+
phone character varying(20),
174+
post_address character varying(255),
175+
membership character varying(50)
176+
);
177+
"""
178+
cursor.execute(create_customers_sql)
179+
conn.commit()
180+
logging.info("'customers' table created successfully.")
181+
182+
# Drop and recreate the orders table
183+
logging.info("Dropping and recreating the 'orders' table...")
184+
cursor.execute("DROP TABLE IF EXISTS orders")
185+
conn.commit()
186+
187+
create_orders_sql = """
188+
CREATE TABLE orders
189+
(
190+
id integer,
191+
customer_id integer,
192+
customer_first_name character varying(50),
193+
customer_last_name character varying(50),
194+
customer_gender character varying(10),
195+
customer_age integer,
196+
customer_email character varying(100),
197+
customer_phone character varying(20),
198+
order_date date,
199+
product_id integer,
200+
product_name character varying(100),
201+
quantity integer,
202+
unit_price numeric(10,2),
203+
total numeric(10,2),
204+
category character varying(50),
205+
brand character varying(50),
206+
product_description text,
207+
return_status BOOLEAN DEFAULT FALSE
208+
);
209+
"""
210+
cursor.execute(create_orders_sql)
211+
conn.commit()
212+
logging.info("'orders' table created successfully.")
213+
214+
# Add Vector extension
215+
logging.info("Adding 'vector' extension...")
216+
cursor.execute("CREATE EXTENSION IF NOT EXISTS vector CASCADE;")
217+
conn.commit()
218+
219+
cursor.execute("DROP TABLE IF EXISTS vector_store;")
220+
conn.commit()
221+
222+
create_vs_sql = """
223+
CREATE TABLE IF NOT EXISTS vector_store(
224+
id text,
225+
title text,
226+
chunk integer,
227+
chunk_id text,
228+
"offset" integer,
229+
page_number integer,
230+
content text,
231+
source text,
232+
metadata text,
233+
content_vector public.vector(1536)
234+
);
235+
"""
236+
cursor.execute(create_vs_sql)
237+
conn.commit()
238+
239+
cursor.execute(
240+
"CREATE INDEX vector_store_content_vector_idx ON vector_store USING hnsw (content_vector vector_cosine_ops);"
241+
)
242+
conn.commit()
243+
logging.info("'vector_store' table and index created successfully.")
244+
245+
# Grant permissions to the admin principal if provided
246+
if postgresql_admin_login and postgresql_admin_login.strip():
247+
logging.info(f"Granting permissions to admin principal: {postgresql_admin_login}")
248+
grant_permissions(cursor, postgresql_db_name, "public", postgresql_admin_login)
249+
conn.commit()
250+
251+
# Grant permissions to the additional principal if provided
252+
if mid_name and mid_name.strip():
253+
logging.info(f"Granting permissions to identity: {mid_name}")
254+
grant_permissions(cursor, postgresql_db_name, "public", mid_name)
255+
conn.commit()
256+
257+
# Set default privileges for future tables in the public schema
258+
logging.info("Setting default privileges for future tables in the 'public' schema...")
259+
cursor.execute("""
260+
ALTER DEFAULT PRIVILEGES IN SCHEMA public
261+
GRANT ALL PRIVILEGES ON TABLES TO azure_pg_admin;
262+
""")
263+
conn.commit()
264+
logging.info("Default privileges set successfully.")
265+
266+
except Exception as e:
267+
logging.error(f"An error occurred: {e}")
268+
finally:
269+
# Close the cursor and connection
270+
if 'cursor' in locals() and cursor:
271+
cursor.close()
272+
if 'conn' in locals() and conn:
273+
conn.close()
274+
logging.info("Database connection closed.")

0 commit comments

Comments
 (0)