diff --git a/apps/web/src/i18n/locales/en/core-errors.ts b/apps/web/src/i18n/locales/en/core-errors.ts index 77b2cd7f2..a667b3b69 100644 --- a/apps/web/src/i18n/locales/en/core-errors.ts +++ b/apps/web/src/i18n/locales/en/core-errors.ts @@ -37,7 +37,7 @@ export const coreErrors = { "sandbox_operation_unsupported": "The selected sandbox provider does not support this operation.", "environment_unavailable": "The Session's environment is no longer available.", "execution_unavailable": "Execution is temporarily unavailable. Try again later.", - "runtime_history_unavailable": "Runtime history is unavailable on this Core.", + "runtime_history_unavailable": "Runtime history is temporarily unavailable. Try again later.", "runtime_history_unsupported": "Runtime history is not supported for this Session.", "core_metrics_unavailable": "Core metrics could not be read. Try again later.", "file_transfer_unavailable": "The file transfer is unavailable. Try again later.", diff --git a/apps/web/src/i18n/locales/zh-CN/core-errors.ts b/apps/web/src/i18n/locales/zh-CN/core-errors.ts index bc0350a15..f787daf43 100644 --- a/apps/web/src/i18n/locales/zh-CN/core-errors.ts +++ b/apps/web/src/i18n/locales/zh-CN/core-errors.ts @@ -36,7 +36,7 @@ export const coreErrors = { "sandbox_operation_unsupported": "所选沙箱提供商不支持此操作。", "environment_unavailable": "此 Session 的环境已不可用。", "execution_unavailable": "执行暂时不可用,请稍后重试。", - "runtime_history_unavailable": "此 Core 上的 Runtime 历史不可用。", + "runtime_history_unavailable": "Runtime 历史暂时不可用,请稍后重试。", "runtime_history_unsupported": "此 Session 不支持 Runtime 历史。", "core_metrics_unavailable": "无法读取 Core 指标,请稍后重试。", "file_transfer_unavailable": "文件传输不可用,请稍后重试。", diff --git a/docs/configuration.md b/docs/configuration.md index f98a71daf..5eefd448a 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -127,7 +127,6 @@ The node installer writes Docker’s host settings into the `native` object of t | `network` | `oac-node-` | Runtime container network | | `seccomp_file` | `/runtime/seccomp.json` | Matched distribution’s seccomp profile | | `nested_sandbox` | `true` | Enables the Docker adapter’s init process and proc-mask configuration | -| `extra_hosts` | Optional | Additional container host mappings | The [Docker adapter](./sandbox-provider.md#docker-adapter) owns container isolation, volume layout and lifecycle behavior. diff --git a/docs/zh/configuration.md b/docs/zh/configuration.md index 8261fc738..b8ad611ba 100644 --- a/docs/zh/configuration.md +++ b/docs/zh/configuration.md @@ -1,7 +1,7 @@ --- title: "配置参考" source: docs/configuration.md -source_hash: e10fcef53a7baf4f77d914bbda7f4158fcf49fc07546596ea78222939d580a6c +source_hash: 3e149cc2ca300bc53e14be2fd98b155c80098fd1e3b308a0b4d72d2ec3071558 --- Core 安装的每项设置都恰好只有一个归属位置,分属以下三类: @@ -131,7 +131,6 @@ Web 的 **System** 页面显示该安装的地址、默认模型和沙箱配置 | `network` | `oac-node-` | Runtime 容器网络 | | `seccomp_file` | `/runtime/seccomp.json` | 所匹配发行版的 seccomp 配置文件 | | `nested_sandbox` | `true` | 启用 Docker 适配器的 init 进程和 proc-mask 配置 | -| `extra_hosts` | 可选 | 额外的容器主机映射 | [Docker 适配器](sandbox-provider.md#docker-adapter)负责容器隔离、卷布局和生命周期行为。 diff --git a/services/core/internal/sandbox/docker/container_options.go b/services/core/internal/sandbox/docker/container_options.go index 0a179d855..f8bee5840 100644 --- a/services/core/internal/sandbox/docker/container_options.go +++ b/services/core/internal/sandbox/docker/container_options.go @@ -27,7 +27,7 @@ func runtimeContainerOptions(config Config, name string, labels map[string]strin } return client.ContainerCreateOptions{Name: name, Image: config.Image, Config: &container.Config{User: "1000:1000", WorkingDir: "/environment/workspace", Labels: labels, Env: environment}, - HostConfig: &container.HostConfig{ReadonlyRootfs: true, CapDrop: []string{"ALL"}, SecurityOpt: []string{"no-new-privileges", "seccomp=" + config.Seccomp, "apparmor=unconfined"}, NetworkMode: container.NetworkMode(config.Network), ExtraHosts: config.ExtraHosts, + HostConfig: &container.HostConfig{ReadonlyRootfs: true, CapDrop: []string{"ALL"}, SecurityOpt: []string{"no-new-privileges", "seccomp=" + config.Seccomp, "apparmor=unconfined"}, NetworkMode: container.NetworkMode(config.Network), MaskedPaths: masked, ReadonlyPaths: readonly, Init: init, Resources: container.Resources{PidsLimit: &limit, Memory: memory, NanoCPUs: cpus}, Tmpfs: map[string]string{"/tmp": "rw,nosuid,nodev,size=128m"}, Mounts: []mount.Mount{ diff --git a/services/core/internal/sandbox/docker/node.go b/services/core/internal/sandbox/docker/node.go index 63a2570fe..115d6bf0c 100644 --- a/services/core/internal/sandbox/docker/node.go +++ b/services/core/internal/sandbox/docker/node.go @@ -20,17 +20,16 @@ import ( // (image_manifest_digest) names the loaded image, so the installer records the // one this host resolves. type Native struct { - Host string `json:"host"` - Image string `json:"image"` - Network string `json:"network"` - SeccompFile string `json:"seccomp_file"` - ExtraHosts []string `json:"extra_hosts"` - NestedSandbox bool `json:"nested_sandbox"` + Host string `json:"host"` + Image string `json:"image"` + Network string `json:"network"` + SeccompFile string `json:"seccomp_file"` + NestedSandbox bool `json:"nested_sandbox"` } func decodeNative(config sandbox.NodeConfig) (Native, error) { var entry Native - if sandbox.DecodeConfigurationObject(config.Native, &entry, "host", "image", "network", "seccomp_file", "extra_hosts", "nested_sandbox") != nil { + if sandbox.DecodeConfigurationObject(config.Native, &entry, "host", "image", "network", "seccomp_file", "nested_sandbox") != nil { return entry, errors.New("invalid managed Docker node configuration") } release := config.Specification.Runtime @@ -63,7 +62,7 @@ func BuildNode(config sandbox.NodeConfig, _ sandbox.LocalOptions, result *sandbo return closeProvider, errors.New("invalid managed Docker endpoint") } closeProvider = func() { _ = c.Close() } - provider, err := New(c, Config{InstallationID: config.InstallationID, Image: entry.Image, Network: entry.Network, Seccomp: string(seccomp), ExtraHosts: entry.ExtraHosts, NestedSandbox: entry.NestedSandbox, Resources: &config.Specification.Resources}) + provider, err := New(c, Config{InstallationID: config.InstallationID, Image: entry.Image, Network: entry.Network, Seccomp: string(seccomp), NestedSandbox: entry.NestedSandbox, Resources: &config.Specification.Resources}) if err != nil { closeProvider() return func() {}, errors.New("invalid managed Docker provider configuration") diff --git a/services/core/internal/sandbox/docker/provider.go b/services/core/internal/sandbox/docker/provider.go index 474c0d59d..c108182a0 100644 --- a/services/core/internal/sandbox/docker/provider.go +++ b/services/core/internal/sandbox/docker/provider.go @@ -25,7 +25,6 @@ const labelPrefix = "io.oac." // trusted daemon/model connectivity; native tool network policy is in the image. type Config struct { InstallationID, Image, Network, Seccomp string - ExtraHosts []string NestedSandbox bool Resources *sandbox.Resources } diff --git a/services/core/tests/integration/local_environment_worker_test.go b/services/core/tests/integration/local_environment_worker_test.go index a3f7651e9..35699205b 100644 --- a/services/core/tests/integration/local_environment_worker_test.go +++ b/services/core/tests/integration/local_environment_worker_test.go @@ -100,8 +100,9 @@ func TestLocalEnvironmentWorkerRejectsGeneralDeviceDespiteCapability(t *testing. if _, err := w.ReadEnvironmentDirectory(t.Context(), unassigned, "reports"); !errors.Is(err, execution.ErrExecutionUnavailable) { t.Fatal("unassigned environment selected general device", err) } - if _, err := sessionAdapter(h.s).GetSessionDevice(t.Context(), h.tenant, other.ID); !errors.Is(err, sessions.ErrNotFound) { - t.Fatal("read persisted an unauthorized placement", err) + // Managed-runtime maintenance may bind its own device to the Session; the read must never bind the general one. + if device, err := sessionAdapter(h.s).GetSessionDevice(t.Context(), h.tenant, other.ID); err == nil && device.ID == h.device.ID || err != nil && !errors.Is(err, sessions.ErrNotFound) { + t.Fatal("read persisted an unauthorized placement", device, err) } }