Files
wehub-resource-sync e0e362d700
SDK Tests / changes (push) Successful in 2m29s
Real E2E Tests / changes (push) Successful in 2m29s
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
SDK Tests / SDK CI (push) Has been cancelled
SDK Tests / CLI Tests (push) Has been cancelled
SDK Tests / Python SDK Quality (code-interpreter) (push) Has been cancelled
SDK Tests / Python SDK Quality (sandbox) (push) Has been cancelled
SDK Tests / Python SDK Tests (code-interpreter) (push) Has been cancelled
SDK Tests / JavaScript SDK Quality And Tests (code-interpreter) (push) Has been cancelled
SDK Tests / JavaScript SDK Quality And Tests (sandbox) (push) Has been cancelled
SDK Tests / Python SDK Tests (sandbox) (push) Has been cancelled
SDK Tests / CLI Quality (push) Has been cancelled
SDK Tests / Kotlin SDK Quality And Tests (sandbox) (push) Has been cancelled
SDK Tests / Kotlin SDK Quality And Tests (code-interpreter) (push) Has been cancelled
SDK Tests / C# SDK Quality And Tests (code-interpreter) (push) Has been cancelled
SDK Tests / C# SDK Quality And Tests (sandbox) (push) Has been cancelled
SDK Tests / Go SDK Quality And Tests (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:39:33 +08:00

217 lines
7.4 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
from typing import Any, Optional
from opensandbox_server.api.schema import ImageSpec, PlatformSpec, Sandbox, SandboxStatus
from opensandbox_server.extensions import extract_extensions_from_mapping
from opensandbox_server.services.constants import SANDBOX_ID_LABEL, SANDBOX_SNAPSHOT_ID_LABEL
def _is_opensandbox_label(label_key: str) -> bool:
return label_key.split("/", 1)[0] == "opensandbox.io"
def _build_sandbox_from_workload(workload: Any, workload_provider: Any) -> Sandbox:
if isinstance(workload, dict):
metadata = workload.get("metadata", {})
spec = workload.get("spec", {})
labels = metadata.get("labels", {})
annotations = metadata.get("annotations", {})
creation_timestamp = metadata.get("creationTimestamp")
else:
metadata = workload.metadata
spec = workload.spec
labels = metadata.labels or {}
annotations = metadata.annotations or {}
creation_timestamp = metadata.creation_timestamp
sandbox_id = labels.get(SANDBOX_ID_LABEL, "")
snapshot_id = labels.get(SANDBOX_SNAPSHOT_ID_LABEL)
expires_at = workload_provider.get_expiration(workload)
status_info = workload_provider.get_status(workload)
user_metadata = {
k: v for k, v in labels.items() if not _is_opensandbox_label(k)
}
image_uri = ""
entrypoint = []
if isinstance(workload, dict):
template = spec.get("template") or spec.get("podTemplate") or {}
pod_spec = template.get("spec", {})
containers = pod_spec.get("containers", [])
if containers:
container = containers[0]
image_uri = container.get("image", "")
entrypoint = container.get("command", [])
elif hasattr(spec, "containers") and spec.containers:
container = spec.containers[0]
image_uri = container.image or ""
entrypoint = container.command or []
image_spec = None
if not snapshot_id:
image_spec = ImageSpec(uri=image_uri) if image_uri else ImageSpec(uri="unknown")
platform_spec = _extract_platform_from_workload(workload)
return Sandbox(
id=sandbox_id,
status=SandboxStatus(
state=status_info["state"],
reason=status_info["reason"],
message=status_info["message"],
last_transition_at=status_info["last_transition_at"],
),
created_at=creation_timestamp,
expires_at=expires_at,
metadata=user_metadata if user_metadata else None,
extensions=extract_extensions_from_mapping(annotations),
image=image_spec,
snapshotId=snapshot_id,
entrypoint=entrypoint,
platform=platform_spec,
)
def _extract_platform_from_workload(workload: Any) -> Optional[PlatformSpec]:
if isinstance(workload, dict):
spec = workload.get("spec") or {}
template = spec.get("template") or {}
pod_template = spec.get("podTemplate") or {}
pod_spec = (
(template.get("spec") if isinstance(template, dict) else None)
or (pod_template.get("spec") if isinstance(pod_template, dict) else None)
or {}
)
else:
spec = getattr(workload, "spec", None)
template = getattr(spec, "template", None)
pod_template = getattr(spec, "pod_template", None)
pod_spec = (
getattr(template, "spec", None)
or getattr(pod_template, "spec", None)
or {}
)
node_selector = (
pod_spec.get("nodeSelector", {})
if isinstance(pod_spec, dict)
else getattr(pod_spec, "node_selector", {}) or {}
)
if not isinstance(node_selector, dict):
return None
os_value = node_selector.get("kubernetes.io/os")
arch_value = node_selector.get("kubernetes.io/arch")
os_constraint = os_value if isinstance(os_value, str) and os_value else None
arch_constraint = arch_value if isinstance(arch_value, str) and arch_value else None
affinity = (
pod_spec.get("affinity")
if isinstance(pod_spec, dict)
else getattr(pod_spec, "affinity", None)
)
if os_constraint is None:
os_constraint = _extract_platform_value_from_affinity(
affinity,
"kubernetes.io/os",
)
if arch_constraint is None:
arch_constraint = _extract_platform_value_from_affinity(
affinity,
"kubernetes.io/arch",
)
if os_constraint and arch_constraint:
return PlatformSpec(os=os_constraint, arch=arch_constraint)
return None
def _extract_platform_value_from_affinity(
affinity: Any,
key: str,
) -> Optional[str]:
if affinity is None:
return None
node_affinity = (
affinity.get("nodeAffinity")
if isinstance(affinity, dict)
else getattr(affinity, "node_affinity", None)
)
if node_affinity is None:
return None
required = (
node_affinity.get("requiredDuringSchedulingIgnoredDuringExecution")
if isinstance(node_affinity, dict)
else getattr(
node_affinity,
"required_during_scheduling_ignored_during_execution",
None,
)
)
if required is None:
return None
terms = (
required.get("nodeSelectorTerms", [])
if isinstance(required, dict)
else getattr(required, "node_selector_terms", []) or []
)
if not isinstance(terms, list) or not terms:
return None
inferred: Optional[str] = None
for term in terms:
expressions = (
term.get("matchExpressions", [])
if isinstance(term, dict)
else getattr(term, "match_expressions", []) or []
)
if not isinstance(expressions, list):
return None
term_value: Optional[str] = None
for expr in expressions:
expr_key = (
expr.get("key")
if isinstance(expr, dict)
else getattr(expr, "key", None)
)
if expr_key != key:
continue
operator = (
expr.get("operator")
if isinstance(expr, dict)
else getattr(expr, "operator", None)
)
values = (
expr.get("values", [])
if isinstance(expr, dict)
else getattr(expr, "values", []) or []
)
if operator != "In" or not isinstance(values, list) or len(values) != 1:
return None
value = values[0]
if not isinstance(value, str) or not value:
return None
term_value = value
break
if term_value is None:
return None
if inferred is None:
inferred = term_value
elif inferred != term_value:
return None
return inferred