trainml 0.5.8__py3-none-any.whl → 0.5.11__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- tests/integration/projects/__init__.py +0 -0
- tests/integration/projects/conftest.py +10 -0
- tests/integration/projects/test_projects_data_connectors_integration.py +44 -0
- tests/integration/projects/test_projects_datastores_integration.py +42 -0
- tests/integration/{test_projects_integration.py → projects/test_projects_integration.py} +0 -6
- tests/integration/projects/test_projects_keys_integration.py +43 -0
- tests/integration/projects/test_projects_secrets_integration.py +44 -0
- tests/integration/projects/test_projects_services_integration.py +44 -0
- tests/integration/test_checkpoints_integration.py +1 -2
- tests/integration/test_models_integration.py +0 -1
- tests/unit/cli/projects/__init__.py +0 -0
- tests/unit/cli/projects/test_cli_project_data_connector_unit.py +28 -0
- tests/unit/cli/projects/test_cli_project_datastore_unit.py +26 -0
- tests/unit/cli/projects/test_cli_project_key_unit.py +26 -0
- tests/unit/cli/projects/test_cli_project_secret_unit.py +26 -0
- tests/unit/cli/projects/test_cli_project_service_unit.py +26 -0
- tests/unit/cli/projects/test_cli_project_unit.py +19 -0
- tests/unit/cloudbender/test_datastores_unit.py +1 -5
- tests/unit/conftest.py +146 -3
- tests/unit/projects/__init__.py +0 -0
- tests/unit/projects/test_project_data_connectors_unit.py +102 -0
- tests/unit/projects/test_project_datastores_unit.py +96 -0
- tests/unit/projects/test_project_keys_unit.py +96 -0
- tests/unit/projects/test_project_secrets_unit.py +101 -0
- tests/unit/projects/test_project_services_unit.py +102 -0
- tests/unit/projects/test_projects_unit.py +128 -0
- tests/unit/test_checkpoints_unit.py +15 -23
- tests/unit/test_datasets_unit.py +15 -20
- tests/unit/test_models_unit.py +13 -16
- tests/unit/test_volumes_unit.py +3 -0
- trainml/__init__.py +1 -1
- trainml/checkpoints.py +14 -3
- trainml/cli/cloudbender/datastore.py +2 -7
- trainml/cli/project/__init__.py +84 -0
- trainml/cli/project/data_connector.py +61 -0
- trainml/cli/project/datastore.py +61 -0
- trainml/cli/project/key.py +124 -0
- trainml/cli/project/secret.py +71 -0
- trainml/cli/project/service.py +61 -0
- trainml/cloudbender/data_connectors.py +8 -0
- trainml/cloudbender/datastores.py +9 -19
- trainml/cloudbender/nodes.py +44 -1
- trainml/cloudbender/providers.py +53 -0
- trainml/cloudbender/regions.py +48 -0
- trainml/datasets.py +14 -3
- trainml/exceptions.py +51 -0
- trainml/jobs.py +2 -13
- trainml/models.py +14 -3
- trainml/projects/__init__.py +3 -0
- trainml/projects/data_connectors.py +63 -0
- trainml/projects/datastores.py +58 -0
- trainml/projects/keys.py +71 -0
- trainml/projects/projects.py +83 -0
- trainml/projects/secrets.py +70 -0
- trainml/projects/services.py +63 -0
- trainml/volumes.py +15 -3
- {trainml-0.5.8.dist-info → trainml-0.5.11.dist-info}/METADATA +1 -1
- {trainml-0.5.8.dist-info → trainml-0.5.11.dist-info}/RECORD +64 -38
- tests/unit/cli/cloudbender/test_cli_reservation_unit.py +0 -34
- tests/unit/cli/test_cli_project_unit.py +0 -42
- tests/unit/cloudbender/test_reservations_unit.py +0 -173
- tests/unit/test_projects_unit.py +0 -320
- trainml/cli/cloudbender/reservation.py +0 -159
- trainml/cli/project.py +0 -149
- trainml/cloudbender/reservations.py +0 -126
- trainml/projects.py +0 -228
- /tests/unit/{test_auth.py → test_auth_unit.py} +0 -0
- /tests/unit/{test_trainml.py → test_trainml_unit.py} +0 -0
- {trainml-0.5.8.dist-info → trainml-0.5.11.dist-info}/LICENSE +0 -0
- {trainml-0.5.8.dist-info → trainml-0.5.11.dist-info}/WHEEL +0 -0
- {trainml-0.5.8.dist-info → trainml-0.5.11.dist-info}/entry_points.txt +0 -0
- {trainml-0.5.8.dist-info → trainml-0.5.11.dist-info}/top_level.txt +0 -0
|
File without changes
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import re
|
|
2
|
+
import sys
|
|
3
|
+
import asyncio
|
|
4
|
+
from pytest import mark, fixture
|
|
5
|
+
|
|
6
|
+
pytestmark = [mark.sdk, mark.integration, mark.projects]
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@mark.create
|
|
10
|
+
@mark.asyncio
|
|
11
|
+
class ProjectDataConnectorsTests:
|
|
12
|
+
@fixture(scope="class")
|
|
13
|
+
async def project_data_connector(self, project):
|
|
14
|
+
data_connectors = await project.data_connectors.list()
|
|
15
|
+
yield data_connectors[0]
|
|
16
|
+
|
|
17
|
+
async def test_list_project_data_connectors(self, project, project_data_connector):
|
|
18
|
+
data_connectors = await project.data_connectors.list()
|
|
19
|
+
assert len(data_connectors) > 0
|
|
20
|
+
|
|
21
|
+
async def test_project_data_connector_properties(
|
|
22
|
+
self, project, project_data_connector
|
|
23
|
+
):
|
|
24
|
+
assert isinstance(project_data_connector.project_uuid, str)
|
|
25
|
+
assert isinstance(project_data_connector.type, str)
|
|
26
|
+
assert isinstance(project_data_connector.name, str)
|
|
27
|
+
assert isinstance(project_data_connector.region_uuid, str)
|
|
28
|
+
assert project.id == project_data_connector.project_uuid
|
|
29
|
+
|
|
30
|
+
async def test_project_data_connector_str(self, project_data_connector):
|
|
31
|
+
string = str(project_data_connector)
|
|
32
|
+
regex = r"^{.*\"name\": \"" + project_data_connector.name + r"\".*}$"
|
|
33
|
+
assert isinstance(string, str)
|
|
34
|
+
assert re.match(regex, string)
|
|
35
|
+
|
|
36
|
+
async def test_project_data_connector_repr(self, project_data_connector):
|
|
37
|
+
string = repr(project_data_connector)
|
|
38
|
+
regex = (
|
|
39
|
+
r"^ProjectDataConnector\( trainml , \*\*{.*'name': '"
|
|
40
|
+
+ project_data_connector.name
|
|
41
|
+
+ r"'.*}\)$"
|
|
42
|
+
)
|
|
43
|
+
assert isinstance(string, str)
|
|
44
|
+
assert re.match(regex, string)
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import re
|
|
2
|
+
import sys
|
|
3
|
+
import asyncio
|
|
4
|
+
from pytest import mark, fixture
|
|
5
|
+
|
|
6
|
+
pytestmark = [mark.sdk, mark.integration, mark.projects]
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@mark.create
|
|
10
|
+
@mark.asyncio
|
|
11
|
+
class ProjectDatastoresTests:
|
|
12
|
+
@fixture(scope="class")
|
|
13
|
+
async def project_datastore(self, project):
|
|
14
|
+
datastores = await project.datastores.list()
|
|
15
|
+
yield datastores[0]
|
|
16
|
+
|
|
17
|
+
async def test_list_project_datastores(self, project):
|
|
18
|
+
datastores = await project.datastores.list()
|
|
19
|
+
assert len(datastores) > 0
|
|
20
|
+
|
|
21
|
+
async def test_project_datastore_properties(self, project, project_datastore):
|
|
22
|
+
assert isinstance(project_datastore.project_uuid, str)
|
|
23
|
+
assert isinstance(project_datastore.type, str)
|
|
24
|
+
assert isinstance(project_datastore.name, str)
|
|
25
|
+
assert isinstance(project_datastore.region_uuid, str)
|
|
26
|
+
assert project.id == project_datastore.project_uuid
|
|
27
|
+
|
|
28
|
+
async def test_project_datastore_str(self, project_datastore):
|
|
29
|
+
string = str(project_datastore)
|
|
30
|
+
regex = r"^{.*\"name\": \"" + project_datastore.name + r"\".*}$"
|
|
31
|
+
assert isinstance(string, str)
|
|
32
|
+
assert re.match(regex, string)
|
|
33
|
+
|
|
34
|
+
async def test_project_datastore_repr(self, project_datastore):
|
|
35
|
+
string = repr(project_datastore)
|
|
36
|
+
regex = (
|
|
37
|
+
r"^ProjectDatastore\( trainml , \*\*{.*'name': '"
|
|
38
|
+
+ project_datastore.name
|
|
39
|
+
+ r"'.*}\)$"
|
|
40
|
+
)
|
|
41
|
+
assert isinstance(string, str)
|
|
42
|
+
assert re.match(regex, string)
|
|
@@ -9,12 +9,6 @@ pytestmark = [mark.sdk, mark.integration, mark.projects]
|
|
|
9
9
|
@mark.create
|
|
10
10
|
@mark.asyncio
|
|
11
11
|
class GetProjectsTests:
|
|
12
|
-
@fixture(scope="class")
|
|
13
|
-
async def project(self, trainml):
|
|
14
|
-
project = await trainml.projects.create(name="New Project", copy_keys=False)
|
|
15
|
-
yield project
|
|
16
|
-
await project.remove()
|
|
17
|
-
|
|
18
12
|
async def test_get_projects(self, trainml):
|
|
19
13
|
projects = await trainml.projects.list()
|
|
20
14
|
assert len(projects) > 0
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import re
|
|
2
|
+
import sys
|
|
3
|
+
import asyncio
|
|
4
|
+
from pytest import mark, fixture
|
|
5
|
+
|
|
6
|
+
pytestmark = [mark.sdk, mark.integration, mark.projects]
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@mark.create
|
|
10
|
+
@mark.asyncio
|
|
11
|
+
class ProjectKeysTests:
|
|
12
|
+
@fixture(scope="class")
|
|
13
|
+
async def project_key(self, project):
|
|
14
|
+
project_key = await project.keys.put(
|
|
15
|
+
type="aws", key_id="ASFHALKF", secret="IUHKLHKAHF"
|
|
16
|
+
)
|
|
17
|
+
yield project_key
|
|
18
|
+
await project.keys.remove(type="aws")
|
|
19
|
+
|
|
20
|
+
async def test_list_project_keys(self, project, project_key):
|
|
21
|
+
keys = await project.keys.list()
|
|
22
|
+
assert len(keys) > 0
|
|
23
|
+
|
|
24
|
+
async def test_project_key_properties(self, project, project_key):
|
|
25
|
+
assert isinstance(project_key.project_uuid, str)
|
|
26
|
+
assert isinstance(project_key.type, str)
|
|
27
|
+
assert isinstance(project_key.key_id, str)
|
|
28
|
+
assert project_key.type == "aws"
|
|
29
|
+
assert project.id == project_key.project_uuid
|
|
30
|
+
|
|
31
|
+
async def test_project_key_str(self, project_key):
|
|
32
|
+
string = str(project_key)
|
|
33
|
+
regex = r"^{.*\"type\": \"" + project_key.type + r"\".*}$"
|
|
34
|
+
assert isinstance(string, str)
|
|
35
|
+
assert re.match(regex, string)
|
|
36
|
+
|
|
37
|
+
async def test_project_key_repr(self, project_key):
|
|
38
|
+
string = repr(project_key)
|
|
39
|
+
regex = (
|
|
40
|
+
r"^ProjectKey\( trainml , \*\*{.*'type': '" + project_key.type + r"'.*}\)$"
|
|
41
|
+
)
|
|
42
|
+
assert isinstance(string, str)
|
|
43
|
+
assert re.match(regex, string)
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import re
|
|
2
|
+
import sys
|
|
3
|
+
import asyncio
|
|
4
|
+
from pytest import mark, fixture
|
|
5
|
+
|
|
6
|
+
pytestmark = [mark.sdk, mark.integration, mark.projects]
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@mark.create
|
|
10
|
+
@mark.asyncio
|
|
11
|
+
class ProjectSecretsTests:
|
|
12
|
+
@fixture(scope="class")
|
|
13
|
+
async def project_secret(self, project):
|
|
14
|
+
project_secret = await project.secrets.put(
|
|
15
|
+
name="secret_value", value="IUHKLHKAHF"
|
|
16
|
+
)
|
|
17
|
+
yield project_secret
|
|
18
|
+
await project.secrets.remove(name="secret_value")
|
|
19
|
+
|
|
20
|
+
async def test_list_project_keys(self, project, project_secret):
|
|
21
|
+
secrets = await project.secrets.list()
|
|
22
|
+
assert len(secrets) > 0
|
|
23
|
+
|
|
24
|
+
async def test_project_secret_properties(self, project, project_secret):
|
|
25
|
+
assert isinstance(project_secret.project_uuid, str)
|
|
26
|
+
assert isinstance(project_secret.name, str)
|
|
27
|
+
assert project_secret.name == "secret_value"
|
|
28
|
+
assert project.id == project_secret.project_uuid
|
|
29
|
+
|
|
30
|
+
async def test_project_secret_str(self, project_secret):
|
|
31
|
+
string = str(project_secret)
|
|
32
|
+
regex = r"^{.*\"name\": \"" + project_secret.name + r"\".*}$"
|
|
33
|
+
assert isinstance(string, str)
|
|
34
|
+
assert re.match(regex, string)
|
|
35
|
+
|
|
36
|
+
async def test_project_secret_repr(self, project_secret):
|
|
37
|
+
string = repr(project_secret)
|
|
38
|
+
regex = (
|
|
39
|
+
r"^ProjectSecret\( trainml , \*\*{.*'name': '"
|
|
40
|
+
+ project_secret.name
|
|
41
|
+
+ r"'.*}\)$"
|
|
42
|
+
)
|
|
43
|
+
assert isinstance(string, str)
|
|
44
|
+
assert re.match(regex, string)
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import re
|
|
2
|
+
import sys
|
|
3
|
+
import asyncio
|
|
4
|
+
from pytest import mark, fixture
|
|
5
|
+
|
|
6
|
+
pytestmark = [mark.sdk, mark.integration, mark.projects]
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@mark.create
|
|
10
|
+
@mark.asyncio
|
|
11
|
+
class ProjectServicesTests:
|
|
12
|
+
@fixture(scope="class")
|
|
13
|
+
async def project_service(self, project):
|
|
14
|
+
services = await project.services.list()
|
|
15
|
+
yield services[0]
|
|
16
|
+
|
|
17
|
+
async def test_list_project_services(self, project):
|
|
18
|
+
services = await project.services.list()
|
|
19
|
+
assert len(services) > 0
|
|
20
|
+
|
|
21
|
+
async def test_project_service_properties(self, project, project_service):
|
|
22
|
+
assert isinstance(project_service.project_uuid, str)
|
|
23
|
+
assert isinstance(project_service.name, str)
|
|
24
|
+
assert isinstance(project_service.id, str)
|
|
25
|
+
assert isinstance(project_service.hostname, str)
|
|
26
|
+
assert isinstance(project_service.region_uuid, str)
|
|
27
|
+
assert isinstance(project_service.public, bool)
|
|
28
|
+
assert project.id == project_service.project_uuid
|
|
29
|
+
|
|
30
|
+
async def test_project_service_str(self, project_service):
|
|
31
|
+
string = str(project_service)
|
|
32
|
+
regex = r"^{.*\"name\": \"" + project_service.name + r"\".*}$"
|
|
33
|
+
assert isinstance(string, str)
|
|
34
|
+
assert re.match(regex, string)
|
|
35
|
+
|
|
36
|
+
async def test_project_service_repr(self, project_service):
|
|
37
|
+
string = repr(project_service)
|
|
38
|
+
regex = (
|
|
39
|
+
r"^ProjectService\( trainml , \*\*{.*'name': '"
|
|
40
|
+
+ project_service.name
|
|
41
|
+
+ r"'.*}\)$"
|
|
42
|
+
)
|
|
43
|
+
assert isinstance(string, str)
|
|
44
|
+
assert re.match(regex, string)
|
|
@@ -16,7 +16,7 @@ class GetCheckpointTests:
|
|
|
16
16
|
source_type="git",
|
|
17
17
|
source_uri="git@github.com:trainML/environment-tests.git",
|
|
18
18
|
)
|
|
19
|
-
checkpoint = await checkpoint.wait_for("ready",
|
|
19
|
+
checkpoint = await checkpoint.wait_for("ready", 180)
|
|
20
20
|
yield checkpoint
|
|
21
21
|
await checkpoint.remove()
|
|
22
22
|
checkpoint = await checkpoint.wait_for("archived", 60)
|
|
@@ -59,7 +59,6 @@ async def test_checkpoint_wasabi(trainml, capsys):
|
|
|
59
59
|
name="CLI Automated Wasabi",
|
|
60
60
|
source_type="wasabi",
|
|
61
61
|
source_uri="s3://trainml-example/models/trainml-examples",
|
|
62
|
-
capacity="10G",
|
|
63
62
|
source_options=dict(endpoint_url="https://s3.wasabisys.com"),
|
|
64
63
|
)
|
|
65
64
|
checkpoint = await checkpoint.wait_for("ready", 300)
|
|
@@ -55,7 +55,6 @@ async def test_model_wasabi(trainml, capsys):
|
|
|
55
55
|
name="CLI Automated Wasabi",
|
|
56
56
|
source_type="wasabi",
|
|
57
57
|
source_uri="s3://trainml-example/models/trainml-examples",
|
|
58
|
-
capacity="10G",
|
|
59
58
|
source_options=dict(endpoint_url="https://s3.wasabisys.com"),
|
|
60
59
|
)
|
|
61
60
|
model = await model.wait_for("ready", 300)
|
|
File without changes
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import re
|
|
2
|
+
import json
|
|
3
|
+
import click
|
|
4
|
+
from unittest.mock import AsyncMock, patch, create_autospec
|
|
5
|
+
from pytest import mark, fixture, raises
|
|
6
|
+
|
|
7
|
+
pytestmark = [mark.cli, mark.unit, mark.projects]
|
|
8
|
+
|
|
9
|
+
from trainml.cli.project import data_connector as specimen
|
|
10
|
+
from trainml.projects import (
|
|
11
|
+
Project,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def test_list_data_connectors(runner, mock_project_data_connectors):
|
|
16
|
+
with patch("trainml.cli.TrainML", new=AsyncMock) as mock_trainml:
|
|
17
|
+
project = create_autospec(Project)
|
|
18
|
+
mock_trainml.projects = AsyncMock()
|
|
19
|
+
mock_trainml.projects.get = AsyncMock(return_value=project)
|
|
20
|
+
mock_trainml.projects.get_current = AsyncMock(return_value=project)
|
|
21
|
+
project.data_connectors = AsyncMock()
|
|
22
|
+
project.data_connectors.list = AsyncMock(
|
|
23
|
+
return_value=mock_project_data_connectors
|
|
24
|
+
)
|
|
25
|
+
result = runner.invoke(specimen, ["list"])
|
|
26
|
+
print(result)
|
|
27
|
+
assert result.exit_code == 0
|
|
28
|
+
project.data_connectors.list.assert_called_once()
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import re
|
|
2
|
+
import json
|
|
3
|
+
import click
|
|
4
|
+
from unittest.mock import AsyncMock, patch, create_autospec
|
|
5
|
+
from pytest import mark, fixture, raises
|
|
6
|
+
|
|
7
|
+
pytestmark = [mark.cli, mark.unit, mark.projects]
|
|
8
|
+
|
|
9
|
+
from trainml.cli.project import datastore as specimen
|
|
10
|
+
from trainml.projects import (
|
|
11
|
+
Project,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def test_list_datastores(runner, mock_project_datastores):
|
|
16
|
+
with patch("trainml.cli.TrainML", new=AsyncMock) as mock_trainml:
|
|
17
|
+
project = create_autospec(Project)
|
|
18
|
+
mock_trainml.projects = AsyncMock()
|
|
19
|
+
mock_trainml.projects.get = AsyncMock(return_value=project)
|
|
20
|
+
mock_trainml.projects.get_current = AsyncMock(return_value=project)
|
|
21
|
+
project.datastores = AsyncMock()
|
|
22
|
+
project.datastores.list = AsyncMock(return_value=mock_project_datastores)
|
|
23
|
+
result = runner.invoke(specimen, ["list"])
|
|
24
|
+
print(result)
|
|
25
|
+
assert result.exit_code == 0
|
|
26
|
+
project.datastores.list.assert_called_once()
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import re
|
|
2
|
+
import json
|
|
3
|
+
import click
|
|
4
|
+
from unittest.mock import AsyncMock, patch, create_autospec
|
|
5
|
+
from pytest import mark, fixture, raises
|
|
6
|
+
|
|
7
|
+
pytestmark = [mark.cli, mark.unit, mark.projects]
|
|
8
|
+
|
|
9
|
+
from trainml.cli.project import key as specimen
|
|
10
|
+
from trainml.projects import (
|
|
11
|
+
Project,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def test_list_keys(runner, mock_project_keys):
|
|
16
|
+
with patch("trainml.cli.TrainML", new=AsyncMock) as mock_trainml:
|
|
17
|
+
project = create_autospec(Project)
|
|
18
|
+
mock_trainml.projects = AsyncMock()
|
|
19
|
+
mock_trainml.projects.get = AsyncMock(return_value=project)
|
|
20
|
+
mock_trainml.projects.get_current = AsyncMock(return_value=project)
|
|
21
|
+
project.keys = AsyncMock()
|
|
22
|
+
project.keys.list = AsyncMock(return_value=mock_project_keys)
|
|
23
|
+
result = runner.invoke(specimen, ["list"])
|
|
24
|
+
print(result)
|
|
25
|
+
assert result.exit_code == 0
|
|
26
|
+
project.keys.list.assert_called_once()
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import re
|
|
2
|
+
import json
|
|
3
|
+
import click
|
|
4
|
+
from unittest.mock import AsyncMock, patch, create_autospec
|
|
5
|
+
from pytest import mark, fixture, raises
|
|
6
|
+
|
|
7
|
+
pytestmark = [mark.cli, mark.unit, mark.projects]
|
|
8
|
+
|
|
9
|
+
from trainml.cli.project import secret as specimen
|
|
10
|
+
from trainml.projects import (
|
|
11
|
+
Project,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def test_list_secrets(runner, mock_project_secrets):
|
|
16
|
+
with patch("trainml.cli.TrainML", new=AsyncMock) as mock_trainml:
|
|
17
|
+
project = create_autospec(Project)
|
|
18
|
+
mock_trainml.projects = AsyncMock()
|
|
19
|
+
mock_trainml.projects.get = AsyncMock(return_value=project)
|
|
20
|
+
mock_trainml.projects.get_current = AsyncMock(return_value=project)
|
|
21
|
+
project.secrets = AsyncMock()
|
|
22
|
+
project.secrets.list = AsyncMock(return_value=mock_project_secrets)
|
|
23
|
+
result = runner.invoke(specimen, ["list"])
|
|
24
|
+
print(result)
|
|
25
|
+
assert result.exit_code == 0
|
|
26
|
+
project.secrets.list.assert_called_once()
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import re
|
|
2
|
+
import json
|
|
3
|
+
import click
|
|
4
|
+
from unittest.mock import AsyncMock, patch, create_autospec
|
|
5
|
+
from pytest import mark, fixture, raises
|
|
6
|
+
|
|
7
|
+
pytestmark = [mark.cli, mark.unit, mark.projects]
|
|
8
|
+
|
|
9
|
+
from trainml.cli.project import service as specimen
|
|
10
|
+
from trainml.projects import (
|
|
11
|
+
Project,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def test_list_services(runner, mock_project_services):
|
|
16
|
+
with patch("trainml.cli.TrainML", new=AsyncMock) as mock_trainml:
|
|
17
|
+
project = create_autospec(Project)
|
|
18
|
+
mock_trainml.projects = AsyncMock()
|
|
19
|
+
mock_trainml.projects.get = AsyncMock(return_value=project)
|
|
20
|
+
mock_trainml.projects.get_current = AsyncMock(return_value=project)
|
|
21
|
+
project.services = AsyncMock()
|
|
22
|
+
project.services.list = AsyncMock(return_value=mock_project_services)
|
|
23
|
+
result = runner.invoke(specimen, ["list"])
|
|
24
|
+
print(result)
|
|
25
|
+
assert result.exit_code == 0
|
|
26
|
+
project.services.list.assert_called_once()
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import re
|
|
2
|
+
import json
|
|
3
|
+
import click
|
|
4
|
+
from unittest.mock import AsyncMock, patch, create_autospec
|
|
5
|
+
from pytest import mark, fixture, raises
|
|
6
|
+
|
|
7
|
+
pytestmark = [mark.cli, mark.unit, mark.projects]
|
|
8
|
+
|
|
9
|
+
from trainml.cli import project as specimen
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def test_list(runner, mock_projects):
|
|
13
|
+
with patch("trainml.cli.TrainML", new=AsyncMock) as mock_trainml:
|
|
14
|
+
mock_trainml.projects = AsyncMock()
|
|
15
|
+
mock_trainml.projects.list = AsyncMock(return_value=mock_projects)
|
|
16
|
+
result = runner.invoke(specimen, ["list"])
|
|
17
|
+
print(result)
|
|
18
|
+
assert result.exit_code == 0
|
|
19
|
+
mock_trainml.projects.list.assert_called_once()
|
|
@@ -119,8 +119,6 @@ class datastoreTests:
|
|
|
119
119
|
assert isinstance(datastore.region_uuid, str)
|
|
120
120
|
assert isinstance(datastore.type, str)
|
|
121
121
|
assert isinstance(datastore.name, str)
|
|
122
|
-
assert isinstance(datastore.uri, str)
|
|
123
|
-
assert isinstance(datastore.root, str)
|
|
124
122
|
|
|
125
123
|
def test_datastore_str(self, datastore):
|
|
126
124
|
string = str(datastore)
|
|
@@ -131,9 +129,7 @@ class datastoreTests:
|
|
|
131
129
|
def test_datastore_repr(self, datastore):
|
|
132
130
|
string = repr(datastore)
|
|
133
131
|
regex = (
|
|
134
|
-
r"^Datastore\( trainml , \*\*{.*'store_id': '"
|
|
135
|
-
+ datastore.id
|
|
136
|
-
+ r"'.*}\)$"
|
|
132
|
+
r"^Datastore\( trainml , \*\*{.*'store_id': '" + datastore.id + r"'.*}\)$"
|
|
137
133
|
)
|
|
138
134
|
assert isinstance(string, str)
|
|
139
135
|
assert re.match(regex, string)
|
tests/unit/conftest.py
CHANGED
|
@@ -16,9 +16,13 @@ from trainml.connections import Connections
|
|
|
16
16
|
from trainml.projects import (
|
|
17
17
|
Projects,
|
|
18
18
|
Project,
|
|
19
|
-
ProjectDatastore,
|
|
20
|
-
ProjectService,
|
|
21
19
|
)
|
|
20
|
+
from trainml.projects.datastores import ProjectDatastores, ProjectDatastore
|
|
21
|
+
from trainml.projects.services import ProjectServices, ProjectService
|
|
22
|
+
from trainml.projects.data_connectors import ProjectDataConnectors, ProjectDataConnector
|
|
23
|
+
from trainml.projects.keys import ProjectKeys, ProjectKey
|
|
24
|
+
from trainml.projects.secrets import ProjectSecrets, ProjectSecret
|
|
25
|
+
|
|
22
26
|
from trainml.cloudbender import Cloudbender
|
|
23
27
|
from trainml.cloudbender.providers import Provider, Providers
|
|
24
28
|
from trainml.cloudbender.regions import Region, Regions
|
|
@@ -26,6 +30,7 @@ from trainml.cloudbender.nodes import Node, Nodes
|
|
|
26
30
|
from trainml.cloudbender.devices import Device, Devices
|
|
27
31
|
from trainml.cloudbender.datastores import Datastore, Datastores
|
|
28
32
|
from trainml.cloudbender.services import Service, Services
|
|
33
|
+
from trainml.cloudbender.data_connectors import DataConnector, DataConnectors
|
|
29
34
|
from trainml.cloudbender.device_configs import DeviceConfig, DeviceConfigs
|
|
30
35
|
|
|
31
36
|
|
|
@@ -948,6 +953,68 @@ def mock_project_services():
|
|
|
948
953
|
]
|
|
949
954
|
|
|
950
955
|
|
|
956
|
+
@fixture(scope="session")
|
|
957
|
+
def mock_data_connectors():
|
|
958
|
+
trainml = Mock()
|
|
959
|
+
yield [
|
|
960
|
+
DataConnector(
|
|
961
|
+
trainml,
|
|
962
|
+
**{
|
|
963
|
+
"provider_uuid": "prov-id-1",
|
|
964
|
+
"region_uuid": "reg-id-1",
|
|
965
|
+
"connector_id": "con-id-1",
|
|
966
|
+
"type": "custom",
|
|
967
|
+
"name": "On-Prem Connection A",
|
|
968
|
+
"protocol": "TCP",
|
|
969
|
+
"port_range": "8000-8099",
|
|
970
|
+
"cidr": "10.0.3.0/24",
|
|
971
|
+
},
|
|
972
|
+
),
|
|
973
|
+
DataConnector(
|
|
974
|
+
trainml,
|
|
975
|
+
**{
|
|
976
|
+
"provider_uuid": "prov-id-2",
|
|
977
|
+
"region_uuid": "reg-id-2",
|
|
978
|
+
"connector_id": "con-id-2",
|
|
979
|
+
"type": "custom",
|
|
980
|
+
"name": "Cloud Connection B",
|
|
981
|
+
"protocol": "UDP",
|
|
982
|
+
"port_range": "5000",
|
|
983
|
+
"cidr": "10.0.2.0/24",
|
|
984
|
+
},
|
|
985
|
+
),
|
|
986
|
+
]
|
|
987
|
+
|
|
988
|
+
|
|
989
|
+
@fixture(
|
|
990
|
+
scope="session",
|
|
991
|
+
)
|
|
992
|
+
def mock_project_data_connectors():
|
|
993
|
+
trainml = Mock()
|
|
994
|
+
yield [
|
|
995
|
+
ProjectDataConnector(
|
|
996
|
+
trainml,
|
|
997
|
+
**{
|
|
998
|
+
"project_uuid": "proj-id-1",
|
|
999
|
+
"region_uuid": "reg-id-1",
|
|
1000
|
+
"id": "con-id-1",
|
|
1001
|
+
"type": "custom",
|
|
1002
|
+
"name": "On-Prem Connection A",
|
|
1003
|
+
},
|
|
1004
|
+
),
|
|
1005
|
+
ProjectDataConnector(
|
|
1006
|
+
trainml,
|
|
1007
|
+
**{
|
|
1008
|
+
"project_uuid": "proj-id-1",
|
|
1009
|
+
"region_uuid": "reg-id-2",
|
|
1010
|
+
"id": "con-id-2",
|
|
1011
|
+
"type": "custom",
|
|
1012
|
+
"name": "Cloud Connection B",
|
|
1013
|
+
},
|
|
1014
|
+
),
|
|
1015
|
+
]
|
|
1016
|
+
|
|
1017
|
+
|
|
951
1018
|
@fixture(scope="session")
|
|
952
1019
|
def mock_device_configs():
|
|
953
1020
|
trainml = Mock()
|
|
@@ -973,6 +1040,60 @@ def mock_device_configs():
|
|
|
973
1040
|
]
|
|
974
1041
|
|
|
975
1042
|
|
|
1043
|
+
@fixture(
|
|
1044
|
+
scope="session",
|
|
1045
|
+
)
|
|
1046
|
+
def mock_project_keys():
|
|
1047
|
+
trainml = Mock()
|
|
1048
|
+
yield [
|
|
1049
|
+
ProjectKey(
|
|
1050
|
+
trainml,
|
|
1051
|
+
**{
|
|
1052
|
+
"project_uuid": "proj-id-1",
|
|
1053
|
+
"type": "aws",
|
|
1054
|
+
"key_id": "AKSHFKHDFS",
|
|
1055
|
+
"updatedAt": "2023-06-02T21:22:40.084Z",
|
|
1056
|
+
},
|
|
1057
|
+
),
|
|
1058
|
+
ProjectKey(
|
|
1059
|
+
trainml,
|
|
1060
|
+
**{
|
|
1061
|
+
"project_uuid": "proj-id-1",
|
|
1062
|
+
"type": "gcp",
|
|
1063
|
+
"key_id": "credentials.json",
|
|
1064
|
+
"updatedAt": "2023-06-02T21:22:40.084Z",
|
|
1065
|
+
},
|
|
1066
|
+
),
|
|
1067
|
+
]
|
|
1068
|
+
|
|
1069
|
+
|
|
1070
|
+
@fixture(
|
|
1071
|
+
scope="session",
|
|
1072
|
+
)
|
|
1073
|
+
def mock_project_secrets():
|
|
1074
|
+
trainml = Mock()
|
|
1075
|
+
yield [
|
|
1076
|
+
ProjectSecret(
|
|
1077
|
+
trainml,
|
|
1078
|
+
**{
|
|
1079
|
+
"project_uuid": "proj-id-1",
|
|
1080
|
+
"name": "super_secret",
|
|
1081
|
+
"created_by": "User",
|
|
1082
|
+
"updatedAt": "2023-06-02T21:22:40.084Z",
|
|
1083
|
+
},
|
|
1084
|
+
),
|
|
1085
|
+
ProjectSecret(
|
|
1086
|
+
trainml,
|
|
1087
|
+
**{
|
|
1088
|
+
"project_uuid": "proj-id-1",
|
|
1089
|
+
"name": "super_secret_2",
|
|
1090
|
+
"created_by": "User",
|
|
1091
|
+
"updatedAt": "2023-06-02T21:22:40.084Z",
|
|
1092
|
+
},
|
|
1093
|
+
),
|
|
1094
|
+
]
|
|
1095
|
+
|
|
1096
|
+
|
|
976
1097
|
@fixture(scope="function")
|
|
977
1098
|
def mock_trainml(
|
|
978
1099
|
mock_my_datasets,
|
|
@@ -991,7 +1112,13 @@ def mock_trainml(
|
|
|
991
1112
|
mock_devices,
|
|
992
1113
|
mock_datastores,
|
|
993
1114
|
mock_services,
|
|
1115
|
+
mock_data_connectors,
|
|
994
1116
|
mock_device_configs,
|
|
1117
|
+
mock_project_datastores,
|
|
1118
|
+
mock_project_services,
|
|
1119
|
+
mock_project_data_connectors,
|
|
1120
|
+
mock_project_keys,
|
|
1121
|
+
mock_project_secrets,
|
|
995
1122
|
):
|
|
996
1123
|
trainml = create_autospec(TrainML)
|
|
997
1124
|
trainml.active_project = "proj-id-1"
|
|
@@ -1015,6 +1142,18 @@ def mock_trainml(
|
|
|
1015
1142
|
trainml.environments.list = AsyncMock(return_value=mock_environments)
|
|
1016
1143
|
trainml.jobs.list = AsyncMock(return_value=mock_jobs)
|
|
1017
1144
|
trainml.projects.list = AsyncMock(return_value=mock_projects)
|
|
1145
|
+
trainml.projects.datastores = create_autospec(ProjectDatastores)
|
|
1146
|
+
trainml.projects.datastores.list = AsyncMock(return_value=mock_project_datastores)
|
|
1147
|
+
trainml.projects.services = create_autospec(ProjectServices)
|
|
1148
|
+
trainml.projects.services.list = AsyncMock(return_value=mock_project_services)
|
|
1149
|
+
trainml.projects.data_connectors = create_autospec(ProjectDataConnectors)
|
|
1150
|
+
trainml.projects.data_connectors.list = AsyncMock(
|
|
1151
|
+
return_value=mock_project_data_connectors
|
|
1152
|
+
)
|
|
1153
|
+
trainml.projects.keys = create_autospec(ProjectKeys)
|
|
1154
|
+
trainml.projects.keys.list = AsyncMock(return_value=mock_project_keys)
|
|
1155
|
+
trainml.projects.secrets = create_autospec(ProjectSecrets)
|
|
1156
|
+
trainml.projects.secrets.list = AsyncMock(return_value=mock_project_secrets)
|
|
1018
1157
|
|
|
1019
1158
|
trainml.cloudbender = create_autospec(Cloudbender)
|
|
1020
1159
|
|
|
@@ -1024,12 +1163,16 @@ def mock_trainml(
|
|
|
1024
1163
|
trainml.cloudbender.regions.list = AsyncMock(return_value=mock_regions)
|
|
1025
1164
|
trainml.cloudbender.nodes = create_autospec(Nodes)
|
|
1026
1165
|
trainml.cloudbender.nodes.list = AsyncMock(return_value=mock_nodes)
|
|
1027
|
-
trainml.cloudbender.devices = create_autospec(
|
|
1166
|
+
trainml.cloudbender.devices = create_autospec(Devices)
|
|
1028
1167
|
trainml.cloudbender.devices.list = AsyncMock(return_value=mock_devices)
|
|
1029
1168
|
trainml.cloudbender.datastores = create_autospec(Datastores)
|
|
1030
1169
|
trainml.cloudbender.datastores.list = AsyncMock(return_value=mock_datastores)
|
|
1031
1170
|
trainml.cloudbender.services = create_autospec(Services)
|
|
1032
1171
|
trainml.cloudbender.services.list = AsyncMock(return_value=mock_services)
|
|
1172
|
+
trainml.cloudbender.data_connectors = create_autospec(DataConnectors)
|
|
1173
|
+
trainml.cloudbender.data_connectors.list = AsyncMock(
|
|
1174
|
+
return_value=mock_data_connectors
|
|
1175
|
+
)
|
|
1033
1176
|
trainml.cloudbender.device_configs = create_autospec(DeviceConfigs)
|
|
1034
1177
|
trainml.cloudbender.device_configs.list = AsyncMock(
|
|
1035
1178
|
return_value=mock_device_configs
|
|
File without changes
|