internal/pkg: known checksum exec artifact
All checks were successful
Test / Create distribution (push) Successful in 53s
Test / Sandbox (push) Successful in 2m57s
Test / ShareFS (push) Successful in 4m48s
Test / Sandbox (race detector) (push) Successful in 5m21s
Test / Hakurei (push) Successful in 5m31s
Test / Hpkg (push) Successful in 5m26s
Test / Hakurei (race detector) (push) Successful in 7m33s
Test / Flake checks (push) Successful in 1m49s
All checks were successful
Test / Create distribution (push) Successful in 53s
Test / Sandbox (push) Successful in 2m57s
Test / ShareFS (push) Successful in 4m48s
Test / Sandbox (race detector) (push) Successful in 5m21s
Test / Hakurei (push) Successful in 5m31s
Test / Hpkg (push) Successful in 5m26s
Test / Hakurei (race detector) (push) Successful in 7m33s
Test / Flake checks (push) Successful in 1m49s
This optionally attaches an output checksum to an execArtifact and enables host networking for the resulting container. Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
@@ -274,32 +274,82 @@ func TestFlatten(t *testing.T) {
|
|||||||
}, pkg.MustDecode("GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9")},
|
}, pkg.MustDecode("GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9")},
|
||||||
|
|
||||||
{"sample exec container", fstest.MapFS{
|
{"sample exec container", fstest.MapFS{
|
||||||
".": {Mode: fs.ModeDir | 0700},
|
".": {Mode: fs.ModeDir | 0700},
|
||||||
|
|
||||||
"checksum": {Mode: fs.ModeDir | 0700},
|
"checksum": {Mode: fs.ModeDir | 0700},
|
||||||
"checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9": {Mode: fs.ModeDir | 0500},
|
"checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9": {Mode: fs.ModeDir | 0500},
|
||||||
"checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9/check": {Mode: 0400, Data: []byte{0x0}},
|
"checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9/check": {Mode: 0400, Data: []byte{0x0}},
|
||||||
"checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU": {Mode: fs.ModeDir | 0500},
|
"checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU": {Mode: fs.ModeDir | 0500},
|
||||||
"checksum/OLBgp1GsljhM2TJ-sbHjaiH9txEUvgdDTAzHv2P24donTt6_529l-9Ua0vFImLlb": {Mode: 0400, Data: []byte{}},
|
"checksum/OLBgp1GsljhM2TJ-sbHjaiH9txEUvgdDTAzHv2P24donTt6_529l-9Ua0vFImLlb": {Mode: 0400, Data: []byte{}},
|
||||||
|
|
||||||
"identifier": {Mode: fs.ModeDir | 0700},
|
"identifier": {Mode: fs.ModeDir | 0700},
|
||||||
"identifier/_gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/OLBgp1GsljhM2TJ-sbHjaiH9txEUvgdDTAzHv2P24donTt6_529l-9Ua0vFImLlb")},
|
"identifier/_gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/OLBgp1GsljhM2TJ-sbHjaiH9txEUvgdDTAzHv2P24donTt6_529l-9Ua0vFImLlb")},
|
||||||
"identifier/nfeISfLeFDr1k-g3hpE1oZ440kTqDdfF8TDpoLdbTPqaMMIl95oiqcvqjRkMjubA": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
|
"identifier/nfeISfLeFDr1k-g3hpE1oZ440kTqDdfF8TDpoLdbTPqaMMIl95oiqcvqjRkMjubA": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
|
||||||
"identifier/oHuqV7p0v1Vd8IdAzjyYM8sfCS0P2LR5tfv5cb6Gbf2ZWUm8Ec-7hYPJ_qr183m7": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9")},
|
"identifier/oHuqV7p0v1Vd8IdAzjyYM8sfCS0P2LR5tfv5cb6Gbf2ZWUm8Ec-7hYPJ_qr183m7": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9")},
|
||||||
|
|
||||||
"temp": {Mode: fs.ModeDir | 0700},
|
"temp": {Mode: fs.ModeDir | 0700},
|
||||||
"work": {Mode: fs.ModeDir | 0700},
|
"work": {Mode: fs.ModeDir | 0700},
|
||||||
}, []pkg.FlatEntry{
|
}, []pkg.FlatEntry{
|
||||||
{Mode: fs.ModeDir | 0700, Path: "."},
|
{Mode: fs.ModeDir | 0700, Path: "."},
|
||||||
|
|
||||||
{Mode: fs.ModeDir | 0700, Path: "checksum"},
|
{Mode: fs.ModeDir | 0700, Path: "checksum"},
|
||||||
{Mode: fs.ModeDir | 0500, Path: "checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9"},
|
{Mode: fs.ModeDir | 0500, Path: "checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9"},
|
||||||
{Mode: 0400, Path: "checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9/check", Data: []byte{0x0}},
|
{Mode: 0400, Path: "checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9/check", Data: []byte{0x0}},
|
||||||
{Mode: fs.ModeDir | 0500, Path: "checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU"},
|
{Mode: fs.ModeDir | 0500, Path: "checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU"},
|
||||||
{Mode: 0400, Path: "checksum/OLBgp1GsljhM2TJ-sbHjaiH9txEUvgdDTAzHv2P24donTt6_529l-9Ua0vFImLlb", Data: []byte{}},
|
{Mode: 0400, Path: "checksum/OLBgp1GsljhM2TJ-sbHjaiH9txEUvgdDTAzHv2P24donTt6_529l-9Ua0vFImLlb", Data: []byte{}},
|
||||||
|
|
||||||
{Mode: fs.ModeDir | 0700, Path: "identifier"},
|
{Mode: fs.ModeDir | 0700, Path: "identifier"},
|
||||||
{Mode: fs.ModeSymlink | 0777, Path: "identifier/_gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", Data: []byte("../checksum/OLBgp1GsljhM2TJ-sbHjaiH9txEUvgdDTAzHv2P24donTt6_529l-9Ua0vFImLlb")},
|
{Mode: fs.ModeSymlink | 0777, Path: "identifier/_gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", Data: []byte("../checksum/OLBgp1GsljhM2TJ-sbHjaiH9txEUvgdDTAzHv2P24donTt6_529l-9Ua0vFImLlb")},
|
||||||
{Mode: fs.ModeSymlink | 0777, Path: "identifier/nfeISfLeFDr1k-g3hpE1oZ440kTqDdfF8TDpoLdbTPqaMMIl95oiqcvqjRkMjubA", Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
|
{Mode: fs.ModeSymlink | 0777, Path: "identifier/nfeISfLeFDr1k-g3hpE1oZ440kTqDdfF8TDpoLdbTPqaMMIl95oiqcvqjRkMjubA", Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
|
||||||
{Mode: fs.ModeSymlink | 0777, Path: "identifier/oHuqV7p0v1Vd8IdAzjyYM8sfCS0P2LR5tfv5cb6Gbf2ZWUm8Ec-7hYPJ_qr183m7", Data: []byte("../checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9")},
|
{Mode: fs.ModeSymlink | 0777, Path: "identifier/oHuqV7p0v1Vd8IdAzjyYM8sfCS0P2LR5tfv5cb6Gbf2ZWUm8Ec-7hYPJ_qr183m7", Data: []byte("../checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9")},
|
||||||
|
|
||||||
{Mode: fs.ModeDir | 0700, Path: "temp"},
|
{Mode: fs.ModeDir | 0700, Path: "temp"},
|
||||||
{Mode: fs.ModeDir | 0700, Path: "work"},
|
{Mode: fs.ModeDir | 0700, Path: "work"},
|
||||||
}, pkg.MustDecode("7PoPpWLjFPXIymbuIYLZAzOpCYr-2PN4CZ11jFdO-mDlnZNgFO3JyOtK8HW8Jxvm")},
|
}, pkg.MustDecode("7PoPpWLjFPXIymbuIYLZAzOpCYr-2PN4CZ11jFdO-mDlnZNgFO3JyOtK8HW8Jxvm")},
|
||||||
|
|
||||||
|
{"testtool net", fstest.MapFS{
|
||||||
|
".": {Mode: fs.ModeDir | 0500},
|
||||||
|
|
||||||
|
"check": {Mode: 0400, Data: []byte("net")},
|
||||||
|
}, []pkg.FlatEntry{
|
||||||
|
{Mode: fs.ModeDir | 0500, Path: "."},
|
||||||
|
|
||||||
|
{Mode: 0400, Path: "check", Data: []byte("net")},
|
||||||
|
}, pkg.MustDecode("a1F_i9PVQI4qMcoHgTQkORuyWLkC1GLIxOhDt2JpU1NGAxWc5VJzdlfRK-PYBh3W")},
|
||||||
|
|
||||||
|
{"sample exec net container", fstest.MapFS{
|
||||||
|
".": {Mode: fs.ModeDir | 0700},
|
||||||
|
|
||||||
|
"checksum": {Mode: fs.ModeDir | 0700},
|
||||||
|
"checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU": {Mode: fs.ModeDir | 0500},
|
||||||
|
"checksum/OLBgp1GsljhM2TJ-sbHjaiH9txEUvgdDTAzHv2P24donTt6_529l-9Ua0vFImLlb": {Mode: 0400, Data: []byte{}},
|
||||||
|
"checksum/a1F_i9PVQI4qMcoHgTQkORuyWLkC1GLIxOhDt2JpU1NGAxWc5VJzdlfRK-PYBh3W": {Mode: fs.ModeDir | 0500},
|
||||||
|
"checksum/a1F_i9PVQI4qMcoHgTQkORuyWLkC1GLIxOhDt2JpU1NGAxWc5VJzdlfRK-PYBh3W/check": {Mode: 0400, Data: []byte("net")},
|
||||||
|
|
||||||
|
"identifier": {Mode: fs.ModeDir | 0700},
|
||||||
|
"identifier/_gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/OLBgp1GsljhM2TJ-sbHjaiH9txEUvgdDTAzHv2P24donTt6_529l-9Ua0vFImLlb")},
|
||||||
|
"identifier/I3T53NtN6HPAyyodHtq2B0clcsoS1nPdvCEb-Zc5K-hoqFGL2od1mftHhwG7gX1S": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/a1F_i9PVQI4qMcoHgTQkORuyWLkC1GLIxOhDt2JpU1NGAxWc5VJzdlfRK-PYBh3W")},
|
||||||
|
"identifier/nfeISfLeFDr1k-g3hpE1oZ440kTqDdfF8TDpoLdbTPqaMMIl95oiqcvqjRkMjubA": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
|
||||||
|
|
||||||
|
"temp": {Mode: fs.ModeDir | 0700},
|
||||||
|
"work": {Mode: fs.ModeDir | 0700},
|
||||||
|
}, []pkg.FlatEntry{
|
||||||
|
{Mode: fs.ModeDir | 0700, Path: "."},
|
||||||
|
|
||||||
|
{Mode: fs.ModeDir | 0700, Path: "checksum"},
|
||||||
|
{Mode: fs.ModeDir | 0500, Path: "checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU"},
|
||||||
|
{Mode: 0400, Path: "checksum/OLBgp1GsljhM2TJ-sbHjaiH9txEUvgdDTAzHv2P24donTt6_529l-9Ua0vFImLlb", Data: []byte{}},
|
||||||
|
{Mode: fs.ModeDir | 0500, Path: "checksum/a1F_i9PVQI4qMcoHgTQkORuyWLkC1GLIxOhDt2JpU1NGAxWc5VJzdlfRK-PYBh3W"},
|
||||||
|
{Mode: 0400, Path: "checksum/a1F_i9PVQI4qMcoHgTQkORuyWLkC1GLIxOhDt2JpU1NGAxWc5VJzdlfRK-PYBh3W/check", Data: []byte("net")},
|
||||||
|
|
||||||
|
{Mode: fs.ModeDir | 0700, Path: "identifier"},
|
||||||
|
{Mode: fs.ModeSymlink | 0777, Path: "identifier/I3T53NtN6HPAyyodHtq2B0clcsoS1nPdvCEb-Zc5K-hoqFGL2od1mftHhwG7gX1S", Data: []byte("../checksum/a1F_i9PVQI4qMcoHgTQkORuyWLkC1GLIxOhDt2JpU1NGAxWc5VJzdlfRK-PYBh3W")},
|
||||||
|
{Mode: fs.ModeSymlink | 0777, Path: "identifier/_gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", Data: []byte("../checksum/OLBgp1GsljhM2TJ-sbHjaiH9txEUvgdDTAzHv2P24donTt6_529l-9Ua0vFImLlb")},
|
||||||
|
{Mode: fs.ModeSymlink | 0777, Path: "identifier/nfeISfLeFDr1k-g3hpE1oZ440kTqDdfF8TDpoLdbTPqaMMIl95oiqcvqjRkMjubA", Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
|
||||||
|
|
||||||
|
{Mode: fs.ModeDir | 0700, Path: "temp"},
|
||||||
|
{Mode: fs.ModeDir | 0700, Path: "work"},
|
||||||
|
}, pkg.MustDecode("bBQVFIt0FnOulljgpLnGtuzHSFgwiCMjc4pmc4rHRqXKQ60Q5aBVYp5f6aH9VdZi")},
|
||||||
}
|
}
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"os"
|
"os"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"slices"
|
||||||
|
|
||||||
"hakurei.app/container"
|
"hakurei.app/container"
|
||||||
"hakurei.app/container/check"
|
"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
|
// An execArtifact is an [Artifact] that produces output by running a program
|
||||||
// part of another [Artifact] in a [container] to produce its output.
|
// 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 {
|
type execArtifact struct {
|
||||||
// Caller-supplied context.
|
// Caller-supplied context.
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
@@ -52,6 +56,33 @@ type execArtifact struct {
|
|||||||
args []string
|
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]
|
// NewExec returns a new [Artifact] bounded by ctx, it cures all [Artifact]
|
||||||
// in paths at the specified maximum concurrent cures limit. Specified paths are
|
// in paths at the specified maximum concurrent cures limit. Specified paths are
|
||||||
// bind mounted read-only in the specified order in the resulting container.
|
// 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
|
// The working and temporary directories are both created and mounted writable
|
||||||
// on /work and /tmp respectively.
|
// 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
|
// A cures value of 0 or lower is equivalent to the value returned by
|
||||||
// [runtime.NumCPU].
|
// [runtime.NumCPU].
|
||||||
func NewExec(
|
func NewExec(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
msg message.Msg,
|
msg message.Msg,
|
||||||
cures int,
|
cures int,
|
||||||
|
checksum *Checksum,
|
||||||
|
|
||||||
dir *check.Absolute,
|
dir *check.Absolute,
|
||||||
env []string,
|
env []string,
|
||||||
@@ -74,7 +109,11 @@ func NewExec(
|
|||||||
|
|
||||||
paths ...ExecContainerPath,
|
paths ...ExecContainerPath,
|
||||||
) Artifact {
|
) 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.
|
// 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
|
// Cure cures the [Artifact] by curing all its dependencies then running the
|
||||||
// container described by the caller.
|
// container described by the caller.
|
||||||
func (a *execArtifact) Cure(c *CureContext) (err error) {
|
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
|
cures := a.cures
|
||||||
if cures < 1 {
|
if cures < 1 {
|
||||||
cures = runtime.NumCPU()
|
cures = runtime.NumCPU()
|
||||||
@@ -205,7 +250,11 @@ func (a *execArtifact) Cure(c *CureContext) (err error) {
|
|||||||
z.ForwardCancel = true
|
z.ForwardCancel = true
|
||||||
z.SeccompPresets |= std.PresetStrict
|
z.SeccompPresets |= std.PresetStrict
|
||||||
z.ParentPerm = 0700
|
z.ParentPerm = 0700
|
||||||
|
z.HostNet = hostNet
|
||||||
z.Hostname = "cure"
|
z.Hostname = "cure"
|
||||||
|
if z.HostNet {
|
||||||
|
z.Hostname = "cure-net"
|
||||||
|
}
|
||||||
z.Uid, z.Gid = (1<<10)-1, (1<<10)-1
|
z.Uid, z.Gid = (1<<10)-1, (1<<10)-1
|
||||||
if a.msg.IsVerbose() {
|
if a.msg.IsVerbose() {
|
||||||
z.Stdin, z.Stdout, z.Stderr = os.Stdin, os.Stdout, os.Stderr
|
z.Stdin, z.Stdout, z.Stderr = os.Stdin, os.Stdout, os.Stderr
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ func TestExec(t *testing.T) {
|
|||||||
t.Context(),
|
t.Context(),
|
||||||
msg,
|
msg,
|
||||||
0,
|
0,
|
||||||
|
nil,
|
||||||
check.MustAbs("/work"),
|
check.MustAbs("/work"),
|
||||||
[]string{"HAKUREI_TEST=1"},
|
[]string{"HAKUREI_TEST=1"},
|
||||||
check.MustAbs("/opt/bin/testtool"),
|
check.MustAbs("/opt/bin/testtool"),
|
||||||
@@ -66,6 +67,7 @@ func TestExec(t *testing.T) {
|
|||||||
t.Context(),
|
t.Context(),
|
||||||
msg,
|
msg,
|
||||||
0,
|
0,
|
||||||
|
nil,
|
||||||
check.MustAbs("/work"),
|
check.MustAbs("/work"),
|
||||||
[]string{"HAKUREI_TEST=1"},
|
[]string{"HAKUREI_TEST=1"},
|
||||||
check.MustAbs("/opt/bin/testtool"),
|
check.MustAbs("/opt/bin/testtool"),
|
||||||
@@ -84,6 +86,7 @@ func TestExec(t *testing.T) {
|
|||||||
t.Context(),
|
t.Context(),
|
||||||
msg,
|
msg,
|
||||||
0,
|
0,
|
||||||
|
nil,
|
||||||
check.MustAbs("/work"),
|
check.MustAbs("/work"),
|
||||||
[]string{"HAKUREI_TEST=1"},
|
[]string{"HAKUREI_TEST=1"},
|
||||||
check.MustAbs("/opt/bin/testtool"),
|
check.MustAbs("/opt/bin/testtool"),
|
||||||
@@ -99,6 +102,7 @@ func TestExec(t *testing.T) {
|
|||||||
t.Context(),
|
t.Context(),
|
||||||
msg,
|
msg,
|
||||||
0,
|
0,
|
||||||
|
nil,
|
||||||
check.MustAbs("/work"),
|
check.MustAbs("/work"),
|
||||||
nil,
|
nil,
|
||||||
check.MustAbs("/opt/bin/testtool"),
|
check.MustAbs("/opt/bin/testtool"),
|
||||||
@@ -110,6 +114,47 @@ func TestExec(t *testing.T) {
|
|||||||
|
|
||||||
testtoolDestroy(t, base, c)
|
testtoolDestroy(t, base, c)
|
||||||
}, pkg.MustDecode("7PoPpWLjFPXIymbuIYLZAzOpCYr-2PN4CZ11jFdO-mDlnZNgFO3JyOtK8HW8Jxvm")},
|
}, pkg.MustDecode("7PoPpWLjFPXIymbuIYLZAzOpCYr-2PN4CZ11jFdO-mDlnZNgFO3JyOtK8HW8Jxvm")},
|
||||||
|
|
||||||
|
{"net", nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
||||||
|
c.SetStrict(true)
|
||||||
|
testtool, testtoolDestroy := newTesttool()
|
||||||
|
|
||||||
|
msg := message.New(log.New(os.Stderr, "container: ", 0))
|
||||||
|
msg.SwapVerbose(testing.Verbose())
|
||||||
|
|
||||||
|
wantChecksum := pkg.MustDecode(
|
||||||
|
"a1F_i9PVQI4qMcoHgTQkORuyWLkC1GLIxOhDt2JpU1NGAxWc5VJzdlfRK-PYBh3W",
|
||||||
|
)
|
||||||
|
cureMany(t, c, []cureStep{
|
||||||
|
{"container", pkg.NewExec(
|
||||||
|
t.Context(),
|
||||||
|
msg,
|
||||||
|
0,
|
||||||
|
&wantChecksum,
|
||||||
|
check.MustAbs("/work"),
|
||||||
|
[]string{"HAKUREI_TEST=1"},
|
||||||
|
check.MustAbs("/opt/bin/testtool"),
|
||||||
|
[]string{"testtool", "net"},
|
||||||
|
|
||||||
|
pkg.MustPath("/file", newStubFile(
|
||||||
|
pkg.KindHTTPGet,
|
||||||
|
pkg.ID{0xfe, 0},
|
||||||
|
nil,
|
||||||
|
nil, nil,
|
||||||
|
)),
|
||||||
|
pkg.MustPath("/.hakurei", stubArtifact{
|
||||||
|
kind: pkg.KindTar,
|
||||||
|
params: []byte("empty directory"),
|
||||||
|
cure: func(c *pkg.CureContext) error {
|
||||||
|
return os.MkdirAll(c.GetWorkDir().String(), 0700)
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
pkg.MustPath("/opt", testtool),
|
||||||
|
), ignorePathname, wantChecksum, nil},
|
||||||
|
})
|
||||||
|
|
||||||
|
testtoolDestroy(t, base, c)
|
||||||
|
}, pkg.MustDecode("bBQVFIt0FnOulljgpLnGtuzHSFgwiCMjc4pmc4rHRqXKQ60Q5aBVYp5f6aH9VdZi")},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -185,6 +185,9 @@ const (
|
|||||||
KindTar
|
KindTar
|
||||||
// KindExec is the kind of [Artifact] returned by [NewExec].
|
// KindExec is the kind of [Artifact] returned by [NewExec].
|
||||||
KindExec
|
KindExec
|
||||||
|
// KindExecNet is the kind of [Artifact] returned by [NewExec] but with a
|
||||||
|
// non-nil checksum.
|
||||||
|
KindExecNet
|
||||||
)
|
)
|
||||||
|
|
||||||
// Ident returns a deterministic identifier for the supplied params and
|
// Ident returns a deterministic identifier for the supplied params and
|
||||||
|
|||||||
36
internal/pkg/testdata/main.go
vendored
36
internal/pkg/testdata/main.go
vendored
@@ -16,7 +16,13 @@ func main() {
|
|||||||
log.SetFlags(0)
|
log.SetFlags(0)
|
||||||
log.SetPrefix("testtool: ")
|
log.SetPrefix("testtool: ")
|
||||||
|
|
||||||
if wantArgs := []string{"testtool"}; !slices.Equal(os.Args, wantArgs) {
|
var hostNet bool
|
||||||
|
wantArgs := []string{"testtool"}
|
||||||
|
if len(os.Args) == 2 {
|
||||||
|
hostNet = true
|
||||||
|
wantArgs = []string{"testtool", "net"}
|
||||||
|
}
|
||||||
|
if !slices.Equal(os.Args, wantArgs) {
|
||||||
log.Fatalf("Args: %q, want %q", os.Args, wantArgs)
|
log.Fatalf("Args: %q, want %q", os.Args, wantArgs)
|
||||||
}
|
}
|
||||||
if wantEnv := []string{
|
if wantEnv := []string{
|
||||||
@@ -31,6 +37,22 @@ func main() {
|
|||||||
log.Fatalf("Executable: %q, want %q", got, wantExec)
|
log.Fatalf("Executable: %q, want %q", got, wantExec)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wantHostname := "cure"
|
||||||
|
if hostNet {
|
||||||
|
wantHostname += "-net"
|
||||||
|
}
|
||||||
|
|
||||||
|
if hostname, err := os.Hostname(); err != nil {
|
||||||
|
log.Fatalf("Hostname: error = %v", err)
|
||||||
|
} else if hostname != wantHostname {
|
||||||
|
log.Fatalf("Hostname: %q, want %q", hostname, wantHostname)
|
||||||
|
}
|
||||||
|
|
||||||
|
ident := "oHuqV7p0v1Vd8IdAzjyYM8sfCS0P2LR5tfv5cb6Gbf2ZWUm8Ec-7hYPJ_qr183m7"
|
||||||
|
if hostNet {
|
||||||
|
ident = "I3T53NtN6HPAyyodHtq2B0clcsoS1nPdvCEb-Zc5K-hoqFGL2od1mftHhwG7gX1S"
|
||||||
|
}
|
||||||
|
|
||||||
var m *vfs.MountInfo
|
var m *vfs.MountInfo
|
||||||
if f, err := os.Open(fhs.Proc + "self/mountinfo"); err != nil {
|
if f, err := os.Open(fhs.Proc + "self/mountinfo"); err != nil {
|
||||||
log.Fatalf("Open: error = %v", err)
|
log.Fatalf("Open: error = %v", err)
|
||||||
@@ -64,14 +86,12 @@ func main() {
|
|||||||
next() // testtool artifact
|
next() // testtool artifact
|
||||||
|
|
||||||
next()
|
next()
|
||||||
if path.Base(m.Root) !=
|
if path.Base(m.Root) != ident || m.Target != "/work" {
|
||||||
"oHuqV7p0v1Vd8IdAzjyYM8sfCS0P2LR5tfv5cb6Gbf2ZWUm8Ec-7hYPJ_qr183m7" || m.Target != "/work" {
|
|
||||||
log.Fatal("unexpected work mount entry")
|
log.Fatal("unexpected work mount entry")
|
||||||
}
|
}
|
||||||
|
|
||||||
next()
|
next()
|
||||||
if path.Base(m.Root) !=
|
if path.Base(m.Root) != ident || m.Target != "/tmp" {
|
||||||
"oHuqV7p0v1Vd8IdAzjyYM8sfCS0P2LR5tfv5cb6Gbf2ZWUm8Ec-7hYPJ_qr183m7" || m.Target != "/tmp" {
|
|
||||||
log.Fatal("unexpected temp mount entry")
|
log.Fatal("unexpected temp mount entry")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,7 +117,11 @@ func main() {
|
|||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := os.WriteFile("check", []byte{0}, 0400); err != nil {
|
checkData := []byte{0}
|
||||||
|
if hostNet {
|
||||||
|
checkData = []byte("net")
|
||||||
|
}
|
||||||
|
if err := os.WriteFile("check", checkData, 0400); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user