chore: initial project setup with backend, frontend, CI/CD, and documentation
Add complete NexaFabric project structure including: - FastAPI backend with SQLAlchemy models, JWT auth, RBAC, audit logging, and provider interfaces - React + TypeScript frontend with Vite, Tailwind CSS, TanStack Query, and Zustand - Docker Compose configuration for PostgreSQL, Redis, API, worker, frontend, and nginx - GitHub Actions and GitLab CI workflows for testing, linting, building, and security scanning - Environment
This commit is contained in:
@@ -0,0 +1,181 @@
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from app.core.config import get_settings
|
||||
from app.core.security import hash_password
|
||||
from app.models.domain import (
|
||||
AuditLog,
|
||||
Cluster,
|
||||
IpAddress,
|
||||
Network,
|
||||
Node,
|
||||
Policy,
|
||||
Project,
|
||||
Role,
|
||||
SecurityGroup,
|
||||
ServiceCatalogItem,
|
||||
Subnet,
|
||||
Tenant,
|
||||
User,
|
||||
Workload,
|
||||
)
|
||||
|
||||
|
||||
SERVICES = [
|
||||
("SSH", "tcp", "22"),
|
||||
("HTTP", "tcp", "80"),
|
||||
("HTTPS", "tcp", "443"),
|
||||
("DNS", "tcp/udp", "53"),
|
||||
("LDAP", "tcp", "389"),
|
||||
("LDAPS", "tcp", "636"),
|
||||
("RDP", "tcp", "3389"),
|
||||
("PostgreSQL", "tcp", "5432"),
|
||||
("MySQL/MariaDB", "tcp", "3306"),
|
||||
("MSSQL", "tcp", "1433"),
|
||||
("Redis", "tcp", "6379"),
|
||||
("SMB", "tcp", "445"),
|
||||
("SMTP", "tcp", "25"),
|
||||
("SMTPS", "tcp", "465"),
|
||||
("IMAPS", "tcp", "993"),
|
||||
("POP3S", "tcp", "995"),
|
||||
("Proxmox API", "tcp", "8006"),
|
||||
("Proxmox SPICE", "tcp", "3128"),
|
||||
]
|
||||
|
||||
|
||||
def seed_demo_data(db: Session) -> None:
|
||||
if db.scalar(select(User).where(User.email == "admin@nexafabric.local")):
|
||||
return
|
||||
|
||||
super_admin = Role(name="Super Admin", permissions=["*"])
|
||||
roles = [
|
||||
super_admin,
|
||||
Role(name="Network Admin", permissions=["networks:*", "ipam:*", "clusters:read"]),
|
||||
Role(name="Security Admin", permissions=["policies:*", "firewall:*", "security-groups:*"]),
|
||||
Role(name="Tenant Admin", permissions=["tenants:read", "projects:*"]),
|
||||
Role(name="Auditor", permissions=["audit:read", "clusters:read", "policies:read"]),
|
||||
Role(name="Read Only User", permissions=["*:read"]),
|
||||
]
|
||||
user = User(
|
||||
email="admin@nexafabric.local",
|
||||
display_name="NexaFabric Administrator",
|
||||
password_hash=hash_password(get_settings().demo_admin_password),
|
||||
roles=[super_admin],
|
||||
)
|
||||
db.add_all(roles + [user])
|
||||
|
||||
tenants = [
|
||||
Tenant(name="Platform", description="Shared infrastructure and platform services"),
|
||||
Tenant(name="Finance", description="Finance applications"),
|
||||
Tenant(name="Research", description="Lab and engineering workloads"),
|
||||
]
|
||||
db.add_all(tenants)
|
||||
db.flush()
|
||||
|
||||
projects = [
|
||||
Project(tenant_id=tenants[0].id, name="Core Services", description="DNS, auth, monitoring"),
|
||||
Project(tenant_id=tenants[1].id, name="ERP", description="Finance ERP workloads"),
|
||||
Project(tenant_id=tenants[2].id, name="Lab", description="Research lab systems"),
|
||||
]
|
||||
db.add_all(projects)
|
||||
db.flush()
|
||||
|
||||
cluster = Cluster(
|
||||
name="Demo Proxmox Cluster",
|
||||
api_url="https://pve-demo.local:8006",
|
||||
token_ref="demo-token-reference",
|
||||
last_sync_status="success",
|
||||
)
|
||||
db.add(cluster)
|
||||
db.flush()
|
||||
|
||||
nodes = [
|
||||
Node(cluster_id=cluster.id, name="pve-01", status="online", cpu_count=32, memory_mb=131072),
|
||||
Node(cluster_id=cluster.id, name="pve-02", status="online", cpu_count=32, memory_mb=131072),
|
||||
Node(cluster_id=cluster.id, name="pve-03", status="warning", cpu_count=24, memory_mb=98304),
|
||||
]
|
||||
db.add_all(nodes)
|
||||
db.flush()
|
||||
|
||||
networks = [
|
||||
Network(cluster_id=cluster.id, project_id=projects[0].id, name="mgmt", kind="bridge", vlan_id=10, gateway="10.10.10.1", dns=["10.10.10.10"], tags=["management"], description="Management bridge"),
|
||||
Network(cluster_id=cluster.id, project_id=projects[0].id, name="services", kind="vlan", vlan_id=20, gateway="10.20.0.1", dns=["10.20.0.10"], tags=["shared"], description="Shared services"),
|
||||
Network(cluster_id=cluster.id, project_id=projects[1].id, name="finance-app", kind="vxlan", vlan_id=120, gateway="10.120.0.1", dns=["10.20.0.10"], tags=["finance"], description="Finance application tier"),
|
||||
Network(cluster_id=cluster.id, project_id=projects[2].id, name="research-lab", kind="vnet", vlan_id=220, gateway="10.220.0.1", dns=["10.20.0.10"], tags=["lab"], description="Research tenant network"),
|
||||
]
|
||||
db.add_all(networks)
|
||||
db.flush()
|
||||
|
||||
subnets = [
|
||||
Subnet(network_id=networks[0].id, cidr="10.10.10.0/24", gateway="10.10.10.1", dns=["10.10.10.10"]),
|
||||
Subnet(network_id=networks[1].id, cidr="10.20.0.0/24", gateway="10.20.0.1", dns=["10.20.0.10"]),
|
||||
Subnet(network_id=networks[2].id, cidr="10.120.0.0/24", gateway="10.120.0.1", dns=["10.20.0.10"]),
|
||||
]
|
||||
db.add_all(subnets)
|
||||
db.flush()
|
||||
|
||||
workloads = []
|
||||
for idx in range(10):
|
||||
project = projects[idx % len(projects)]
|
||||
workloads.append(
|
||||
Workload(
|
||||
cluster_id=cluster.id,
|
||||
node_id=nodes[idx % len(nodes)].id,
|
||||
project_id=project.id,
|
||||
external_id=str(100 + idx),
|
||||
name=f"{project.name.lower().replace(' ', '-')}-{idx + 1}",
|
||||
kind="qemu" if idx % 3 else "lxc",
|
||||
status="running" if idx != 7 else "stopped",
|
||||
tags=["web"] if idx % 2 else ["db"],
|
||||
)
|
||||
)
|
||||
db.add_all(workloads)
|
||||
db.flush()
|
||||
|
||||
db.add_all(
|
||||
[
|
||||
IpAddress(subnet_id=subnets[0].id, address="10.10.10.20", status="assigned", workload_id=workloads[0].id),
|
||||
IpAddress(subnet_id=subnets[1].id, address="10.20.0.50", status="reserved", note="Load balancer VIP"),
|
||||
IpAddress(subnet_id=subnets[2].id, address="10.120.0.99", status="conflict", note="Duplicate detected during import"),
|
||||
]
|
||||
)
|
||||
|
||||
groups = [
|
||||
SecurityGroup(project_id=projects[0].id, name="Management", description="Administrative access"),
|
||||
SecurityGroup(project_id=projects[1].id, name="Finance Web", description="Finance web tier"),
|
||||
SecurityGroup(project_id=projects[1].id, name="Finance DB", description="Finance database tier"),
|
||||
]
|
||||
db.add_all(groups)
|
||||
|
||||
db.add_all(
|
||||
[
|
||||
Policy(
|
||||
project_id=projects[1].id,
|
||||
name="Finance web to database",
|
||||
definition={
|
||||
"source": "sg:Finance Web",
|
||||
"destination": "sg:Finance DB",
|
||||
"service": {"protocol": "tcp", "ports": "5432"},
|
||||
"action": "allow",
|
||||
"direction": "egress",
|
||||
"logging": True,
|
||||
"description": "Allow PostgreSQL from finance web tier to database tier.",
|
||||
},
|
||||
),
|
||||
Policy(
|
||||
project_id=projects[0].id,
|
||||
name="Management SSH",
|
||||
definition={
|
||||
"source": "network:mgmt",
|
||||
"destination": "any",
|
||||
"service": {"protocol": "tcp", "ports": "22"},
|
||||
"action": "allow",
|
||||
"direction": "ingress",
|
||||
},
|
||||
),
|
||||
]
|
||||
)
|
||||
|
||||
db.add_all([ServiceCatalogItem(name=name, protocol=proto, ports=ports, editable=True) for name, proto, ports in SERVICES])
|
||||
db.add(AuditLog(user_id=user.id, action="seed.created", object_type="system", result="success"))
|
||||
db.commit()
|
||||
Reference in New Issue
Block a user