diff --git a/docs/source/conf.py b/docs/source/conf.py index 3f4d36bd86b823b9fe642011cd62c8efa55ee16a..74502fb22f8ea416e23b894aae62d6e1d7727368 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -1,28 +1,27 @@ # -- Project information ----------------------------------------------------- -project = 'GÉANT Service Orchestrator' -copyright = '2023, GÉANT Vereniging' -author = 'GÉANT Orchestration and Automation Team' +project = "GÉANT Service Orchestrator" +copyright = "2023, GÉANT Vereniging" +author = "GÉANT Orchestration and Automation Team" # -- General configuration --------------------------------------------------- -extensions = ['sphinx_rtd_theme', 'sphinx.ext.autodoc', 'sphinxcontrib.jquery'] +extensions = ["sphinx_rtd_theme", "sphinx.ext.autodoc", "sphinxcontrib.jquery"] -templates_path = ['templates'] -exclude_patterns = ['build', 'Thumbs.db', '.DS_Store', 'venv', 'vale', '__init__.py'] +templates_path = ["templates"] +exclude_patterns = ["build", "Thumbs.db", ".DS_Store", "venv", "vale", "__init__.py"] # -- Options for HTML output ------------------------------------------------- -html_theme = 'sphinx_rtd_theme' -html_static_path = ['static'] +html_theme = "sphinx_rtd_theme" +html_static_path = ["static"] html_theme_options = { - 'style_nav_header_background': 'rgb(0 63 95)', + "style_nav_header_background": "rgb(0 63 95)", } -html_css_files = ['custom.css'] -html_js_files = ['custom.js'] -html_logo = 'static/geant_logo_white.svg' +html_css_files = ["custom.css"] +html_js_files = ["custom.js"] +html_logo = "static/geant_logo_white.svg" # Both the class' and the ``__init__`` method's docstring are concatenated and inserted. -autoclass_content = 'both' -autodoc_typehints = 'none' +autoclass_content = "both" +autodoc_typehints = "none" # Display todos by setting to True todo_include_todos = True - diff --git a/gso/__init__.py b/gso/__init__.py index 7239754917e0f67f003219004a04a2b7ca86101b..abb76a7cd09d52fe0d266e04a9f5ab9b1d550c3d 100644 --- a/gso/__init__.py +++ b/gso/__init__.py @@ -2,7 +2,7 @@ import typer from orchestrator import OrchestratorCore, app_settings from orchestrator.cli.main import app as cli_app -import gso.products # noqa: F401 +import gso.products import gso.workflows # noqa: F401 from gso.api import router as api_router from gso.cli import netbox diff --git a/gso/api/v1/imports.py b/gso/api/v1/imports.py index c99db7736804aaeea9a1fe36d65ef9c3ed472d91..7088e5a662b93ebe035656e3f4f8f095e0104066 100644 --- a/gso/api/v1/imports.py +++ b/gso/api/v1/imports.py @@ -116,22 +116,25 @@ class IptrunkImportModel(BaseModel): def check_if_customer_exists(cls, value: str) -> str: try: get_customer_by_name(value) - except CustomerNotFoundError: - raise ValueError(f"Customer {value} not found") + except CustomerNotFoundError as e: + msg = f"Customer {value} not found" + raise ValueError(msg) from e return value @validator("side_a_node_id", "side_b_node_id") def check_if_router_side_is_available(cls, value: str) -> str: if value not in cls._get_active_routers(): - raise ValueError(f"Router {value} not found") + msg = f"Router {value} not found" + raise ValueError(msg) return value @validator("side_a_ae_members", "side_b_ae_members") def check_side_uniqueness(cls, value: list[str]) -> list[str]: if len(value) != len(set(value)): - raise ValueError("Items must be unique") + msg = "Items must be unique" + raise ValueError(msg) return value @@ -145,20 +148,24 @@ class IptrunkImportModel(BaseModel): len_b = len(side_b_members) if len_a < min_links: - raise ValueError(f"Side A members should be at least {min_links} (iptrunk_minimum_links)") + msg = f"Side A members should be at least {min_links} (iptrunk_minimum_links)" + raise ValueError(msg) if len_a != len_b: - raise ValueError("Mismatch between Side A and B members") + msg = "Mismatch between Side A and B members" + raise ValueError(msg) return values def _start_process(process_name: str, data: dict) -> UUID: """Start a process and handle common exceptions.""" - pid: UUID = processes.start_process(process_name, [data]) if pid is None: - raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="Failed to start the process.") + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail="Failed to start the process.", + ) process = processes._get_process(pid) if process.last_status == "failed": @@ -198,7 +205,6 @@ def import_router(router_data: RouterImportModel) -> dict[str, Any]: :raises HTTPException: If there's an error in the process. """ - pid = _start_process("import_router", router_data.dict()) return {"detail": "Router added successfully", "pid": pid} @@ -215,6 +221,5 @@ def import_iptrunk(iptrunk_data: IptrunkImportModel) -> dict[str, Any]: :raises HTTPException: If there's an error in the process. """ - pid = _start_process("import_iptrunk", iptrunk_data.dict()) return {"detail": "Iptrunk added successfully", "pid": pid} diff --git a/gso/api/v1/subscriptions.py b/gso/api/v1/subscriptions.py index 65eae878f18cec1c9aa5e45693fc60f029b06d68..cd0731f2f1694b638ad03130d622efb9323f021a 100644 --- a/gso/api/v1/subscriptions.py +++ b/gso/api/v1/subscriptions.py @@ -9,10 +9,18 @@ from orchestrator.services.subscriptions import build_extended_domain_model from gso.services.subscriptions import get_active_router_subscriptions -router = APIRouter(prefix="/subscriptions", tags=["Subscriptions"], dependencies=[Depends(opa_security_default)]) +router = APIRouter( + prefix="/subscriptions", + tags=["Subscriptions"], + dependencies=[Depends(opa_security_default)], +) -@router.get("/routers", status_code=status.HTTP_200_OK, response_model=list[SubscriptionDomainModelSchema]) +@router.get( + "/routers", + status_code=status.HTTP_200_OK, + response_model=list[SubscriptionDomainModelSchema], +) def subscription_routers() -> list[dict[str, Any]]: """Retrieve all active routers subscriptions.""" subscriptions = [] diff --git a/gso/migrations/env.py b/gso/migrations/env.py index 4d84cfb15787fc357dd96857fb97b4cee13b80a8..ba4d2a664eaa3dd6e6a3d49ed125faa63078c7d3 100644 --- a/gso/migrations/env.py +++ b/gso/migrations/env.py @@ -32,7 +32,10 @@ def run_migrations_offline() -> None: """ url = config.get_main_option("sqlalchemy.url") context.configure( - url=url, target_metadata=target_metadata, literal_binds=True, dialect_opts={"paramstyle": "named"} + url=url, + target_metadata=target_metadata, + literal_binds=True, + dialect_opts={"paramstyle": "named"}, ) with context.begin_transaction(): diff --git a/gso/migrations/versions/2023-08-14_3657611f0dfc_add_router_workflows.py b/gso/migrations/versions/2023-08-14_3657611f0dfc_add_router_workflows.py index 153d5433579308b23e2d06b394b5d9f4a620158e..86157af6ab6bc3128af28f6af26b62aea70ab324 100644 --- a/gso/migrations/versions/2023-08-14_3657611f0dfc_add_router_workflows.py +++ b/gso/migrations/versions/2023-08-14_3657611f0dfc_add_router_workflows.py @@ -9,8 +9,8 @@ import sqlalchemy as sa from alembic import op # revision identifiers, used by Alembic. -revision = '3657611f0dfc' -down_revision = '91047dd30b40' +revision = "3657611f0dfc" +down_revision = "91047dd30b40" branch_labels = None depends_on = None @@ -22,14 +22,14 @@ new_workflows = [ "name": "create_router", "target": "CREATE", "description": "Create router", - "product_type": "Router" + "product_type": "Router", }, { "name": "terminate_router", "target": "TERMINATE", "description": "Terminate router", - "product_type": "Router" - } + "product_type": "Router", + }, ] diff --git a/gso/migrations/versions/2023-08-14_91047dd30b40_add_site_workflows.py b/gso/migrations/versions/2023-08-14_91047dd30b40_add_site_workflows.py index f39467eadecc248717f851bea8b221cd5b5d378e..7c69717cf235d2d7533bee9268ac9a30f6cf969e 100644 --- a/gso/migrations/versions/2023-08-14_91047dd30b40_add_site_workflows.py +++ b/gso/migrations/versions/2023-08-14_91047dd30b40_add_site_workflows.py @@ -9,8 +9,8 @@ import sqlalchemy as sa from alembic import op # revision identifiers, used by Alembic. -revision = '91047dd30b40' -down_revision = '97436160a422' +revision = "91047dd30b40" +down_revision = "97436160a422" branch_labels = None depends_on = None @@ -22,7 +22,7 @@ new_workflows = [ "name": "create_site", "target": "CREATE", "description": "Create Site", - "product_type": "Site" + "product_type": "Site", } ] diff --git a/gso/migrations/versions/2023-08-14_97436160a422_add_initial_products.py b/gso/migrations/versions/2023-08-14_97436160a422_add_initial_products.py index e3bdc2fa74f3688b590af92a3cf4d4144f1d526d..7243674ab9e44bada15348e6d072a354eeb6f230 100644 --- a/gso/migrations/versions/2023-08-14_97436160a422_add_initial_products.py +++ b/gso/migrations/versions/2023-08-14_97436160a422_add_initial_products.py @@ -9,546 +9,1254 @@ import sqlalchemy as sa from alembic import op # revision identifiers, used by Alembic. -revision = '97436160a422' +revision = "97436160a422" down_revision = None -branch_labels = ('data',) -depends_on = 'a09ac125ea73' +branch_labels = ("data",) +depends_on = "a09ac125ea73" def upgrade() -> None: conn = op.get_bind() - conn.execute(sa.text(""" + conn.execute( + sa.text( + """ INSERT INTO products (name, description, product_type, tag, status) VALUES ('Site', 'A GÉANT Site', 'Site', 'SITE', 'active') RETURNING products.product_id - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO products (name, description, product_type, tag, status) VALUES ('Router', 'A GÉANT Router', 'Router', 'ROUTER', 'active') RETURNING products.product_id - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO products (name, description, product_type, tag, status) VALUES ('IP trunk', 'A GÉANT IP Trunk', 'Iptrunk', 'IPTRUNK', 'active') RETURNING products.product_id - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO product_blocks (name, description, tag, status) VALUES ('SiteBlock', 'Site PB', 'SITEPB', 'active') RETURNING product_blocks.product_block_id - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO product_blocks (name, description, tag, status) VALUES ('RouterBlock', 'Router PB', 'ROUTERPB', 'active') RETURNING product_blocks.product_block_id - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO product_blocks (name, description, tag, status) VALUES ('IptrunkBlock', 'IP Trunk PB', 'IPTRUNKPB', 'active') RETURNING product_blocks.product_block_id - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO resource_types (resource_type, description) VALUES ('site_name', 'Name of a Site') RETURNING resource_types.resource_type_id - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO resource_types (resource_type, description) VALUES ('iptrunk_minimum_links', 'Minimum amount of members in a LAG') RETURNING resource_types.resource_type_id - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO resource_types (resource_type, description) VALUES ('iptrunk_description', 'Description of an IP Trunk') RETURNING resource_types.resource_type_id - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO resource_types (resource_type, description) VALUES ('router_ias_lt_ipv4_network', 'IPv4 network for a logical tunnel between master routing table and IAS') RETURNING resource_types.resource_type_id - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO resource_types (resource_type, description) VALUES ('geant_s_sid', 'GÉANT Service ID') RETURNING resource_types.resource_type_id - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO resource_types (resource_type, description) VALUES ('iptrunk_isis_metric', 'ISIS metric') RETURNING resource_types.resource_type_id - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO resource_types (resource_type, description) VALUES ('iptrunk_sideA_ae_geant_a_sid', 'GÉANT Service ID for access port') RETURNING resource_types.resource_type_id - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO resource_types (resource_type, description) VALUES ('iptrunk_sideB_ae_geant_a_sid', 'GÉANT Service ID for access port') RETURNING resource_types.resource_type_id - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO resource_types (resource_type, description) VALUES ('router_lo_ipv6_address', 'IPv6 address of loopback interface') RETURNING resource_types.resource_type_id - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO resource_types (resource_type, description) VALUES ('iptrunk_sideB_ae_members', 'LAG members on side B') RETURNING resource_types.resource_type_id - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO resource_types (resource_type, description) VALUES ('router_lo_ipv4_address', 'IPv4 address of loopback interface') RETURNING resource_types.resource_type_id - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO resource_types (resource_type, description) VALUES ('site_city', 'City of a Site') RETURNING resource_types.resource_type_id - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO resource_types (resource_type, description) VALUES ('site_tier', 'Tier of a Site') RETURNING resource_types.resource_type_id - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO resource_types (resource_type, description) VALUES ('router_role', 'Role of a Router') RETURNING resource_types.resource_type_id - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO resource_types (resource_type, description) VALUES ('iptrunk_type', 'Type of an IP Trunk') RETURNING resource_types.resource_type_id - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO resource_types (resource_type, description) VALUES ('site_bgp_community_id', 'BGP Community ID') RETURNING resource_types.resource_type_id - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO resource_types (resource_type, description) VALUES ('iptrunk_sideA_ae_iface', 'LAG interface') RETURNING resource_types.resource_type_id - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO resource_types (resource_type, description) VALUES ('iptrunk_ipv4_network', 'IPv4 network of an IP Trunk') RETURNING resource_types.resource_type_id - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO resource_types (resource_type, description) VALUES ('iptrunk_sideB_ae_members_description', 'Descriptions of LAG members') RETURNING resource_types.resource_type_id - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO resource_types (resource_type, description) VALUES ('iptrunk_speed', 'Speed of LAG members') RETURNING resource_types.resource_type_id - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO resource_types (resource_type, description) VALUES ('site_country_code', 'Country code of a Site') RETURNING resource_types.resource_type_id - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO resource_types (resource_type, description) VALUES ('router_access_via_ts', 'Whether a router should get accessed through terminal server') RETURNING resource_types.resource_type_id - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO resource_types (resource_type, description) VALUES ('site_internal_id', 'Third octet of a Site''s private network') RETURNING resource_types.resource_type_id - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO resource_types (resource_type, description) VALUES ('router_si_ipv4_network', 'IPv4 network for SI interface') RETURNING resource_types.resource_type_id - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO resource_types (resource_type, description) VALUES ('router_ias_lt_ipv6_network', 'IPv6 network for a logical tunnel between master routing table and IAS') RETURNING resource_types.resource_type_id - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO resource_types (resource_type, description) VALUES ('site_latitude', 'Latitude of a Site') RETURNING resource_types.resource_type_id - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO resource_types (resource_type, description) VALUES ('site_country', 'Country of a Site') RETURNING resource_types.resource_type_id - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO resource_types (resource_type, description) VALUES ('site_ts_address', 'Terminal Server address') RETURNING resource_types.resource_type_id - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO resource_types (resource_type, description) VALUES ('iptrunk_sideB_ae_iface', 'LAG interface') RETURNING resource_types.resource_type_id - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO resource_types (resource_type, description) VALUES ('router_is_ias_connected', 'Whether a Logical Tunnel between master routing table and IAS is needed') RETURNING resource_types.resource_type_id - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO resource_types (resource_type, description) VALUES ('iptrunk_ipv6_network', 'IPv6 network of an IP Trunk') RETURNING resource_types.resource_type_id - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO resource_types (resource_type, description) VALUES ('site_longitude', 'Longitude of a Site') RETURNING resource_types.resource_type_id - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO resource_types (resource_type, description) VALUES ('router_lo_iso_address', 'ISO address of a loopback interface') RETURNING resource_types.resource_type_id - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO resource_types (resource_type, description) VALUES ('iptrunk_sideA_ae_members', 'LAG members on side A') RETURNING resource_types.resource_type_id - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO resource_types (resource_type, description) VALUES ('router_fqdn', 'FQDN of a Router') RETURNING resource_types.resource_type_id - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO resource_types (resource_type, description) VALUES ('iptrunk_sideA_ae_members_description', 'Descriptions of LAG members') RETURNING resource_types.resource_type_id - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO resource_types (resource_type, description) VALUES ('router_ts_port', 'Port number of the Terminal Server') RETURNING resource_types.resource_type_id - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO resource_types (resource_type, description) VALUES ('router_vendor', 'Vendor of a Router') RETURNING resource_types.resource_type_id - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO product_product_blocks (product_id, product_block_id) VALUES ((SELECT products.product_id FROM products WHERE products.name IN ('Site')), (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('SiteBlock'))) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO product_product_blocks (product_id, product_block_id) VALUES ((SELECT products.product_id FROM products WHERE products.name IN ('Router')), (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('RouterBlock'))) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO product_product_blocks (product_id, product_block_id) VALUES ((SELECT products.product_id FROM products WHERE products.name IN ('IP trunk')), (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock'))) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO product_block_relations (in_use_by_id, depends_on_id) VALUES ((SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('RouterBlock')), (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('SiteBlock'))) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO product_block_relations (in_use_by_id, depends_on_id) VALUES ((SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock')), (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('RouterBlock'))) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO product_block_resource_types (product_block_id, resource_type_id) VALUES ((SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('SiteBlock')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('site_name'))) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO product_block_resource_types (product_block_id, resource_type_id) VALUES ((SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('SiteBlock')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('site_city'))) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO product_block_resource_types (product_block_id, resource_type_id) VALUES ((SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('SiteBlock')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('site_country'))) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO product_block_resource_types (product_block_id, resource_type_id) VALUES ((SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('SiteBlock')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('site_country_code'))) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO product_block_resource_types (product_block_id, resource_type_id) VALUES ((SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('SiteBlock')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('site_latitude'))) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO product_block_resource_types (product_block_id, resource_type_id) VALUES ((SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('SiteBlock')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('site_longitude'))) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO product_block_resource_types (product_block_id, resource_type_id) VALUES ((SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('SiteBlock')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('site_internal_id'))) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO product_block_resource_types (product_block_id, resource_type_id) VALUES ((SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('SiteBlock')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('site_bgp_community_id'))) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO product_block_resource_types (product_block_id, resource_type_id) VALUES ((SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('SiteBlock')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('site_tier'))) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO product_block_resource_types (product_block_id, resource_type_id) VALUES ((SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('SiteBlock')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('site_ts_address'))) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO product_block_resource_types (product_block_id, resource_type_id) VALUES ((SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('RouterBlock')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('router_fqdn'))) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO product_block_resource_types (product_block_id, resource_type_id) VALUES ((SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('RouterBlock')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('router_ts_port'))) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO product_block_resource_types (product_block_id, resource_type_id) VALUES ((SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('RouterBlock')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('router_access_via_ts'))) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO product_block_resource_types (product_block_id, resource_type_id) VALUES ((SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('RouterBlock')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('router_lo_ipv4_address'))) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO product_block_resource_types (product_block_id, resource_type_id) VALUES ((SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('RouterBlock')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('router_lo_ipv6_address'))) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO product_block_resource_types (product_block_id, resource_type_id) VALUES ((SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('RouterBlock')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('router_lo_iso_address'))) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO product_block_resource_types (product_block_id, resource_type_id) VALUES ((SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('RouterBlock')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('router_si_ipv4_network'))) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO product_block_resource_types (product_block_id, resource_type_id) VALUES ((SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('RouterBlock')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('router_ias_lt_ipv4_network'))) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO product_block_resource_types (product_block_id, resource_type_id) VALUES ((SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('RouterBlock')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('router_ias_lt_ipv6_network'))) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO product_block_resource_types (product_block_id, resource_type_id) VALUES ((SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('RouterBlock')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('router_vendor'))) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO product_block_resource_types (product_block_id, resource_type_id) VALUES ((SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('RouterBlock')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('router_role'))) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO product_block_resource_types (product_block_id, resource_type_id) VALUES ((SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('RouterBlock')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('router_is_ias_connected'))) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO product_block_resource_types (product_block_id, resource_type_id) VALUES ((SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('geant_s_sid'))) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO product_block_resource_types (product_block_id, resource_type_id) VALUES ((SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_description'))) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO product_block_resource_types (product_block_id, resource_type_id) VALUES ((SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_type'))) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO product_block_resource_types (product_block_id, resource_type_id) VALUES ((SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_speed'))) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO product_block_resource_types (product_block_id, resource_type_id) VALUES ((SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_minimum_links'))) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO product_block_resource_types (product_block_id, resource_type_id) VALUES ((SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_isis_metric'))) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO product_block_resource_types (product_block_id, resource_type_id) VALUES ((SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_ipv4_network'))) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO product_block_resource_types (product_block_id, resource_type_id) VALUES ((SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_ipv6_network'))) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO product_block_resource_types (product_block_id, resource_type_id) VALUES ((SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_sideA_ae_iface'))) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO product_block_resource_types (product_block_id, resource_type_id) VALUES ((SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_sideA_ae_geant_a_sid'))) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO product_block_resource_types (product_block_id, resource_type_id) VALUES ((SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_sideA_ae_members'))) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO product_block_resource_types (product_block_id, resource_type_id) VALUES ((SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_sideA_ae_members_description'))) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO product_block_resource_types (product_block_id, resource_type_id) VALUES ((SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_sideB_ae_iface'))) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO product_block_resource_types (product_block_id, resource_type_id) VALUES ((SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_sideB_ae_geant_a_sid'))) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO product_block_resource_types (product_block_id, resource_type_id) VALUES ((SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_sideB_ae_members'))) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO product_block_resource_types (product_block_id, resource_type_id) VALUES ((SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_sideB_ae_members_description'))) - """)) + """ + ) + ) def downgrade() -> None: conn = op.get_bind() - conn.execute(sa.text(""" + conn.execute( + sa.text( + """ DELETE FROM product_block_resource_types WHERE product_block_resource_types.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('SiteBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('site_name')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM subscription_instance_values USING product_block_resource_types WHERE subscription_instance_values.subscription_instance_id IN (SELECT subscription_instances.subscription_instance_id FROM subscription_instances WHERE subscription_instances.subscription_instance_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('SiteBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('site_name')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM product_block_resource_types WHERE product_block_resource_types.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('SiteBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('site_city')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM subscription_instance_values USING product_block_resource_types WHERE subscription_instance_values.subscription_instance_id IN (SELECT subscription_instances.subscription_instance_id FROM subscription_instances WHERE subscription_instances.subscription_instance_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('SiteBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('site_city')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM product_block_resource_types WHERE product_block_resource_types.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('SiteBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('site_country')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM subscription_instance_values USING product_block_resource_types WHERE subscription_instance_values.subscription_instance_id IN (SELECT subscription_instances.subscription_instance_id FROM subscription_instances WHERE subscription_instances.subscription_instance_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('SiteBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('site_country')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM product_block_resource_types WHERE product_block_resource_types.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('SiteBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('site_country_code')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM subscription_instance_values USING product_block_resource_types WHERE subscription_instance_values.subscription_instance_id IN (SELECT subscription_instances.subscription_instance_id FROM subscription_instances WHERE subscription_instances.subscription_instance_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('SiteBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('site_country_code')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM product_block_resource_types WHERE product_block_resource_types.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('SiteBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('site_latitude')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM subscription_instance_values USING product_block_resource_types WHERE subscription_instance_values.subscription_instance_id IN (SELECT subscription_instances.subscription_instance_id FROM subscription_instances WHERE subscription_instances.subscription_instance_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('SiteBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('site_latitude')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM product_block_resource_types WHERE product_block_resource_types.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('SiteBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('site_longitude')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM subscription_instance_values USING product_block_resource_types WHERE subscription_instance_values.subscription_instance_id IN (SELECT subscription_instances.subscription_instance_id FROM subscription_instances WHERE subscription_instances.subscription_instance_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('SiteBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('site_longitude')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM product_block_resource_types WHERE product_block_resource_types.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('SiteBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('site_internal_id')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM subscription_instance_values USING product_block_resource_types WHERE subscription_instance_values.subscription_instance_id IN (SELECT subscription_instances.subscription_instance_id FROM subscription_instances WHERE subscription_instances.subscription_instance_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('SiteBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('site_internal_id')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM product_block_resource_types WHERE product_block_resource_types.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('SiteBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('site_bgp_community_id')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM subscription_instance_values USING product_block_resource_types WHERE subscription_instance_values.subscription_instance_id IN (SELECT subscription_instances.subscription_instance_id FROM subscription_instances WHERE subscription_instances.subscription_instance_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('SiteBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('site_bgp_community_id')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM product_block_resource_types WHERE product_block_resource_types.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('SiteBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('site_tier')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM subscription_instance_values USING product_block_resource_types WHERE subscription_instance_values.subscription_instance_id IN (SELECT subscription_instances.subscription_instance_id FROM subscription_instances WHERE subscription_instances.subscription_instance_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('SiteBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('site_tier')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM product_block_resource_types WHERE product_block_resource_types.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('SiteBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('site_ts_address')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM subscription_instance_values USING product_block_resource_types WHERE subscription_instance_values.subscription_instance_id IN (SELECT subscription_instances.subscription_instance_id FROM subscription_instances WHERE subscription_instances.subscription_instance_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('SiteBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('site_ts_address')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM product_block_resource_types WHERE product_block_resource_types.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('RouterBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('router_fqdn')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM subscription_instance_values USING product_block_resource_types WHERE subscription_instance_values.subscription_instance_id IN (SELECT subscription_instances.subscription_instance_id FROM subscription_instances WHERE subscription_instances.subscription_instance_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('RouterBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('router_fqdn')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM product_block_resource_types WHERE product_block_resource_types.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('RouterBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('router_ts_port')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM subscription_instance_values USING product_block_resource_types WHERE subscription_instance_values.subscription_instance_id IN (SELECT subscription_instances.subscription_instance_id FROM subscription_instances WHERE subscription_instances.subscription_instance_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('RouterBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('router_ts_port')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM product_block_resource_types WHERE product_block_resource_types.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('RouterBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('router_access_via_ts')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM subscription_instance_values USING product_block_resource_types WHERE subscription_instance_values.subscription_instance_id IN (SELECT subscription_instances.subscription_instance_id FROM subscription_instances WHERE subscription_instances.subscription_instance_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('RouterBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('router_access_via_ts')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM product_block_resource_types WHERE product_block_resource_types.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('RouterBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('router_lo_ipv4_address')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM subscription_instance_values USING product_block_resource_types WHERE subscription_instance_values.subscription_instance_id IN (SELECT subscription_instances.subscription_instance_id FROM subscription_instances WHERE subscription_instances.subscription_instance_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('RouterBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('router_lo_ipv4_address')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM product_block_resource_types WHERE product_block_resource_types.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('RouterBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('router_lo_ipv6_address')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM subscription_instance_values USING product_block_resource_types WHERE subscription_instance_values.subscription_instance_id IN (SELECT subscription_instances.subscription_instance_id FROM subscription_instances WHERE subscription_instances.subscription_instance_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('RouterBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('router_lo_ipv6_address')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM product_block_resource_types WHERE product_block_resource_types.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('RouterBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('router_lo_iso_address')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM subscription_instance_values USING product_block_resource_types WHERE subscription_instance_values.subscription_instance_id IN (SELECT subscription_instances.subscription_instance_id FROM subscription_instances WHERE subscription_instances.subscription_instance_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('RouterBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('router_lo_iso_address')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM product_block_resource_types WHERE product_block_resource_types.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('RouterBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('router_si_ipv4_network')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM subscription_instance_values USING product_block_resource_types WHERE subscription_instance_values.subscription_instance_id IN (SELECT subscription_instances.subscription_instance_id FROM subscription_instances WHERE subscription_instances.subscription_instance_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('RouterBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('router_si_ipv4_network')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM product_block_resource_types WHERE product_block_resource_types.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('RouterBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('router_ias_lt_ipv4_network')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM subscription_instance_values USING product_block_resource_types WHERE subscription_instance_values.subscription_instance_id IN (SELECT subscription_instances.subscription_instance_id FROM subscription_instances WHERE subscription_instances.subscription_instance_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('RouterBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('router_ias_lt_ipv4_network')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM product_block_resource_types WHERE product_block_resource_types.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('RouterBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('router_ias_lt_ipv6_network')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM subscription_instance_values USING product_block_resource_types WHERE subscription_instance_values.subscription_instance_id IN (SELECT subscription_instances.subscription_instance_id FROM subscription_instances WHERE subscription_instances.subscription_instance_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('RouterBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('router_ias_lt_ipv6_network')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM product_block_resource_types WHERE product_block_resource_types.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('RouterBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('router_vendor')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM subscription_instance_values USING product_block_resource_types WHERE subscription_instance_values.subscription_instance_id IN (SELECT subscription_instances.subscription_instance_id FROM subscription_instances WHERE subscription_instances.subscription_instance_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('RouterBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('router_vendor')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM product_block_resource_types WHERE product_block_resource_types.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('RouterBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('router_role')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM subscription_instance_values USING product_block_resource_types WHERE subscription_instance_values.subscription_instance_id IN (SELECT subscription_instances.subscription_instance_id FROM subscription_instances WHERE subscription_instances.subscription_instance_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('RouterBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('router_role')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM product_block_resource_types WHERE product_block_resource_types.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('RouterBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('router_is_ias_connected')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM subscription_instance_values USING product_block_resource_types WHERE subscription_instance_values.subscription_instance_id IN (SELECT subscription_instances.subscription_instance_id FROM subscription_instances WHERE subscription_instances.subscription_instance_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('RouterBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('router_is_ias_connected')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM product_block_resource_types WHERE product_block_resource_types.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('geant_s_sid')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM subscription_instance_values USING product_block_resource_types WHERE subscription_instance_values.subscription_instance_id IN (SELECT subscription_instances.subscription_instance_id FROM subscription_instances WHERE subscription_instances.subscription_instance_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('geant_s_sid')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM product_block_resource_types WHERE product_block_resource_types.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_description')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM subscription_instance_values USING product_block_resource_types WHERE subscription_instance_values.subscription_instance_id IN (SELECT subscription_instances.subscription_instance_id FROM subscription_instances WHERE subscription_instances.subscription_instance_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_description')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM product_block_resource_types WHERE product_block_resource_types.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_type')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM subscription_instance_values USING product_block_resource_types WHERE subscription_instance_values.subscription_instance_id IN (SELECT subscription_instances.subscription_instance_id FROM subscription_instances WHERE subscription_instances.subscription_instance_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_type')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM product_block_resource_types WHERE product_block_resource_types.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_speed')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM subscription_instance_values USING product_block_resource_types WHERE subscription_instance_values.subscription_instance_id IN (SELECT subscription_instances.subscription_instance_id FROM subscription_instances WHERE subscription_instances.subscription_instance_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_speed')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM product_block_resource_types WHERE product_block_resource_types.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_minimum_links')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM subscription_instance_values USING product_block_resource_types WHERE subscription_instance_values.subscription_instance_id IN (SELECT subscription_instances.subscription_instance_id FROM subscription_instances WHERE subscription_instances.subscription_instance_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_minimum_links')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM product_block_resource_types WHERE product_block_resource_types.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_isis_metric')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM subscription_instance_values USING product_block_resource_types WHERE subscription_instance_values.subscription_instance_id IN (SELECT subscription_instances.subscription_instance_id FROM subscription_instances WHERE subscription_instances.subscription_instance_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_isis_metric')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM product_block_resource_types WHERE product_block_resource_types.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_ipv4_network')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM subscription_instance_values USING product_block_resource_types WHERE subscription_instance_values.subscription_instance_id IN (SELECT subscription_instances.subscription_instance_id FROM subscription_instances WHERE subscription_instances.subscription_instance_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_ipv4_network')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM product_block_resource_types WHERE product_block_resource_types.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_ipv6_network')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM subscription_instance_values USING product_block_resource_types WHERE subscription_instance_values.subscription_instance_id IN (SELECT subscription_instances.subscription_instance_id FROM subscription_instances WHERE subscription_instances.subscription_instance_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_ipv6_network')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM product_block_resource_types WHERE product_block_resource_types.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_sideA_ae_iface')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM subscription_instance_values USING product_block_resource_types WHERE subscription_instance_values.subscription_instance_id IN (SELECT subscription_instances.subscription_instance_id FROM subscription_instances WHERE subscription_instances.subscription_instance_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_sideA_ae_iface')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM product_block_resource_types WHERE product_block_resource_types.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_sideA_ae_geant_a_sid')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM subscription_instance_values USING product_block_resource_types WHERE subscription_instance_values.subscription_instance_id IN (SELECT subscription_instances.subscription_instance_id FROM subscription_instances WHERE subscription_instances.subscription_instance_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_sideA_ae_geant_a_sid')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM product_block_resource_types WHERE product_block_resource_types.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_sideA_ae_members')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM subscription_instance_values USING product_block_resource_types WHERE subscription_instance_values.subscription_instance_id IN (SELECT subscription_instances.subscription_instance_id FROM subscription_instances WHERE subscription_instances.subscription_instance_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_sideA_ae_members')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM product_block_resource_types WHERE product_block_resource_types.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_sideA_ae_members_description')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM subscription_instance_values USING product_block_resource_types WHERE subscription_instance_values.subscription_instance_id IN (SELECT subscription_instances.subscription_instance_id FROM subscription_instances WHERE subscription_instances.subscription_instance_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_sideA_ae_members_description')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM product_block_resource_types WHERE product_block_resource_types.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_sideB_ae_iface')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM subscription_instance_values USING product_block_resource_types WHERE subscription_instance_values.subscription_instance_id IN (SELECT subscription_instances.subscription_instance_id FROM subscription_instances WHERE subscription_instances.subscription_instance_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_sideB_ae_iface')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM product_block_resource_types WHERE product_block_resource_types.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_sideB_ae_geant_a_sid')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM subscription_instance_values USING product_block_resource_types WHERE subscription_instance_values.subscription_instance_id IN (SELECT subscription_instances.subscription_instance_id FROM subscription_instances WHERE subscription_instances.subscription_instance_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_sideB_ae_geant_a_sid')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM product_block_resource_types WHERE product_block_resource_types.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_sideB_ae_members')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM subscription_instance_values USING product_block_resource_types WHERE subscription_instance_values.subscription_instance_id IN (SELECT subscription_instances.subscription_instance_id FROM subscription_instances WHERE subscription_instances.subscription_instance_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_sideB_ae_members')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM product_block_resource_types WHERE product_block_resource_types.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_sideB_ae_members_description')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM subscription_instance_values USING product_block_resource_types WHERE subscription_instance_values.subscription_instance_id IN (SELECT subscription_instances.subscription_instance_id FROM subscription_instances WHERE subscription_instances.subscription_instance_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_sideB_ae_members_description')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM subscription_instance_values WHERE subscription_instance_values.resource_type_id IN (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('site_name', 'iptrunk_minimum_links', 'iptrunk_description', 'router_ias_lt_ipv4_network', 'geant_s_sid', 'iptrunk_isis_metric', 'iptrunk_sideA_ae_geant_a_sid', 'iptrunk_sideB_ae_geant_a_sid', 'router_lo_ipv6_address', 'iptrunk_sideB_ae_members', 'router_lo_ipv4_address', 'site_city', 'site_tier', 'router_role', 'iptrunk_type', 'site_bgp_community_id', 'iptrunk_sideA_ae_iface', 'iptrunk_ipv4_network', 'iptrunk_sideB_ae_members_description', 'iptrunk_speed', 'site_country_code', 'router_access_via_ts', 'site_internal_id', 'router_si_ipv4_network', 'router_ias_lt_ipv6_network', 'site_latitude', 'site_country', 'site_ts_address', 'iptrunk_sideB_ae_iface', 'router_is_ias_connected', 'iptrunk_ipv6_network', 'site_longitude', 'router_lo_iso_address', 'iptrunk_sideA_ae_members', 'router_fqdn', 'iptrunk_sideA_ae_members_description', 'router_ts_port', 'router_vendor')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM resource_types WHERE resource_types.resource_type IN ('site_name', 'iptrunk_minimum_links', 'iptrunk_description', 'router_ias_lt_ipv4_network', 'geant_s_sid', 'iptrunk_isis_metric', 'iptrunk_sideA_ae_geant_a_sid', 'iptrunk_sideB_ae_geant_a_sid', 'router_lo_ipv6_address', 'iptrunk_sideB_ae_members', 'router_lo_ipv4_address', 'site_city', 'site_tier', 'router_role', 'iptrunk_type', 'site_bgp_community_id', 'iptrunk_sideA_ae_iface', 'iptrunk_ipv4_network', 'iptrunk_sideB_ae_members_description', 'iptrunk_speed', 'site_country_code', 'router_access_via_ts', 'site_internal_id', 'router_si_ipv4_network', 'router_ias_lt_ipv6_network', 'site_latitude', 'site_country', 'site_ts_address', 'iptrunk_sideB_ae_iface', 'router_is_ias_connected', 'iptrunk_ipv6_network', 'site_longitude', 'router_lo_iso_address', 'iptrunk_sideA_ae_members', 'router_fqdn', 'iptrunk_sideA_ae_members_description', 'router_ts_port', 'router_vendor') - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM product_product_blocks WHERE product_product_blocks.product_id IN (SELECT products.product_id FROM products WHERE products.name IN ('Site')) AND product_product_blocks.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('SiteBlock')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM product_product_blocks WHERE product_product_blocks.product_id IN (SELECT products.product_id FROM products WHERE products.name IN ('Router')) AND product_product_blocks.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('RouterBlock')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM product_product_blocks WHERE product_product_blocks.product_id IN (SELECT products.product_id FROM products WHERE products.name IN ('IP trunk')) AND product_product_blocks.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM product_block_relations WHERE product_block_relations.in_use_by_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('RouterBlock')) AND product_block_relations.depends_on_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('SiteBlock')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM product_block_relations WHERE product_block_relations.in_use_by_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock')) AND product_block_relations.depends_on_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('RouterBlock')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM subscription_instances WHERE subscription_instances.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock', 'RouterBlock', 'SiteBlock')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock', 'RouterBlock', 'SiteBlock') - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM processes WHERE processes.pid IN (SELECT processes_subscriptions.pid FROM processes_subscriptions WHERE processes_subscriptions.subscription_id IN (SELECT subscriptions.subscription_id FROM subscriptions WHERE subscriptions.product_id IN (SELECT products.product_id FROM products WHERE products.name IN ('Router', 'IP trunk', 'Site')))) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM processes_subscriptions WHERE processes_subscriptions.subscription_id IN (SELECT subscriptions.subscription_id FROM subscriptions WHERE subscriptions.product_id IN (SELECT products.product_id FROM products WHERE products.name IN ('Router', 'IP trunk', 'Site'))) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM subscription_instances WHERE subscription_instances.subscription_id IN (SELECT subscriptions.subscription_id FROM subscriptions WHERE subscriptions.product_id IN (SELECT products.product_id FROM products WHERE products.name IN ('Router', 'IP trunk', 'Site'))) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM subscriptions WHERE subscriptions.product_id IN (SELECT products.product_id FROM products WHERE products.name IN ('Router', 'IP trunk', 'Site')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM products WHERE products.name IN ('Router', 'IP trunk', 'Site') - """)) + """ + ) + ) diff --git a/gso/migrations/versions/2023-08-14_a6eefd32c4f7_add_ip_trunk_workflows.py b/gso/migrations/versions/2023-08-14_a6eefd32c4f7_add_ip_trunk_workflows.py index b341eb7c8c9061959febac45181b1a70028e6236..89ddbdde88f820e1facff9a7743ff7753e8e671f 100644 --- a/gso/migrations/versions/2023-08-14_a6eefd32c4f7_add_ip_trunk_workflows.py +++ b/gso/migrations/versions/2023-08-14_a6eefd32c4f7_add_ip_trunk_workflows.py @@ -9,8 +9,8 @@ import sqlalchemy as sa from alembic import op # revision identifiers, used by Alembic. -revision = 'a6eefd32c4f7' -down_revision = '3657611f0dfc' +revision = "a6eefd32c4f7" +down_revision = "3657611f0dfc" branch_labels = None depends_on = None @@ -22,26 +22,26 @@ new_workflows = [ "name": "create_iptrunk", "target": "CREATE", "description": "Create IP trunk", - "product_type": "Iptrunk" + "product_type": "Iptrunk", }, { "name": "terminate_iptrunk", "target": "TERMINATE", "description": "Terminate IPtrunk", - "product_type": "Iptrunk" + "product_type": "Iptrunk", }, { "name": "modify_trunk_interface", "target": "MODIFY", "description": "Modify IP Trunk interface", - "product_type": "Iptrunk" + "product_type": "Iptrunk", }, { "name": "modify_isis_metric", "target": "MODIFY", "description": "Modify IP trunk", - "product_type": "Iptrunk" - } + "product_type": "Iptrunk", + }, ] diff --git a/gso/migrations/versions/2023-08-16_e68720f2ec32_add_ip_trunk_migration_workflow.py b/gso/migrations/versions/2023-08-16_e68720f2ec32_add_ip_trunk_migration_workflow.py index f2ad05f776ede60ab8c2d4f696454347a48f4e57..0fe19e739d0b8db2dabe366eda7da6ffd8be8e30 100644 --- a/gso/migrations/versions/2023-08-16_e68720f2ec32_add_ip_trunk_migration_workflow.py +++ b/gso/migrations/versions/2023-08-16_e68720f2ec32_add_ip_trunk_migration_workflow.py @@ -9,8 +9,8 @@ import sqlalchemy as sa from alembic import op # revision identifiers, used by Alembic. -revision = 'e68720f2ec32' -down_revision = 'a6eefd32c4f7' +revision = "e68720f2ec32" +down_revision = "a6eefd32c4f7" branch_labels = None depends_on = None @@ -22,7 +22,7 @@ new_workflows = [ "name": "migrate_iptrunk", "target": "MODIFY", "description": "Migrate an IP Trunk", - "product_type": "Iptrunk" + "product_type": "Iptrunk", } ] diff --git a/gso/migrations/versions/2023-08-23_01e42c100448_update_ip_trunk_model.py b/gso/migrations/versions/2023-08-23_01e42c100448_update_ip_trunk_model.py index 99979d8c15cd47b7251a17c1f54fc46be398cdb0..3fadabca869db85a58784f2401243356ffbed251 100644 --- a/gso/migrations/versions/2023-08-23_01e42c100448_update_ip_trunk_model.py +++ b/gso/migrations/versions/2023-08-23_01e42c100448_update_ip_trunk_model.py @@ -9,105 +9,227 @@ import sqlalchemy as sa from alembic import op # revision identifiers, used by Alembic. -revision = '01e42c100448' -down_revision = 'e68720f2ec32' +revision = "01e42c100448" +down_revision = "e68720f2ec32" branch_labels = None depends_on = None def upgrade() -> None: conn = op.get_bind() - conn.execute(sa.text(""" + conn.execute( + sa.text( + """ DELETE FROM product_block_resource_types WHERE product_block_resource_types.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_sideA_ae_members')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM subscription_instance_values USING product_block_resource_types WHERE subscription_instance_values.subscription_instance_id IN (SELECT subscription_instances.subscription_instance_id FROM subscription_instances WHERE subscription_instances.subscription_instance_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_sideA_ae_members')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM product_block_resource_types WHERE product_block_resource_types.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_sideB_ae_geant_a_sid')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM subscription_instance_values USING product_block_resource_types WHERE subscription_instance_values.subscription_instance_id IN (SELECT subscription_instances.subscription_instance_id FROM subscription_instances WHERE subscription_instances.subscription_instance_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_sideB_ae_geant_a_sid')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM product_block_resource_types WHERE product_block_resource_types.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_sideB_ae_members')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM subscription_instance_values USING product_block_resource_types WHERE subscription_instance_values.subscription_instance_id IN (SELECT subscription_instances.subscription_instance_id FROM subscription_instances WHERE subscription_instances.subscription_instance_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_sideB_ae_members')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM product_block_resource_types WHERE product_block_resource_types.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_sideA_ae_members_description')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM subscription_instance_values USING product_block_resource_types WHERE subscription_instance_values.subscription_instance_id IN (SELECT subscription_instances.subscription_instance_id FROM subscription_instances WHERE subscription_instances.subscription_instance_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_sideA_ae_members_description')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM product_block_resource_types WHERE product_block_resource_types.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_sideA_ae_geant_a_sid')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM subscription_instance_values USING product_block_resource_types WHERE subscription_instance_values.subscription_instance_id IN (SELECT subscription_instances.subscription_instance_id FROM subscription_instances WHERE subscription_instances.subscription_instance_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_sideA_ae_geant_a_sid')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM product_block_resource_types WHERE product_block_resource_types.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_sideB_ae_members_description')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM subscription_instance_values USING product_block_resource_types WHERE subscription_instance_values.subscription_instance_id IN (SELECT subscription_instances.subscription_instance_id FROM subscription_instances WHERE subscription_instances.subscription_instance_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_sideB_ae_members_description')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM product_block_resource_types WHERE product_block_resource_types.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_sideB_ae_iface')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM subscription_instance_values USING product_block_resource_types WHERE subscription_instance_values.subscription_instance_id IN (SELECT subscription_instances.subscription_instance_id FROM subscription_instances WHERE subscription_instances.subscription_instance_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_sideB_ae_iface')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM product_block_resource_types WHERE product_block_resource_types.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_sideA_ae_iface')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM subscription_instance_values USING product_block_resource_types WHERE subscription_instance_values.subscription_instance_id IN (SELECT subscription_instances.subscription_instance_id FROM subscription_instances WHERE subscription_instances.subscription_instance_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_sideA_ae_iface')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM product_block_relations WHERE product_block_relations.in_use_by_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock')) AND product_block_relations.depends_on_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('RouterBlock')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM subscription_instance_values WHERE subscription_instance_values.resource_type_id IN (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_sideA_ae_members', 'iptrunk_sideB_ae_geant_a_sid', 'iptrunk_sideB_ae_members', 'iptrunk_sideA_ae_members_description', 'iptrunk_sideA_ae_geant_a_sid', 'iptrunk_sideB_ae_members_description', 'iptrunk_sideB_ae_iface', 'iptrunk_sideA_ae_iface')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_sideA_ae_members', 'iptrunk_sideB_ae_geant_a_sid', 'iptrunk_sideB_ae_members', 'iptrunk_sideA_ae_members_description', 'iptrunk_sideA_ae_geant_a_sid', 'iptrunk_sideB_ae_members_description', 'iptrunk_sideB_ae_iface', 'iptrunk_sideA_ae_iface') - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO product_blocks (name, description, tag, status) VALUES ('IptrunkSideBlock', 'IP Trunk side', 'IPTSIDE', 'active') RETURNING product_blocks.product_block_id - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO resource_types (resource_type, description) VALUES ('iptrunk_side_ae_members_description', 'LAG member descriptions') RETURNING resource_types.resource_type_id - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO resource_types (resource_type, description) VALUES ('iptrunk_side_ae_iface', 'LAG interfaces') RETURNING resource_types.resource_type_id - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO resource_types (resource_type, description) VALUES ('iptrunk_side_ae_members', 'LAG interface names') RETURNING resource_types.resource_type_id - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO resource_types (resource_type, description) VALUES ('iptrunk_side_ae_geant_a_sid', 'GÉANT SID') RETURNING resource_types.resource_type_id - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO product_block_relations (in_use_by_id, depends_on_id) VALUES ((SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkSideBlock')), (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('RouterBlock'))) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO product_block_relations (in_use_by_id, depends_on_id) VALUES ((SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock')), (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkSideBlock'))) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO product_block_resource_types (product_block_id, resource_type_id) VALUES ((SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkSideBlock')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_side_ae_members_description'))) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO product_block_resource_types (product_block_id, resource_type_id) VALUES ((SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkSideBlock')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_side_ae_iface'))) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO product_block_resource_types (product_block_id, resource_type_id) VALUES ((SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkSideBlock')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_side_ae_members'))) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO product_block_resource_types (product_block_id, resource_type_id) VALUES ((SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkSideBlock')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_side_ae_geant_a_sid'))) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ WITH subscription_instance_ids AS ( SELECT subscription_instances.subscription_instance_id @@ -129,8 +251,12 @@ INSERT INTO product_block_resource_types (product_block_id, resource_type_id) VA CROSS JOIN subscription_instance_ids WHERE resource_types.resource_type = 'iptrunk_side_ae_members_description' - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ WITH subscription_instance_ids AS ( SELECT subscription_instances.subscription_instance_id @@ -152,8 +278,12 @@ INSERT INTO product_block_resource_types (product_block_id, resource_type_id) VA CROSS JOIN subscription_instance_ids WHERE resource_types.resource_type = 'iptrunk_side_ae_iface' - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ WITH subscription_instance_ids AS ( SELECT subscription_instances.subscription_instance_id @@ -175,8 +305,12 @@ INSERT INTO product_block_resource_types (product_block_id, resource_type_id) VA CROSS JOIN subscription_instance_ids WHERE resource_types.resource_type = 'iptrunk_side_ae_members' - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ WITH subscription_instance_ids AS ( SELECT subscription_instances.subscription_instance_id @@ -198,50 +332,108 @@ INSERT INTO product_block_resource_types (product_block_id, resource_type_id) VA CROSS JOIN subscription_instance_ids WHERE resource_types.resource_type = 'iptrunk_side_ae_geant_a_sid' - """)) + """ + ) + ) def downgrade() -> None: conn = op.get_bind() - conn.execute(sa.text(""" + conn.execute( + sa.text( + """ DELETE FROM product_block_resource_types WHERE product_block_resource_types.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkSideBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_side_ae_members_description')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM subscription_instance_values USING product_block_resource_types WHERE subscription_instance_values.subscription_instance_id IN (SELECT subscription_instances.subscription_instance_id FROM subscription_instances WHERE subscription_instances.subscription_instance_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkSideBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_side_ae_members_description')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM product_block_resource_types WHERE product_block_resource_types.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkSideBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_side_ae_iface')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM subscription_instance_values USING product_block_resource_types WHERE subscription_instance_values.subscription_instance_id IN (SELECT subscription_instances.subscription_instance_id FROM subscription_instances WHERE subscription_instances.subscription_instance_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkSideBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_side_ae_iface')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM product_block_resource_types WHERE product_block_resource_types.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkSideBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_side_ae_members')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM subscription_instance_values USING product_block_resource_types WHERE subscription_instance_values.subscription_instance_id IN (SELECT subscription_instances.subscription_instance_id FROM subscription_instances WHERE subscription_instances.subscription_instance_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkSideBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_side_ae_members')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM product_block_resource_types WHERE product_block_resource_types.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkSideBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_side_ae_geant_a_sid')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM subscription_instance_values USING product_block_resource_types WHERE subscription_instance_values.subscription_instance_id IN (SELECT subscription_instances.subscription_instance_id FROM subscription_instances WHERE subscription_instances.subscription_instance_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkSideBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_side_ae_geant_a_sid')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM subscription_instance_values WHERE subscription_instance_values.resource_type_id IN (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_side_ae_members_description', 'iptrunk_side_ae_iface', 'iptrunk_side_ae_members', 'iptrunk_side_ae_geant_a_sid')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_side_ae_members_description', 'iptrunk_side_ae_iface', 'iptrunk_side_ae_members', 'iptrunk_side_ae_geant_a_sid') - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM product_block_relations WHERE product_block_relations.in_use_by_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkSideBlock')) AND product_block_relations.depends_on_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('RouterBlock')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM product_block_relations WHERE product_block_relations.in_use_by_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkBlock')) AND product_block_relations.depends_on_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkSideBlock')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM subscription_instances WHERE subscription_instances.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkSideBlock')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM product_blocks WHERE product_blocks.name IN ('IptrunkSideBlock') - """)) + """ + ) + ) diff --git a/gso/migrations/versions/2023-10-11_394dc60d5c02_modify_ip_trunk_model.py b/gso/migrations/versions/2023-10-11_394dc60d5c02_modify_ip_trunk_model.py index ce76bb6d3cb8d701bda8d69e0f474a81ec2e288e..51be3c59acc0641a3cce2058d60f4c650708bf25 100644 --- a/gso/migrations/versions/2023-10-11_394dc60d5c02_modify_ip_trunk_model.py +++ b/gso/migrations/versions/2023-10-11_394dc60d5c02_modify_ip_trunk_model.py @@ -9,78 +9,162 @@ import sqlalchemy as sa from alembic import op # revision identifiers, used by Alembic. -revision = '394dc60d5c02' -down_revision = '01e42c100448' +revision = "394dc60d5c02" +down_revision = "01e42c100448" branch_labels = None depends_on = None def upgrade() -> None: conn = op.get_bind() - conn.execute(sa.text(""" + conn.execute( + sa.text( + """ DELETE FROM product_block_resource_types WHERE product_block_resource_types.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkSideBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_side_ae_members_description')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM subscription_instance_values USING product_block_resource_types WHERE subscription_instance_values.subscription_instance_id IN (SELECT subscription_instances.subscription_instance_id FROM subscription_instances WHERE subscription_instances.subscription_instance_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkSideBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_side_ae_members_description')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM product_block_resource_types WHERE product_block_resource_types.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkSideBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_side_ae_members')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM subscription_instance_values USING product_block_resource_types WHERE subscription_instance_values.subscription_instance_id IN (SELECT subscription_instances.subscription_instance_id FROM subscription_instances WHERE subscription_instances.subscription_instance_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkSideBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_side_ae_members')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM subscription_instance_values WHERE subscription_instance_values.resource_type_id IN (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_side_ae_members_description', 'iptrunk_side_ae_members')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_side_ae_members_description', 'iptrunk_side_ae_members') - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO product_blocks (name, description, tag, status) VALUES ('IptrunkInterfaceBlock', 'Interface in a LAG as part of an IP trunk', 'IPTINT', 'active') RETURNING product_blocks.product_block_id - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO resource_types (resource_type, description) VALUES ('interface_description', 'Description of a LAG interface') RETURNING resource_types.resource_type_id - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO resource_types (resource_type, description) VALUES ('interface_name', 'Interface name of a LAG member') RETURNING resource_types.resource_type_id - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO product_block_relations (in_use_by_id, depends_on_id) VALUES ((SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkSideBlock')), (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkInterfaceBlock'))) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO product_block_resource_types (product_block_id, resource_type_id) VALUES ((SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkInterfaceBlock')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('interface_description'))) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ INSERT INTO product_block_resource_types (product_block_id, resource_type_id) VALUES ((SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkInterfaceBlock')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('interface_name'))) - """)) + """ + ) + ) def downgrade() -> None: conn = op.get_bind() - conn.execute(sa.text(""" + conn.execute( + sa.text( + """ DELETE FROM product_block_resource_types WHERE product_block_resource_types.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkInterfaceBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('interface_description')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM subscription_instance_values USING product_block_resource_types WHERE subscription_instance_values.subscription_instance_id IN (SELECT subscription_instances.subscription_instance_id FROM subscription_instances WHERE subscription_instances.subscription_instance_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkInterfaceBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('interface_description')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM product_block_resource_types WHERE product_block_resource_types.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkInterfaceBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('interface_name')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM subscription_instance_values USING product_block_resource_types WHERE subscription_instance_values.subscription_instance_id IN (SELECT subscription_instances.subscription_instance_id FROM subscription_instances WHERE subscription_instances.subscription_instance_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkInterfaceBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('interface_name')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM subscription_instance_values WHERE subscription_instance_values.resource_type_id IN (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('interface_description', 'interface_name')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM resource_types WHERE resource_types.resource_type IN ('interface_description', 'interface_name') - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM product_block_relations WHERE product_block_relations.in_use_by_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkSideBlock')) AND product_block_relations.depends_on_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkInterfaceBlock')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM subscription_instances WHERE subscription_instances.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkInterfaceBlock')) - """)) - conn.execute(sa.text(""" + """ + ) + ) + conn.execute( + sa.text( + """ DELETE FROM product_blocks WHERE product_blocks.name IN ('IptrunkInterfaceBlock') - """)) + """ + ) + ) diff --git a/gso/migrations/versions/2023-11-02_259c320235f5_add_site_modification_and_termination_.py b/gso/migrations/versions/2023-11-02_259c320235f5_add_site_modification_and_termination_.py index 32a9db91d428494340cf1c7678360fcac567d71e..996e169fb94f6014df8a06a1bf85252963f363f8 100644 --- a/gso/migrations/versions/2023-11-02_259c320235f5_add_site_modification_and_termination_.py +++ b/gso/migrations/versions/2023-11-02_259c320235f5_add_site_modification_and_termination_.py @@ -16,8 +16,18 @@ branch_labels = None depends_on = None new_workflows = [ - {"name": "modify_site", "target": "MODIFY", "description": "Modify site", "product_type": "Site"}, - {"name": "terminate_site", "target": "TERMINATE", "description": "Terminate site", "product_type": "Site"}, + { + "name": "modify_site", + "target": "MODIFY", + "description": "Modify site", + "product_type": "Site", + }, + { + "name": "terminate_site", + "target": "TERMINATE", + "description": "Terminate site", + "product_type": "Site", + }, ] diff --git a/gso/products/__init__.py b/gso/products/__init__.py index e6a8c06f8850748b36233be63006a8fa9709d946..b2887f35d7c4fb6c9734bd9800d30fcf58356ff8 100644 --- a/gso/products/__init__.py +++ b/gso/products/__init__.py @@ -23,5 +23,5 @@ SUBSCRIPTION_MODEL_REGISTRY.update( "Site": Site, "Router": Router, "IP trunk": Iptrunk, - } + }, ) diff --git a/gso/products/product_blocks/iptrunk.py b/gso/products/product_blocks/iptrunk.py index 7fab56c0d20be1d1adb9e9b65ffebd8049caa1ff..8212a6ec3e7a9ffd90e5eaba92cce9e8076e491d 100644 --- a/gso/products/product_blocks/iptrunk.py +++ b/gso/products/product_blocks/iptrunk.py @@ -7,7 +7,11 @@ from orchestrator.domain.base import ProductBlockModel from orchestrator.forms.validators import UniqueConstrainedList from orchestrator.types import SubscriptionLifecycle, strEnum -from gso.products.product_blocks.router import RouterBlock, RouterBlockInactive, RouterBlockProvisioning +from gso.products.product_blocks.router import ( + RouterBlock, + RouterBlockInactive, + RouterBlockProvisioning, +) class PhyPortCapacity(strEnum): @@ -35,7 +39,9 @@ class LAGMemberList(UniqueConstrainedList[T]): # type: ignore[type-var] class IptrunkInterfaceBlockInactive( - ProductBlockModel, lifecycle=[SubscriptionLifecycle.INITIAL], product_block_name="IptrunkInterfaceBlock" + ProductBlockModel, + lifecycle=[SubscriptionLifecycle.INITIAL], + product_block_name="IptrunkInterfaceBlock", ): # TODO: add validation for interface names, making the type a constrained string interface_name: str | None = None @@ -58,7 +64,9 @@ class IptrunkSides(UniqueConstrainedList[T]): # type: ignore[type-var] class IptrunkSideBlockInactive( - ProductBlockModel, lifecycle=[SubscriptionLifecycle.INITIAL], product_block_name="IptrunkSideBlock" + ProductBlockModel, + lifecycle=[SubscriptionLifecycle.INITIAL], + product_block_name="IptrunkSideBlock", ): iptrunk_side_node: RouterBlockInactive iptrunk_side_ae_iface: str | None = None @@ -81,7 +89,9 @@ class IptrunkSideBlock(IptrunkSideBlockProvisioning, lifecycle=[SubscriptionLife class IptrunkBlockInactive( - ProductBlockModel, lifecycle=[SubscriptionLifecycle.INITIAL], product_block_name="IptrunkBlock" + ProductBlockModel, + lifecycle=[SubscriptionLifecycle.INITIAL], + product_block_name="IptrunkBlock", ): """A trunk that's currently inactive, see :class:`IptrunkBlock`.""" diff --git a/gso/products/product_blocks/router.py b/gso/products/product_blocks/router.py index a8a820448a1b7388b903b0be69b7da9d4c17d660..80985885e807621e4751fcd94d0601e786572524 100644 --- a/gso/products/product_blocks/router.py +++ b/gso/products/product_blocks/router.py @@ -5,7 +5,11 @@ from orchestrator.domain.base import ProductBlockModel from orchestrator.types import SubscriptionLifecycle, strEnum from pydantic import ConstrainedInt -from gso.products.product_blocks.site import SiteBlock, SiteBlockInactive, SiteBlockProvisioning +from gso.products.product_blocks.site import ( + SiteBlock, + SiteBlockInactive, + SiteBlockProvisioning, +) class RouterVendor(strEnum): @@ -34,7 +38,9 @@ class PortNumber(ConstrainedInt): class RouterBlockInactive( - ProductBlockModel, lifecycle=[SubscriptionLifecycle.INITIAL], product_block_name="RouterBlock" + ProductBlockModel, + lifecycle=[SubscriptionLifecycle.INITIAL], + product_block_name="RouterBlock", ): """A router that's being currently inactive. See :class:`RouterBlock`.""" diff --git a/gso/products/product_blocks/site.py b/gso/products/product_blocks/site.py index 739e1a0a91629b6dc2e427bfbd6ccd93daa8bb63..ce5ec5f18cd071cc750d059d1bab608ff4ff4f01 100644 --- a/gso/products/product_blocks/site.py +++ b/gso/products/product_blocks/site.py @@ -1,6 +1,5 @@ """The product block that describes a site subscription.""" import re -from typing import Union from orchestrator.domain.base import ProductBlockModel from orchestrator.types import SubscriptionLifecycle, strEnum @@ -31,9 +30,10 @@ class LatitudeCoordinate(ConstrainedStr): regex = re.compile(r"^-?([1-8]?\d(\.\d+)?|90(\.0+)?)$") @classmethod - def validate(cls, value: Union[str]) -> Union[str]: + def validate(cls, value: str) -> str: if not cls.regex.match(value): - raise ValueError("Invalid latitude coordinate. Valid examples: '40.7128', '-74.0060', '90', '-90', '0'.") + msg = "Invalid latitude coordinate. Valid examples: '40.7128', '-74.0060', '90', '-90', '0'." + raise ValueError(msg) return value @@ -49,14 +49,19 @@ class LongitudeCoordinate(ConstrainedStr): regex = re.compile(r"^-?(180(\.0+)?|((1[0-7]\d)|([1-9]?\d))(\.\d+)?)$") @classmethod - def validate(cls, value: Union[str]) -> Union[str]: + def validate(cls, value: str) -> str: if not cls.regex.match(value): - raise ValueError("Invalid longitude coordinate. Valid examples: '40.7128', '-74.0060', '180', '-180'") + msg = "Invalid longitude coordinate. Valid examples: '40.7128', '-74.0060', '180', '-180'" + raise ValueError(msg) return value -class SiteBlockInactive(ProductBlockModel, lifecycle=[SubscriptionLifecycle.INITIAL], product_block_name="SiteBlock"): +class SiteBlockInactive( + ProductBlockModel, + lifecycle=[SubscriptionLifecycle.INITIAL], + product_block_name="SiteBlock", +): """A site that's currently inactive, see :class:`SiteBlock`.""" site_name: str | None = None diff --git a/gso/products/product_types/iptrunk.py b/gso/products/product_types/iptrunk.py index 05d21e65059a433d8df17086d0be93bbeab31d68..82b283b678371a7a9af4e5e3ca547b4536cfc690 100644 --- a/gso/products/product_types/iptrunk.py +++ b/gso/products/product_types/iptrunk.py @@ -1,7 +1,11 @@ from orchestrator.domain.base import SubscriptionModel from orchestrator.types import SubscriptionLifecycle -from gso.products.product_blocks.iptrunk import IptrunkBlock, IptrunkBlockInactive, IptrunkBlockProvisioning +from gso.products.product_blocks.iptrunk import ( + IptrunkBlock, + IptrunkBlockInactive, + IptrunkBlockProvisioning, +) class IptrunkInactive(SubscriptionModel, is_base=True): diff --git a/gso/products/product_types/router.py b/gso/products/product_types/router.py index 370c066524640792ca4c72fe46c03be704b16144..e0cfa3b092a6491c5d337f907da4c85afb42d92a 100644 --- a/gso/products/product_types/router.py +++ b/gso/products/product_types/router.py @@ -1,7 +1,11 @@ from orchestrator.domain.base import SubscriptionModel from orchestrator.types import SubscriptionLifecycle -from gso.products.product_blocks.router import RouterBlock, RouterBlockInactive, RouterBlockProvisioning +from gso.products.product_blocks.router import ( + RouterBlock, + RouterBlockInactive, + RouterBlockProvisioning, +) class RouterInactive(SubscriptionModel, is_base=True): diff --git a/gso/products/product_types/site.py b/gso/products/product_types/site.py index 76e51cfcdfef2f94602bf1dc86672f35eb97876c..5a78adffa596c376414d464502fe45c1ff09aa1e 100644 --- a/gso/products/product_types/site.py +++ b/gso/products/product_types/site.py @@ -1,7 +1,11 @@ from orchestrator.domain.base import SubscriptionModel from orchestrator.types import SubscriptionLifecycle -from gso.products.product_blocks.site import SiteBlock, SiteBlockInactive, SiteBlockProvisioning +from gso.products.product_blocks.site import ( + SiteBlock, + SiteBlockInactive, + SiteBlockProvisioning, +) class SiteInactive(SubscriptionModel, is_base=True): diff --git a/gso/schedules/scheduling.py b/gso/schedules/scheduling.py index 0df187da338d0f09aec03f47c03fc69510adc856..8202bd3b1be54cede66c820020c54a20fb00636b 100644 --- a/gso/schedules/scheduling.py +++ b/gso/schedules/scheduling.py @@ -1,6 +1,7 @@ import inspect +from collections.abc import Callable from functools import wraps -from typing import Any, Callable +from typing import Any from celery import current_app from celery.schedules import crontab @@ -35,7 +36,8 @@ def scheduler( module = inspect.getmodule(task_func) if module is None: - raise ValueError(f"Module for the task function {task_func.__name__} could not be found.") + msg = f"Module for the task function {task_func.__name__} could not be found." + raise ValueError(msg) task_path = f"{module.__name__}.{task_func.__name__}" current_app.conf.beat_schedule[task_func.__name__] = { diff --git a/gso/services/crm.py b/gso/services/crm.py index 5ccd3e45f80b0febf706f001f5e85e71c1c38bd9..54f73785bab784f60da990e93b45ba445979a464 100644 --- a/gso/services/crm.py +++ b/gso/services/crm.py @@ -6,8 +6,6 @@ from pydantic_forms.validators import Choice class CustomerNotFoundError(Exception): """Exception raised when a customer is not found.""" - pass - def all_customers() -> list[dict]: return [ @@ -23,7 +21,8 @@ def get_customer_by_name(name: str) -> dict[str, Any]: if customer["name"] == name: return customer - raise CustomerNotFoundError(f"Customer {name} not found") + msg = f"Customer {name} not found" + raise CustomerNotFoundError(msg) def customer_selector() -> Choice: @@ -31,4 +30,4 @@ def customer_selector() -> Choice: for customer in all_customers(): customers[customer["id"]] = customer["name"] - return Choice("Select a customer", zip(customers.keys(), customers.items())) # type: ignore[arg-type] + return Choice("Select a customer", zip(customers.keys(), customers.items(), strict=True)) # type: ignore[arg-type] diff --git a/gso/services/infoblox.py b/gso/services/infoblox.py index 0082f9bf2525d3ba32f19a6e3918cbe32348b2de..cac1e59ffda1a0313ab866dd0c16f7c31a544769 100644 --- a/gso/services/infoblox.py +++ b/gso/services/infoblox.py @@ -2,7 +2,10 @@ import ipaddress from logging import getLogger from infoblox_client import connector, objects -from infoblox_client.exceptions import InfobloxCannotCreateObject, InfobloxCannotUpdateObject +from infoblox_client.exceptions import ( + InfobloxCannotCreateObject, + InfobloxCannotUpdateObject, +) from gso.settings import IPAMParams, load_oss_params @@ -29,7 +32,7 @@ def _setup_connection() -> tuple[connector.Connector, IPAMParams]: "username": oss.INFOBLOX.username, "password": oss.INFOBLOX.password, "wapi_version": oss.INFOBLOX.wapi_version, - "ssl_verify": True if oss.INFOBLOX.scheme == "https" else False, + "ssl_verify": oss.INFOBLOX.scheme == "https", } return connector.Connector(options), oss @@ -66,7 +69,8 @@ def _allocate_network( return ipaddress.ip_network(created_net.network) logger.warning(f"IP container {container} appears to be full.") - raise AllocationError(f"Cannot allocate anything in {containers}, check whether any IP space is available.") + msg = f"Cannot allocate anything in {containers}, check whether any IP space is available." + raise AllocationError(msg) def hostname_available(hostname: str) -> bool: @@ -123,7 +127,9 @@ def allocate_v6_network(service_type: str, comment: str | None = "") -> ipaddres return ipaddress.IPv6Network(_allocate_network(conn, dns_view, netmask, containers, comment)) -def find_network_by_cidr(ip_network: ipaddress.IPv4Network | ipaddress.IPv6Network) -> objects.Network | None: +def find_network_by_cidr( + ip_network: ipaddress.IPv4Network | ipaddress.IPv6Network, +) -> objects.Network | None: """Find a network in Infoblox by its :term:`CIDR`. :param ip_network: The :term:`CIDR` that is searched. @@ -146,11 +152,15 @@ def delete_network(ip_network: ipaddress.IPv4Network | ipaddress.IPv6Network) -> if network: network.delete() else: - raise DeletionError(f"Could not find network {ip_network}, nothing has been deleted.") + msg = f"Could not find network {ip_network}, nothing has been deleted." + raise DeletionError(msg) def allocate_host( - hostname: str, service_type: str, cname_aliases: list[str], comment: str + hostname: str, + service_type: str, + cname_aliases: list[str], + comment: str, ) -> tuple[ipaddress.IPv4Address, ipaddress.IPv6Address]: """Allocate a new host record in Infoblox. @@ -170,7 +180,8 @@ def allocate_host( :type comment: str """ if not hostname_available(hostname): - raise AllocationError(f"Cannot allocate new host, FQDN {hostname} already taken.") + msg = f"Cannot allocate new host, FQDN {hostname} already taken." + raise AllocationError(msg) conn, oss = _setup_connection() allocation_networks_v4 = getattr(oss, service_type).V4.networks @@ -183,14 +194,20 @@ def allocate_host( ipv6_object = objects.IP.create(ip=v6_alloc, mac="00:00:00:00:00:00", configure_for_dhcp=False) try: new_host = objects.HostRecord.create( - conn, ip=ipv6_object, name=hostname, aliases=cname_aliases, comment=comment, dns_view=dns_view + conn, + ip=ipv6_object, + name=hostname, + aliases=cname_aliases, + comment=comment, + dns_view=dns_view, ) created_v6 = ipaddress.IPv6Address(new_host.ipv6addr) except InfobloxCannotCreateObject: logger.warning(f"Cannot find 1 available IP address in network {ipv6_range}.") if created_v6 is None: - raise AllocationError(f"Cannot find 1 available IP address in networks {allocation_networks_v6}.") + msg = f"Cannot find 1 available IP address in networks {allocation_networks_v6}." + raise AllocationError(msg) created_v4 = None for ipv4_range in allocation_networks_v4: @@ -206,12 +223,15 @@ def allocate_host( logger.warning(f"Cannot find 1 available IP address in network {ipv4_range}.") if created_v4 is None: - raise AllocationError(f"Cannot find 1 available IP address in networks {allocation_networks_v4}.") + msg = f"Cannot find 1 available IP address in networks {allocation_networks_v4}." + raise AllocationError(msg) return created_v4, created_v6 -def find_host_by_ip(ip_addr: ipaddress.IPv4Address | ipaddress.IPv6Address) -> objects.HostRecord | None: +def find_host_by_ip( + ip_addr: ipaddress.IPv4Address | ipaddress.IPv6Address, +) -> objects.HostRecord | None: """Find a host record in Infoblox by its associated IP address. :param ip_addr: The IP address of a host that is searched for. @@ -220,10 +240,14 @@ def find_host_by_ip(ip_addr: ipaddress.IPv4Address | ipaddress.IPv6Address) -> o conn, _ = _setup_connection() if ip_addr.version == 4: return objects.HostRecord.search( - conn, ipv4addr=ip_addr, return_fields=["ipv4addrs", "name", "view", "aliases", "comment"] + conn, + ipv4addr=ip_addr, + return_fields=["ipv4addrs", "name", "view", "aliases", "comment"], ) return objects.HostRecord.search( - conn, ipv6addr=ip_addr, return_fields=["ipv6addrs", "name", "view", "aliases", "comment"] + conn, + ipv6addr=ip_addr, + return_fields=["ipv6addrs", "name", "view", "aliases", "comment"], ) @@ -234,7 +258,11 @@ def find_host_by_fqdn(fqdn: str) -> objects.HostRecord | None: :type fqdn: str """ conn, _ = _setup_connection() - return objects.HostRecord.search(conn, name=fqdn, return_fields=["ipv4addrs", "name", "view", "aliases", "comment"]) + return objects.HostRecord.search( + conn, + name=fqdn, + return_fields=["ipv4addrs", "name", "view", "aliases", "comment"], + ) def delete_host_by_ip(ip_addr: ipaddress.IPv4Address | ipaddress.IPv6Address) -> None: @@ -250,7 +278,8 @@ def delete_host_by_ip(ip_addr: ipaddress.IPv4Address | ipaddress.IPv6Address) -> if host: host.delete() else: - raise DeletionError(f"Could not find host at {ip_addr}, nothing has been deleted.") + msg = f"Could not find host at {ip_addr}, nothing has been deleted." + raise DeletionError(msg) def delete_host_by_fqdn(fqdn: str) -> None: @@ -266,4 +295,5 @@ def delete_host_by_fqdn(fqdn: str) -> None: if host: host.delete() else: - raise DeletionError(f"Could not find host at {fqdn}, nothing has been deleted.") + msg = f"Could not find host at {fqdn}, nothing has been deleted." + raise DeletionError(msg) diff --git a/gso/services/netbox_client.py b/gso/services/netbox_client.py index 9a9d65e042ed7b2823a2a7bc17f1ee3f8ca36483..7da15a8604941c582d92b3bc958f1e1e417fdc91 100644 --- a/gso/services/netbox_client.py +++ b/gso/services/netbox_client.py @@ -8,7 +8,12 @@ from pynetbox.models.dcim import Devices, DeviceTypes, Interfaces from gso.products.product_types.router import Router from gso.settings import load_oss_params -from gso.utils.device_info import DEFAULT_SITE, FEASIBLE_IP_TRUNK_LAG_RANGE, ROUTER_ROLE, TierInfo +from gso.utils.device_info import ( + DEFAULT_SITE, + FEASIBLE_IP_TRUNK_LAG_RANGE, + ROUTER_ROLE, + TierInfo, +) from gso.utils.exceptions import NotFoundError, WorkflowStateError @@ -56,17 +61,20 @@ class NetboxClient: def get_allocated_interfaces_by_gso_subscription(self, device_name: str, subscription_id: UUID) -> list[Interfaces]: """Return all allocated interfaces of a device by name.""" - device = self.get_device_by_name(device_name) return self.netbox.dcim.interfaces.filter( - device_id=device.id, enabled=True, mark_connected=True, description=subscription_id + device_id=device.id, + enabled=True, + mark_connected=True, + description=subscription_id, ) def get_device_by_name(self, device_name: str) -> Devices: """Return the device object by name from netbox, or raise not found.""" device = self.netbox.dcim.devices.get(name=device_name) if device is None: - raise NotFoundError(f"Device: {device_name} not found.") + msg = f"Device: {device_name} not found." + raise NotFoundError(msg) return device def get_interface_by_name_and_device(self, iface_name: str, device_name: str) -> Interfaces: @@ -74,18 +82,24 @@ class NetboxClient: device = self.get_device_by_name(device_name) interface = self.netbox.dcim.interfaces.get(device_id=device.id, name=iface_name) if interface is None: - raise NotFoundError(f"Interface: {iface_name} on device with id: {device.id} not found.") + msg = f"Interface: {iface_name} on device with id: {device.id} not found." + raise NotFoundError(msg) return interface def get_interfaces_by_device(self, device_name: str, speed: str) -> list[Interfaces]: """Get all interfaces of a device by name and speed that are not reserved and not allocated.""" device = self.get_device_by_name(device_name) return list( - self.netbox.dcim.interfaces.filter(device_id=device.id, enabled=False, mark_connected=False, speed=speed) + self.netbox.dcim.interfaces.filter(device_id=device.id, enabled=False, mark_connected=False, speed=speed), ) def create_interface( - self, iface_name: str, type: str, device_name: str, description: str | None = None, enabled: bool = False + self, + iface_name: str, + type: str, + device_name: str, + description: str | None = None, + enabled: bool = False, ) -> Interfaces: """Create new interface on a device, where device is defined by name. @@ -106,17 +120,15 @@ class NetboxClient: def delete_interface(self, device_name: str, iface_name: str) -> None: """Delete an interface from a device by name.""" - interface = self.get_interface_by_name_and_device(iface_name, device_name) return interface.delete() def create_device_type(self, manufacturer: str, model: str, slug: str) -> DeviceTypes: """Create a new device type in Netbox.""" - # First get manufacturer id manufacturer_id = int(self.netbox.dcim.manufacturers.get(name=manufacturer).id) device_type = DeviceType( - **{"manufacturer": manufacturer_id, "model": model, "slug": slug} # type: ignore[arg-type] + **{"manufacturer": manufacturer_id, "model": model, "slug": slug}, # type: ignore[arg-type] ) return self.netbox.dcim.device_types.create(dict(device_type)) @@ -135,7 +147,6 @@ class NetboxClient: @staticmethod def calculate_interface_speed(interface: Interfaces) -> int | None: """Calculate the interface speed in bits per second.""" - type_parts = interface.type.value.split("-") if "gbase" in type_parts[0]: return int("".join(filter(str.isdigit, type_parts[0]))) * 1000000 @@ -143,7 +154,6 @@ class NetboxClient: def create_device(self, device_name: str, site_tier: str) -> Devices: """Create a new device in Netbox.""" - # Get device type id tier_info = TierInfo().get_module_by_name(f"Tier{site_tier}") device_type = self.netbox.dcim.device_types.get(model=tier_info.device_type) @@ -156,7 +166,10 @@ class NetboxClient: # Create new device device = self.netbox.dcim.devices.create( - name=device_name, device_type=device_type.id, role=device_role.id, site=device_site.id + name=device_name, + device_type=device_type.id, + role=device_role.id, + site=device_site.id, ) module_bays = list(self.netbox.dcim.module_bays.filter(device_id=device.id)) card_type = self.netbox.dcim.module_types.get(model=tier_info.module_type) @@ -183,7 +196,11 @@ class NetboxClient: self.netbox.dcim.devices.get(name=device_name).delete() def attach_interface_to_lag( - self, device_name: str, lag_name: str, iface_name: str, description: str | None = None + self, + device_name: str, + lag_name: str, + iface_name: str, + description: str | None = None, ) -> Interfaces: """Assign a given interface to a :term:`LAG`. @@ -196,8 +213,9 @@ class NetboxClient: # Assign interface to LAG, ensuring it doesn't already belong to a LAG if iface.lag: + msg = f"The interface: {iface_name} on device: {device_name} already belongs to a LAG: {iface.lag.name}." raise WorkflowStateError( - f"The interface: {iface_name} on device: {device_name} already belongs to a LAG: {iface.lag.name}." + msg, ) iface.lag = lag.id @@ -210,13 +228,13 @@ class NetboxClient: def reserve_interface(self, device_name: str, iface_name: str) -> Interfaces: """Reserve an interface by enabling it.""" - # First get interface from device interface = self.get_interface_by_name_and_device(iface_name, device_name) # Check if interface is reserved if interface.enabled: - raise WorkflowStateError(f"The interface: {iface_name} on device: {device_name} is already reserved.") + msg = f"The interface: {iface_name} on device: {device_name} is already reserved." + raise WorkflowStateError(msg) # Reserve interface by enabling it interface.enabled = True @@ -226,13 +244,13 @@ class NetboxClient: def allocate_interface(self, device_name: str, iface_name: str) -> Interfaces: """Allocate an interface by marking it as connected.""" - # First get interface from device interface = self.get_interface_by_name_and_device(iface_name, device_name) # Check if interface is reserved if interface.mark_connected: - raise WorkflowStateError(f"The interface: {iface_name} on device: {device_name} is already allocated.") + msg = f"The interface: {iface_name} on device: {device_name} is already allocated." + raise WorkflowStateError(msg) # Allocate interface by marking it as connected interface.mark_connected = True @@ -242,7 +260,6 @@ class NetboxClient: def free_interface(self, device_name: str, iface_name: str) -> Interfaces: """Free interface by marking disconnect and disable it.""" - # First get interface from device interface = self.get_interface_by_name_and_device(iface_name, device_name) interface.mark_connected = False @@ -257,15 +274,16 @@ class NetboxClient: device = self.get_device_by_name(device_name) lag = self.netbox.dcim.interfaces.get(device_id=device.id, name=lag_name) for interface in self.netbox.dcim.interfaces.filter( - device_id=device.id, lag_id=lag.id, enabled=False, mark_connected=False + device_id=device.id, + lag_id=lag.id, + enabled=False, + mark_connected=False, ): interface.lag = None interface.save() - return def get_available_lags(self, router_id: UUID) -> list[str]: """Return all available :term:`LAG`s not assigned to a device.""" - router_name = Router.from_subscription(router_id).router.router_fqdn device = self.get_device_by_name(router_name) @@ -283,17 +301,18 @@ class NetboxClient: @staticmethod def calculate_speed_bits_per_sec(speed: str) -> int: """Extract the numeric part from the speed.""" - numeric_part = int("".join(filter(str.isdigit, speed))) # Convert to bits per second return numeric_part * 1000000 def get_available_interfaces(self, router_id: UUID | UUIDstr, speed: str) -> Interfaces: """Return all available interfaces of a device filtered by speed.""" - router = Router.from_subscription(router_id).router.router_fqdn device = self.get_device_by_name(router) speed_bps = self.calculate_speed_bits_per_sec(speed) return self.netbox.dcim.interfaces.filter( - device=device.name, enabled=False, mark_connected=False, speed=speed_bps + device=device.name, + enabled=False, + mark_connected=False, + speed=speed_bps, ) diff --git a/gso/services/provisioning_proxy.py b/gso/services/provisioning_proxy.py index c36c5a7df7752eaa2f765eba802482051925157e..96ac9fe6d94ae5410f9ef98dce23d66dff30bc0d 100644 --- a/gso/services/provisioning_proxy.py +++ b/gso/services/provisioning_proxy.py @@ -52,7 +52,6 @@ def _send_request(operation: CUDOperation, endpoint: str, parameters: dict, call """ oss = settings.load_oss_params() pp_params = oss.PROVISIONING_PROXY - assert pp_params # Build up a callback URL of the Provisioning Proxy to return its results to. callback_url = f"{oss.GENERAL.public_hostname}{callback_route}" @@ -82,7 +81,11 @@ _send_delete = partial(_send_request, CUDOperation.DELETE) def provision_router( - subscription: RouterProvisioning, process_id: UUIDstr, callback_route: str, tt_number: str, dry_run: bool = True + subscription: RouterProvisioning, + process_id: UUIDstr, + callback_route: str, + tt_number: str, + dry_run: bool = True, ) -> None: """Provision a new router using :term:`LSO`. @@ -149,7 +152,11 @@ def provision_ip_trunk( def check_ip_trunk( - subscription: IptrunkProvisioning, process_id: UUIDstr, callback_route: str, tt_number: str, check_name: str + subscription: IptrunkProvisioning, + process_id: UUIDstr, + callback_route: str, + tt_number: str, + check_name: str, ) -> None: """Provision an IP trunk service using :term:`LSO`. @@ -175,7 +182,11 @@ def check_ip_trunk( def deprovision_ip_trunk( - subscription: Iptrunk, process_id: UUIDstr, callback_route: str, tt_number: str, dry_run: bool = True + subscription: Iptrunk, + process_id: UUIDstr, + callback_route: str, + tt_number: str, + dry_run: bool = True, ) -> None: """Deprovision an IP trunk service using :term:`LSO`. @@ -298,6 +309,10 @@ def pp_interaction(provisioning_step: Step) -> StepList: """ return ( begin - >> callback_step(name=provisioning_step.name, action_step=provisioning_step, validate_step=_evaluate_pp_results) + >> callback_step( + name=provisioning_step.name, + action_step=provisioning_step, + validate_step=_evaluate_pp_results, + ) >> _show_pp_results ) diff --git a/gso/services/subscriptions.py b/gso/services/subscriptions.py index 42c57eb244ad20e3c4eaf6dcf27345ce119b9109..4b8fc92e395cccc33d0f7ec0cd7063c846693974 100644 --- a/gso/services/subscriptions.py +++ b/gso/services/subscriptions.py @@ -48,10 +48,12 @@ def get_active_subscriptions( results = query.with_entities(*dynamic_fields).all() - return [dict(zip(includes, result)) for result in results] + return [dict(zip(includes, result, strict=True)) for result in results] -def get_active_site_subscriptions(includes: list[str] | None = None) -> list[SubscriptionType]: +def get_active_site_subscriptions( + includes: list[str] | None = None, +) -> list[SubscriptionType]: """Retrieve active subscriptions specifically for sites. :param includes: The fields to be included in the returned Subscription objects. @@ -63,7 +65,9 @@ def get_active_site_subscriptions(includes: list[str] | None = None) -> list[Sub return get_active_subscriptions(product_type=ProductType.SITE, includes=includes) -def get_active_router_subscriptions(includes: list[str] | None = None) -> list[SubscriptionType]: +def get_active_router_subscriptions( + includes: list[str] | None = None, +) -> list[SubscriptionType]: """Retrieve active subscriptions specifically for routers. :param includes: The fields to be included in the returned Subscription objects. @@ -120,7 +124,8 @@ def count_incomplete_validate_products() -> int: The count of incomplete 'validate_products' processes. """ return ProcessTable.query.filter( - ProcessTable.workflow_name == "validate_products", ProcessTable.last_status != "completed" + ProcessTable.workflow_name == "validate_products", + ProcessTable.last_status != "completed", ).count() diff --git a/gso/utils/exceptions.py b/gso/utils/exceptions.py index 21c127e88b3144d43eb6474e8a890881f36135b0..541eb0c6d0f9f129df47fae4757f961ad8200498 100644 --- a/gso/utils/exceptions.py +++ b/gso/utils/exceptions.py @@ -1,10 +1,6 @@ class NotFoundError(Exception): """Exception raised for not found search.""" - pass - class WorkflowStateError(Exception): """Exception raised on problems during workflow.""" - - pass diff --git a/gso/utils/helpers.py b/gso/utils/helpers.py index b0f493f13662a912d5414fe65860072ec711ce03..983643305141fc1fc96d51cc4b1ecf1cdb9f28b8 100644 --- a/gso/utils/helpers.py +++ b/gso/utils/helpers.py @@ -52,11 +52,13 @@ def available_interfaces_choices(router_id: UUID, speed: str) -> Choice | None: interface["name"]: f"{interface['name']} - {interface['module']['display']} - {interface['description']}" for interface in NetboxClient().get_available_interfaces(router_id, speed) } - return Choice("ae member", zip(interfaces.keys(), interfaces.items())) # type: ignore[arg-type] + return Choice("ae member", zip(interfaces.keys(), interfaces.items(), strict=True)) # type: ignore[arg-type] def available_interfaces_choices_including_current_members( - router_id: UUID | UUIDstr, speed: str, interfaces: list[IptrunkInterfaceBlock] + router_id: UUID | UUIDstr, + speed: str, + interfaces: list[IptrunkInterfaceBlock], ) -> Choice | None: """Return a list of available interfaces for a given router and speed including the current members. @@ -70,16 +72,17 @@ def available_interfaces_choices_including_current_members( available_interfaces.extend( [ NetboxClient().get_interface_by_name_and_device( - interface.interface_name, Router.from_subscription(router_id).router.router_fqdn + interface.interface_name, + Router.from_subscription(router_id).router.router_fqdn, ) for interface in interfaces - ] + ], ) options = { interface["name"]: f"{interface['name']} - {interface['module']['display']} - {interface['description']}" for interface in available_interfaces } - return Choice("ae member", zip(options.keys(), options.items())) # type: ignore[arg-type] + return Choice("ae member", zip(options.keys(), options.items(), strict=True)) # type: ignore[arg-type] def available_lags_choices(router_id: UUID) -> Choice | None: @@ -88,11 +91,10 @@ def available_lags_choices(router_id: UUID) -> Choice | None: For Nokia routers, return a list of available lags. For Juniper routers, return a string. """ - if Router.from_subscription(router_id).router.router_vendor != RouterVendor.NOKIA: return None side_a_ae_iface_list = NetboxClient().get_available_lags(router_id) - return Choice("ae iface", zip(side_a_ae_iface_list, side_a_ae_iface_list)) # type: ignore[arg-type] + return Choice("ae iface", zip(side_a_ae_iface_list, side_a_ae_iface_list, strict=True)) # type: ignore[arg-type] def get_router_vendor(router_id: UUID) -> str: @@ -118,7 +120,7 @@ def iso_from_ipv4(ipv4_address: IPv4Address) -> str: padded_octets = [f"{x:>03}" for x in str(ipv4_address).split(".")] joined_octets = "".join(padded_octets) re_split = ".".join(re.findall("....", joined_octets)) - return ".".join(["49.51e5.0001", re_split, "00"]) + return f"49.51e5.0001.{re_split}.00" def validate_router_in_netbox(subscription_id: UUIDstr) -> UUIDstr | None: @@ -136,7 +138,8 @@ def validate_router_in_netbox(subscription_id: UUIDstr) -> UUIDstr | None: if router.router_vendor == RouterVendor.NOKIA: device = NetboxClient().get_device_by_name(router.router_fqdn) if not device: - raise ValueError("The selected router does not exist in Netbox.") + msg = "The selected router does not exist in Netbox." + raise ValueError(msg) return subscription_id @@ -153,14 +156,16 @@ def validate_iptrunk_unique_interface(interfaces: list[LAGMember]) -> list[LAGMe """ interface_names = [member.interface_name for member in interfaces] if len(interface_names) != len(set(interface_names)): - raise ValueError("Interfaces must be unique.") + msg = "Interfaces must be unique." + raise ValueError(msg) return interfaces def validate_site_fields_is_unique(field_name: str, value: str | int) -> str | int: """Validate that a site field is unique.""" if len(get_active_subscriptions_by_field_and_value(field_name, str(value))) > 0: - raise ValueError(f"{field_name} must be unique") + msg = f"{field_name} must be unique" + raise ValueError(msg) return value @@ -169,8 +174,9 @@ def validate_ipv4_or_ipv6(value: str) -> str: try: ipaddress.ip_address(value) return value - except ValueError: - raise ValueError("Enter a valid IPv4 or IPv6 address.") + except ValueError as e: + msg = "Enter a valid IPv4 or IPv6 address." + raise ValueError(msg) from e def validate_country_code(country_code: str) -> str: @@ -178,8 +184,9 @@ def validate_country_code(country_code: str) -> str: try: pycountry.countries.lookup(country_code) return country_code - except LookupError: - raise ValueError("Invalid or non-existent country code, it must be in ISO 3166-1 alpha-2 format.") + except LookupError as e: + msg = "Invalid or non-existent country code, it must be in ISO 3166-1 alpha-2 format." + raise ValueError(msg) from e def validate_site_name(site_name: str) -> str: @@ -189,8 +196,8 @@ def validate_site_name(site_name: str) -> str: """ pattern = re.compile(r"^[A-Z]{3}[0-9]?$") if not pattern.match(site_name): + msg = "Enter a valid site name. It must consist of three uppercase letters (A-Z) followed by an optional single digit (0-9)." raise ValueError( - "Enter a valid site name. It must consist of three uppercase letters (A-Z) followed by an optional single " - "digit (0-9)." + msg, ) return site_name diff --git a/gso/workflows/iptrunk/create_iptrunk.py b/gso/workflows/iptrunk/create_iptrunk.py index ff83e7c3a464b662ed36bebad5e2546fa48376b0..b755b72a6accc7901f9b49a2af058b88ec3b6a04 100644 --- a/gso/workflows/iptrunk/create_iptrunk.py +++ b/gso/workflows/iptrunk/create_iptrunk.py @@ -10,7 +10,11 @@ from orchestrator.workflows.utils import wrap_create_initial_input_form from pydantic import validator from pynetbox.models.dcim import Interfaces -from gso.products.product_blocks.iptrunk import IptrunkInterfaceBlockInactive, IptrunkType, PhyPortCapacity +from gso.products.product_blocks.iptrunk import ( + IptrunkInterfaceBlockInactive, + IptrunkType, + PhyPortCapacity, +) from gso.products.product_blocks.router import RouterVendor from gso.products.product_types.iptrunk import IptrunkInactive, IptrunkProvisioning from gso.products.product_types.router import Router @@ -51,7 +55,7 @@ def initial_input_form_generator(product_name: str) -> FormGenerator: initial_user_input = yield CreateIptrunkForm - router_enum_a = Choice("Select a router", zip(routers.keys(), routers.items())) # type: ignore[arg-type] + router_enum_a = Choice("Select a router", zip(routers.keys(), routers.items(), strict=True)) # type: ignore[arg-type] class SelectRouterSideA(FormPage): class Config: @@ -73,7 +77,8 @@ def initial_input_form_generator(product_name: str) -> FormGenerator: class NokiaLAGMemberA(LAGMember): interface_name: available_interfaces_choices( # type: ignore[valid-type] - router_a, initial_user_input.iptrunk_speed + router_a, + initial_user_input.iptrunk_speed, ) class NokiaAeMembersA(UniqueConstrainedList[NokiaLAGMemberA]): @@ -98,7 +103,7 @@ def initial_input_form_generator(product_name: str) -> FormGenerator: user_input_side_a = yield CreateIptrunkSideAForm # Remove the selected router for side A, to prevent any loops routers.pop(str(router_a)) - router_enum_b = Choice("Select a router", zip(routers.keys(), routers.items())) # type: ignore[arg-type] + router_enum_b = Choice("Select a router", zip(routers.keys(), routers.items(), strict=True)) # type: ignore[arg-type] class SelectRouterSideB(FormPage): class Config: @@ -117,7 +122,8 @@ def initial_input_form_generator(product_name: str) -> FormGenerator: class NokiaLAGMemberB(LAGMember): interface_name: available_interfaces_choices( # type: ignore[valid-type] - router_b, initial_user_input.iptrunk_speed + router_b, + initial_user_input.iptrunk_speed, ) class NokiaAeMembersB(UniqueConstrainedList): @@ -165,10 +171,12 @@ def create_subscription(product: UUIDstr, customer: UUIDstr) -> State: @step("Get information from IPAM") def get_info_from_ipam(subscription: IptrunkProvisioning) -> State: subscription.iptrunk.iptrunk_ipv4_network = infoblox.allocate_v4_network( - "TRUNK", subscription.iptrunk.iptrunk_description + "TRUNK", + subscription.iptrunk.iptrunk_description, ) subscription.iptrunk.iptrunk_ipv6_network = infoblox.allocate_v6_network( - "TRUNK", subscription.iptrunk.iptrunk_description + "TRUNK", + subscription.iptrunk.iptrunk_description, ) return {"subscription": subscription} @@ -203,7 +211,7 @@ def initialize_subscription( subscription.iptrunk.iptrunk_sides[0].iptrunk_side_ae_geant_a_sid = side_a_ae_geant_a_sid for member in side_a_ae_members: subscription.iptrunk.iptrunk_sides[0].iptrunk_side_ae_members.append( - IptrunkInterfaceBlockInactive.new(subscription_id=uuid4(), **member) + IptrunkInterfaceBlockInactive.new(subscription_id=uuid4(), **member), ) subscription.iptrunk.iptrunk_sides[1].iptrunk_side_node = Router.from_subscription(side_b_node_id).router @@ -211,7 +219,7 @@ def initialize_subscription( subscription.iptrunk.iptrunk_sides[1].iptrunk_side_ae_geant_a_sid = side_b_ae_geant_a_sid for member in side_b_ae_members: subscription.iptrunk.iptrunk_sides[1].iptrunk_side_ae_members.append( - IptrunkInterfaceBlockInactive.new(subscription_id=uuid4(), **member) + IptrunkInterfaceBlockInactive.new(subscription_id=uuid4(), **member), ) subscription.description = f"IP trunk, geant_s_sid:{geant_s_sid}" @@ -222,7 +230,10 @@ def initialize_subscription( @step("Provision IP trunk interface [DRY RUN]") def provision_ip_trunk_iface_dry( - subscription: IptrunkProvisioning, callback_route: str, process_id: UUIDstr, tt_number: str + subscription: IptrunkProvisioning, + callback_route: str, + process_id: UUIDstr, + tt_number: str, ) -> State: provisioning_proxy.provision_ip_trunk(subscription, process_id, callback_route, tt_number, "trunk_interface", True) @@ -231,7 +242,10 @@ def provision_ip_trunk_iface_dry( @step("Provision IP trunk interface [FOR REAL]") def provision_ip_trunk_iface_real( - subscription: IptrunkProvisioning, callback_route: str, process_id: UUIDstr, tt_number: str + subscription: IptrunkProvisioning, + callback_route: str, + process_id: UUIDstr, + tt_number: str, ) -> State: provisioning_proxy.provision_ip_trunk(subscription, process_id, callback_route, tt_number, "trunk_interface", False) @@ -240,7 +254,10 @@ def provision_ip_trunk_iface_real( @step("Check IP connectivity of the trunk") def check_ip_trunk_connectivity( - subscription: IptrunkProvisioning, callback_route: str, process_id: UUIDstr, tt_number: str + subscription: IptrunkProvisioning, + callback_route: str, + process_id: UUIDstr, + tt_number: str, ) -> State: provisioning_proxy.check_ip_trunk(subscription, process_id, callback_route, tt_number, "ping") @@ -249,7 +266,10 @@ def check_ip_trunk_connectivity( @step("Provision IP trunk ISIS interface [DRY RUN]") def provision_ip_trunk_isis_iface_dry( - subscription: IptrunkProvisioning, callback_route: str, process_id: UUIDstr, tt_number: str + subscription: IptrunkProvisioning, + callback_route: str, + process_id: UUIDstr, + tt_number: str, ) -> State: provisioning_proxy.provision_ip_trunk(subscription, process_id, callback_route, tt_number, "isis_interface") @@ -258,7 +278,10 @@ def provision_ip_trunk_isis_iface_dry( @step("Provision IP trunk ISIS interface [FOR REAL]") def provision_ip_trunk_isis_iface_real( - subscription: IptrunkProvisioning, callback_route: str, process_id: UUIDstr, tt_number: str + subscription: IptrunkProvisioning, + callback_route: str, + process_id: UUIDstr, + tt_number: str, ) -> State: provisioning_proxy.provision_ip_trunk(subscription, process_id, callback_route, tt_number, "isis_interface", False) @@ -267,7 +290,10 @@ def provision_ip_trunk_isis_iface_real( @step("Check ISIS adjacency") def check_ip_trunk_isis( - subscription: IptrunkProvisioning, callback_route: str, process_id: UUIDstr, tt_number: str + subscription: IptrunkProvisioning, + callback_route: str, + process_id: UUIDstr, + tt_number: str, ) -> State: provisioning_proxy.check_ip_trunk(subscription, process_id, callback_route, tt_number, "isis") @@ -277,7 +303,6 @@ def check_ip_trunk_isis( @step("NextBox integration") def reserve_interfaces_in_netbox(subscription: IptrunkProvisioning) -> State: """Create the LAG interfaces in NetBox and attach the lag interfaces to the physical interfaces.""" - nbclient = NetboxClient() for trunk_side in subscription.iptrunk.iptrunk_sides: if trunk_side.iptrunk_side_node.router_vendor == RouterVendor.NOKIA: diff --git a/gso/workflows/iptrunk/migrate_iptrunk.py b/gso/workflows/iptrunk/migrate_iptrunk.py index 0d238437f4ec9f8016c0e693be1ea8fd201c13ff..03744c83d1a2505c7ce5702023017358034cb456 100644 --- a/gso/workflows/iptrunk/migrate_iptrunk.py +++ b/gso/workflows/iptrunk/migrate_iptrunk.py @@ -50,7 +50,7 @@ def initial_input_form_generator(subscription_id: UUIDstr) -> FormGenerator: replaced_side_enum = Choice( "Select the side of the IP trunk to be replaced", - zip(sides_dict.keys(), sides_dict.items()), # type: ignore[arg-type] + zip(sides_dict.keys(), sides_dict.items(), strict=True), # type: ignore[arg-type] ) class IPTrunkMigrateForm(FormPage): @@ -81,7 +81,7 @@ def initial_input_form_generator(subscription_id: UUIDstr) -> FormGenerator: continue routers[str(router_id)] = router["description"] - new_router_enum = Choice("Select a new router", zip(routers.keys(), routers.items())) # type: ignore[arg-type] + new_router_enum = Choice("Select a new router", zip(routers.keys(), routers.items(), strict=True)) # type: ignore[arg-type] class NewSideIPTrunkRouterForm(FormPage): class Config: @@ -97,7 +97,8 @@ def initial_input_form_generator(subscription_id: UUIDstr) -> FormGenerator: class NokiaLAGMember(LAGMember): interface_name: available_interfaces_choices( # type: ignore[valid-type] - new_router, subscription.iptrunk.iptrunk_speed + new_router, + subscription.iptrunk.iptrunk_speed, ) class NokiaAeMembers(UniqueConstrainedList[NokiaLAGMember]): @@ -120,7 +121,10 @@ def initial_input_form_generator(subscription_id: UUIDstr) -> FormGenerator: else 1 ) existing_lag_ae_members = [ - {"interface_name": iface.interface_name, "interface_description": iface.interface_description} + { + "interface_name": iface.interface_name, + "interface_description": iface.interface_description, + } for iface in subscription.iptrunk.iptrunk_sides[replace_index].iptrunk_side_ae_members ] @@ -137,7 +141,8 @@ def initial_input_form_generator(subscription_id: UUIDstr) -> FormGenerator: if get_router_vendor(new_router) == RouterVendor.JUNIPER: juniper_lag_re = re.compile("^ae\\d{1,2}$") if not juniper_lag_re.match(new_lag_interface): - raise ValueError("Invalid LAG name, please try again.") + msg = "Invalid LAG name, please try again." + raise ValueError(msg) return new_lag_interface new_side_input = yield NewSideIPTrunkForm @@ -277,10 +282,7 @@ def confirm_continue_move_fiber() -> FormGenerator: class Config: title = "Please confirm before continuing" - info_label: Label = ( - "New Trunk interface has been deployed, " - "wait for the physical connection to be moved." # type: ignore[assignment] - ) + info_label: Label = "New Trunk interface has been deployed, wait for the physical connection to be moved." # type: ignore[assignment] yield ProvisioningResultPage @@ -328,9 +330,7 @@ def confirm_continue_restore_isis() -> FormGenerator: class Config: title = "Please confirm before continuing" - info_label: Label = ( - "ISIS config has been deployed, confirm if you want to restore the old metric." # type: ignore[assignment] - ) + info_label: Label = "ISIS config has been deployed, confirm if you want to restore the old metric." # type: ignore[assignment] yield ProvisioningResultPage @@ -339,7 +339,11 @@ def confirm_continue_restore_isis() -> FormGenerator: @step("Restore ISIS metric to original value") def restore_isis_metric( - subscription: Iptrunk, process_id: UUIDstr, callback_route: str, tt_number: str, old_isis_metric: int + subscription: Iptrunk, + process_id: UUIDstr, + callback_route: str, + tt_number: str, + old_isis_metric: int, ) -> State: subscription.iptrunk.iptrunk_isis_metric = old_isis_metric provisioning_proxy.provision_ip_trunk(subscription, process_id, callback_route, tt_number, "isis_interface", False) @@ -432,7 +436,7 @@ def update_subscription_model( # And update the list to only include the new member interfaces for member in new_lag_member_interfaces: subscription.iptrunk.iptrunk_sides[0].iptrunk_side_ae_members.append( - IptrunkInterfaceBlock.new(subscription_id=uuid4(), **member) + IptrunkInterfaceBlock.new(subscription_id=uuid4(), **member), ) return {"subscription": subscription, "old_side_data": old_side_data} @@ -490,11 +494,15 @@ def update_netbox( if old_side_data["iptrunk_side_node"]["router_vendor"] == RouterVendor.NOKIA: # Set interfaces to free for iface in old_side_data["iptrunk_side_ae_members"]: - nbclient.free_interface(old_side_data["iptrunk_side_node"]["router_fqdn"], iface["interface_name"]) + nbclient.free_interface( + old_side_data["iptrunk_side_node"]["router_fqdn"], + iface["interface_name"], + ) # Delete LAG interfaces nbclient.delete_interface( - old_side_data["iptrunk_side_node"]["router_fqdn"], old_side_data["iptrunk_side_ae_iface"] + old_side_data["iptrunk_side_node"]["router_fqdn"], + old_side_data["iptrunk_side_ae_iface"], ) return {"subscription": subscription} diff --git a/gso/workflows/iptrunk/modify_isis_metric.py b/gso/workflows/iptrunk/modify_isis_metric.py index 910bec4fcfb65fc463bdbd3042f003cda329460c..9678e292950af550393b7889ef74e0590ceade0e 100644 --- a/gso/workflows/iptrunk/modify_isis_metric.py +++ b/gso/workflows/iptrunk/modify_isis_metric.py @@ -31,7 +31,10 @@ def modify_iptrunk_subscription(subscription: Iptrunk, isis_metric: int) -> Stat @step("Provision IP trunk ISIS interface [DRY RUN]") def provision_ip_trunk_isis_iface_dry( - subscription: Iptrunk, process_id: UUIDstr, callback_route: str, tt_number: str + subscription: Iptrunk, + process_id: UUIDstr, + callback_route: str, + tt_number: str, ) -> State: provisioning_proxy.provision_ip_trunk(subscription, process_id, callback_route, tt_number, "isis_interface") @@ -40,7 +43,10 @@ def provision_ip_trunk_isis_iface_dry( @step("Provision IP trunk ISIS interface [FOR REAL]") def provision_ip_trunk_isis_iface_real( - subscription: Iptrunk, process_id: UUIDstr, callback_route: str, tt_number: str + subscription: Iptrunk, + process_id: UUIDstr, + callback_route: str, + tt_number: str, ) -> State: provisioning_proxy.provision_ip_trunk(subscription, process_id, callback_route, tt_number, "isis_interface", False) diff --git a/gso/workflows/iptrunk/modify_trunk_interface.py b/gso/workflows/iptrunk/modify_trunk_interface.py index 908b20e295db94d50b4a52627a924890a98e0c0f..9978f498a3cc4d3f99b31eb64a2b4f82e6d3aa07 100644 --- a/gso/workflows/iptrunk/modify_trunk_interface.py +++ b/gso/workflows/iptrunk/modify_trunk_interface.py @@ -1,5 +1,4 @@ import ipaddress -from typing import List, Type from uuid import uuid4 from orchestrator.forms import FormPage, ReadOnlyField @@ -12,7 +11,11 @@ from orchestrator.workflows.utils import wrap_modify_initial_input_form from pydantic import validator from pydantic_forms.validators import Label -from gso.products.product_blocks.iptrunk import IptrunkInterfaceBlock, IptrunkType, PhyPortCapacity +from gso.products.product_blocks.iptrunk import ( + IptrunkInterfaceBlock, + IptrunkType, + PhyPortCapacity, +) from gso.products.product_blocks.router import RouterVendor from gso.products.product_types.iptrunk import Iptrunk from gso.services import provisioning_proxy @@ -26,7 +29,7 @@ from gso.utils.helpers import ( ) -def initialize_ae_members(subscription: Iptrunk, initial_user_input: dict, side_index: int) -> Type[LAGMember]: +def initialize_ae_members(subscription: Iptrunk, initial_user_input: dict, side_index: int) -> type[LAGMember]: """Initialize the list of AE members.""" router = subscription.iptrunk.iptrunk_sides[side_index].iptrunk_side_node iptrunk_minimum_link = initial_user_input["iptrunk_minimum_links"] @@ -34,12 +37,19 @@ def initialize_ae_members(subscription: Iptrunk, initial_user_input: dict, side_ iptrunk_speed = initial_user_input["iptrunk_speed"] class NokiaLAGMember(LAGMember): - interface_name: available_interfaces_choices_including_current_members( # type: ignore[valid-type] - router.owner_subscription_id, - iptrunk_speed, - subscription.iptrunk.iptrunk_sides[side_index].iptrunk_side_ae_members, - ) if iptrunk_speed == subscription.iptrunk.iptrunk_speed else ( - available_interfaces_choices(router.owner_subscription_id, initial_user_input["iptrunk_speed"]) + interface_name: ( + available_interfaces_choices_including_current_members( # type: ignore[valid-type] + router.owner_subscription_id, + iptrunk_speed, + subscription.iptrunk.iptrunk_sides[side_index].iptrunk_side_ae_members, + ) + if iptrunk_speed == subscription.iptrunk.iptrunk_speed + else ( + available_interfaces_choices( + router.owner_subscription_id, + initial_user_input["iptrunk_speed"], + ) + ) ) class NokiaAeMembers(UniqueConstrainedList[NokiaLAGMember]): @@ -136,7 +146,10 @@ def modify_iptrunk_subscription( removed_ae_members = {} for side_index in range(2): previous_ae_members[side_index] = [ - {"interface_name": member.interface_name, "interface_description": member.interface_description} + { + "interface_name": member.interface_name, + "interface_description": member.interface_description, + } for member in subscription.iptrunk.iptrunk_sides[side_index].iptrunk_side_ae_members ] for side_index in range(2): @@ -157,14 +170,14 @@ def modify_iptrunk_subscription( # And update the list to only include the new member interfaces for member in side_a_ae_members: subscription.iptrunk.iptrunk_sides[0].iptrunk_side_ae_members.append( - IptrunkInterfaceBlock.new(subscription_id=uuid4(), **member) + IptrunkInterfaceBlock.new(subscription_id=uuid4(), **member), ) subscription.iptrunk.iptrunk_sides[1].iptrunk_side_ae_geant_a_sid = side_b_ae_geant_a_sid subscription.iptrunk.iptrunk_sides[1].iptrunk_side_ae_members.clear() for member in side_b_ae_members: subscription.iptrunk.iptrunk_sides[1].iptrunk_side_ae_members.append( - IptrunkInterfaceBlock.new(subscription_id=uuid4(), **member) + IptrunkInterfaceBlock.new(subscription_id=uuid4(), **member), ) subscription.description = f"IP trunk, geant_s_sid:{geant_s_sid}" @@ -178,10 +191,20 @@ def modify_iptrunk_subscription( @step("Provision IP trunk interface [DRY RUN]") def provision_ip_trunk_iface_dry( - subscription: Iptrunk, process_id: UUIDstr, callback_route: str, tt_number: str, removed_ae_members: List[str] + subscription: Iptrunk, + process_id: UUIDstr, + callback_route: str, + tt_number: str, + removed_ae_members: list[str], ) -> State: provisioning_proxy.provision_ip_trunk( - subscription, process_id, callback_route, tt_number, "trunk_interface", True, removed_ae_members + subscription, + process_id, + callback_route, + tt_number, + "trunk_interface", + True, + removed_ae_members, ) return {"subscription": subscription} @@ -189,10 +212,20 @@ def provision_ip_trunk_iface_dry( @step("Provision IP trunk interface [FOR REAL]") def provision_ip_trunk_iface_real( - subscription: Iptrunk, process_id: UUIDstr, callback_route: str, tt_number: str, removed_ae_members: List[str] + subscription: Iptrunk, + process_id: UUIDstr, + callback_route: str, + tt_number: str, + removed_ae_members: list[str], ) -> State: provisioning_proxy.provision_ip_trunk( - subscription, process_id, callback_route, tt_number, "trunk_interface", False, removed_ae_members + subscription, + process_id, + callback_route, + tt_number, + "trunk_interface", + False, + removed_ae_members, ) return {"subscription": subscription} @@ -201,7 +234,7 @@ def provision_ip_trunk_iface_real( @step("Update interfaces in Netbox. Reserving interfaces.") def update_interfaces_in_netbox(subscription: Iptrunk, removed_ae_members: dict, previous_ae_members: dict) -> State: nbclient = NetboxClient() - for side in range(0, 2): + for side in range(2): if subscription.iptrunk.iptrunk_sides[side].iptrunk_side_node.router_vendor == RouterVendor.NOKIA: lag_interface = subscription.iptrunk.iptrunk_sides[side].iptrunk_side_ae_iface router_name = subscription.iptrunk.iptrunk_sides[side].iptrunk_side_node.router_fqdn @@ -238,8 +271,7 @@ def allocate_interfaces_in_netbox(subscription: Iptrunk, previous_ae_members: di attach the lag interfaces to the physical interfaces detach old ones from the LAG. """ - - for side in range(0, 2): + for side in range(2): nbclient = NetboxClient() if subscription.iptrunk.iptrunk_sides[side].iptrunk_side_node.router_vendor == RouterVendor.NOKIA: for interface in subscription.iptrunk.iptrunk_sides[side].iptrunk_side_ae_members: diff --git a/gso/workflows/iptrunk/terminate_iptrunk.py b/gso/workflows/iptrunk/terminate_iptrunk.py index 8bad1c40be738dc532a24688776c7f4fff2677fb..97e9bbb5e13bff0c843652705e31c1d22ea6be09 100644 --- a/gso/workflows/iptrunk/terminate_iptrunk.py +++ b/gso/workflows/iptrunk/terminate_iptrunk.py @@ -5,7 +5,12 @@ from orchestrator.forms.validators import Label from orchestrator.targets import Target from orchestrator.types import FormGenerator, State, SubscriptionLifecycle, UUIDstr from orchestrator.workflow import StepList, conditional, done, init, step, workflow -from orchestrator.workflows.steps import resync, set_status, store_process_subscription, unsync +from orchestrator.workflows.steps import ( + resync, + set_status, + store_process_subscription, + unsync, +) from orchestrator.workflows.utils import wrap_modify_initial_input_form from gso.products.product_blocks.router import RouterVendor @@ -32,7 +37,10 @@ def initial_input_form_generator() -> FormGenerator: @step("Drain traffic from trunk") def drain_traffic_from_ip_trunk( - subscription: Iptrunk, process_id: UUIDstr, callback_route: str, tt_number: str + subscription: Iptrunk, + process_id: UUIDstr, + callback_route: str, + tt_number: str, ) -> State: provisioning_proxy.provision_ip_trunk(subscription, process_id, callback_route, tt_number, "isis_interface", False) @@ -64,7 +72,10 @@ def free_interfaces_in_netbox(subscription: Iptrunk) -> State: for member in subscription.iptrunk.iptrunk_sides[side].iptrunk_side_ae_members: nbclient.free_interface(router_fqdn, member.interface_name) # Delete LAGs - nbclient.delete_interface(router_fqdn, subscription.iptrunk.iptrunk_sides[side].iptrunk_side_ae_iface) + nbclient.delete_interface( + router_fqdn, + subscription.iptrunk.iptrunk_sides[side].iptrunk_side_ae_iface, + ) return {"subscription": subscription} diff --git a/gso/workflows/router/create_router.py b/gso/workflows/router/create_router.py index 3f681a0266a2242ff80007ea4eb4769009142827..45d14e6c77927923495f3d6b1fb1d2f8043db0f5 100644 --- a/gso/workflows/router/create_router.py +++ b/gso/workflows/router/create_router.py @@ -11,7 +11,12 @@ from orchestrator.workflows.steps import resync, set_status, store_process_subsc from orchestrator.workflows.utils import wrap_create_initial_input_form from pydantic import validator -from gso.products.product_blocks.router import PortNumber, RouterRole, RouterVendor, generate_fqdn +from gso.products.product_blocks.router import ( + PortNumber, + RouterRole, + RouterVendor, + generate_fqdn, +) from gso.products.product_types.router import RouterInactive, RouterProvisioning from gso.products.product_types.site import Site from gso.services import infoblox, provisioning_proxy, subscriptions @@ -27,7 +32,7 @@ def _site_selector() -> Choice: site_subscriptions[str(site["subscription_id"])] = site["description"] # noinspection PyTypeChecker - return Choice("Select a site", zip(site_subscriptions.keys(), site_subscriptions.items())) # type: ignore[arg-type] + return Choice("Select a site", zip(site_subscriptions.keys(), site_subscriptions.items(), strict=True)) # type: ignore[arg-type] def initial_input_form_generator(product_name: str) -> FormGenerator: @@ -48,12 +53,14 @@ def initial_input_form_generator(product_name: str) -> FormGenerator: def hostname_must_be_available(cls, hostname: str, **kwargs: dict[str, Any]) -> str: router_site = kwargs["values"].get("router_site") if not router_site: - raise ValueError("Please select a site before setting the hostname.") + msg = "Please select a site before setting the hostname." + raise ValueError(msg) selected_site = Site.from_subscription(router_site).site input_fqdn = generate_fqdn(hostname, selected_site.site_name, selected_site.site_country_code) if not infoblox.hostname_available(f"lo0.{input_fqdn}"): - raise ValueError(f'FQDN "{input_fqdn}" is not available.') + msg = f'FQDN "{input_fqdn}" is not available.' + raise ValueError(msg) return hostname @@ -85,7 +92,9 @@ def initialize_subscription( subscription.router.router_vendor = router_vendor subscription.router.router_site = Site.from_subscription(router_site).site fqdn = generate_fqdn( - hostname, subscription.router.router_site.site_name, subscription.router.router_site.site_country_code + hostname, + subscription.router.router_site.site_name, + subscription.router.router_site.site_country_code, ) subscription.router.router_fqdn = fqdn subscription.router.router_role = router_role @@ -115,13 +124,16 @@ def ipam_allocate_ias_networks(subscription: RouterProvisioning) -> State: fqdn = subscription.router.router_fqdn subscription.router.router_si_ipv4_network = infoblox.allocate_v4_network( - "SI", f"SI for {fqdn} - {subscription.subscription_id}" + "SI", + f"SI for {fqdn} - {subscription.subscription_id}", ) subscription.router.router_ias_lt_ipv4_network = infoblox.allocate_v4_network( - "LT_IAS", f"LT for {fqdn} - {subscription.subscription_id}" + "LT_IAS", + f"LT for {fqdn} - {subscription.subscription_id}", ) subscription.router.router_ias_lt_ipv6_network = infoblox.allocate_v6_network( - "LT_IAS", f"LT for {fqdn} - {subscription.subscription_id}" + "LT_IAS", + f"LT for {fqdn} - {subscription.subscription_id}", ) return {"subscription": subscription} @@ -129,7 +141,10 @@ def ipam_allocate_ias_networks(subscription: RouterProvisioning) -> State: @step("Provision router [DRY RUN]") def provision_router_dry( - subscription: RouterProvisioning, process_id: UUIDstr, callback_route: str, tt_number: str + subscription: RouterProvisioning, + process_id: UUIDstr, + callback_route: str, + tt_number: str, ) -> State: provisioning_proxy.provision_router(subscription, process_id, callback_route, tt_number) @@ -138,7 +153,10 @@ def provision_router_dry( @step("Provision router [FOR REAL]") def provision_router_real( - subscription: RouterProvisioning, process_id: UUIDstr, callback_route: str, tt_number: str + subscription: RouterProvisioning, + process_id: UUIDstr, + callback_route: str, + tt_number: str, ) -> State: provisioning_proxy.provision_router(subscription, process_id, callback_route, tt_number, False) @@ -176,19 +194,19 @@ def verify_ipam_ias(subscription: RouterProvisioning) -> State: if not si_ipv4_network or str(subscription.subscription_id) not in si_ipv4_network.comment: new_state = { "ipam_si_warning": f"SI IPv4 network expected at {subscription.router.router_si_ipv4_network}, " - f"but it was not found or misconfigured, please investigate and adjust if necessary." + f"but it was not found or misconfigured, please investigate and adjust if necessary.", } if not ias_lt_ipv4_network or str(subscription.subscription_id) not in ias_lt_ipv4_network.comment: new_state = new_state | { "ipam_ias_lt_ipv4_warning": "IAS/LT IPv4 network expected at " f"{subscription.router.router_ias_lt_ipv4_network}, but it was not found or misconfigured, please " - "investigate and adjust if necessary." + "investigate and adjust if necessary.", } if not ias_lt_ipv6_network or str(subscription.subscription_id) not in ias_lt_ipv6_network.comment: new_state = new_state | { "ipam_ias_lt_ipv6_warning": f"IAS/LT IPv6 network expected at " f"{subscription.router.router_ias_lt_ipv6_network}, but it was not found or misconfigured, please " - "investigate and adjust if necessary." + "investigate and adjust if necessary.", } return new_state diff --git a/gso/workflows/router/terminate_router.py b/gso/workflows/router/terminate_router.py index 47d09b414c13b94cf93a836da241fcc3c957fa39..a0afa93faeda111e818c5771405dc0840c46c922 100644 --- a/gso/workflows/router/terminate_router.py +++ b/gso/workflows/router/terminate_router.py @@ -6,7 +6,12 @@ from orchestrator.forms.validators import Label from orchestrator.targets import Target from orchestrator.types import FormGenerator, SubscriptionLifecycle, UUIDstr from orchestrator.workflow import StepList, conditional, done, init, step, workflow -from orchestrator.workflows.steps import resync, set_status, store_process_subscription, unsync +from orchestrator.workflows.steps import ( + resync, + set_status, + store_process_subscription, + unsync, +) from orchestrator.workflows.utils import wrap_modify_initial_input_form from gso.products.product_blocks.router import RouterVendor diff --git a/gso/workflows/site/create_site.py b/gso/workflows/site/create_site.py index ae2e11c32c356d2a53987ea042b3fd21eb3a354c..6c3a034dccfcc406b682b70a5b7e4198803e2845 100644 --- a/gso/workflows/site/create_site.py +++ b/gso/workflows/site/create_site.py @@ -19,7 +19,7 @@ from gso.utils.helpers import ( ) -def initial_input_form_generator(product_name: str) -> FormGenerator: # noqa: C901 +def initial_input_form_generator(product_name: str) -> FormGenerator: class CreateSiteForm(FormPage): class Config: title = product_name diff --git a/gso/workflows/site/modify_site.py b/gso/workflows/site/modify_site.py index 15f1c6b45a3826b20a227bdd24b5361c456946fe..8fc105f1ae3de85116635fc1921404669e2b256c 100644 --- a/gso/workflows/site/modify_site.py +++ b/gso/workflows/site/modify_site.py @@ -2,7 +2,12 @@ from orchestrator.forms import FormPage from orchestrator.targets import Target from orchestrator.types import FormGenerator, State, SubscriptionLifecycle, UUIDstr from orchestrator.workflow import StepList, done, init, step, workflow -from orchestrator.workflows.steps import resync, set_status, store_process_subscription, unsync +from orchestrator.workflows.steps import ( + resync, + set_status, + store_process_subscription, + unsync, +) from orchestrator.workflows.utils import wrap_modify_initial_input_form from pydantic import validator from pydantic.fields import ModelField diff --git a/gso/workflows/site/terminate_site.py b/gso/workflows/site/terminate_site.py index 73a99e22e0d32a7abf0d1dda1314d80a6b911d7d..c9d5b662be4d5b3f570c3313d11a93d03dcfdca4 100644 --- a/gso/workflows/site/terminate_site.py +++ b/gso/workflows/site/terminate_site.py @@ -3,7 +3,12 @@ from orchestrator.forms.validators import Label from orchestrator.targets import Target from orchestrator.types import FormGenerator, SubscriptionLifecycle, UUIDstr from orchestrator.workflow import StepList, done, init, workflow -from orchestrator.workflows.steps import resync, set_status, store_process_subscription, unsync +from orchestrator.workflows.steps import ( + resync, + set_status, + store_process_subscription, + unsync, +) from orchestrator.workflows.utils import wrap_modify_initial_input_form from gso.products.product_types.site import Site diff --git a/gso/workflows/tasks/import_iptrunk.py b/gso/workflows/tasks/import_iptrunk.py index 04f583539ed364d87568fc04066a44e2a2d90141..b6b9d836be91e3d28530c4ef6f00f5f2ca306527 100644 --- a/gso/workflows/tasks/import_iptrunk.py +++ b/gso/workflows/tasks/import_iptrunk.py @@ -28,7 +28,7 @@ def _generate_routers() -> dict[str, str]: def initial_input_form_generator() -> FormGenerator: routers = _generate_routers() - router_enum = Choice("Select a router", zip(routers.keys(), routers.items())) # type: ignore[arg-type] + router_enum = Choice("Select a router", zip(routers.keys(), routers.items(), strict=True)) # type: ignore[arg-type] class CreateIptrunkForm(FormPage): class Config: diff --git a/gso/workflows/tasks/import_router.py b/gso/workflows/tasks/import_router.py index 517261452a81250f7684a02e7660671f3125ada3..31e936ee5a15be75231bfb21b67a90fad99e8f39 100644 --- a/gso/workflows/tasks/import_router.py +++ b/gso/workflows/tasks/import_router.py @@ -27,7 +27,8 @@ def _get_site_by_name(site_name: str) -> Site: """ subscription = subscriptions.get_active_subscriptions_by_field_and_value("site_name", site_name)[0] if not subscription: - raise ValueError(f"Site with name {site_name} not found.") + msg = f"Site with name {site_name} not found." + raise ValueError(msg) return Site.from_subscription(subscription.subscription_id) diff --git a/gso/workflows/tasks/import_site.py b/gso/workflows/tasks/import_site.py index af96fca24e6e67d0ffac5013c593eed238a16706..9e3815096d0cb3965b87b5213fa0edcd025c1bc6 100644 --- a/gso/workflows/tasks/import_site.py +++ b/gso/workflows/tasks/import_site.py @@ -54,7 +54,6 @@ def generate_initial_input_form() -> FormGenerator: ) def import_site() -> StepList: """Workflow to import a site without provisioning it.""" - return ( init >> create_subscription diff --git a/pyproject.toml b/pyproject.toml index b0097659e16da3dbe5b85f949a414bc0c9f7d131..2469a1a252d4512fa44cf2020140226ebe642cb8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -101,7 +101,7 @@ target-version = "py311" ban-relative-imports = "all" [tool.ruff.per-file-ignores] -"test/*" = ["S101", "PLR2004"] +"test/*" = ["D", "S101", "PLR2004"] [tool.ruff.isort] known-third-party = ["pydantic", "migrations"] diff --git a/test/__init__.py b/test/__init__.py index 17c55014877312ca91ee846b5639eda4a36597eb..433e89b0fcb66b0730237cc78cded4048140751c 100644 --- a/test/__init__.py +++ b/test/__init__.py @@ -6,7 +6,7 @@ LSO_RESULT_SUCCESS = { "job_id": str(uuid4()), "output": "parsed_output", "return_code": 0, - } + }, } LSO_RESULT_FAILURE = { @@ -15,7 +15,7 @@ LSO_RESULT_FAILURE = { "job_id": str(uuid4()), "output": "parsed_output", "return_code": 1, - } + }, } USER_CONFIRM_EMPTY_FORM = [{}] diff --git a/test/conftest.py b/test/conftest.py index 8e4a71136d1ad8fc94696e9a0de308a96d8b0e94..dd36e9f348991512c23fd9d906d8ca255320b348 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -1,287 +1,321 @@ -import contextlib -import ipaddress -import json -import logging -import os -import socket -import tempfile -from pathlib import Path - -import orchestrator -import pytest -from alembic import command -from alembic.config import Config -from faker import Faker -from faker.providers import BaseProvider -from orchestrator import app_settings -from orchestrator.db import Database, db -from orchestrator.db.database import ENGINE_ARGUMENTS, SESSION_ARGUMENTS, BaseModel -from sqlalchemy import create_engine, text -from sqlalchemy.engine import make_url -from sqlalchemy.orm import scoped_session, sessionmaker -from starlette.testclient import TestClient - -from gso.main import init_gso_app - -logging.getLogger("faker.factory").setLevel(logging.WARNING) - - -def pytest_collection_modifyitems(config, items): - if bool(os.environ.get("SKIP_ALL_TESTS")): - for item in items: - item.add_marker(pytest.mark.skip(reason="Skipped due to SKIP_ALL_TESTS env variable")) - - -class FakerProvider(BaseProvider): - def ipv4_network(self): - ipv4 = self.generator.ipv4() - interface = ipaddress.IPv4Interface(ipv4 + "/24") - network = interface.network.network_address - - return ipaddress.IPv4Network(str(network) + "/24") - - def ipv6_network(self): - ipv6 = self.generator.ipv6() - interface = ipaddress.IPv6Interface(ipv6 + "/64") - network = interface.network.network_address - - return ipaddress.IPv6Network(str(network) + "/64") - - def tt_number(self) -> str: - random_date = self.generator.date(pattern="%Y%m%d") - random_int = self.generator.random_int(min=10000000, max=99999999) - - return f"TT#{random_date}{random_int}" - - def geant_gid(self) -> str: - return self.generator.numerify("GID-#####") - - def geant_sid(self) -> str: - return self.generator.numerify("SID-#####") - - def site_name(self) -> str: - site_name = "".join(self.generator.random_letter().upper() for _ in range(3)) - - if self.generator.boolean(): - digit = self.generator.random_int(min=1, max=9) - site_name += str(digit) - - return site_name - - def network_interface(self) -> str: - return self.generator.numerify("ge-@#/@#/@#") - - -@pytest.fixture(scope="session") -def faker() -> Faker: - fake = Faker() - fake.add_provider(FakerProvider) - return fake - - -@pytest.fixture(scope="session") -def configuration_data() -> dict: - with contextlib.closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as s: - s.bind(("", 0)) - s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - yield { - "GENERAL": {"public_hostname": "https://gap.geant.org"}, - "NETBOX": {"api": "https://127.0.0.1:8000", "token": "TOKEN"}, - "IPAM": { - "INFOBLOX": { - "scheme": "https", - "wapi_version": "2.12", - "host": "10.0.0.1", - "username": "robot-user", - "password": "robot-user-password", - }, - "LO": { - "V4": {"containers": [], "networks": ["10.255.255.0/26"], "mask": 32}, - "V6": {"containers": [], "networks": ["dead:beef::/80"], "mask": 128}, - "domain_name": ".lo", - "dns_view": "default", - }, - "TRUNK": { - "V4": {"containers": ["10.255.255.0/24", "10.255.254.0/24"], "networks": [], "mask": 31}, - "V6": {"containers": ["dead:beef::/64", "dead:beee::/64"], "networks": [], "mask": 126}, - "domain_name": ".trunk", - "dns_view": "default", - }, - "GEANT_IP": { - "V4": {"containers": ["10.255.255.0/24", "10.255.254.0/24"], "networks": [], "mask": 31}, - "V6": {"containers": ["dead:beef::/64", "dead:beee::/64"], "networks": [], "mask": 126}, - "domain_name": ".geantip", - "dns_view": "default", - }, - "SI": { - "V4": {"containers": ["10.255.253.128/25"], "networks": [], "mask": 31}, - "V6": {"containers": [], "networks": [], "mask": 126}, - "domain_name": ".geantip", - "dns_view": "default", - }, - "LT_IAS": { - "V4": {"containers": ["10.255.255.0/24"], "networks": [], "mask": 31}, - "V6": {"containers": ["dead:beef:cc::/48"], "networks": [], "mask": 126}, - "domain_name": ".geantip", - "dns_view": "default", - }, - }, - "PROVISIONING_PROXY": { - "scheme": "https", - "api_base": "localhost:44444", - "auth": "Bearer <token>", - "api_version": 1123, - }, - "CELERY": { - "broker_url": "redis://localhost:6379", - "result_backend": "rpc://localhost:6379/0", - "result_expires": 3600, - }, - } - - -@pytest.fixture(scope="session", autouse=True) -def data_config_filename(configuration_data) -> str: - """Create a temporary file with configuration data and set an environment variable to its path.""" - with tempfile.NamedTemporaryFile(mode="w+", delete=False) as f: - json.dump(configuration_data, f, ensure_ascii=False) - os.environ["OSS_PARAMS_FILENAME"] = f.name - - yield f.name - del os.environ["OSS_PARAMS_FILENAME"] - os.remove(f.name) - - -@pytest.fixture(scope="session") -def db_uri(): - """Provide the database uri configuration to run the migration on.""" - return os.environ.get("DATABASE_URI_TEST", "postgresql://nwa:nwa@localhost/gso-test-db") - - -def run_migrations(db_uri: str) -> None: - """Configure the alembic migration and run the migration on the database. - - Args: - ---- - db_uri: The database uri configuration to run the migration on. - - Returns: - ------- - None - """ - - path = Path(__file__).resolve().parent - app_settings.DATABASE_URI = db_uri - alembic_cfg = Config(file_=path / "../gso/alembic.ini") - alembic_cfg.set_main_option("sqlalchemy.url", db_uri) - - alembic_cfg.set_main_option("script_location", str(path / "../gso/migrations")) - version_locations = alembic_cfg.get_main_option("version_locations") - alembic_cfg.set_main_option( - "version_locations", f"{version_locations} {os.path.dirname(orchestrator.__file__)}/migrations/versions/schema" - ) - - command.upgrade(alembic_cfg, "heads") - - -@pytest.fixture(scope="session") -def database(db_uri): - """Create database and run migrations and cleanup after wards. - - Args: - ---- - db_uri: The database uri configuration to run the migration on. - """ - - db.update(Database(db_uri)) - url = make_url(db_uri) - db_to_create = url.database - url = url.set(database="postgres") - - engine = create_engine(url) - with engine.connect() as conn: - conn.execute(text("COMMIT;")) - conn.execute( - text("SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname=:db_name").bindparams( - db_name=db_to_create - ) - ) - - conn.execute(text(f'DROP DATABASE IF EXISTS "{db_to_create}";')) - conn.execute(text("COMMIT;")) - conn.execute(text(f'CREATE DATABASE "{db_to_create}";')) - - run_migrations(db_uri) - db.wrapped_database.engine = create_engine(db_uri, **ENGINE_ARGUMENTS) - - try: - yield - finally: - db.wrapped_database.engine.dispose() - with engine.connect() as conn: - conn.execute(text("COMMIT;")) - # Terminate all connections to the database - conn.execute( - text(f"SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname='{db_to_create}';") # noqa - ) - conn.execute(text(f'DROP DATABASE IF EXISTS "{db_to_create}";')) # noqa - - -@pytest.fixture(autouse=True) -def db_session(database): - """Ensure that tests are executed within a transactional scope that automatically rolls back after completion. - - This fixture facilitates a pattern known as 'transactional tests'. At the start, it establishes a connection and - begins an overarching transaction. Any database operations performed within the test function—whether they commit - or not happen within the context of this master transaction. - - From the perspective of the test function, it seems as though changes are getting committed to the database, - enabling the tests to query and assert the persistence of data. Yet, once the test completes, this fixture - intervenes to roll back the master transaction. This ensures a clean slate after each test, preventing tests from - polluting the database state for subsequent tests. - - Benefits: - - Each test runs in isolation with a pristine database state. - - Avoids the overhead of recreating the database schema or re-seeding data between tests. - - Args: - ---- - database: A fixture reference that initializes the database. - """ - - with contextlib.closing(db.wrapped_database.engine.connect()) as test_connection: - # Create a new session factory for this context. - session_factory = sessionmaker(bind=test_connection, **SESSION_ARGUMENTS) - scoped_session_instance = scoped_session(session_factory, scopefunc=db.wrapped_database._scopefunc) - - # Point the database session to this new scoped session. - db.wrapped_database.session_factory = session_factory - db.wrapped_database.scoped_session = scoped_session_instance - - # Set the query for the base model. - BaseModel.set_query(scoped_session_instance.query_property()) - transaction = test_connection.begin() - try: - yield - finally: - transaction.rollback() - scoped_session_instance.remove() - - -@pytest.fixture(scope="session", autouse=True) -def fastapi_app(database, db_uri): - """Load the GSO FastAPI app for testing purposes. - - This implementation is as close as possible to the one present in orchestrator-core. - """ - from oauth2_lib.settings import oauth2lib_settings - - oauth2lib_settings.OAUTH2_ACTIVE = False - oauth2lib_settings.ENVIRONMENT_IGNORE_MUTATION_DISABLED = ["local", "TESTING"] - app_settings.DATABASE_URI = db_uri - return init_gso_app() - - -@pytest.fixture(scope="session") -def test_client(fastapi_app): - return TestClient(fastapi_app) +import contextlib +import ipaddress +import json +import logging +import os +import socket +import tempfile +from pathlib import Path + +import orchestrator +import pytest +from alembic import command +from alembic.config import Config +from faker import Faker +from faker.providers import BaseProvider +from orchestrator import app_settings +from orchestrator.db import Database, db +from orchestrator.db.database import ENGINE_ARGUMENTS, SESSION_ARGUMENTS, BaseModel +from sqlalchemy import create_engine, text +from sqlalchemy.engine import make_url +from sqlalchemy.orm import scoped_session, sessionmaker +from starlette.testclient import TestClient + +from gso.main import init_gso_app + +logging.getLogger("faker.factory").setLevel(logging.WARNING) + + +def pytest_collection_modifyitems(config, items): + if bool(os.environ.get("SKIP_ALL_TESTS")): + for item in items: + item.add_marker(pytest.mark.skip(reason="Skipped due to SKIP_ALL_TESTS env variable")) + + +class FakerProvider(BaseProvider): + def ipv4_network(self): + ipv4 = self.generator.ipv4() + interface = ipaddress.IPv4Interface(ipv4 + "/24") + network = interface.network.network_address + + return ipaddress.IPv4Network(str(network) + "/24") + + def ipv6_network(self): + ipv6 = self.generator.ipv6() + interface = ipaddress.IPv6Interface(ipv6 + "/64") + network = interface.network.network_address + + return ipaddress.IPv6Network(str(network) + "/64") + + def tt_number(self) -> str: + random_date = self.generator.date(pattern="%Y%m%d") + random_int = self.generator.random_int(min=10000000, max=99999999) + + return f"TT#{random_date}{random_int}" + + def geant_gid(self) -> str: + return self.generator.numerify("GID-#####") + + def geant_sid(self) -> str: + return self.generator.numerify("SID-#####") + + def site_name(self) -> str: + site_name = "".join(self.generator.random_letter().upper() for _ in range(3)) + + if self.generator.boolean(): + digit = self.generator.random_int(min=1, max=9) + site_name += str(digit) + + return site_name + + def network_interface(self) -> str: + return self.generator.numerify("ge-@#/@#/@#") + + +@pytest.fixture(scope="session") +def faker() -> Faker: + fake = Faker() + fake.add_provider(FakerProvider) + return fake + + +@pytest.fixture(scope="session") +def configuration_data() -> dict: + with contextlib.closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as s: + s.bind(("", 0)) + s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + yield { + "GENERAL": {"public_hostname": "https://gap.geant.org"}, + "NETBOX": {"api": "https://127.0.0.1:8000", "token": "TOKEN"}, + "IPAM": { + "INFOBLOX": { + "scheme": "https", + "wapi_version": "2.12", + "host": "10.0.0.1", + "username": "robot-user", + "password": "robot-user-password", + }, + "LO": { + "V4": { + "containers": [], + "networks": ["10.255.255.0/26"], + "mask": 32, + }, + "V6": { + "containers": [], + "networks": ["dead:beef::/80"], + "mask": 128, + }, + "domain_name": ".lo", + "dns_view": "default", + }, + "TRUNK": { + "V4": { + "containers": ["10.255.255.0/24", "10.255.254.0/24"], + "networks": [], + "mask": 31, + }, + "V6": { + "containers": ["dead:beef::/64", "dead:beee::/64"], + "networks": [], + "mask": 126, + }, + "domain_name": ".trunk", + "dns_view": "default", + }, + "GEANT_IP": { + "V4": { + "containers": ["10.255.255.0/24", "10.255.254.0/24"], + "networks": [], + "mask": 31, + }, + "V6": { + "containers": ["dead:beef::/64", "dead:beee::/64"], + "networks": [], + "mask": 126, + }, + "domain_name": ".geantip", + "dns_view": "default", + }, + "SI": { + "V4": { + "containers": ["10.255.253.128/25"], + "networks": [], + "mask": 31, + }, + "V6": {"containers": [], "networks": [], "mask": 126}, + "domain_name": ".geantip", + "dns_view": "default", + }, + "LT_IAS": { + "V4": { + "containers": ["10.255.255.0/24"], + "networks": [], + "mask": 31, + }, + "V6": { + "containers": ["dead:beef:cc::/48"], + "networks": [], + "mask": 126, + }, + "domain_name": ".geantip", + "dns_view": "default", + }, + }, + "PROVISIONING_PROXY": { + "scheme": "https", + "api_base": "localhost:44444", + "auth": "Bearer <token>", + "api_version": 1123, + }, + "CELERY": { + "broker_url": "redis://localhost:6379", + "result_backend": "rpc://localhost:6379/0", + "result_expires": 3600, + }, + } + + +@pytest.fixture(scope="session", autouse=True) +def data_config_filename(configuration_data) -> str: + """Create a temporary file with configuration data and set an environment variable to its path.""" + with tempfile.NamedTemporaryFile(mode="w+", delete=False) as f: + json.dump(configuration_data, f, ensure_ascii=False) + os.environ["OSS_PARAMS_FILENAME"] = f.name + + yield f.name + del os.environ["OSS_PARAMS_FILENAME"] + os.remove(f.name) + + +@pytest.fixture(scope="session") +def db_uri(): + """Provide the database uri configuration to run the migration on.""" + return os.environ.get("DATABASE_URI_TEST", "postgresql://nwa:nwa@localhost/gso-test-db") + + +def run_migrations(db_uri: str) -> None: + """Configure the alembic migration and run the migration on the database. + + Args: + ---- + db_uri: The database uri configuration to run the migration on. + + Returns: + ------- + None + """ + path = Path(__file__).resolve().parent + app_settings.DATABASE_URI = db_uri + alembic_cfg = Config(file_=path / "../gso/alembic.ini") + alembic_cfg.set_main_option("sqlalchemy.url", db_uri) + + alembic_cfg.set_main_option("script_location", str(path / "../gso/migrations")) + version_locations = alembic_cfg.get_main_option("version_locations") + alembic_cfg.set_main_option( + "version_locations", + f"{version_locations} {os.path.dirname(orchestrator.__file__)}/migrations/versions/schema", + ) + + command.upgrade(alembic_cfg, "heads") + + +@pytest.fixture(scope="session") +def database(db_uri): + """Create database and run migrations and cleanup after wards. + + Args: + ---- + db_uri: The database uri configuration to run the migration on. + """ + db.update(Database(db_uri)) + url = make_url(db_uri) + db_to_create = url.database + url = url.set(database="postgres") + + engine = create_engine(url) + with engine.connect() as conn: + conn.execute(text("COMMIT;")) + conn.execute( + text("SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname=:db_name").bindparams( + db_name=db_to_create, + ), + ) + + conn.execute(text(f'DROP DATABASE IF EXISTS "{db_to_create}";')) + conn.execute(text("COMMIT;")) + conn.execute(text(f'CREATE DATABASE "{db_to_create}";')) + + run_migrations(db_uri) + db.wrapped_database.engine = create_engine(db_uri, **ENGINE_ARGUMENTS) + + try: + yield + finally: + db.wrapped_database.engine.dispose() + with engine.connect() as conn: + conn.execute(text("COMMIT;")) + # Terminate all connections to the database + conn.execute( + text(f"SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname='{db_to_create}';") # noqa + ) + conn.execute(text(f'DROP DATABASE IF EXISTS "{db_to_create}";')) + + +@pytest.fixture(autouse=True) +def db_session(database): + """Ensure that tests are executed within a transactional scope that automatically rolls back after completion. + + This fixture facilitates a pattern known as 'transactional tests'. At the start, it establishes a connection and + begins an overarching transaction. Any database operations performed within the test function—whether they commit + or not happen within the context of this master transaction. + + From the perspective of the test function, it seems as though changes are getting committed to the database, + enabling the tests to query and assert the persistence of data. Yet, once the test completes, this fixture + intervenes to roll back the master transaction. This ensures a clean slate after each test, preventing tests from + polluting the database state for subsequent tests. + + Benefits: + - Each test runs in isolation with a pristine database state. + - Avoids the overhead of recreating the database schema or re-seeding data between tests. + + Args: + ---- + database: A fixture reference that initializes the database. + """ + with contextlib.closing(db.wrapped_database.engine.connect()) as test_connection: + # Create a new session factory for this context. + session_factory = sessionmaker(bind=test_connection, **SESSION_ARGUMENTS) + scoped_session_instance = scoped_session(session_factory, scopefunc=db.wrapped_database._scopefunc) + + # Point the database session to this new scoped session. + db.wrapped_database.session_factory = session_factory + db.wrapped_database.scoped_session = scoped_session_instance + + # Set the query for the base model. + BaseModel.set_query(scoped_session_instance.query_property()) + transaction = test_connection.begin() + try: + yield + finally: + transaction.rollback() + scoped_session_instance.remove() + + +@pytest.fixture(scope="session", autouse=True) +def fastapi_app(database, db_uri): + """Load the GSO FastAPI app for testing purposes. + + This implementation is as close as possible to the one present in orchestrator-core. + """ + from oauth2_lib.settings import oauth2lib_settings + + oauth2lib_settings.OAUTH2_ACTIVE = False + oauth2lib_settings.ENVIRONMENT_IGNORE_MUTATION_DISABLED = ["local", "TESTING"] + app_settings.DATABASE_URI = db_uri + return init_gso_app() + + +@pytest.fixture(scope="session") +def test_client(fastapi_app): + return TestClient(fastapi_app) diff --git a/test/fixtures.py b/test/fixtures.py index 601463de6f392f13b83b2efa7b74b9443255a636..e7a8d7f9d7c2798c8e003716ed5361e4d59ff66a 100644 --- a/test/fixtures.py +++ b/test/fixtures.py @@ -6,7 +6,12 @@ from orchestrator.domain import SubscriptionModel from orchestrator.types import SubscriptionLifecycle, UUIDstr from gso.products import ProductType -from gso.products.product_blocks.iptrunk import IptrunkInterfaceBlock, IptrunkSideBlock, IptrunkType, PhyPortCapacity +from gso.products.product_blocks.iptrunk import ( + IptrunkInterfaceBlock, + IptrunkSideBlock, + IptrunkType, + PhyPortCapacity, +) from gso.products.product_blocks.router import RouterRole, RouterVendor from gso.products.product_blocks.site import SiteTier from gso.products.product_types.iptrunk import IptrunkInactive @@ -17,7 +22,7 @@ from gso.services import subscriptions CUSTOMER_ID: UUIDstr = "2f47f65a-0911-e511-80d0-005056956c1a" -@pytest.fixture +@pytest.fixture() def site_subscription_factory(faker): def subscription_create( description=None, @@ -68,7 +73,7 @@ def site_subscription_factory(faker): return subscription_create -@pytest.fixture +@pytest.fixture() def router_subscription_factory(site_subscription_factory, faker): def subscription_create( description=None, @@ -131,7 +136,7 @@ def router_subscription_factory(site_subscription_factory, faker): return subscription_create -@pytest.fixture +@pytest.fixture() def iptrunk_side_subscription_factory(router_subscription_factory, faker): def subscription_create( iptrunk_side_node=None, @@ -146,10 +151,14 @@ def iptrunk_side_subscription_factory(router_subscription_factory, faker): iptrunk_side_ae_geant_a_sid = iptrunk_side_ae_geant_a_sid or faker.geant_sid() iptrunk_side_ae_members = iptrunk_side_ae_members or [ IptrunkInterfaceBlock.new( - faker.uuid4(), interface_name=faker.network_interface(), interface_description=faker.sentence() + faker.uuid4(), + interface_name=faker.network_interface(), + interface_description=faker.sentence(), ), IptrunkInterfaceBlock.new( - faker.uuid4(), interface_name=faker.network_interface(), interface_description=faker.sentence() + faker.uuid4(), + interface_name=faker.network_interface(), + interface_description=faker.sentence(), ), ] @@ -165,7 +174,7 @@ def iptrunk_side_subscription_factory(router_subscription_factory, faker): return subscription_create -@pytest.fixture +@pytest.fixture() def iptrunk_subscription_factory(iptrunk_side_subscription_factory, faker): def subscription_create( description=None, @@ -204,7 +213,8 @@ def iptrunk_subscription_factory(iptrunk_side_subscription_factory, faker): iptrunk_subscription.iptrunk.iptrunk_sides = iptrunk_sides iptrunk_subscription = SubscriptionModel.from_other_lifecycle( - iptrunk_subscription, SubscriptionLifecycle.ACTIVE + iptrunk_subscription, + SubscriptionLifecycle.ACTIVE, ) iptrunk_subscription.description = description iptrunk_subscription.start_date = start_date diff --git a/test/imports/test_imports.py b/test/imports/test_imports.py index 82a8eae6cc75bbe0374a6696b3acd0dc72b15ba9..9a70dfdfa9f9bacda93e5e7d9b30b1d39ebae176 100644 --- a/test/imports/test_imports.py +++ b/test/imports/test_imports.py @@ -15,7 +15,7 @@ ROUTER_IMPORT_ENDPOINT = "/api/v1/imports/routers" IPTRUNK_IMPORT_API_URL = "/api/v1/imports/iptrunks" -@pytest.fixture +@pytest.fixture() def iptrunk_data(router_subscription_factory, faker): router_side_a = router_subscription_factory() router_side_b = router_subscription_factory() @@ -30,20 +30,28 @@ def iptrunk_data(router_subscription_factory, faker): "side_a_ae_iface": faker.network_interface(), "side_a_ae_geant_a_sid": faker.geant_sid(), "side_a_ae_members": [ - {"interface_name": faker.network_interface(), "interface_description": faker.sentence()} for _ in range(5) + { + "interface_name": faker.network_interface(), + "interface_description": faker.sentence(), + } + for _ in range(5) ], "side_b_node_id": router_side_b, "side_b_ae_iface": faker.network_interface(), "side_b_ae_geant_a_sid": faker.geant_sid(), "side_b_ae_members": [ - {"interface_name": faker.network_interface(), "interface_description": faker.sentence()} for _ in range(5) + { + "interface_name": faker.network_interface(), + "interface_description": faker.sentence(), + } + for _ in range(5) ], "iptrunk_ipv4_network": str(faker.ipv4_network()), "iptrunk_ipv6_network": str(faker.ipv6_network()), } -@pytest.fixture +@pytest.fixture() def mock_routers(iptrunk_data): with patch("gso.services.subscriptions.get_active_router_subscriptions") as mock_get_active_router_subscriptions: @@ -58,7 +66,10 @@ def mock_routers(iptrunk_data): "subscription_id": iptrunk_data["side_b_node_id"], "description": "iptrunk_sideB_node_id description", }, - {"subscription_id": str(uuid4()), "description": "random description"}, + { + "subscription_id": str(uuid4()), + "description": "random description", + }, ] return [ {"subscription_id": iptrunk_data["side_a_node_id"]}, @@ -79,7 +90,7 @@ def test_import_iptrunk_successful_with_mocked_process(mock_start_process, test_ assert response.json()["pid"] == "123e4567-e89b-12d3-a456-426655440000" -@pytest.fixture +@pytest.fixture() def site_data(faker): return { "site_name": faker.site_name(), @@ -96,7 +107,7 @@ def site_data(faker): } -@pytest.fixture +@pytest.fixture() def router_data(faker, site_data): mock_ipv4 = faker.ipv4() return { @@ -121,7 +132,8 @@ def test_import_site_endpoint(test_client, site_data): assert "detail" in response.json() assert "pid" in response.json() subscription = subscriptions.retrieve_subscription_by_subscription_instance_value( - resource_type="site_name", value=site_data["site_name"] + resource_type="site_name", + value=site_data["site_name"], ) assert subscription is not None @@ -189,7 +201,8 @@ def test_import_iptrunk_successful_with_real_process(test_client, mock_routers, assert "pid" in response subscription = subscriptions.retrieve_subscription_by_subscription_instance_value( - resource_type="geant_s_sid", value=iptrunk_data["geant_s_sid"] + resource_type="geant_s_sid", + value=iptrunk_data["geant_s_sid"], ) assert subscription is not None @@ -203,8 +216,12 @@ def test_import_iptrunk_invalid_customer(mock_start_process, test_client, mock_r assert response.status_code == 422 assert response.json() == { "detail": [ - {"loc": ["body", "customer"], "msg": "Customer not_existing_customer not found", "type": "value_error"} - ] + { + "loc": ["body", "customer"], + "msg": "Customer not_existing_customer not found", + "type": "value_error", + }, + ], } @@ -229,7 +246,7 @@ def test_import_iptrunk_invalid_router_id_side_a_and_b(mock_start_process, test_ "msg": f"Router {iptrunk_data['side_b_node_id']} not found", "type": "value_error", }, - ] + ], } @@ -237,8 +254,14 @@ def test_import_iptrunk_invalid_router_id_side_a_and_b(mock_start_process, test_ def test_import_iptrunk_non_unique_members_side_a(mock_start_process, test_client, mock_routers, iptrunk_data, faker): mock_start_process.return_value = "123e4567-e89b-12d3-a456-426655440000" - repeat_interface_a = {"interface_name": faker.network_interface(), "interface_description": faker.sentence()} - repeat_interface_b = {"interface_name": faker.network_interface(), "interface_description": faker.sentence()} + repeat_interface_a = { + "interface_name": faker.network_interface(), + "interface_description": faker.sentence(), + } + repeat_interface_b = { + "interface_name": faker.network_interface(), + "interface_description": faker.sentence(), + } iptrunk_data["side_a_ae_members"] = [repeat_interface_a for _ in range(5)] iptrunk_data["side_b_ae_members"] = [repeat_interface_b for _ in range(5)] @@ -247,20 +270,31 @@ def test_import_iptrunk_non_unique_members_side_a(mock_start_process, test_clien assert response.status_code == 422 assert response.json() == { "detail": [ - {"loc": ["body", "side_a_ae_members"], "msg": "Items must be unique", "type": "value_error"}, - {"loc": ["body", "side_b_ae_members"], "msg": "Items must be unique", "type": "value_error"}, + { + "loc": ["body", "side_a_ae_members"], + "msg": "Items must be unique", + "type": "value_error", + }, + { + "loc": ["body", "side_b_ae_members"], + "msg": "Items must be unique", + "type": "value_error", + }, { "loc": ["body", "__root__"], "msg": "Side A members should be at least 5 (iptrunk_minimum_links)", "type": "value_error", }, - ] + ], } @patch("gso.api.v1.imports._start_process") def test_import_iptrunk_fails_on_side_a_member_count_mismatch( - mock_start_process, test_client, mock_routers, iptrunk_data + mock_start_process, + test_client, + mock_routers, + iptrunk_data, ): mock_start_process.return_value = "123e4567-e89b-12d3-a456-426655440000" @@ -275,14 +309,17 @@ def test_import_iptrunk_fails_on_side_a_member_count_mismatch( "loc": ["body", "__root__"], "msg": "Side A members should be at least 5 (iptrunk_minimum_links)", "type": "value_error", - } - ] + }, + ], } @patch("gso.api.v1.imports._start_process") def test_import_iptrunk_fails_on_side_a_and_b_members_mismatch( - mock_start_process, test_client, iptrunk_data, mock_routers + mock_start_process, + test_client, + iptrunk_data, + mock_routers, ): mock_start_process.return_value = "123e4567-e89b-12d3-a456-426655440000" @@ -292,5 +329,11 @@ def test_import_iptrunk_fails_on_side_a_and_b_members_mismatch( assert response.status_code == 422 assert response.json() == { - "detail": [{"loc": ["body", "__root__"], "msg": "Mismatch between Side A and B members", "type": "value_error"}] + "detail": [ + { + "loc": ["body", "__root__"], + "msg": "Mismatch between Side A and B members", + "type": "value_error", + }, + ], } diff --git a/test/schedules/test_scheduling.py b/test/schedules/test_scheduling.py index 5007ed0068ac21607f7fc0ed065df71793f7c95e..496b36733b562a60c31ec01b58c5ef2811fc66b9 100644 --- a/test/schedules/test_scheduling.py +++ b/test/schedules/test_scheduling.py @@ -13,20 +13,20 @@ def validate_subscriptions(): return vs -@pytest.fixture +@pytest.fixture() def mock_get_insync_subscriptions(): with patch("gso.schedules.validate_subscriptions.get_insync_subscriptions") as mock: yield mock -@pytest.fixture +@pytest.fixture() def mock_get_execution_context(): with patch("gso.schedules.validate_subscriptions.get_execution_context") as mock: mock.return_value = {"validate": MagicMock()} yield mock -@pytest.fixture +@pytest.fixture() def mock_logger(): with patch("gso.schedules.validate_subscriptions.logger") as mock: yield mock @@ -41,7 +41,14 @@ def mock_celery(): def test_scheduler_updates_beat_schedule(mock_celery): mock_celery.conf.beat_schedule = {} - @scheduler(name="A cool task", minute="0", hour="0", day_of_week="*", day_of_month="*", month_of_year="*") + @scheduler( + name="A cool task", + minute="0", + hour="0", + day_of_week="*", + day_of_month="*", + month_of_year="*", + ) def mock_task(): return "task result" @@ -56,7 +63,14 @@ def test_scheduler_updates_beat_schedule(mock_celery): def test_scheduled_task_still_works(): """Ensure that the scheduler decorator does not change the behavior of the function it decorates.""" - @scheduler(name="A cool task", minute="0", hour="0", day_of_week="*", day_of_month="*", month_of_year="*") + @scheduler( + name="A cool task", + minute="0", + hour="0", + day_of_week="*", + day_of_month="*", + month_of_year="*", + ) def mock_task(): return "task result" diff --git a/test/schemas/test_types.py b/test/schemas/test_types.py index e5d757dbb84550df27f05949caf2e1ad78c7a2c8..5265d08097fc2ef50b3a929a6408f3a450de868a 100644 --- a/test/schemas/test_types.py +++ b/test/schemas/test_types.py @@ -4,7 +4,7 @@ from gso.products.product_blocks.site import LatitudeCoordinate, LongitudeCoordi @pytest.mark.parametrize( - "input_value, is_valid", + ("input_value", "is_valid"), [ ("40.7128", True), ("-74.0060", True), @@ -30,7 +30,7 @@ def test_latitude(input_value, is_valid): @pytest.mark.parametrize( - "input_value, is_valid", + ("input_value", "is_valid"), [ ("40.7128", True), ("-74.0060", True), diff --git a/test/services/test_infoblox.py b/test/services/test_infoblox.py index 003107a3cb5feb6696d40c791582ecfd966f920e..64bf43fdb5917d53a1e06cc95405ce34b0f0bdd0 100644 --- a/test/services/test_infoblox.py +++ b/test/services/test_infoblox.py @@ -11,9 +11,17 @@ from gso.services.infoblox import AllocationError, DeletionError def _set_up_network_responses(): - responses.add(method=responses.GET, url=re.compile(r".+/wapi/v2\.12/network\?network=10\.255\.255\.0.+"), json=[]) + responses.add( + method=responses.GET, + url=re.compile(r".+/wapi/v2\.12/network\?network=10\.255\.255\.0.+"), + json=[], + ) - responses.add(method=responses.GET, url=re.compile(r".+/wapi/v2\.12/ipv6network\?network=dead%3Abeef.+"), json=[]) + responses.add( + method=responses.GET, + url=re.compile(r".+/wapi/v2\.12/ipv6network\?network=dead%3Abeef.+"), + json=[], + ) responses.add( method=responses.POST, @@ -68,7 +76,7 @@ def _set_up_host_responses(): method=responses.GET, url=re.compile( r"https://10.0.0.1/wapi/v2.12/record%3Ahost\?name=broken&ipv6addr=func%3Anextavailableip%3Adead%3Abeef%3A%3" - r"A%2F80%2Cdefault.*" + r"A%2F80%2Cdefault.*", ), json=[], status=codes.BAD, @@ -87,7 +95,7 @@ def _set_up_host_responses(): "duid": "00:00:00:00:00:00:00:00:00:00", "host": "test.lo.geant.net", "ipv6addr": "dead:beef::1", - } + }, ], "ip": "dead:beef::1", "name": "test.lo.geant.net", @@ -109,7 +117,7 @@ def _set_up_host_responses(): "host": "test.lo.geant.net", "ipv4addr": "10.255.255.129", "mac": "00:00:00:00:00:00", - } + }, ], "name": "test.lo.geant.net", "view": "default", @@ -132,11 +140,11 @@ def _set_up_host_responses(): "host": "test.lo.geant.net", "ipv4addr": "10.255.255.129", "mac": "00:00:00:00:00:00", - } + }, ], "name": "test.lo.geant.net", "view": "default", - } + }, ], ) @@ -169,7 +177,10 @@ def test_allocate_bad_network(data_config_filename: PathLike): def test_allocate_good_host(data_config_filename: PathLike): _set_up_host_responses() new_host = infoblox.allocate_host("test.lo.geant.net", "LO", [], "test host") - assert new_host == (ipaddress.ip_address("10.255.255.129"), ipaddress.ip_address("dead:beef::1")) + assert new_host == ( + ipaddress.ip_address("10.255.255.129"), + ipaddress.ip_address("dead:beef::1"), + ) @responses.activate @@ -191,7 +202,7 @@ def test_delete_good_network(data_config_filename: PathLike): "_ref": "network/ZG5zLm5ldHdvcmskNjIuNDAuOTYuMC8yNC8w:10.255.255.0/26/default", "network": "10.255.255.0/26", "network_view": "default", - } + }, ], ) @@ -223,7 +234,7 @@ def test_delete_good_host(data_config_filename: PathLike): responses.add( method=responses.GET, url=re.compile( - r"https://10\.0\.0\.1/wapi/v2\.12/record%3Ahost\?(?:name=ha_lo\.gso|ipv4addr=10\.255\.255\.1)?.+" + r"https://10\.0\.0\.1/wapi/v2\.12/record%3Ahost\?(?:name=ha_lo\.gso|ipv4addr=10\.255\.255\.1)?.+", ), json=[ { @@ -235,7 +246,7 @@ def test_delete_good_host(data_config_filename: PathLike): "configure_for_dhcp": False, "host": "ha_lo.gso", "ipv4addr": "10.255.255.1", - } + }, ], "ipv6addrs": [ { @@ -244,18 +255,18 @@ def test_delete_good_host(data_config_filename: PathLike): "configure_for_dhcp": False, "host": "ha_lo.gso", "ipv6addr": "dead:beef::1", - } + }, ], "name": "ha_lo.gso", "view": "default", - } + }, ], ) responses.add( method=responses.DELETE, url=re.compile( - r"https://10\.0\.0\.1/wapi/v2\.12/record%3Ahost/.+(ha_lo\.gso|dead:beef::1|10\.255\.255\.1)/default" + r"https://10\.0\.0\.1/wapi/v2\.12/record%3Ahost/.+(ha_lo\.gso|dead:beef::1|10\.255\.255\.1)/default", ), json=[], ) diff --git a/test/services/test_netbox.py b/test/services/test_netbox.py index 15508fe77466fcc100ae26ffe7ceae33931db6ff..69983297ea35f75b775b4b967db6d97979189662 100644 --- a/test/services/test_netbox.py +++ b/test/services/test_netbox.py @@ -76,7 +76,14 @@ def lag(): @patch("gso.services.netbox_client.pynetbox.api") def test_create_device( - mock_api, device, device_type, device_role, site, device_bay, card_type, data_config_filename: PathLike + mock_api, + device, + device_type, + device_role, + site, + device_bay, + card_type, + data_config_filename: PathLike, ): device_name = "mx1.lab.geant.net" device.name = device_name diff --git a/test/workflows/__init__.py b/test/workflows/__init__.py index 3843a79b6d7e1fa7c990600e664e3cc0134971b4..66b9bea12c4a6ce0a0a191102a965c1094cc2575 100644 --- a/test/workflows/__init__.py +++ b/test/workflows/__init__.py @@ -1,8 +1,9 @@ import difflib import pprint +from collections.abc import Callable from copy import deepcopy from itertools import chain, repeat -from typing import Callable, cast +from typing import cast from uuid import uuid4 import structlog @@ -33,19 +34,19 @@ def assert_success(result): def assert_waiting(result): assert result.on_failed( - _raise_exception + _raise_exception, ).iswaiting(), f"Unexpected process status. Expected Waiting, but was: {result}" def assert_suspended(result): assert result.on_failed( - _raise_exception + _raise_exception, ).issuspend(), f"Unexpected process status. Expected Suspend, but was: {result}" def assert_awaiting_callback(result): assert result.on_failed( - _raise_exception + _raise_exception, ).isawaitingcallback(), f"Unexpected process status. Expected Awaiting Callback, but was: {result}" @@ -59,14 +60,14 @@ def assert_failed(result): def assert_complete(result): assert result.on_failed( - _raise_exception + _raise_exception, ).iscomplete(), f"Unexpected process status. Expected Complete, but was: {result}" def assert_state(result, expected): state = result.unwrap() actual = {} - for key in expected.keys(): + for key in expected: actual[key] = state[key] assert expected == actual, f"Invalid state. Expected superset of: {expected}, but was: {actual}" @@ -84,7 +85,10 @@ def assert_state_equal(result: ProcessTable, expected: dict, excluded_keys: list del expected_state[key] assert state == expected_state, "Unexpected state:\n" + "\n".join( - difflib.ndiff(pprint.pformat(state).splitlines(), pprint.pformat(expected_state).splitlines()) + difflib.ndiff( + pprint.pformat(state).splitlines(), + pprint.pformat(expected_state).splitlines(), + ), ) @@ -103,7 +107,7 @@ def extract_state(result): def extract_error(result): - assert isinstance(result, Process), f"Expected a Process, but got {repr(result)} of type {type(result)}" + assert isinstance(result, Process), f"Expected a Process, but got {result!r} of type {type(result)}" assert not isinstance(result.s, Process), "Result contained a Process in a Process, this should not happen" return extract_state(result).get("error") @@ -157,7 +161,7 @@ def _store_step(step_log: list[tuple[Step, Process]]) -> Callable[[ProcessStat, state = process.unwrap() state.pop("__step_name_override", None) - for k in state.get("__remove_keys", []) + ["__remove_keys"]: + for k in [*state.get("__remove_keys", []), "__remove_keys"]: state.pop(k, None) if state.pop("__replace_last_state", None): step_log[-1] = (step, process) @@ -204,7 +208,9 @@ def run_workflow(workflow_key: str, input_data: State | list[State]) -> tuple[Pr def resume_workflow( - process: ProcessStat, step_log: list[tuple[Step, Process]], input_data: State | list[State] + process: ProcessStat, + step_log: list[tuple[Step, Process]], + input_data: State | list[State], ) -> tuple[Process, list]: # ATTENTION!! This code needs to be as similar as possible to `server.services.processes.resume_process` # The main differences are: we use a different step log function, and we don't run in a separate thread @@ -212,7 +218,7 @@ def resume_workflow( filter( lambda p: not (p[1].isfailed() or p[1].issuspend() or p[1].iswaiting() or p[1].isawaitingcallback()), step_log, - ) + ), ) nr_of_steps_done = len(persistent) remaining_steps = process.workflow.steps[nr_of_steps_done:] @@ -239,7 +245,8 @@ def resume_workflow( def run_form_generator( - form_generator: FormGenerator, extra_inputs: list[State] | None = None + form_generator: FormGenerator, + extra_inputs: list[State] | None = None, ) -> tuple[list[dict], State]: """Run a form generator to get the resulting forms and result. @@ -322,7 +329,6 @@ def assert_pp_interaction_success(result: Process, process_stat: ProcessStat, st confirmation input step. Two assertions are made: the workflow is awaiting callback at first, and suspended when waiting for the user to confirm the results received. """ - assert_awaiting_callback(result) result, step_log = resume_workflow(process_stat, step_log, input_data=LSO_RESULT_SUCCESS) assert_suspended(result) diff --git a/test/workflows/iptrunk/test_create_iptrunk.py b/test/workflows/iptrunk/test_create_iptrunk.py index 10a87d1253033f7964bb7482db18e6498586d059..527a05fc40bffc6dca62875629d663a47936fe71 100644 --- a/test/workflows/iptrunk/test_create_iptrunk.py +++ b/test/workflows/iptrunk/test_create_iptrunk.py @@ -18,7 +18,7 @@ from test.workflows import ( ) -@pytest.fixture +@pytest.fixture() def netbox_client_mock(): # Mock NetboxClient methods with ( @@ -41,7 +41,7 @@ def netbox_client_mock(): yield -@pytest.fixture +@pytest.fixture() def input_form_wizard_data(router_subscription_factory, faker): router_side_a = router_subscription_factory() router_side_b = router_subscription_factory() @@ -60,7 +60,10 @@ def input_form_wizard_data(router_subscription_factory, faker): "side_a_ae_iface": "LAG1", "side_a_ae_geant_a_sid": faker.geant_sid(), "side_a_ae_members": [ - LAGMember(interface_name=f"Interface{interface}", interface_description=faker.sentence()) + LAGMember( + interface_name=f"Interface{interface}", + interface_description=faker.sentence(), + ) for interface in range(5) ], } @@ -69,7 +72,10 @@ def input_form_wizard_data(router_subscription_factory, faker): "side_b_ae_iface": "LAG4", "side_b_ae_geant_a_sid": faker.geant_sid(), "side_b_ae_members": [ - LAGMember(interface_name=f"Interface{interface}", interface_description=faker.sentence()) + LAGMember( + interface_name=f"Interface{interface}", + interface_description=faker.sentence(), + ) for interface in range(5) ], } @@ -83,7 +89,7 @@ def input_form_wizard_data(router_subscription_factory, faker): ] -@pytest.mark.workflow +@pytest.mark.workflow() @patch("gso.workflows.iptrunk.create_iptrunk.provisioning_proxy.check_ip_trunk") @patch("gso.workflows.iptrunk.create_iptrunk.provisioning_proxy.provision_ip_trunk") @patch("gso.workflows.iptrunk.create_iptrunk.infoblox.allocate_v6_network") @@ -115,14 +121,14 @@ def test_successful_iptrunk_creation_with_standard_lso_result( subscription_id = state["subscription_id"] subscription = Iptrunk.from_subscription(subscription_id) - assert "active" == subscription.status + assert subscription.status == "active" assert subscription.description == f"IP trunk, geant_s_sid:{input_form_wizard_data[0]['geant_s_sid']}" assert mock_provision_ip_trunk.call_count == 4 assert mock_check_ip_trunk.call_count == 2 -@pytest.mark.workflow +@pytest.mark.workflow() @patch("gso.workflows.iptrunk.create_iptrunk.provisioning_proxy.check_ip_trunk") @patch("gso.workflows.iptrunk.create_iptrunk.provisioning_proxy.provision_ip_trunk") @patch("gso.workflows.iptrunk.create_iptrunk.infoblox.allocate_v6_network") diff --git a/test/workflows/iptrunk/test_migrate_iptrunk.py b/test/workflows/iptrunk/test_migrate_iptrunk.py index 8285ffb9bb840ec586f0cde12adc0f24c849c4bd..d1383e41e8b2066753718ebf81a5d611a38c472f 100644 --- a/test/workflows/iptrunk/test_migrate_iptrunk.py +++ b/test/workflows/iptrunk/test_migrate_iptrunk.py @@ -17,7 +17,7 @@ from test.workflows import ( from test.workflows.iptrunk.test_create_iptrunk import MockedNetboxClient -@pytest.mark.workflow +@pytest.mark.workflow() @patch("gso.workflows.iptrunk.migrate_iptrunk.provisioning_proxy.migrate_ip_trunk") @patch("gso.workflows.iptrunk.migrate_iptrunk.provisioning_proxy.provision_ip_trunk") @patch("gso.services.netbox_client.NetboxClient.get_available_interfaces") @@ -65,7 +65,7 @@ def test_migrate_iptrunk_success( { "tt_number": faker.tt_number(), "replace_side": str( - old_subscription.iptrunk.iptrunk_sides[0].iptrunk_side_node.subscription.subscription_id + old_subscription.iptrunk.iptrunk_sides[0].iptrunk_side_node.subscription.subscription_id, ), }, { @@ -74,7 +74,10 @@ def test_migrate_iptrunk_success( { "new_lag_interface": "LAG1", "new_lag_member_interfaces": [ - LAGMember(interface_name=f"Interface{interface}", interface_description=faker.sentence()) + LAGMember( + interface_name=f"Interface{interface}", + interface_description=faker.sentence(), + ) for interface in range(2) ], }, @@ -102,7 +105,7 @@ def test_migrate_iptrunk_success( subscription_id = state["subscription_id"] subscription = Iptrunk.from_subscription(subscription_id) - assert "active" == subscription.status + assert subscription.status == "active" assert mock_provision_ip_trunk.call_count == 2 assert mock_migrate_ip_trunk.call_count == 7 # Assert all Netbox calls have been made diff --git a/test/workflows/iptrunk/test_modify_isis_metric.py b/test/workflows/iptrunk/test_modify_isis_metric.py index 0a303fb51151da3577dadfeac96892ba6c116dee..d26eded3abcdf104e7dc64a20cb36384f58fe398 100644 --- a/test/workflows/iptrunk/test_modify_isis_metric.py +++ b/test/workflows/iptrunk/test_modify_isis_metric.py @@ -3,10 +3,15 @@ from unittest.mock import patch import pytest from gso.products import Iptrunk -from test.workflows import assert_complete, assert_pp_interaction_success, extract_state, run_workflow +from test.workflows import ( + assert_complete, + assert_pp_interaction_success, + extract_state, + run_workflow, +) -@pytest.mark.workflow +@pytest.mark.workflow() @patch("gso.workflows.iptrunk.modify_isis_metric.provisioning_proxy.provision_ip_trunk") def test_iptrunk_modify_isis_metric_success( mock_provision_ip_trunk, @@ -33,6 +38,6 @@ def test_iptrunk_modify_isis_metric_success( subscription_id = state["subscription_id"] subscription = Iptrunk.from_subscription(subscription_id) - assert "active" == subscription.status + assert subscription.status == "active" assert mock_provision_ip_trunk.call_count == 2 assert subscription.iptrunk.iptrunk_isis_metric == new_isis_metric diff --git a/test/workflows/iptrunk/test_modify_trunk_interface.py b/test/workflows/iptrunk/test_modify_trunk_interface.py index 2cb048c3cfa39ae0c7b5c677ace2ffce48e05fcd..8601b8ad675bc0c287b98ad277f58bf3cc52c81e 100644 --- a/test/workflows/iptrunk/test_modify_trunk_interface.py +++ b/test/workflows/iptrunk/test_modify_trunk_interface.py @@ -4,11 +4,16 @@ import pytest from gso.products import Iptrunk from gso.products.product_blocks.iptrunk import IptrunkType, PhyPortCapacity -from test.workflows import assert_complete, assert_pp_interaction_success, extract_state, run_workflow +from test.workflows import ( + assert_complete, + assert_pp_interaction_success, + extract_state, + run_workflow, +) from test.workflows.iptrunk.test_create_iptrunk import MockedNetboxClient -@pytest.mark.workflow +@pytest.mark.workflow() @patch("gso.workflows.iptrunk.modify_trunk_interface.provisioning_proxy.provision_ip_trunk") @patch("gso.services.netbox_client.NetboxClient.get_available_interfaces") @patch("gso.services.netbox_client.NetboxClient.attach_interface_to_lag") @@ -86,7 +91,7 @@ def test_iptrunk_modify_trunk_interface_success( subscription_id = state["subscription_id"] subscription = Iptrunk.from_subscription(subscription_id) - assert "active" == subscription.status + assert subscription.status == "active" assert mock_provision_ip_trunk.call_count == 2 # Assert all Netbox calls have been made assert mocked_reserve_interface.call_count == 10 # 5 interfaces per side @@ -107,7 +112,8 @@ def test_iptrunk_modify_trunk_interface_success( for interface in interfaces: if interface["interface_name"] == name: return interface - raise IndexError(f"Interface {name} not found!") + msg = f"Interface {name} not found!" + raise IndexError(msg) for member in subscription.iptrunk.iptrunk_sides[0].iptrunk_side_ae_members: assert ( diff --git a/test/workflows/iptrunk/test_terminate_iptrunk.py b/test/workflows/iptrunk/test_terminate_iptrunk.py index a3ac220a268f228373914b4e67446b6fa02d519f..1e17b34a631fc0a5f50b4d87945ef594c36b4af0 100644 --- a/test/workflows/iptrunk/test_terminate_iptrunk.py +++ b/test/workflows/iptrunk/test_terminate_iptrunk.py @@ -4,10 +4,15 @@ import pytest from gso.products import Iptrunk from test.services.conftest import MockedNetboxClient -from test.workflows import assert_complete, assert_pp_interaction_success, extract_state, run_workflow +from test.workflows import ( + assert_complete, + assert_pp_interaction_success, + extract_state, + run_workflow, +) -@pytest.mark.workflow +@pytest.mark.workflow() @patch("gso.workflows.iptrunk.terminate_iptrunk.provisioning_proxy.provision_ip_trunk") @patch("gso.workflows.iptrunk.terminate_iptrunk.provisioning_proxy.deprovision_ip_trunk") @patch("gso.workflows.iptrunk.terminate_iptrunk.infoblox.delete_network") @@ -32,7 +37,11 @@ def test_successful_iptrunk_termination( # Run workflow initial_iptrunk_data = [ {"subscription_id": product_id}, - {"tt_number": faker.tt_number(), "remove_configuration": True, "clean_up_ipam": True}, + { + "tt_number": faker.tt_number(), + "remove_configuration": True, + "clean_up_ipam": True, + }, ] result, process_stat, step_log = run_workflow("terminate_iptrunk", initial_iptrunk_data) @@ -49,7 +58,7 @@ def test_successful_iptrunk_termination( subscription_id = state["subscription_id"] subscription = Iptrunk.from_subscription(subscription_id) - assert "terminated" == subscription.status + assert subscription.status == "terminated" assert mock_provision_ip_trunk.call_count == 1 assert mock_deprovision_ip_trunk.call_count == 2 assert mock_infoblox_delete_network.call_count == 2 diff --git a/test/workflows/router/test_create_router.py b/test/workflows/router/test_create_router.py index 460541a81b11a049aeccfdc307336434e35b7ff6..67c6496cfb0b3f088a106d1d5737b66a49166b4a 100644 --- a/test/workflows/router/test_create_router.py +++ b/test/workflows/router/test_create_router.py @@ -17,7 +17,7 @@ from test.workflows import ( ) -@pytest.fixture +@pytest.fixture() def router_creation_input_form_data(site_subscription_factory, faker): router_site = site_subscription_factory() @@ -33,7 +33,7 @@ def router_creation_input_form_data(site_subscription_factory, faker): } -@pytest.mark.workflow +@pytest.mark.workflow() @patch("gso.workflows.router.create_router.provisioning_proxy.provision_router") @patch("gso.workflows.router.create_router.NetboxClient.create_device") @patch("gso.workflows.router.create_router.infoblox.hostname_available") @@ -87,7 +87,7 @@ def test_create_router_success( mac="00:00:00:00:00:00", ip=str(mock_v4), host=f"lo0.{mock_fqdn}", - ) + ), ], name=mock_fqdn, ) @@ -107,18 +107,23 @@ def test_create_router_success( state = extract_state(result) subscription = Router.from_subscription(subscription_id) - assert "active" == subscription.status + assert subscription.status == "active" assert subscription.description == f"Router {mock_fqdn}" assert mock_provision_router.call_count == 2 assert mock_netbox_create_device.call_count == 1 assert mock_find_host_by_fqdn.call_count == 1 assert mock_find_network_by_cidr.call_count == 3 - for error in ["ipam_warning", "ipam_si_warning", "ipam_ias_lt_ipv4_warning", "ipam_ias_lt_ipv6_warning"]: + for error in [ + "ipam_warning", + "ipam_si_warning", + "ipam_ias_lt_ipv4_warning", + "ipam_ias_lt_ipv6_warning", + ]: assert error not in state -@pytest.mark.workflow +@pytest.mark.workflow() @patch("gso.workflows.router.create_router.provisioning_proxy.provision_router") @patch("gso.workflows.router.create_router.NetboxClient.create_device") @patch("gso.workflows.router.create_router.infoblox.hostname_available") @@ -163,7 +168,7 @@ def test_create_router_lso_failure( mac="00:00:00:00:00:00", ip=str(mock_v4), host=f"lo0.{mock_fqdn}", - ) + ), ], name=mock_fqdn, ) @@ -188,7 +193,7 @@ def test_create_router_lso_failure( assert_pp_interaction_failure(result, process_stat, step_log) - assert "provisioning" == subscription.status + assert subscription.status == "provisioning" assert subscription.description == f"Router {mock_fqdn}" assert mock_provision_router.call_count == 2 diff --git a/test/workflows/router/test_terminate_router.py b/test/workflows/router/test_terminate_router.py index 1e585a5c70644b1f4736d9ca4b3876f8e16c2021..b7c31d98f3e799fe3f7650230af1b5b8e78940b7 100644 --- a/test/workflows/router/test_terminate_router.py +++ b/test/workflows/router/test_terminate_router.py @@ -6,12 +6,16 @@ from gso.products import Router from test.workflows import assert_complete, extract_state, run_workflow -@pytest.fixture +@pytest.fixture() def router_termination_input_form_data(site_subscription_factory, faker): - return {"tt_number": faker.tt_number(), "remove_configuration": True, "clean_up_ipam": True} + return { + "tt_number": faker.tt_number(), + "remove_configuration": True, + "clean_up_ipam": True, + } -@pytest.mark.workflow +@pytest.mark.workflow() @patch("gso.workflows.router.terminate_router.NetboxClient.delete_device") @patch("gso.workflows.router.terminate_router.infoblox.delete_host_by_ip") @patch("gso.workflows.router.terminate_router.infoblox.delete_network") @@ -28,7 +32,10 @@ def test_terminate_router_success( product_id = router_subscription_factory() # Run workflow - initial_router_data = [{"subscription_id": product_id}, router_termination_input_form_data] + initial_router_data = [ + {"subscription_id": product_id}, + router_termination_input_form_data, + ] result, process_stat, step_log = run_workflow("terminate_router", initial_router_data) assert_complete(result) @@ -36,7 +43,7 @@ def test_terminate_router_success( subscription_id = state["subscription_id"] subscription = Router.from_subscription(subscription_id) - assert "terminated" == subscription.status + assert subscription.status == "terminated" assert mock_delete_network.call_count == 3 assert mock_delete_device.call_count == 1 assert mock_delete_host_by_ip.call_count == 1 diff --git a/test/workflows/site/test_create_site.py b/test/workflows/site/test_create_site.py index c553d80a677aa0a2c3bbfc69b1ac03504ca5fe04..531c02f7215e877ad9ebc1f029082b40ebb2cc04 100644 --- a/test/workflows/site/test_create_site.py +++ b/test/workflows/site/test_create_site.py @@ -9,7 +9,7 @@ from gso.services.subscriptions import get_product_id_by_name from test.workflows import assert_complete, extract_state, run_workflow -@pytest.mark.workflow +@pytest.mark.workflow() def test_create_site(responses, faker): product_id = get_product_id_by_name(ProductType.SITE) initial_site_data = [ @@ -34,14 +34,14 @@ def test_create_site(responses, faker): state = extract_state(result) subscription_id = state["subscription_id"] subscription = Site.from_subscription(subscription_id) - assert "active" == subscription.status + assert subscription.status == "active" assert ( subscription.description == f"Site in {initial_site_data[1]['site_city']}, {initial_site_data[1]['site_country']}" ) -@pytest.mark.workflow +@pytest.mark.workflow() def test_site_name_is_incorrect(responses, faker): """Test validate site name on site creation. diff --git a/test/workflows/site/test_modify_site.py b/test/workflows/site/test_modify_site.py index 00475d7ef2ed93e998f336e52f6e61fc8c726346..2afac782ced138d9e67982d6402950e82ff5fca8 100644 --- a/test/workflows/site/test_modify_site.py +++ b/test/workflows/site/test_modify_site.py @@ -5,7 +5,7 @@ from gso.products.product_types.site import Site from test.workflows import assert_complete, extract_state, run_workflow -@pytest.mark.workflow +@pytest.mark.workflow() def test_modify_site(responses, site_subscription_factory): subscription_id = site_subscription_factory() initial_site_data = [ @@ -22,12 +22,12 @@ def test_modify_site(responses, site_subscription_factory): state = extract_state(result) subscription_id = state["subscription_id"] subscription = Site.from_subscription(subscription_id) - assert "active" == subscription.status + assert subscription.status == "active" assert subscription.site.site_bgp_community_id == initial_site_data[1]["site_bgp_community_id"] assert subscription.site.site_internal_id == initial_site_data[1]["site_internal_id"] -@pytest.mark.workflow +@pytest.mark.workflow() def test_modify_site_with_invalid_data(responses, site_subscription_factory): subscription_a = Site.from_subscription(site_subscription_factory()) subscription_b = Site.from_subscription(site_subscription_factory()) diff --git a/test/workflows/site/test_terminate_site.py b/test/workflows/site/test_terminate_site.py index fc88b10273a12bbaed779715b0bb45d976a84432..25347c9d067a8b8426805b7f9834192490ffcf2c 100644 --- a/test/workflows/site/test_terminate_site.py +++ b/test/workflows/site/test_terminate_site.py @@ -4,7 +4,7 @@ from gso.products.product_types.site import Site from test.workflows import assert_complete, extract_state, run_workflow -@pytest.mark.workflow +@pytest.mark.workflow() def test_terminate_site(responses, site_subscription_factory): subscription_id = site_subscription_factory() initial_site_data = [{"subscription_id": subscription_id}, {}] @@ -14,4 +14,4 @@ def test_terminate_site(responses, site_subscription_factory): state = extract_state(result) subscription_id = state["subscription_id"] subscription = Site.from_subscription(subscription_id) - assert "terminated" == subscription.status + assert subscription.status == "terminated" diff --git a/utils/netboxcli.py b/utils/netboxcli.py index 64f8f3ffe955b53e4f934e7b38f4f12ece6ffbe0..f5bdc92b598a41b3c1c921481d7914d7a79c7a4f 100644 --- a/utils/netboxcli.py +++ b/utils/netboxcli.py @@ -1,230 +1,242 @@ -"""Command line tool to communicate with the NetBox API.""" -from typing import Any, Dict, List - -import click -import pandas as pd - -from gso.services.netbox_client import NetboxClient - - -def convert_to_table(data: List[Dict[str, Any]], fields: List[str]) -> pd.DataFrame: - if not data: - raise ValueError("No data is available for your request") - - df = pd.DataFrame(data) - if fields: - df = df[fields] - - return df - - -@click.group() -def cli() -> None: - pass - - -@cli.group() -def create() -> None: - pass - - -@create.command() -@click.option("--fqdn", prompt="Enter device name", help="Device name") -@click.option("--model", default="vmx", help="Device model") -def device(fqdn: str, model: str) -> None: - click.echo(f"Creating device: fqdn={fqdn}, model={model}") - new_device = NetboxClient().create_device(fqdn, model) - click.echo(new_device) - - -@create.command() -@click.option("--name", help="Interface name") -@click.option("--type", default="10gbase-t", help="Interface type, default is 10GBASE-T") -@click.option("--speed", default="1000", help="Interface speed , default is 1000") -@click.option("--fqdn", help="Device where to create interface") -def interface(name: str, type: str, speed: str, fqdn: str) -> None: - click.echo(f"Creating interface: name={name}, speed={speed}, fqdn={fqdn}") - new_interface = NetboxClient().create_interface(name, type, speed, fqdn) - click.echo(new_interface) - - -@create.command() -@click.option("--name", help="Manufacturer name") -@click.option("--slug", help="Short name for manufacturer") -def manufacturer(name: str, slug: str) -> None: - click.echo(f"Creating manufacturer: name={name}") - manufacturer = NetboxClient().create_device_manufacturer(name, slug) - click.echo(manufacturer) - - -@create.command() -@click.option("--manufacturer", help="Manufacturer for device") -@click.option("--model", help="Model for device") -@click.option("--slug", help="Short name for manufacturer") -def device_type(manufacturer: str, model: str, slug: str) -> None: - click.echo(f"Creating device type: manufacturer={manufacturer} model = {model}") - device_type = NetboxClient().create_device_type(manufacturer, model, slug) - click.echo(device_type) - - -@create.command() -@click.option("--name", help="Name for device role") -@click.option("--slug", help="Short name for device role") -def device_role(name: str, slug: str) -> None: - click.echo(f"Creating device role: name={name}") - device_role = NetboxClient().create_device_role(name, slug) - click.echo(device_role) - - -@create.command() -@click.option("--name", help="Name for device site") -@click.option("--slug", help="Short name for device site") -def device_site(name: str, slug: str) -> None: - click.echo(f"Creating device site: name={name}") - device_site = NetboxClient().create_device_site(name, slug) - click.echo(device_site) - - -create.add_command(device) -create.add_command(interface) -create.add_command(manufacturer) -create.add_command(device_type) -create.add_command(device_role) -create.add_command(device_site) - - -# Define list commands here -@cli.group() -def list() -> None: - pass - - -@list.command() -@click.option("--fqdn", help="Device name to list interfaces") -@click.option("--speed", default="1000", help="Interface speed to list interfaces (default 1000=1G)") -def interfaces(fqdn: str, speed: str) -> None: - click.echo(f"Listing all interfaces for: device with fqdn={fqdn}, speed={speed}") - interface_list = NetboxClient().get_interfaces_by_device(fqdn, speed) - display_fields = ["name", "enabled", "mark_connected", "custom_fields", "lag", "speed"] - iface_list = [] - for iface in interface_list: - iface_list.append(dict(iface)) - - table = convert_to_table(iface_list, display_fields) - click.echo(table) - - -@list.command() -def devices() -> None: - click.echo("Listing all devices:") - device_list = NetboxClient().get_all_devices() - display_fields = ["name", "device_type"] - devices = [] - for device in device_list: - devices.append(dict(device)) - - table = convert_to_table(devices, display_fields) - click.echo(table) - - -list.add_command(interfaces) -list.add_command(devices) - - -# Define delete commands here -@cli.group() -def delete() -> None: - pass - - -@delete.command() # type: ignore[no-redef] -@click.option("--fqdn", help="Name of device to delete") -def device(fqdn: str) -> None: - click.echo(f"Deleting device: device={fqdn}") - NetboxClient().delete_device(fqdn) - - -@delete.command() # type: ignore[no-redef] -@click.option("--fqdn", help="Device name from where to get interface to delete") -@click.option("--iface", help="Name of interface name to delete") -def interface(fqdn: str, iface: str) -> None: - click.echo(f"Deleting interface: device={fqdn}, interface name={iface}") - NetboxClient().delete_interface(fqdn, iface) - - -delete.add_command(device) -delete.add_command(interface) - - -# The action command -@cli.group() -def action() -> None: - pass - - -@action.command() -@click.option("--fqdn", help="Device name from where to get interface to edit") -@click.option("--iface", help="Interface name to edit") -def reserve_interface(fqdn: str, iface: str) -> None: - click.echo(f"Reserving interface: device ={fqdn}, interface name={iface}") - reserved_iface = NetboxClient().reserve_interface(fqdn, iface) - click.echo(reserved_iface) - - -@action.command() -@click.option("--fqdn", help="Device name from where to get interface to edit") -@click.option("--iface", help="Interface name to edit") -def free_interface(fqdn: str, iface: str) -> None: - click.echo(f"Freeing interface: device={fqdn}, interface name={iface}") - freed_iface = NetboxClient().free_interface(fqdn, iface) - click.echo(freed_iface) - - -@action.command() -@click.option("--fqdn", help="Device name from where to get interface to edit") -@click.option("--iface", help="Interface name to edit") -def allocate_interface(fqdn: str, iface: str) -> None: - click.echo(f"Allocating interface: device={fqdn}, interface name={iface}") - allocated_iface = NetboxClient().allocate_interface(fqdn, iface) - click.echo(allocated_iface) - - -@action.command() -@click.option("--fqdn", help="Device name from where to get interface to edit") -@click.option("--iface", help="Interface name to edit") -def deallocate_interface(fqdn: str, iface: str) -> None: - click.echo(f"Deallocating interface: device={fqdn}, interface name={iface}") - deallocated_iface = NetboxClient().free_interface(fqdn, iface) - click.echo(deallocated_iface) - - -@action.command() -@click.option("--fqdn", help="Device name from where to get physical interface to attach LAG") -@click.option("--lag", help="LAG name to attach physical interface to") -@click.option("--iface", help="Interface name to attach to LAG") -def attach_interface_to_lag(fqdn: str, lag: str, iface: str) -> None: - click.echo(f"Attaching LAG to physical interface: device={fqdn}, LAG name={lag}, interface name={iface}") - attached_iface = NetboxClient().attach_interface_to_lag(fqdn, lag, iface) - click.echo(attached_iface) - - -@action.command() -@click.option("--fqdn", help="Device name from where to get physical interface to detach LAG") -@click.option("--lag", help="LAG name to detach from physical interface") -@click.option("--iface", help="Interface name to detach LAG from") -def detach_interface_from_lag(fqdn: str, lag: str, iface: str) -> None: - click.echo(f"Detaching LAG from physical interface: device={fqdn}, LAG name={lag}, interface name={iface}") - NetboxClient().detach_interfaces_from_lag(fqdn, lag) - click.echo(f"Detached LAG from physical interface: device={fqdn}, LAG name={lag}, interface name={iface}") - - -action.add_command(reserve_interface) -action.add_command(free_interface) -action.add_command(allocate_interface) -action.add_command(deallocate_interface) -action.add_command(attach_interface_to_lag) -action.add_command(detach_interface_from_lag) - - -if __name__ == "__main__": - cli() +"""Command line tool to communicate with the NetBox API.""" +from typing import Any + +import click +import pandas as pd + +from gso.services.netbox_client import NetboxClient + + +def convert_to_table(data: list[dict[str, Any]], fields: list[str]) -> pd.DataFrame: + if not data: + msg = "No data is available for your request" + raise ValueError(msg) + + df = pd.DataFrame(data) + if fields: + df = df[fields] + + return df + + +@click.group() +def cli() -> None: + pass + + +@cli.group() +def create() -> None: + pass + + +@create.command() +@click.option("--fqdn", prompt="Enter device name", help="Device name") +@click.option("--model", default="vmx", help="Device model") +def device(fqdn: str, model: str) -> None: + click.echo(f"Creating device: fqdn={fqdn}, model={model}") + new_device = NetboxClient().create_device(fqdn, model) + click.echo(new_device) + + +@create.command() +@click.option("--name", help="Interface name") +@click.option("--type", default="10gbase-t", help="Interface type, default is 10GBASE-T") +@click.option("--speed", default="1000", help="Interface speed , default is 1000") +@click.option("--fqdn", help="Device where to create interface") +def interface(name: str, type: str, speed: str, fqdn: str) -> None: + click.echo(f"Creating interface: name={name}, speed={speed}, fqdn={fqdn}") + new_interface = NetboxClient().create_interface(name, type, speed, fqdn) + click.echo(new_interface) + + +@create.command() +@click.option("--name", help="Manufacturer name") +@click.option("--slug", help="Short name for manufacturer") +def manufacturer(name: str, slug: str) -> None: + click.echo(f"Creating manufacturer: name={name}") + manufacturer = NetboxClient().create_device_manufacturer(name, slug) + click.echo(manufacturer) + + +@create.command() +@click.option("--manufacturer", help="Manufacturer for device") +@click.option("--model", help="Model for device") +@click.option("--slug", help="Short name for manufacturer") +def device_type(manufacturer: str, model: str, slug: str) -> None: + click.echo(f"Creating device type: manufacturer={manufacturer} model = {model}") + device_type = NetboxClient().create_device_type(manufacturer, model, slug) + click.echo(device_type) + + +@create.command() +@click.option("--name", help="Name for device role") +@click.option("--slug", help="Short name for device role") +def device_role(name: str, slug: str) -> None: + click.echo(f"Creating device role: name={name}") + device_role = NetboxClient().create_device_role(name, slug) + click.echo(device_role) + + +@create.command() +@click.option("--name", help="Name for device site") +@click.option("--slug", help="Short name for device site") +def device_site(name: str, slug: str) -> None: + click.echo(f"Creating device site: name={name}") + device_site = NetboxClient().create_device_site(name, slug) + click.echo(device_site) + + +create.add_command(device) +create.add_command(interface) +create.add_command(manufacturer) +create.add_command(device_type) +create.add_command(device_role) +create.add_command(device_site) + + +# Define list commands here +@cli.group() +def list() -> None: + pass + + +@list.command() +@click.option("--fqdn", help="Device name to list interfaces") +@click.option( + "--speed", + default="1000", + help="Interface speed to list interfaces (default 1000=1G)", +) +def interfaces(fqdn: str, speed: str) -> None: + click.echo(f"Listing all interfaces for: device with fqdn={fqdn}, speed={speed}") + interface_list = NetboxClient().get_interfaces_by_device(fqdn, speed) + display_fields = [ + "name", + "enabled", + "mark_connected", + "custom_fields", + "lag", + "speed", + ] + iface_list = [] + for iface in interface_list: + iface_list.append(dict(iface)) + + table = convert_to_table(iface_list, display_fields) + click.echo(table) + + +@list.command() +def devices() -> None: + click.echo("Listing all devices:") + device_list = NetboxClient().get_all_devices() + display_fields = ["name", "device_type"] + devices = [] + for device in device_list: + devices.append(dict(device)) + + table = convert_to_table(devices, display_fields) + click.echo(table) + + +list.add_command(interfaces) +list.add_command(devices) + + +# Define delete commands here +@cli.group() +def delete() -> None: + pass + + +@delete.command() # type: ignore[no-redef] +@click.option("--fqdn", help="Name of device to delete") +def device(fqdn: str) -> None: + click.echo(f"Deleting device: device={fqdn}") + NetboxClient().delete_device(fqdn) + + +@delete.command() # type: ignore[no-redef] +@click.option("--fqdn", help="Device name from where to get interface to delete") +@click.option("--iface", help="Name of interface name to delete") +def interface(fqdn: str, iface: str) -> None: + click.echo(f"Deleting interface: device={fqdn}, interface name={iface}") + NetboxClient().delete_interface(fqdn, iface) + + +delete.add_command(device) +delete.add_command(interface) + + +# The action command +@cli.group() +def action() -> None: + pass + + +@action.command() +@click.option("--fqdn", help="Device name from where to get interface to edit") +@click.option("--iface", help="Interface name to edit") +def reserve_interface(fqdn: str, iface: str) -> None: + click.echo(f"Reserving interface: device ={fqdn}, interface name={iface}") + reserved_iface = NetboxClient().reserve_interface(fqdn, iface) + click.echo(reserved_iface) + + +@action.command() +@click.option("--fqdn", help="Device name from where to get interface to edit") +@click.option("--iface", help="Interface name to edit") +def free_interface(fqdn: str, iface: str) -> None: + click.echo(f"Freeing interface: device={fqdn}, interface name={iface}") + freed_iface = NetboxClient().free_interface(fqdn, iface) + click.echo(freed_iface) + + +@action.command() +@click.option("--fqdn", help="Device name from where to get interface to edit") +@click.option("--iface", help="Interface name to edit") +def allocate_interface(fqdn: str, iface: str) -> None: + click.echo(f"Allocating interface: device={fqdn}, interface name={iface}") + allocated_iface = NetboxClient().allocate_interface(fqdn, iface) + click.echo(allocated_iface) + + +@action.command() +@click.option("--fqdn", help="Device name from where to get interface to edit") +@click.option("--iface", help="Interface name to edit") +def deallocate_interface(fqdn: str, iface: str) -> None: + click.echo(f"Deallocating interface: device={fqdn}, interface name={iface}") + deallocated_iface = NetboxClient().free_interface(fqdn, iface) + click.echo(deallocated_iface) + + +@action.command() +@click.option("--fqdn", help="Device name from where to get physical interface to attach LAG") +@click.option("--lag", help="LAG name to attach physical interface to") +@click.option("--iface", help="Interface name to attach to LAG") +def attach_interface_to_lag(fqdn: str, lag: str, iface: str) -> None: + click.echo(f"Attaching LAG to physical interface: device={fqdn}, LAG name={lag}, interface name={iface}") + attached_iface = NetboxClient().attach_interface_to_lag(fqdn, lag, iface) + click.echo(attached_iface) + + +@action.command() +@click.option("--fqdn", help="Device name from where to get physical interface to detach LAG") +@click.option("--lag", help="LAG name to detach from physical interface") +@click.option("--iface", help="Interface name to detach LAG from") +def detach_interface_from_lag(fqdn: str, lag: str, iface: str) -> None: + click.echo(f"Detaching LAG from physical interface: device={fqdn}, LAG name={lag}, interface name={iface}") + NetboxClient().detach_interfaces_from_lag(fqdn, lag) + click.echo(f"Detached LAG from physical interface: device={fqdn}, LAG name={lag}, interface name={iface}") + + +action.add_command(reserve_interface) +action.add_command(free_interface) +action.add_command(allocate_interface) +action.add_command(deallocate_interface) +action.add_command(attach_interface_to_lag) +action.add_command(detach_interface_from_lag) + + +if __name__ == "__main__": + cli()