Skip to content

Commit e9bf80d

Browse files
albertsolaCopilot
andcommitted
MPT-19903: add /public/v1/integration/extensions/{extensionId}/instances endpoint
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 914a22d commit e9bf80d

3 files changed

Lines changed: 220 additions & 0 deletions

File tree

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
from mpt_api_client.http import AsyncService, Service
2+
from mpt_api_client.http.mixins import (
3+
AsyncCollectionMixin,
4+
AsyncCreateMixin,
5+
AsyncGetMixin,
6+
CollectionMixin,
7+
CreateMixin,
8+
GetMixin,
9+
)
10+
from mpt_api_client.models import Model
11+
from mpt_api_client.models.model import BaseModel
12+
13+
14+
class ExtensionInstance(Model):
15+
"""Extension Instance resource.
16+
17+
Attributes:
18+
name: Instance name.
19+
revision: Revision number.
20+
extension: Reference to the extension.
21+
meta: Extension metadata reference.
22+
external_id: External identifier for the instance.
23+
status: Instance status (Connecting, Disconnected, Running, Deleted).
24+
channel: Channel configuration.
25+
audit: Audit information (created, updated, connecting, running, disconnected).
26+
"""
27+
28+
name: str | None
29+
revision: int | None
30+
extension: BaseModel | None
31+
meta: BaseModel | None
32+
external_id: str | None
33+
status: str | None
34+
channel: BaseModel | None
35+
audit: BaseModel | None
36+
37+
38+
class ExtensionInstancesServiceConfig:
39+
"""Extension Instances service configuration."""
40+
41+
_endpoint = "/public/v1/integration/extensions/{extension_id}/instances"
42+
_model_class = ExtensionInstance
43+
_collection_key = "data"
44+
45+
46+
class ExtensionInstancesService(
47+
CreateMixin[ExtensionInstance],
48+
GetMixin[ExtensionInstance],
49+
CollectionMixin[ExtensionInstance],
50+
Service[ExtensionInstance],
51+
ExtensionInstancesServiceConfig,
52+
):
53+
"""Sync service for /public/v1/integration/extensions/{extensionId}/instances endpoint."""
54+
55+
56+
class AsyncExtensionInstancesService(
57+
AsyncCreateMixin[ExtensionInstance],
58+
AsyncGetMixin[ExtensionInstance],
59+
AsyncCollectionMixin[ExtensionInstance],
60+
AsyncService[ExtensionInstance],
61+
ExtensionInstancesServiceConfig,
62+
):
63+
"""Async service for /public/v1/integration/extensions/{extensionId}/instances endpoint."""

