diff --git a/README.md b/README.md index cb0cac396dac06de905b67f05d408286af9365c1..b4563b2f937cd4cd5f7918a61fc3251c84aeb7be 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # GÉANT Service Orchestrator -The GÉANT interpretation of [`orchestrator-core`](https://github.com/workfloworchestrator/orchestrator-core). +The GÉANT interpretation of [``orchestrator-core``](https://github.com/workfloworchestrator/orchestrator-core). ## Documentation You can build the documentation locally using [build-docs.sh](build-docs.sh). diff --git a/build-docs.sh b/build-docs.sh index 016b34edae07b74c348218478f5a149c22a50765..34eadabbe43f22cac9e4abd40c3fadf1c3d872a3 100755 --- a/build-docs.sh +++ b/build-docs.sh @@ -1,4 +1,10 @@ +#!/bin/sh +set -o errexit +set -o nounset + +export OSS_PARAMS_FILENAME=../gso/oss-params-example.json + pip install sphinx_rtd_theme sphinxcontrib-jquery -cd docs || exit 1 +cd docs sphinx-build source build diff --git a/docs/source/glossary.rst b/docs/source/glossary.rst index b98edde4222ab7f001fba8b36dfcc750d1821a8e..69f1a655f906c8b1c89ac44bd67db2ec2c118be4 100644 --- a/docs/source/glossary.rst +++ b/docs/source/glossary.rst @@ -14,6 +14,9 @@ Glossary of terms Classless Inter-Domain Routing. A method for denoting IP ranges in the form of ``9.9.0.0/16`` or ``fe80:1234:abcd::/48``. + CLI + Command Line Interface. + CNAME A type of DNS record that is used as an alias from one hostname to another @@ -26,10 +29,13 @@ Glossary of terms GSO GÉANT Service Orchestrator + IAS + IAS + IPAM IP Address Management - IS-IS + ISIS Intermediate System to Intermediate System: a routing protocol described in `RFC 7142 <https://datatracker.ietf.org/doc/html/rfc7142>`_. @@ -43,7 +49,7 @@ Glossary of terms Lightweight Service Orchestrator NET - Network Entity Title: used for :term:`IS-IS` routing. + Network Entity Title: used for :term:`ISIS` routing. OSS Operational Support Systems diff --git a/docs/source/module/products/index.rst b/docs/source/module/products/index.rst index 415b1c48357cd59d9a59fbd372be22cf11ac7b2c..75e79f7971fdec9a4df0d62d395046e04f037a37 100644 --- a/docs/source/module/products/index.rst +++ b/docs/source/module/products/index.rst @@ -13,13 +13,3 @@ Subpackages product_blocks/index product_types/index - -Submodules ----------- - -``gso.products.shared`` module -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. automodule:: gso.products.shared - :members: - :show-inheritance: diff --git a/docs/source/module/workflows/iptrunk/index.rst b/docs/source/module/workflows/iptrunk/index.rst index 3bfaec18bfb011680bf0ef5b902b587aeb6b3e6c..089aa1249ae7597e14953f60da9120d38de4c3f8 100644 --- a/docs/source/module/workflows/iptrunk/index.rst +++ b/docs/source/module/workflows/iptrunk/index.rst @@ -17,4 +17,3 @@ Submodules modify_isis_metric modify_trunk_interface terminate_iptrunk - utils diff --git a/docs/vale/styles/Vocab/geant-jargon/accept.txt b/docs/vale/styles/Vocab/geant-jargon/accept.txt index 8de3c79dbe36016d729a9916d363ddf0a00be386..1d257c7ce79b1216f12842a1b7899a2986f9f817 100644 --- a/docs/vale/styles/Vocab/geant-jargon/accept.txt +++ b/docs/vale/styles/Vocab/geant-jargon/accept.txt @@ -1,7 +1,7 @@ GÉANT Automation Platform [GSO|gso] Vereniging -[[T|t]ERMINATE|terminate] +[[T|t]erminate|TERMINATE] WFO Ansible [Dd]eprovision @@ -12,3 +12,4 @@ Dark_fiber [I|i]ptrunk [A|a]llocate PHASE 1 +[Mm]odify diff --git a/gso/api/v1/imports.py b/gso/api/v1/imports.py index e87f4ad8ed30cef561ee943ff525c40006a07f52..12524e1e50c2656ddcb6e35dc03c05bdc356bcc5 100644 --- a/gso/api/v1/imports.py +++ b/gso/api/v1/imports.py @@ -71,8 +71,7 @@ class SiteImportModel(BaseModel): 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). + The site name must consist of three uppercase letters, optionally followed by a single digit. """ validate_site_fields_is_unique("site_name", site_name) validate_site_name(site_name) diff --git a/gso/products/product_blocks/iptrunk.py b/gso/products/product_blocks/iptrunk.py index 3bf5266bc7ab6531f39cf553073b8724880e2304..80419a298d9551ef45148f13178e5986e8c9aa0e 100644 --- a/gso/products/product_blocks/iptrunk.py +++ b/gso/products/product_blocks/iptrunk.py @@ -149,7 +149,7 @@ class IptrunkBlock(IptrunkBlockProvisioning, lifecycle=[SubscriptionLifecycle.AC iptrunk_speed: PhyPortCapacity #: The minimum amount of links the trunk should consist of. iptrunk_minimum_links: int - #: The :term:`IS-IS` metric of this link + #: The :term:`ISIS` metric of this link iptrunk_isis_metric: int #: The IPv4 network used for this trunk. iptrunk_ipv4_network: ipaddress.IPv4Network diff --git a/gso/products/product_blocks/router.py b/gso/products/product_blocks/router.py index 8f0896a56777769583b6ce4d0ebaabb8630e10b3..290ca41f11853bbf57f1c83c4407045211ff9cb3 100644 --- a/gso/products/product_blocks/router.py +++ b/gso/products/product_blocks/router.py @@ -96,13 +96,13 @@ class RouterBlock(RouterBlockProvisioning, lifecycle=[SubscriptionLifecycle.ACTI router_lo_ipv4_address: ipaddress.IPv4Address #: The IPv6 loopback address of the router. router_lo_ipv6_address: ipaddress.IPv6Address - #: The :term:`ISO` :term:`NET` of the router, used for :term:`IS-IS` support. + #: The :term:`ISO` :term:`NET` of the router, used for :term:`ISIS` support. router_lo_iso_address: str #: The SI IPv4 network of the router. router_si_ipv4_network: ipaddress.IPv4Network | None - #: The IAS LT IPv4 network of the router. + #: The :term:`IAS` LT IPv4 network of the router. router_ias_lt_ipv4_network: ipaddress.IPv4Network | None - #: The IAS LT IPv6 network of the router. + #: The :term:`IAS` LT IPv6 network of the router. router_ias_lt_ipv6_network: ipaddress.IPv6Network | None #: The vendor of the router, can be any of the values defined in :class:`RouterVendor`. router_vendor: RouterVendor @@ -110,5 +110,5 @@ class RouterBlock(RouterBlockProvisioning, lifecycle=[SubscriptionLifecycle.ACTI router_role: RouterRole #: The :class:`Site` that this router resides in. Both physically and computationally. router_site: SiteBlock - #: The router is going to have an LT interface between inet0 and IAS + #: The router is going to have an LT interface between inet0 and :term:`IAS`. router_is_ias_connected: bool diff --git a/gso/products/product_blocks/site.py b/gso/products/product_blocks/site.py index 1950d2973cf3113bea8ba5f2f85793bd3a056fef..efe21c4b270a8974c1615b89f025012ff8793582 100644 --- a/gso/products/product_blocks/site.py +++ b/gso/products/product_blocks/site.py @@ -119,5 +119,5 @@ class SiteBlock(SiteBlockProvisioning, lifecycle=[SubscriptionLifecycle.ACTIVE]) site_tier: SiteTier #: The address of the terminal server that this router is connected to. The terminal server provides out of band #: access. This is required in case a link goes down, or when a router is initially added to the network and it - #: does not have any IP trunks connected to it yet. + #: does not have any IP trunks connected to it. site_ts_address: str | None = None diff --git a/gso/schedules/scheduling.py b/gso/schedules/scheduling.py index d7044351b1493b154961eaa67c421a98290cff10..8525956cb7933facebd090d8c34938f66640bb56 100644 --- a/gso/schedules/scheduling.py +++ b/gso/schedules/scheduling.py @@ -1,4 +1,4 @@ -"""Definition of the decorator that allows for scheduling tasks in :term:`GSO` that are to run periodically.""" +"""Definition of the decorator that schedules tasks in :term:`GSO` that are to run periodically.""" import inspect from collections.abc import Callable @@ -21,11 +21,11 @@ def scheduler( Examples -------- - - `minute='*/15'`: Run every 15 minutes. - - `hour='*/3'`: Run every 3 hours. - - `day_of_week='mon-fri'`: Run on weekdays only. - - `day_of_month='1-7,15-21'`: Run on the first and third weeks of the month. - - `month_of_year='*/3'`: Run on the first month of each quarter. + - ``minute='*/15'``: Run every 15 minutes. + - ``hour='*/3'``: Run every 3 hours. + - ``day_of_week='mon-fri'``: Run on weekdays only. + - ``day_of_month='1-7,15-21'``: Run on the first and third weeks of the month. + - ``month_of_year='*/3'``: Run on the first month of each quarter. All time units can be specified with lists of numbers or crontab pattern strings for advanced scheduling. All specified time parts (minute, hour, day, etc.) must align for a task to run. diff --git a/gso/services/crm.py b/gso/services/crm.py index e656d6cdaa5690035a847b899fb61578ae0c607d..e0b8c61c39650ebc81ac438d8ea281792b74f51f 100644 --- a/gso/services/crm.py +++ b/gso/services/crm.py @@ -1,6 +1,7 @@ """A module that returns the customers available in :term:`GSO`. -For the time being, it's hardcoded to only contain GÉANT as a customer, since this is needed for PHASE 1 deployment. +For the time being, it's hardcoded to only contain GÉANT as a customer, since this is needed for the deployment of phase +1. """ from typing import Any diff --git a/gso/services/infoblox.py b/gso/services/infoblox.py index 1dbc29ebdc2eb14f44f635711f1c58f50e998168..efadf0bc0a4830011a8403d35f36ca9f49645a4d 100644 --- a/gso/services/infoblox.py +++ b/gso/services/infoblox.py @@ -1,4 +1,4 @@ -"""The Infoblox service that allows :term:`GSO` to allocate :term:`IPAM` resources that are used in products.""" +"""The Infoblox service that allocates :term:`IPAM` resources used in :term:`GSO` products.""" import ipaddress from logging import getLogger @@ -53,7 +53,7 @@ def _allocate_network( :param conn: An active Infoblox connection. :type conn: :class:`infoblox_client.connector.Connector` - :param dns_view: The Infoblox `dns_view` in which the network should be allocated. + :param dns_view: The Infoblox ``dns_view`` in which the network should be allocated. :type dns_view: str :param netmask: The netmask of the desired network. Can be up to 32 for v4 networks, and 128 for v6 networks. :type netmask: int @@ -178,7 +178,7 @@ def allocate_host( :param cname_aliases: A list of any :term:`CNAME` aliases that should be associated with this host. Most often this will be a single loopback address. :type cname_aliases: list[str] - :param comment: A comment that is added to the host record in Infoblox, should be the `subscription_id` of the new + :param comment: A comment that is added to the host record in Infoblox, should be the ``subscription_id`` of the new :class:`Router` subscription. :type comment: str """ diff --git a/gso/services/netbox_client.py b/gso/services/netbox_client.py index e8e2bdf4605e14fac01cdba2dd96c030d08446c8..4bf9fd6609c0032b2fc30c6605b5dd87ca62190d 100644 --- a/gso/services/netbox_client.py +++ b/gso/services/netbox_client.py @@ -213,10 +213,10 @@ class NetboxClient: """ iface = self.get_interface_by_name_and_device(iface_name, device_name) - # Get LAG + # Get :term:`LAG` lag = self.get_interface_by_name_and_device(lag_name, device_name) - # Assign interface to LAG, ensuring it doesn't already belong to a LAG + # Assign interface to :term:`LAG`, ensuring it does not already belong to a :term:`LAG`. if iface.lag: msg = f"The interface: {iface_name} on device: {device_name} already belongs to a LAG: {iface.lag.name}." raise WorkflowStateError( @@ -275,7 +275,7 @@ class NetboxClient: return interface def detach_interfaces_from_lag(self, device_name: str, lag_name: str) -> None: - """Detach all interfaces from a LAG.""" + """Detach all interfaces from a :term:`LAG`.""" 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( @@ -288,11 +288,11 @@ class NetboxClient: interface.save() def get_available_lags(self, router_id: UUID) -> list[str]: - """Return all available :term:`LAG`s not assigned to a device.""" + """Return all available :term:`LAG` not assigned to a device.""" router_name = Router.from_subscription(router_id).router.router_fqdn device = self.get_device_by_name(router_name) - # Get the existing LAG interfaces for the device + # Get the existing :term:`LAG` interfaces for the device lag_interface_names = [ interface["name"] for interface in self.netbox.dcim.interfaces.filter(device=device.name, type="lag") ] diff --git a/gso/services/provisioning_proxy.py b/gso/services/provisioning_proxy.py index 51e942abd88b3bf99728323305cb41bd97ba8037..01cf6983df4f9054173f156e8321472c558a4fd2 100644 --- a/gso/services/provisioning_proxy.py +++ b/gso/services/provisioning_proxy.py @@ -101,7 +101,7 @@ def provision_router( :type callback_route: str :param tt_number: Trouble ticket number related to the operation. :type tt_number: str - :param dry_run: A boolean indicating whether this should be a dry run or not, defaults to `True`. + :param dry_run: A boolean indicating whether this should be a dry run or not, defaults to ``True``. :type dry_run: bool :rtype: None """ @@ -137,11 +137,11 @@ def provision_ip_trunk( :type tt_number: str :param config_object: The type of object that's deployed. :type config_object: str - :param dry_run: A boolean indicating whether this should be a dry run or not, defaults to `True`. + :param dry_run: A boolean indicating whether this should be a dry run or not, defaults to ``True``. :type dry_run: bool :rtype: None - :param removed_ae_members: A list of interfaces that are removed from the :term:`LAG`, defaults to `None`. - it's only used when we removed some interfaces from the LAG in modify_ip_trunk. + :param removed_ae_members: A list of interfaces that are removed from the :term:`LAG`, defaults to ``None``. + only used when removing interfaces from the :term:`LAG` in ``modify_ip_trunk``. """ parameters = { "subscription": json.loads(json_dumps(subscription)), @@ -204,7 +204,7 @@ def deprovision_ip_trunk( :type callback_route: str :param tt_number: Trouble ticket number related to the operation. :type tt_number: str - :param dry_run: A boolean indicating whether this should be a dry run or not, defaults to `True`. + :param dry_run: A boolean indicating whether this should be a dry run or not, defaults to ``True``. :type dry_run: bool :rtype: None """ @@ -237,14 +237,14 @@ def migrate_ip_trunk( :param subscription: The subscription object that's to be migrated. :type subscription: :class:`Iptrunk` - :param new_node: The new node that is being migrated to + :param new_node: The new node that is being migrated to. :type new_node: :class:`Router` - :param new_lag_interface: The name of the new aggregated Ethernet interface + :param new_lag_interface: The name of the new aggregated Ethernet interface. :type new_lag_interface: str - :param new_lag_member_interfaces: The new list of interfaces that are part of the :term:`LAG` + :param new_lag_member_interfaces: The new list of interfaces that are part of the :term:`LAG`. :type new_lag_member_interfaces: list[str] - :param replace_index: The index of the side that is going to be replaced as part of the existing trunk, - can be `0` or `1`. + :param replace_index: The index of the side that is going to be replaced as part of the existing trunk, can be ``0`` + or ``1``. :type replace_index: int :param process_id: The related process ID, used for callback. :type process_id: UUIDstr @@ -252,11 +252,11 @@ def migrate_ip_trunk( :type callback_route: str :param tt_number: Trouble ticket number related to the operation. :type tt_number: str - :param verb: The verb that is passed to the executed playbook + :param verb: The verb that is passed to the executed playbook. :type verb: str :param config_object: The object that is configured. :type config_object: str - :param dry_run: A boolean indicating whether this should be a dry run or not, defaults to `True`. + :param dry_run: A boolean indicating whether this should be a dry run or not, defaults to ``True``. :type dry_run: bool :rtype: None """ @@ -306,8 +306,8 @@ def pp_interaction(provisioning_step: Step) -> StepList: """Interact with the provisioning proxy :term:`LSO` using a callback step. An asynchronous interaction with the provisioning proxy. This is an external system that executes Ansible playbooks - in order to provision service subscriptions. If the playbook fails, this step will also fail, allowing for the user - to retry provisioning from the UI. + to provision service subscriptions. If the playbook fails, this step will also fail, allowing for the user to retry + provisioning from the UI. :param provisioning_step: A workflow step that performs an operation remotely using the provisioning proxy. :type provisioning_step: :class:`Step` diff --git a/gso/services/subscriptions.py b/gso/services/subscriptions.py index be283789507c03b10262bb6391effa5690cb8eb6..3f3bcc8a9e05057eac94ad7d4cf13cddc8dcf004 100644 --- a/gso/services/subscriptions.py +++ b/gso/services/subscriptions.py @@ -1,6 +1,6 @@ """A collection of methods that make interaction with coreDB more straight-forward. -This prevents someone from having to re-write database statements multiple times, that might turn out to be erroneous +This prevents someone from having to re-write database statements many times, that might turn out to be erroneous or inconsistent when not careful. """ @@ -103,7 +103,7 @@ def get_active_subscriptions_by_field_and_value(field_name: str, field_value: st :param field_name: The name of the field to filter by. :type field_name: str - :param field_value: The value of the field to match against. + :param field_value: The value of the field to match. :type field_value: Any :return: A list of active Subscription objects that match the criteria. diff --git a/gso/utils/__init__.py b/gso/utils/__init__.py index 62340c1d5a8267a8c0a65703365077ed3a17b192..5d9237978f9dce7d87e2e8fd18b1636bdd4b88e0 100644 --- a/gso/utils/__init__.py +++ b/gso/utils/__init__.py @@ -1 +1 @@ -"""Utility module that contains helper methods, exceptions, etc.""" +"""Utility module that has helper methods, exceptions, etc.""" diff --git a/gso/utils/helpers.py b/gso/utils/helpers.py index d59b6d8595b188d3c054ddcae94ddeff3ae4b9ca..7cd8540a5e623660906cac49aba03e6797875b5d 100644 --- a/gso/utils/helpers.py +++ b/gso/utils/helpers.py @@ -209,12 +209,12 @@ def validate_country_code(country_code: str) -> str: def validate_site_name(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). + The site name must consist of three uppercase letters, optionally followed by a single digit. """ 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 " + "Enter a valid site name. It must consist of three uppercase letters (A-Z), followed by an optional single " f"digit (0-9). Received: {site_name}" ) raise ValueError(msg) diff --git a/gso/workflows/iptrunk/create_iptrunk.py b/gso/workflows/iptrunk/create_iptrunk.py index a0a5af27121c2f0b4ea8385b1d6abc34a09dc891..169f940ed829cad1de233379d1bd26dd2ec6590e 100644 --- a/gso/workflows/iptrunk/create_iptrunk.py +++ b/gso/workflows/iptrunk/create_iptrunk.py @@ -335,11 +335,11 @@ 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.""" + """Create the :term:`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: - # Create LAG interfaces + # Create :term:`LAG` interfaces lag_interface: Interfaces = nbclient.create_interface( iface_name=trunk_side.iptrunk_side_ae_iface, interface_type="lag", @@ -347,7 +347,7 @@ def reserve_interfaces_in_netbox(subscription: IptrunkProvisioning) -> State: description=str(subscription.subscription_id), enabled=True, ) - # Attach physical interfaces to LAG + # Attach physical interfaces to :term:`LAG` # Update interface description to subscription ID # Reserve interfaces for interface in trunk_side.iptrunk_side_ae_members: @@ -368,7 +368,7 @@ def reserve_interfaces_in_netbox(subscription: IptrunkProvisioning) -> State: @step("Allocate interfaces in Netbox") def allocate_interfaces_in_netbox(subscription: IptrunkProvisioning) -> State: - """Allocate the LAG interfaces in NetBox and attach the lag interfaces to the physical interfaces.""" + """Allocate the :term:`LAG` interfaces in NetBox and attach the lag interfaces to the physical interfaces.""" for trunk_side in subscription.iptrunk.iptrunk_sides: if trunk_side.iptrunk_side_node.router_vendor == RouterVendor.NOKIA: for interface in trunk_side.iptrunk_side_ae_members: diff --git a/gso/workflows/iptrunk/migrate_iptrunk.py b/gso/workflows/iptrunk/migrate_iptrunk.py index 55bde271934ccb339429af052f1a3bb6e1ea7773..f5fb625f61f12b6579e64c6aacd13ab3ddff060d 100644 --- a/gso/workflows/iptrunk/migrate_iptrunk.py +++ b/gso/workflows/iptrunk/migrate_iptrunk.py @@ -43,7 +43,7 @@ logger = getLogger(__name__) def initial_input_form_generator(subscription_id: UUIDstr) -> FormGenerator: - """Gather input from the operator on the new router that the IP trunk should terminate on.""" + """Gather input from the operator on the new router that the IP trunk should connect to.""" subscription = Iptrunk.from_subscription(subscription_id) form_title = ( f"Subscription {subscription.iptrunk.geant_s_sid} " @@ -498,7 +498,7 @@ def reserve_interfaces_in_netbox( nbclient = NetboxClient() if new_side.router_vendor == RouterVendor.NOKIA: - # Create LAG interfaces + # Create :term:`LAG` interfaces lag_interface: Interfaces = nbclient.create_interface( iface_name=new_lag_interface, interface_type="lag", @@ -506,7 +506,7 @@ def reserve_interfaces_in_netbox( description=str(subscription.subscription_id), enabled=True, ) - # Attach physical interfaces to LAG + # Attach physical interfaces to :term:`LAG` # Reserve interfaces for interface in new_lag_member_interfaces: nbclient.attach_interface_to_lag( @@ -545,7 +545,7 @@ def update_netbox( iface["interface_name"], ) - # Delete LAG interfaces + # Delete :term:`LAG` interfaces nbclient.delete_interface( old_side_data["iptrunk_side_node"]["router_fqdn"], old_side_data["iptrunk_side_ae_iface"], @@ -563,7 +563,7 @@ def migrate_iptrunk() -> StepList: * Reserve new interfaces in Netbox * Set the :term:`ISIS` metric of the current trunk to an arbitrarily high value to drain all traffic - * Disable - but don't delete - the old configuration on the routers, first as a dry run + * Disable - but do not delete - the old configuration on the routers, first as a dry run * Deploy the new configuration on the routers, first as a dry run * Wait for operator confirmation that the physical fiber has been moved before continuing * Deploy a new :term:`ISIS` interface between routers A and C @@ -571,7 +571,7 @@ def migrate_iptrunk() -> StepList: * Restore the old :term:`ISIS` metric on the new trunk * Delete the old, disabled configuration on the routers, first as a dry run * Reflect the changes made in :term:`IPAM` - * Update the subscription model in the database accordingly + * Update the subscription model in the database * Update the reserved interfaces in Netbox TODO: add interface checks diff --git a/gso/workflows/iptrunk/modify_trunk_interface.py b/gso/workflows/iptrunk/modify_trunk_interface.py index 3c3e5662d7e73ed758c332c3f9c8e9b3ea38326d..64265ddebf894299b5feba6c39e6a85fea38d3ac 100644 --- a/gso/workflows/iptrunk/modify_trunk_interface.py +++ b/gso/workflows/iptrunk/modify_trunk_interface.py @@ -248,7 +248,7 @@ def update_interfaces_in_netbox(subscription: Iptrunk, removed_ae_members: dict, # Free removed interfaces for member in removed_ae_members[str(side)]: nbclient.free_interface(router_name, member["interface_name"]) - # Attach physical interfaces to LAG + # Attach physical interfaces to :term:`LAG` # Update interface description to subscription ID # Reserve interfaces for interface in subscription.iptrunk.iptrunk_sides[side].iptrunk_side_ae_members: @@ -274,7 +274,7 @@ def update_interfaces_in_netbox(subscription: Iptrunk, removed_ae_members: dict, @step("Allocate interfaces in Netbox") def allocate_interfaces_in_netbox(subscription: Iptrunk, previous_ae_members: dict) -> State: - """Allocate the LAG interfaces in NetBox. + """Allocate the :term:`LAG` interfaces in NetBox. Attach the :term:`LAG` interfaces to the physical interfaces detach old ones from the :term:`LAG`. """ @@ -311,7 +311,7 @@ def modify_trunk_interface() -> StepList: * Update the subscription in the database * Reserve new interfaces in Netbox * Provision the updated version of the IP trunk, first as a dry run - * Allocate the previously reserved interfaces in Netbox + * Allocate the reserved interfaces in Netbox """ return ( init diff --git a/gso/workflows/iptrunk/terminate_iptrunk.py b/gso/workflows/iptrunk/terminate_iptrunk.py index b4eb75cbaa0b72bc7c0d4f9ccec4f14386a943bd..22046fb68c14d5405ee37b815dd22ec9ffae825e 100644 --- a/gso/workflows/iptrunk/terminate_iptrunk.py +++ b/gso/workflows/iptrunk/terminate_iptrunk.py @@ -24,7 +24,7 @@ from gso.utils.helpers import set_isis_to_90000 def initial_input_form_generator() -> FormGenerator: - """Ask the operator to confirm whether router configuration and/or IPAM resources should be deleted.""" + """Ask the operator to confirm whether router configuration and :term:`IPAM` resources should be deleted.""" class TerminateForm(FormPage): termination_label: Label = ( @@ -129,7 +129,7 @@ def terminate_iptrunk() -> StepList: * Set the :term:`ISIS` metric of the IP trunk to an arbitrarily high value * Disable and remove configuration from the routers, first as a dry run * Mark the IP trunk interfaces as free in Netbox - * Clear IPAM resources, if selected by the operator + * Clear :term:`IPAM` resources, if selected by the operator * Terminate the subscription in the service database """ run_config_steps = conditional(lambda state: state["remove_configuration"]) diff --git a/gso/workflows/router/create_router.py b/gso/workflows/router/create_router.py index 1ec7f8222cc59c6417b747c7bbfaf69cde398408..9b49313438806ddef1578ef0b362063bef12328a 100644 --- a/gso/workflows/router/create_router.py +++ b/gso/workflows/router/create_router.py @@ -128,7 +128,7 @@ def ipam_allocate_loopback(subscription: RouterProvisioning, is_ias_connected: b @step("Allocate IAS connection in IPAM") def ipam_allocate_ias_networks(subscription: RouterProvisioning) -> State: - """Allocate required IAS :term:`IPAM` resources.""" + """Allocate required :term:`IAS` :term:`IPAM` resources.""" fqdn = subscription.router.router_fqdn subscription.router.router_si_ipv4_network = infoblox.allocate_v4_network( diff --git a/gso/workflows/router/terminate_router.py b/gso/workflows/router/terminate_router.py index e22823977c775937bc0fb45e740a75de9278ce42..04583ffc29d3f7e48ef49497be27dc875c6c1c9f 100644 --- a/gso/workflows/router/terminate_router.py +++ b/gso/workflows/router/terminate_router.py @@ -25,7 +25,7 @@ logger = logging.getLogger(__name__) def initial_input_form_generator(subscription_id: UUIDstr) -> FormGenerator: - """Let the operator decide whether to delete configuration on the router, and/or clear up :term:`IPAM` resources.""" + """Let the operator decide whether to delete configuration on the router, and clear up :term:`IPAM` resources.""" Router.from_subscription(subscription_id) class TerminateForm(FormPage): @@ -59,7 +59,7 @@ def deprovision_si_ips(subscription: Router) -> dict: @step("Deprovision IAS LT interfaces from IPAM") def deprovision_lt_ips(subscription: Router) -> dict: - """Clear up IAS LT interfaces from :term:`IPAM`.""" + """Clear up :term:`IAS` LT interfaces from :term:`IPAM`.""" infoblox.delete_network(ipaddress.IPv4Network(subscription.router.router_ias_lt_ipv4_network)) infoblox.delete_network(ipaddress.IPv6Network(subscription.router.router_ias_lt_ipv6_network)) diff --git a/gso/workflows/site/create_site.py b/gso/workflows/site/create_site.py index ac4fbb7ed62dca473349fbe089ba637f2ddd4582..7e93a5431edc7fa6e050298a0c5b9b39051bf6ef 100644 --- a/gso/workflows/site/create_site.py +++ b/gso/workflows/site/create_site.py @@ -62,8 +62,7 @@ def initial_input_form_generator(product_name: str) -> FormGenerator: 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). + The site name must consist of three uppercase letters, followed by an optional single digit. """ validate_site_fields_is_unique("site_name", site_name) validate_site_name(site_name) diff --git a/test/workflows/__init__.py b/test/workflows/__init__.py index c4852e9dcffc3b3c0e286d3851481398d1731cf0..b5234cb3f5a0a3a272212ddd8098a704c62c92bf 100644 --- a/test/workflows/__init__.py +++ b/test/workflows/__init__.py @@ -116,7 +116,7 @@ def extract_error(result): class WorkflowInstanceForTests(LazyWorkflowInstance): """Register Test workflows. - Similar to `LazyWorkflowInstance` but does not require an import during instantiate + Similar to ``LazyWorkflowInstance`` but does not require an import during instantiate Used for creating test workflows """ @@ -173,7 +173,7 @@ def _store_step(step_log: list[tuple[Step, Process]]) -> Callable[[ProcessStat, def run_workflow(workflow_key: str, input_data: State | list[State]) -> tuple[Process, ProcessStat, list]: - # ATTENTION!! This code needs to be as similar as possible to `server.services.processes.start_process` + # ATTENTION!! This code needs to be as similar as possible to ``server.services.processes.start_process`` # The main differences are: we use a different step log function, and we don't run in # a separate thread user = "john.doe" @@ -212,7 +212,7 @@ def resume_workflow( 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` + # 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 persistent = list( filter( diff --git a/test/workflows/site/test_create_site.py b/test/workflows/site/test_create_site.py index 0ddb06b0e082126d685893951517a41da5730967..d5d013a7b310b124d8e25ec0c64e9efe0a2c27c2 100644 --- a/test/workflows/site/test_create_site.py +++ b/test/workflows/site/test_create_site.py @@ -51,10 +51,7 @@ def test_site_name_is_incorrect(responses, faker): The validation should throw an exception in case of a invalid string. """ invalid_site_name = "AMST10" - expected_exception_msg = ( - r".*Enter a valid site name\. It must consist of three uppercase letters \(A-Z\) followed by an optional single" - rf" digit \(0\-9\)\. Received: {invalid_site_name} \(type=value_error\)" - ) + expected_exception_msg = rf".*Enter a valid site name.+Received: {invalid_site_name}.*" product_id = get_product_id_by_name(ProductType.SITE) initial_site_data = [ {"product": product_id},