Loading deploy/kafka.sh +2 −1 Original line number Diff line number Diff line Loading @@ -61,7 +61,8 @@ function kfk_deploy_single() { else echo ">>> Deploy Kafka" cp "${KFK_MANIFESTS_PATH}/single-node.yaml" "${TMP_MANIFESTS_FOLDER}/kfk_single_node.yaml" #sed -i "s/<KFK_NAMESPACE>/${KFK_NAMESPACE}/" "${TMP_MANIFESTS_FOLDER}/kfk_single_node.yaml" # Set the correct advertised listeners based on the namespace sed -i "s|kafka-public\.kafka\.svc\.cluster\.local|kafka-public.${KFK_NAMESPACE}.svc.cluster.local|g" "${TMP_MANIFESTS_FOLDER}/kfk_single_node.yaml" kubectl --namespace ${KFK_NAMESPACE} apply -f "${TMP_MANIFESTS_FOLDER}/kfk_single_node.yaml" echo ">>> Waiting Kafka statefulset to be created..." Loading src/common/tools/kafka/Variables.py +3 −8 Original line number Diff line number Diff line Loading @@ -38,6 +38,8 @@ class KafkaConfig(Enum): KFK_NAMESPACE = get_setting('KFK_NAMESPACE', default='kafka') KFK_PORT = get_setting('KFK_SERVER_PORT', default='9092') kafka_server_address = KFK_SERVER_ADDRESS_TEMPLATE.format(KFK_NAMESPACE, KFK_PORT) LOGGER.debug('KFK_SERVER_ADDRESS not set, using default: {:s}'.format(kafka_server_address)) LOGGER.debug('Using KFK_SERVER_ADDRESS={:s}'.format(kafka_server_address)) return kafka_server_address @staticmethod Loading Loading @@ -139,10 +141,3 @@ class KafkaTopic(Enum): else: LOGGER.debug('All topics created and available.') return True if __name__ == '__main__': import os if 'KFK_SERVER_ADDRESS' not in os.environ: os.environ['KFK_SERVER_ADDRESS'] = 'kafka-service.kafka.svc.cluster.local:9092' KafkaTopic.create_all_topics() src/context/Dockerfile +1 −1 Original line number Diff line number Diff line Loading @@ -35,7 +35,7 @@ RUN python3 -m pip install --upgrade 'pip-tools==7.3.0' # Get common Python packages # Note: this step enables sharing the previous Docker build steps among all the Python components WORKDIR /var/teraflow COPY common_requirements_py313.in common_requirements.in COPY common_requirements.in common_requirements.in RUN pip-compile --quiet --output-file=common_requirements.txt common_requirements.in RUN python3 -m pip install -r common_requirements.txt Loading src/tests/Fixtures.py +129 −0 Original line number Diff line number Diff line Loading @@ -12,14 +12,143 @@ # See the License for the specific language governing permissions and # limitations under the License. import os import pytest from typing import Optional, Tuple from context.client.ContextClient import ContextClient from device.client.DeviceClient import DeviceClient from monitoring.client.MonitoringClient import MonitoringClient from e2e_orchestrator.client.E2EOrchestratorClient import E2EOrchestratorClient from service.client.ServiceClient import ServiceClient from vnt_manager.client.VNTManagerClient import VNTManagerClient # Service endpoints from kubectl get services -A # These are ClusterIP addresses - update if services are redeployed SERVICE_ENDPOINTS = { 'opt': { 'context': ('10.152.183.189', 1010), 'device': ('10.152.183.92', 2020), 'service': ('10.152.183.198', 3030), }, 'ip': { 'context': ('10.152.183.79', 1010), 'device': ('10.152.183.112', 2020), 'service': ('10.152.183.174', 3030), 'vnt_manager': ('10.152.183.23', 10080), }, 'e2e': { 'context': ('10.152.183.81', 1010), 'device': ('10.152.183.169', 2020), 'service': ('10.152.183.177', 3030), 'e2e_orchestrator': ('10.152.183.201', 10050), } } def _get_endpoint(layer: str, service_name: str) -> Tuple[str, int]: """Get service endpoint from environment variable or default mapping.""" env_host = os.getenv(f'TFS_{layer.upper()}_{service_name.upper()}_HOST') env_port = os.getenv(f'TFS_{layer.upper()}_{service_name.upper()}_PORT') if env_host and env_port: return (env_host, int(env_port)) endpoint = SERVICE_ENDPOINTS.get(layer, {}).get(service_name) if endpoint is None: raise ValueError(f"No endpoint found for layer='{layer}', service='{service_name}'") return endpoint # ========== Optical Layer Fixtures ========== @pytest.fixture(scope='session') def context_client_opt(): host, port = _get_endpoint('opt', 'context') _client = ContextClient(host=host, port=port) yield _client _client.close() @pytest.fixture(scope='session') def device_client_opt(): host, port = _get_endpoint('opt', 'device') _client = DeviceClient(host=host, port=port) yield _client _client.close() @pytest.fixture(scope='session') def service_client_opt(): host, port = _get_endpoint('opt', 'service') _client = ServiceClient(host=host, port=port) yield _client _client.close() # ========== IP Layer Fixtures ========== @pytest.fixture(scope='session') def context_client_ip(): host, port = _get_endpoint('ip', 'context') _client = ContextClient(host=host, port=port) yield _client _client.close() @pytest.fixture(scope='session') def device_client_ip(): host, port = _get_endpoint('ip', 'device') _client = DeviceClient(host=host, port=port) yield _client _client.close() @pytest.fixture(scope='session') def service_client_ip(): host, port = _get_endpoint('ip', 'service') _client = ServiceClient(host=host, port=port) yield _client _client.close() @pytest.fixture(scope='session') def vnt_manager_client_ip(): host, port = _get_endpoint('ip', 'vnt_manager') _client = VNTManagerClient(host=host, port=port) yield _client _client.close() # ========== E2E Layer Fixtures ========== @pytest.fixture(scope='session') def context_client_e2e(): host, port = _get_endpoint('e2e', 'context') _client = ContextClient(host=host, port=port) yield _client _client.close() @pytest.fixture(scope='session') def device_client_e2e(): host, port = _get_endpoint('e2e', 'device') _client = DeviceClient(host=host, port=port) yield _client _client.close() @pytest.fixture(scope='session') def service_client_e2e(): host, port = _get_endpoint('e2e', 'service') _client = ServiceClient(host=host, port=port) yield _client _client.close() @pytest.fixture(scope='session') def e2eorchestrator_client_e2e(): host, port = _get_endpoint('e2e', 'e2e_orchestrator') _client = E2EOrchestratorClient(host=host, port=port) yield _client _client.close() # ========== Legacy Fixtures (for backward compatibility) ========== # These use environment variables from tfs_runtime_env_vars.sh @pytest.fixture(scope='session') def service_client(): _client = ServiceClient() Loading src/tests/ofc25/Dockerfile +42 −9 Original line number Diff line number Diff line Loading @@ -25,13 +25,13 @@ ENV PYTHONUNBUFFERED=0 # Get generic Python packages RUN python3 -m pip install --upgrade 'pip==25.2' RUN python3 -m pip install --upgrade 'setuptools==79.0.0' 'wheel==0.45.1' RUN python3 -m pip install --upgrade 'pip-tools==7.3.0's==7.3.0' RUN python3 -m pip install --upgrade 'pip-tools==7.3.0' # Get common Python packages # Note: this step enables sharing the previous Docker build steps among all the Python components WORKDIR /var/teraflow COPY common_requirements.in common_requirements.in RUN pip-compile --quiet --output-file=common_requirements.txt common_requirements.in RUN pip-compile --resolver=backtracking --quiet --output-file=common_requirements.txt common_requirements.in RUN python3 -m pip install -r common_requirements.txt # Add common files into working directory Loading @@ -51,8 +51,27 @@ RUN find . -type f -exec sed -i -E 's/^(import\ .*)_pb2/from . \1_pb2/g' {} \; # Create component sub-folders, get specific Python packages RUN mkdir -p /var/teraflow/tests/ofc25 WORKDIR /var/teraflow/tests/ofc25 COPY src/tests/ofc25/requirements.in requirements.in RUN pip-compile --quiet --output-file=requirements.txt requirements.in # Copy all component requirements COPY src/context/requirements.in context_requirements.in COPY src/device/requirements.in device_requirements.in COPY src/monitoring/requirements.in monitoring_requirements.in COPY src/e2e_orchestrator/requirements.in e2e_orchestrator_requirements.in COPY src/service/requirements.in service_requirements.in COPY src/slice/requirements.in slice_requirements.in COPY src/vnt_manager/requirements.in vnt_manager_requirements.in # Compile all requirements together to avoid conflicts RUN pip-compile --quiet --output-file=requirements.txt \ context_requirements.in \ device_requirements.in \ monitoring_requirements.in \ e2e_orchestrator_requirements.in \ service_requirements.in \ slice_requirements.in \ vnt_manager_requirements.in # Install all requirements RUN python3 -m pip install -r requirements.txt # Add component files into working directory Loading @@ -77,18 +96,32 @@ COPY src/vnt_manager/__init__.py vnt_manager/__init__.py COPY src/vnt_manager/client/. vnt_manager/client/ COPY src/tests/*.py ./tests/ COPY src/tests/ofc25/__init__.py ./tests/ofc25/__init__.py COPY src/tests/ofc25/descriptors/descriptor_ip.json ./tests/ofc25/descriptors/descriptor_ip.json COPY src/tests/ofc25/descriptors/descriptor_opt.json ./tests/ofc25/descriptors/descriptor_opt.json COPY src/tests/ofc25/descriptors/descriptor_e2e.json ./tests/ofc25/descriptors/descriptor_e2e.json COPY src/tests/ofc25/descriptors/topology_ip.json ./tests/ofc25/descriptors/topology_ip.json COPY src/tests/ofc25/descriptors/topology_opt.json ./tests/ofc25/descriptors/topology_opt.json COPY src/tests/ofc25/descriptors/topology_e2e-netorch.json ./tests/ofc25/descriptors/topology_e2e.json COPY src/tests/ofc25/tests/. ./tests/ofc25/tests/ # Copy runtime environment variables (generated by deploy/tfs.sh) COPY tfs_runtime_env_vars_opt.sh ./tfs_runtime_env_vars_opt.sh COPY tfs_runtime_env_vars_ip.sh ./tfs_runtime_env_vars_ip.sh COPY tfs_runtime_env_vars_e2e.sh ./tfs_runtime_env_vars_e2e.sh RUN tee ./run_tests.sh <<EOF !/bin/bash source /var/teraflow/tfs_runtime_env_vars.sh #!/bin/bash set -e export PYTHONPATH=/var/teraflow # Test optical layer source /var/teraflow/tfs_runtime_env_vars_opt.sh pytest --verbose --log-level=INFO /var/teraflow/tests/ofc25/tests/test_functional_bootstrap_opt.py --junitxml=/opt/results/report_bootstrap_opt.xml # Test IP layer source /var/teraflow/tfs_runtime_env_vars_ip.sh pytest --verbose --log-level=INFO /var/teraflow/tests/ofc25/tests/test_functional_bootstrap_ip.py --junitxml=/opt/results/report_bootstrap_ip.xml # Test E2E orchestration sleep 5 source /var/teraflow/tfs_runtime_env_vars_e2e.sh pytest --verbose --log-level=INFO /var/teraflow/tests/ofc25/tests/test_functional_bootstrap_e2e.py --junitxml=/opt/results/report_bootstrap_e2e.xml pytest --verbose --log-level=INFO /var/teraflow/tests/ofc25/tests/test_functional_create_service.py --junitxml=/opt/results/report_create_service.xml pytest --verbose --log-level=INFO /var/teraflow/tests/ofc25/tests/test_functional_delete_service.py --junitxml=/opt/results/report_delete_service.xml Loading Loading
deploy/kafka.sh +2 −1 Original line number Diff line number Diff line Loading @@ -61,7 +61,8 @@ function kfk_deploy_single() { else echo ">>> Deploy Kafka" cp "${KFK_MANIFESTS_PATH}/single-node.yaml" "${TMP_MANIFESTS_FOLDER}/kfk_single_node.yaml" #sed -i "s/<KFK_NAMESPACE>/${KFK_NAMESPACE}/" "${TMP_MANIFESTS_FOLDER}/kfk_single_node.yaml" # Set the correct advertised listeners based on the namespace sed -i "s|kafka-public\.kafka\.svc\.cluster\.local|kafka-public.${KFK_NAMESPACE}.svc.cluster.local|g" "${TMP_MANIFESTS_FOLDER}/kfk_single_node.yaml" kubectl --namespace ${KFK_NAMESPACE} apply -f "${TMP_MANIFESTS_FOLDER}/kfk_single_node.yaml" echo ">>> Waiting Kafka statefulset to be created..." Loading
src/common/tools/kafka/Variables.py +3 −8 Original line number Diff line number Diff line Loading @@ -38,6 +38,8 @@ class KafkaConfig(Enum): KFK_NAMESPACE = get_setting('KFK_NAMESPACE', default='kafka') KFK_PORT = get_setting('KFK_SERVER_PORT', default='9092') kafka_server_address = KFK_SERVER_ADDRESS_TEMPLATE.format(KFK_NAMESPACE, KFK_PORT) LOGGER.debug('KFK_SERVER_ADDRESS not set, using default: {:s}'.format(kafka_server_address)) LOGGER.debug('Using KFK_SERVER_ADDRESS={:s}'.format(kafka_server_address)) return kafka_server_address @staticmethod Loading Loading @@ -139,10 +141,3 @@ class KafkaTopic(Enum): else: LOGGER.debug('All topics created and available.') return True if __name__ == '__main__': import os if 'KFK_SERVER_ADDRESS' not in os.environ: os.environ['KFK_SERVER_ADDRESS'] = 'kafka-service.kafka.svc.cluster.local:9092' KafkaTopic.create_all_topics()
src/context/Dockerfile +1 −1 Original line number Diff line number Diff line Loading @@ -35,7 +35,7 @@ RUN python3 -m pip install --upgrade 'pip-tools==7.3.0' # Get common Python packages # Note: this step enables sharing the previous Docker build steps among all the Python components WORKDIR /var/teraflow COPY common_requirements_py313.in common_requirements.in COPY common_requirements.in common_requirements.in RUN pip-compile --quiet --output-file=common_requirements.txt common_requirements.in RUN python3 -m pip install -r common_requirements.txt Loading
src/tests/Fixtures.py +129 −0 Original line number Diff line number Diff line Loading @@ -12,14 +12,143 @@ # See the License for the specific language governing permissions and # limitations under the License. import os import pytest from typing import Optional, Tuple from context.client.ContextClient import ContextClient from device.client.DeviceClient import DeviceClient from monitoring.client.MonitoringClient import MonitoringClient from e2e_orchestrator.client.E2EOrchestratorClient import E2EOrchestratorClient from service.client.ServiceClient import ServiceClient from vnt_manager.client.VNTManagerClient import VNTManagerClient # Service endpoints from kubectl get services -A # These are ClusterIP addresses - update if services are redeployed SERVICE_ENDPOINTS = { 'opt': { 'context': ('10.152.183.189', 1010), 'device': ('10.152.183.92', 2020), 'service': ('10.152.183.198', 3030), }, 'ip': { 'context': ('10.152.183.79', 1010), 'device': ('10.152.183.112', 2020), 'service': ('10.152.183.174', 3030), 'vnt_manager': ('10.152.183.23', 10080), }, 'e2e': { 'context': ('10.152.183.81', 1010), 'device': ('10.152.183.169', 2020), 'service': ('10.152.183.177', 3030), 'e2e_orchestrator': ('10.152.183.201', 10050), } } def _get_endpoint(layer: str, service_name: str) -> Tuple[str, int]: """Get service endpoint from environment variable or default mapping.""" env_host = os.getenv(f'TFS_{layer.upper()}_{service_name.upper()}_HOST') env_port = os.getenv(f'TFS_{layer.upper()}_{service_name.upper()}_PORT') if env_host and env_port: return (env_host, int(env_port)) endpoint = SERVICE_ENDPOINTS.get(layer, {}).get(service_name) if endpoint is None: raise ValueError(f"No endpoint found for layer='{layer}', service='{service_name}'") return endpoint # ========== Optical Layer Fixtures ========== @pytest.fixture(scope='session') def context_client_opt(): host, port = _get_endpoint('opt', 'context') _client = ContextClient(host=host, port=port) yield _client _client.close() @pytest.fixture(scope='session') def device_client_opt(): host, port = _get_endpoint('opt', 'device') _client = DeviceClient(host=host, port=port) yield _client _client.close() @pytest.fixture(scope='session') def service_client_opt(): host, port = _get_endpoint('opt', 'service') _client = ServiceClient(host=host, port=port) yield _client _client.close() # ========== IP Layer Fixtures ========== @pytest.fixture(scope='session') def context_client_ip(): host, port = _get_endpoint('ip', 'context') _client = ContextClient(host=host, port=port) yield _client _client.close() @pytest.fixture(scope='session') def device_client_ip(): host, port = _get_endpoint('ip', 'device') _client = DeviceClient(host=host, port=port) yield _client _client.close() @pytest.fixture(scope='session') def service_client_ip(): host, port = _get_endpoint('ip', 'service') _client = ServiceClient(host=host, port=port) yield _client _client.close() @pytest.fixture(scope='session') def vnt_manager_client_ip(): host, port = _get_endpoint('ip', 'vnt_manager') _client = VNTManagerClient(host=host, port=port) yield _client _client.close() # ========== E2E Layer Fixtures ========== @pytest.fixture(scope='session') def context_client_e2e(): host, port = _get_endpoint('e2e', 'context') _client = ContextClient(host=host, port=port) yield _client _client.close() @pytest.fixture(scope='session') def device_client_e2e(): host, port = _get_endpoint('e2e', 'device') _client = DeviceClient(host=host, port=port) yield _client _client.close() @pytest.fixture(scope='session') def service_client_e2e(): host, port = _get_endpoint('e2e', 'service') _client = ServiceClient(host=host, port=port) yield _client _client.close() @pytest.fixture(scope='session') def e2eorchestrator_client_e2e(): host, port = _get_endpoint('e2e', 'e2e_orchestrator') _client = E2EOrchestratorClient(host=host, port=port) yield _client _client.close() # ========== Legacy Fixtures (for backward compatibility) ========== # These use environment variables from tfs_runtime_env_vars.sh @pytest.fixture(scope='session') def service_client(): _client = ServiceClient() Loading
src/tests/ofc25/Dockerfile +42 −9 Original line number Diff line number Diff line Loading @@ -25,13 +25,13 @@ ENV PYTHONUNBUFFERED=0 # Get generic Python packages RUN python3 -m pip install --upgrade 'pip==25.2' RUN python3 -m pip install --upgrade 'setuptools==79.0.0' 'wheel==0.45.1' RUN python3 -m pip install --upgrade 'pip-tools==7.3.0's==7.3.0' RUN python3 -m pip install --upgrade 'pip-tools==7.3.0' # Get common Python packages # Note: this step enables sharing the previous Docker build steps among all the Python components WORKDIR /var/teraflow COPY common_requirements.in common_requirements.in RUN pip-compile --quiet --output-file=common_requirements.txt common_requirements.in RUN pip-compile --resolver=backtracking --quiet --output-file=common_requirements.txt common_requirements.in RUN python3 -m pip install -r common_requirements.txt # Add common files into working directory Loading @@ -51,8 +51,27 @@ RUN find . -type f -exec sed -i -E 's/^(import\ .*)_pb2/from . \1_pb2/g' {} \; # Create component sub-folders, get specific Python packages RUN mkdir -p /var/teraflow/tests/ofc25 WORKDIR /var/teraflow/tests/ofc25 COPY src/tests/ofc25/requirements.in requirements.in RUN pip-compile --quiet --output-file=requirements.txt requirements.in # Copy all component requirements COPY src/context/requirements.in context_requirements.in COPY src/device/requirements.in device_requirements.in COPY src/monitoring/requirements.in monitoring_requirements.in COPY src/e2e_orchestrator/requirements.in e2e_orchestrator_requirements.in COPY src/service/requirements.in service_requirements.in COPY src/slice/requirements.in slice_requirements.in COPY src/vnt_manager/requirements.in vnt_manager_requirements.in # Compile all requirements together to avoid conflicts RUN pip-compile --quiet --output-file=requirements.txt \ context_requirements.in \ device_requirements.in \ monitoring_requirements.in \ e2e_orchestrator_requirements.in \ service_requirements.in \ slice_requirements.in \ vnt_manager_requirements.in # Install all requirements RUN python3 -m pip install -r requirements.txt # Add component files into working directory Loading @@ -77,18 +96,32 @@ COPY src/vnt_manager/__init__.py vnt_manager/__init__.py COPY src/vnt_manager/client/. vnt_manager/client/ COPY src/tests/*.py ./tests/ COPY src/tests/ofc25/__init__.py ./tests/ofc25/__init__.py COPY src/tests/ofc25/descriptors/descriptor_ip.json ./tests/ofc25/descriptors/descriptor_ip.json COPY src/tests/ofc25/descriptors/descriptor_opt.json ./tests/ofc25/descriptors/descriptor_opt.json COPY src/tests/ofc25/descriptors/descriptor_e2e.json ./tests/ofc25/descriptors/descriptor_e2e.json COPY src/tests/ofc25/descriptors/topology_ip.json ./tests/ofc25/descriptors/topology_ip.json COPY src/tests/ofc25/descriptors/topology_opt.json ./tests/ofc25/descriptors/topology_opt.json COPY src/tests/ofc25/descriptors/topology_e2e-netorch.json ./tests/ofc25/descriptors/topology_e2e.json COPY src/tests/ofc25/tests/. ./tests/ofc25/tests/ # Copy runtime environment variables (generated by deploy/tfs.sh) COPY tfs_runtime_env_vars_opt.sh ./tfs_runtime_env_vars_opt.sh COPY tfs_runtime_env_vars_ip.sh ./tfs_runtime_env_vars_ip.sh COPY tfs_runtime_env_vars_e2e.sh ./tfs_runtime_env_vars_e2e.sh RUN tee ./run_tests.sh <<EOF !/bin/bash source /var/teraflow/tfs_runtime_env_vars.sh #!/bin/bash set -e export PYTHONPATH=/var/teraflow # Test optical layer source /var/teraflow/tfs_runtime_env_vars_opt.sh pytest --verbose --log-level=INFO /var/teraflow/tests/ofc25/tests/test_functional_bootstrap_opt.py --junitxml=/opt/results/report_bootstrap_opt.xml # Test IP layer source /var/teraflow/tfs_runtime_env_vars_ip.sh pytest --verbose --log-level=INFO /var/teraflow/tests/ofc25/tests/test_functional_bootstrap_ip.py --junitxml=/opt/results/report_bootstrap_ip.xml # Test E2E orchestration sleep 5 source /var/teraflow/tfs_runtime_env_vars_e2e.sh pytest --verbose --log-level=INFO /var/teraflow/tests/ofc25/tests/test_functional_bootstrap_e2e.py --junitxml=/opt/results/report_bootstrap_e2e.xml pytest --verbose --log-level=INFO /var/teraflow/tests/ofc25/tests/test_functional_create_service.py --junitxml=/opt/results/report_create_service.xml pytest --verbose --log-level=INFO /var/teraflow/tests/ofc25/tests/test_functional_delete_service.py --junitxml=/opt/results/report_delete_service.xml Loading