BuzzerboyAWSLightsail 0.330.1__py3-none-any.whl → 0.331.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- BuzzerboyAWSLightsailStack/LightsailContainer.py +5 -4
- BuzzerboyAWSLightsailStack/LightsailDatabase.py +105 -37
- {buzzerboyawslightsail-0.330.1.dist-info → buzzerboyawslightsail-0.331.1.dist-info}/METADATA +1 -1
- buzzerboyawslightsail-0.331.1.dist-info/RECORD +11 -0
- buzzerboyawslightsail-0.330.1.dist-info/RECORD +0 -11
- {buzzerboyawslightsail-0.330.1.dist-info → buzzerboyawslightsail-0.331.1.dist-info}/WHEEL +0 -0
- {buzzerboyawslightsail-0.330.1.dist-info → buzzerboyawslightsail-0.331.1.dist-info}/licenses/LICENSE +0 -0
- {buzzerboyawslightsail-0.330.1.dist-info → buzzerboyawslightsail-0.331.1.dist-info}/top_level.txt +0 -0
|
@@ -70,18 +70,19 @@ class ArchitectureFlags(Enum):
|
|
|
70
70
|
"""
|
|
71
71
|
Architecture configuration flags for optional components.
|
|
72
72
|
|
|
73
|
-
Includes both base and container-specific flags.
|
|
73
|
+
Includes both base flags and container-specific flags.
|
|
74
74
|
|
|
75
75
|
Base flags:
|
|
76
76
|
:param SKIP_DEFAULT_POST_APPLY_SCRIPTS: Skip default post-apply scripts
|
|
77
|
-
:param PRESERVE_EXISTING_SECRETS: Don't overwrite existing secret versions
|
|
77
|
+
:param PRESERVE_EXISTING_SECRETS: Don't overwrite existing secret versions (smart detection)
|
|
78
78
|
:param IGNORE_SECRET_CHANGES: Ignore all changes to secret after initial creation
|
|
79
79
|
|
|
80
80
|
Container-specific flags:
|
|
81
81
|
:param SKIP_DATABASE: Skip database creation
|
|
82
82
|
:param SKIP_DOMAIN: Skip domain and DNS configuration
|
|
83
83
|
"""
|
|
84
|
-
|
|
84
|
+
|
|
85
|
+
# Base flags from BaseLightsailArchitectureFlags
|
|
85
86
|
SKIP_DEFAULT_POST_APPLY_SCRIPTS = "skip_default_post_apply_scripts"
|
|
86
87
|
PRESERVE_EXISTING_SECRETS = "preserve_existing_secrets"
|
|
87
88
|
IGNORE_SECRET_CHANGES = "ignore_secret_changes"
|
|
@@ -185,7 +186,7 @@ class LightsailContainerStack(LightsailBase):
|
|
|
185
186
|
super()._set_default_post_apply_scripts()
|
|
186
187
|
|
|
187
188
|
# Skip if flag is set
|
|
188
|
-
if
|
|
189
|
+
if BaseLightsailArchitectureFlags.SKIP_DEFAULT_POST_APPLY_SCRIPTS.value in self.flags:
|
|
189
190
|
return
|
|
190
191
|
|
|
191
192
|
# Add container-specific scripts
|
|
@@ -41,22 +41,28 @@ from cdktf_cdktf_provider_random import password
|
|
|
41
41
|
|
|
42
42
|
#endregion
|
|
43
43
|
|
|
44
|
+
#region Null Provider and Resources
|
|
45
|
+
from cdktf_cdktf_provider_null.resource import Resource as NullResource
|
|
46
|
+
|
|
47
|
+
#endregion
|
|
48
|
+
|
|
44
49
|
#region ArchitectureFlags
|
|
45
50
|
class ArchitectureFlags(Enum):
|
|
46
51
|
"""
|
|
47
52
|
Architecture configuration flags for optional components.
|
|
48
53
|
|
|
49
|
-
Includes both base and database-specific flags.
|
|
54
|
+
Includes both base flags and database-specific flags.
|
|
50
55
|
|
|
51
56
|
Base flags:
|
|
52
57
|
:param SKIP_DEFAULT_POST_APPLY_SCRIPTS: Skip default post-apply scripts
|
|
53
|
-
:param PRESERVE_EXISTING_SECRETS: Don't overwrite existing secret versions
|
|
58
|
+
:param PRESERVE_EXISTING_SECRETS: Don't overwrite existing secret versions (smart detection)
|
|
54
59
|
:param IGNORE_SECRET_CHANGES: Ignore all changes to secret after initial creation
|
|
55
60
|
|
|
56
61
|
Database-specific flags:
|
|
57
62
|
:param SKIP_DATABASE_USERS: Skip creating individual database users (use master user only)
|
|
58
63
|
"""
|
|
59
|
-
|
|
64
|
+
|
|
65
|
+
# Base flags from BaseLightsailArchitectureFlags
|
|
60
66
|
SKIP_DEFAULT_POST_APPLY_SCRIPTS = "skip_default_post_apply_scripts"
|
|
61
67
|
PRESERVE_EXISTING_SECRETS = "preserve_existing_secrets"
|
|
62
68
|
IGNORE_SECRET_CHANGES = "ignore_secret_changes"
|
|
@@ -73,8 +79,8 @@ class LightsailDatabaseStack(LightsailBase):
|
|
|
73
79
|
|
|
74
80
|
A comprehensive database stack that deploys:
|
|
75
81
|
* Lightsail Database instance with PostgreSQL
|
|
76
|
-
* Multiple databases within the instance
|
|
77
|
-
* Individual database users with scoped permissions
|
|
82
|
+
* Multiple databases within the instance (automated creation)
|
|
83
|
+
* Individual database users with scoped permissions (automated creation)
|
|
78
84
|
* Secrets Manager for storing all database credentials
|
|
79
85
|
* IAM resources for programmatic access
|
|
80
86
|
|
|
@@ -126,6 +132,7 @@ class LightsailDatabaseStack(LightsailBase):
|
|
|
126
132
|
:param db_instance_size: Database instance size (default: "micro_2_0")
|
|
127
133
|
:param db_engine: Database engine version (default: "postgres_14")
|
|
128
134
|
:param master_username: Master database username (default: "dbmasteruser")
|
|
135
|
+
:param db_publicly_accessible: Enable public access to database (default: True, required for automated provisioning)
|
|
129
136
|
"""
|
|
130
137
|
# Set database-specific defaults
|
|
131
138
|
if "project_name" not in kwargs:
|
|
@@ -135,7 +142,7 @@ class LightsailDatabaseStack(LightsailBase):
|
|
|
135
142
|
environment = kwargs.get("environment", "dev")
|
|
136
143
|
kwargs["secret_name"] = f"{project_name}/{environment}/database-credentials"
|
|
137
144
|
|
|
138
|
-
# ===== Database-Specific Configuration (set before
|
|
145
|
+
# ===== Database-Specific Configuration (MUST be set before super().__init__) =====
|
|
139
146
|
self.databases = kwargs.get("databases", [])
|
|
140
147
|
|
|
141
148
|
# Validate required parameters
|
|
@@ -146,12 +153,13 @@ class LightsailDatabaseStack(LightsailBase):
|
|
|
146
153
|
self.master_username = kwargs.get("master_username", "dbmasteruser")
|
|
147
154
|
self.db_instance_size = kwargs.get("db_instance_size", "micro_2_0")
|
|
148
155
|
self.db_engine = kwargs.get("db_engine", "postgres_14")
|
|
156
|
+
self.db_publicly_accessible = kwargs.get("db_publicly_accessible", True)
|
|
149
157
|
|
|
150
158
|
# ===== Internal State =====
|
|
151
159
|
self.database_users = {}
|
|
152
160
|
self.database_passwords = {}
|
|
153
161
|
|
|
154
|
-
# Call parent constructor
|
|
162
|
+
# Call parent constructor (this will call _set_default_post_apply_scripts)
|
|
155
163
|
super().__init__(scope, id, **kwargs)
|
|
156
164
|
|
|
157
165
|
def _set_default_post_apply_scripts(self):
|
|
@@ -162,7 +170,7 @@ class LightsailDatabaseStack(LightsailBase):
|
|
|
162
170
|
super()._set_default_post_apply_scripts()
|
|
163
171
|
|
|
164
172
|
# Skip if flag is set
|
|
165
|
-
if
|
|
173
|
+
if BaseLightsailArchitectureFlags.SKIP_DEFAULT_POST_APPLY_SCRIPTS.value in self.flags:
|
|
166
174
|
return
|
|
167
175
|
|
|
168
176
|
# Add database-specific scripts before the final message
|
|
@@ -191,8 +199,9 @@ class LightsailDatabaseStack(LightsailBase):
|
|
|
191
199
|
|
|
192
200
|
Creates:
|
|
193
201
|
* Database passwords for master and individual users
|
|
194
|
-
* Lightsail PostgreSQL database instance
|
|
195
|
-
* Individual
|
|
202
|
+
* Lightsail PostgreSQL database instance (with public access enabled)
|
|
203
|
+
* Individual databases within the instance (automated via SQL)
|
|
204
|
+
* Individual database users with scoped permissions (automated via SQL)
|
|
196
205
|
"""
|
|
197
206
|
# Generate passwords first
|
|
198
207
|
self.create_database_passwords()
|
|
@@ -241,7 +250,13 @@ class LightsailDatabaseStack(LightsailBase):
|
|
|
241
250
|
* Engine: PostgreSQL (version specified by db_engine)
|
|
242
251
|
* Size: Configurable (default: micro_2_0)
|
|
243
252
|
* Master database: Uses first database name from the list
|
|
253
|
+
* Public Access: Configurable (default: True for automated provisioning)
|
|
244
254
|
* Final snapshot: Disabled (skip_final_snapshot=True)
|
|
255
|
+
|
|
256
|
+
.. note::
|
|
257
|
+
Public access is enabled by default to allow automated database creation
|
|
258
|
+
via local-exec provisioners. This can be disabled by setting
|
|
259
|
+
db_publicly_accessible=False, but will require manual database setup.
|
|
245
260
|
"""
|
|
246
261
|
# Use the first database name as the master database name
|
|
247
262
|
master_db_name = self.clean_hyphens(self.databases[0])
|
|
@@ -255,6 +270,7 @@ class LightsailDatabaseStack(LightsailBase):
|
|
|
255
270
|
master_database_name=master_db_name,
|
|
256
271
|
master_username=self.master_username,
|
|
257
272
|
master_password=self.master_password.result,
|
|
273
|
+
publicly_accessible=self.db_publicly_accessible,
|
|
258
274
|
skip_final_snapshot=True,
|
|
259
275
|
tags={
|
|
260
276
|
"Environment": self.environment,
|
|
@@ -280,28 +296,35 @@ class LightsailDatabaseStack(LightsailBase):
|
|
|
280
296
|
|
|
281
297
|
def create_database_users(self):
|
|
282
298
|
"""
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
This method
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
299
|
+
Create individual databases and users within the Lightsail PostgreSQL instance.
|
|
300
|
+
|
|
301
|
+
This method automates the creation of databases and users using SQL commands
|
|
302
|
+
executed via null_resource provisioners. For each database in the databases list:
|
|
303
|
+
1. Generates a password for the database user
|
|
304
|
+
2. Stores credentials in the secrets dictionary
|
|
305
|
+
3. Creates the database (if not the first one - master database)
|
|
306
|
+
4. Creates a dedicated user with the generated password
|
|
307
|
+
5. Grants all privileges on the database to the user
|
|
308
|
+
|
|
309
|
+
**Automated Database Setup:**
|
|
310
|
+
The following operations are performed automatically for each database:
|
|
294
311
|
* CREATE DATABASE {db_name};
|
|
295
312
|
* CREATE USER "{db_name}-dbuser" WITH PASSWORD '{password}';
|
|
296
313
|
* GRANT ALL PRIVILEGES ON DATABASE {db_name} TO "{db_name}-dbuser";
|
|
314
|
+
* GRANT ALL ON SCHEMA public TO "{db_name}-dbuser";
|
|
297
315
|
|
|
298
316
|
.. note::
|
|
299
|
-
|
|
300
|
-
|
|
317
|
+
The first database in the list is created as the master database during
|
|
318
|
+
instance creation, so it's skipped in this automated provisioning process.
|
|
319
|
+
|
|
320
|
+
.. note::
|
|
321
|
+
Requires publicly_accessible=True on the database instance for the
|
|
322
|
+
provisioner to connect from the local machine running Terraform.
|
|
301
323
|
"""
|
|
302
324
|
if ArchitectureFlags.SKIP_DATABASE_USERS.value in self.flags:
|
|
303
325
|
return
|
|
304
326
|
|
|
327
|
+
# Store credentials for all databases
|
|
305
328
|
for db_name in self.databases:
|
|
306
329
|
clean_db_name = self.clean_hyphens(db_name)
|
|
307
330
|
username = f"{clean_db_name}-dbuser"
|
|
@@ -319,22 +342,67 @@ class LightsailDatabaseStack(LightsailBase):
|
|
|
319
342
|
"database": clean_db_name
|
|
320
343
|
}
|
|
321
344
|
|
|
322
|
-
#
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
f"CREATE USER \"{username}\" WITH PASSWORD '<password_from_secrets>';",
|
|
331
|
-
f"GRANT ALL PRIVILEGES ON DATABASE \"{clean_db_name}\" TO \"{username}\";"
|
|
332
|
-
])
|
|
345
|
+
# Skip the first database as it's already created as the master database
|
|
346
|
+
databases_to_create = self.databases[1:] if len(self.databases) > 1 else []
|
|
347
|
+
|
|
348
|
+
# Create additional databases and users using null_resource
|
|
349
|
+
for db_name in databases_to_create:
|
|
350
|
+
clean_db_name = self.clean_hyphens(db_name)
|
|
351
|
+
username = f"{clean_db_name}-dbuser"
|
|
352
|
+
password_ref = self.database_passwords[db_name].result
|
|
333
353
|
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
354
|
+
# SQL commands to create database and user
|
|
355
|
+
# Using environment variables to avoid Terraform interpolation issues
|
|
356
|
+
sql_commands = f"""#!/bin/bash
|
|
357
|
+
set -e
|
|
358
|
+
|
|
359
|
+
echo "Creating database: {clean_db_name}"
|
|
360
|
+
|
|
361
|
+
# Wait for database to be ready (add retry logic)
|
|
362
|
+
for i in {{1..30}}; do
|
|
363
|
+
if PGPASSWORD="$MASTER_PASSWORD" psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d postgres -c "SELECT 1" > /dev/null 2>&1; then
|
|
364
|
+
echo "Database is ready"
|
|
365
|
+
break
|
|
366
|
+
fi
|
|
367
|
+
echo "Waiting for database to be ready... ($i/30)"
|
|
368
|
+
sleep 10
|
|
369
|
+
done
|
|
370
|
+
|
|
371
|
+
# Create database
|
|
372
|
+
PGPASSWORD="$MASTER_PASSWORD" psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d postgres -c "CREATE DATABASE \\"{clean_db_name}\\";" || echo "Database {clean_db_name} may already exist"
|
|
373
|
+
|
|
374
|
+
# Create user
|
|
375
|
+
PGPASSWORD="$MASTER_PASSWORD" psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d postgres -c "CREATE USER \\"{username}\\" WITH PASSWORD '$USER_PASSWORD';" || echo "User {username} may already exist"
|
|
376
|
+
|
|
377
|
+
# Grant database privileges
|
|
378
|
+
PGPASSWORD="$MASTER_PASSWORD" psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d postgres -c "GRANT ALL PRIVILEGES ON DATABASE \\"{clean_db_name}\\" TO \\"{username}\\";"
|
|
379
|
+
|
|
380
|
+
# Grant schema privileges
|
|
381
|
+
PGPASSWORD="$MASTER_PASSWORD" psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d {clean_db_name} -c "GRANT ALL ON SCHEMA public TO \\"{username}\\";"
|
|
382
|
+
|
|
383
|
+
echo "Successfully created database: {clean_db_name} with user: {username}"
|
|
384
|
+
"""
|
|
385
|
+
|
|
386
|
+
# Create null_resource to execute SQL commands
|
|
387
|
+
db_resource = NullResource(
|
|
388
|
+
self,
|
|
389
|
+
f"create_database_{clean_db_name}",
|
|
390
|
+
depends_on=[self.database]
|
|
337
391
|
)
|
|
392
|
+
|
|
393
|
+
# Add provisioner using override
|
|
394
|
+
db_resource.add_override("provisioner", [{
|
|
395
|
+
"local-exec": {
|
|
396
|
+
"command": sql_commands,
|
|
397
|
+
"environment": {
|
|
398
|
+
"DB_HOST": self.database.master_endpoint_address,
|
|
399
|
+
"DB_PORT": self.database.master_endpoint_port,
|
|
400
|
+
"DB_USER": self.master_username,
|
|
401
|
+
"MASTER_PASSWORD": self.master_password.result,
|
|
402
|
+
"USER_PASSWORD": password_ref,
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
}])
|
|
338
406
|
|
|
339
407
|
def create_outputs(self):
|
|
340
408
|
"""
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
BuzzerboyAWSLightsailStack/LightSailPostDeploy.py,sha256=uOEOe5qORPgvivC0Ba0w045PQztfS6z-ynwyikaPQzI,5025
|
|
2
|
+
BuzzerboyAWSLightsailStack/LightsailAIContainer.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
|
+
BuzzerboyAWSLightsailStack/LightsailBase.py,sha256=Fn1RQv4lVtkLmCZH6FFpxpnGQ6W0CRjF7nNNjI_uFjY,26085
|
|
4
|
+
BuzzerboyAWSLightsailStack/LightsailContainer.py,sha256=Ax7MIaeKY3tCxiTeX3sfnviM9ksWjestDXkg2w3XLes,13871
|
|
5
|
+
BuzzerboyAWSLightsailStack/LightsailDatabase.py,sha256=yKgWbM5UaEV-kSxy3rV8hM6WIDCRRM_z-DUAaY2X654,19258
|
|
6
|
+
BuzzerboyAWSLightsailStack/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
7
|
+
buzzerboyawslightsail-0.331.1.dist-info/licenses/LICENSE,sha256=hxCyRAUWBBbbve3BaE8Qtl_sxcUo-8AYNAslHjeiu3w,921
|
|
8
|
+
buzzerboyawslightsail-0.331.1.dist-info/METADATA,sha256=34sNvPKHxuM1uhrG-deG4ClnsLIBQXp2u27-Vd9-iMk,4942
|
|
9
|
+
buzzerboyawslightsail-0.331.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
10
|
+
buzzerboyawslightsail-0.331.1.dist-info/top_level.txt,sha256=xqYoH36d7_13q4vRi5bZr1zIz9mR7b8ms_6ez3BqRgQ,27
|
|
11
|
+
buzzerboyawslightsail-0.331.1.dist-info/RECORD,,
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
BuzzerboyAWSLightsailStack/LightSailPostDeploy.py,sha256=uOEOe5qORPgvivC0Ba0w045PQztfS6z-ynwyikaPQzI,5025
|
|
2
|
-
BuzzerboyAWSLightsailStack/LightsailAIContainer.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
|
-
BuzzerboyAWSLightsailStack/LightsailBase.py,sha256=Fn1RQv4lVtkLmCZH6FFpxpnGQ6W0CRjF7nNNjI_uFjY,26085
|
|
4
|
-
BuzzerboyAWSLightsailStack/LightsailContainer.py,sha256=XnJU1iydnmiWTB_9MNIA9pnvsAnMyymuw38koKJj4bM,13831
|
|
5
|
-
BuzzerboyAWSLightsailStack/LightsailDatabase.py,sha256=hXZzphlD3COTd7J7yNjzHFqQu-wvh1fX6k7LRoPvews,15962
|
|
6
|
-
BuzzerboyAWSLightsailStack/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
7
|
-
buzzerboyawslightsail-0.330.1.dist-info/licenses/LICENSE,sha256=hxCyRAUWBBbbve3BaE8Qtl_sxcUo-8AYNAslHjeiu3w,921
|
|
8
|
-
buzzerboyawslightsail-0.330.1.dist-info/METADATA,sha256=vYh8iPWubNWfx3fcSktLnl3H8T7J5c7n6kKSNOT343I,4942
|
|
9
|
-
buzzerboyawslightsail-0.330.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
10
|
-
buzzerboyawslightsail-0.330.1.dist-info/top_level.txt,sha256=xqYoH36d7_13q4vRi5bZr1zIz9mR7b8ms_6ez3BqRgQ,27
|
|
11
|
-
buzzerboyawslightsail-0.330.1.dist-info/RECORD,,
|
|
File without changes
|
{buzzerboyawslightsail-0.330.1.dist-info → buzzerboyawslightsail-0.331.1.dist-info}/licenses/LICENSE
RENAMED
|
File without changes
|
{buzzerboyawslightsail-0.330.1.dist-info → buzzerboyawslightsail-0.331.1.dist-info}/top_level.txt
RENAMED
|
File without changes
|