Commit 2a5bd9f1 authored by Lluis Gifre Renom's avatar Lluis Gifre Renom
Browse files

fix(demo): generate missing Python protobuf modules before deployment

parent c122cad7
Loading
Loading
Loading
Loading
+6 −5
Changes for proto/generate_code_python.sh: 6 added lines, 5 removed lines.
Original line number Diff line number Diff line
@@ -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
@@ -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' {} \;
+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
@@ -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
@@ -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).
+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
@@ -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)"
+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
@@ -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'
@@ -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",
@@ -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()