semantics
This commit is contained in:
@@ -1,16 +1,16 @@
|
||||
# #region MigrationPlugin [C:5] [TYPE Module] [SEMANTICS migration, export, import, mapping, superset]
|
||||
# @BRIEF Orchestrates export, DB-mapping transformation, and import of Superset dashboards across environments.
|
||||
# @LAYER: App
|
||||
# @LAYER App
|
||||
# @RELATION IMPLEMENTS -> PluginBase
|
||||
# @RELATION DEPENDS_ON -> SupersetClient
|
||||
# @RELATION DEPENDS_ON -> MigrationEngine
|
||||
# @RELATION DEPENDS_ON -> IdMappingService
|
||||
# @RELATION USES -> TaskContext
|
||||
# @PRE: Plugin loader can resolve infrastructure dependencies and execution requests provide validated migration context.
|
||||
# @POST: Plugin metadata remains stable and migration execution preserves mapped-environment import guarantees.
|
||||
# @SIDE_EFFECT: Reads config, opens database sessions, creates temporary artifacts, and triggers Superset export/import workflows.
|
||||
# @DATA_CONTRACT: Input[TaskContext{from_env,to_env,dashboard_regex,replace_db_config,from_db_id,to_db_id,passwords?}] -> Output[MigrationResult|artifact set]
|
||||
# @INVARIANT: Dashboards must never be imported with unmapped/source DB connections to prevent data leaks or cross-environment pollution.
|
||||
# @RELATION DEPENDS_ON -> [TaskContext]
|
||||
# @PRE Plugin loader can resolve infrastructure dependencies and execution requests provide validated migration context.
|
||||
# @POST Plugin metadata remains stable and migration execution preserves mapped-environment import guarantees.
|
||||
# @SIDE_EFFECT Reads config, opens database sessions, creates temporary artifacts, and triggers Superset export/import workflows.
|
||||
# @DATA_CONTRACT Input[TaskContext{from_env,to_env,dashboard_regex,replace_db_config,from_db_id,to_db_id,passwords?}] -> Output[MigrationResult|artifact set]
|
||||
# @INVARIANT Dashboards must never be imported with unmapped/source DB connections to prevent data leaks or cross-environment pollution.
|
||||
|
||||
import re
|
||||
from typing import Any
|
||||
@@ -29,14 +29,14 @@ from ..models.mapping import DatabaseMapping, Environment
|
||||
|
||||
# #region MigrationPlugin [TYPE Class]
|
||||
# @BRIEF Implementation of the migration plugin workflow and transformation orchestration.
|
||||
# @PRE: SupersetClient authenticated, database session active
|
||||
# @POST: Returns MigrationResult with success/failure status and artifact list
|
||||
# @TEST_FIXTURE: superset_export_zip -> file:backend/tests/fixtures/migration/dashboard_export.zip
|
||||
# @TEST_FIXTURE: db_mapping_payload -> INLINE_JSON: {"db_mappings": {"source_uuid_1": "target_uuid_2"}}
|
||||
# @TEST_FIXTURE: password_inject_payload -> INLINE_JSON: {"passwords": {"PostgreSQL": "secret123"}}
|
||||
# @TEST_INVARIANT: strict_db_isolation -> VERIFIED_BY: [successful_dashboard_transfer, missing_mapping_resolution]
|
||||
# @SIDE_EFFECT: Writes migration artifacts to database, triggers dashboard imports
|
||||
# @DATA_CONTRACT: MigrationPlan AST, DryRunResult, RiskAssessment
|
||||
# @PRE SupersetClient authenticated, database session active
|
||||
# @POST Returns MigrationResult with success/failure status and artifact list
|
||||
# @TEST_FIXTURE superset_export_zip -> file:backend/tests/fixtures/migration/dashboard_export.zip
|
||||
# @TEST_FIXTURE db_mapping_payload -> INLINE_JSON: {"db_mappings": {"source_uuid_1": "target_uuid_2"}}
|
||||
# @TEST_FIXTURE password_inject_payload -> INLINE_JSON: {"passwords": {"PostgreSQL": "secret123"}}
|
||||
# @TEST_INVARIANT strict_db_isolation -> VERIFIED_BY: [successful_dashboard_transfer, missing_mapping_resolution]
|
||||
# @SIDE_EFFECT Writes migration artifacts to database, triggers dashboard imports
|
||||
# @DATA_CONTRACT MigrationPlan AST, DryRunResult, RiskAssessment
|
||||
class MigrationPlugin(PluginBase):
|
||||
"""
|
||||
A plugin to migrate Superset dashboards between environments.
|
||||
@@ -45,9 +45,9 @@ class MigrationPlugin(PluginBase):
|
||||
@property
|
||||
# region id [TYPE Function]
|
||||
# @PURPOSE: Returns the unique identifier for the migration plugin.
|
||||
# @PRE: None.
|
||||
# @POST: Returns stable string "superset-migration".
|
||||
# @RETURN: str
|
||||
# @PRE None.
|
||||
# @POST Returns stable string "superset-migration".
|
||||
# @RETURN str
|
||||
def id(self) -> str:
|
||||
with belief_scope("MigrationPlugin.id"):
|
||||
return "superset-migration"
|
||||
@@ -56,9 +56,9 @@ class MigrationPlugin(PluginBase):
|
||||
@property
|
||||
# region name [TYPE Function]
|
||||
# @PURPOSE: Returns the human-readable name of the plugin.
|
||||
# @PRE: None.
|
||||
# @POST: Returns "Superset Dashboard Migration".
|
||||
# @RETURN: str
|
||||
# @PRE None.
|
||||
# @POST Returns "Superset Dashboard Migration".
|
||||
# @RETURN str
|
||||
def name(self) -> str:
|
||||
with belief_scope("MigrationPlugin.name"):
|
||||
return "Superset Dashboard Migration"
|
||||
@@ -67,9 +67,9 @@ class MigrationPlugin(PluginBase):
|
||||
@property
|
||||
# region description [TYPE Function]
|
||||
# @PURPOSE: Returns the semantic description of the plugin.
|
||||
# @PRE: None.
|
||||
# @POST: Returns description string.
|
||||
# @RETURN: str
|
||||
# @PRE None.
|
||||
# @POST Returns description string.
|
||||
# @RETURN str
|
||||
def description(self) -> str:
|
||||
with belief_scope("MigrationPlugin.description"):
|
||||
return "Migrates dashboards between Superset environments."
|
||||
@@ -78,9 +78,9 @@ class MigrationPlugin(PluginBase):
|
||||
@property
|
||||
# region version [TYPE Function]
|
||||
# @PURPOSE: Returns the semantic version of the migration plugin.
|
||||
# @PRE: None.
|
||||
# @POST: Returns "1.0.0".
|
||||
# @RETURN: str
|
||||
# @PRE None.
|
||||
# @POST Returns "1.0.0".
|
||||
# @RETURN str
|
||||
def version(self) -> str:
|
||||
with belief_scope("MigrationPlugin.version"):
|
||||
return "1.0.0"
|
||||
@@ -89,9 +89,9 @@ class MigrationPlugin(PluginBase):
|
||||
@property
|
||||
# region ui_route [TYPE Function]
|
||||
# @PURPOSE: Returns the frontend routing anchor for the plugin.
|
||||
# @PRE: None.
|
||||
# @POST: Returns "/migration".
|
||||
# @RETURN: str
|
||||
# @PRE None.
|
||||
# @POST Returns "/migration".
|
||||
# @RETURN str
|
||||
def ui_route(self) -> str:
|
||||
with belief_scope("MigrationPlugin.ui_route"):
|
||||
return "/migration"
|
||||
@@ -99,9 +99,9 @@ class MigrationPlugin(PluginBase):
|
||||
|
||||
# region get_schema [TYPE Function]
|
||||
# @PURPOSE: Generates the JSON Schema for the plugin execution form dynamically.
|
||||
# @PRE: ConfigManager is accessible and environments are defined.
|
||||
# @POST: Returns a JSON Schema dict matching current system environments.
|
||||
# @RETURN: Dict[str, Any]
|
||||
# @PRE ConfigManager is accessible and environments are defined.
|
||||
# @POST Returns a JSON Schema dict matching current system environments.
|
||||
# @RETURN Dict[str, Any]
|
||||
def get_schema(self) -> dict[str, Any]:
|
||||
with belief_scope("MigrationPlugin.get_schema"):
|
||||
app_logger.reason("Generating migration UI schema")
|
||||
@@ -153,18 +153,18 @@ class MigrationPlugin(PluginBase):
|
||||
|
||||
# region execute [TYPE Function]
|
||||
# @PURPOSE: Orchestrates the dashboard migration pipeline including extraction, AST mutation, and ingestion.
|
||||
# @PARAM: params (Dict[str, Any]) - Extracted parameters from UI/API execution request.
|
||||
# @PARAM: context (Optional[TaskContext]) - Dependency injected TaskContext for IO tracing.
|
||||
# @PRE: Source and target environments must resolve. Matching dashboards must exist.
|
||||
# @POST: Dashboard ZIP bundles are transformed and imported. ID mappings are synchronized.
|
||||
# @SIDE_EFFECT: Creates temp files, mutates target Superset state, blocks on user input (passwords/mappings).
|
||||
# @TEST_CONTRACT: Dict[str, Any] -> Dict[str, Any]
|
||||
# @TEST_SCENARIO: successful_dashboard_transfer -> ZIP is downloaded, DB mappings applied via AST, target import succeeds.
|
||||
# @TEST_SCENARIO: missing_password_injection -> Target import fails on auth, TaskManager pauses for user input, retries with password successfully.
|
||||
# @TEST_SCENARIO: empty_selection -> Returns NO_MATCHES gracefully when regex finds zero dashboards.
|
||||
# @TEST_EDGE: missing_env_field -> [ValueError: Could not resolve source or target environment]
|
||||
# @TEST_EDGE: invalid_regex_pattern -> [Regex compilation exception is thrown or caught gracefully]
|
||||
# @TEST_EDGE: target_api_timeout -> [Dashboard added to failed_dashboards, task concludes with PARTIAL_SUCCESS]
|
||||
# @PARAM params (Dict[str, Any]) - Extracted parameters from UI/API execution request.
|
||||
# @PARAM context (Optional[TaskContext]) - Dependency injected TaskContext for IO tracing.
|
||||
# @PRE Source and target environments must resolve. Matching dashboards must exist.
|
||||
# @POST Dashboard ZIP bundles are transformed and imported. ID mappings are synchronized.
|
||||
# @SIDE_EFFECT Creates temp files, mutates target Superset state, blocks on user input (passwords/mappings).
|
||||
# @TEST_CONTRACT Dict[str, Any] -> Dict[str, Any]
|
||||
# @TEST_SCENARIO successful_dashboard_transfer -> ZIP is downloaded, DB mappings applied via AST, target import succeeds.
|
||||
# @TEST_SCENARIO missing_password_injection -> Target import fails on auth, TaskManager pauses for user input, retries with password successfully.
|
||||
# @TEST_SCENARIO empty_selection -> Returns NO_MATCHES gracefully when regex finds zero dashboards.
|
||||
# @TEST_EDGE missing_env_field -> [ValueError: Could not resolve source or target environment]
|
||||
# @TEST_EDGE invalid_regex_pattern -> [Regex compilation exception is thrown or caught gracefully]
|
||||
# @TEST_EDGE target_api_timeout -> [Dashboard added to failed_dashboards, task concludes with PARTIAL_SUCCESS]
|
||||
async def execute(self, params: dict[str, Any], context: TaskContext | None = None):
|
||||
with belief_scope("MigrationPlugin.execute"):
|
||||
app_logger.reason("Evaluating migration task parameters", extra={"params": params})
|
||||
|
||||
Reference in New Issue
Block a user