feat: Implement recursive storage listing and directory browsing for backups, and add a migration option to fix cross-filters.

This commit is contained in:
2026-02-25 20:01:33 +03:00
parent 5d42a6b930
commit f9ac282596
12 changed files with 533 additions and 53 deletions

View File

@@ -851,9 +851,9 @@ def _build_tool_catalog(current_user: User, config_manager: ConfigManager, db: S
{
"operation": "execute_migration",
"domain": "migration",
"description": "Run dashboard migration (id/slug/title) between environments",
"description": "Run dashboard migration (id/slug/title) between environments. Optional boolean flags: replace_db_config, fix_cross_filters",
"required_entities": ["source_env", "target_env"],
"optional_entities": ["dashboard_id", "dashboard_ref"],
"optional_entities": ["dashboard_id", "dashboard_ref", "replace_db_config", "fix_cross_filters"],
"risk_level": "guarded",
"requires_confirmation": False,
},
@@ -1208,20 +1208,30 @@ async def _dispatch_intent(
if operation == "execute_migration":
_check_any_permission(current_user, [("plugin:migration", "EXECUTE"), ("plugin:superset-migration", "EXECUTE")])
src_token = entities.get("source_env")
dashboard_ref = entities.get("dashboard_ref")
dashboard_id = _resolve_dashboard_id_entity(entities, config_manager, env_hint=src_token)
src = _resolve_env_id(src_token, config_manager)
tgt = _resolve_env_id(entities.get("target_env"), config_manager)
if not dashboard_id or not src or not tgt:
raise HTTPException(status_code=422, detail="Missing dashboard_id/dashboard_ref/source_env/target_env")
if not src or not tgt:
raise HTTPException(status_code=422, detail="Missing source_env/target_env")
if not dashboard_id and not dashboard_ref:
raise HTTPException(status_code=422, detail="Missing dashboard_id/dashboard_ref")
migration_params: Dict[str, Any] = {
"source_env_id": src,
"target_env_id": tgt,
"replace_db_config": _coerce_query_bool(entities.get("replace_db_config", False)),
"fix_cross_filters": _coerce_query_bool(entities.get("fix_cross_filters", True)),
}
if dashboard_id:
migration_params["selected_ids"] = [dashboard_id]
else:
# Fallback: pass dashboard_ref as regex for the migration plugin to match
migration_params["dashboard_regex"] = str(dashboard_ref)
task = await task_manager.create_task(
plugin_id="superset-migration",
params={
"selected_ids": [dashboard_id],
"source_env_id": src,
"target_env_id": tgt,
"replace_db_config": False,
},
params=migration_params,
user_id=current_user.id,
)
return (