diff --git a/lso/__init__.py b/lso/__init__.py
index e05c6549c648a51d1e5f71f0afda3d9167f8cf4c..8fbe5e1fa6814ed8e5305f831b31d8da502282fe 100644
--- a/lso/__init__.py
+++ b/lso/__init__.py
@@ -29,14 +29,14 @@ def create_app():
         allow_headers=["*"],
     )
 
-    app.include_router(default.router, prefix='/api')
-    app.include_router(device.router, prefix='/api/device')
-    app.include_router(ip_trunk.router, prefix='/api/ip_trunk')
+    app.include_router(default.router, prefix="/api")
+    app.include_router(device.router, prefix="/api/device")
+    app.include_router(ip_trunk.router, prefix="/api/ip_trunk")
 
     # test that config params are loaded and available
     config.load()
 
-    logging.info('FastAPI app initialized')
+    logging.info("FastAPI app initialized")
 
     environment.setup_logging()
 
diff --git a/lso/app.py b/lso/app.py
index 4d83e840392acc9344b5c94eb347100f0a252fa6..e5455fcf9558ba6e27b96937f2ea6d1af4ebbc9e 100644
--- a/lso/app.py
+++ b/lso/app.py
@@ -7,8 +7,5 @@ app = lso.create_app()
 
 if __name__ == "__main__":
     import uvicorn
-    uvicorn.run(
-        'lso.app:app',
-        host='0.0.0.0',
-        port=44444,
-        log_level='debug')
+
+    uvicorn.run("lso.app:app", host="0.0.0.0", port=44444, log_level="debug")
diff --git a/lso/config.py b/lso/config.py
index 4817aabd2ef61673fad8904cc0b54c85ec818a7d..b7353339bab85760c0746cb8c0da130f0b33ba33 100644
--- a/lso/config.py
+++ b/lso/config.py
@@ -13,13 +13,11 @@ import jsonschema
 from pydantic import BaseModel, DirectoryPath
 
 CONFIG_SCHEMA = {
-    '$schema': 'http://json-schema.org/draft-07/schema#',
-    'type': 'object',
-    'properties': {
-        'ansible_playbooks_root_dir': {'type': 'string'}
-    },
-    'required': ['ansible_playbooks_root_dir'],
-    'additionalProperties': False
+    "$schema": "http://json-schema.org/draft-07/schema#",
+    "type": "object",
+    "properties": {"ansible_playbooks_root_dir": {"type": "string"}},
+    "required": ["ansible_playbooks_root_dir"],
+    "additionalProperties": False,
 }
 
 
@@ -28,6 +26,7 @@ class Config(BaseModel):
     Simple Config class that only contains the path to the used Ansible
     playbooks.
     """
+
     ansible_playbooks_root_dir: DirectoryPath
 
 
@@ -55,6 +54,6 @@ def load() -> Config:
 
     :return: a dict containing the parsed configuration parameters
     """
-    assert 'SETTINGS_FILENAME' in os.environ
-    with open(os.environ['SETTINGS_FILENAME'], encoding='utf-8') as file:
+    assert "SETTINGS_FILENAME" in os.environ
+    with open(os.environ["SETTINGS_FILENAME"], encoding="utf-8") as file:
         return load_from_file(file)
