Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,19 @@ def cli(namespace: str, fulfillment_address: str, service_account: str) -> Itera
instance.close()


@pytest.fixture(scope="session")
def private_cli(namespace: str, fulfillment_private_address: str, service_account: str) -> Iterator[OsacCLI]:
instance = OsacCLI(
binary=env("OSAC_CLI_PATH", "osac"),
address=f"https://{fulfillment_private_address.rsplit(':', 1)[0]}",
token_script=f"oc create token -n {namespace} {service_account} --as system:admin",
namespace=namespace,
private=True,
)
yield instance
instance.close()


@pytest.fixture(scope="session")
def keycloak_url(cluster_domain: str) -> str:
return env("OSAC_KEYCLOAK_URL", f"https://keycloak-keycloak.{cluster_domain}")
Expand Down
34 changes: 30 additions & 4 deletions tests/core/osac_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,22 @@ def __init__(
token_script: str,
namespace: str,
default_instance_type: str | None = None,
private: bool = False,
) -> None:
self.binary: str = binary
self.namespace: str = namespace
self._address: str = address
self._token_script: str = token_script
self._private: bool = private
self.default_instance_type: str | None = default_instance_type
# Each OsacCLI instance gets its own config directory so that parallel
# xdist workers (or multiple CLI fixtures) don't overwrite each other's
# login credentials via the shared ~/.config/osac/config.json.
self._config_dir: str = tempfile.mkdtemp(prefix="osac-config-")
self._run("login", "--address", address, "--insecure", "--token-script", token_script)
login_args = ["login", "--address", address, "--insecure", "--token-script", token_script]
if self._private:
login_args.append("--private")
self._run(*login_args)

def close(self) -> None:
shutil.rmtree(self._config_dir, ignore_errors=True)
Expand All @@ -43,7 +48,10 @@ def _run_unchecked(self, *args: str, timeout: int = 300) -> tuple[str, int]:
return run_unchecked(self.binary, "--config", self._config_dir, *args, timeout=timeout)

def relogin(self) -> None:
self._run("login", "--address", self._address, "--insecure", "--token-script", self._token_script)
login_args = ["login", "--address", self._address, "--insecure", "--token-script", self._token_script]
if self._private:
login_args.append("--private")
self._run(*login_args)

@staticmethod
def _parse_uuid(stdout: str) -> str:
Expand Down Expand Up @@ -124,10 +132,28 @@ def create_compute_instance(
def delete_compute_instance(self, *, uuid: str) -> None:
self._run("delete", "computeinstance", uuid)

def create_instance_type(self, *, name: str, cores: int, memory_gib: int, description: str = "") -> str:
args: list[str] = ["create", "instancetype", "--name", name, "--cores", str(cores), "--memory-gib", str(memory_gib)]
def create_instance_type(
self,
*,
name: str,
cores: int,
memory_gib: int,
description: str = "",
gpu_pci_device_selector: str = "",
gpu_resource_name: str = "",
gpu_count: int = 0,
) -> str:
args: list[str] = [
"create", "instancetype", "--name", name, "--cores", str(cores), "--memory-gib", str(memory_gib),
]
if description:
args.extend(["--description", description])
if gpu_pci_device_selector:
args.extend(["--gpu-pci-device-selector", gpu_pci_device_selector])
if gpu_resource_name:
args.extend(["--gpu-resource-name", gpu_resource_name])
if gpu_count:
args.extend(["--gpu-count", str(gpu_count)])
return self._parse_uuid(self._run(*args))

def describe_instance_type(self, *, name: str) -> str:
Expand Down
39 changes: 39 additions & 0 deletions tests/vmaas/test_instance_type_lifecycle.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,45 @@ def test_instance_type_lifecycle(cli: OsacCLI, private_grpc: GRPCClient) -> None
raise


def test_create_instance_type_via_cli(private_cli: OsacCLI, private_grpc: GRPCClient) -> None:
it_name: str = f"e2e-cli-it-{uuid4().hex[:8]}"

try:
private_cli.create_instance_type(
name=it_name,
cores=TEST_CORES,
memory_gib=TEST_MEMORY_GIB,
description="CLI create test type",
gpu_pci_device_selector=TEST_GPU["pci_device_selector"],
gpu_resource_name=TEST_GPU["resource_name"],
gpu_count=TEST_GPU["count"],
)

response: dict = private_grpc.get_instance_type(name=it_name)
spec: dict = response["object"]["spec"]
assert spec["cores"] == TEST_CORES, f"spec.cores mismatch: {spec['cores']} != {TEST_CORES}"
assert spec["memoryGib"] == TEST_MEMORY_GIB, (
f"spec.memoryGib mismatch: {spec['memoryGib']} != {TEST_MEMORY_GIB}"
)
assert "gpu" in spec, f"spec.gpu missing from response: {spec}"
gpu: dict = spec["gpu"]
assert gpu["pciDeviceSelector"] == TEST_GPU["pci_device_selector"], (
f"gpu.pciDeviceSelector mismatch: {gpu['pciDeviceSelector']} != {TEST_GPU['pci_device_selector']}"
)
assert gpu["resourceName"] == TEST_GPU["resource_name"], (
f"gpu.resourceName mismatch: {gpu['resourceName']} != {TEST_GPU['resource_name']}"
)
assert gpu["count"] == TEST_GPU["count"], f"gpu.count mismatch: {gpu['count']} != {TEST_GPU['count']}"

finally:
try:
private_grpc.delete_instance_type(name=it_name)
except subprocess.CalledProcessError as e:
output = ((e.stdout or "") + (e.stderr or "")).lower()
if "not found" not in output:
raise
Comment thread
coderabbitai[bot] marked this conversation as resolved.


def test_gpu_instance_type(private_grpc: GRPCClient) -> None:
gpu_name: str = f"e2e-gpu-lifecycle-{uuid4().hex[:8]}"
nogpu_name: str = f"e2e-nogpu-lifecycle-{uuid4().hex[:8]}"
Expand Down
Loading