hst/config: move container fields from toplevel
All checks were successful
Test / Create distribution (push) Successful in 33s
Test / Sandbox (push) Successful in 2m7s
Test / Hpkg (push) Successful in 3m54s
Test / Hakurei (race detector) (push) Successful in 5m18s
Test / Sandbox (race detector) (push) Successful in 2m10s
Test / Hakurei (push) Successful in 2m13s
Test / Flake checks (push) Successful in 1m33s

This change also moves pd behaviour to cmd/hakurei, as this does not belong in the hst API.

Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
2025-10-07 01:50:56 +09:00
parent f280994957
commit 9e48d7f562
19 changed files with 435 additions and 336 deletions

View File

@@ -1,6 +1,7 @@
package hst
import (
"errors"
"time"
"hakurei.app/container"
@@ -35,11 +36,6 @@ type (
// Passed to wayland security-context-v1 and used as part of defaults in dbus session proxy.
ID string `json:"id"`
// Pathname to executable file in the container filesystem.
Path *container.Absolute `json:"path,omitempty"`
// Final args passed to the initial program.
Args []string `json:"args"`
// System services to make available in the container.
Enablements *Enablements `json:"enablements,omitempty"`
@@ -53,14 +49,6 @@ type (
// and the bare socket is made available to the container.
DirectWayland bool `json:"direct_wayland,omitempty"`
// String used as the username of the emulated user, validated against the default NAME_REGEX from adduser.
// Defaults to passwd name of target uid or chronos.
Username string `json:"username,omitempty"`
// Pathname of shell in the container filesystem to use for the emulated user.
Shell *container.Absolute `json:"shell"`
// Directory in the container filesystem to enter and use as the home directory of the emulated user.
Home *container.Absolute `json:"home"`
// Extra acl update ops to perform before setuid.
ExtraPerms []*ExtraPermConfig `json:"extra_perms,omitempty"`
@@ -114,9 +102,50 @@ type (
If the first element targets /, it is inserted early and excluded from path hiding. */
Filesystem []FilesystemConfigJSON `json:"filesystem"`
// String used as the username of the emulated user, validated against the default NAME_REGEX from adduser.
// Defaults to passwd name of target uid or chronos.
Username string `json:"username,omitempty"`
// Pathname of shell in the container filesystem to use for the emulated user.
Shell *container.Absolute `json:"shell"`
// Directory in the container filesystem to enter and use as the home directory of the emulated user.
Home *container.Absolute `json:"home"`
// Pathname to executable file in the container filesystem.
Path *container.Absolute `json:"path,omitempty"`
// Final args passed to the initial program.
Args []string `json:"args"`
}
)
// ErrConfigNull is returned by [Config.Validate] for an invalid configuration that contains a null value for any
// field that must not be null.
var ErrConfigNull = errors.New("unexpected null in config")
func (config *Config) Validate() error {
if config == nil {
return &AppError{Step: "validate configuration", Err: ErrConfigNull,
Msg: "invalid configuration"}
}
if config.Container == nil {
return &AppError{Step: "validate configuration", Err: ErrConfigNull,
Msg: "configuration missing container state"}
}
if config.Container.Home == nil {
return &AppError{Step: "validate configuration", Err: ErrConfigNull,
Msg: "container configuration missing path to home directory"}
}
if config.Container.Shell == nil {
return &AppError{Step: "validate configuration", Err: ErrConfigNull,
Msg: "container configuration missing path to shell"}
}
if config.Container.Path == nil {
return &AppError{Step: "validate configuration", Err: ErrConfigNull,
Msg: "container configuration missing path to initial program"}
}
return nil
}
// ExtraPermConfig describes an acl update op.
type ExtraPermConfig struct {
Ensure bool `json:"ensure,omitempty"`

View File

@@ -1,12 +1,49 @@
package hst_test
import (
"reflect"
"testing"
"hakurei.app/container"
"hakurei.app/hst"
)
func TestConfigValidate(t *testing.T) {
testCases := []struct {
name string
config *hst.Config
wantErr error
}{
{"nil", nil, &hst.AppError{Step: "validate configuration", Err: hst.ErrConfigNull,
Msg: "invalid configuration"}},
{"container", &hst.Config{}, &hst.AppError{Step: "validate configuration", Err: hst.ErrConfigNull,
Msg: "configuration missing container state"}},
{"home", &hst.Config{Container: &hst.ContainerConfig{}}, &hst.AppError{Step: "validate configuration", Err: hst.ErrConfigNull,
Msg: "container configuration missing path to home directory"}},
{"shell", &hst.Config{Container: &hst.ContainerConfig{
Home: container.AbsFHSTmp,
}}, &hst.AppError{Step: "validate configuration", Err: hst.ErrConfigNull,
Msg: "container configuration missing path to shell"}},
{"path", &hst.Config{Container: &hst.ContainerConfig{
Home: container.AbsFHSTmp,
Shell: container.AbsFHSTmp,
}}, &hst.AppError{Step: "validate configuration", Err: hst.ErrConfigNull,
Msg: "container configuration missing path to initial program"}},
{"valid", &hst.Config{Container: &hst.ContainerConfig{
Home: container.AbsFHSTmp,
Shell: container.AbsFHSTmp,
Path: container.AbsFHSTmp,
}}, nil},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
if err := tc.config.Validate(); !reflect.DeepEqual(err, tc.wantErr) {
t.Errorf("Validate: error = %#v, want %#v", err, tc.wantErr)
}
})
}
}
func TestExtraPermConfig(t *testing.T) {
testCases := []struct {
name string

View File

@@ -60,15 +60,6 @@ func Template() *Config {
return &Config{
ID: "org.chromium.Chromium",
Path: container.AbsFHSRun.Append("current-system/sw/bin/chromium"),
Args: []string{
"chromium",
"--ignore-gpu-blocklist",
"--disable-smooth-scrolling",
"--enable-features=UseOzonePlatform",
"--ozone-platform=wayland",
},
Enablements: NewEnablements(EWayland | EDBus | EPulse),
SessionBus: &dbus.Config{
@@ -93,9 +84,6 @@ func Template() *Config {
},
DirectWayland: false,
Username: "chronos",
Shell: container.AbsFHSRun.Append("current-system/sw/bin/zsh"),
Home: container.MustAbs("/data/data/org.chromium.Chromium"),
ExtraPerms: []*ExtraPermConfig{
{Path: container.AbsFHSVarLib.Append("hakurei/u0"), Ensure: true, Execute: true},
{Path: container.AbsFHSVarLib.Append("hakurei/u0/org.chromium.Chromium"), Read: true, Write: true, Execute: true},
@@ -140,6 +128,19 @@ func Template() *Config {
Target: container.MustAbs("/data/data/org.chromium.Chromium"), Write: true, Ensure: true}},
{&FSBind{Source: container.AbsFHSDev.Append("dri"), Device: true, Optional: true}},
},
Username: "chronos",
Shell: container.AbsFHSRun.Append("current-system/sw/bin/zsh"),
Home: container.MustAbs("/data/data/org.chromium.Chromium"),
Path: container.AbsFHSRun.Append("current-system/sw/bin/chromium"),
Args: []string{
"chromium",
"--ignore-gpu-blocklist",
"--disable-smooth-scrolling",
"--enable-features=UseOzonePlatform",
"--ozone-platform=wayland",
},
},
}
}

View File

@@ -92,14 +92,6 @@ func TestAppError(t *testing.T) {
func TestTemplate(t *testing.T) {
const want = `{
"id": "org.chromium.Chromium",
"path": "/run/current-system/sw/bin/chromium",
"args": [
"chromium",
"--ignore-gpu-blocklist",
"--disable-smooth-scrolling",
"--enable-features=UseOzonePlatform",
"--ozone-platform=wayland"
],
"enablements": {
"wayland": true,
"dbus": true,
@@ -141,9 +133,6 @@ func TestTemplate(t *testing.T) {
"broadcast": null,
"filter": true
},
"username": "chronos",
"shell": "/run/current-system/sw/bin/zsh",
"home": "/data/data/org.chromium.Chromium",
"extra_perms": [
{
"ensure": true,
@@ -238,6 +227,17 @@ func TestTemplate(t *testing.T) {
"dev": true,
"optional": true
}
],
"username": "chronos",
"shell": "/run/current-system/sw/bin/zsh",
"home": "/data/data/org.chromium.Chromium",
"path": "/run/current-system/sw/bin/chromium",
"args": [
"chromium",
"--ignore-gpu-blocklist",
"--disable-smooth-scrolling",
"--enable-features=UseOzonePlatform",
"--ozone-platform=wayland"
]
}
}`