|
| 1 | +"""Tests for Nebius automatic subnet resolution.""" |
| 2 | + |
| 3 | +from __future__ import annotations |
| 4 | + |
| 5 | +from unittest.mock import MagicMock |
| 6 | + |
| 7 | +import pytest |
| 8 | + |
| 9 | +from transformerlab.compute_providers.models import ClusterConfig |
| 10 | +from transformerlab.compute_providers.nebius import NEBIUS_AUTO_SUBNET_NAME, NebiusProvider |
| 11 | + |
| 12 | + |
| 13 | +def test_resolve_subnet_uses_configured_id() -> None: |
| 14 | + p = NebiusProvider(team_id="t1", parent_id="proj", subnet_id="subnet-fixed") |
| 15 | + assert p._resolve_subnet_id_for_launch() == "subnet-fixed" |
| 16 | + |
| 17 | + |
| 18 | +def test_resolve_subnet_reuses_existing_list() -> None: |
| 19 | + p = NebiusProvider(team_id="t1", parent_id="proj-a", subnet_id=None) |
| 20 | + p._run_nebius = MagicMock(return_value={"subnets": [{"metadata": {"id": "sn-1", "name": "s1"}}]}) |
| 21 | + assert p._resolve_subnet_id_for_launch() == "sn-1" |
| 22 | + p._run_nebius.assert_called_once() |
| 23 | + assert p._resolved_subnet_id == "sn-1" |
| 24 | + |
| 25 | + |
| 26 | +def test_resolve_subnet_creates_network_then_subnet() -> None: |
| 27 | + p = NebiusProvider(team_id="t1", parent_id="proj-b", subnet_id=None) |
| 28 | + subnet_list_returns: list = [[], []] |
| 29 | + |
| 30 | + def fake_run(args: list, stdin_json=None, timeout=120): |
| 31 | + joined = " ".join(args) |
| 32 | + if "subnet list" in joined: |
| 33 | + return {"subnets": subnet_list_returns.pop(0)} |
| 34 | + if "network list" in joined: |
| 35 | + return {"networks": []} |
| 36 | + if "create-default" in joined: |
| 37 | + return {"metadata": {"id": "net-new"}} |
| 38 | + if "subnet create" in joined: |
| 39 | + return {"metadata": {"id": "sn-created"}} |
| 40 | + raise AssertionError(f"unexpected nebius call: {joined}") |
| 41 | + |
| 42 | + p._run_nebius = MagicMock(side_effect=fake_run) |
| 43 | + assert p._resolve_subnet_id_for_launch() == "sn-created" |
| 44 | + create_calls = [c for c in p._run_nebius.call_args_list if "subnet create" in " ".join(c[0][0])] |
| 45 | + assert len(create_calls) == 1 |
| 46 | + create_args = create_calls[0][0][0] |
| 47 | + assert NEBIUS_AUTO_SUBNET_NAME in create_args |
| 48 | + |
| 49 | + |
| 50 | +def test_resolve_subnet_requires_parent_when_no_subnet() -> None: |
| 51 | + p = NebiusProvider(team_id="t1", parent_id=None, subnet_id=None) |
| 52 | + with pytest.raises(ValueError, match="parent_id"): |
| 53 | + p._resolve_subnet_id_for_launch() |
| 54 | + |
| 55 | + |
| 56 | +def test_cloud_init_includes_self_termination_trap() -> None: |
| 57 | + p = NebiusProvider(team_id="t1") |
| 58 | + user_data = p._build_cloud_init("cluster-a", ClusterConfig(run="echo hello"), public_key="ssh-ed25519 AAAATEST") |
| 59 | + assert "_tfl_self_terminate" in user_data |
| 60 | + assert "trap _tfl_self_terminate EXIT" in user_data |
| 61 | + |
| 62 | + |
| 63 | +def test_cloud_init_self_termination_fallbacks() -> None: |
| 64 | + p = NebiusProvider(team_id="t1") |
| 65 | + user_data = p._build_cloud_init("cluster-a", ClusterConfig(run="echo hello"), public_key="ssh-ed25519 AAAATEST") |
| 66 | + assert "_tfl_self_delete_instance" in user_data |
| 67 | + assert "_tfl_ensure_nebius_cli" in user_data |
| 68 | + assert "https://storage.eu-north1.nebius.cloud/cli/install.sh | bash" in user_data |
| 69 | + assert 'export PATH="$HOME/.nebius/bin:$PATH"' in user_data |
| 70 | + assert 'nebius compute instance delete --id "$_iid" --async' in user_data |
| 71 | + assert "shutdown -h now || poweroff || true" in user_data |
0 commit comments