Skip to content
Snippets Groups Projects
Commit e567da26 authored by Mohammad Torkashvand's avatar Mohammad Torkashvand
Browse files

added an API for getting all active subscriptions

parent 8701ab80
No related branches found
No related tags found
1 merge request!87added an API for getting all active subscriptions
Pipeline #84252 passed
from fastapi import APIRouter
from gso.api.v1.imports import router as imports_router
from gso.api.v1.subscriptions import router as subscriptions_router
router = APIRouter()
router.include_router(imports_router)
router.include_router(subscriptions_router)
......@@ -77,7 +77,8 @@ class IptrunkImportModel(BaseModel):
@classmethod
def _get_active_routers(cls) -> set[str]:
return {
str(router_id) for router_id in subscriptions.get_active_router_subscriptions(fields=["subscription_id"])
str(router["subscription_id"])
for router in subscriptions.get_active_router_subscriptions(includes=["subscription_id"])
}
@validator("customer")
......
from typing import Any
from fastapi import Depends, status
from fastapi.routing import APIRouter
from orchestrator.domain import SubscriptionModel
from orchestrator.schemas import SubscriptionDomainModelSchema
from orchestrator.security import opa_security_default
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.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 = []
for r in get_active_router_subscriptions():
subscription = SubscriptionModel.from_subscription(r["subscription_id"])
extended_model = build_extended_domain_model(subscription)
subscriptions.append(extended_model)
return subscriptions
from typing import Any
from uuid import UUID
from asyncio_redis import Subscription
from orchestrator.db import (
ProductTable,
ResourceTypeTable,
......@@ -8,57 +8,71 @@ from orchestrator.db import (
SubscriptionInstanceValueTable,
SubscriptionTable,
)
from orchestrator.graphql.schemas.subscription import Subscription
from orchestrator.types import SubscriptionLifecycle
from gso.products import ProductType
SubscriptionType = dict[str, Any]
def get_active_subscriptions(product_type: str, fields: list[str]) -> list[Subscription]:
def get_active_subscriptions(
product_type: str,
includes: list[str] | None = None,
excludes: list[str] | None = None,
) -> list[SubscriptionType]:
"""Retrieve active subscriptions for a specific product type.
:param product_type: The type of the product for which to retrieve subscriptions.
:type product_type: str
:param fields: List of fields to be included in the returned Subscription objects.
:type fields: list[str]
:param includes: List of fields to be included in the returned Subscription objects.
:type includes: list[str]
:param excludes: List of fields to be excluded from the returned Subscription objects.
:type excludes: list[str]
:return: A list of Subscription objects that match the query.
:rtype: list[Subscription]
"""
dynamic_fields = [getattr(SubscriptionTable, field) for field in fields]
if not includes:
includes = [col.name for col in SubscriptionTable.__table__.columns]
return (
SubscriptionTable.query.join(ProductTable)
.filter(
ProductTable.product_type == product_type,
SubscriptionTable.status == SubscriptionLifecycle.ACTIVE,
)
.with_entities(*dynamic_fields)
.all()
if excludes:
includes = [field for field in includes if field not in excludes]
dynamic_fields = [getattr(SubscriptionTable, field) for field in includes]
query = SubscriptionTable.query.join(ProductTable).filter(
ProductTable.product_type == product_type,
SubscriptionTable.status == SubscriptionLifecycle.ACTIVE,
)
results = query.with_entities(*dynamic_fields).all()
return [dict(zip(includes, result)) for result in results]
def get_active_site_subscriptions(fields: list[str]) -> list[Subscription]:
def get_active_site_subscriptions(includes: list[str] | None = None) -> list[SubscriptionType]:
"""Retrieve active subscriptions specifically for sites.
:param fields: The fields to be included in the returned Subscription objects.
:type fields: list[str]
:param includes: The fields to be included in the returned Subscription objects.
:type includes: list[str]
:return: A list of Subscription objects for sites.
:rtype: list[Subscription]
"""
return get_active_subscriptions(ProductType.SITE, fields)
return get_active_subscriptions(product_type=ProductType.SITE, includes=includes)
def get_active_router_subscriptions(fields: list[str]) -> list[Subscription]:
def get_active_router_subscriptions(includes: list[str] | None = None) -> list[SubscriptionType]:
"""Retrieve active subscriptions specifically for routers.
:param fields: The fields to be included in the returned Subscription objects.
:type fields: list[str]
:param includes: The fields to be included in the returned Subscription objects.
:type includes: list[str]
:return: A list of Subscription objects for routers.
:rtype: list[Subscription]
"""
return get_active_subscriptions(product_type=ProductType.ROUTER, fields=fields)
return get_active_subscriptions(product_type=ProductType.ROUTER, includes=includes)
def get_product_id_by_name(product_name: ProductType) -> UUID:
......
......@@ -33,10 +33,9 @@ def initial_input_form_generator(product_name: str) -> FormGenerator:
# * interface names must be validated
routers = {}
for router_id, router_description in subscriptions.get_active_router_subscriptions(
fields=["subscription_id", "description"]
):
routers[str(router_id)] = router_description
for router in subscriptions.get_active_router_subscriptions(includes=["subscription_id", "description"]):
routers[str(router["subscription_id"])] = router["description"]
class CreateIptrunkForm(FormPage):
class Config:
......
......@@ -23,10 +23,8 @@ from gso.utils.helpers import iso_from_ipv4
def _site_selector() -> Choice:
site_subscriptions = {}
for site_id, site_description in subscriptions.get_active_site_subscriptions(
fields=["subscription_id", "description"]
):
site_subscriptions[str(site_id)] = site_description
for site in subscriptions.get_active_site_subscriptions(includes=["subscription_id", "description"]):
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]
......
......@@ -20,10 +20,9 @@ from gso.workflows.iptrunk.create_iptrunk import initialize_subscription
def _generate_routers() -> dict[str, str]:
"""Generate a dictionary of router IDs and descriptions."""
routers = {}
for router_id, router_description in subscriptions.get_active_router_subscriptions(
fields=["subscription_id", "description"]
):
routers[str(router_id)] = router_description
for subscription in subscriptions.get_active_router_subscriptions(includes=["subscription_id", "description"]):
routers[str(subscription["subscription_id"])] = subscription["description"]
return routers
......
......@@ -86,6 +86,7 @@ def router_subscription_factory(site_subscription_factory, faker):
router_role=RouterRole.PE,
router_site=None,
router_is_ias_connected=True,
status: SubscriptionLifecycle | None = None,
) -> UUIDstr:
description = description or faker.text(max_nb_chars=30)
router_fqdn = router_fqdn or faker.domain_name(levels=4)
......@@ -118,6 +119,10 @@ def router_subscription_factory(site_subscription_factory, faker):
router_subscription = SubscriptionModel.from_other_lifecycle(router_subscription, SubscriptionLifecycle.ACTIVE)
router_subscription.description = description
router_subscription.start_date = start_date
if status:
router_subscription.status = status
router_subscription.save()
db.session.commit()
......
......@@ -48,13 +48,23 @@ def mock_routers(iptrunk_data):
with patch("gso.services.subscriptions.get_active_router_subscriptions") as mock_get_active_router_subscriptions:
def _active_router_subscriptions(*args, **kwargs):
if kwargs["fields"] == ["subscription_id", "description"]:
if kwargs["includes"] == ["subscription_id", "description"]:
return [
(iptrunk_data["side_a_node_id"], "side_a_node_id description"),
(iptrunk_data["side_b_node_id"], "side_b_node_id description"),
(str(uuid4()), "random description"),
{
"subscription_id": iptrunk_data["side_a_node_id"],
"description": "iptrunk_sideA_node_id description",
},
{
"subscription_id": iptrunk_data["side_b_node_id"],
"description": "iptrunk_sideB_node_id description",
},
{"subscription_id": str(uuid4()), "description": "random description"},
]
return [iptrunk_data["side_a_node_id"], iptrunk_data["side_b_node_id"], str(uuid4())]
return [
{"subscription_id": iptrunk_data["side_a_node_id"]},
{"subscription_id": iptrunk_data["side_b_node_id"]},
{"subscription_id": str(uuid4())},
]
mock_get_active_router_subscriptions.side_effect = _active_router_subscriptions
yield mock_get_active_router_subscriptions
......@@ -200,6 +210,9 @@ def test_import_iptrunk_invalid_customer(mock_start_process, test_client, mock_r
@patch("gso.api.v1.imports._start_process")
def test_import_iptrunk_invalid_router_id_side_a_and_b(mock_start_process, test_client, iptrunk_data):
iptrunk_data["side_a_node_id"] = "NOT FOUND"
iptrunk_data["side_b_node_id"] = "NOT FOUND"
mock_start_process.return_value = "123e4567-e89b-12d3-a456-426655440000"
response = test_client.post(IPTRUNK_IMPORT_API_URL, json=iptrunk_data)
......
from test.fixtures import router_subscription_factory, site_subscription_factory # noqa
from orchestrator.types import SubscriptionLifecycle
ROUTER_SUBSCRIPTION_ENDPOINT = "/api/v1/subscriptions/routers"
def test_router_subscriptions_endpoint(test_client, router_subscription_factory):
router_subscription_factory()
router_subscription_factory()
router_subscription_factory()
router_subscription_factory(status=SubscriptionLifecycle.TERMINATED)
router_subscription_factory(status=SubscriptionLifecycle.INITIAL)
response = test_client.get(ROUTER_SUBSCRIPTION_ENDPOINT)
assert response.status_code == 200
assert len(response.json()) == 3
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment