Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 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
8 changes: 8 additions & 0 deletions datacrunch_compat/datacrunch/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,19 @@
__version__,
authentication,
balance,
cluster_types,
constants,
container_types,
containers,
exceptions,
helpers,
http_client,
images,
instance_types,
instances,
job_deployments,
locations,
long_term,
ssh_keys,
startup_scripts,
volume_types,
Expand All @@ -28,7 +32,9 @@
'__version__',
'authentication',
'balance',
'cluster_types',
'constants',
'container_types',
'containers',
'datacrunch',
'exceptions',
Expand All @@ -37,7 +43,9 @@
'images',
'instance_types',
'instances',
'job_deployments',
'locations',
'long_term',
'ssh_keys',
'startup_scripts',
'volume_types',
Expand Down
8 changes: 8 additions & 0 deletions datacrunch_compat/datacrunch/datacrunch.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,17 @@
from verda._version import __version__
from verda.authentication import AuthenticationService
from verda.balance import BalanceService
from verda.cluster_types import ClusterTypesService
from verda.constants import Constants
from verda.container_types import ContainerTypesService
from verda.containers import ContainersService
from verda.http_client import HTTPClient
from verda.images import ImagesService
from verda.instance_types import InstanceTypesService
from verda.instances import InstancesService
from verda.job_deployments import JobDeploymentsService
from verda.locations import LocationsService
from verda.long_term import LongTermService
from verda.ssh_keys import SSHKeysService
from verda.startup_scripts import StartupScriptsService
from verda.volume_types import VolumeTypesService
Expand All @@ -20,14 +24,18 @@
__all__ = [
'AuthenticationService',
'BalanceService',
'ClusterTypesService',
'Constants',
'ContainerTypesService',
'ContainersService',
'DataCrunchClient',
'HTTPClient',
'ImagesService',
'InstanceTypesService',
'InstancesService',
'JobDeploymentsService',
'LocationsService',
'LongTermService',
'SSHKeysService',
'StartupScriptsService',
'VolumeTypesService',
Expand Down
8 changes: 8 additions & 0 deletions docs/source/api/services/cluster_types.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Cluster Types
=============

.. autoclass:: verda.cluster_types.ClusterTypesService
:members:

.. autoclass:: verda.cluster_types.ClusterType
:members:
8 changes: 8 additions & 0 deletions docs/source/api/services/container_types.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Container Types
===============

.. autoclass:: verda.container_types.ContainerTypesService
:members:

.. autoclass:: verda.container_types.ContainerType
:members:
14 changes: 14 additions & 0 deletions docs/source/api/services/job_deployments.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
Job Deployments
===============

.. autoclass:: verda.job_deployments.JobDeploymentsService
:members:

.. autoclass:: verda.job_deployments.JobDeployment
:members:

.. autoclass:: verda.job_deployments.JobDeploymentSummary
:members:

.. autoclass:: verda.job_deployments.JobScalingOptions
:members:
8 changes: 8 additions & 0 deletions docs/source/api/services/long_term.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Long Term
=========

.. autoclass:: verda.long_term.LongTermService
:members:

.. autoclass:: verda.long_term.LongTermPeriod
:members:
51 changes: 51 additions & 0 deletions tests/unit_tests/cluster_types/test_cluster_types.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import responses # https://github.com/getsentry/responses

from verda.cluster_types import ClusterType, ClusterTypesService

CLUSTER_TYPE_ID = 'cluster-c0de-a5d2-4972-ae4e-d429115d055b'


@responses.activate
def test_cluster_types(http_client):
endpoint = http_client._base_url + '/cluster-types?currency=usd'
responses.add(
responses.GET,
endpoint,
json=[
{
'id': CLUSTER_TYPE_ID,
'model': 'H200',
'name': 'H200 Cluster',
'cluster_type': '16H200',
'cpu': {'description': '64 CPU', 'number_of_cores': 64},
'gpu': {'description': '16x H200', 'number_of_gpus': 16},
'gpu_memory': {'description': '2.2TB VRAM', 'size_in_gigabytes': 2200},
'memory': {'description': '4TB RAM', 'size_in_gigabytes': 4096},
'price_per_hour': '45.50',
'currency': 'usd',
'manufacturer': 'NVIDIA',
'node_details': ['2x 8 GPU nodes'],
'supported_os': ['ubuntu-24.04-cuda-12.8-cluster'],
}
],
status=200,
)

service = ClusterTypesService(http_client)

cluster_types = service.get()
cluster_type = cluster_types[0]

assert isinstance(cluster_types, list)
assert len(cluster_types) == 1
assert isinstance(cluster_type, ClusterType)
assert cluster_type.id == CLUSTER_TYPE_ID
assert cluster_type.model == 'H200'
assert cluster_type.name == 'H200 Cluster'
assert cluster_type.cluster_type == '16H200'
assert cluster_type.price_per_hour == 45.5
assert cluster_type.currency == 'usd'
assert cluster_type.manufacturer == 'NVIDIA'
assert cluster_type.node_details == ['2x 8 GPU nodes']
assert cluster_type.supported_os == ['ubuntu-24.04-cuda-12.8-cluster']
assert responses.assert_call_count(endpoint, 1) is True
49 changes: 49 additions & 0 deletions tests/unit_tests/container_types/test_container_types.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import responses # https://github.com/getsentry/responses

from verda.container_types import ContainerType, ContainerTypesService

CONTAINER_TYPE_ID = 'type-c0de-a5d2-4972-ae4e-d429115d055b'


@responses.activate
def test_container_types(http_client):
endpoint = http_client._base_url + '/container-types?currency=eur'
responses.add(
responses.GET,
endpoint,
json=[
{
'id': CONTAINER_TYPE_ID,
'model': 'H100',
'name': 'H100 SXM5 80GB',
'instance_type': '1H100.80S.22V',
'cpu': {'description': '22 CPU', 'number_of_cores': 22},
'gpu': {'description': '1x H100 SXM5 80GB', 'number_of_gpus': 1},
'gpu_memory': {'description': '80GB GPU RAM', 'size_in_gigabytes': 80},
'memory': {'description': '187GB RAM', 'size_in_gigabytes': 187},
'serverless_price': '1.75',
'serverless_spot_price': '0.87',
'currency': 'eur',
'manufacturer': 'NVIDIA',
}
],
status=200,
)

service = ContainerTypesService(http_client)

container_types = service.get(currency='eur')
container_type = container_types[0]

assert isinstance(container_types, list)
assert len(container_types) == 1
assert isinstance(container_type, ContainerType)
assert container_type.id == CONTAINER_TYPE_ID
assert container_type.model == 'H100'
assert container_type.name == 'H100 SXM5 80GB'
assert container_type.instance_type == '1H100.80S.22V'
assert container_type.serverless_price == 1.75
assert container_type.serverless_spot_price == 0.87
assert container_type.currency == 'eur'
assert container_type.manufacturer == 'NVIDIA'
assert responses.assert_call_count(endpoint, 1) is True
37 changes: 35 additions & 2 deletions tests/unit_tests/instance_types/test_instance_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,36 @@
STORAGE_DESCRIPTION = '1800GB NVME'
STORAGE_SIZE = 1800
INSTANCE_TYPE_DESCRIPTION = 'Dedicated Bare metal Server'
BEST_FOR = ['Large model inference', 'Multi-GPU training']
MODEL = 'V100'
NAME = 'Tesla V100'
P2P = '300 GB/s'
PRICE_PER_HOUR = 5.0
SPOT_PRICE_PER_HOUR = 2.5
SERVERLESS_PRICE = 1.25
SERVERLESS_SPOT_PRICE = 0.75
INSTANCE_TYPE = '8V100.48M'
CURRENCY = 'eur'
MANUFACTURER = 'NVIDIA'
DISPLAY_NAME = 'NVIDIA Tesla V100'
SUPPORTED_OS = ['ubuntu-24.04-cuda-12.8-open-docker']


@responses.activate
def test_instance_types(http_client):
# arrange - add response mock
responses.add(
responses.GET,
http_client._base_url + '/instance-types',
http_client._base_url + '/instance-types?currency=eur',
json=[
{
'id': TYPE_ID,
'best_for': BEST_FOR,
'cpu': {
'description': CPU_DESCRIPTION,
'number_of_cores': NUMBER_OF_CORES,
},
'deploy_warning': 'Use updated drivers',
'gpu': {
'description': GPU_DESCRIPTION,
'number_of_gpus': NUMBER_OF_GPUS,
Expand All @@ -48,9 +61,18 @@ def test_instance_types(http_client):
'size_in_gigabytes': STORAGE_SIZE,
},
'description': INSTANCE_TYPE_DESCRIPTION,
'model': MODEL,
'name': NAME,
'p2p': P2P,
'price_per_hour': '5.00',
'spot_price': '2.50',
'serverless_price': '1.25',
'serverless_spot_price': '0.75',
'instance_type': INSTANCE_TYPE,
'currency': CURRENCY,
'manufacturer': MANUFACTURER,
'display_name': DISPLAY_NAME,
'supported_os': SUPPORTED_OS,
}
],
status=200,
Expand All @@ -59,7 +81,7 @@ def test_instance_types(http_client):
instance_types_service = InstanceTypesService(http_client)

# act
instance_types = instance_types_service.get()
instance_types = instance_types_service.get(currency='eur')
instance_type = instance_types[0]

# assert
Expand All @@ -71,6 +93,17 @@ def test_instance_types(http_client):
assert instance_type.price_per_hour == PRICE_PER_HOUR
assert instance_type.spot_price_per_hour == SPOT_PRICE_PER_HOUR
assert instance_type.instance_type == INSTANCE_TYPE
assert instance_type.best_for == BEST_FOR
assert instance_type.model == MODEL
assert instance_type.name == NAME
assert instance_type.p2p == P2P
assert instance_type.currency == CURRENCY
assert instance_type.manufacturer == MANUFACTURER
assert instance_type.display_name == DISPLAY_NAME
assert instance_type.supported_os == SUPPORTED_OS
assert instance_type.deploy_warning == 'Use updated drivers'
assert instance_type.serverless_price == SERVERLESS_PRICE
assert instance_type.serverless_spot_price == SERVERLESS_SPOT_PRICE
assert isinstance(instance_type.cpu, dict)
assert isinstance(instance_type.gpu, dict)
assert isinstance(instance_type.memory, dict)
Expand Down
Loading