container: improve doc comments
Some checks failed
Test / Create distribution (push) Successful in 32s
Test / Hakurei (push) Failing after 58s
Test / Planterette (push) Failing after 1m11s
Test / Hakurei (race detector) (push) Failing after 1m35s
Test / Sandbox (push) Failing after 1m35s
Test / Sandbox (race detector) (push) Failing after 2m27s
Test / Flake checks (push) Has been skipped
Some checks failed
Test / Create distribution (push) Successful in 32s
Test / Hakurei (push) Failing after 58s
Test / Planterette (push) Failing after 1m11s
Test / Hakurei (race detector) (push) Failing after 1m35s
Test / Sandbox (push) Failing after 1m35s
Test / Sandbox (race detector) (push) Failing after 2m27s
Test / Flake checks (push) Has been skipped
Putting them on the builder methods is more useful. Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
parent
bd3fa53a55
commit
dcff0a8c3c
@ -91,12 +91,13 @@ type (
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Start starts the container init. The init process blocks until Serve is called.
|
||||||
func (p *Container) Start() error {
|
func (p *Container) Start() error {
|
||||||
if p.cmd != nil {
|
if p.cmd != nil {
|
||||||
return errors.New("sandbox: already started")
|
return errors.New("container: already started")
|
||||||
}
|
}
|
||||||
if p.Ops == nil || len(*p.Ops) == 0 {
|
if p.Ops == nil || len(*p.Ops) == 0 {
|
||||||
return errors.New("sandbox: starting an empty container")
|
return errors.New("container: starting an empty container")
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, cancel := context.WithCancel(p.ctx)
|
ctx, cancel := context.WithCancel(p.ctx)
|
||||||
@ -160,6 +161,8 @@ func (p *Container) Start() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Serve serves [Container.Params] to the container init.
|
||||||
|
// Serve must only be called once.
|
||||||
func (p *Container) Serve() error {
|
func (p *Container) Serve() error {
|
||||||
if p.setup == nil {
|
if p.setup == nil {
|
||||||
panic("invalid serve")
|
panic("invalid serve")
|
||||||
@ -213,6 +216,7 @@ func (p *Container) Serve() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Wait waits for the container init process to exit.
|
||||||
func (p *Container) Wait() error { defer p.cancel(); return p.cmd.Wait() }
|
func (p *Container) Wait() error { defer p.cancel(); return p.cmd.Wait() }
|
||||||
|
|
||||||
func (p *Container) String() string {
|
func (p *Container) String() string {
|
||||||
|
124
container/ops.go
124
container/ops.go
@ -15,7 +15,10 @@ import (
|
|||||||
|
|
||||||
type (
|
type (
|
||||||
Ops []Op
|
Ops []Op
|
||||||
Op interface {
|
|
||||||
|
// Op is a generic setup step ran inside the container init.
|
||||||
|
// Implementations of this interface are sent as a stream of gobs.
|
||||||
|
Op interface {
|
||||||
// early is called in host root.
|
// early is called in host root.
|
||||||
early(params *Params) error
|
early(params *Params) error
|
||||||
// apply is called in intermediate root.
|
// apply is called in intermediate root.
|
||||||
@ -27,11 +30,17 @@ type (
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Grow grows the slice Ops points to using [slices.Grow].
|
||||||
func (f *Ops) Grow(n int) { *f = slices.Grow(*f, n) }
|
func (f *Ops) Grow(n int) { *f = slices.Grow(*f, n) }
|
||||||
|
|
||||||
func init() { gob.Register(new(BindMountOp)) }
|
func init() { gob.Register(new(BindMountOp)) }
|
||||||
|
|
||||||
// BindMountOp bind mounts host path Source on container path Target.
|
// Bind appends an [Op] that bind mounts host path [BindMountOp.Source] on container path [BindMountOp.Target].
|
||||||
|
func (f *Ops) Bind(source, target string, flags int) *Ops {
|
||||||
|
*f = append(*f, &BindMountOp{source, "", target, flags})
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
||||||
type BindMountOp struct {
|
type BindMountOp struct {
|
||||||
Source, SourceFinal, Target string
|
Source, SourceFinal, Target string
|
||||||
|
|
||||||
@ -39,8 +48,11 @@ type BindMountOp struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
// BindOptional skips nonexistent host paths.
|
||||||
BindOptional = 1 << iota
|
BindOptional = 1 << iota
|
||||||
|
// BindWritable mounts filesystem read-write.
|
||||||
BindWritable
|
BindWritable
|
||||||
|
// BindDevice allows access to devices (special files) on this filesystem.
|
||||||
BindDevice
|
BindDevice
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -108,14 +120,15 @@ func (b *BindMountOp) String() string {
|
|||||||
}
|
}
|
||||||
return fmt.Sprintf("%q on %q flags %#x", b.Source, b.Target, b.Flags&BindWritable)
|
return fmt.Sprintf("%q on %q flags %#x", b.Source, b.Target, b.Flags&BindWritable)
|
||||||
}
|
}
|
||||||
func (f *Ops) Bind(source, target string, flags int) *Ops {
|
|
||||||
*f = append(*f, &BindMountOp{source, "", target, flags})
|
|
||||||
return f
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() { gob.Register(new(MountProcOp)) }
|
func init() { gob.Register(new(MountProcOp)) }
|
||||||
|
|
||||||
// MountProcOp mounts a private instance of proc.
|
// Proc appends an [Op] that mounts a private instance of proc.
|
||||||
|
func (f *Ops) Proc(dest string) *Ops {
|
||||||
|
*f = append(*f, MountProcOp(dest))
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
||||||
type MountProcOp string
|
type MountProcOp string
|
||||||
|
|
||||||
func (p MountProcOp) early(*Params) error { return nil }
|
func (p MountProcOp) early(*Params) error { return nil }
|
||||||
@ -137,14 +150,15 @@ func (p MountProcOp) apply(params *Params) error {
|
|||||||
func (p MountProcOp) Is(op Op) bool { vp, ok := op.(MountProcOp); return ok && p == vp }
|
func (p MountProcOp) Is(op Op) bool { vp, ok := op.(MountProcOp); return ok && p == vp }
|
||||||
func (MountProcOp) prefix() string { return "mounting" }
|
func (MountProcOp) prefix() string { return "mounting" }
|
||||||
func (p MountProcOp) String() string { return fmt.Sprintf("proc on %q", string(p)) }
|
func (p MountProcOp) String() string { return fmt.Sprintf("proc on %q", string(p)) }
|
||||||
func (f *Ops) Proc(dest string) *Ops {
|
|
||||||
*f = append(*f, MountProcOp(dest))
|
|
||||||
return f
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() { gob.Register(new(MountDevOp)) }
|
func init() { gob.Register(new(MountDevOp)) }
|
||||||
|
|
||||||
// MountDevOp mounts part of host dev.
|
// Dev appends an [Op] that mounts a subset of host /dev.
|
||||||
|
func (f *Ops) Dev(dest string) *Ops {
|
||||||
|
*f = append(*f, MountDevOp(dest))
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
||||||
type MountDevOp string
|
type MountDevOp string
|
||||||
|
|
||||||
func (d MountDevOp) early(*Params) error { return nil }
|
func (d MountDevOp) early(*Params) error { return nil }
|
||||||
@ -231,14 +245,15 @@ func (d MountDevOp) apply(params *Params) error {
|
|||||||
func (d MountDevOp) Is(op Op) bool { vd, ok := op.(MountDevOp); return ok && d == vd }
|
func (d MountDevOp) Is(op Op) bool { vd, ok := op.(MountDevOp); return ok && d == vd }
|
||||||
func (MountDevOp) prefix() string { return "mounting" }
|
func (MountDevOp) prefix() string { return "mounting" }
|
||||||
func (d MountDevOp) String() string { return fmt.Sprintf("dev on %q", string(d)) }
|
func (d MountDevOp) String() string { return fmt.Sprintf("dev on %q", string(d)) }
|
||||||
func (f *Ops) Dev(dest string) *Ops {
|
|
||||||
*f = append(*f, MountDevOp(dest))
|
|
||||||
return f
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() { gob.Register(new(MountMqueueOp)) }
|
func init() { gob.Register(new(MountMqueueOp)) }
|
||||||
|
|
||||||
// MountMqueueOp mounts a private mqueue instance on container Path.
|
// Mqueue appends an [Op] that mounts a private instance of mqueue.
|
||||||
|
func (f *Ops) Mqueue(dest string) *Ops {
|
||||||
|
*f = append(*f, MountMqueueOp(dest))
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
||||||
type MountMqueueOp string
|
type MountMqueueOp string
|
||||||
|
|
||||||
func (m MountMqueueOp) early(*Params) error { return nil }
|
func (m MountMqueueOp) early(*Params) error { return nil }
|
||||||
@ -260,14 +275,15 @@ func (m MountMqueueOp) apply(params *Params) error {
|
|||||||
func (m MountMqueueOp) Is(op Op) bool { vm, ok := op.(MountMqueueOp); return ok && m == vm }
|
func (m MountMqueueOp) Is(op Op) bool { vm, ok := op.(MountMqueueOp); return ok && m == vm }
|
||||||
func (MountMqueueOp) prefix() string { return "mounting" }
|
func (MountMqueueOp) prefix() string { return "mounting" }
|
||||||
func (m MountMqueueOp) String() string { return fmt.Sprintf("mqueue on %q", string(m)) }
|
func (m MountMqueueOp) String() string { return fmt.Sprintf("mqueue on %q", string(m)) }
|
||||||
func (f *Ops) Mqueue(dest string) *Ops {
|
|
||||||
*f = append(*f, MountMqueueOp(dest))
|
|
||||||
return f
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() { gob.Register(new(MountTmpfsOp)) }
|
func init() { gob.Register(new(MountTmpfsOp)) }
|
||||||
|
|
||||||
// MountTmpfsOp mounts tmpfs on container Path.
|
// Tmpfs appends an [Op] that mounts tmpfs on container path [MountTmpfsOp.Path].
|
||||||
|
func (f *Ops) Tmpfs(dest string, size int, perm os.FileMode) *Ops {
|
||||||
|
*f = append(*f, &MountTmpfsOp{dest, size, perm})
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
||||||
type MountTmpfsOp struct {
|
type MountTmpfsOp struct {
|
||||||
Path string
|
Path string
|
||||||
Size int
|
Size int
|
||||||
@ -288,14 +304,15 @@ func (t *MountTmpfsOp) apply(*Params) error {
|
|||||||
func (t *MountTmpfsOp) Is(op Op) bool { vt, ok := op.(*MountTmpfsOp); return ok && *t == *vt }
|
func (t *MountTmpfsOp) Is(op Op) bool { vt, ok := op.(*MountTmpfsOp); return ok && *t == *vt }
|
||||||
func (*MountTmpfsOp) prefix() string { return "mounting" }
|
func (*MountTmpfsOp) prefix() string { return "mounting" }
|
||||||
func (t *MountTmpfsOp) String() string { return fmt.Sprintf("tmpfs on %q size %d", t.Path, t.Size) }
|
func (t *MountTmpfsOp) String() string { return fmt.Sprintf("tmpfs on %q size %d", t.Path, t.Size) }
|
||||||
func (f *Ops) Tmpfs(dest string, size int, perm os.FileMode) *Ops {
|
|
||||||
*f = append(*f, &MountTmpfsOp{dest, size, perm})
|
|
||||||
return f
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() { gob.Register(new(SymlinkOp)) }
|
func init() { gob.Register(new(SymlinkOp)) }
|
||||||
|
|
||||||
// SymlinkOp creates a symlink in the container filesystem.
|
// Link appends an [Op] that creates a symlink in the container filesystem.
|
||||||
|
func (f *Ops) Link(target, linkName string) *Ops {
|
||||||
|
*f = append(*f, &SymlinkOp{target, linkName})
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
||||||
type SymlinkOp [2]string
|
type SymlinkOp [2]string
|
||||||
|
|
||||||
func (l *SymlinkOp) early(*Params) error {
|
func (l *SymlinkOp) early(*Params) error {
|
||||||
@ -331,14 +348,15 @@ func (l *SymlinkOp) apply(params *Params) error {
|
|||||||
func (l *SymlinkOp) Is(op Op) bool { vl, ok := op.(*SymlinkOp); return ok && *l == *vl }
|
func (l *SymlinkOp) Is(op Op) bool { vl, ok := op.(*SymlinkOp); return ok && *l == *vl }
|
||||||
func (*SymlinkOp) prefix() string { return "creating" }
|
func (*SymlinkOp) prefix() string { return "creating" }
|
||||||
func (l *SymlinkOp) String() string { return fmt.Sprintf("symlink on %q target %q", l[1], l[0]) }
|
func (l *SymlinkOp) String() string { return fmt.Sprintf("symlink on %q target %q", l[1], l[0]) }
|
||||||
func (f *Ops) Link(target, linkName string) *Ops {
|
|
||||||
*f = append(*f, &SymlinkOp{target, linkName})
|
|
||||||
return f
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() { gob.Register(new(MkdirOp)) }
|
func init() { gob.Register(new(MkdirOp)) }
|
||||||
|
|
||||||
// MkdirOp creates a directory in the container filesystem.
|
// Mkdir appends an [Op] that creates a directory in the container filesystem.
|
||||||
|
func (f *Ops) Mkdir(dest string, perm os.FileMode) *Ops {
|
||||||
|
*f = append(*f, &MkdirOp{dest, perm})
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
||||||
type MkdirOp struct {
|
type MkdirOp struct {
|
||||||
Path string
|
Path string
|
||||||
Perm os.FileMode
|
Perm os.FileMode
|
||||||
@ -359,14 +377,21 @@ func (m *MkdirOp) apply(*Params) error {
|
|||||||
func (m *MkdirOp) Is(op Op) bool { vm, ok := op.(*MkdirOp); return ok && m == vm }
|
func (m *MkdirOp) Is(op Op) bool { vm, ok := op.(*MkdirOp); return ok && m == vm }
|
||||||
func (*MkdirOp) prefix() string { return "creating" }
|
func (*MkdirOp) prefix() string { return "creating" }
|
||||||
func (m *MkdirOp) String() string { return fmt.Sprintf("directory %q perm %s", m.Path, m.Perm) }
|
func (m *MkdirOp) String() string { return fmt.Sprintf("directory %q perm %s", m.Path, m.Perm) }
|
||||||
func (f *Ops) Mkdir(dest string, perm os.FileMode) *Ops {
|
|
||||||
*f = append(*f, &MkdirOp{dest, perm})
|
|
||||||
return f
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() { gob.Register(new(TmpfileOp)) }
|
func init() { gob.Register(new(TmpfileOp)) }
|
||||||
|
|
||||||
// TmpfileOp places a file in container Path containing Data.
|
// Place appends an [Op] that places a file in container path [TmpfileOp.Path] containing [TmpfileOp.Data].
|
||||||
|
func (f *Ops) Place(name string, data []byte) *Ops { *f = append(*f, &TmpfileOp{name, data}); return f }
|
||||||
|
|
||||||
|
// PlaceP is like Place but writes the address of [TmpfileOp.Data] to the pointer dataP points to.
|
||||||
|
func (f *Ops) PlaceP(name string, dataP **[]byte) *Ops {
|
||||||
|
t := &TmpfileOp{Path: name}
|
||||||
|
*dataP = &t.Data
|
||||||
|
|
||||||
|
*f = append(*f, t)
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
||||||
type TmpfileOp struct {
|
type TmpfileOp struct {
|
||||||
Path string
|
Path string
|
||||||
Data []byte
|
Data []byte
|
||||||
@ -415,19 +440,19 @@ func (*TmpfileOp) prefix() string { return "placing" }
|
|||||||
func (t *TmpfileOp) String() string {
|
func (t *TmpfileOp) String() string {
|
||||||
return fmt.Sprintf("tmpfile %q (%d bytes)", t.Path, len(t.Data))
|
return fmt.Sprintf("tmpfile %q (%d bytes)", t.Path, len(t.Data))
|
||||||
}
|
}
|
||||||
func (f *Ops) Place(name string, data []byte) *Ops { *f = append(*f, &TmpfileOp{name, data}); return f }
|
|
||||||
func (f *Ops) PlaceP(name string, dataP **[]byte) *Ops {
|
|
||||||
t := &TmpfileOp{Path: name}
|
|
||||||
*dataP = &t.Data
|
|
||||||
|
|
||||||
*f = append(*f, t)
|
|
||||||
return f
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() { gob.Register(new(AutoEtcOp)) }
|
func init() { gob.Register(new(AutoEtcOp)) }
|
||||||
|
|
||||||
// AutoEtcOp expands host /etc into a toplevel symlink mirror with /etc semantics.
|
// Etc appends an [Op] that expands host /etc into a toplevel symlink mirror with /etc semantics.
|
||||||
// This is not a generic setup op. It is implemented here to reduce ipc overhead.
|
// This is not a generic setup op. It is implemented here to reduce ipc overhead.
|
||||||
|
func (f *Ops) Etc(host, prefix string) *Ops {
|
||||||
|
e := &AutoEtcOp{prefix}
|
||||||
|
f.Mkdir("/etc", 0755)
|
||||||
|
f.Bind(host, e.hostPath(), 0)
|
||||||
|
*f = append(*f, e)
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
||||||
type AutoEtcOp struct{ Prefix string }
|
type AutoEtcOp struct{ Prefix string }
|
||||||
|
|
||||||
func (e *AutoEtcOp) early(*Params) error { return nil }
|
func (e *AutoEtcOp) early(*Params) error { return nil }
|
||||||
@ -473,10 +498,3 @@ func (e *AutoEtcOp) Is(op Op) bool {
|
|||||||
}
|
}
|
||||||
func (*AutoEtcOp) prefix() string { return "setting up" }
|
func (*AutoEtcOp) prefix() string { return "setting up" }
|
||||||
func (e *AutoEtcOp) String() string { return fmt.Sprintf("auto etc %s", e.Prefix) }
|
func (e *AutoEtcOp) String() string { return fmt.Sprintf("auto etc %s", e.Prefix) }
|
||||||
func (f *Ops) Etc(host, prefix string) *Ops {
|
|
||||||
e := &AutoEtcOp{prefix}
|
|
||||||
f.Mkdir("/etc", 0755)
|
|
||||||
f.Bind(host, e.hostPath(), 0)
|
|
||||||
*f = append(*f, e)
|
|
||||||
return f
|
|
||||||
}
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user