aboutsummaryrefslogtreecommitdiffhomepage
path: root/internal/pkg/exec.go
diff options
context:
space:
mode:
authorOphestra <cat@gensokyo.uk>2026-01-06 20:57:43 +0900
committerOphestra <cat@gensokyo.uk>2026-01-06 20:58:34 +0900
commit156096ac987f5ec8be8dbf65332c4d61e675f3cf (patch)
treec7f3069fc2e92715107f5ae7ae8841f638e106cf /internal/pkg/exec.go
parentceb75538cfdaff0a37c7d614fb77aa8c75669600 (diff)
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 <cat@gensokyo.uk>
Diffstat (limited to 'internal/pkg/exec.go')
-rw-r--r--internal/pkg/exec.go51
1 files changed, 50 insertions, 1 deletions
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