Loading proto/generate_code_python.sh +6 −5 Changes for proto/generate_code_python.sh: 6 added lines, 5 removed lines. Original line number Diff line number Diff line Loading @@ -14,9 +14,10 @@ # limitations under the License. # Make folder containing the script the root folder for its execution cd $(dirname $0) cd "$(dirname "$0")" PYTHON="${PYTHON:-python3}" mkdir -p src/python mkdir -p src/python/asyncio rm -rf src/python/*.py tee src/python/__init__.py << EOF > /dev/null Loading @@ -36,10 +37,10 @@ tee src/python/__init__.py << EOF > /dev/null EOF # Generate Python code python3 -m grpc_tools.protoc -I=./ --python_out=src/python/ --grpc_python_out=src/python/ *.proto "$PYTHON" -m grpc_tools.protoc -I=./ --python_out=src/python/ --grpc_python_out=src/python/ *.proto # new line added to generate protobuf for the `grpclib` library python3 -m grpc_tools.protoc -I=./ --python_out=src/python/asyncio --grpclib_python_out=src/python/asyncio *.proto "$PYTHON" -m grpc_tools.protoc -I=./ --python_out=src/python/asyncio --grpclib_python_out=src/python/asyncio *.proto # Arrange generated code imports to enable imports from arbitrary subpackages find src/python -type f -iname *.py -exec sed -i -E 's/^(import\ .*)_pb2/from . \1_pb2/g' {} \; find src/python -type f -iname '*.py' -exec sed -i -E 's/^(import\ .*)_pb2/from . \1_pb2/g' {} \; src/tests/ecoc26-hyr-agentic-optical/README.md +20 −1 Changes for src/tests/ecoc26-hyr-agentic-optical/README.md: 20 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -24,6 +24,25 @@ For example, on a machine with a prepared pyenv environment: pyenv shell tfs ``` On a fresh clone, protobuf sources in `proto/` have not yet been compiled for host-side Python tools. The launcher generates missing modules before any cleanup, using `DEMO_PYTHON` (default `python3`). That interpreter must have the TFS dependencies, including `grpcio-tools`, `grpclib`, and PyYAML. Container image builds do not prepare these host-side modules. To generate and check them manually from the repository root: ```bash PYTHON=python3 bash -eu proto/generate_code_python.sh PYTHONPATH="$PWD/src" python3 -c \ 'from tests.tools.load_scenario.__main__ import main; import yaml' ``` Use the Python environment compatible with the controller requirements; do not install arbitrary latest protobuf/gRPC versions into the system interpreter. The import-path variable is `PYTHONPATH`, not `PYTHON_PATH`. The launcher sets it for its preflight, so exporting it manually cannot fix missing generated files. After changing `.proto` sources, regenerate them with the command above. Internet access is required for container images and the configured LLM. Ports 80 and 32000 must be available for ingress and the local registry. The Docker management subnet `172.254.253.0/24` must not overlap another Loading Loading @@ -104,7 +123,7 @@ configuration. Prefer `redeploy-all.sh` for a completely fresh rehearsal. `deploy_specs.sh` contains the self-contained demo deployment settings; neither launcher sources `my_deploy.sh`. `DEMO_PYTHON` selects the Python executable (default `python`). `DEMO_PYTHON` selects the Python executable (default `python3`). `DEMO_WAIT_SECONDS` controls Kubernetes waits (default 600), including the upstream TFS component rollout through `TFS_ROLLOUT_TIMEOUT_SECONDS`, and `NODE_AGENT_WAIT_SECONDS` bounds node-agent initialization (default 300). Loading src/tests/ecoc26-hyr-agentic-optical/redeploy.sh +15 −2 Changes for src/tests/ecoc26-hyr-agentic-optical/redeploy.sh: 15 added lines, 2 removed lines. Original line number Diff line number Diff line Loading @@ -45,8 +45,21 @@ for CMD in docker microk8s kubectl helm3 jq timeout curl "$DEMO_PYTHON"; do done docker info >/dev/null # Validate dependencies and private configuration before deleting anything. PYTHONPATH="$REPO_ROOT/src" "$DEMO_PYTHON" -c \ 'from tests.tools.load_scenario.__main__ import main; import yaml' if [[ ! -f "$REPO_ROOT/src/common/proto/context_pb2.py" ]]; then echo "Generating missing TFS Python protobuf modules..." if ! "$DEMO_PYTHON" -c 'import grpc_tools.protoc; import grpclib'; then echo "Install TFS Python dependencies in the DEMO_PYTHON environment." >&2 echo "See the demo README prerequisites; no deployment was changed." >&2 exit 1 fi PYTHON="$DEMO_PYTHON" bash -eu proto/generate_code_python.sh fi if ! PYTHONPATH="$REPO_ROOT/src" "$DEMO_PYTHON" -c \ 'from tests.tools.load_scenario.__main__ import main; import yaml'; then echo "Scenario-loader preflight failed; no deployment was changed." >&2 echo "Check DEMO_PYTHON dependencies and generated protobuf modules." >&2 exit 1 fi "$DEMO_PYTHON" "$SCRIPT_DIR/prepare_agentic.py" --check echo "WARNING: this resets the local tfs namespace (including chat sessions)" Loading src/tests/ecoc26-hyr-agentic-optical/test_deployment.py +15 −0 Changes for src/tests/ecoc26-hyr-agentic-optical/test_deployment.py: 15 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -65,6 +65,11 @@ class DeploymentTests(unittest.TestCase): scenario.mkdir(parents=True) for script in SCRIPT_DIR.glob("*.sh"): shutil.copy(script, scenario) (root / "proto").mkdir() shutil.copy( SCRIPT_DIR.parents[2] / "proto/generate_code_python.sh", root / "proto", ) (root / "deploy").mkdir() (root / "deploy" / "all.sh").write_text( 'echo "core-deploy:$TFS_COMPONENTS" >> "$COMMAND_LOG"\n' Loading Loading @@ -115,6 +120,7 @@ esac result, log = self.run_launcher(["--yes"]) self.assertEqual(result.returncode, 0, result.stderr) stages = [ "fakepython -m grpc_tools.protoc", "docker rm -f na-t1", "docker pull", "docker run", Loading Loading @@ -156,6 +162,15 @@ esac self.assertNotEqual(result.returncode, 0) self.assertNotIn("docker rm", log) def test_missing_generator_dependencies_prevent_cleanup(self): result, log = self.run_launcher( ["--yes"], failure="import grpc_tools.protoc" ) self.assertNotEqual(result.returncode, 0) self.assertIn("Install TFS Python dependencies", result.stderr) self.assertNotIn("docker rm", log) self.assertNotIn("kubectl delete", log) if __name__ == "__main__": unittest.main() Loading
proto/generate_code_python.sh +6 −5 Changes for proto/generate_code_python.sh: 6 added lines, 5 removed lines. Original line number Diff line number Diff line Loading @@ -14,9 +14,10 @@ # limitations under the License. # Make folder containing the script the root folder for its execution cd $(dirname $0) cd "$(dirname "$0")" PYTHON="${PYTHON:-python3}" mkdir -p src/python mkdir -p src/python/asyncio rm -rf src/python/*.py tee src/python/__init__.py << EOF > /dev/null Loading @@ -36,10 +37,10 @@ tee src/python/__init__.py << EOF > /dev/null EOF # Generate Python code python3 -m grpc_tools.protoc -I=./ --python_out=src/python/ --grpc_python_out=src/python/ *.proto "$PYTHON" -m grpc_tools.protoc -I=./ --python_out=src/python/ --grpc_python_out=src/python/ *.proto # new line added to generate protobuf for the `grpclib` library python3 -m grpc_tools.protoc -I=./ --python_out=src/python/asyncio --grpclib_python_out=src/python/asyncio *.proto "$PYTHON" -m grpc_tools.protoc -I=./ --python_out=src/python/asyncio --grpclib_python_out=src/python/asyncio *.proto # Arrange generated code imports to enable imports from arbitrary subpackages find src/python -type f -iname *.py -exec sed -i -E 's/^(import\ .*)_pb2/from . \1_pb2/g' {} \; find src/python -type f -iname '*.py' -exec sed -i -E 's/^(import\ .*)_pb2/from . \1_pb2/g' {} \;
src/tests/ecoc26-hyr-agentic-optical/README.md +20 −1 Changes for src/tests/ecoc26-hyr-agentic-optical/README.md: 20 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -24,6 +24,25 @@ For example, on a machine with a prepared pyenv environment: pyenv shell tfs ``` On a fresh clone, protobuf sources in `proto/` have not yet been compiled for host-side Python tools. The launcher generates missing modules before any cleanup, using `DEMO_PYTHON` (default `python3`). That interpreter must have the TFS dependencies, including `grpcio-tools`, `grpclib`, and PyYAML. Container image builds do not prepare these host-side modules. To generate and check them manually from the repository root: ```bash PYTHON=python3 bash -eu proto/generate_code_python.sh PYTHONPATH="$PWD/src" python3 -c \ 'from tests.tools.load_scenario.__main__ import main; import yaml' ``` Use the Python environment compatible with the controller requirements; do not install arbitrary latest protobuf/gRPC versions into the system interpreter. The import-path variable is `PYTHONPATH`, not `PYTHON_PATH`. The launcher sets it for its preflight, so exporting it manually cannot fix missing generated files. After changing `.proto` sources, regenerate them with the command above. Internet access is required for container images and the configured LLM. Ports 80 and 32000 must be available for ingress and the local registry. The Docker management subnet `172.254.253.0/24` must not overlap another Loading Loading @@ -104,7 +123,7 @@ configuration. Prefer `redeploy-all.sh` for a completely fresh rehearsal. `deploy_specs.sh` contains the self-contained demo deployment settings; neither launcher sources `my_deploy.sh`. `DEMO_PYTHON` selects the Python executable (default `python`). `DEMO_PYTHON` selects the Python executable (default `python3`). `DEMO_WAIT_SECONDS` controls Kubernetes waits (default 600), including the upstream TFS component rollout through `TFS_ROLLOUT_TIMEOUT_SECONDS`, and `NODE_AGENT_WAIT_SECONDS` bounds node-agent initialization (default 300). Loading
src/tests/ecoc26-hyr-agentic-optical/redeploy.sh +15 −2 Changes for src/tests/ecoc26-hyr-agentic-optical/redeploy.sh: 15 added lines, 2 removed lines. Original line number Diff line number Diff line Loading @@ -45,8 +45,21 @@ for CMD in docker microk8s kubectl helm3 jq timeout curl "$DEMO_PYTHON"; do done docker info >/dev/null # Validate dependencies and private configuration before deleting anything. PYTHONPATH="$REPO_ROOT/src" "$DEMO_PYTHON" -c \ 'from tests.tools.load_scenario.__main__ import main; import yaml' if [[ ! -f "$REPO_ROOT/src/common/proto/context_pb2.py" ]]; then echo "Generating missing TFS Python protobuf modules..." if ! "$DEMO_PYTHON" -c 'import grpc_tools.protoc; import grpclib'; then echo "Install TFS Python dependencies in the DEMO_PYTHON environment." >&2 echo "See the demo README prerequisites; no deployment was changed." >&2 exit 1 fi PYTHON="$DEMO_PYTHON" bash -eu proto/generate_code_python.sh fi if ! PYTHONPATH="$REPO_ROOT/src" "$DEMO_PYTHON" -c \ 'from tests.tools.load_scenario.__main__ import main; import yaml'; then echo "Scenario-loader preflight failed; no deployment was changed." >&2 echo "Check DEMO_PYTHON dependencies and generated protobuf modules." >&2 exit 1 fi "$DEMO_PYTHON" "$SCRIPT_DIR/prepare_agentic.py" --check echo "WARNING: this resets the local tfs namespace (including chat sessions)" Loading
src/tests/ecoc26-hyr-agentic-optical/test_deployment.py +15 −0 Changes for src/tests/ecoc26-hyr-agentic-optical/test_deployment.py: 15 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -65,6 +65,11 @@ class DeploymentTests(unittest.TestCase): scenario.mkdir(parents=True) for script in SCRIPT_DIR.glob("*.sh"): shutil.copy(script, scenario) (root / "proto").mkdir() shutil.copy( SCRIPT_DIR.parents[2] / "proto/generate_code_python.sh", root / "proto", ) (root / "deploy").mkdir() (root / "deploy" / "all.sh").write_text( 'echo "core-deploy:$TFS_COMPONENTS" >> "$COMMAND_LOG"\n' Loading Loading @@ -115,6 +120,7 @@ esac result, log = self.run_launcher(["--yes"]) self.assertEqual(result.returncode, 0, result.stderr) stages = [ "fakepython -m grpc_tools.protoc", "docker rm -f na-t1", "docker pull", "docker run", Loading Loading @@ -156,6 +162,15 @@ esac self.assertNotEqual(result.returncode, 0) self.assertNotIn("docker rm", log) def test_missing_generator_dependencies_prevent_cleanup(self): result, log = self.run_launcher( ["--yes"], failure="import grpc_tools.protoc" ) self.assertNotEqual(result.returncode, 0) self.assertIn("Install TFS Python dependencies", result.stderr) self.assertNotIn("docker rm", log) self.assertNotIn("kubectl delete", log) if __name__ == "__main__": unittest.main()