diff --git a/gso/api/v1/imports.py b/gso/api/v1/imports.py index 5a7ef6c6ef791747fda0e82ee3300e4c45df4edf..c99db7736804aaeea9a1fe36d65ef9c3ed472d91 100644 --- a/gso/api/v1/imports.py +++ b/gso/api/v1/imports.py @@ -6,16 +6,21 @@ from fastapi import Depends, HTTPException, status from fastapi.routing import APIRouter from orchestrator.security import opa_security_default from orchestrator.services import processes -from orchestrator.services import subscriptions as wfo_subscriptions from pydantic import BaseModel, root_validator, validator -from sqlalchemy.exc import MultipleResultsFound +from pydantic.fields import ModelField from gso.products.product_blocks.iptrunk import IptrunkType, PhyPortCapacity from gso.products.product_blocks.router import RouterRole, RouterVendor from gso.products.product_blocks.site import SiteTier from gso.services import subscriptions from gso.services.crm import CustomerNotFoundError, get_customer_by_name -from gso.utils.helpers import LAGMember +from gso.utils.helpers import ( + LAGMember, + validate_country_code, + validate_ipv4_or_ipv6, + validate_site_fields_is_unique, + validate_site_name, +) router = APIRouter(prefix="/imports", tags=["Imports"], dependencies=[Depends(opa_security_default)]) @@ -38,6 +43,32 @@ class SiteImportModel(BaseModel): site_ts_address: str customer: str + @validator("site_ts_address", allow_reuse=True) + def validate_ts_address(cls, site_ts_address: str) -> str: + validate_site_fields_is_unique("site_ts_address", site_ts_address) + validate_ipv4_or_ipv6(site_ts_address) + return site_ts_address + + @validator("site_country_code", allow_reuse=True) + def country_code_must_exist(cls, country_code: str) -> str: + validate_country_code(country_code) + return country_code + + @validator("site_internal_id", "site_bgp_community_id", allow_reuse=True) + def validate_unique_fields(cls, value: str, field: ModelField) -> str | int: + return validate_site_fields_is_unique(field.name, value) + + @validator("site_name", allow_reuse=True) + def site_name_must_be_valid(cls, site_name: str) -> str: + """Validate the site name. + + The site name must consist of three uppercase letters (A-Z) followed + by an optional single digit (0-9). + """ + validate_site_fields_is_unique("site_name", site_name) + validate_site_name(site_name) + return site_name + class RouterImportModel(BaseModel): customer: str @@ -151,15 +182,6 @@ def import_site(site: SiteImportModel) -> dict[str, Any]: :raises HTTPException: If the site already exists or if there's an error in the process. """ - try: - subscription = wfo_subscriptions.retrieve_subscription_by_subscription_instance_value( - resource_type="site_name", value=site.site_name, sub_status=("provisioning", "active") - ) - if subscription: - raise HTTPException(status_code=status.HTTP_409_CONFLICT, detail="Site already exists.") - except MultipleResultsFound: - raise HTTPException(status_code=status.HTTP_409_CONFLICT, detail="Multiple subscriptions found.") - pid = _start_process("import_site", site.dict()) return {"detail": "Site added successfully.", "pid": pid} diff --git a/gso/workflows/tasks/import_site.py b/gso/workflows/tasks/import_site.py index fd3a55cc77b80250951076302e21668b75c151f2..af96fca24e6e67d0ffac5013c593eed238a16706 100644 --- a/gso/workflows/tasks/import_site.py +++ b/gso/workflows/tasks/import_site.py @@ -5,20 +5,12 @@ from orchestrator.targets import Target from orchestrator.types import FormGenerator, State, SubscriptionLifecycle from orchestrator.workflow import StepList, done, init, step, workflow from orchestrator.workflows.steps import resync, set_status, store_process_subscription -from pydantic import validator -from pydantic.fields import ModelField from gso.products import ProductType from gso.products.product_blocks.site import SiteTier from gso.products.product_types.site import SiteInactive from gso.services import subscriptions from gso.services.crm import get_customer_by_name -from gso.utils.helpers import ( - validate_country_code, - validate_ipv4_or_ipv6, - validate_site_fields_is_unique, - validate_site_name, -) from gso.workflows.site.create_site import initialize_subscription @@ -51,32 +43,6 @@ def generate_initial_input_form() -> FormGenerator: site_ts_address: str customer: str - @validator("site_ts_address", allow_reuse=True) - def validate_ts_address(cls, site_ts_address: str) -> str: - validate_site_fields_is_unique("site_ts_address", site_ts_address) - validate_ipv4_or_ipv6(site_ts_address) - return site_ts_address - - @validator("site_country_code", allow_reuse=True) - def country_code_must_exist(cls, country_code: str) -> str: - validate_country_code(country_code) - return country_code - - @validator("site_internal_id", "site_bgp_community_id", allow_reuse=True) - def validate_unique_fields(cls, value: str, field: ModelField) -> str | int: - return validate_site_fields_is_unique(field.name, value) - - @validator("site_name", allow_reuse=True) - def site_name_must_be_valid(cls, site_name: str) -> str: - """Validate the site name. - - The site name must consist of three uppercase letters (A-Z) followed - by an optional single digit (0-9). - """ - validate_site_fields_is_unique("site_name", site_name) - validate_site_name(site_name) - return site_name - user_input = yield ImportSite return user_input.dict() diff --git a/test/imports/test_imports.py b/test/imports/test_imports.py index d63651f2b1880c53b3a8aee4775ae796b81e46bb..82a8eae6cc75bbe0374a6696b3acd0dc72b15ba9 100644 --- a/test/imports/test_imports.py +++ b/test/imports/test_imports.py @@ -132,7 +132,7 @@ def test_import_site_endpoint_with_existing_site(test_client, site_data): assert response.status_code == 201 response = test_client.post(SITE_IMPORT_ENDPOINT, json=site_data) - assert response.status_code == 409 + assert response.status_code == 422 assert SubscriptionTable.query.count() == 1