Files
wehub-resource-sync e0e362d700
SDK Tests / SDK CI (push) Blocked by required conditions
SDK Tests / changes (push) Successful in 2m29s
Real E2E Tests / changes (push) Successful in 2m29s
SDK Tests / Python SDK Tests (sandbox) (push) Waiting to run
SDK Tests / CLI Quality (push) Waiting to run
SDK Tests / CLI Tests (push) Waiting to run
SDK Tests / Python SDK Quality (code-interpreter) (push) Waiting to run
SDK Tests / Python SDK Quality (sandbox) (push) Waiting to run
SDK Tests / Python SDK Tests (code-interpreter) (push) Waiting to run
SDK Tests / JavaScript SDK Quality And Tests (code-interpreter) (push) Waiting to run
SDK Tests / JavaScript SDK Quality And Tests (sandbox) (push) Waiting to run
SDK Tests / Kotlin SDK Quality And Tests (sandbox) (push) Waiting to run
SDK Tests / Kotlin SDK Quality And Tests (code-interpreter) (push) Waiting to run
SDK Tests / C# SDK Quality And Tests (code-interpreter) (push) Waiting to run
SDK Tests / C# SDK Quality And Tests (sandbox) (push) Waiting to run
SDK Tests / Go SDK Quality And Tests (push) Waiting to run
Deploy Docs Pages / build (push) Has been cancelled
Deploy Docs Pages / deploy (push) Has been cancelled
Real E2E Tests / JavaScript E2E (docker bridge) (push) Has been cancelled
Real E2E Tests / Python E2E (docker bridge) (push) Has been cancelled
Real E2E Tests / Java E2E (docker bridge) (push) Has been cancelled
Real E2E Tests / C# E2E (docker bridge) (push) Has been cancelled
Real E2E Tests / Go E2E (docker bridge) (push) Has been cancelled
Real E2E Tests / Real E2E CI (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:39:33 +08:00

168 lines
6.0 KiB
Python

#
# Copyright 2026 Alibaba Group Holding Ltd.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
from __future__ import annotations
import json
import httpx
import pytest
from opensandbox.adapters.egress_adapter import EgressAdapter
from opensandbox.config import ConnectionConfig
from opensandbox.config.connection_sync import ConnectionConfigSync
from opensandbox.exceptions import SandboxApiException
from opensandbox.models.sandboxes import SandboxEndpoint
from opensandbox.sync.adapters.egress_adapter import EgressAdapterSync
class _CredentialVaultAsyncTransport(httpx.AsyncBaseTransport):
def __init__(self) -> None:
self.requests: list[httpx.Request] = []
async def handle_async_request(self, request: httpx.Request) -> httpx.Response:
self.requests.append(request)
if request.method == "POST" and request.url.path == "/credential-vault":
return httpx.Response(
201,
json={
"revision": 1,
"credentials": [
{"name": "gitlab-token", "sourceType": "inline", "revision": 1}
],
"bindings": [
{
"name": "gitlab-api",
"revision": 1,
"auth": {"type": "apiKey", "name": "PRIVATE-TOKEN"},
"match": {"hosts": ["code.example.com"]},
}
],
},
request=request,
)
if request.method == "PATCH" and request.url.path == "/credential-vault":
return httpx.Response(
200,
json={"revision": 2, "credentials": [], "bindings": []},
request=request,
)
if request.method == "GET" and request.url.path == "/credential-vault/bindings":
return httpx.Response(
200,
json={
"revision": 2,
"bindings": [{"name": "gitlab-api", "revision": 2}],
},
request=request,
)
if request.method == "GET" and request.url.path == "/credential-vault/credentials/missing":
return httpx.Response(404, text="credential not found", request=request)
return httpx.Response(204, request=request)
class _CredentialVaultSyncTransport(httpx.BaseTransport):
def __init__(self) -> None:
self.requests: list[httpx.Request] = []
def handle_request(self, request: httpx.Request) -> httpx.Response:
self.requests.append(request)
if request.method == "GET" and request.url.path == "/credential-vault":
return httpx.Response(
200,
json={"revision": 7, "credentials": [], "bindings": []},
request=request,
)
if request.method == "GET" and request.url.path == "/credential-vault/credentials/missing":
return httpx.Response(404, text="credential not found", request=request)
return httpx.Response(204, request=request)
@pytest.mark.asyncio
async def test_async_credential_vault_create_patch_and_list_bindings() -> None:
transport = _CredentialVaultAsyncTransport()
adapter = EgressAdapter(
ConnectionConfig(transport=transport),
SandboxEndpoint(endpoint="sandbox.internal:18080", headers={"X-Egress": "1"}),
)
state = await adapter.create(
credentials=[
{
"name": "gitlab-token",
"source": {"value": "secret-token"},
}
],
bindings=[
{
"name": "gitlab-api",
"match": {"hosts": ["code.example.com"]},
"auth": {
"type": "apiKey",
"name": "PRIVATE-TOKEN",
"credential": "gitlab-token",
},
}
],
)
assert state.revision == 1
assert state.credentials[0].source_type == "inline"
post_body = json.loads(transport.requests[0].content)
assert post_body["credentials"][0]["source"] == {
"type": "inline",
"value": "secret-token",
}
assert post_body["bindings"][0]["auth"]["type"] == "apiKey"
assert transport.requests[0].headers["X-Egress"] == "1"
patched = await adapter.patch(
expected_revision=1,
credentials={"delete": ["gitlab-token"]},
bindings={"delete": ["gitlab-api"]},
)
assert patched.revision == 2
patch_body = json.loads(transport.requests[1].content)
assert patch_body == {
"expectedRevision": 1,
"credentials": {"delete": ["gitlab-token"]},
"bindings": {"delete": ["gitlab-api"]},
}
bindings = await adapter.list_bindings()
assert bindings[0].name == "gitlab-api"
with pytest.raises(SandboxApiException) as exc_info:
await adapter.get_credential("missing")
assert exc_info.value.status_code == 404
def test_sync_credential_vault_get_and_delete() -> None:
transport = _CredentialVaultSyncTransport()
adapter = EgressAdapterSync(
ConnectionConfigSync(transport=transport),
SandboxEndpoint(endpoint="sandbox.internal:18080"),
)
state = adapter.get()
assert state.revision == 7
adapter.delete()
assert [request.method for request in transport.requests] == ["GET", "DELETE"]
with pytest.raises(SandboxApiException) as exc_info:
adapter.get_credential("missing")
assert exc_info.value.status_code == 404