diff --git a/lso/environment.py b/lso/environment.py
index 3cab8a89ac92dc6ffcfc471fc24d1a54f71099e6..fddbf74c32910d7b567f8f4bd367027e9efdb182 100644
--- a/lso/environment.py
+++ b/lso/environment.py
@@ -6,36 +6,19 @@ import logging.config
 import os
 
 LOGGING_DEFAULT_CONFIG = {
-    'version': 1,
-    'disable_existing_loggers': False,
-    'formatters': {
-        'simple': {
-            'format': '%(asctime)s - %(name)s '
-                      '(%(lineno)d) - %(levelname)s - %(message)s'
+    "version": 1,
+    "disable_existing_loggers": False,
+    "formatters": {"simple": {"format": "%(asctime)s - %(name)s " "(%(lineno)d) - %(levelname)s - %(message)s"}},
+    "handlers": {
+        "console": {
+            "class": "logging.StreamHandler",
+            "level": "DEBUG",
+            "formatter": "simple",
+            "stream": "ext://sys.stdout",
         }
     },
-
-    'handlers': {
-        'console': {
-            'class': 'logging.StreamHandler',
-            'level': 'DEBUG',
-            'formatter': 'simple',
-            'stream': 'ext://sys.stdout'
-        }
-    },
-
-    'loggers': {
-        'resource_management': {
-            'level': 'DEBUG',
-            'handlers': ['console'],
-            'propagate': False
-        }
-    },
-
-    'root': {
-        'level': 'INFO',
-        'handlers': ['console']
-    }
+    "loggers": {"resource_management": {"level": "DEBUG", "handlers": ["console"], "propagate": False}},
+    "root": {"level": "INFO", "handlers": ["console"]},
 }
 
 
@@ -47,9 +30,9 @@ def setup_logging():
     the filename, otherwise use LOGGING_DEFAULT_CONFIG
     """
     logging_config = LOGGING_DEFAULT_CONFIG
-    if 'LOGGING_CONFIG' in os.environ:
-        filename = os.environ['LOGGING_CONFIG']
-        with open(filename, encoding='utf-8') as file:
+    if "LOGGING_CONFIG" in os.environ:
+        filename = os.environ["LOGGING_CONFIG"]
+        with open(filename, encoding="utf-8") as file:
             logging_config = json.loads(file.read())
 
     logging.config.dictConfig(logging_config)
diff --git a/lso/playbook.py b/lso/playbook.py
index e92f0a0abb678c0a2120dcc35d985dfcbcf77f0f..4ebd2663a5433299809a2ed04c2306a7d1441dbf 100644
--- a/lso/playbook.py
+++ b/lso/playbook.py
@@ -18,10 +18,11 @@ class PlaybookJobStatus(str, enum.Enum):
     """
     Enumerator for status codes of a playbook job that's running.
     """
+
     #: All is well.
-    OK = 'ok'
+    OK = "ok"
     #: An error has occurred.
-    ERROR = 'error'
+    ERROR = "error"
 
 
 class PlaybookLaunchResponse(BaseModel):
@@ -34,12 +35,13 @@ class PlaybookLaunchResponse(BaseModel):
     :param info:
     :type info: str, optional
     """
+
     #: Status of a Playbook job.
     status: PlaybookJobStatus
     #: The ID assigned to a job.
-    job_id: str = ''
+    job_id: str = ""
     #: Information on a job.
-    info: str = ''
+    info: str = ""
 
 
 def playbook_launch_success(job_id: str) -> PlaybookLaunchResponse:
@@ -64,13 +66,7 @@ def playbook_launch_error(reason: str) -> PlaybookLaunchResponse:
     return PlaybookLaunchResponse(status=PlaybookJobStatus.ERROR, info=reason)
 
 
-def _run_playbook_proc(
-        job_id: str,
-        playbook_path: str,
-        extra_vars: dict,
-        inventory: [str],
-        callback: str
-):
+def _run_playbook_proc(job_id: str, playbook_path: str, extra_vars: dict, inventory: [str], callback: str):
     """
     Internal function for running a playbook.
 
@@ -80,21 +76,17 @@ def _run_playbook_proc(
     :param str callback: Callback URL to PUT to when execution is completed.
     :param [str] inventory: Ansible inventory to run the playbook against.
     """
-    ansible_playbook_run = ansible_runner.run(
-        playbook=playbook_path,
-        inventory=inventory,
-        extravars=extra_vars
-    )
+    ansible_playbook_run = ansible_runner.run(playbook=playbook_path, inventory=inventory, extravars=extra_vars)
 
     payload = [
         {
-            'pp_run_results': {
-                'status': ansible_playbook_run.status,
-                'job_id': job_id,
-                'output': str(ansible_playbook_run.stdout.read()),
-                'return_code': int(ansible_playbook_run.rc)
+            "pp_run_results": {
+                "status": ansible_playbook_run.status,
+                "job_id": job_id,
+                "output": str(ansible_playbook_run.stdout.read()),
+                "return_code": int(ansible_playbook_run.rc),
             },
-            'confirm': 'ACCEPTED'
+            "confirm": "ACCEPTED",
         }
     ]
 
@@ -102,11 +94,7 @@ def _run_playbook_proc(
     assert request_result.status_code == 204
 
 
-def run_playbook(
-        playbook_path: str,
-        extra_vars: dict,
-        inventory: [str],
-        callback: str) -> PlaybookLaunchResponse:
+def run_playbook(playbook_path: str, extra_vars: dict, inventory: [str], callback: str) -> PlaybookLaunchResponse:
     """
     Run an Ansible playbook against a specified inventory.
 
@@ -126,12 +114,13 @@ def run_playbook(
     thread = threading.Thread(
         target=_run_playbook_proc,
         kwargs={
-            'job_id': job_id,
-            'playbook_path': playbook_path,
-            'inventory': inventory,
-            'extra_vars': extra_vars,
-            'callback': callback
-        })
+            "job_id": job_id,
+            "playbook_path": playbook_path,
+            "inventory": inventory,
+            "extra_vars": extra_vars,
+            "callback": callback,
+        },
+    )
     thread.start()
 
     return playbook_launch_success(job_id=job_id)
diff --git a/lso/routes/default.py b/lso/routes/default.py
index 5295ece1d760774556d50a847d077de31ed971da..a9da37278f61a01e84661466a964de6704ea27dd 100644
--- a/lso/routes/default.py
+++ b/lso/routes/default.py
@@ -8,8 +8,8 @@ import pkg_resources
 from fastapi import APIRouter
 from pydantic import BaseModel, constr
 
-API_VERSION = '0.1'
-VERSION_STRING = constr(regex=r'\d+\.\d+')
+API_VERSION = "0.1"
+VERSION_STRING = constr(regex=r"\d+\.\d+")
 
 router = APIRouter()
 
@@ -24,12 +24,11 @@ class Version(BaseModel):
     module: VERSION_STRING
 
 
-@router.get('/version')
+@router.get("/version")
 def version() -> Version:
     """
     Return the version numbers of the API version, and the module version.
 
     :return: Version object with both API and `goat-lso` versions numbers.
     """
-    return Version(api=API_VERSION,
-                   module=pkg_resources.get_distribution('goat-lso').version)
+    return Version(api=API_VERSION, module=pkg_resources.get_distribution("goat-lso").version)
diff --git a/lso/routes/device.py b/lso/routes/device.py
index cdd4aaa4493d5184552fe489f95eb29ae449a36e..81ee971a5cc3dcb09e2decfbbe1770328842cdda 100644
--- a/lso/routes/device.py
+++ b/lso/routes/device.py
@@ -24,6 +24,7 @@ class NodeProvisioningParams(BaseModel):
     :param dry_run:
     :type dry_run: bool, optional
     """
+
     #: Callback URL that is reported back to WFO, this will allow for the
     #: workflow to continue once the playbook has been executed.
     callback: HttpUrl
@@ -35,9 +36,8 @@ class NodeProvisioningParams(BaseModel):
     dry_run: Optional[bool] = True
 
 
-@router.post('/')
-async def provision_node(params: NodeProvisioningParams) \
-        -> playbook.PlaybookLaunchResponse:
+@router.post("/")
+async def provision_node(params: NodeProvisioningParams) -> playbook.PlaybookLaunchResponse:
     """
     Launches a playbook to provision a new node.
     The response will contain either a job id or error information.
@@ -48,22 +48,20 @@ async def provision_node(params: NodeProvisioningParams) \
     :rtype: :class:`lso.playbook.PlaybookLaunchResponse`
     """
     extra_vars = {
-        'wfo_device_json': params.subscription,
-        'dry_run': str(params.dry_run),
-        'verb': 'deploy',
-        'commit_comment': 'Base config deployed with WFO/LSO & Ansible'
+        "wfo_device_json": params.subscription,
+        "dry_run": str(params.dry_run),
+        "verb": "deploy",
+        "commit_comment": "Base config deployed with WFO/LSO & Ansible",
     }
 
-    if params.subscription['device_type'] == 'router':
-        playbook_path = \
-            os.path.join(config_params.ansible_playbooks_root_dir,
-                         'base_config.yaml')
+    if params.subscription["device_type"] == "router":
+        playbook_path = os.path.join(config_params.ansible_playbooks_root_dir, "base_config.yaml")
     else:
-        raise ValueError(f'Cannot find playbook path for device type '
-                         f"{params.subscription['device_type']}!!")
+        raise ValueError(f"Cannot find playbook path for device type " f"{params.subscription['device_type']}!!")
 
     return playbook.run_playbook(
         playbook_path=playbook_path,
         inventory=f"{params.subscription['device']['device_fqdn']}",
         extra_vars=extra_vars,
-        callback=params.callback)
+        callback=params.callback,
+    )
diff --git a/lso/routes/ip_trunk.py b/lso/routes/ip_trunk.py
index ceecca6b2d9498775980e3ff3834d67977c1fdde..10448788ed0238109bd27cd10ec33e074204f39d 100644
--- a/lso/routes/ip_trunk.py
+++ b/lso/routes/ip_trunk.py
@@ -16,6 +16,7 @@ config_params = config.load()
 
 class IPTrunkParams(BaseModel):
     """Default parameters for an IPtrunk deployment."""
+
     #: The address where LSO should call back to upon completion.
     callback: HttpUrl
     #: A dictionary representation of the IP trunk
@@ -25,6 +26,7 @@ class IPTrunkParams(BaseModel):
 
 class IPTrunkProvisioningParams(IPTrunkParams):
     """Additional parameters for provisioning an IPtrunk."""
+
     #: Whether this playbook execution should be a dry run, or run for real.
     #: defaults to ``True`` for obvious reasons, also making it an optional
     #: parameter.
@@ -35,6 +37,7 @@ class IPTrunkProvisioningParams(IPTrunkParams):
 
 class IPTrunkModifyParams(IPTrunkParams):
     """Additional parameters for modifying an IPtrunk."""
+
     #: Whether this playbook execution should be a dry run, or run for real.
     #: defaults to ``True`` for obvious reasons, also making it an optional
     #: parameter.
@@ -46,21 +49,22 @@ class IPTrunkModifyParams(IPTrunkParams):
 
 class IPTrunkCheckParams(IPTrunkParams):
     """Additional parameters for checking an IPtrunk."""
+
     #: The name of the check that is to be performed.
     check_name: str
 
 
 class IPTrunkDeleteParams(IPTrunkParams):
     """Additional parameters for deleting an IPtrunk."""
+
     #: Whether this playbook execution should be a dry run, or run for real.
     #: defaults to ``True`` for obvious reasons, also making it an optional
     #: parameter.
     dry_run: Optional[bool] = True
 
 
-@router.post('/')
-def provision_ip_trunk(params: IPTrunkProvisioningParams) \
-        -> PlaybookLaunchResponse:
+@router.post("/")
+def provision_ip_trunk(params: IPTrunkProvisioningParams) -> PlaybookLaunchResponse:
     """
     Launch a playbook to provision a new IP trunk service.
     The response will contain either a job ID, or error information.
@@ -72,29 +76,30 @@ def provision_ip_trunk(params: IPTrunkProvisioningParams) \
     :rtype: :class:`lso.playbook.PlaybookLaunchResponse`
     """
     extra_vars = {
-        'wfo_trunk_json': params.subscription,
-        'dry_run': str(params.dry_run),
-        'verb': 'deploy',
-        'config_object': params.object,
-        'commit_comment': f'IPtrunk '
-                          f"{params.subscription['iptrunk']['geant_s_sid']} "
-                          f"({params.subscription['subscription_id']}) - "
-                          f'deployment of {params.object}'
+        "wfo_trunk_json": params.subscription,
+        "dry_run": str(params.dry_run),
+        "verb": "deploy",
+        "config_object": params.object,
+        "commit_comment": f"IPtrunk "
+        f"{params.subscription['iptrunk']['geant_s_sid']} "
+        f"({params.subscription['subscription_id']}) - "
+        f"deployment of {params.object}",
     }
 
     return run_playbook(
-        playbook_path=path.join(config_params.ansible_playbooks_root_dir,
-                                'iptrunks.yaml'),
-        inventory=str(params.subscription['iptrunk']['iptrunk_sideA_node'][
-                          'device_fqdn'] + "\n" +
-                      params.subscription['iptrunk']['iptrunk_sideB_node'][
-                          'device_fqdn'] + "\n"),
+        playbook_path=path.join(config_params.ansible_playbooks_root_dir, "iptrunks.yaml"),
+        inventory=str(
+            params.subscription["iptrunk"]["iptrunk_sideA_node"]["device_fqdn"]
+            + "\n"
+            + params.subscription["iptrunk"]["iptrunk_sideB_node"]["device_fqdn"]
+            + "\n"
+        ),
         extra_vars=extra_vars,
-        callback=params.callback
+        callback=params.callback,
     )
 
 
-@router.put('/')
+@router.put("/")
 def modify_ip_trunk(params: IPTrunkModifyParams) -> PlaybookLaunchResponse:
     """
     Launch a playbook that modifies an existing IP trunk service.
@@ -105,28 +110,29 @@ def modify_ip_trunk(params: IPTrunkModifyParams) -> PlaybookLaunchResponse:
     :rtype: :class:`lso.playbook.PlaybookLaunchResponse`
     """
     extra_vars = {
-        'wfo_trunk_json': params.subscription,
-        'old_wfo_trunk_json': params.old_subscription,
-        'dry_run': str(params.dry_run),
-        'verb': 'modify',
-        'commit_comment': f'IPtrunk '
-                          f"{params.subscription['iptrunk']['geant_s_sid']} "
-                          f"({params.subscription['subscription_id']})"
+        "wfo_trunk_json": params.subscription,
+        "old_wfo_trunk_json": params.old_subscription,
+        "dry_run": str(params.dry_run),
+        "verb": "modify",
+        "commit_comment": f"IPtrunk "
+        f"{params.subscription['iptrunk']['geant_s_sid']} "
+        f"({params.subscription['subscription_id']})",
     }
 
     return run_playbook(
-        playbook_path=path.join(config_params.ansible_playbooks_root_dir,
-                                'iptrunks.yaml'),
-        inventory=str(params.subscription['iptrunk']['iptrunk_sideA_node'][
-                          'device_fqdn'] + "\n" +
-                      params.subscription['iptrunk']['iptrunk_sideB_node'][
-                          'device_fqdn'] + "\n"),
+        playbook_path=path.join(config_params.ansible_playbooks_root_dir, "iptrunks.yaml"),
+        inventory=str(
+            params.subscription["iptrunk"]["iptrunk_sideA_node"]["device_fqdn"]
+            + "\n"
+            + params.subscription["iptrunk"]["iptrunk_sideB_node"]["device_fqdn"]
+            + "\n"
+        ),
         extra_vars=extra_vars,
-        callback=params.callback
+        callback=params.callback,
     )
 
 
-@router.delete('/')
+@router.delete("/")
 def delete_ip_trunk(params: IPTrunkDeleteParams) -> PlaybookLaunchResponse:
     """
     Launch a playbook that deletes an existing IP trunk service.
@@ -138,29 +144,30 @@ def delete_ip_trunk(params: IPTrunkDeleteParams) -> PlaybookLaunchResponse:
     :rtype: :class:`lso.playbook.PlaybookLaunchResponse`
     """
     extra_vars = {
-        'wfo_trunk_json': params.subscription,
-        'dry_run': str(params.dry_run),
-        'verb': 'terminate',
-        'config_object': "trunk_deprovision",
-        'commit_comment': f'IPtrunk '
-                          f"{params.subscription['iptrunk']['geant_s_sid']} "
-                          f"({params.subscription['subscription_id']}) "
-                          f'- termination'
+        "wfo_trunk_json": params.subscription,
+        "dry_run": str(params.dry_run),
+        "verb": "terminate",
+        "config_object": "trunk_deprovision",
+        "commit_comment": f"IPtrunk "
+        f"{params.subscription['iptrunk']['geant_s_sid']} "
+        f"({params.subscription['subscription_id']}) "
+        f"- termination",
     }
 
     return run_playbook(
-        playbook_path=path.join(config_params.ansible_playbooks_root_dir,
-                                'iptrunks.yaml'),
-        inventory=str(params.subscription['iptrunk']['iptrunk_sideA_node'][
-                          'device_fqdn'] + "\n" +
-                      params.subscription['iptrunk']['iptrunk_sideB_node'][
-                          'device_fqdn'] + "\n"),
+        playbook_path=path.join(config_params.ansible_playbooks_root_dir, "iptrunks.yaml"),
+        inventory=str(
+            params.subscription["iptrunk"]["iptrunk_sideA_node"]["device_fqdn"]
+            + "\n"
+            + params.subscription["iptrunk"]["iptrunk_sideB_node"]["device_fqdn"]
+            + "\n"
+        ),
         extra_vars=extra_vars,
-        callback=params.callback
+        callback=params.callback,
     )
 
 
-@router.post('/perform_check')
+@router.post("/perform_check")
 def check_ip_trunk(params: IPTrunkCheckParams) -> PlaybookLaunchResponse:
     """
     Launch a playbook that performs a check on an IP trunk service instance.
@@ -172,16 +179,14 @@ def check_ip_trunk(params: IPTrunkCheckParams) -> PlaybookLaunchResponse:
     :rtype: :class:`lso.playbook.PlaybookLaunchResponse`
     """
     extra_vars = {
-        'wfo_ip_trunk_json': params.subscription,
+        "wfo_ip_trunk_json": params.subscription,
     }
     # FIXME: needs to be updated when checks become available, this includes
     # writing tests.
 
     return run_playbook(
-        playbook_path=path.join(config_params.ansible_playbooks_root_dir,
-                                f'{params.check_name}.yaml'),
-        inventory=params.subscription['iptrunk']['iptrunk_sideA_node'][
-            'device_fqdn'],
+        playbook_path=path.join(config_params.ansible_playbooks_root_dir, f"{params.check_name}.yaml"),
+        inventory=params.subscription["iptrunk"]["iptrunk_sideA_node"]["device_fqdn"],
         extra_vars=extra_vars,
-        callback=params.callback
+        callback=params.callback,
     )
diff --git a/requirements.txt b/requirements.txt
index 275a0407b11eca109e2dcfa31a9516dff7992bb1..b5cc91c67993659a7dd60ba59f15506342a37ef7 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -14,6 +14,11 @@ sphinx
 sphinx-rtd-theme
 requests
 docutils
+isort
+black
+flake8
+mypy
+ruff
 
 ansible-core==2.14.0
 ansible_merge_vars
diff --git a/setup.py b/setup.py
index 0d385378fb3130b84da0e9c76c17f13d58c84200..0f87e0af72d699bf907957897f257d1f6fc7dbb8 100644
--- a/setup.py
+++ b/setup.py
@@ -1,33 +1,33 @@
 from setuptools import find_packages, setup
 
 setup(
-    name='goat-lso',
+    name="goat-lso",
     version="0.1",
-    author='GÉANT Orchestration & Automation Team',
-    author_email='TBD',
-    description='Lightweight Service Orchestrator',
-    url='https://gitlab.geant.org/goat/gap/lso',
+    author="GÉANT Orchestration & Automation Team",
+    author_email="TBD",
+    description="Lightweight Service Orchestrator",
+    url="https://gitlab.geant.org/goat/gap/lso",
     packages=find_packages(),
     install_requires=[
-        'jsonschema',
-        'fastapi',
-        'pydantic',
-        'ansible',
-        'requests',
-        'uvicorn',
-        'ncclient',
-        'xmltodict',
-        'netaddr'
+        "jsonschema",
+        "fastapi",
+        "pydantic",
+        "ansible",
+        "requests",
+        "uvicorn",
+        "ncclient",
+        "xmltodict",
+        "netaddr",
     ],
-    license='MIT',
-    license_files=('LICENSE.txt',),
+    license="MIT",
+    license_files=("LICENSE.txt",),
     classifiers=[
-        'Programming Language :: Python :: 3',
-        'Programming Language :: Python :: 3.10',
-        'Programming Language :: Python :: 3.11',
-        'License :: OSI Approved :: MIT License',
-        'Operating System :: OS Independent',
-        'Development Status :: 2 - Pre-Alpha'
+        "Programming Language :: Python :: 3",
+        "Programming Language :: Python :: 3.10",
+        "Programming Language :: Python :: 3.11",
+        "License :: OSI Approved :: MIT License",
+        "Operating System :: OS Independent",
+        "Development Status :: 2 - Pre-Alpha",
     ],
-    python_requires='>=3.10'
+    python_requires=">=3.10",
 )
diff --git a/test/conftest.py b/test/conftest.py
index 21bf46a2a1e785aeedb66ffba09038b41f54e3da..7274c1d51f54229e58f3c3052dd683ef825f0c68 100644
--- a/test/conftest.py
+++ b/test/conftest.py
@@ -7,10 +7,7 @@ from fastapi.testclient import TestClient
 
 import lso
 
-TEST_CONFIG = {
-    'collection-name': 'kvklink.echo',
-    'test-role': 'kvklink.echo.echo_uptime'
-}
+TEST_CONFIG = {"collection-name": "kvklink.echo", "test-role": "kvklink.echo.echo_uptime"}
 
 
 @pytest.fixture
@@ -18,9 +15,7 @@ def config_data():
     """
     valid config data used to start the server
     """
-    return {
-        'ansible_playbooks_root_dir': '/'
-    }
+    return {"ansible_playbooks_root_dir": "/"}
 
 
 @pytest.fixture
@@ -30,7 +25,7 @@ def config_file(config_data):
 
     :return: Path to valid configuration file
     """
-    with tempfile.NamedTemporaryFile(mode='w') as file:
+    with tempfile.NamedTemporaryFile(mode="w") as file:
         file.write(json.dumps(config_data))
         file.flush()
         yield file.name
@@ -41,6 +36,6 @@ def client(config_file):
     """
     returns a client that can be used to test the server
     """
-    os.environ['SETTINGS_FILENAME'] = config_file
+    os.environ["SETTINGS_FILENAME"] = config_file
     app = lso.create_app()
     yield TestClient(app)  # wait here until calling context ends
diff --git a/test/routes/__init__.py b/test/routes/__init__.py
index d9e950da00b8937efa6239639eed0ea75764f862..921a61f4715ac2c6cc9db918dd0d46b46450e529 100644
--- a/test/routes/__init__.py
+++ b/test/routes/__init__.py
@@ -1,13 +1,12 @@
 from typing import TextIO
 
-TEST_CALLBACK_URL = 'https://fqdn.abc.xyz/api/resume'
+TEST_CALLBACK_URL = "https://fqdn.abc.xyz/api/resume"
 
 
 def test_ansible_runner_run(**kwargs):
-
     class Runner:
         def __init__(self):
-            self.status = 'success'
+            self.status = "success"
             self.rc = 0
             self.stdout = TextIO()
 
diff --git a/test/routes/test_device.py b/test/routes/test_device.py
index d342316ac5a3688f6db40e436afc2020429cf686..731f26397236ebdf931defd0459feea619b66094 100644
--- a/test/routes/test_device.py
+++ b/test/routes/test_device.py
@@ -13,32 +13,31 @@ def test_router_provisioning(client):
     responses.put(url=TEST_CALLBACK_URL, status=204)
 
     params = {
-        'callback': TEST_CALLBACK_URL,
-        'dry_run': True,
-        'verb': 'deploy',
-        'subscription': {
-            'device': {
-                'ts_address': '127.0.0.1',
-                'ts_port': '1234',
-                'device_fqdn': 'bogus.fqdn.org',
-                'lo_address': {'v4': '1.2.3.4', 'v6': '2001:db8::1'},
-                'lo_iso_address': '1.2.3.4.5.6',
-                'snmp_location': 'city,country[1.2,3.4]',
-                'si_ipv4_network': '1.2.3.0/24',
-                'ias_lt_network': {'v4': '1.2.3.0/24', 'v6': '2001:db8::/64'},
-                'site_country_code': 'XX',
-                'site_city': 'NOWHERE',
-                'site_latitude': '0.000',
-                'site_longitude': '0.000',
+        "callback": TEST_CALLBACK_URL,
+        "dry_run": True,
+        "verb": "deploy",
+        "subscription": {
+            "device": {
+                "ts_address": "127.0.0.1",
+                "ts_port": "1234",
+                "device_fqdn": "bogus.fqdn.org",
+                "lo_address": {"v4": "1.2.3.4", "v6": "2001:db8::1"},
+                "lo_iso_address": "1.2.3.4.5.6",
+                "snmp_location": "city,country[1.2,3.4]",
+                "si_ipv4_network": "1.2.3.0/24",
+                "ias_lt_network": {"v4": "1.2.3.0/24", "v6": "2001:db8::/64"},
+                "site_country_code": "XX",
+                "site_city": "NOWHERE",
+                "site_latitude": "0.000",
+                "site_longitude": "0.000",
             },
-            'device_type': 'router',
-            'device_vendor': 'vendor'
-        }
+            "device_type": "router",
+            "device_vendor": "vendor",
+        },
     }
 
-    with patch('lso.playbook.ansible_runner.run',
-               new=test_ansible_runner_run) as _run:
-        rv = client.post('/api/device/', json=params)
+    with patch("lso.playbook.ansible_runner.run", new=test_ansible_runner_run) as _run:
+        rv = client.post("/api/device/", json=params)
         assert rv.status_code == 200
         response = rv.json()
         # wait two seconds for the run thread to finish
@@ -47,4 +46,4 @@ def test_router_provisioning(client):
     jsonschema.validate(response, PlaybookLaunchResponse.schema())
     responses.assert_call_count(TEST_CALLBACK_URL, 1)
 
-    assert response['status'] == 'ok'
+    assert response["status"] == "ok"
diff --git a/test/routes/test_ip_trunk.py b/test/routes/test_ip_trunk.py
index 0e8378cbc5cc3128d129a1e26567c35033ad2fd0..841e09e3783a4ac4dd1439327b03198de736bdff 100644
--- a/test/routes/test_ip_trunk.py
+++ b/test/routes/test_ip_trunk.py
@@ -8,93 +8,85 @@ from lso.playbook import PlaybookLaunchResponse
 from test.routes import TEST_CALLBACK_URL, test_ansible_runner_run
 
 _SUBSCRIPTION_OBJECT = {
-    'subscription_id': '0',
-    'description': 'IP trunk, geant_s_sid:GS-00000',
-    'iptrunk': {
-        'geant_s_sid': 'GS-00000',
-        'iptrunk_description': 'A description for this trunk',
-        'iptrunk_isis_metric': 9000,
-        'iptrunk_minimum_links': 1,
-        'iptrunk_sideA_ae_geant_a_sid': 'GA-00000',
-        'iptrunk_sideA_ae_iface': 'ae0',
-        'iptrunk_sideA_ae_members': [
-            'ge-0/0/0'
-        ],
-        'iptrunk_sideA_ae_members_description': [
-            'this is the first interface on side A'
-        ],
-        'iptrunk_sideA_node': {
-            'device_fqdn': 'rtx.city.country.geant.net',
-            'device_ias_lt_ipv4_network': '1.0.0.0/31',
-            'device_ias_lt_ipv6_network': 'dead:beef::3/126',
-            'device_lo_ipv4_address': '1.0.0.0',
-            'device_lo_ipv6_address': 'dead:beef::',
-            'device_lo_iso_address': '00.0000.0000.0000.0000.0000.00',
-            'device_role': 'p',
-            'device_si_ipv4_network': '0.0.1.0/31',
-            'device_site': {
-                'name': 'SiteBlock',
-                'label': None,
-                'site_city': 'City',
-                'site_name': 'city',
-                'site_tier': '1',
-                'site_country': 'Country',
-                'site_latitude': 0.0,
-                'site_longitude': 0.0,
-                'site_internal_id': 0,
-                'site_country_code': 'XX',
-                'owner_subscription_id': '0',
-                'site_bgp_community_id': 0,
-                'subscription_instance_id': '0'
+    "subscription_id": "0",
+    "description": "IP trunk, geant_s_sid:GS-00000",
+    "iptrunk": {
+        "geant_s_sid": "GS-00000",
+        "iptrunk_description": "A description for this trunk",
+        "iptrunk_isis_metric": 9000,
+        "iptrunk_minimum_links": 1,
+        "iptrunk_sideA_ae_geant_a_sid": "GA-00000",
+        "iptrunk_sideA_ae_iface": "ae0",
+        "iptrunk_sideA_ae_members": ["ge-0/0/0"],
+        "iptrunk_sideA_ae_members_description": ["this is the first interface on side A"],
+        "iptrunk_sideA_node": {
+            "device_fqdn": "rtx.city.country.geant.net",
+            "device_ias_lt_ipv4_network": "1.0.0.0/31",
+            "device_ias_lt_ipv6_network": "dead:beef::3/126",
+            "device_lo_ipv4_address": "1.0.0.0",
+            "device_lo_ipv6_address": "dead:beef::",
+            "device_lo_iso_address": "00.0000.0000.0000.0000.0000.00",
+            "device_role": "p",
+            "device_si_ipv4_network": "0.0.1.0/31",
+            "device_site": {
+                "name": "SiteBlock",
+                "label": None,
+                "site_city": "City",
+                "site_name": "city",
+                "site_tier": "1",
+                "site_country": "Country",
+                "site_latitude": 0.0,
+                "site_longitude": 0.0,
+                "site_internal_id": 0,
+                "site_country_code": "XX",
+                "owner_subscription_id": "0",
+                "site_bgp_community_id": 0,
+                "subscription_instance_id": "0",
             },
-            'device_ts_address': '127.0.0.1',
-            'device_ts_port': 22,
-            'device_vendor': 'vendor',
-            'owner_subscription_id': '0',
-            'subscription_instance_id': '0'
+            "device_ts_address": "127.0.0.1",
+            "device_ts_port": 22,
+            "device_vendor": "vendor",
+            "owner_subscription_id": "0",
+            "subscription_instance_id": "0",
         },
-        'iptrunk_sideB_ae_geant_a_sid': 'GA-00002',
-        'iptrunk_sideB_ae_iface': 'ae0',
-        'iptrunk_sideB_ae_members': [
-            'ge-0/0/0'
-        ],
-        'iptrunk_sideB_ae_members_description': [
-            'this is the first interface side B'
-        ],
-        'iptrunk_sideB_node': {
-            'device_fqdn': 'rtx.town.country.geant.net',
-            'device_ias_lt_ipv4_network': '0.0.0.0/31',
-            'device_ias_lt_ipv6_network': 'deaf:beef::1/126',
-            'device_lo_ipv4_address': '0.0.0.0',
-            'device_lo_ipv6_address': 'dead:beef::2',
-            'device_lo_iso_address': '00.0000.0000.0000.0000.0000.00',
-            'device_role': 'p',
-            'device_si_ipv4_network': '0.1.0.0/31',
-            'device_site': {
-                'name': 'SiteBlock',
-                'label': None,
-                'site_city': 'Town',
-                'site_name': 'town',
-                'site_tier': '1',
-                'site_country': 'Country',
-                'site_latitude': 0.0,
-                'site_longitude': 0.0,
-                'site_internal_id': 1,
-                'site_country_code': 'xx',
-                'owner_subscription_id': '0',
-                'site_bgp_community_id': 2,
-                'subscription_instance_id': '0'
+        "iptrunk_sideB_ae_geant_a_sid": "GA-00002",
+        "iptrunk_sideB_ae_iface": "ae0",
+        "iptrunk_sideB_ae_members": ["ge-0/0/0"],
+        "iptrunk_sideB_ae_members_description": ["this is the first interface side B"],
+        "iptrunk_sideB_node": {
+            "device_fqdn": "rtx.town.country.geant.net",
+            "device_ias_lt_ipv4_network": "0.0.0.0/31",
+            "device_ias_lt_ipv6_network": "deaf:beef::1/126",
+            "device_lo_ipv4_address": "0.0.0.0",
+            "device_lo_ipv6_address": "dead:beef::2",
+            "device_lo_iso_address": "00.0000.0000.0000.0000.0000.00",
+            "device_role": "p",
+            "device_si_ipv4_network": "0.1.0.0/31",
+            "device_site": {
+                "name": "SiteBlock",
+                "label": None,
+                "site_city": "Town",
+                "site_name": "town",
+                "site_tier": "1",
+                "site_country": "Country",
+                "site_latitude": 0.0,
+                "site_longitude": 0.0,
+                "site_internal_id": 1,
+                "site_country_code": "xx",
+                "owner_subscription_id": "0",
+                "site_bgp_community_id": 2,
+                "subscription_instance_id": "0",
             },
-            'device_ts_address': '127.0.0.2',
-            'device_ts_port': 22,
-            'device_vendor': 'vendor',
-            'owner_subscription_id': '0',
-            'subscription_instance_id': '0'
+            "device_ts_address": "127.0.0.2",
+            "device_ts_port": 22,
+            "device_vendor": "vendor",
+            "owner_subscription_id": "0",
+            "subscription_instance_id": "0",
         },
-        'iptrunk_speed': '1',
-        'iptrunk_type': 'Dark_fiber'
+        "iptrunk_speed": "1",
+        "iptrunk_type": "Dark_fiber",
     },
-    'status': 'provisioning'
+    "status": "provisioning",
 }
 
 
@@ -103,16 +95,15 @@ def test_ip_trunk_provisioning(client):
     responses.put(url=TEST_CALLBACK_URL, status=204)
 
     params = {
-        'callback': TEST_CALLBACK_URL,
-        'dry_run': True,
-        'object': 'trunk_interface',
-        'verb': 'deploy',
-        'subscription': _SUBSCRIPTION_OBJECT
+        "callback": TEST_CALLBACK_URL,
+        "dry_run": True,
+        "object": "trunk_interface",
+        "verb": "deploy",
+        "subscription": _SUBSCRIPTION_OBJECT,
     }
 
-    with patch('lso.playbook.ansible_runner.run',
-               new=test_ansible_runner_run) as _run:
-        rv = client.post('/api/ip_trunk/', json=params)
+    with patch("lso.playbook.ansible_runner.run", new=test_ansible_runner_run) as _run:
+        rv = client.post("/api/ip_trunk/", json=params)
         assert rv.status_code == 200
         response = rv.json()
         # wait a second for the run thread to finish
@@ -121,7 +112,7 @@ def test_ip_trunk_provisioning(client):
     jsonschema.validate(response, PlaybookLaunchResponse.schema())
     responses.assert_call_count(TEST_CALLBACK_URL, 1)
 
-    assert response['status'] == 'ok'
+    assert response["status"] == "ok"
 
 
 @responses.activate
@@ -129,16 +120,15 @@ def test_ip_trunk_modification(client):
     responses.put(url=TEST_CALLBACK_URL, status=204)
 
     params = {
-        'callback': TEST_CALLBACK_URL,
-        'dry_run': True,
-        'verb': 'modify',
-        'subscription': _SUBSCRIPTION_OBJECT,
-        'old_subscription': _SUBSCRIPTION_OBJECT
+        "callback": TEST_CALLBACK_URL,
+        "dry_run": True,
+        "verb": "modify",
+        "subscription": _SUBSCRIPTION_OBJECT,
+        "old_subscription": _SUBSCRIPTION_OBJECT,
     }
 
-    with patch('lso.playbook.ansible_runner.run',
-               new=test_ansible_runner_run) as _run:
-        rv = client.put('/api/ip_trunk/', json=params)
+    with patch("lso.playbook.ansible_runner.run", new=test_ansible_runner_run) as _run:
+        rv = client.put("/api/ip_trunk/", json=params)
         assert rv.status_code == 200
         response = rv.json()
         # wait a second for the run thread to finish
@@ -147,25 +137,17 @@ def test_ip_trunk_modification(client):
     jsonschema.validate(response, PlaybookLaunchResponse.schema())
     responses.assert_call_count(TEST_CALLBACK_URL, 1)
 
-    assert response['status'] == 'ok'
+    assert response["status"] == "ok"
 
 
 @responses.activate
 def test_ip_trunk_modification(client):
     responses.put(url=TEST_CALLBACK_URL, status=204)
 
-    params = {
-        'callback': TEST_CALLBACK_URL,
-        'dry_run': True,
-        'verb': 'terminate',
-        'subscription': _SUBSCRIPTION_OBJECT
-    }
+    params = {"callback": TEST_CALLBACK_URL, "dry_run": True, "verb": "terminate", "subscription": _SUBSCRIPTION_OBJECT}
 
-    with patch('lso.playbook.ansible_runner.run',
-               new=test_ansible_runner_run) as _run:
-        rv = client.request(url='/api/ip_trunk/',
-                            method=responses.DELETE,
-                            json=params)
+    with patch("lso.playbook.ansible_runner.run", new=test_ansible_runner_run) as _run:
+        rv = client.request(url="/api/ip_trunk/", method=responses.DELETE, json=params)
         assert rv.status_code == 200
         response = rv.json()
         # wait a second for the run thread to finish
@@ -174,4 +156,4 @@ def test_ip_trunk_modification(client):
     jsonschema.validate(response, PlaybookLaunchResponse.schema())
     responses.assert_call_count(TEST_CALLBACK_URL, 1)
 
-    assert response['status'] == 'ok'
+    assert response["status"] == "ok"
diff --git a/test/test_config.py b/test/test_config.py
index 9f9a2424b19f38dd381572cab2613c5aa45be29b..0322560b466f2d7412bacce8cdf2f5f1e911b604 100644
--- a/test/test_config.py
+++ b/test/test_config.py
@@ -16,16 +16,14 @@ def test_validate_testenv_config(config_file):
 
     :param config_file: Configuration file pytest fixture
     """
-    os.environ['SETTINGS_FILENAME'] = config_file
+    os.environ["SETTINGS_FILENAME"] = config_file
     params = config.load()
     assert params
 
 
-@pytest.mark.parametrize('bad_config', [
-    {'name': 'bad version', 'version': 123},
-    {'name': 'missing version'},
-    {'version': 'missing name'}
-])
+@pytest.mark.parametrize(
+    "bad_config", [{"name": "bad version", "version": 123}, {"name": "missing version"}, {"version": "missing name"}]
+)
 def test_bad_config(bad_config):
     with io.StringIO(json.dumps(bad_config)) as file:
         file.seek(0)  # rewind file position to the beginning