From 1f5e2a0a381bfa980eb24074203840743f7f1752 Mon Sep 17 00:00:00 2001
From: Karel van Klink <karel.vanklink@geant.org>
Date: Tue, 10 Sep 2024 14:03:19 +0200
Subject: [PATCH] Move types module into utils to avoid collision with existing
 external module

---
 gso/api/v1/network.py                         |  4 +-
 gso/cli/imports.py                            |  7 ++--
 gso/products/product_blocks/iptrunk.py        |  2 +-
 .../product_blocks/lan_switch_interconnect.py |  2 +-
 gso/products/product_blocks/office_router.py  |  3 +-
 gso/products/product_blocks/router.py         |  3 +-
 gso/products/product_blocks/site.py           |  6 +--
 .../product_blocks/super_pop_switch.py        |  3 +-
 gso/products/product_blocks/switch.py         |  3 +-
 gso/services/infoblox.py                      |  2 +-
 gso/services/librenms_client.py               |  2 +-
 gso/settings.py                               |  2 +-
 gso/types/ip_address.py                       | 20 ----------
 gso/utils/helpers.py                          |  5 ++-
 gso/utils/shared_enums.py                     | 28 --------------
 gso/{ => utils}/types/__init__.py             |  0
 gso/{ => utils}/types/base_site.py            | 10 ++---
 gso/{ => utils}/types/coordinates.py          |  0
 gso/{ => utils}/types/country_code.py         |  0
 gso/{ => utils}/types/interfaces.py           |  0
 gso/utils/types/ip_address.py                 | 38 +++++++++++++++++++
 gso/{ => utils}/types/netbox_router.py        |  0
 gso/{ => utils}/types/site_name.py            |  0
 gso/{ => utils}/types/snmp.py                 |  0
 gso/{ => utils}/types/tt_number.py            |  0
 gso/{ => utils}/types/unique_field.py         |  0
 .../iptrunk/create_imported_iptrunk.py        |  2 +-
 gso/workflows/iptrunk/create_iptrunk.py       |  6 +--
 gso/workflows/iptrunk/deploy_twamp.py         |  2 +-
 gso/workflows/iptrunk/migrate_iptrunk.py      |  4 +-
 gso/workflows/iptrunk/modify_isis_metric.py   |  2 +-
 .../iptrunk/modify_trunk_interface.py         |  7 ++--
 gso/workflows/iptrunk/terminate_iptrunk.py    |  2 +-
 .../create_lan_switch_interconnect.py         | 18 ++++-----
 .../create_imported_office_router.py          |  3 +-
 .../opengear/create_imported_opengear.py      |  2 +-
 .../router/create_imported_router.py          |  3 +-
 gso/workflows/router/create_router.py         |  5 ++-
 gso/workflows/router/promote_p_to_pe.py       |  2 +-
 gso/workflows/router/redeploy_base_config.py  |  2 +-
 gso/workflows/router/terminate_router.py      |  2 +-
 gso/workflows/router/update_ibgp_mesh.py      |  4 +-
 gso/workflows/site/create_imported_site.py    |  6 +--
 gso/workflows/site/create_site.py             |  6 +--
 gso/workflows/site/modify_site.py             |  6 +--
 .../create_imported_super_pop_switch.py       |  3 +-
 test/cli/test_imports.py                      |  2 +-
 test/conftest.py                              |  2 +-
 test/fixtures.py                              |  2 +-
 test/schemas/test_types.py                    |  2 +-
 test/services/test_librenms_client.py         |  2 +-
 test/utils/test_helpers.py                    |  2 +-
 .../iptrunk/test_create_imported_iptrunk.py   |  2 +-
 test/workflows/iptrunk/test_create_iptrunk.py |  2 +-
 .../iptrunk/test_modify_trunk_interface.py    |  2 +-
 55 files changed, 123 insertions(+), 122 deletions(-)
 delete mode 100644 gso/types/ip_address.py
 rename gso/{ => utils}/types/__init__.py (100%)
 rename gso/{ => utils}/types/base_site.py (69%)
 rename gso/{ => utils}/types/coordinates.py (100%)
 rename gso/{ => utils}/types/country_code.py (100%)
 rename gso/{ => utils}/types/interfaces.py (100%)
 create mode 100644 gso/utils/types/ip_address.py
 rename gso/{ => utils}/types/netbox_router.py (100%)
 rename gso/{ => utils}/types/site_name.py (100%)
 rename gso/{ => utils}/types/snmp.py (100%)
 rename gso/{ => utils}/types/tt_number.py (100%)
 rename gso/{ => utils}/types/unique_field.py (100%)

diff --git a/gso/api/v1/network.py b/gso/api/v1/network.py
index 62983f77..e4a19de9 100644
--- a/gso/api/v1/network.py
+++ b/gso/api/v1/network.py
@@ -13,9 +13,9 @@ from starlette import status
 from gso.products.product_blocks.iptrunk import IptrunkType
 from gso.products.product_blocks.router import RouterRole
 from gso.services.subscriptions import get_active_iptrunk_subscriptions
-from gso.types.coordinates import LatitudeCoordinate, LongitudeCoordinate
-from gso.types.interfaces import PhysicalPortCapacity
 from gso.utils.shared_enums import Vendor
+from gso.utils.types.coordinates import LatitudeCoordinate, LongitudeCoordinate
+from gso.utils.types.interfaces import PhysicalPortCapacity
 
 router = APIRouter(prefix="/networks", tags=["Network"], dependencies=[Depends(authorize)])
 
diff --git a/gso/cli/imports.py b/gso/cli/imports.py
index e7179465..33a4636a 100644
--- a/gso/cli/imports.py
+++ b/gso/cli/imports.py
@@ -31,9 +31,10 @@ from gso.services.subscriptions import (
     get_active_subscriptions_by_field_and_value,
     get_subscriptions,
 )
-from gso.types.base_site import BaseSiteValidatorModel
-from gso.types.interfaces import LAGMember, LAGMemberList, PhysicalPortCapacity
-from gso.utils.shared_enums import IPv4AddressType, IPv6AddressType, PortNumber, Vendor
+from gso.utils.shared_enums import Vendor
+from gso.utils.types.base_site import BaseSiteValidatorModel
+from gso.utils.types.interfaces import LAGMember, LAGMemberList, PhysicalPortCapacity
+from gso.utils.types.ip_address import IPv4AddressType, IPv6AddressType, PortNumber
 
 app: typer.Typer = typer.Typer()
 
diff --git a/gso/products/product_blocks/iptrunk.py b/gso/products/product_blocks/iptrunk.py
index 1ff4fe46..ad83609d 100644
--- a/gso/products/product_blocks/iptrunk.py
+++ b/gso/products/product_blocks/iptrunk.py
@@ -15,7 +15,7 @@ from gso.products.product_blocks.router import (
     RouterBlockInactive,
     RouterBlockProvisioning,
 )
-from gso.types.interfaces import LAGMemberList, PhysicalPortCapacity
+from gso.utils.types.interfaces import LAGMemberList, PhysicalPortCapacity
 
 
 class IptrunkType(strEnum):
diff --git a/gso/products/product_blocks/lan_switch_interconnect.py b/gso/products/product_blocks/lan_switch_interconnect.py
index 544da1e7..e2626de5 100644
--- a/gso/products/product_blocks/lan_switch_interconnect.py
+++ b/gso/products/product_blocks/lan_switch_interconnect.py
@@ -5,7 +5,7 @@ from orchestrator.types import SubscriptionLifecycle, strEnum
 
 from gso.products.product_blocks.router import RouterBlock, RouterBlockInactive, RouterBlockProvisioning
 from gso.products.product_blocks.switch import SwitchBlock, SwitchBlockInactive, SwitchBlockProvisioning
-from gso.types.interfaces import LAGMemberList
+from gso.utils.types.interfaces import LAGMemberList
 
 
 class LanSwitchInterconnectAddressSpace(strEnum):
diff --git a/gso/products/product_blocks/office_router.py b/gso/products/product_blocks/office_router.py
index 65eab025..bff50dd3 100644
--- a/gso/products/product_blocks/office_router.py
+++ b/gso/products/product_blocks/office_router.py
@@ -8,7 +8,8 @@ from gso.products.product_blocks.site import (
     SiteBlockInactive,
     SiteBlockProvisioning,
 )
-from gso.utils.shared_enums import IPv4AddressType, IPv6AddressType, PortNumber, Vendor
+from gso.utils.shared_enums import Vendor
+from gso.utils.types.ip_address import IPv4AddressType, IPv6AddressType, PortNumber
 
 
 class OfficeRouterBlockInactive(
diff --git a/gso/products/product_blocks/router.py b/gso/products/product_blocks/router.py
index 17deeccb..6d7dabf9 100644
--- a/gso/products/product_blocks/router.py
+++ b/gso/products/product_blocks/router.py
@@ -8,7 +8,8 @@ from gso.products.product_blocks.site import (
     SiteBlockInactive,
     SiteBlockProvisioning,
 )
-from gso.utils.shared_enums import IPv4AddressType, IPv6AddressType, PortNumber, Vendor
+from gso.utils.shared_enums import Vendor
+from gso.utils.types.ip_address import IPv4AddressType, IPv6AddressType, PortNumber
 
 
 class RouterRole(strEnum):
diff --git a/gso/products/product_blocks/site.py b/gso/products/product_blocks/site.py
index 436288c5..eec86847 100644
--- a/gso/products/product_blocks/site.py
+++ b/gso/products/product_blocks/site.py
@@ -3,9 +3,9 @@
 from orchestrator.domain.base import ProductBlockModel
 from orchestrator.types import SubscriptionLifecycle, strEnum
 
-from gso.types.coordinates import LatitudeCoordinate, LongitudeCoordinate
-from gso.types.ip_address import IPAddress
-from gso.types.site_name import SiteName
+from gso.utils.types.coordinates import LatitudeCoordinate, LongitudeCoordinate
+from gso.utils.types.ip_address import IPAddress
+from gso.utils.types.site_name import SiteName
 
 
 class SiteTier(strEnum):
diff --git a/gso/products/product_blocks/super_pop_switch.py b/gso/products/product_blocks/super_pop_switch.py
index 3335b28c..872f37b5 100644
--- a/gso/products/product_blocks/super_pop_switch.py
+++ b/gso/products/product_blocks/super_pop_switch.py
@@ -8,7 +8,8 @@ from gso.products.product_blocks.site import (
     SiteBlockInactive,
     SiteBlockProvisioning,
 )
-from gso.utils.shared_enums import IPv4AddressType, PortNumber, Vendor
+from gso.utils.shared_enums import Vendor
+from gso.utils.types.ip_address import IPv4AddressType, PortNumber
 
 
 class SuperPopSwitchBlockInactive(
diff --git a/gso/products/product_blocks/switch.py b/gso/products/product_blocks/switch.py
index f0aa0414..bdf2b465 100644
--- a/gso/products/product_blocks/switch.py
+++ b/gso/products/product_blocks/switch.py
@@ -9,7 +9,8 @@ from gso.products.product_blocks.site import (
     SiteBlockInactive,
     SiteBlockProvisioning,
 )
-from gso.utils.shared_enums import PortNumber, Vendor
+from gso.utils.shared_enums import Vendor
+from gso.utils.types.ip_address import PortNumber
 
 
 class SwitchModel(strEnum):
diff --git a/gso/services/infoblox.py b/gso/services/infoblox.py
index 22e56ab5..8e06be86 100644
--- a/gso/services/infoblox.py
+++ b/gso/services/infoblox.py
@@ -10,7 +10,7 @@ from infoblox_client.exceptions import (
 )
 
 from gso.settings import IPAMParams, load_oss_params
-from gso.utils.shared_enums import IPv4AddressType, IPv6AddressType
+from gso.utils.types.ip_address import IPv4AddressType, IPv6AddressType
 
 logger = getLogger(__name__)
 NULL_MAC = "00:00:00:00:00:00"
diff --git a/gso/services/librenms_client.py b/gso/services/librenms_client.py
index 4d8e4b19..ae3fcac6 100644
--- a/gso/services/librenms_client.py
+++ b/gso/services/librenms_client.py
@@ -10,7 +10,7 @@ from requests import HTTPError, Response
 from requests.adapters import HTTPAdapter
 
 from gso.settings import load_oss_params
-from gso.types.snmp import SNMPVersion
+from gso.utils.types.snmp import SNMPVersion
 
 logger = logging.getLogger(__name__)
 
diff --git a/gso/settings.py b/gso/settings.py
index d2a845f3..f7d40de7 100644
--- a/gso/settings.py
+++ b/gso/settings.py
@@ -16,7 +16,7 @@ from pydantic_forms.types import UUIDstr, strEnum
 from pydantic_settings import BaseSettings
 from typing_extensions import Doc
 
-from gso.utils.shared_enums import PortNumber
+from gso.utils.types.ip_address import PortNumber
 
 logger = logging.getLogger(__name__)
 
diff --git a/gso/types/ip_address.py b/gso/types/ip_address.py
deleted file mode 100644
index 2a71b64e..00000000
--- a/gso/types/ip_address.py
+++ /dev/null
@@ -1,20 +0,0 @@
-"""IP addresses."""
-
-import ipaddress
-from typing import Annotated
-
-from pydantic import AfterValidator
-
-
-def validate_ipv4_or_ipv6(value: str) -> str:
-    """Validate that a value is a valid IPv4 or IPv6 address."""
-    try:
-        ipaddress.ip_address(value)
-    except ValueError as e:
-        msg = "Enter a valid IPv4 or IPv6 address."
-        raise ValueError(msg) from e
-    else:
-        return value
-
-
-IPAddress = Annotated[str, AfterValidator(validate_ipv4_or_ipv6)]
diff --git a/gso/utils/helpers.py b/gso/utils/helpers.py
index f1063cec..4a78b989 100644
--- a/gso/utils/helpers.py
+++ b/gso/utils/helpers.py
@@ -11,8 +11,9 @@ from gso.products.product_blocks.router import RouterRole
 from gso.products.product_types.router import Router
 from gso.services import subscriptions
 from gso.services.netbox_client import NetboxClient
-from gso.types.interfaces import PhysicalPortCapacity
-from gso.utils.shared_enums import IPv4AddressType, Vendor
+from gso.utils.shared_enums import Vendor
+from gso.utils.types.interfaces import PhysicalPortCapacity
+from gso.utils.types.ip_address import IPv4AddressType
 
 if TYPE_CHECKING:
     from gso.products.product_blocks.iptrunk import IptrunkInterfaceBlock
diff --git a/gso/utils/shared_enums.py b/gso/utils/shared_enums.py
index 94538f78..929e5b0b 100644
--- a/gso/utils/shared_enums.py
+++ b/gso/utils/shared_enums.py
@@ -1,16 +1,6 @@
 """Shared choices for the different models."""
 
-import ipaddress
-from typing import Annotated, Any
-
-from pydantic import Field, PlainSerializer
 from pydantic_forms.types import strEnum
-from typing_extensions import Doc
-
-
-def convert_to_str(value: Any) -> str:
-    """Convert the value to a string."""
-    return str(value)
 
 
 class Vendor(strEnum):
@@ -20,24 +10,6 @@ class Vendor(strEnum):
     NOKIA = "nokia"
 
 
-PortNumber = Annotated[
-    int,
-    Field(
-        gt=0,
-        le=49151,
-    ),
-    Doc(
-        "Constrained integer for valid port numbers. The range from 49152 to 65535 is marked as ephemeral, "
-        "and can therefore not be selected for permanent allocation."
-    ),
-]
-
-
-IPv4AddressType = Annotated[ipaddress.IPv4Address, PlainSerializer(convert_to_str, return_type=str, when_used="always")]
-
-IPv6AddressType = Annotated[ipaddress.IPv6Address, PlainSerializer(convert_to_str, return_type=str, when_used="always")]
-
-
 class ConnectionStrategy(strEnum):
     """An enumerator for the connection Strategies."""
 
diff --git a/gso/types/__init__.py b/gso/utils/types/__init__.py
similarity index 100%
rename from gso/types/__init__.py
rename to gso/utils/types/__init__.py
diff --git a/gso/types/base_site.py b/gso/utils/types/base_site.py
similarity index 69%
rename from gso/types/base_site.py
rename to gso/utils/types/base_site.py
index 3184e174..c5af009a 100644
--- a/gso/types/base_site.py
+++ b/gso/utils/types/base_site.py
@@ -3,11 +3,11 @@
 from pydantic import BaseModel
 
 from gso.products.product_blocks.site import SiteTier
-from gso.types.coordinates import LatitudeCoordinate, LongitudeCoordinate
-from gso.types.country_code import CountryCode
-from gso.types.ip_address import IPAddress
-from gso.types.site_name import SiteName
-from gso.types.unique_field import UniqueField
+from gso.utils.types.coordinates import LatitudeCoordinate, LongitudeCoordinate
+from gso.utils.types.country_code import CountryCode
+from gso.utils.types.ip_address import IPAddress
+from gso.utils.types.site_name import SiteName
+from gso.utils.types.unique_field import UniqueField
 
 
 class BaseSiteValidatorModel(BaseModel):
diff --git a/gso/types/coordinates.py b/gso/utils/types/coordinates.py
similarity index 100%
rename from gso/types/coordinates.py
rename to gso/utils/types/coordinates.py
diff --git a/gso/types/country_code.py b/gso/utils/types/country_code.py
similarity index 100%
rename from gso/types/country_code.py
rename to gso/utils/types/country_code.py
diff --git a/gso/types/interfaces.py b/gso/utils/types/interfaces.py
similarity index 100%
rename from gso/types/interfaces.py
rename to gso/utils/types/interfaces.py
diff --git a/gso/utils/types/ip_address.py b/gso/utils/types/ip_address.py
new file mode 100644
index 00000000..94cb8bea
--- /dev/null
+++ b/gso/utils/types/ip_address.py
@@ -0,0 +1,38 @@
+"""IP addresses."""
+
+import ipaddress
+from typing import Annotated, Any
+
+from pydantic import AfterValidator, Field, PlainSerializer
+from typing_extensions import Doc
+
+
+def validate_ipv4_or_ipv6(value: str) -> str:
+    """Validate that a value is a valid IPv4 or IPv6 address."""
+    try:
+        ipaddress.ip_address(value)
+    except ValueError as e:
+        msg = "Enter a valid IPv4 or IPv6 address."
+        raise ValueError(msg) from e
+    else:
+        return value
+
+
+def _str(value: Any) -> str:
+    return str(value)
+
+
+IPv4AddressType = Annotated[ipaddress.IPv4Address, PlainSerializer(_str, return_type=str, when_used="always")]
+IPv6AddressType = Annotated[ipaddress.IPv6Address, PlainSerializer(_str, return_type=str, when_used="always")]
+IPAddress = Annotated[str, AfterValidator(validate_ipv4_or_ipv6)]
+PortNumber = Annotated[
+    int,
+    Field(
+        gt=0,
+        le=49151,
+    ),
+    Doc(
+        "Constrained integer for valid port numbers. The range from 49152 to 65535 is marked as ephemeral, "
+        "and can therefore not be selected for permanent allocation."
+    ),
+]
diff --git a/gso/types/netbox_router.py b/gso/utils/types/netbox_router.py
similarity index 100%
rename from gso/types/netbox_router.py
rename to gso/utils/types/netbox_router.py
diff --git a/gso/types/site_name.py b/gso/utils/types/site_name.py
similarity index 100%
rename from gso/types/site_name.py
rename to gso/utils/types/site_name.py
diff --git a/gso/types/snmp.py b/gso/utils/types/snmp.py
similarity index 100%
rename from gso/types/snmp.py
rename to gso/utils/types/snmp.py
diff --git a/gso/types/tt_number.py b/gso/utils/types/tt_number.py
similarity index 100%
rename from gso/types/tt_number.py
rename to gso/utils/types/tt_number.py
diff --git a/gso/types/unique_field.py b/gso/utils/types/unique_field.py
similarity index 100%
rename from gso/types/unique_field.py
rename to gso/utils/types/unique_field.py
diff --git a/gso/workflows/iptrunk/create_imported_iptrunk.py b/gso/workflows/iptrunk/create_imported_iptrunk.py
index 18f76a7f..4d754375 100644
--- a/gso/workflows/iptrunk/create_imported_iptrunk.py
+++ b/gso/workflows/iptrunk/create_imported_iptrunk.py
@@ -19,8 +19,8 @@ from gso.products.product_types.iptrunk import ImportedIptrunkInactive
 from gso.products.product_types.router import Router
 from gso.services import subscriptions
 from gso.services.partners import get_partner_by_name
-from gso.types.interfaces import LAGMember, LAGMemberList, PhysicalPortCapacity
 from gso.utils.helpers import active_router_selector
+from gso.utils.types.interfaces import LAGMember, LAGMemberList, PhysicalPortCapacity
 
 
 def initial_input_form_generator() -> FormGenerator:
diff --git a/gso/workflows/iptrunk/create_iptrunk.py b/gso/workflows/iptrunk/create_iptrunk.py
index c62ca920..9cab8df3 100644
--- a/gso/workflows/iptrunk/create_iptrunk.py
+++ b/gso/workflows/iptrunk/create_iptrunk.py
@@ -34,9 +34,6 @@ from gso.services.partners import get_partner_by_name
 from gso.services.sharepoint import SharePointClient
 from gso.services.subscriptions import get_non_terminated_iptrunk_subscriptions
 from gso.settings import load_oss_params
-from gso.types.interfaces import JuniperLAGMember, LAGMember, LAGMemberList, PhysicalPortCapacity
-from gso.types.netbox_router import NetboxEnabledRouter
-from gso.types.tt_number import TTNumber
 from gso.utils.helpers import (
     available_interfaces_choices,
     available_lags_choices,
@@ -44,6 +41,9 @@ from gso.utils.helpers import (
     get_router_vendor,
 )
 from gso.utils.shared_enums import Vendor
+from gso.utils.types.interfaces import JuniperLAGMember, LAGMember, LAGMemberList, PhysicalPortCapacity
+from gso.utils.types.netbox_router import NetboxEnabledRouter
+from gso.utils.types.tt_number import TTNumber
 from gso.utils.workflow_steps import prompt_sharepoint_checklist_url
 
 
diff --git a/gso/workflows/iptrunk/deploy_twamp.py b/gso/workflows/iptrunk/deploy_twamp.py
index feb7100a..11dce53b 100644
--- a/gso/workflows/iptrunk/deploy_twamp.py
+++ b/gso/workflows/iptrunk/deploy_twamp.py
@@ -13,7 +13,7 @@ from orchestrator.workflows.utils import wrap_modify_initial_input_form
 
 from gso.products.product_types.iptrunk import Iptrunk
 from gso.services.lso_client import execute_playbook, lso_interaction
-from gso.types.tt_number import TTNumber
+from gso.utils.types.tt_number import TTNumber
 
 
 def _initial_input_form_generator(subscription_id: UUIDstr) -> FormGenerator:
diff --git a/gso/workflows/iptrunk/migrate_iptrunk.py b/gso/workflows/iptrunk/migrate_iptrunk.py
index 0ed107a6..c7021875 100644
--- a/gso/workflows/iptrunk/migrate_iptrunk.py
+++ b/gso/workflows/iptrunk/migrate_iptrunk.py
@@ -33,14 +33,14 @@ from gso.services.netbox_client import NetboxClient
 from gso.services.sharepoint import SharePointClient
 from gso.services.subscriptions import get_active_router_subscriptions
 from gso.settings import load_oss_params
-from gso.types.interfaces import JuniperAEInterface, JuniperLAGMember, LAGMember, LAGMemberList
-from gso.types.tt_number import TTNumber
 from gso.utils.helpers import (
     available_interfaces_choices,
     available_lags_choices,
     get_router_vendor,
 )
 from gso.utils.shared_enums import Vendor
+from gso.utils.types.interfaces import JuniperAEInterface, JuniperLAGMember, LAGMember, LAGMemberList
+from gso.utils.types.tt_number import TTNumber
 from gso.utils.workflow_steps import prompt_sharepoint_checklist_url, set_isis_to_max
 
 
diff --git a/gso/workflows/iptrunk/modify_isis_metric.py b/gso/workflows/iptrunk/modify_isis_metric.py
index 493f0eb9..da14d078 100644
--- a/gso/workflows/iptrunk/modify_isis_metric.py
+++ b/gso/workflows/iptrunk/modify_isis_metric.py
@@ -12,7 +12,7 @@ from orchestrator.workflows.utils import wrap_modify_initial_input_form
 
 from gso.products.product_types.iptrunk import Iptrunk
 from gso.services.lso_client import execute_playbook, lso_interaction
-from gso.types.tt_number import TTNumber
+from gso.utils.types.tt_number import TTNumber
 
 
 def initial_input_form_generator(subscription_id: UUIDstr) -> FormGenerator:
diff --git a/gso/workflows/iptrunk/modify_trunk_interface.py b/gso/workflows/iptrunk/modify_trunk_interface.py
index 6ec7d59a..30076382 100644
--- a/gso/workflows/iptrunk/modify_trunk_interface.py
+++ b/gso/workflows/iptrunk/modify_trunk_interface.py
@@ -23,15 +23,16 @@ from gso.products.product_blocks.iptrunk import (
 from gso.products.product_types.iptrunk import Iptrunk
 from gso.services.lso_client import execute_playbook, lso_interaction
 from gso.services.netbox_client import NetboxClient
-from gso.types.interfaces import JuniperLAGMember, LAGMember, LAGMemberList, PhysicalPortCapacity
-from gso.types.tt_number import TTNumber
 from gso.utils.helpers import (
     available_interfaces_choices,
     available_interfaces_choices_including_current_members,
     calculate_recommended_minimum_links,
     get_router_vendor,
 )
-from gso.utils.shared_enums import IPv4AddressType, IPv6AddressType, Vendor
+from gso.utils.shared_enums import Vendor
+from gso.utils.types.interfaces import JuniperLAGMember, LAGMember, LAGMemberList, PhysicalPortCapacity
+from gso.utils.types.ip_address import IPv4AddressType, IPv6AddressType
+from gso.utils.types.tt_number import TTNumber
 from gso.workflows.iptrunk.migrate_iptrunk import check_ip_trunk_optical_levels_pre
 from gso.workflows.iptrunk.validate_iptrunk import check_ip_trunk_isis
 
diff --git a/gso/workflows/iptrunk/terminate_iptrunk.py b/gso/workflows/iptrunk/terminate_iptrunk.py
index fec1c48b..ac628d39 100644
--- a/gso/workflows/iptrunk/terminate_iptrunk.py
+++ b/gso/workflows/iptrunk/terminate_iptrunk.py
@@ -22,9 +22,9 @@ from gso.products.product_types.iptrunk import Iptrunk
 from gso.services import infoblox
 from gso.services.lso_client import execute_playbook, lso_interaction
 from gso.services.netbox_client import NetboxClient
-from gso.types.tt_number import TTNumber
 from gso.utils.helpers import get_router_vendor
 from gso.utils.shared_enums import Vendor
+from gso.utils.types.tt_number import TTNumber
 from gso.utils.workflow_steps import set_isis_to_max
 
 
diff --git a/gso/workflows/lan_switch_interconnect/create_lan_switch_interconnect.py b/gso/workflows/lan_switch_interconnect/create_lan_switch_interconnect.py
index 29dd38e4..973cf1d8 100644
--- a/gso/workflows/lan_switch_interconnect/create_lan_switch_interconnect.py
+++ b/gso/workflows/lan_switch_interconnect/create_lan_switch_interconnect.py
@@ -21,15 +21,6 @@ from gso.products.product_types.lan_switch_interconnect import LanSwitchIntercon
 from gso.products.product_types.router import Router
 from gso.products.product_types.switch import Switch
 from gso.services.partners import get_partner_by_name
-from gso.types.interfaces import (
-    JuniperAEInterface,
-    JuniperLAGMember,
-    JuniperPhyInterface,
-    LAGMember,
-    PhysicalPortCapacity,
-    validate_interface_names_are_unique,
-)
-from gso.types.tt_number import TTNumber
 from gso.utils.helpers import (
     active_router_selector,
     active_switch_selector,
@@ -37,6 +28,15 @@ from gso.utils.helpers import (
     available_lags_choices,
 )
 from gso.utils.shared_enums import Vendor
+from gso.utils.types.interfaces import (
+    JuniperAEInterface,
+    JuniperLAGMember,
+    JuniperPhyInterface,
+    LAGMember,
+    PhysicalPortCapacity,
+    validate_interface_names_are_unique,
+)
+from gso.utils.types.tt_number import TTNumber
 
 
 def _initial_input_form(product_name: str) -> FormGenerator:
diff --git a/gso/workflows/office_router/create_imported_office_router.py b/gso/workflows/office_router/create_imported_office_router.py
index e82f69cb..8b830634 100644
--- a/gso/workflows/office_router/create_imported_office_router.py
+++ b/gso/workflows/office_router/create_imported_office_router.py
@@ -13,7 +13,8 @@ from gso.products.product_types.office_router import ImportedOfficeRouterInactiv
 from gso.services import subscriptions
 from gso.services.partners import get_partner_by_name
 from gso.services.subscriptions import get_site_by_name
-from gso.utils.shared_enums import IPv4AddressType, IPv6AddressType, PortNumber, Vendor
+from gso.utils.shared_enums import Vendor
+from gso.utils.types.ip_address import IPv4AddressType, IPv6AddressType, PortNumber
 
 
 @step("Create subscription")
diff --git a/gso/workflows/opengear/create_imported_opengear.py b/gso/workflows/opengear/create_imported_opengear.py
index e7699986..ce4bd3cf 100644
--- a/gso/workflows/opengear/create_imported_opengear.py
+++ b/gso/workflows/opengear/create_imported_opengear.py
@@ -12,7 +12,7 @@ from gso.products import ProductName
 from gso.products.product_types.opengear import ImportedOpengearInactive
 from gso.services.partners import get_partner_by_name
 from gso.services.subscriptions import get_product_id_by_name, get_site_by_name
-from gso.utils.shared_enums import IPv4AddressType
+from gso.utils.types.ip_address import IPv4AddressType
 
 
 @step("Create subscription")
diff --git a/gso/workflows/router/create_imported_router.py b/gso/workflows/router/create_imported_router.py
index c8ba442b..12a71c79 100644
--- a/gso/workflows/router/create_imported_router.py
+++ b/gso/workflows/router/create_imported_router.py
@@ -14,7 +14,8 @@ from gso.products.product_types.router import ImportedRouterInactive
 from gso.services.partners import get_partner_by_name
 from gso.services.subscriptions import get_product_id_by_name, get_site_by_name
 from gso.utils.helpers import generate_fqdn
-from gso.utils.shared_enums import IPv4AddressType, IPv6AddressType, PortNumber, Vendor
+from gso.utils.shared_enums import Vendor
+from gso.utils.types.ip_address import IPv4AddressType, IPv6AddressType, PortNumber
 
 
 @step("Create subscription")
diff --git a/gso/workflows/router/create_router.py b/gso/workflows/router/create_router.py
index 68c55cf0..04d38b75 100644
--- a/gso/workflows/router/create_router.py
+++ b/gso/workflows/router/create_router.py
@@ -23,9 +23,10 @@ from gso.services.netbox_client import NetboxClient
 from gso.services.partners import get_partner_by_name
 from gso.services.sharepoint import SharePointClient
 from gso.settings import load_oss_params
-from gso.types.tt_number import TTNumber
 from gso.utils.helpers import generate_fqdn, iso_from_ipv4
-from gso.utils.shared_enums import PortNumber, Vendor
+from gso.utils.shared_enums import Vendor
+from gso.utils.types.ip_address import PortNumber
+from gso.utils.types.tt_number import TTNumber
 from gso.utils.workflow_steps import (
     deploy_base_config_dry,
     deploy_base_config_real,
diff --git a/gso/workflows/router/promote_p_to_pe.py b/gso/workflows/router/promote_p_to_pe.py
index f294bd99..0f0b31da 100644
--- a/gso/workflows/router/promote_p_to_pe.py
+++ b/gso/workflows/router/promote_p_to_pe.py
@@ -21,9 +21,9 @@ from gso.services import lso_client
 from gso.services.kentik_client import KentikClient, NewKentikDevice
 from gso.services.lso_client import lso_interaction
 from gso.services.subscriptions import get_all_active_sites
-from gso.types.tt_number import TTNumber
 from gso.utils.helpers import generate_inventory_for_active_routers
 from gso.utils.shared_enums import Vendor
+from gso.utils.types.tt_number import TTNumber
 
 
 def initial_input_form_generator(subscription_id: UUIDstr) -> FormGenerator:
diff --git a/gso/workflows/router/redeploy_base_config.py b/gso/workflows/router/redeploy_base_config.py
index eef8b6e7..48348abb 100644
--- a/gso/workflows/router/redeploy_base_config.py
+++ b/gso/workflows/router/redeploy_base_config.py
@@ -10,7 +10,7 @@ from orchestrator.workflows.utils import wrap_modify_initial_input_form
 
 from gso.products.product_types.router import Router
 from gso.services.lso_client import lso_interaction
-from gso.types.tt_number import TTNumber
+from gso.utils.types.tt_number import TTNumber
 from gso.utils.workflow_steps import deploy_base_config_dry, deploy_base_config_real
 
 
diff --git a/gso/workflows/router/terminate_router.py b/gso/workflows/router/terminate_router.py
index 60895ab3..f7caa6c9 100644
--- a/gso/workflows/router/terminate_router.py
+++ b/gso/workflows/router/terminate_router.py
@@ -28,9 +28,9 @@ from gso.services.librenms_client import LibreNMSClient
 from gso.services.lso_client import execute_playbook, lso_interaction
 from gso.services.netbox_client import NetboxClient
 from gso.settings import load_oss_params
-from gso.types.tt_number import TTNumber
 from gso.utils.helpers import generate_inventory_for_active_routers
 from gso.utils.shared_enums import Vendor
+from gso.utils.types.tt_number import TTNumber
 
 logger = logging.getLogger(__name__)
 
diff --git a/gso/workflows/router/update_ibgp_mesh.py b/gso/workflows/router/update_ibgp_mesh.py
index f8f17a48..a506e625 100644
--- a/gso/workflows/router/update_ibgp_mesh.py
+++ b/gso/workflows/router/update_ibgp_mesh.py
@@ -17,9 +17,9 @@ from gso.products.product_types.router import Router
 from gso.services import librenms_client, lso_client
 from gso.services.lso_client import lso_interaction
 from gso.services.subscriptions import get_trunks_that_terminate_on_router
-from gso.types.snmp import SNMPVersion
-from gso.types.tt_number import TTNumber
 from gso.utils.helpers import generate_inventory_for_active_routers
+from gso.utils.types.snmp import SNMPVersion
+from gso.utils.types.tt_number import TTNumber
 
 
 def initial_input_form_generator(subscription_id: UUIDstr) -> FormGenerator:
diff --git a/gso/workflows/site/create_imported_site.py b/gso/workflows/site/create_imported_site.py
index 297761db..8a9b3d9e 100644
--- a/gso/workflows/site/create_imported_site.py
+++ b/gso/workflows/site/create_imported_site.py
@@ -14,9 +14,9 @@ from gso.products.product_blocks.site import SiteTier
 from gso.products.product_types.site import ImportedSiteInactive
 from gso.services import subscriptions
 from gso.services.partners import get_partner_by_name
-from gso.types.base_site import BaseSiteValidatorModel
-from gso.types.coordinates import LatitudeCoordinate, LongitudeCoordinate
-from gso.types.ip_address import IPAddress
+from gso.utils.types.base_site import BaseSiteValidatorModel
+from gso.utils.types.coordinates import LatitudeCoordinate, LongitudeCoordinate
+from gso.utils.types.ip_address import IPAddress
 
 
 @step("Create subscription")
diff --git a/gso/workflows/site/create_site.py b/gso/workflows/site/create_site.py
index ec80732c..eb5409d7 100644
--- a/gso/workflows/site/create_site.py
+++ b/gso/workflows/site/create_site.py
@@ -12,9 +12,9 @@ from pydantic_forms.validators import ReadOnlyField
 from gso.products.product_blocks import site as site_pb
 from gso.products.product_types import site
 from gso.services.partners import get_partner_by_name
-from gso.types.base_site import BaseSiteValidatorModel
-from gso.types.coordinates import LatitudeCoordinate, LongitudeCoordinate
-from gso.types.ip_address import IPAddress
+from gso.utils.types.base_site import BaseSiteValidatorModel
+from gso.utils.types.coordinates import LatitudeCoordinate, LongitudeCoordinate
+from gso.utils.types.ip_address import IPAddress
 
 
 def initial_input_form_generator(product_name: str) -> FormGenerator:
diff --git a/gso/workflows/site/modify_site.py b/gso/workflows/site/modify_site.py
index b68626b1..9c94e550 100644
--- a/gso/workflows/site/modify_site.py
+++ b/gso/workflows/site/modify_site.py
@@ -18,9 +18,9 @@ from pydantic_forms.validators import ReadOnlyField
 
 from gso.products.product_blocks.site import SiteTier
 from gso.products.product_types.site import Site
-from gso.types.coordinates import LatitudeCoordinate, LongitudeCoordinate
-from gso.types.ip_address import IPAddress
-from gso.types.unique_field import UniqueField
+from gso.utils.types.coordinates import LatitudeCoordinate, LongitudeCoordinate
+from gso.utils.types.ip_address import IPAddress
+from gso.utils.types.unique_field import UniqueField
 
 
 def initial_input_form_generator(subscription_id: UUIDstr) -> FormGenerator:
diff --git a/gso/workflows/super_pop_switch/create_imported_super_pop_switch.py b/gso/workflows/super_pop_switch/create_imported_super_pop_switch.py
index 1cdb7d09..da99dd68 100644
--- a/gso/workflows/super_pop_switch/create_imported_super_pop_switch.py
+++ b/gso/workflows/super_pop_switch/create_imported_super_pop_switch.py
@@ -14,7 +14,8 @@ from gso.services import subscriptions
 from gso.services.partners import get_partner_by_name
 from gso.services.subscriptions import get_site_by_name
 from gso.utils.helpers import generate_fqdn
-from gso.utils.shared_enums import IPv4AddressType, PortNumber, Vendor
+from gso.utils.shared_enums import Vendor
+from gso.utils.types.ip_address import IPv4AddressType, PortNumber
 
 
 @step("Create subscription")
diff --git a/test/cli/test_imports.py b/test/cli/test_imports.py
index 89933fc8..d794d0f0 100644
--- a/test/cli/test_imports.py
+++ b/test/cli/test_imports.py
@@ -16,9 +16,9 @@ from gso.products import Router, Site
 from gso.products.product_blocks.iptrunk import IptrunkType
 from gso.products.product_blocks.router import RouterRole
 from gso.products.product_blocks.site import SiteTier
-from gso.types.interfaces import PhysicalPortCapacity
 from gso.utils.helpers import iso_from_ipv4
 from gso.utils.shared_enums import Vendor
+from gso.utils.types.interfaces import PhysicalPortCapacity
 
 
 ##############
diff --git a/test/conftest.py b/test/conftest.py
index 8cfea9d2..2eb7e6a2 100644
--- a/test/conftest.py
+++ b/test/conftest.py
@@ -34,7 +34,7 @@ from urllib3_mock import Responses
 
 from gso.main import init_gso_app
 from gso.services.partners import PartnerSchema, create_partner
-from gso.types.interfaces import LAGMember, LAGMemberList
+from gso.utils.types.interfaces import LAGMember, LAGMemberList
 from test.fixtures import (  # noqa: F401
     iptrunk_side_subscription_factory,
     iptrunk_subscription_factory,
diff --git a/test/fixtures.py b/test/fixtures.py
index 4fa5a2a0..0bb920c0 100644
--- a/test/fixtures.py
+++ b/test/fixtures.py
@@ -36,8 +36,8 @@ from gso.products.product_types.router import ImportedRouterInactive, Router, Ro
 from gso.products.product_types.site import ImportedSiteInactive, Site, SiteInactive
 from gso.products.product_types.super_pop_switch import ImportedSuperPopSwitchInactive, SuperPopSwitchInactive
 from gso.services import subscriptions
-from gso.types.interfaces import PhysicalPortCapacity
 from gso.utils.shared_enums import Vendor
+from gso.utils.types.interfaces import PhysicalPortCapacity
 from test.workflows import WorkflowInstanceForTests
 
 
diff --git a/test/schemas/test_types.py b/test/schemas/test_types.py
index 33c3f209..d34f35d7 100644
--- a/test/schemas/test_types.py
+++ b/test/schemas/test_types.py
@@ -1,7 +1,7 @@
 import pytest
 from pydantic import BaseModel, ValidationError
 
-from gso.types.coordinates import LatitudeCoordinate, LongitudeCoordinate
+from gso.utils.types.coordinates import LatitudeCoordinate, LongitudeCoordinate
 
 
 class LatitudeModel(BaseModel):
diff --git a/test/services/test_librenms_client.py b/test/services/test_librenms_client.py
index 1bd14b9b..c64b5933 100644
--- a/test/services/test_librenms_client.py
+++ b/test/services/test_librenms_client.py
@@ -5,7 +5,7 @@ import pytest
 from requests import HTTPError
 
 from gso.services.librenms_client import LibreNMSClient
-from gso.types.snmp import SNMPVersion
+from gso.utils.types.snmp import SNMPVersion
 
 
 @pytest.fixture()
diff --git a/test/utils/test_helpers.py b/test/utils/test_helpers.py
index 5f947609..28779cd7 100644
--- a/test/utils/test_helpers.py
+++ b/test/utils/test_helpers.py
@@ -6,12 +6,12 @@ from orchestrator.types import SubscriptionLifecycle
 from gso.products import Router
 from gso.products.product_blocks.iptrunk import IptrunkInterfaceBlock
 from gso.products.product_blocks.router import RouterRole
-from gso.types.tt_number import validate_tt_number
 from gso.utils.helpers import (
     available_interfaces_choices_including_current_members,
     generate_inventory_for_active_routers,
 )
 from gso.utils.shared_enums import Vendor
+from gso.utils.types.tt_number import validate_tt_number
 
 
 @pytest.fixture()
diff --git a/test/workflows/iptrunk/test_create_imported_iptrunk.py b/test/workflows/iptrunk/test_create_imported_iptrunk.py
index 263c4f16..d172dc8d 100644
--- a/test/workflows/iptrunk/test_create_imported_iptrunk.py
+++ b/test/workflows/iptrunk/test_create_imported_iptrunk.py
@@ -4,7 +4,7 @@ from orchestrator.types import SubscriptionLifecycle
 from gso.products import ProductName
 from gso.products.product_blocks.iptrunk import IptrunkType
 from gso.products.product_types.iptrunk import ImportedIptrunk
-from gso.types.interfaces import PhysicalPortCapacity
+from gso.utils.types.interfaces import PhysicalPortCapacity
 from test.workflows import (
     assert_complete,
     extract_state,
diff --git a/test/workflows/iptrunk/test_create_iptrunk.py b/test/workflows/iptrunk/test_create_iptrunk.py
index cd33943c..0b7e00e6 100644
--- a/test/workflows/iptrunk/test_create_iptrunk.py
+++ b/test/workflows/iptrunk/test_create_iptrunk.py
@@ -7,8 +7,8 @@ from infoblox_client.objects import HostRecord
 from gso.products import Iptrunk, ProductName
 from gso.products.product_blocks.iptrunk import IptrunkType
 from gso.services.subscriptions import get_product_id_by_name
-from gso.types.interfaces import PhysicalPortCapacity
 from gso.utils.shared_enums import Vendor
+from gso.utils.types.interfaces import PhysicalPortCapacity
 from test import USER_CONFIRM_EMPTY_FORM
 from test.services.conftest import MockedNetboxClient, MockedSharePointClient
 from test.workflows import (
diff --git a/test/workflows/iptrunk/test_modify_trunk_interface.py b/test/workflows/iptrunk/test_modify_trunk_interface.py
index b784d262..85c395e8 100644
--- a/test/workflows/iptrunk/test_modify_trunk_interface.py
+++ b/test/workflows/iptrunk/test_modify_trunk_interface.py
@@ -4,8 +4,8 @@ import pytest
 
 from gso.products import Iptrunk
 from gso.products.product_blocks.iptrunk import IptrunkType
-from gso.types.interfaces import LAGMemberList, PhysicalPortCapacity
 from gso.utils.shared_enums import Vendor
+from gso.utils.types.interfaces import LAGMemberList, PhysicalPortCapacity
 from test.conftest import UseJuniperSide
 from test.workflows import (
     assert_complete,
-- 
GitLab