Full lab documentation and infrastructure as code

- Trino catalogs, Grafana, Spark jobs, LDAP LDIF, NPM compose
- Airflow DAG scripts, Proxmox VM inventory, network docs
- Ansible playbook, Gitea CI validate workflow
- Backup and health-check scripts, cron documentation
- Homepage DOCS tab with links to all documentation
- Extended collect-fleet-config.sh and populate-repo.py
This commit is contained in:
Lakehouse Admin
2026-05-19 23:12:41 +02:00
parent 3c8993a41e
commit df5ec93dc3
46 changed files with 1809 additions and 74 deletions
+1 -1
View File
@@ -1193,7 +1193,7 @@ enable_swagger_ui = True
#
# Variable: AIRFLOW__API__SECRET_KEY
#
secret_key = REDACTED
secret_key = 010RL08807/JBjH4cWzNaw==
# Expose the configuration file in the web server. Set to ``non-sensitive-only`` to show all values
# except those that have security implications. ``True`` shows all values. ``False`` hides the
@@ -0,0 +1,90 @@
#!/usr/bin/env python3
"""
Script to generate fake telemetry data for Cassandra
Generates approximately 1GB of data
"""
from cassandra.cluster import Cluster
import random
from datetime import datetime, timedelta
import uuid
import sys
# Database connection details
DB_HOST = "10.0.21.51"
DB_PORT = "9042"
KEYSPACE = "telemetry"
TABLE_NAME = "device_metrics"
# Data generation settings
TARGET_ROWS = 3000000 # Approximately 1GB of data
BATCH_SIZE = 5000
# Sample data
METRIC_TYPES = ["temperature", "humidity", "pressure", "voltage", "current"]
DEVICE_PREFIX = "device-"
def generate_fake_device_metric():
"""Generate a single fake device metric"""
device_id = f"{DEVICE_PREFIX}{random.randint(1, 50000)}"
# Random timestamp within the last year
days_ago = random.randint(0, 365)
metric_ts = datetime.now() - timedelta(days=days_ago, hours=random.randint(0, 23),
minutes=random.randint(0, 59))
metric_type = random.choice(METRIC_TYPES)
metric_value = round(random.uniform(0.0, 100.0), 4)
# Generate a long payload field
payload = "X" * 200
return (device_id, metric_ts, metric_type, metric_value, payload)
def main():
print(f"Connecting to Cassandra at {DB_HOST}:{DB_PORT}...")
cluster = Cluster([DB_HOST], port=DB_PORT)
session = cluster.connect()
print(f"Generating {TARGET_ROWS} device metrics...")
print(f"Batch size: {BATCH_SIZE}")
total_generated = 0
batch = []
for i in range(TARGET_ROWS):
batch.append(generate_fake_device_metric())
if len(batch) >= BATCH_SIZE:
session.execute(
f"""
INSERT INTO {KEYSPACE}.{TABLE_NAME} (device_id, metric_ts, metric_type, metric_value, payload)
VALUES (%s, %s, %s, %s, %s)
""",
batch
)
total_generated += len(batch)
batch = []
if total_generated % 100000 == 0:
print(f"Generated {total_generated} rows...")
# Insert remaining rows
if batch:
session.execute(
f"""
INSERT INTO {KEYSPACE}.{TABLE_NAME} (device_id, metric_ts, metric_type, metric_value, payload)
VALUES (%s, %s, %s, %s, %s)
""",
batch
)
total_generated += len(batch)
session.shutdown()
cluster.shutdown()
print(f"Completed! Generated {total_generated} device metrics.")
if __name__ == "__main__":
main()
@@ -0,0 +1,89 @@
#!/usr/bin/env python3
"""
Script to generate fake event data for MongoDB
Generates approximately 1GB of data
"""
import pymongo
import random
from datetime import datetime, timedelta
import uuid
import sys
# Database connection details
DB_HOST = "10.0.21.51"
DB_PORT = "27017"
DB_NAME = "supplychain"
COLLECTION_NAME = "events"
# Data generation settings
TARGET_DOCUMENTS = 3000000 # Approximately 1GB of data
BATCH_SIZE = 5000
# Sample data
EVENT_TYPES = ["INSERT", "UPDATE", "DELETE", "CREATE", "MODIFY"]
REGIONS = ["EU", "APAC", "LATAM", "NA", "EMEA"]
SOURCES = ["ERP", "WMS", "CRM", "SCM", "TMS"]
def generate_fake_event():
"""Generate a single fake event"""
event_id = uuid.uuid4()
event_type = random.choice(EVENT_TYPES)
region = random.choice(REGIONS)
source = random.choice(SOURCES)
# Random timestamp within the last year
days_ago = random.randint(0, 365)
ts = datetime.now() - timedelta(days=days_ago, hours=random.randint(0, 23),
minutes=random.randint(0, 59))
amount = random.uniform(100.0, 50000.0)
# Generate a long payload field (like the existing data)
payload = "X" * 500
return {
"event_id": event_id,
"type": event_type,
"region": region,
"source": source,
"amount": amount,
"ts": ts,
"payload": payload
}
def main():
print(f"Connecting to MongoDB at {DB_HOST}:{DB_PORT}...")
client = pymongo.MongoClient(f"mongodb://{DB_HOST}:{DB_PORT}/")
db = client[DB_NAME]
collection = db[COLLECTION_NAME]
print(f"Generating {TARGET_DOCUMENTS} events...")
print(f"Batch size: {BATCH_SIZE}")
total_generated = 0
batch = []
for i in range(TARGET_DOCUMENTS):
batch.append(generate_fake_event())
if len(batch) >= BATCH_SIZE:
collection.insert_many(batch)
total_generated += len(batch)
batch = []
if total_generated % 100000 == 0:
print(f"Generated {total_generated} documents...")
# Insert remaining documents
if batch:
collection.insert_many(batch)
total_generated += len(batch)
client.close()
print(f"Completed! Generated {total_generated} events.")
if __name__ == "__main__":
main()
@@ -0,0 +1,106 @@
#!/usr/bin/env python3
"""
Script to generate fake employee event data for MySQL
Generates approximately 1GB of data
"""
import mysql.connector
import random
from datetime import datetime, timedelta
import uuid
import sys
# Database connection details
DB_HOST = "10.0.21.51"
DB_PORT = "3306"
DB_NAME = "hr"
DB_USER = "mo"
DB_PASSWORD = "Dell2026!"
# Data generation settings
TARGET_ROWS = 4000000 # Approximately 1GB of data
BATCH_SIZE = 10000
# Sample data
DEPARTMENTS = ["HR", "Operations", "Sales", "Marketing", "Finance", "IT", "Engineering", "Legal"]
ROLE_NAMES = ["Analyst", "Lead", "Manager", "Consultant", "Director", "Engineer", "Specialist", "Coordinator"]
REGIONS = ["EU", "APAC", "LATAM", "NA", "EMEA"]
EVENT_TYPES = ["TRANSFER", "PROMOTION", "TERMINATION", "HIRED", "SALARY_CHANGE", "DEPARTMENT_CHANGE"]
def generate_fake_employee_event():
"""Generate a single fake employee event"""
employee_id = random.randint(1, 100000)
department = random.choice(DEPARTMENTS)
role_name = random.choice(ROLE_NAMES)
region = random.choice(REGIONS)
event_type = random.choice(EVENT_TYPES)
# Random timestamp within the last 2 years
days_ago = random.randint(0, 730)
event_ts = datetime.now() - timedelta(days=days_ago, hours=random.randint(0, 23),
minutes=random.randint(0, 59))
salary_change = round(random.uniform(1000.0, 20000.0), 2) if random.random() > 0.3 else None
# Generate a long notes field (like the existing data)
notes = str(uuid.uuid4()) * 10
return (employee_id, department, role_name, region, event_type, salary_change, event_ts, notes)
def main():
print(f"Connecting to MySQL at {DB_HOST}:{DB_PORT}...")
conn = mysql.connector.connect(
host=DB_HOST,
port=DB_PORT,
database=DB_NAME,
user=DB_USER,
password=DB_PASSWORD
)
cursor = conn.cursor()
print(f"Generating {TARGET_ROWS} employee events...")
print(f"Batch size: {BATCH_SIZE}")
total_generated = 0
batch = []
for i in range(TARGET_ROWS):
batch.append(generate_fake_employee_event())
if len(batch) >= BATCH_SIZE:
cursor.executemany(
"""
INSERT INTO employee_events (employee_id, department, role_name, region,
event_type, salary_change, event_ts, notes)
VALUES (%s, %s, %s, %s, %s, %s, %s, %s)
""",
batch
)
conn.commit()
total_generated += len(batch)
batch = []
if total_generated % 100000 == 0:
print(f"Generated {total_generated} rows...")
# Insert remaining rows
if batch:
cursor.executemany(
"""
INSERT INTO employee_events (employee_id, department, role_name, region,
event_type, salary_change, event_ts, notes)
VALUES (%s, %s, %s, %s, %s, %s, %s, %s)
""",
batch
)
conn.commit()
total_generated += len(batch)
cursor.close()
conn.close()
print(f"Completed! Generated {total_generated} employee events.")
if __name__ == "__main__":
main()
@@ -0,0 +1,227 @@
#!/usr/bin/env python3
"""
Script to generate fake graph data for Neo4j
Generates approximately 1GB of data with nodes and relationships
"""
from neo4j import GraphDatabase
import random
import uuid
import sys
# Database connection details
DB_HOST = "10.0.21.51"
DB_PORT = "7687"
DB_USER = "neo4j"
DB_PASSWORD = "testpwd"
# Data generation settings
TARGET_NODES = 500000 # Approximately 1GB of data with relationships
BATCH_SIZE = 1000
# Sample data
PRODUCT_CATEGORIES = ["Electronics", "Clothing", "Food", "Furniture", "Toys", "Books"]
SUPPLIER_REGIONS = ["EU", "APAC", "LATAM", "NA", "EMEA"]
RELATIONSHIP_TYPES = ["SUPPLIES", "RELATED_TO", "COMPATIBLE_WITH", "PART_OF"]
def generate_fake_product():
"""Generate a single fake product node"""
product_id = str(uuid.uuid4())
name = f"Product-{random.randint(1000, 999999)}"
category = random.choice(PRODUCT_CATEGORIES)
price = round(random.uniform(10.0, 1000.0), 2)
stock = random.randint(0, 1000)
# Generate a long description field
description = "X" * 200
return {
"product_id": product_id,
"name": name,
"category": category,
"price": price,
"stock": stock,
"description": description
}
def generate_fake_supplier():
"""Generate a single fake supplier node"""
supplier_id = str(uuid.uuid4())
name = f"Supplier-{random.randint(1000, 999999)}"
region = random.choice(SUPPLIER_REGIONS)
rating = round(random.uniform(1.0, 5.0), 1)
# Generate a long address field
address = "X" * 150
return {
"supplier_id": supplier_id,
"name": name,
"region": region,
"rating": rating,
"address": address
}
def main():
print(f"Connecting to Neo4j at {DB_HOST}:{DB_PORT}...")
driver = GraphDatabase.driver(f"bolt://{DB_HOST}:{DB_PORT}",
auth=(DB_USER, DB_PASSWORD))
with driver.session() as session:
print(f"Generating {TARGET_NODES} product nodes...")
print(f"Batch size: {BATCH_SIZE}")
total_products = 0
total_suppliers = 0
product_ids = []
# Generate product nodes
batch = []
for i in range(TARGET_NODES):
product = generate_fake_product()
batch.append(product)
product_ids.append(product["product_id"])
if len(batch) >= BATCH_SIZE:
session.run(
"""
UNWIND $batch as row
CREATE (p:Product {
product_id: row.product_id,
name: row.name,
category: row.category,
price: row.price,
stock: row.stock,
description: row.description
})
""",
batch=batch
)
total_products += len(batch)
batch = []
if total_products % 50000 == 0:
print(f"Generated {total_products} product nodes...")
# Insert remaining products
if batch:
session.run(
"""
UNWIND $batch as row
CREATE (p:Product {
product_id: row.product_id,
name: row.name,
category: row.category,
price: row.price,
stock: row.stock,
description: row.description
})
""",
batch=batch
)
total_products += len(batch)
print(f"Generated {total_products} product nodes.")
# Generate supplier nodes (fewer than products)
print(f"Generating supplier nodes...")
target_suppliers = 10000
batch = []
supplier_ids = []
for i in range(target_suppliers):
supplier = generate_fake_supplier()
batch.append(supplier)
supplier_ids.append(supplier["supplier_id"])
if len(batch) >= BATCH_SIZE:
session.run(
"""
UNWIND $batch as row
CREATE (s:Supplier {
supplier_id: row.supplier_id,
name: row.name,
region: row.region,
rating: row.rating,
address: row.address
})
""",
batch=batch
)
total_suppliers += len(batch)
batch = []
if batch:
session.run(
"""
UNWIND $batch as row
CREATE (s:Supplier {
supplier_id: row.supplier_id,
name: row.name,
region: row.region,
rating: row.rating,
address: row.address
})
""",
batch=batch
)
total_suppliers += len(batch)
print(f"Generated {total_suppliers} supplier nodes.")
# Create relationships between products and suppliers
print(f"Creating relationships...")
batch = []
total_relationships = 0
for product_id in product_ids:
# Each product is supplied by 1-3 random suppliers
num_suppliers = random.randint(1, 3)
for _ in range(num_suppliers):
supplier_id = random.choice(supplier_ids)
rel_type = random.choice(RELATIONSHIP_TYPES)
batch.append({
"product_id": product_id,
"supplier_id": supplier_id,
"rel_type": rel_type
})
if len(batch) >= BATCH_SIZE:
session.run(
"""
UNWIND $batch as row
MATCH (p:Product {product_id: row.product_id})
MATCH (s:Supplier {supplier_id: row.supplier_id})
CALL apoc.create.relationship(p, row.rel_type, {}, s) YIELD rel
RETURN rel
""",
batch=batch
)
total_relationships += len(batch)
batch = []
if total_relationships % 50000 == 0:
print(f"Created {total_relationships} relationships...")
if batch:
session.run(
"""
UNWIND $batch as row
MATCH (p:Product {product_id: row.product_id})
MATCH (s:Supplier {supplier_id: row.supplier_id})
CALL apoc.create.relationship(p, row.rel_type, {}, s) YIELD rel
RETURN rel
""",
batch=batch
)
total_relationships += len(batch)
print(f"Created {total_relationships} relationships.")
driver.close()
print(f"Completed! Generated {total_products} products, {total_suppliers} suppliers, and {total_relationships} relationships.")
if __name__ == "__main__":
main()
@@ -0,0 +1,108 @@
#!/usr/bin/env python3
"""
Script to generate fake sales order data for PostgreSQL
Generates approximately 1GB of data
"""
import psycopg2
import random
from datetime import datetime, timedelta
import uuid
import sys
# Database connection details
DB_HOST = "10.0.21.51"
DB_PORT = "5432"
DB_NAME = "postgres"
DB_USER = "mo"
DB_PASSWORD = "Dell2026!"
# Data generation settings
TARGET_ROWS = 4000000 # Approximately 1GB of data
BATCH_SIZE = 10000
# Sample data
REGIONS = ["EU", "APAC", "LATAM", "NA", "EMEA"]
SALES_CHANNELS = ["STORE", "ONLINE", "MOBILE", "B2B"]
CURRENCIES = ["EUR", "USD", "GBP", "JPY", "CNY"]
ORDER_STATUSES = ["SHIPPED", "PENDING", "CANCELLED", "RETURNED", "DELIVERED"]
def generate_fake_order():
"""Generate a single fake sales order"""
customer_id = random.randint(1, 100000)
product_id = random.randint(1, 5000)
region = random.choice(REGIONS)
sales_channel = random.choice(SALES_CHANNELS)
# Random timestamp within the last 2 years
days_ago = random.randint(0, 730)
order_ts = datetime.now() - timedelta(days=days_ago, hours=random.randint(0, 23),
minutes=random.randint(0, 59))
amount = round(random.uniform(10.0, 10000.0), 2)
currency = random.choice(CURRENCIES)
order_status = random.choice(ORDER_STATUSES)
# Generate a long notes field (like the existing data)
notes = str(uuid.uuid4()) * 10
return (customer_id, product_id, region, sales_channel, order_ts,
amount, currency, order_status, notes)
def main():
print(f"Connecting to PostgreSQL at {DB_HOST}:{DB_PORT}...")
conn = psycopg2.connect(
host=DB_HOST,
port=DB_PORT,
database=DB_NAME,
user=DB_USER,
password=DB_PASSWORD
)
cursor = conn.cursor()
print(f"Generating {TARGET_ROWS} sales orders...")
print(f"Batch size: {BATCH_SIZE}")
total_generated = 0
batch = []
for i in range(TARGET_ROWS):
batch.append(generate_fake_order())
if len(batch) >= BATCH_SIZE:
cursor.executemany(
"""
INSERT INTO sales_orders (customer_id, product_id, region, sales_channel,
order_ts, amount, currency, order_status, notes)
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s)
""",
batch
)
conn.commit()
total_generated += len(batch)
batch = []
if total_generated % 100000 == 0:
print(f"Generated {total_generated} rows...")
# Insert remaining rows
if batch:
cursor.executemany(
"""
INSERT INTO sales_orders (customer_id, product_id, region, sales_channel,
order_ts, amount, currency, order_status, notes)
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s)
""",
batch
)
conn.commit()
total_generated += len(batch)
cursor.close()
conn.close()
print(f"Completed! Generated {total_generated} sales orders.")
if __name__ == "__main__":
main()