From 156096ac987f5ec8be8dbf65332c4d61e675f3cf Mon Sep 17 00:00:00 2001 From: Ophestra Date: Tue, 6 Jan 2026 20:57:43 +0900 Subject: internal/pkg: known checksum exec artifact This optionally attaches an output checksum to an execArtifact and enables host networking for the resulting container. Signed-off-by: Ophestra --- internal/pkg/exec.go | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) (limited to 'internal/pkg/exec.go') diff --git a/internal/pkg/exec.go b/internal/pkg/exec.go index 539bd935..930624fc 100644 --- a/internal/pkg/exec.go +++ b/internal/pkg/exec.go @@ -6,6 +6,7 @@ import ( "errors" "os" "runtime" + "slices" "hakurei.app/container" "hakurei.app/container/check" @@ -29,6 +30,9 @@ func MustPath(pathname string, a Artifact) ExecContainerPath { // An execArtifact is an [Artifact] that produces output by running a program // part of another [Artifact] in a [container] to produce its output. +// +// Methods of execArtifact does not modify any struct field or underlying arrays +// referred to by slices. type execArtifact struct { // Caller-supplied context. ctx context.Context @@ -52,6 +56,33 @@ type execArtifact struct { args []string } +// execNetArtifact is like execArtifact but implements [KnownChecksum] and has +// its resulting container keep the host net namespace. +type execNetArtifact struct { + checksum Checksum + + execArtifact +} + +var _ KnownChecksum = new(execNetArtifact) + +// Checksum returns the caller-supplied checksum. +func (a *execNetArtifact) Checksum() Checksum { return a.checksum } + +// Kind returns the hardcoded [Kind] constant. +func (a *execNetArtifact) Kind() Kind { return KindExecNet } + +// Params is [Checksum] concatenated with [KindExec] params. +func (a *execNetArtifact) Params() []byte { + return slices.Concat(a.checksum[:], a.execArtifact.Params()) +} + +// Cure cures the [Artifact] by curing all its dependencies then running the +// container described by the caller. The container retains host networking. +func (a *execNetArtifact) Cure(c *CureContext) error { + return a.cure(c, true) +} + // NewExec returns a new [Artifact] bounded by ctx, it cures all [Artifact] // in paths at the specified maximum concurrent cures limit. Specified paths are // bind mounted read-only in the specified order in the resulting container. @@ -60,12 +91,16 @@ type execArtifact struct { // The working and temporary directories are both created and mounted writable // on /work and /tmp respectively. // +// If checksum is non-nil, the resulting [Artifact] implements [KnownChecksum] +// and its container runs in the host net namespace. +// // A cures value of 0 or lower is equivalent to the value returned by // [runtime.NumCPU]. func NewExec( ctx context.Context, msg message.Msg, cures int, + checksum *Checksum, dir *check.Absolute, env []string, @@ -74,7 +109,11 @@ func NewExec( paths ...ExecContainerPath, ) Artifact { - return &execArtifact{ctx, paths, msg, cures, dir, env, path, args} + a := execArtifact{ctx, paths, msg, cures, dir, env, path, args} + if checksum == nil { + return &a + } + return &execNetArtifact{*checksum, a} } // Kind returns the hardcoded [Kind] constant. @@ -126,6 +165,12 @@ func (a *execArtifact) Dependencies() []Artifact { // Cure cures the [Artifact] by curing all its dependencies then running the // container described by the caller. func (a *execArtifact) Cure(c *CureContext) (err error) { + return a.cure(c, false) +} + +// cure is like Cure but allows optional host net namespace. This is used for +// the [KnownChecksum] variant where networking is allowed. +func (a *execArtifact) cure(c *CureContext, hostNet bool) (err error) { cures := a.cures if cures < 1 { cures = runtime.NumCPU() @@ -205,7 +250,11 @@ func (a *execArtifact) Cure(c *CureContext) (err error) { z.ForwardCancel = true z.SeccompPresets |= std.PresetStrict z.ParentPerm = 0700 + z.HostNet = hostNet z.Hostname = "cure" + if z.HostNet { + z.Hostname = "cure-net" + } z.Uid, z.Gid = (1<<10)-1, (1<<10)-1 if a.msg.IsVerbose() { z.Stdin, z.Stdout, z.Stderr = os.Stdin, os.Stdout, os.Stderr -- cgit v1.3.1