-
Notifications
You must be signed in to change notification settings - Fork 877
Expand file tree
/
Copy pathc7e91a2b4d60_add_resource_namespacing.py
More file actions
72 lines (60 loc) · 2.8 KB
/
Copy pathc7e91a2b4d60_add_resource_namespacing.py
File metadata and controls
72 lines (60 loc) · 2.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# -*- coding: utf-8 -*-
"""Location: ./mcpgateway/alembic/versions/c7e91a2b4d60_add_resource_namespacing.py
Copyright contributors to the MCP-CONTEXT-FORGE project
SPDX-License-Identifier: Apache-2.0
Add persisted resource namespacing.
Revision ID: c7e91a2b4d60
Revises: 5e211ec89cad
Downgrade restores federated upstream names and discards manual base overrides.
It uses stored values only, independently of the current separator configuration.
"""
# Standard
from typing import Sequence, Union
# Third-Party
from alembic import op
import sqlalchemy as sa
# First-Party
from mcpgateway.config import settings
from mcpgateway.utils.create_slug import slugify
revision: str = "c7e91a2b4d60" # pragma: allowlist secret
down_revision: Union[str, Sequence[str], None] = "5e211ec89cad" # pragma: allowlist secret
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
"""Initialize naming state once and prefix federated resources."""
bind = op.get_bind()
inspector = sa.inspect(bind)
if not inspector.has_table("resources"):
return
columns = {column["name"] for column in inspector.get_columns("resources")}
for name in ("original_name", "custom_name_slug"):
if name not in columns:
op.add_column("resources", sa.Column(name, sa.Text(), nullable=True))
rows = (
bind.execute(sa.text("SELECT r.id, r.name, r.gateway_id, g.name AS gateway_name " "FROM resources r LEFT JOIN gateways g ON r.gateway_id = g.id " "WHERE r.original_name IS NULL"))
.mappings()
.all()
)
for row in rows:
base = slugify(row["name"])
gateway_slug = slugify(row["gateway_name"]) if row["gateway_id"] and row["gateway_name"] else ""
name = row["name"]
if gateway_slug:
name = (f"{gateway_slug}{settings.gateway_tool_name_separator}{base}" if base else gateway_slug)[:255]
bind.execute(
sa.text("UPDATE resources SET original_name = :original, custom_name_slug = :base, name = :name WHERE id = :id"),
{"id": row["id"], "original": row["name"], "base": base, "name": name},
)
def downgrade() -> None:
"""Restore upstream names, leaving local names unchanged, then drop naming state."""
bind = op.get_bind()
inspector = sa.inspect(bind)
if not inspector.has_table("resources"):
return
columns = {column["name"] for column in inspector.get_columns("resources")}
if "original_name" in columns:
bind.execute(sa.text("UPDATE resources SET name = original_name WHERE gateway_id IS NOT NULL AND original_name IS NOT NULL"))
with op.batch_alter_table("resources") as batch:
for name in ("custom_name_slug", "original_name"):
if name in columns:
batch.drop_column(name)