feat(appliance): initial release of MERICA standalone appliance v1.0.0
This commit is contained in:
@@ -0,0 +1,105 @@
|
||||
"""
|
||||
Governance API Router for MERICA Studio & OpenMetadata 2.0
|
||||
Provides REST endpoints to query and manage:
|
||||
- Domains (Data Mesh aggregates)
|
||||
- Owners (Group-based accountability)
|
||||
- Tiers (Criticality levels: Tier 1 to 5)
|
||||
- Certifications (Bronze, Silver, Gold)
|
||||
- Retention Policies (Data Lifecycle presets)
|
||||
"""
|
||||
from typing import Optional, List, Dict, Any
|
||||
from pydantic import BaseModel, Field
|
||||
from fastapi import APIRouter, HTTPException, status
|
||||
|
||||
from app.services.openmetadata_service import (
|
||||
list_openmetadata_domains,
|
||||
list_openmetadata_owners,
|
||||
get_governance_tiers,
|
||||
get_retention_options,
|
||||
apply_table_governance,
|
||||
apply_entity_governance
|
||||
)
|
||||
|
||||
router = APIRouter(prefix="/governance", tags=["Data Governance & OpenMetadata"])
|
||||
|
||||
|
||||
class ApplyGovernanceRequest(BaseModel):
|
||||
table_fqn: Optional[str] = Field(None, description="Fully qualified name of table (e.g. dlh_postgres_service.dlh_lakehouse.bronze_lakehouse.environmental_permits_cdc)")
|
||||
pipeline_fqn: Optional[str] = Field(None, description="Fully qualified name of pipeline (e.g. dlh_airflow_service.example_permits_medallion_dbt_postgres)")
|
||||
entity_type: str = Field("table", description="Target entity type: 'table' or 'pipeline'")
|
||||
domain_id: Optional[str] = Field(None, description="UUID of the OpenMetadata Domain")
|
||||
owner_id: Optional[str] = Field(None, description="UUID of the Owner Group Team")
|
||||
tier: Optional[str] = Field(None, description="Tier tag (e.g. Tier.Tier1, Tier.Tier2, Tier.Tier3)")
|
||||
certification: Optional[str] = Field(None, description="Certification tag (e.g. Certification.Bronze, Certification.Silver, Certification.Gold)")
|
||||
retention_period: Optional[str] = Field(None, description="ISO-8601 duration (e.g. P30D, P90D, P3Y, P5Y) - applicable to tables")
|
||||
usage_count: Optional[int] = Field(None, description="Optional hit count to register in OpenMetadata usage analytics")
|
||||
|
||||
|
||||
@router.get("/summary", summary="Get complete governance options summary")
|
||||
def get_governance_summary():
|
||||
"""Retrieve all available governance metadata options in a single call."""
|
||||
return {
|
||||
"domains": list_openmetadata_domains(),
|
||||
"owners": list_openmetadata_owners(),
|
||||
"tiers": get_governance_tiers(),
|
||||
"retention_options": get_retention_options(),
|
||||
"certifications": [
|
||||
{"tag": "Certification.Bronze", "name": "Bronze Verified", "description": "Raw ingested data passing structural syntax & type tests."},
|
||||
{"tag": "Certification.Silver", "name": "Silver Certified", "description": "Curated & cleansed warehouse data passing GE quality assertions."},
|
||||
{"tag": "Certification.Gold", "name": "Gold Certified", "description": "Mission-critical analytical data product ready for executive reporting."}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@router.get("/domains", summary="List OpenMetadata business domains")
|
||||
def get_domains():
|
||||
"""List business domains configured in OpenMetadata (Data Mesh Bounded Contexts)."""
|
||||
return list_openmetadata_domains()
|
||||
|
||||
|
||||
@router.get("/owners", summary="List eligible asset owner groups")
|
||||
def get_owners():
|
||||
"""List teams/groups eligible to own data assets (teamType='Group')."""
|
||||
return list_openmetadata_owners()
|
||||
|
||||
|
||||
@router.get("/tiers", summary="List standard Lakehouse data tiers")
|
||||
def get_tiers():
|
||||
"""List standard criticality tiers (Tier 1 to Tier 5)."""
|
||||
return get_governance_tiers()
|
||||
|
||||
|
||||
@router.get("/retention-options", summary="List standard retention period presets")
|
||||
def get_retention_presets():
|
||||
"""List standard ISO-8601 data retention policy presets."""
|
||||
return get_retention_options()
|
||||
|
||||
|
||||
@router.post("/apply", summary="Apply governance attributes to a Lakehouse table or pipeline")
|
||||
def apply_governance(req: ApplyGovernanceRequest):
|
||||
"""Apply domains, owners, tier, certification, and retention/usage to a table or pipeline entity."""
|
||||
target_fqn = req.pipeline_fqn if (req.entity_type == "pipeline" or req.pipeline_fqn) else req.table_fqn
|
||||
entity_type = "pipeline" if (req.pipeline_fqn or req.entity_type == "pipeline") else "table"
|
||||
|
||||
if not target_fqn:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail="Either table_fqn or pipeline_fqn must be provided."
|
||||
)
|
||||
|
||||
res = apply_entity_governance(
|
||||
entity_fqn=target_fqn,
|
||||
entity_type=entity_type,
|
||||
domain_id=req.domain_id,
|
||||
owner_id=req.owner_id,
|
||||
tier=req.tier,
|
||||
certification=req.certification,
|
||||
retention_period=req.retention_period,
|
||||
usage_count=req.usage_count
|
||||
)
|
||||
if res.get("status") == "error":
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
detail=res.get("message", "Failed to apply governance attributes.")
|
||||
)
|
||||
return res
|
||||
Reference in New Issue
Block a user