datacrunch 1.15.0__py3-none-any.whl → 1.16.0__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.
- datacrunch/InferenceClient/inference_client.py +200 -65
- datacrunch/__init__.py +2 -0
- datacrunch/_version.py +6 -0
- datacrunch/authentication/authentication.py +7 -14
- datacrunch/balance/balance.py +1 -3
- datacrunch/constants.py +19 -17
- datacrunch/containers/containers.py +151 -123
- datacrunch/datacrunch.py +18 -18
- datacrunch/helpers.py +7 -2
- datacrunch/http_client/http_client.py +14 -14
- datacrunch/images/images.py +9 -3
- datacrunch/instance_types/instance_types.py +42 -35
- datacrunch/instances/instances.py +62 -50
- datacrunch/locations/locations.py +1 -2
- datacrunch/ssh_keys/ssh_keys.py +3 -4
- datacrunch/startup_scripts/startup_scripts.py +10 -8
- datacrunch/volume_types/volume_types.py +10 -8
- datacrunch/volumes/volumes.py +60 -73
- {datacrunch-1.15.0.dist-info → datacrunch-1.16.0.dist-info}/METADATA +46 -72
- datacrunch-1.16.0.dist-info/RECORD +35 -0
- datacrunch-1.16.0.dist-info/WHEEL +4 -0
- datacrunch/__version__.py +0 -1
- datacrunch-1.15.0.dist-info/RECORD +0 -69
- datacrunch-1.15.0.dist-info/WHEEL +0 -5
- datacrunch-1.15.0.dist-info/licenses/LICENSE +0 -21
- datacrunch-1.15.0.dist-info/top_level.txt +0 -2
- tests/__init__.py +0 -0
- tests/integration_tests/__init__.py +0 -0
- tests/integration_tests/conftest.py +0 -20
- tests/integration_tests/test_instances.py +0 -36
- tests/integration_tests/test_locations.py +0 -65
- tests/integration_tests/test_volumes.py +0 -94
- tests/unit_tests/__init__.py +0 -0
- tests/unit_tests/authentication/__init__.py +0 -0
- tests/unit_tests/authentication/test_authentication.py +0 -202
- tests/unit_tests/balance/__init__.py +0 -0
- tests/unit_tests/balance/test_balance.py +0 -25
- tests/unit_tests/conftest.py +0 -21
- tests/unit_tests/containers/__init__.py +0 -1
- tests/unit_tests/containers/test_containers.py +0 -959
- tests/unit_tests/http_client/__init__.py +0 -0
- tests/unit_tests/http_client/test_http_client.py +0 -193
- tests/unit_tests/images/__init__.py +0 -0
- tests/unit_tests/images/test_images.py +0 -41
- tests/unit_tests/instance_types/__init__.py +0 -0
- tests/unit_tests/instance_types/test_instance_types.py +0 -87
- tests/unit_tests/instances/__init__.py +0 -0
- tests/unit_tests/instances/test_instances.py +0 -483
- tests/unit_tests/ssh_keys/__init__.py +0 -0
- tests/unit_tests/ssh_keys/test_ssh_keys.py +0 -198
- tests/unit_tests/startup_scripts/__init__.py +0 -0
- tests/unit_tests/startup_scripts/test_startup_scripts.py +0 -196
- tests/unit_tests/test_datacrunch.py +0 -65
- tests/unit_tests/test_exceptions.py +0 -33
- tests/unit_tests/volume_types/__init__.py +0 -0
- tests/unit_tests/volume_types/test_volume_types.py +0 -50
- tests/unit_tests/volumes/__init__.py +0 -0
- tests/unit_tests/volumes/test_volumes.py +0 -641
|
@@ -1,959 +0,0 @@
|
|
|
1
|
-
import pytest
|
|
2
|
-
import responses # https://github.com/getsentry/responses
|
|
3
|
-
from responses import matchers
|
|
4
|
-
|
|
5
|
-
from datacrunch.containers.containers import (
|
|
6
|
-
CONTAINER_DEPLOYMENTS_ENDPOINT,
|
|
7
|
-
CONTAINER_REGISTRY_CREDENTIALS_ENDPOINT,
|
|
8
|
-
SECRETS_ENDPOINT,
|
|
9
|
-
SERVERLESS_COMPUTE_RESOURCES_ENDPOINT,
|
|
10
|
-
Container,
|
|
11
|
-
ContainerDeploymentStatus,
|
|
12
|
-
ContainerRegistrySettings,
|
|
13
|
-
ContainersService,
|
|
14
|
-
Deployment,
|
|
15
|
-
EnvVar,
|
|
16
|
-
EnvVarType,
|
|
17
|
-
EntrypointOverridesSettings,
|
|
18
|
-
HealthcheckSettings,
|
|
19
|
-
RegistryCredential,
|
|
20
|
-
Secret,
|
|
21
|
-
VolumeMount,
|
|
22
|
-
VolumeMountType,
|
|
23
|
-
ComputeResource,
|
|
24
|
-
ScalingOptions,
|
|
25
|
-
ScalingPolicy,
|
|
26
|
-
ScalingTriggers,
|
|
27
|
-
QueueLoadScalingTrigger,
|
|
28
|
-
UtilizationScalingTrigger,
|
|
29
|
-
DockerHubCredentials,
|
|
30
|
-
GithubCredentials,
|
|
31
|
-
GCRCredentials,
|
|
32
|
-
AWSECRCredentials,
|
|
33
|
-
CustomRegistryCredentials,
|
|
34
|
-
ReplicaInfo,
|
|
35
|
-
)
|
|
36
|
-
from datacrunch.exceptions import APIException
|
|
37
|
-
|
|
38
|
-
DEPLOYMENT_NAME = "test-deployment"
|
|
39
|
-
CONTAINER_NAME = "test-container"
|
|
40
|
-
COMPUTE_RESOURCE_NAME_GENERAL_COMPUTE = "General Compute"
|
|
41
|
-
COMPUTE_RESOURCE_NAME_H100 = "H100"
|
|
42
|
-
SECRET_NAME = "test-secret"
|
|
43
|
-
SECRET_VALUE = "test-secret-value"
|
|
44
|
-
REGISTRY_CREDENTIAL_NAME = "test-credential"
|
|
45
|
-
ENV_VAR_NAME = "TEST_VAR"
|
|
46
|
-
ENV_VAR_VALUE = "test-value"
|
|
47
|
-
|
|
48
|
-
INVALID_REQUEST = "INVALID_REQUEST"
|
|
49
|
-
INVALID_REQUEST_MESSAGE = "Invalid request"
|
|
50
|
-
|
|
51
|
-
# Sample deployment data for testing
|
|
52
|
-
DEPLOYMENT_DATA = {
|
|
53
|
-
"name": DEPLOYMENT_NAME,
|
|
54
|
-
"container_registry_settings": {
|
|
55
|
-
"is_private": False
|
|
56
|
-
},
|
|
57
|
-
"containers": [
|
|
58
|
-
{
|
|
59
|
-
"name": CONTAINER_NAME,
|
|
60
|
-
"image": "nginx:latest",
|
|
61
|
-
"exposed_port": 80,
|
|
62
|
-
"healthcheck": {
|
|
63
|
-
"enabled": True,
|
|
64
|
-
"port": 80,
|
|
65
|
-
"path": "/health"
|
|
66
|
-
},
|
|
67
|
-
"entrypoint_overrides": {
|
|
68
|
-
"enabled": False
|
|
69
|
-
},
|
|
70
|
-
"env": [
|
|
71
|
-
{
|
|
72
|
-
"name": "ENV_VAR1",
|
|
73
|
-
"value_or_reference_to_secret": "value1",
|
|
74
|
-
"type": "plain"
|
|
75
|
-
}
|
|
76
|
-
],
|
|
77
|
-
"volume_mounts": [
|
|
78
|
-
{
|
|
79
|
-
"type": "scratch",
|
|
80
|
-
"mount_path": "/data"
|
|
81
|
-
}
|
|
82
|
-
]
|
|
83
|
-
}
|
|
84
|
-
],
|
|
85
|
-
"compute": {
|
|
86
|
-
"name": COMPUTE_RESOURCE_NAME_GENERAL_COMPUTE,
|
|
87
|
-
"size": 1,
|
|
88
|
-
"is_available": True
|
|
89
|
-
},
|
|
90
|
-
"is_spot": False,
|
|
91
|
-
"endpoint_base_url": "https://test-deployment.datacrunch.io",
|
|
92
|
-
"scaling": {
|
|
93
|
-
"min_replica_count": 1,
|
|
94
|
-
"max_replica_count": 3,
|
|
95
|
-
"scale_down_policy": {
|
|
96
|
-
"delay_seconds": 300
|
|
97
|
-
},
|
|
98
|
-
"scale_up_policy": {
|
|
99
|
-
"delay_seconds": 60
|
|
100
|
-
},
|
|
101
|
-
"queue_message_ttl_seconds": 3600,
|
|
102
|
-
"concurrent_requests_per_replica": 10,
|
|
103
|
-
"scaling_triggers": {
|
|
104
|
-
"queue_load": {
|
|
105
|
-
"threshold": 0.75
|
|
106
|
-
},
|
|
107
|
-
"cpu_utilization": {
|
|
108
|
-
"enabled": True,
|
|
109
|
-
"threshold": 0.8
|
|
110
|
-
},
|
|
111
|
-
"gpu_utilization": {
|
|
112
|
-
"enabled": False
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
},
|
|
116
|
-
"created_at": "2023-01-01T00:00:00+00:00"
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
# Sample compute resources data
|
|
120
|
-
COMPUTE_RESOURCES_DATA = [
|
|
121
|
-
{
|
|
122
|
-
"name": COMPUTE_RESOURCE_NAME_GENERAL_COMPUTE,
|
|
123
|
-
"size": 1,
|
|
124
|
-
"is_available": True
|
|
125
|
-
},
|
|
126
|
-
{
|
|
127
|
-
"name": COMPUTE_RESOURCE_NAME_H100,
|
|
128
|
-
"size": 4,
|
|
129
|
-
"is_available": True
|
|
130
|
-
}
|
|
131
|
-
]
|
|
132
|
-
|
|
133
|
-
# Sample secrets data
|
|
134
|
-
SECRETS_DATA = [
|
|
135
|
-
{
|
|
136
|
-
"name": SECRET_NAME,
|
|
137
|
-
"created_at": "2023-01-01T00:00:00+00:00",
|
|
138
|
-
"secret_type": "generic"
|
|
139
|
-
}
|
|
140
|
-
]
|
|
141
|
-
|
|
142
|
-
# Sample registry credentials data
|
|
143
|
-
REGISTRY_CREDENTIALS_DATA = [
|
|
144
|
-
{
|
|
145
|
-
"name": REGISTRY_CREDENTIAL_NAME,
|
|
146
|
-
"created_at": "2023-01-01T00:00:00+00:00"
|
|
147
|
-
}
|
|
148
|
-
]
|
|
149
|
-
|
|
150
|
-
# Sample deployment status data
|
|
151
|
-
DEPLOYMENT_STATUS_DATA = {
|
|
152
|
-
"status": "healthy"
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
# Sample replicas data
|
|
156
|
-
REPLICAS_DATA = {
|
|
157
|
-
"list": [
|
|
158
|
-
{
|
|
159
|
-
"id": "replica-1",
|
|
160
|
-
"status": "running",
|
|
161
|
-
"started_at": "2023-01-01T00:00:00+00:00"
|
|
162
|
-
}
|
|
163
|
-
]
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
# Sample environment variables data
|
|
168
|
-
ENV_VARS_DATA = [{
|
|
169
|
-
"container_name": CONTAINER_NAME,
|
|
170
|
-
"env": [
|
|
171
|
-
{
|
|
172
|
-
"name": ENV_VAR_NAME,
|
|
173
|
-
"value_or_reference_to_secret": ENV_VAR_VALUE,
|
|
174
|
-
"type": "plain"
|
|
175
|
-
}
|
|
176
|
-
]
|
|
177
|
-
}]
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
class TestContainersService:
|
|
181
|
-
@pytest.fixture
|
|
182
|
-
def containers_service(self, http_client):
|
|
183
|
-
return ContainersService(http_client)
|
|
184
|
-
|
|
185
|
-
@pytest.fixture
|
|
186
|
-
def deployments_endpoint(self, http_client):
|
|
187
|
-
return http_client._base_url + CONTAINER_DEPLOYMENTS_ENDPOINT
|
|
188
|
-
|
|
189
|
-
@pytest.fixture
|
|
190
|
-
def compute_resources_endpoint(self, http_client):
|
|
191
|
-
return http_client._base_url + SERVERLESS_COMPUTE_RESOURCES_ENDPOINT
|
|
192
|
-
|
|
193
|
-
@pytest.fixture
|
|
194
|
-
def secrets_endpoint(self, http_client):
|
|
195
|
-
return http_client._base_url + SECRETS_ENDPOINT
|
|
196
|
-
|
|
197
|
-
@pytest.fixture
|
|
198
|
-
def registry_credentials_endpoint(self, http_client):
|
|
199
|
-
return http_client._base_url + CONTAINER_REGISTRY_CREDENTIALS_ENDPOINT
|
|
200
|
-
|
|
201
|
-
@responses.activate
|
|
202
|
-
def test_get_deployments(self, containers_service, deployments_endpoint):
|
|
203
|
-
# arrange - add response mock
|
|
204
|
-
responses.add(
|
|
205
|
-
responses.GET,
|
|
206
|
-
deployments_endpoint,
|
|
207
|
-
json=[DEPLOYMENT_DATA],
|
|
208
|
-
status=200
|
|
209
|
-
)
|
|
210
|
-
|
|
211
|
-
# act
|
|
212
|
-
deployments = containers_service.get_deployments()
|
|
213
|
-
deployment = deployments[0]
|
|
214
|
-
|
|
215
|
-
# assert
|
|
216
|
-
assert type(deployments) == list
|
|
217
|
-
assert len(deployments) == 1
|
|
218
|
-
assert type(deployment) == Deployment
|
|
219
|
-
assert deployment.name == DEPLOYMENT_NAME
|
|
220
|
-
assert len(deployment.containers) == 1
|
|
221
|
-
assert type(deployment.containers[0]) == Container
|
|
222
|
-
assert type(deployment.compute) == ComputeResource
|
|
223
|
-
assert deployment.compute.name == COMPUTE_RESOURCE_NAME_GENERAL_COMPUTE
|
|
224
|
-
assert responses.assert_call_count(deployments_endpoint, 1) is True
|
|
225
|
-
|
|
226
|
-
@responses.activate
|
|
227
|
-
def test_get_deployment_by_name(self, containers_service, deployments_endpoint):
|
|
228
|
-
# arrange - add response mock
|
|
229
|
-
url = f"{deployments_endpoint}/{DEPLOYMENT_NAME}"
|
|
230
|
-
responses.add(
|
|
231
|
-
responses.GET,
|
|
232
|
-
url,
|
|
233
|
-
json=DEPLOYMENT_DATA,
|
|
234
|
-
status=200
|
|
235
|
-
)
|
|
236
|
-
|
|
237
|
-
# act
|
|
238
|
-
deployment = containers_service.get_deployment_by_name(DEPLOYMENT_NAME)
|
|
239
|
-
|
|
240
|
-
# assert
|
|
241
|
-
assert type(deployment) == Deployment
|
|
242
|
-
assert deployment.name == DEPLOYMENT_NAME
|
|
243
|
-
assert len(deployment.containers) == 1
|
|
244
|
-
assert deployment.containers[0].name == CONTAINER_NAME
|
|
245
|
-
assert deployment.compute.name == COMPUTE_RESOURCE_NAME_GENERAL_COMPUTE
|
|
246
|
-
assert responses.assert_call_count(url, 1) is True
|
|
247
|
-
|
|
248
|
-
@responses.activate
|
|
249
|
-
def test_get_deployment_by_name_error(self, containers_service, deployments_endpoint):
|
|
250
|
-
# arrange - add response mock
|
|
251
|
-
url = f"{deployments_endpoint}/nonexistent"
|
|
252
|
-
responses.add(
|
|
253
|
-
responses.GET,
|
|
254
|
-
url,
|
|
255
|
-
json={"code": INVALID_REQUEST, "message": INVALID_REQUEST_MESSAGE},
|
|
256
|
-
status=400
|
|
257
|
-
)
|
|
258
|
-
|
|
259
|
-
# act
|
|
260
|
-
with pytest.raises(APIException) as excinfo:
|
|
261
|
-
containers_service.get_deployment_by_name("nonexistent")
|
|
262
|
-
|
|
263
|
-
# assert
|
|
264
|
-
assert excinfo.value.code == INVALID_REQUEST
|
|
265
|
-
assert excinfo.value.message == INVALID_REQUEST_MESSAGE
|
|
266
|
-
assert responses.assert_call_count(url, 1) is True
|
|
267
|
-
|
|
268
|
-
@responses.activate
|
|
269
|
-
def test_create_deployment(self, containers_service, deployments_endpoint):
|
|
270
|
-
# arrange - add response mock
|
|
271
|
-
responses.add(
|
|
272
|
-
responses.POST,
|
|
273
|
-
deployments_endpoint,
|
|
274
|
-
json=DEPLOYMENT_DATA,
|
|
275
|
-
status=200
|
|
276
|
-
)
|
|
277
|
-
|
|
278
|
-
container = Container(
|
|
279
|
-
image="nginx:latest",
|
|
280
|
-
exposed_port=80,
|
|
281
|
-
healthcheck=HealthcheckSettings(
|
|
282
|
-
enabled=True, port=80, path="/health"),
|
|
283
|
-
entrypoint_overrides=EntrypointOverridesSettings(enabled=False),
|
|
284
|
-
env=[EnvVar(
|
|
285
|
-
name="ENV_VAR1", value_or_reference_to_secret="value1", type=EnvVarType.PLAIN)],
|
|
286
|
-
volume_mounts=[VolumeMount(
|
|
287
|
-
type=VolumeMountType.SCRATCH, mount_path="/data")]
|
|
288
|
-
)
|
|
289
|
-
|
|
290
|
-
compute = ComputeResource(
|
|
291
|
-
name=COMPUTE_RESOURCE_NAME_GENERAL_COMPUTE, size=1)
|
|
292
|
-
|
|
293
|
-
container_registry_settings = ContainerRegistrySettings(
|
|
294
|
-
is_private=False)
|
|
295
|
-
|
|
296
|
-
# create deployment object
|
|
297
|
-
deployment = Deployment(
|
|
298
|
-
name=DEPLOYMENT_NAME,
|
|
299
|
-
container_registry_settings=container_registry_settings,
|
|
300
|
-
containers=[container],
|
|
301
|
-
compute=compute,
|
|
302
|
-
is_spot=False
|
|
303
|
-
)
|
|
304
|
-
|
|
305
|
-
# act
|
|
306
|
-
created_deployment = containers_service.create_deployment(deployment)
|
|
307
|
-
|
|
308
|
-
# assert
|
|
309
|
-
assert type(created_deployment) == Deployment
|
|
310
|
-
assert created_deployment.name == DEPLOYMENT_NAME
|
|
311
|
-
assert len(created_deployment.containers) == 1
|
|
312
|
-
assert created_deployment.containers[0].name == CONTAINER_NAME
|
|
313
|
-
assert created_deployment.compute.name == COMPUTE_RESOURCE_NAME_GENERAL_COMPUTE
|
|
314
|
-
assert responses.assert_call_count(deployments_endpoint, 1) is True
|
|
315
|
-
|
|
316
|
-
@responses.activate
|
|
317
|
-
def test_update_deployment(self, containers_service, deployments_endpoint):
|
|
318
|
-
# arrange - add response mock
|
|
319
|
-
url = f"{deployments_endpoint}/{DEPLOYMENT_NAME}"
|
|
320
|
-
responses.add(
|
|
321
|
-
responses.PATCH,
|
|
322
|
-
url,
|
|
323
|
-
json=DEPLOYMENT_DATA,
|
|
324
|
-
status=200
|
|
325
|
-
)
|
|
326
|
-
|
|
327
|
-
# create deployment object
|
|
328
|
-
container = Container(
|
|
329
|
-
name=CONTAINER_NAME,
|
|
330
|
-
image="nginx:latest",
|
|
331
|
-
exposed_port=80
|
|
332
|
-
)
|
|
333
|
-
|
|
334
|
-
container_registry_settings = ContainerRegistrySettings(
|
|
335
|
-
is_private=False)
|
|
336
|
-
|
|
337
|
-
compute = ComputeResource(
|
|
338
|
-
name=COMPUTE_RESOURCE_NAME_GENERAL_COMPUTE, size=1)
|
|
339
|
-
|
|
340
|
-
deployment = Deployment(
|
|
341
|
-
name=DEPLOYMENT_NAME,
|
|
342
|
-
container_registry_settings=container_registry_settings,
|
|
343
|
-
containers=[container],
|
|
344
|
-
compute=compute
|
|
345
|
-
)
|
|
346
|
-
|
|
347
|
-
# act
|
|
348
|
-
updated_deployment = containers_service.update_deployment(
|
|
349
|
-
DEPLOYMENT_NAME, deployment)
|
|
350
|
-
|
|
351
|
-
# assert
|
|
352
|
-
assert type(updated_deployment) == Deployment
|
|
353
|
-
assert updated_deployment.name == DEPLOYMENT_NAME
|
|
354
|
-
assert len(updated_deployment.containers) == 1
|
|
355
|
-
assert updated_deployment.containers[0].name == CONTAINER_NAME
|
|
356
|
-
assert updated_deployment.compute.name == COMPUTE_RESOURCE_NAME_GENERAL_COMPUTE
|
|
357
|
-
assert responses.assert_call_count(url, 1) is True
|
|
358
|
-
|
|
359
|
-
@responses.activate
|
|
360
|
-
def test_delete_deployment(self, containers_service, deployments_endpoint):
|
|
361
|
-
# arrange - add response mock
|
|
362
|
-
url = f"{deployments_endpoint}/{DEPLOYMENT_NAME}"
|
|
363
|
-
responses.add(
|
|
364
|
-
responses.DELETE,
|
|
365
|
-
url,
|
|
366
|
-
status=204
|
|
367
|
-
)
|
|
368
|
-
|
|
369
|
-
# act
|
|
370
|
-
containers_service.delete_deployment(DEPLOYMENT_NAME)
|
|
371
|
-
|
|
372
|
-
# assert
|
|
373
|
-
assert responses.assert_call_count(url, 1) is True
|
|
374
|
-
|
|
375
|
-
@responses.activate
|
|
376
|
-
def test_get_deployment_status(self, containers_service, deployments_endpoint):
|
|
377
|
-
# arrange - add response mock
|
|
378
|
-
url = f"{deployments_endpoint}/{DEPLOYMENT_NAME}/status"
|
|
379
|
-
responses.add(
|
|
380
|
-
responses.GET,
|
|
381
|
-
url,
|
|
382
|
-
json=DEPLOYMENT_STATUS_DATA,
|
|
383
|
-
status=200
|
|
384
|
-
)
|
|
385
|
-
|
|
386
|
-
# act
|
|
387
|
-
status = containers_service.get_deployment_status(DEPLOYMENT_NAME)
|
|
388
|
-
|
|
389
|
-
# assert
|
|
390
|
-
assert status == ContainerDeploymentStatus.HEALTHY
|
|
391
|
-
assert responses.assert_call_count(url, 1) is True
|
|
392
|
-
|
|
393
|
-
@responses.activate
|
|
394
|
-
def test_restart_deployment(self, containers_service, deployments_endpoint):
|
|
395
|
-
# arrange - add response mock
|
|
396
|
-
url = f"{deployments_endpoint}/{DEPLOYMENT_NAME}/restart"
|
|
397
|
-
responses.add(
|
|
398
|
-
responses.POST,
|
|
399
|
-
url,
|
|
400
|
-
status=204
|
|
401
|
-
)
|
|
402
|
-
|
|
403
|
-
# act
|
|
404
|
-
containers_service.restart_deployment(DEPLOYMENT_NAME)
|
|
405
|
-
|
|
406
|
-
# assert
|
|
407
|
-
assert responses.assert_call_count(url, 1) is True
|
|
408
|
-
|
|
409
|
-
@responses.activate
|
|
410
|
-
def test_get_deployment_scaling_options(self, containers_service, deployments_endpoint):
|
|
411
|
-
# arrange - add response mock
|
|
412
|
-
url = f"{deployments_endpoint}/{DEPLOYMENT_NAME}/scaling"
|
|
413
|
-
responses.add(
|
|
414
|
-
responses.GET,
|
|
415
|
-
url,
|
|
416
|
-
json=DEPLOYMENT_DATA["scaling"],
|
|
417
|
-
status=200
|
|
418
|
-
)
|
|
419
|
-
|
|
420
|
-
# act
|
|
421
|
-
scaling_options = containers_service.get_deployment_scaling_options(
|
|
422
|
-
DEPLOYMENT_NAME)
|
|
423
|
-
|
|
424
|
-
# assert
|
|
425
|
-
assert isinstance(scaling_options, ScalingOptions)
|
|
426
|
-
assert scaling_options.min_replica_count == 1
|
|
427
|
-
assert scaling_options.max_replica_count == 3
|
|
428
|
-
assert responses.assert_call_count(url, 1) is True
|
|
429
|
-
|
|
430
|
-
@responses.activate
|
|
431
|
-
def test_update_deployment_scaling_options(self, containers_service, deployments_endpoint):
|
|
432
|
-
# arrange - add response mock
|
|
433
|
-
url = f"{deployments_endpoint}/{DEPLOYMENT_NAME}/scaling"
|
|
434
|
-
responses.add(
|
|
435
|
-
responses.PATCH,
|
|
436
|
-
url,
|
|
437
|
-
json=DEPLOYMENT_DATA["scaling"],
|
|
438
|
-
status=200
|
|
439
|
-
)
|
|
440
|
-
|
|
441
|
-
# create scaling options object
|
|
442
|
-
scaling_options = ScalingOptions(
|
|
443
|
-
min_replica_count=1,
|
|
444
|
-
max_replica_count=5,
|
|
445
|
-
scale_down_policy=ScalingPolicy(delay_seconds=300),
|
|
446
|
-
scale_up_policy=ScalingPolicy(delay_seconds=60),
|
|
447
|
-
queue_message_ttl_seconds=3600,
|
|
448
|
-
concurrent_requests_per_replica=10,
|
|
449
|
-
scaling_triggers=ScalingTriggers(
|
|
450
|
-
queue_load=QueueLoadScalingTrigger(threshold=0.75),
|
|
451
|
-
cpu_utilization=UtilizationScalingTrigger(
|
|
452
|
-
enabled=True, threshold=0.8),
|
|
453
|
-
gpu_utilization=UtilizationScalingTrigger(enabled=False)
|
|
454
|
-
)
|
|
455
|
-
)
|
|
456
|
-
|
|
457
|
-
# act
|
|
458
|
-
updated_scaling = containers_service.update_deployment_scaling_options(
|
|
459
|
-
DEPLOYMENT_NAME, scaling_options)
|
|
460
|
-
|
|
461
|
-
# assert
|
|
462
|
-
assert isinstance(updated_scaling, ScalingOptions)
|
|
463
|
-
assert updated_scaling.min_replica_count == 1
|
|
464
|
-
assert updated_scaling.max_replica_count == 3
|
|
465
|
-
assert responses.assert_call_count(url, 1) is True
|
|
466
|
-
|
|
467
|
-
@responses.activate
|
|
468
|
-
def test_get_deployment_replicas(self, containers_service, deployments_endpoint):
|
|
469
|
-
# arrange - add response mock
|
|
470
|
-
url = f"{deployments_endpoint}/{DEPLOYMENT_NAME}/replicas"
|
|
471
|
-
responses.add(
|
|
472
|
-
responses.GET,
|
|
473
|
-
url,
|
|
474
|
-
json=REPLICAS_DATA,
|
|
475
|
-
status=200
|
|
476
|
-
)
|
|
477
|
-
|
|
478
|
-
# act
|
|
479
|
-
replicas = containers_service.get_deployment_replicas(DEPLOYMENT_NAME)
|
|
480
|
-
|
|
481
|
-
# assert
|
|
482
|
-
assert len(replicas) == 1
|
|
483
|
-
assert replicas[0] == ReplicaInfo(
|
|
484
|
-
"replica-1", "running", "2023-01-01T00:00:00+00:00")
|
|
485
|
-
assert responses.assert_call_count(url, 1) is True
|
|
486
|
-
|
|
487
|
-
@responses.activate
|
|
488
|
-
def test_purge_deployment_queue(self, containers_service, deployments_endpoint):
|
|
489
|
-
# arrange - add response mock
|
|
490
|
-
url = f"{deployments_endpoint}/{DEPLOYMENT_NAME}/purge-queue"
|
|
491
|
-
responses.add(
|
|
492
|
-
responses.POST,
|
|
493
|
-
url,
|
|
494
|
-
status=204
|
|
495
|
-
)
|
|
496
|
-
|
|
497
|
-
# act
|
|
498
|
-
containers_service.purge_deployment_queue(DEPLOYMENT_NAME)
|
|
499
|
-
|
|
500
|
-
# assert
|
|
501
|
-
assert responses.assert_call_count(url, 1) is True
|
|
502
|
-
|
|
503
|
-
@responses.activate
|
|
504
|
-
def test_pause_deployment(self, containers_service, deployments_endpoint):
|
|
505
|
-
# arrange - add response mock
|
|
506
|
-
url = f"{deployments_endpoint}/{DEPLOYMENT_NAME}/pause"
|
|
507
|
-
responses.add(
|
|
508
|
-
responses.POST,
|
|
509
|
-
url,
|
|
510
|
-
status=204
|
|
511
|
-
)
|
|
512
|
-
|
|
513
|
-
# act
|
|
514
|
-
containers_service.pause_deployment(DEPLOYMENT_NAME)
|
|
515
|
-
|
|
516
|
-
# assert
|
|
517
|
-
assert responses.assert_call_count(url, 1) is True
|
|
518
|
-
|
|
519
|
-
@responses.activate
|
|
520
|
-
def test_resume_deployment(self, containers_service, deployments_endpoint):
|
|
521
|
-
# arrange - add response mock
|
|
522
|
-
url = f"{deployments_endpoint}/{DEPLOYMENT_NAME}/resume"
|
|
523
|
-
responses.add(
|
|
524
|
-
responses.POST,
|
|
525
|
-
url,
|
|
526
|
-
status=204
|
|
527
|
-
)
|
|
528
|
-
|
|
529
|
-
# act
|
|
530
|
-
containers_service.resume_deployment(DEPLOYMENT_NAME)
|
|
531
|
-
|
|
532
|
-
# assert
|
|
533
|
-
assert responses.assert_call_count(url, 1) is True
|
|
534
|
-
|
|
535
|
-
@responses.activate
|
|
536
|
-
def test_get_deployment_environment_variables(self, containers_service, deployments_endpoint):
|
|
537
|
-
# arrange - add response mock
|
|
538
|
-
url = f"{deployments_endpoint}/{DEPLOYMENT_NAME}/environment-variables"
|
|
539
|
-
responses.add(
|
|
540
|
-
responses.GET,
|
|
541
|
-
url,
|
|
542
|
-
json=ENV_VARS_DATA,
|
|
543
|
-
status=200
|
|
544
|
-
)
|
|
545
|
-
|
|
546
|
-
# act
|
|
547
|
-
env_vars = containers_service.get_deployment_environment_variables(
|
|
548
|
-
DEPLOYMENT_NAME)
|
|
549
|
-
|
|
550
|
-
# assert
|
|
551
|
-
assert env_vars[CONTAINER_NAME] == [EnvVar(
|
|
552
|
-
name=ENV_VAR_NAME,
|
|
553
|
-
value_or_reference_to_secret=ENV_VAR_VALUE,
|
|
554
|
-
type=EnvVarType.PLAIN
|
|
555
|
-
)]
|
|
556
|
-
assert responses.assert_call_count(url, 1) is True
|
|
557
|
-
|
|
558
|
-
@responses.activate
|
|
559
|
-
def test_add_deployment_environment_variables(self, containers_service, deployments_endpoint):
|
|
560
|
-
# arrange - add response mock
|
|
561
|
-
url = f"{deployments_endpoint}/{DEPLOYMENT_NAME}/environment-variables"
|
|
562
|
-
responses.add(
|
|
563
|
-
responses.POST,
|
|
564
|
-
url,
|
|
565
|
-
json=ENV_VARS_DATA,
|
|
566
|
-
status=200
|
|
567
|
-
)
|
|
568
|
-
|
|
569
|
-
# act
|
|
570
|
-
env_vars = [EnvVar(
|
|
571
|
-
name=ENV_VAR_NAME,
|
|
572
|
-
value_or_reference_to_secret=ENV_VAR_VALUE,
|
|
573
|
-
type=EnvVarType.PLAIN
|
|
574
|
-
)]
|
|
575
|
-
result = containers_service.add_deployment_environment_variables(
|
|
576
|
-
DEPLOYMENT_NAME, CONTAINER_NAME, env_vars)
|
|
577
|
-
|
|
578
|
-
# assert
|
|
579
|
-
assert result[CONTAINER_NAME] == [EnvVar(
|
|
580
|
-
name=ENV_VAR_NAME,
|
|
581
|
-
value_or_reference_to_secret=ENV_VAR_VALUE,
|
|
582
|
-
type=EnvVarType.PLAIN
|
|
583
|
-
)]
|
|
584
|
-
assert responses.assert_call_count(url, 1) is True
|
|
585
|
-
|
|
586
|
-
@responses.activate
|
|
587
|
-
def test_update_deployment_environment_variables(self, containers_service, deployments_endpoint):
|
|
588
|
-
# arrange - add response mock
|
|
589
|
-
url = f"{deployments_endpoint}/{DEPLOYMENT_NAME}/environment-variables"
|
|
590
|
-
responses.add(
|
|
591
|
-
responses.PATCH,
|
|
592
|
-
url,
|
|
593
|
-
json=ENV_VARS_DATA[0],
|
|
594
|
-
status=200
|
|
595
|
-
)
|
|
596
|
-
|
|
597
|
-
# act
|
|
598
|
-
env_vars = [EnvVar(
|
|
599
|
-
name=ENV_VAR_NAME,
|
|
600
|
-
value_or_reference_to_secret=ENV_VAR_VALUE,
|
|
601
|
-
type=EnvVarType.PLAIN
|
|
602
|
-
)]
|
|
603
|
-
result = containers_service.update_deployment_environment_variables(
|
|
604
|
-
DEPLOYMENT_NAME, CONTAINER_NAME, env_vars)
|
|
605
|
-
|
|
606
|
-
# assert
|
|
607
|
-
assert result[CONTAINER_NAME] == [EnvVar(
|
|
608
|
-
name=ENV_VAR_NAME,
|
|
609
|
-
value_or_reference_to_secret=ENV_VAR_VALUE,
|
|
610
|
-
type=EnvVarType.PLAIN
|
|
611
|
-
)]
|
|
612
|
-
assert responses.assert_call_count(url, 1) is True
|
|
613
|
-
|
|
614
|
-
@responses.activate
|
|
615
|
-
def test_delete_deployment_environment_variables(self, containers_service, deployments_endpoint):
|
|
616
|
-
# arrange - add response mock
|
|
617
|
-
url = f"{deployments_endpoint}/{DEPLOYMENT_NAME}/environment-variables"
|
|
618
|
-
responses.add(
|
|
619
|
-
responses.DELETE,
|
|
620
|
-
url,
|
|
621
|
-
json=ENV_VARS_DATA,
|
|
622
|
-
status=200
|
|
623
|
-
)
|
|
624
|
-
|
|
625
|
-
# act
|
|
626
|
-
result = containers_service.delete_deployment_environment_variables(
|
|
627
|
-
DEPLOYMENT_NAME, CONTAINER_NAME, ["random-env-var-name"])
|
|
628
|
-
|
|
629
|
-
# assert
|
|
630
|
-
assert result == {CONTAINER_NAME: [EnvVar(
|
|
631
|
-
name=ENV_VAR_NAME,
|
|
632
|
-
value_or_reference_to_secret=ENV_VAR_VALUE,
|
|
633
|
-
type=EnvVarType.PLAIN
|
|
634
|
-
)]}
|
|
635
|
-
assert responses.assert_call_count(url, 1) is True
|
|
636
|
-
|
|
637
|
-
@responses.activate
|
|
638
|
-
def test_get_compute_resources(self, containers_service, compute_resources_endpoint):
|
|
639
|
-
# arrange - add response mock
|
|
640
|
-
responses.add(
|
|
641
|
-
responses.GET,
|
|
642
|
-
compute_resources_endpoint,
|
|
643
|
-
# Wrap in list to simulate resource groups
|
|
644
|
-
json=[COMPUTE_RESOURCES_DATA],
|
|
645
|
-
status=200
|
|
646
|
-
)
|
|
647
|
-
|
|
648
|
-
# act
|
|
649
|
-
resources = containers_service.get_compute_resources()
|
|
650
|
-
|
|
651
|
-
# assert
|
|
652
|
-
assert type(resources) == list
|
|
653
|
-
assert len(resources) == 2
|
|
654
|
-
assert type(resources[0]) == ComputeResource
|
|
655
|
-
assert resources[0].name == COMPUTE_RESOURCE_NAME_GENERAL_COMPUTE
|
|
656
|
-
assert resources[0].size == 1
|
|
657
|
-
assert resources[0].is_available == True
|
|
658
|
-
assert responses.assert_call_count(
|
|
659
|
-
compute_resources_endpoint, 1) is True
|
|
660
|
-
|
|
661
|
-
@responses.activate
|
|
662
|
-
def test_get_compute_resources_filter_by_size(self, containers_service, compute_resources_endpoint):
|
|
663
|
-
# arrange - add response mock
|
|
664
|
-
responses.add(
|
|
665
|
-
responses.GET,
|
|
666
|
-
compute_resources_endpoint,
|
|
667
|
-
json=[COMPUTE_RESOURCES_DATA],
|
|
668
|
-
status=200
|
|
669
|
-
)
|
|
670
|
-
|
|
671
|
-
# act
|
|
672
|
-
resources = containers_service.get_compute_resources(size=4)
|
|
673
|
-
|
|
674
|
-
# assert
|
|
675
|
-
assert type(resources) == list
|
|
676
|
-
assert len(resources) == 1
|
|
677
|
-
assert type(resources[0]) == ComputeResource
|
|
678
|
-
assert resources[0].name == COMPUTE_RESOURCE_NAME_H100
|
|
679
|
-
assert resources[0].size == 4
|
|
680
|
-
assert resources[0].is_available == True
|
|
681
|
-
assert responses.assert_call_count(
|
|
682
|
-
compute_resources_endpoint, 1) is True
|
|
683
|
-
|
|
684
|
-
@responses.activate
|
|
685
|
-
def test_get_compute_resources_filter_by_availability(self, containers_service, compute_resources_endpoint):
|
|
686
|
-
# arrange - add response mock
|
|
687
|
-
responses.add(
|
|
688
|
-
responses.GET,
|
|
689
|
-
compute_resources_endpoint,
|
|
690
|
-
json=[COMPUTE_RESOURCES_DATA],
|
|
691
|
-
status=200
|
|
692
|
-
)
|
|
693
|
-
|
|
694
|
-
# act
|
|
695
|
-
resources = containers_service.get_compute_resources(is_available=True)
|
|
696
|
-
|
|
697
|
-
# assert
|
|
698
|
-
assert type(resources) == list
|
|
699
|
-
assert len(resources) == 2
|
|
700
|
-
assert all(r.is_available == True for r in resources)
|
|
701
|
-
assert responses.assert_call_count(
|
|
702
|
-
compute_resources_endpoint, 1) is True
|
|
703
|
-
|
|
704
|
-
@responses.activate
|
|
705
|
-
def test_get_compute_resources_filter_by_size_and_availability(self, containers_service, compute_resources_endpoint):
|
|
706
|
-
# arrange - add response mock
|
|
707
|
-
responses.add(
|
|
708
|
-
responses.GET,
|
|
709
|
-
compute_resources_endpoint,
|
|
710
|
-
json=[COMPUTE_RESOURCES_DATA],
|
|
711
|
-
status=200
|
|
712
|
-
)
|
|
713
|
-
|
|
714
|
-
# act
|
|
715
|
-
resources = containers_service.get_compute_resources(
|
|
716
|
-
size=1, is_available=True)
|
|
717
|
-
|
|
718
|
-
# assert
|
|
719
|
-
assert type(resources) == list
|
|
720
|
-
assert len(resources) == 1
|
|
721
|
-
assert resources[0].name == COMPUTE_RESOURCE_NAME_GENERAL_COMPUTE
|
|
722
|
-
assert resources[0].size == 1
|
|
723
|
-
assert resources[0].is_available == True
|
|
724
|
-
assert responses.assert_call_count(
|
|
725
|
-
compute_resources_endpoint, 1) is True
|
|
726
|
-
|
|
727
|
-
@responses.activate
|
|
728
|
-
def test_get_secrets(self, containers_service, secrets_endpoint):
|
|
729
|
-
# arrange - add response mock
|
|
730
|
-
responses.add(
|
|
731
|
-
responses.GET,
|
|
732
|
-
secrets_endpoint,
|
|
733
|
-
json=SECRETS_DATA,
|
|
734
|
-
status=200
|
|
735
|
-
)
|
|
736
|
-
|
|
737
|
-
# act
|
|
738
|
-
secrets = containers_service.get_secrets()
|
|
739
|
-
|
|
740
|
-
# assert
|
|
741
|
-
assert type(secrets) == list
|
|
742
|
-
assert len(secrets) == 1
|
|
743
|
-
assert type(secrets[0]) == Secret
|
|
744
|
-
assert secrets[0].name == SECRET_NAME
|
|
745
|
-
assert responses.assert_call_count(secrets_endpoint, 1) is True
|
|
746
|
-
|
|
747
|
-
@responses.activate
|
|
748
|
-
def test_create_secret(self, containers_service, secrets_endpoint):
|
|
749
|
-
# arrange - add response mock
|
|
750
|
-
responses.add(
|
|
751
|
-
responses.POST,
|
|
752
|
-
secrets_endpoint,
|
|
753
|
-
status=201,
|
|
754
|
-
match=[
|
|
755
|
-
matchers.json_params_matcher(
|
|
756
|
-
# The test will now fail if the request body doesn't match the expected JSON structure
|
|
757
|
-
{"name": SECRET_NAME, "value": SECRET_VALUE}
|
|
758
|
-
)
|
|
759
|
-
]
|
|
760
|
-
)
|
|
761
|
-
|
|
762
|
-
# act
|
|
763
|
-
containers_service.create_secret(SECRET_NAME, SECRET_VALUE)
|
|
764
|
-
|
|
765
|
-
# assert
|
|
766
|
-
assert responses.assert_call_count(secrets_endpoint, 1) is True
|
|
767
|
-
|
|
768
|
-
@responses.activate
|
|
769
|
-
def test_delete_secret(self, containers_service, secrets_endpoint):
|
|
770
|
-
# arrange - add response mock
|
|
771
|
-
url = f"{secrets_endpoint}/{SECRET_NAME}?force=false"
|
|
772
|
-
responses.add(
|
|
773
|
-
responses.DELETE,
|
|
774
|
-
url,
|
|
775
|
-
status=200
|
|
776
|
-
)
|
|
777
|
-
|
|
778
|
-
# act
|
|
779
|
-
containers_service.delete_secret(SECRET_NAME)
|
|
780
|
-
|
|
781
|
-
# assert
|
|
782
|
-
assert responses.assert_call_count(url, 1) is True
|
|
783
|
-
request = responses.calls[0].request
|
|
784
|
-
assert "force=false" in request.url
|
|
785
|
-
|
|
786
|
-
@responses.activate
|
|
787
|
-
def test_delete_secret_with_force(self, containers_service, secrets_endpoint):
|
|
788
|
-
# arrange
|
|
789
|
-
url = f"{secrets_endpoint}/{SECRET_NAME}?force=true"
|
|
790
|
-
responses.add(
|
|
791
|
-
responses.DELETE,
|
|
792
|
-
url,
|
|
793
|
-
status=200
|
|
794
|
-
)
|
|
795
|
-
|
|
796
|
-
# act
|
|
797
|
-
containers_service.delete_secret(SECRET_NAME, force=True)
|
|
798
|
-
|
|
799
|
-
# assert
|
|
800
|
-
assert responses.assert_call_count(url, 1) is True
|
|
801
|
-
request = responses.calls[0].request
|
|
802
|
-
assert "force=true" in request.url
|
|
803
|
-
|
|
804
|
-
@responses.activate
|
|
805
|
-
def test_get_registry_credentials(self, containers_service, registry_credentials_endpoint):
|
|
806
|
-
# arrange - add response mock
|
|
807
|
-
responses.add(
|
|
808
|
-
responses.GET,
|
|
809
|
-
registry_credentials_endpoint,
|
|
810
|
-
json=REGISTRY_CREDENTIALS_DATA,
|
|
811
|
-
status=200
|
|
812
|
-
)
|
|
813
|
-
|
|
814
|
-
# act
|
|
815
|
-
credentials = containers_service.get_registry_credentials()
|
|
816
|
-
|
|
817
|
-
# assert
|
|
818
|
-
assert type(credentials) == list
|
|
819
|
-
assert len(credentials) == 1
|
|
820
|
-
assert type(credentials[0]) == RegistryCredential
|
|
821
|
-
assert credentials[0].name == REGISTRY_CREDENTIAL_NAME
|
|
822
|
-
assert responses.assert_call_count(
|
|
823
|
-
registry_credentials_endpoint, 1) is True
|
|
824
|
-
|
|
825
|
-
@responses.activate
|
|
826
|
-
def test_add_registry_credentials(self, containers_service, registry_credentials_endpoint):
|
|
827
|
-
USERNAME = "username"
|
|
828
|
-
ACCESS_TOKEN = "token"
|
|
829
|
-
# arrange - add response mock
|
|
830
|
-
responses.add(
|
|
831
|
-
responses.POST,
|
|
832
|
-
registry_credentials_endpoint,
|
|
833
|
-
status=201
|
|
834
|
-
)
|
|
835
|
-
|
|
836
|
-
# act
|
|
837
|
-
creds = DockerHubCredentials(
|
|
838
|
-
name=REGISTRY_CREDENTIAL_NAME,
|
|
839
|
-
username=USERNAME,
|
|
840
|
-
access_token=ACCESS_TOKEN
|
|
841
|
-
)
|
|
842
|
-
containers_service.add_registry_credentials(creds)
|
|
843
|
-
|
|
844
|
-
# assert
|
|
845
|
-
assert responses.assert_call_count(
|
|
846
|
-
registry_credentials_endpoint, 1) is True
|
|
847
|
-
assert responses.calls[0].request.body.decode(
|
|
848
|
-
'utf-8') == '{"name": "test-credential", "type": "dockerhub", "username": "username", "access_token": "token"}'
|
|
849
|
-
|
|
850
|
-
@responses.activate
|
|
851
|
-
def test_add_registry_credentials_github(self, containers_service, registry_credentials_endpoint):
|
|
852
|
-
# arrange
|
|
853
|
-
responses.add(
|
|
854
|
-
responses.POST,
|
|
855
|
-
registry_credentials_endpoint,
|
|
856
|
-
status=201
|
|
857
|
-
)
|
|
858
|
-
|
|
859
|
-
# act
|
|
860
|
-
creds = GithubCredentials(
|
|
861
|
-
name=REGISTRY_CREDENTIAL_NAME,
|
|
862
|
-
username="test-username",
|
|
863
|
-
access_token="test-token"
|
|
864
|
-
)
|
|
865
|
-
containers_service.add_registry_credentials(creds)
|
|
866
|
-
|
|
867
|
-
# assert
|
|
868
|
-
assert responses.assert_call_count(
|
|
869
|
-
registry_credentials_endpoint, 1) is True
|
|
870
|
-
assert responses.calls[0].request.body.decode(
|
|
871
|
-
'utf-8') == '{"name": "test-credential", "type": "ghcr", "username": "test-username", "access_token": "test-token"}'
|
|
872
|
-
|
|
873
|
-
@responses.activate
|
|
874
|
-
def test_add_registry_credentials_gcr(self, containers_service, registry_credentials_endpoint):
|
|
875
|
-
# arrange
|
|
876
|
-
responses.add(
|
|
877
|
-
responses.POST,
|
|
878
|
-
registry_credentials_endpoint,
|
|
879
|
-
status=201
|
|
880
|
-
)
|
|
881
|
-
|
|
882
|
-
# act
|
|
883
|
-
service_account_key = '{"key": "value"}'
|
|
884
|
-
creds = GCRCredentials(
|
|
885
|
-
name=REGISTRY_CREDENTIAL_NAME,
|
|
886
|
-
service_account_key=service_account_key
|
|
887
|
-
)
|
|
888
|
-
containers_service.add_registry_credentials(creds)
|
|
889
|
-
|
|
890
|
-
# assert
|
|
891
|
-
assert responses.assert_call_count(
|
|
892
|
-
registry_credentials_endpoint, 1) is True
|
|
893
|
-
assert responses.calls[0].request.body.decode(
|
|
894
|
-
'utf-8') == '{"name": "test-credential", "type": "gcr", "service_account_key": "{\\"key\\": \\"value\\"}"}'
|
|
895
|
-
|
|
896
|
-
@responses.activate
|
|
897
|
-
def test_add_registry_credentials_aws_ecr(self, containers_service, registry_credentials_endpoint):
|
|
898
|
-
# arrange
|
|
899
|
-
responses.add(
|
|
900
|
-
responses.POST,
|
|
901
|
-
registry_credentials_endpoint,
|
|
902
|
-
status=201
|
|
903
|
-
)
|
|
904
|
-
|
|
905
|
-
# act
|
|
906
|
-
creds = AWSECRCredentials(
|
|
907
|
-
name=REGISTRY_CREDENTIAL_NAME,
|
|
908
|
-
access_key_id="test-key",
|
|
909
|
-
secret_access_key="test-secret",
|
|
910
|
-
region="us-west-2",
|
|
911
|
-
ecr_repo="test.ecr.aws.com"
|
|
912
|
-
)
|
|
913
|
-
containers_service.add_registry_credentials(creds)
|
|
914
|
-
|
|
915
|
-
# assert
|
|
916
|
-
assert responses.assert_call_count(
|
|
917
|
-
registry_credentials_endpoint, 1) is True
|
|
918
|
-
assert responses.calls[0].request.body.decode(
|
|
919
|
-
'utf-8') == '{"name": "test-credential", "type": "aws-ecr", "access_key_id": "test-key", "secret_access_key": "test-secret", "region": "us-west-2", "ecr_repo": "test.ecr.aws.com"}'
|
|
920
|
-
|
|
921
|
-
@responses.activate
|
|
922
|
-
def test_add_registry_credentials_custom(self, containers_service, registry_credentials_endpoint):
|
|
923
|
-
# arrange
|
|
924
|
-
responses.add(
|
|
925
|
-
responses.POST,
|
|
926
|
-
registry_credentials_endpoint,
|
|
927
|
-
status=201
|
|
928
|
-
)
|
|
929
|
-
|
|
930
|
-
# act
|
|
931
|
-
docker_config = '{"auths": {"registry.example.com": {"auth": "base64-encoded"}}}'
|
|
932
|
-
creds = CustomRegistryCredentials(
|
|
933
|
-
name=REGISTRY_CREDENTIAL_NAME,
|
|
934
|
-
docker_config_json=docker_config
|
|
935
|
-
)
|
|
936
|
-
containers_service.add_registry_credentials(creds)
|
|
937
|
-
|
|
938
|
-
# assert
|
|
939
|
-
assert responses.assert_call_count(
|
|
940
|
-
registry_credentials_endpoint, 1) is True
|
|
941
|
-
assert responses.calls[0].request.body.decode(
|
|
942
|
-
'utf-8') == '{"name": "test-credential", "type": "custom", "docker_config_json": "{\\"auths\\": {\\"registry.example.com\\": {\\"auth\\": \\"base64-encoded\\"}}}"}'
|
|
943
|
-
|
|
944
|
-
@responses.activate
|
|
945
|
-
def test_delete_registry_credentials(self, containers_service, registry_credentials_endpoint):
|
|
946
|
-
# arrange - add response mock
|
|
947
|
-
url = f"{registry_credentials_endpoint}/{REGISTRY_CREDENTIAL_NAME}"
|
|
948
|
-
responses.add(
|
|
949
|
-
responses.DELETE,
|
|
950
|
-
url,
|
|
951
|
-
status=200
|
|
952
|
-
)
|
|
953
|
-
|
|
954
|
-
# act
|
|
955
|
-
containers_service.delete_registry_credentials(
|
|
956
|
-
REGISTRY_CREDENTIAL_NAME)
|
|
957
|
-
|
|
958
|
-
# assert
|
|
959
|
-
assert responses.assert_call_count(url, 1) is True
|