diff --git a/gso/services/ipam.py b/gso/services/ipam.py index 0a1b0655cff1d9a28b4ccb628f9fe19bde03fcf4..1b0a7415a00caeb823162412bc5ad7fc2df02816 100644 --- a/gso/services/ipam.py +++ b/gso/services/ipam.py @@ -4,6 +4,7 @@ from typing import Union from pydantic import BaseSettings from gso.services import _ipam +from gso.services._ipam import V4HostAddress, V6HostAddress class V4ServiceNetwork(BaseSettings): @@ -19,20 +20,14 @@ class ServiceNetworks(BaseSettings): v6: ipaddress.IPv6Network -class V4HostAddress(BaseSettings): - v4: ipaddress.IPv4Address - - -class V6HostAddress(BaseSettings): - v6: ipaddress.IPv6Address - - class HostAddresses(BaseSettings): v4: ipaddress.IPv4Address v6: ipaddress.IPv6Address -def new_service_networks(service_type="", comment="", extattrs={}) -> ServiceNetworks: +def new_service_networks(service_type="", comment="", extattrs=None) -> ServiceNetworks: + if extattrs is None: + extattrs = {} v4_service_network = _ipam.allocate_service_ipv4_network( service_type=service_type, comment=comment, extattrs=extattrs ) @@ -48,8 +43,10 @@ def new_service_host( service_networks: ServiceNetworks = None, host_addresses: HostAddresses = None, cname_aliases=None, - extattrs={}, + extattrs=None, ) -> HostAddresses: + if extattrs is None: + extattrs = {} return _ipam.allocate_service_host( hostname=hostname, service_type=service_type, @@ -67,8 +64,10 @@ def delete_service_network( def delete_service_host( - hostname="", host_addresses: HostAddresses = None, cname_aliases=[], service_type="" -) -> HostAddresses: + hostname="", host_addresses: HostAddresses = None, cname_aliases=None, service_type="" +) -> V4HostAddress | V6HostAddress: + if cname_aliases is None: + cname_aliases = [] return _ipam.delete_service_host( hostname=hostname, host_addresses=host_addresses, cname_aliases=cname_aliases, service_type=service_type ) diff --git a/gso/services/provisioning_proxy.py b/gso/services/provisioning_proxy.py index 05de47005502229647bfa48c635ecf8704b9392f..a3ffde6f40a20649bab14d4d089923f9bf83f010 100644 --- a/gso/services/provisioning_proxy.py +++ b/gso/services/provisioning_proxy.py @@ -1,4 +1,5 @@ """The Provisioning Proxy service, which interacts with LSO running externally. + LSO is responsible for executing Ansible playbooks, that deploy subscriptions. """ import json @@ -8,8 +9,6 @@ import requests from orchestrator import inputstep from orchestrator.config.assignee import Assignee from orchestrator.domain import SubscriptionModel - -# noinspection PyProtectedMember from orchestrator.forms import FormPage, ReadOnlyField from orchestrator.forms.validators import Accept, Label, LongText from orchestrator.types import State, UUIDstr, strEnum @@ -25,6 +24,7 @@ logger = logging.getLogger(__name__) class CUDOperation(strEnum): """Enum for different C(R)UD operations that the provisioning proxy supports. + Read is not applicable, hence these become CUD and not CRUD operations. """ @@ -37,8 +37,7 @@ class CUDOperation(strEnum): def _send_request(endpoint: str, parameters: dict, process_id: UUIDstr, operation: CUDOperation): - """Internal function for sending a request to LSO. The callback address is - derived using the process ID provided. + """Send a request to LSO. The callback address is derived using the process ID provided. :param str endpoint: The LSO-specific endpoint to call, depending on the type of service object that is acted upon. @@ -70,12 +69,12 @@ def _send_request(endpoint: str, parameters: dict, process_id: UUIDstr, operatio request = requests.delete(url, json=parameters, timeout=10000) if request.status_code != 200: - print(request.content) + logger.debug(request.content) raise AssertionError(request.content) def provision_device(subscription: DeviceProvisioning, process_id: UUIDstr, dry_run: bool = True): - """Function that provisions a new device using LSO. + """Provision a new device using LSO. :param :class:`DeviceProvisioning` subscription: The subscription object that is to be provisioned. @@ -91,7 +90,7 @@ def provision_device(subscription: DeviceProvisioning, process_id: UUIDstr, dry_ def provision_ip_trunk( subscription: IptrunkProvisioning, process_id: UUIDstr, config_object: str, dry_run: bool = True ): - """Function that provisions an IP trunk service using LSO. + """Provision an IP trunk service using LSO. :param :class:`IptrunkProvisioning` subscription: The subscription object that is to be provisioned. @@ -136,7 +135,7 @@ def provision_ip_trunk( def deprovision_ip_trunk(subscription: Iptrunk, process_id: UUIDstr, dry_run: bool = True): - """Function that provisions an IP trunk service using LSO. + """Deprovision an IP trunk service using LSO. :param :class:`IptrunkProvisioning` subscription: The subscription object that is to be provisioned. @@ -162,7 +161,7 @@ def await_pp_results(subscription: SubscriptionModel, label_text: str) -> State: @validator("pp_run_results", allow_reuse=True, pre=True, always=True) def run_results_must_be_given(cls, run_results): if run_results is None: - raise ValueError("Run results may not be empty. " "Wait for the provisioning proxy to finish.") + raise ValueError("Run results may not be empty. Wait for the provisioning proxy to finish.") return run_results result_page = yield ProvisioningResultPage diff --git a/gso/settings.py b/gso/settings.py index 93c855f19d1d5b8cd4076e61678635c6679f6afb..88f5dc924a4108e8dbd6aed6c49d2f5a78c64c2a 100644 --- a/gso/settings.py +++ b/gso/settings.py @@ -1,11 +1,13 @@ """GSO settings, ensuring that the required parameters are set correctly.""" import ipaddress import json +import logging import os -# from pydantic import BaseSettings, Field from pydantic import BaseSettings +logger = logging.getLogger(__name__) + class GeneralParams(BaseSettings): """General parameters for a GSO configuration file.""" @@ -42,8 +44,9 @@ class V6NetworkParams(BaseSettings): class ServiceNetworkParams(BaseSettings): - """Parameters for InfoBlox that describe IPv4 and v6 networks, and the - corresponding domain name that should be used as a suffix. + """Parameters for InfoBlox. + + The parameters describe IPv4 and v6 networks, and the corresponding domain name that should be used as a suffix. """ V4: V4NetworkParams @@ -82,12 +85,10 @@ class OSSParams(BaseSettings): def load_oss_params() -> OSSParams: - """Look for OSS_PARAMS_FILENAME in the environment and load the parameters - from that file. - """ + """Look for OSS_PARAMS_FILENAME in the environment and load the parameters from that file.""" with open(os.environ["OSS_PARAMS_FILENAME"], encoding="utf-8") as file: return OSSParams(**json.loads(file.read())) if __name__ == "__main__": - print(load_oss_params()) + logger.debug(load_oss_params()) diff --git a/gso/workflows/device/terminate_device.py b/gso/workflows/device/terminate_device.py index ed2e7bcde19095125391c09ee2c2c141b2d5271f..612080f201785c0591a1ffcd7c13523bad404f9c 100644 --- a/gso/workflows/device/terminate_device.py +++ b/gso/workflows/device/terminate_device.py @@ -1,18 +1,20 @@ import ipaddress +from typing import Type from orchestrator.forms import FormPage from orchestrator.forms.validators import Label from orchestrator.targets import Target -from orchestrator.types import InputForm, SubscriptionLifecycle, UUIDstr +from orchestrator.types import SubscriptionLifecycle, UUIDstr from orchestrator.workflow import done, init, step, workflow 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 BaseModel from gso.products.product_types.device import Device from gso.services import ipam -def initial_input_form_generator(subscription_id: UUIDstr) -> InputForm: +def initial_input_form_generator(subscription_id: UUIDstr) -> Type[BaseModel]: subscription = Device.from_subscription(subscription_id) class TerminateForm(FormPage): diff --git a/pyproject.toml b/pyproject.toml index d89d802ff78dd32f26ddc626dfa6bfdae4b5c4ec..58a0772194a473811220f1a86376d66c4390bab8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -17,6 +17,7 @@ exclude = ''' | \.tox | venv | gso/migrations + | gso/services/_ipam\.py )/ ) ''' @@ -51,7 +52,8 @@ exclude = [ "__pycache__", "htmlcov", "venv", - "gso/migrations" + "gso/migrations", + "_ipam.py" # TODO: remove ] ignore = [ "C417", @@ -72,7 +74,8 @@ ignore = [ "N803", "N801", "N815", - "N802" + "N802", + "S101" ] line-length = 120 select = [ @@ -94,7 +97,7 @@ target-version = "py310" ban-relative-imports = "all" [tool.ruff.per-file-ignores] -"test/*" = ["S101", "B033", "N816", "N802"] +"test/*" = ["B033", "N816", "N802"] [tool.ruff.isort] known-third-party = ["pydantic", "migrations"]