Skip to content
Snippets Groups Projects
Commit ac11f41a authored by geant-release-service's avatar geant-release-service
Browse files

Finished release 2.47.

parents aa51ad9a 0be5536b
No related branches found
No related tags found
No related merge requests found
Pipeline #93351 passed
# Changelog
## [2.47] - 2025-04-15
- Make generation of new virtual circuit ID optional in layer 2 circuit migration workflow
- Add REST API endpoint for getting the list of available versions
## [2.46] - 2025-04-08
- Integrated a new l2circuit migration workflow within the database.
- Enhancements to Layer 2 Circuit Workflows
- Fixed a bug in the prefix list validation logic when an FQDN list is unexpectedly empty.
- Code Improvements and Utility Updates
- Added SDP steps to the test_terminate_router to ensure proper execution.
- Reworked SDP functions within workflow_steps for improved process clarity.
- Integrated additional SDP steps in the terminate_router process.
- Adjusted SDP steps in the promote_p_to_pe workflow.
- Updated SDP steps within the update_ibgp_mesh workflow.
## [2.45] - 2025-04-02
- Add email notifications to Kentik-related steps in workflows.
- Improve Kentik license handling in Router termination workflow.
......
......@@ -4,8 +4,10 @@ from fastapi import APIRouter
from gso.api.v1.network import router as network_router
from gso.api.v1.subscriptions import router as subscriptions_router
from gso.api.v1.version import router as version_router
router = APIRouter()
router.include_router(subscriptions_router)
router.include_router(network_router)
router.include_router(version_router)
"""API for getting the version of the orchestrator."""
from fastapi import APIRouter
from orchestrator.graphql.resolvers.version import VERSIONS
from starlette import status
router = APIRouter(prefix="/version", tags=["Version"])
@router.get("/", status_code=status.HTTP_200_OK)
def version() -> dict[str, str]:
"""Get the version of deployed services."""
version_dict = {}
for item in VERSIONS:
if ":" in item:
key, value = item.split(":", 1)
version_dict[key.strip()] = value.strip()
return version_dict
......@@ -87,6 +87,7 @@ def input_form_generator(subscription_id: UUIDstr) -> FormGenerator:
model_config = ConfigDict(title="Migrating Layer 2 Circuit")
new_edge_port: active_edge_port_selector(partner_id=replace_side_partner.partner_id) # type: ignore[valid-type]
generate_new_vc_id: bool = False
user_input = yield SelectNewEdgePortForm
......@@ -98,11 +99,17 @@ def input_form_generator(subscription_id: UUIDstr) -> FormGenerator:
"subscription_id": subscription_id,
"old_edge_port": initial_user_input.replace_side,
"new_edge_port": user_input.new_edge_port,
"generate_new_vc_id": user_input.generate_new_vc_id,
}
@step("Update subscription model")
def update_subscription_model(subscription: Layer2Circuit, old_edge_port: UUIDstr, new_edge_port: UUIDstr) -> State:
def update_subscription_model(
subscription: Layer2Circuit,
old_edge_port: UUIDstr,
new_edge_port: UUIDstr,
generate_new_vc_id: bool, # noqa: FBT001
) -> State:
"""Replace the old Edge Port with the newly selected one in the subscription model."""
replace_index = (
0
......@@ -114,12 +121,12 @@ def update_subscription_model(subscription: Layer2Circuit, old_edge_port: UUIDst
new_edge_port
).edge_port
vc_id = generate_unique_vc_id(l2c_type=subscription.layer_2_circuit.layer_2_circuit_type)
if not vc_id:
msg = "Failed to generate unique Virtual Circuit ID."
raise ProcessFailureError(msg)
subscription.layer_2_circuit.virtual_circuit_id = vc_id
if generate_new_vc_id:
vc_id = generate_unique_vc_id(l2c_type=subscription.layer_2_circuit.layer_2_circuit_type)
if not vc_id:
msg = "Failed to generate unique Virtual Circuit ID."
raise ProcessFailureError(msg)
subscription.layer_2_circuit.virtual_circuit_id = vc_id
return {"subscription": subscription}
......
......@@ -4,7 +4,7 @@ from setuptools import find_packages, setup
setup(
name="geant-service-orchestrator",
version="2.46",
version="2.47",
author="GÉANT Orchestration and Automation Team",
author_email="goat@geant.org",
description="GÉANT Service Orchestrator",
......
import os
from uuid import uuid4
LSO_RESULT_SUCCESS = {
......@@ -20,5 +19,3 @@ LSO_RESULT_FAILURE = {
}
USER_CONFIRM_EMPTY_FORM = [{}]
os.environ["TESTING"] = "true"
from importlib import metadata
def test_version_endpoint(test_client, monkeypatch):
"""
Test that the /version endpoint returns the correct versions:
"""
response = test_client.get("api/v1/version")
assert response.status_code == 200
data = response.json()
assert data == {
"GAP Ansible collection": "Unknown",
"GÉANT Service Orchestrator": metadata.version("geant-service-orchestrator"),
"GÉANT Service Orchestrator GUI": "Unknown",
"LSO": "Unknown",
"Moodi Ansible collection": "Unknown",
"orchestrator-core": "3.1.1",
}
......@@ -54,13 +54,16 @@ class UseJuniperSide(strEnum):
def pytest_configure(config):
"""Set an environment variable before loading any test modules."""
config_filename = "gso/oss-params-example.json"
os.environ["OSS_PARAMS_FILENAME"] = config_filename
# Set environment variables for the test session
os.environ["OSS_PARAMS_FILENAME"] = "gso/oss-params-example.json"
os.environ["TESTING"] = "true"
# Register finalizers to clean up after tests are done
def cleanup() -> None:
del os.environ["OSS_PARAMS_FILENAME"]
del os.environ["TESTING"]
def pytest_unconfigure(config):
"""Clean up the environment variable after all tests."""
os.environ.pop("OSS_PARAMS_FILENAME", None)
pytest.session_cleanup = cleanup
class FakerProvider(BaseProvider):
......
......@@ -12,9 +12,11 @@ from test.workflows import assert_complete, assert_lso_interaction_success, extr
@pytest.mark.parametrize("layer_2_circuit_service_type", LAYER_2_CIRCUIT_SERVICE_TYPES)
@pytest.mark.parametrize("run_old_side_ansible", [False, True])
@pytest.mark.parametrize("run_new_side_ansible", [False, True])
@pytest.mark.parametrize("generate_new_vc_id", [False, True])
@patch("gso.services.lso_client._send_request")
def test_migrate_layer_2_circuit(
mock_lso_interaction,
generate_new_vc_id,
run_new_side_ansible,
run_old_side_ansible,
layer_2_circuit_service_type,
......@@ -31,6 +33,7 @@ def test_migrate_layer_2_circuit(
)
new_edge_port = edge_port_subscription_factory(node=side_b_router.router)
old_vc_id = subscription.layer_2_circuit.virtual_circuit_id
initial_layer_2_circuit_data = [
{"subscription_id": subscription.subscription_id},
{
......@@ -40,7 +43,10 @@ def test_migrate_layer_2_circuit(
"run_old_side_ansible": run_old_side_ansible,
"run_new_side_ansible": run_new_side_ansible,
},
{"new_edge_port": new_edge_port.subscription_id},
{
"new_edge_port": new_edge_port.subscription_id,
"generate_new_vc_id": generate_new_vc_id,
},
]
result, process_stat, step_log = run_workflow("migrate_layer_2_circuit", initial_layer_2_circuit_data)
......@@ -70,3 +76,4 @@ def test_migrate_layer_2_circuit(
assert replaced_edge_port.edge_port_ae_members[1].model_dump(
exclude="owner_subscription_id"
) == new_edge_port.edge_port.edge_port_ae_members[1].model_dump(exclude="owner_subscription_id")
assert (old_vc_id == subscription.layer_2_circuit.virtual_circuit_id) is not generate_new_vc_id
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment