Add feature flags, seed data utilities, and Angular frontend scaffold
Major enhancements: - Feature flag system for cloud vs air-gapped deployment modes - Automatic storage backend selection based on deployment mode - Comprehensive seed data generation utilities - Support for generating CSV, JSON, binary, and PCAP test files - Quick seed script for easy data generation - Angular 19 frontend complete setup documentation - Material Design UI component examples and configuration Fixes: - Resolve SQLAlchemy metadata column name conflict - Rename metadata to custom_metadata throughout codebase - Fix API health check issues Documentation: - FEATURES.md - Complete feature overview - FRONTEND_SETUP.md - Angular 19 setup guide with examples - SUMMARY.md - Implementation summary 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -36,7 +36,7 @@ async def upload_artifact(
|
||||
test_suite: Optional[str] = Form(None),
|
||||
test_config: Optional[str] = Form(None),
|
||||
test_result: Optional[str] = Form(None),
|
||||
metadata: Optional[str] = Form(None),
|
||||
custom_metadata: Optional[str] = Form(None),
|
||||
description: Optional[str] = Form(None),
|
||||
tags: Optional[str] = Form(None),
|
||||
version: Optional[str] = Form(None),
|
||||
@@ -51,7 +51,7 @@ async def upload_artifact(
|
||||
- **test_suite**: Test suite identifier
|
||||
- **test_config**: JSON string of test configuration
|
||||
- **test_result**: Test result (pass, fail, skip, error)
|
||||
- **metadata**: JSON string of additional metadata
|
||||
- **custom_metadata**: JSON string of additional metadata
|
||||
- **description**: Text description of the artifact
|
||||
- **tags**: JSON array of tags (as string)
|
||||
- **version**: Version identifier
|
||||
@@ -60,7 +60,7 @@ async def upload_artifact(
|
||||
try:
|
||||
# Parse JSON fields
|
||||
test_config_dict = json.loads(test_config) if test_config else None
|
||||
metadata_dict = json.loads(metadata) if metadata else None
|
||||
metadata_dict = json.loads(custom_metadata) if custom_metadata else None
|
||||
tags_list = json.loads(tags) if tags else None
|
||||
|
||||
# Generate unique storage path
|
||||
@@ -88,7 +88,7 @@ async def upload_artifact(
|
||||
test_suite=test_suite,
|
||||
test_config=test_config_dict,
|
||||
test_result=test_result,
|
||||
metadata=metadata_dict,
|
||||
custom_metadata=metadata_dict,
|
||||
description=description,
|
||||
tags=tags_list,
|
||||
version=version,
|
||||
|
||||
@@ -3,10 +3,13 @@ from typing import Literal
|
||||
|
||||
|
||||
class Settings(BaseSettings):
|
||||
# Deployment mode (feature flag)
|
||||
deployment_mode: Literal["cloud", "air-gapped"] = "air-gapped"
|
||||
|
||||
# Database
|
||||
database_url: str = "postgresql://user:password@localhost:5432/datalake"
|
||||
|
||||
# Storage Backend
|
||||
# Storage Backend (automatically set based on deployment_mode if not explicitly configured)
|
||||
storage_backend: Literal["s3", "minio"] = "minio"
|
||||
|
||||
# AWS S3
|
||||
@@ -31,5 +34,13 @@ class Settings(BaseSettings):
|
||||
env_file = ".env"
|
||||
case_sensitive = False
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
# Auto-configure storage backend based on deployment mode if not explicitly set
|
||||
if self.deployment_mode == "cloud" and self.storage_backend == "minio":
|
||||
self.storage_backend = "s3"
|
||||
elif self.deployment_mode == "air-gapped" and self.storage_backend == "s3":
|
||||
self.storage_backend = "minio"
|
||||
|
||||
|
||||
settings = Settings()
|
||||
|
||||
@@ -40,6 +40,7 @@ async def startup_event():
|
||||
"""Initialize database on startup"""
|
||||
logger.info("Initializing database...")
|
||||
init_db()
|
||||
logger.info(f"Deployment mode: {settings.deployment_mode}")
|
||||
logger.info(f"Using storage backend: {settings.storage_backend}")
|
||||
logger.info("Application started successfully")
|
||||
|
||||
@@ -51,6 +52,7 @@ async def root():
|
||||
"message": "Test Artifact Data Lake API",
|
||||
"version": "1.0.0",
|
||||
"docs": "/docs",
|
||||
"deployment_mode": settings.deployment_mode,
|
||||
"storage_backend": settings.storage_backend
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ class Artifact(Base):
|
||||
test_result = Column(String(50), index=True) # pass, fail, skip, error
|
||||
|
||||
# Additional metadata
|
||||
metadata = Column(JSON)
|
||||
custom_metadata = Column(JSON)
|
||||
description = Column(Text)
|
||||
tags = Column(JSON) # Array of tags for categorization
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ class ArtifactCreate(BaseModel):
|
||||
test_suite: Optional[str] = None
|
||||
test_config: Optional[Dict[str, Any]] = None
|
||||
test_result: Optional[str] = None
|
||||
metadata: Optional[Dict[str, Any]] = None
|
||||
custom_metadata: Optional[Dict[str, Any]] = None
|
||||
description: Optional[str] = None
|
||||
tags: Optional[List[str]] = None
|
||||
version: Optional[str] = None
|
||||
@@ -26,7 +26,7 @@ class ArtifactResponse(BaseModel):
|
||||
test_suite: Optional[str] = None
|
||||
test_config: Optional[Dict[str, Any]] = None
|
||||
test_result: Optional[str] = None
|
||||
metadata: Optional[Dict[str, Any]] = None
|
||||
custom_metadata: Optional[Dict[str, Any]] = None
|
||||
description: Optional[str] = None
|
||||
tags: Optional[List[str]] = None
|
||||
created_at: datetime
|
||||
|
||||
Reference in New Issue
Block a user