mpt_api_client/resources/integration/extensions.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@
1313
)
1414
from mpt_api_client.models import Model
1515
from mpt_api_client.models.model import BaseModel
16+
from mpt_api_client.resources.integration.extension_instances import (
17+
AsyncExtensionInstancesService,
18+
ExtensionInstancesService,
19+
)
1620
from mpt_api_client.resources.integration.mixins import (
1721
AsyncExtensionMixin,
1822
ExtensionMixin,
@@ -79,6 +83,12 @@ class ExtensionsService(
7983
):
8084
"""Sync service for the /public/v1/integration/extensions endpoint."""
8185

86+
def instances(self, extension_id: str) -> ExtensionInstancesService:
87+
"""Return extension instances service."""
88+
return ExtensionInstancesService(
89+
http_client=self.http_client, endpoint_params={"extension_id": extension_id}
90+
)
91+
8292

8393
class AsyncExtensionsService(
8494
AsyncExtensionMixin[Extension],
@@ -91,3 +101,9 @@ class AsyncExtensionsService(
91101
ExtensionsServiceConfig,
92102
):
93103
"""Async service for the /public/v1/integration/extensions endpoint."""
104+
105+
def instances(self, extension_id: str) -> AsyncExtensionInstancesService:
106+
"""Return extension instances service."""
107+
return AsyncExtensionInstancesService(
108+
http_client=self.http_client, endpoint_params={"extension_id": extension_id}
109+
)
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
import httpx
2+
import pytest
3+
import respx
4+
5+
from mpt_api_client.models.model import BaseModel
6+
from mpt_api_client.resources.integration.extension_instances import (
7+
AsyncExtensionInstancesService,
8+
ExtensionInstance,
9+
ExtensionInstancesService,
10+
)
11+
from mpt_api_client.resources.integration.extensions import (
12+
AsyncExtensionsService,
13+
ExtensionsService,
14+
)
15+
16+
17+
@pytest.fixture
18+
def extension_instances_service(http_client):
19+
return ExtensionInstancesService(
20+
http_client=http_client, endpoint_params={"extension_id": "EXT-001"}
21+
)
22+
23+
24+
@pytest.fixture
25+
def async_extension_instances_service(async_http_client):
26+
return AsyncExtensionInstancesService(
27+
http_client=async_http_client, endpoint_params={"extension_id": "EXT-001"}
28+
)
29+
30+
31+
@pytest.fixture
32+
def extensions_service(http_client):
33+
return ExtensionsService(http_client=http_client)
34+
35+
36+
@pytest.fixture
37+
def async_extensions_service(async_http_client):
38+
return AsyncExtensionsService(http_client=async_http_client)
39+
40+
41+
@pytest.mark.parametrize(
42+
"method",
43+
[
44+
"get",
45+
"create",
46+
"iterate",
47+
],
48+
)
49+
def test_mixins_present(extension_instances_service, method):
50+
result = hasattr(extension_instances_service, method)
51+
52+
assert result is True
53+
54+
55+
@pytest.mark.parametrize(
56+
"method",
57+
[
58+
"get",
59+
"create",
60+
"iterate",
61+
],
62+
)
63+
def test_async_mixins_present(async_extension_instances_service, method):
64+
result = hasattr(async_extension_instances_service, method)
65+
66+
assert result is True
67+
68+
69+
def test_extension_instance_primitive_fields():
70+
instance_data = {
71+
"id": "INS-001",
72+
"name": "My Instance",
73+
"revision": 2,
74+
"externalId": "ext-123",
75+
"status": "Running",
76+
"extension": {"id": "EXT-001"},
77+
"meta": {"id": "META-001"},
78+
"channel": {"type": "grpc"},
79+
"audit": {"created": {"at": "2024-01-01T00:00:00Z"}},
80+
}
81+
82+
result = ExtensionInstance(instance_data)
83+
84+
assert result.id == "INS-001"
85+
assert result.name == "My Instance"
86+
assert result.revision == 2
87+
assert result.external_id == "ext-123"
88+
assert result.status == "Running"
89+
assert isinstance(result.extension, BaseModel)
90+
assert isinstance(result.meta, BaseModel)
91+
assert isinstance(result.channel, BaseModel)
92+
assert isinstance(result.audit, BaseModel)
93+
94+
95+
def test_extension_instance_create(extension_instances_service):
96+
payload = {"externalId": "ext-123", "version": "1.0.0", "channel": {"type": "grpc"}}
97+
expected_response = {"id": "INS-001", "name": "My Instance", "status": "Connecting"}
98+
with respx.mock:
99+
mock_route = respx.post(
100+
"https://api.example.com/public/v1/integration/extensions/EXT-001/instances"
101+
).mock(return_value=httpx.Response(httpx.codes.CREATED, json=expected_response))
102+
103+
result = extension_instances_service.create(payload)
104+
105+
assert mock_route.call_count == 1
106+
assert mock_route.calls[0].request.method == "POST"
107+
assert result.to_dict() == expected_response
108+
109+
110+
def test_extension_instances_list(extension_instances_service):
111+
expected_response = {
112+
"data": [
113+
{"id": "INS-001", "name": "Instance 1", "status": "Running"},
114+
{"id": "INS-002", "name": "Instance 2", "status": "Disconnected"},
115+
]
116+
}
117+
with respx.mock:
118+
mock_route = respx.get(
119+
"https://api.example.com/public/v1/integration/extensions/EXT-001/instances"
120+
).mock(return_value=httpx.Response(httpx.codes.OK, json=expected_response))
121+
122+
result = list(extension_instances_service.iterate())
123+
124+
assert mock_route.call_count == 1
125+
assert len(result) == 2
126+
assert result[0].id == "INS-001"
127+
assert result[1].id == "INS-002"
128+
129+
130+
def test_extensions_instances_accessor(extensions_service, http_client):
131+
result = extensions_service.instances("EXT-001")
132+
133+
assert isinstance(result, ExtensionInstancesService)
134+
assert result.http_client is http_client
135+
136+
137+
def test_async_extensions_instances_accessor(async_extensions_service, async_http_client):
138+
result = async_extensions_service.instances("EXT-001")
139+
140+
assert isinstance(result, AsyncExtensionInstancesService)
141+
assert result.http_client is async_http_client

0 commit comments

Comments
 (0)