internal/pkg: support explicit overlay mount
All checks were successful
Test / Create distribution (push) Successful in 47s
Test / Sandbox (push) Successful in 2m48s
Test / ShareFS (push) Successful in 4m43s
Test / Sandbox (race detector) (push) Successful in 5m15s
Test / Hpkg (push) Successful in 5m25s
Test / Hakurei (push) Successful in 5m38s
Test / Hakurei (race detector) (push) Successful in 7m28s
Test / Flake checks (push) Successful in 1m44s
All checks were successful
Test / Create distribution (push) Successful in 47s
Test / Sandbox (push) Successful in 2m48s
Test / ShareFS (push) Successful in 4m43s
Test / Sandbox (race detector) (push) Successful in 5m15s
Test / Hpkg (push) Successful in 5m25s
Test / Hakurei (push) Successful in 5m38s
Test / Hakurei (race detector) (push) Successful in 7m28s
Test / Flake checks (push) Successful in 1m44s
This removes all but the /work/ auto overlay behaviour and enables much greater flexibility. This also renames ExecContainerPath to ExecPath so it is easier to type. Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
@@ -295,9 +295,9 @@ func TestFlatten(t *testing.T) {
|
|||||||
"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/U2cbgVgEtjfRuvHfE1cQnZ3t8yoexULQyo_VLgvxAVJSsobMcNaFIsuDWtmt7kzK": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9")},
|
||||||
"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")},
|
|
||||||
|
|
||||||
"temp": {Mode: fs.ModeDir | 0700},
|
"temp": {Mode: fs.ModeDir | 0700},
|
||||||
"work": {Mode: fs.ModeDir | 0700},
|
"work": {Mode: fs.ModeDir | 0700},
|
||||||
@@ -311,13 +311,13 @@ func TestFlatten(t *testing.T) {
|
|||||||
{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/U2cbgVgEtjfRuvHfE1cQnZ3t8yoexULQyo_VLgvxAVJSsobMcNaFIsuDWtmt7kzK", Data: []byte("../checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9")},
|
||||||
{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.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"), nil},
|
}, pkg.MustDecode("UiV6kMz7KrTsc_yphiyQzFLqjRanHxUOwrBMtkKuWo4mOO6WgPFAcoUEeSp7eVIW"), nil},
|
||||||
|
|
||||||
{"testtool net", fstest.MapFS{
|
{"testtool net", fstest.MapFS{
|
||||||
".": {Mode: fs.ModeDir | 0500},
|
".": {Mode: fs.ModeDir | 0500},
|
||||||
@@ -340,7 +340,7 @@ func TestFlatten(t *testing.T) {
|
|||||||
|
|
||||||
"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/I3T53NtN6HPAyyodHtq2B0clcsoS1nPdvCEb-Zc5K-hoqFGL2od1mftHhwG7gX1S": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/a1F_i9PVQI4qMcoHgTQkORuyWLkC1GLIxOhDt2JpU1NGAxWc5VJzdlfRK-PYBh3W")},
|
"identifier/QdsJhGgnk5N2xdUNGcndXQxFKifxf1V_2t9X8CQ-pDcg24x6mGJC_BiLfGbs6Qml": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/a1F_i9PVQI4qMcoHgTQkORuyWLkC1GLIxOhDt2JpU1NGAxWc5VJzdlfRK-PYBh3W")},
|
||||||
"identifier/nfeISfLeFDr1k-g3hpE1oZ440kTqDdfF8TDpoLdbTPqaMMIl95oiqcvqjRkMjubA": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
|
"identifier/nfeISfLeFDr1k-g3hpE1oZ440kTqDdfF8TDpoLdbTPqaMMIl95oiqcvqjRkMjubA": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
|
||||||
|
|
||||||
"temp": {Mode: fs.ModeDir | 0700},
|
"temp": {Mode: fs.ModeDir | 0700},
|
||||||
@@ -355,13 +355,13 @@ func TestFlatten(t *testing.T) {
|
|||||||
{Mode: 0400, Path: "checksum/a1F_i9PVQI4qMcoHgTQkORuyWLkC1GLIxOhDt2JpU1NGAxWc5VJzdlfRK-PYBh3W/check", Data: []byte("net")},
|
{Mode: 0400, Path: "checksum/a1F_i9PVQI4qMcoHgTQkORuyWLkC1GLIxOhDt2JpU1NGAxWc5VJzdlfRK-PYBh3W/check", Data: []byte("net")},
|
||||||
|
|
||||||
{Mode: fs.ModeDir | 0700, Path: "identifier"},
|
{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/QdsJhGgnk5N2xdUNGcndXQxFKifxf1V_2t9X8CQ-pDcg24x6mGJC_BiLfGbs6Qml", 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/_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.ModeDir | 0700, Path: "temp"},
|
{Mode: fs.ModeDir | 0700, Path: "temp"},
|
||||||
{Mode: fs.ModeDir | 0700, Path: "work"},
|
{Mode: fs.ModeDir | 0700, Path: "work"},
|
||||||
}, pkg.MustDecode("bBQVFIt0FnOulljgpLnGtuzHSFgwiCMjc4pmc4rHRqXKQ60Q5aBVYp5f6aH9VdZi"), nil},
|
}, pkg.MustDecode("ek4K-0d4iRSArkY2TCs3WK34DbiYeOmhE_4vsJTSu_6roY4ZF3YG6eKRooal-i1o"), nil},
|
||||||
|
|
||||||
{"sample exec container overlay root", fstest.MapFS{
|
{"sample exec container overlay root", fstest.MapFS{
|
||||||
".": {Mode: fs.ModeDir | 0700},
|
".": {Mode: fs.ModeDir | 0700},
|
||||||
@@ -372,7 +372,7 @@ func TestFlatten(t *testing.T) {
|
|||||||
"checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU": {Mode: fs.ModeDir | 0500},
|
"checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU": {Mode: fs.ModeDir | 0500},
|
||||||
|
|
||||||
"identifier": {Mode: fs.ModeDir | 0700},
|
"identifier": {Mode: fs.ModeDir | 0700},
|
||||||
"identifier/cIjP14zs5el6W_BQhufL_c0vWg-V6Z6pDpsbEa3sYtZ1381u1bKnH3N16RIrw-1S": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9")},
|
"identifier/5ey2wpmMpj483YYa7ZZQciYLA2cx3_l167JCqWW4Pd-5DVp81dj9EsBtVTwYptF6": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9")},
|
||||||
"identifier/nfeISfLeFDr1k-g3hpE1oZ440kTqDdfF8TDpoLdbTPqaMMIl95oiqcvqjRkMjubA": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
|
"identifier/nfeISfLeFDr1k-g3hpE1oZ440kTqDdfF8TDpoLdbTPqaMMIl95oiqcvqjRkMjubA": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
|
||||||
|
|
||||||
"temp": {Mode: fs.ModeDir | 0700},
|
"temp": {Mode: fs.ModeDir | 0700},
|
||||||
@@ -386,42 +386,12 @@ func TestFlatten(t *testing.T) {
|
|||||||
{Mode: fs.ModeDir | 0500, Path: "checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU"},
|
{Mode: fs.ModeDir | 0500, Path: "checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU"},
|
||||||
|
|
||||||
{Mode: fs.ModeDir | 0700, Path: "identifier"},
|
{Mode: fs.ModeDir | 0700, Path: "identifier"},
|
||||||
{Mode: fs.ModeSymlink | 0777, Path: "identifier/cIjP14zs5el6W_BQhufL_c0vWg-V6Z6pDpsbEa3sYtZ1381u1bKnH3N16RIrw-1S", Data: []byte("../checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9")},
|
{Mode: fs.ModeSymlink | 0777, Path: "identifier/5ey2wpmMpj483YYa7ZZQciYLA2cx3_l167JCqWW4Pd-5DVp81dj9EsBtVTwYptF6", Data: []byte("../checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9")},
|
||||||
{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.ModeDir | 0700, Path: "temp"},
|
{Mode: fs.ModeDir | 0700, Path: "temp"},
|
||||||
{Mode: fs.ModeDir | 0700, Path: "work"},
|
{Mode: fs.ModeDir | 0700, Path: "work"},
|
||||||
}, pkg.MustDecode("gFT9kprYBqEJKifJIl2sHn_3TgULWVLTU4DrYAHiGcRmcdFRZ0YtjiROW820cAEc"), nil},
|
}, pkg.MustDecode("VIqqpf0ip9jcyw63i6E8lCMGUcLivQBe4Bevt3WusNac-1MSy5bzB647qGUBzl-W"), nil},
|
||||||
|
|
||||||
{"sample exec container overlay temp", fstest.MapFS{
|
|
||||||
".": {Mode: fs.ModeDir | 0700},
|
|
||||||
|
|
||||||
"checksum": {Mode: fs.ModeDir | 0700},
|
|
||||||
"checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9": {Mode: fs.ModeDir | 0500},
|
|
||||||
"checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9/check": {Mode: 0400, Data: []byte{0}},
|
|
||||||
"checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU": {Mode: fs.ModeDir | 0500},
|
|
||||||
|
|
||||||
"identifier": {Mode: fs.ModeDir | 0700},
|
|
||||||
"identifier/3ELJ8l42g6XeIoLGR9LheVhMIwSIleD6VrhsliBuon5DAdBOwFSMqd7aiUI4fll7": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9")},
|
|
||||||
"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/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9"},
|
|
||||||
{Mode: 0400, Path: "checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9/check", Data: []byte{0}},
|
|
||||||
{Mode: fs.ModeDir | 0500, Path: "checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU"},
|
|
||||||
|
|
||||||
{Mode: fs.ModeDir | 0700, Path: "identifier"},
|
|
||||||
{Mode: fs.ModeSymlink | 0777, Path: "identifier/3ELJ8l42g6XeIoLGR9LheVhMIwSIleD6VrhsliBuon5DAdBOwFSMqd7aiUI4fll7", Data: []byte("../checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9")},
|
|
||||||
{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("_r1IBeMWCkLwQ9Im9w0tV9_CWIOfQlXkkP2CogPHLmZp_AB6W3_8HVZqDV00dNAm"), nil},
|
|
||||||
|
|
||||||
{"sample exec container overlay work", fstest.MapFS{
|
{"sample exec container overlay work", fstest.MapFS{
|
||||||
".": {Mode: fs.ModeDir | 0700},
|
".": {Mode: fs.ModeDir | 0700},
|
||||||
@@ -432,7 +402,7 @@ func TestFlatten(t *testing.T) {
|
|||||||
"checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU": {Mode: fs.ModeDir | 0500},
|
"checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU": {Mode: fs.ModeDir | 0500},
|
||||||
|
|
||||||
"identifier": {Mode: fs.ModeDir | 0700},
|
"identifier": {Mode: fs.ModeDir | 0700},
|
||||||
"identifier/VMCurZKCA_MV80zb-ZBWVytfl3rhYOKJeo2u9l-OuaytQ_w_r4EsqgJ2nfO93x5_": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9")},
|
"identifier/5ynpgDp5mcAmbFndOESXjQnOy_RG6furIxDpQz6c0bImBBLMAI8FouNbAB0uNs6f": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9")},
|
||||||
"identifier/nfeISfLeFDr1k-g3hpE1oZ440kTqDdfF8TDpoLdbTPqaMMIl95oiqcvqjRkMjubA": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
|
"identifier/nfeISfLeFDr1k-g3hpE1oZ440kTqDdfF8TDpoLdbTPqaMMIl95oiqcvqjRkMjubA": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
|
||||||
|
|
||||||
"temp": {Mode: fs.ModeDir | 0700},
|
"temp": {Mode: fs.ModeDir | 0700},
|
||||||
@@ -446,12 +416,12 @@ func TestFlatten(t *testing.T) {
|
|||||||
{Mode: fs.ModeDir | 0500, Path: "checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU"},
|
{Mode: fs.ModeDir | 0500, Path: "checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU"},
|
||||||
|
|
||||||
{Mode: fs.ModeDir | 0700, Path: "identifier"},
|
{Mode: fs.ModeDir | 0700, Path: "identifier"},
|
||||||
{Mode: fs.ModeSymlink | 0777, Path: "identifier/VMCurZKCA_MV80zb-ZBWVytfl3rhYOKJeo2u9l-OuaytQ_w_r4EsqgJ2nfO93x5_", Data: []byte("../checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9")},
|
{Mode: fs.ModeSymlink | 0777, Path: "identifier/5ynpgDp5mcAmbFndOESXjQnOy_RG6furIxDpQz6c0bImBBLMAI8FouNbAB0uNs6f", Data: []byte("../checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9")},
|
||||||
{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.ModeDir | 0700, Path: "temp"},
|
{Mode: fs.ModeDir | 0700, Path: "temp"},
|
||||||
{Mode: fs.ModeDir | 0700, Path: "work"},
|
{Mode: fs.ModeDir | 0700, Path: "work"},
|
||||||
}, pkg.MustDecode("-DrfvuB9gUAT-Tgw6V1KjFyosYGMGKJW7KMZFF1Ew8jZ9LJ82FtXf0wTgM3fO0oD"), nil},
|
}, pkg.MustDecode("RibudsoY1X4_dtshfvL5LYfCPcxVnP0ikOn3yBHzOrt6BpevQiANLJF6Xua76-gM"), nil},
|
||||||
|
|
||||||
{"sample file short", fstest.MapFS{
|
{"sample file short", fstest.MapFS{
|
||||||
".": {Mode: fs.ModeDir | 0700},
|
".": {Mode: fs.ModeDir | 0700},
|
||||||
|
|||||||
@@ -20,17 +20,27 @@ import (
|
|||||||
// AbsWork is the container pathname [CureContext.GetWorkDir] is mounted on.
|
// AbsWork is the container pathname [CureContext.GetWorkDir] is mounted on.
|
||||||
var AbsWork = fhs.AbsRoot.Append("work/")
|
var AbsWork = fhs.AbsRoot.Append("work/")
|
||||||
|
|
||||||
// ExecContainerPath is an [Artifact] and the [check.Absolute] pathname to make
|
// ExecPath is a slice of [Artifact] and the [check.Absolute] pathname to make
|
||||||
// it available under in the container.
|
// it available at under in the container.
|
||||||
type ExecContainerPath struct {
|
type ExecPath struct {
|
||||||
|
// Pathname in the container mount namespace.
|
||||||
P *check.Absolute
|
P *check.Absolute
|
||||||
A Artifact
|
// Artifacts to mount on the pathname, must contain at least one [Artifact].
|
||||||
|
// If there are multiple entries or W is true, P is set up as an overlay
|
||||||
|
// mount, and entries of A must not implement [File].
|
||||||
|
A []Artifact
|
||||||
|
// Whether to make the mount point writable via an invisible tmpfs upperdir.
|
||||||
|
W bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustPath returns [ExecContainerPath] for pathname and [Artifact] and panics
|
// Path returns a populated [ExecPath].
|
||||||
// if pathname is not absolute.
|
func Path(pathname *check.Absolute, writable bool, a ...Artifact) ExecPath {
|
||||||
func MustPath(pathname string, a Artifact) ExecContainerPath {
|
return ExecPath{pathname, a, writable}
|
||||||
return ExecContainerPath{check.MustAbs(pathname), a}
|
}
|
||||||
|
|
||||||
|
// MustPath is like [Path], but takes a string pathname via [check.MustAbs].
|
||||||
|
func MustPath(pathname string, writable bool, a ...Artifact) ExecPath {
|
||||||
|
return ExecPath{check.MustAbs(pathname), a, writable}
|
||||||
}
|
}
|
||||||
|
|
||||||
// An execArtifact is an [Artifact] that produces output by running a program
|
// An execArtifact is an [Artifact] that produces output by running a program
|
||||||
@@ -41,8 +51,8 @@ func MustPath(pathname string, a Artifact) ExecContainerPath {
|
|||||||
type execArtifact struct {
|
type execArtifact struct {
|
||||||
// Caller-supplied context.
|
// Caller-supplied context.
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
// Caller-supplied inner read-only bind mounts.
|
// Caller-supplied inner mount points.
|
||||||
paths []ExecContainerPath
|
paths []ExecPath
|
||||||
// Caller-supplied logging facility, passed through to [container] and used
|
// Caller-supplied logging facility, passed through to [container] and used
|
||||||
// internally to produce verbose output.
|
// internally to produce verbose output.
|
||||||
msg message.Msg
|
msg message.Msg
|
||||||
@@ -95,20 +105,11 @@ func (a *execNetArtifact) Cure(c *CureContext) error {
|
|||||||
//
|
//
|
||||||
// The working and temporary directories are both created and mounted writable
|
// The working and temporary directories are both created and mounted writable
|
||||||
// on [AbsWork] and [fhs.AbsTmp] respectively. If one or more paths target
|
// on [AbsWork] and [fhs.AbsTmp] respectively. If one or more paths target
|
||||||
// [fhs.AbsTmp], the final entry is set up as a writable overlay mount on /tmp
|
|
||||||
// backed by the host side temporary directory. If one or more paths target
|
|
||||||
// [AbsWork], the final entry is set up as a writable overlay mount on /work for
|
// [AbsWork], the final entry is set up as a writable overlay mount on /work for
|
||||||
// which the upperdir is the host side work directory. In this configuration,
|
// which the upperdir is the host side work directory. In this configuration,
|
||||||
// the program must avoid causing whiteout files to be created, cure fails if
|
// the W field is ignored, and the program must avoid causing whiteout files to
|
||||||
// upperdir ends up with anything other than directory, regular or symlink
|
// be created. Cure fails if upperdir ends up with entries other than directory,
|
||||||
// entries.
|
// regular or symlink.
|
||||||
//
|
|
||||||
// If the first path targets [fhs.AbsRoot], it is made writable via an overlay
|
|
||||||
// mount with writes going to an ephemeral tmpfs bound to the lifetime of the
|
|
||||||
// container. This is primarily to make it possible for [container] to set up
|
|
||||||
// mount points targeting paths not available in the [Artifact] backing root,
|
|
||||||
// and to accommodate poorly written programs that insist on writing to awkward
|
|
||||||
// paths, it must not be used as scratch space.
|
|
||||||
//
|
//
|
||||||
// If checksum is non-nil, the resulting [Artifact] implements [KnownChecksum]
|
// If checksum is non-nil, the resulting [Artifact] implements [KnownChecksum]
|
||||||
// and its container runs in the host net namespace.
|
// and its container runs in the host net namespace.
|
||||||
@@ -126,7 +127,7 @@ func NewExec(
|
|||||||
path *check.Absolute,
|
path *check.Absolute,
|
||||||
args []string,
|
args []string,
|
||||||
|
|
||||||
paths ...ExecContainerPath,
|
paths ...ExecPath,
|
||||||
) Artifact {
|
) Artifact {
|
||||||
a := execArtifact{ctx, paths, msg, cures, dir, env, path, args}
|
a := execArtifact{ctx, paths, msg, cures, dir, env, path, args}
|
||||||
if checksum == nil {
|
if checksum == nil {
|
||||||
@@ -142,17 +143,22 @@ func (a *execArtifact) Kind() Kind { return KindExec }
|
|||||||
func (a *execArtifact) Params() []byte {
|
func (a *execArtifact) Params() []byte {
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
for _, p := range a.paths {
|
for _, p := range a.paths {
|
||||||
|
if p.W {
|
||||||
|
buf.WriteByte(1)
|
||||||
|
} else {
|
||||||
|
buf.WriteByte(0)
|
||||||
|
}
|
||||||
if p.P != nil {
|
if p.P != nil {
|
||||||
buf.WriteString(p.P.String())
|
buf.WriteString(p.P.String())
|
||||||
} else {
|
} else {
|
||||||
buf.WriteString("invalid P\x00")
|
buf.WriteString("invalid P\x00")
|
||||||
}
|
}
|
||||||
if p.A != nil {
|
buf.WriteByte(0)
|
||||||
id := Ident(p.A)
|
for _, d := range p.A {
|
||||||
|
id := Ident(d)
|
||||||
buf.Write(id[:])
|
buf.Write(id[:])
|
||||||
} else {
|
|
||||||
buf.WriteString("invalid A\x00")
|
|
||||||
}
|
}
|
||||||
|
buf.WriteByte(0)
|
||||||
}
|
}
|
||||||
buf.WriteByte(0)
|
buf.WriteByte(0)
|
||||||
buf.WriteString(a.dir.String())
|
buf.WriteString(a.dir.String())
|
||||||
@@ -170,15 +176,13 @@ func (a *execArtifact) Params() []byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Dependencies returns a slice of all artifacts collected from caller-supplied
|
// Dependencies returns a slice of all artifacts collected from caller-supplied
|
||||||
// [ExecContainerPath].
|
// [ExecPath].
|
||||||
func (a *execArtifact) Dependencies() []Artifact {
|
func (a *execArtifact) Dependencies() []Artifact {
|
||||||
artifacts := make([]Artifact, 0, len(a.paths))
|
artifacts := make([][]Artifact, 0, len(a.paths))
|
||||||
for _, p := range a.paths {
|
for _, p := range a.paths {
|
||||||
if p.A != nil {
|
artifacts = append(artifacts, p.A)
|
||||||
artifacts = append(artifacts, p.A)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return artifacts
|
return slices.Concat(artifacts...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cure cures the [Artifact] by curing all its dependencies then running the
|
// Cure cures the [Artifact] by curing all its dependencies then running the
|
||||||
@@ -200,35 +204,42 @@ func (a *execArtifact) cure(c *CureContext, hostNet bool) (err error) {
|
|||||||
cures = runtime.NumCPU()
|
cures = runtime.NumCPU()
|
||||||
}
|
}
|
||||||
|
|
||||||
overlayTempIndex, overlayWorkIndex := -1, -1
|
overlayWorkIndex := -1
|
||||||
paths := make([][2]*check.Absolute, len(a.paths))
|
type curePath struct {
|
||||||
|
// Copied from ExecPath.P.
|
||||||
|
dst *check.Absolute
|
||||||
|
// Cured from ExecPath.A.
|
||||||
|
src []*check.Absolute
|
||||||
|
}
|
||||||
|
paths := make([]curePath, len(a.paths))
|
||||||
for i, p := range a.paths {
|
for i, p := range a.paths {
|
||||||
if p.P == nil || p.A == nil {
|
if p.P == nil || len(p.A) == 0 {
|
||||||
return os.ErrInvalid
|
return os.ErrInvalid
|
||||||
}
|
}
|
||||||
if p.P.Is(fhs.AbsTmp) {
|
if p.P.Is(AbsWork) {
|
||||||
overlayTempIndex = i
|
|
||||||
} else if p.P.Is(AbsWork) {
|
|
||||||
overlayWorkIndex = i
|
overlayWorkIndex = i
|
||||||
}
|
}
|
||||||
paths[i][1] = p.P
|
paths[i].dst = p.P
|
||||||
|
paths[i].src = make([]*check.Absolute, len(p.A))
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(paths) > 0 {
|
if len(paths) > 0 {
|
||||||
type cureArtifact struct {
|
type cureArtifact struct {
|
||||||
// Index of pending Artifact in paths.
|
// Index of pending Artifact in paths.
|
||||||
index int
|
index [2]int
|
||||||
// Pending artifact.
|
// Pending artifact.
|
||||||
a Artifact
|
a Artifact
|
||||||
}
|
}
|
||||||
ac := make(chan cureArtifact, len(paths))
|
ac := make(chan cureArtifact, len(paths))
|
||||||
for i, p := range a.paths {
|
for i, p := range a.paths {
|
||||||
ac <- cureArtifact{i, p.A}
|
for j, d := range p.A {
|
||||||
|
ac <- cureArtifact{[2]int{i, j}, d}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type cureRes struct {
|
type cureRes struct {
|
||||||
// Index of result in paths.
|
// Index of result in paths.
|
||||||
index int
|
index [2]int
|
||||||
// Cured pathname.
|
// Cured pathname.
|
||||||
pathname *check.Absolute
|
pathname *check.Absolute
|
||||||
// Error returned by c.
|
// Error returned by c.
|
||||||
@@ -260,7 +271,7 @@ func (a *execArtifact) cure(c *CureContext, hostNet bool) (err error) {
|
|||||||
if cr.err != nil {
|
if cr.err != nil {
|
||||||
errs = append(errs, cr.err)
|
errs = append(errs, cr.err)
|
||||||
} else {
|
} else {
|
||||||
paths[cr.index][0] = cr.pathname
|
paths[cr.index[0]].src[cr.index[1]] = cr.pathname
|
||||||
}
|
}
|
||||||
|
|
||||||
if count == len(paths) {
|
if count == len(paths) {
|
||||||
@@ -293,32 +304,9 @@ func (a *execArtifact) cure(c *CureContext, hostNet bool) (err error) {
|
|||||||
|
|
||||||
z.Dir, z.Env, z.Path, z.Args = a.dir, a.env, a.path, a.args
|
z.Dir, z.Env, z.Path, z.Args = a.dir, a.env, a.path, a.args
|
||||||
z.Grow(len(paths) + 4)
|
z.Grow(len(paths) + 4)
|
||||||
if len(paths) > 0 && paths[0][1].Is(fhs.AbsRoot) {
|
|
||||||
z.OverlayEphemeral(fhs.AbsRoot, paths[0][0])
|
|
||||||
paths = paths[1:]
|
|
||||||
overlayTempIndex--
|
|
||||||
overlayWorkIndex--
|
|
||||||
}
|
|
||||||
|
|
||||||
temp, work := c.GetTempDir(), c.GetWorkDir()
|
temp, work := c.GetTempDir(), c.GetWorkDir()
|
||||||
for i, b := range paths {
|
for i, b := range paths {
|
||||||
if i == overlayTempIndex {
|
|
||||||
tempUpper := temp.Append("upper")
|
|
||||||
if err = os.MkdirAll(tempUpper.String(), 0700); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
tempWork := temp.Append("work")
|
|
||||||
if err = os.MkdirAll(tempWork.String(), 0700); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
z.Overlay(
|
|
||||||
fhs.AbsTmp,
|
|
||||||
tempUpper,
|
|
||||||
tempWork,
|
|
||||||
b[0],
|
|
||||||
)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if i == overlayWorkIndex {
|
if i == overlayWorkIndex {
|
||||||
if err = os.MkdirAll(work.String(), 0700); err != nil {
|
if err = os.MkdirAll(work.String(), 0700); err != nil {
|
||||||
return
|
return
|
||||||
@@ -331,11 +319,18 @@ func (a *execArtifact) cure(c *CureContext, hostNet bool) (err error) {
|
|||||||
AbsWork,
|
AbsWork,
|
||||||
work,
|
work,
|
||||||
tempWork,
|
tempWork,
|
||||||
b[0],
|
b.src...,
|
||||||
)
|
)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
z.Bind(b[0], b[1], 0)
|
|
||||||
|
if a.paths[i].W {
|
||||||
|
z.OverlayEphemeral(b.dst, b.src...)
|
||||||
|
} else if len(b.src) == 1 {
|
||||||
|
z.Bind(b.src[0], b.dst, 0)
|
||||||
|
} else {
|
||||||
|
z.OverlayReadonly(b.dst, b.src...)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if overlayWorkIndex < 0 {
|
if overlayWorkIndex < 0 {
|
||||||
z.Bind(
|
z.Bind(
|
||||||
@@ -344,13 +339,11 @@ func (a *execArtifact) cure(c *CureContext, hostNet bool) (err error) {
|
|||||||
std.BindWritable|std.BindEnsure,
|
std.BindWritable|std.BindEnsure,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if overlayTempIndex < 0 {
|
z.Bind(
|
||||||
z.Bind(
|
c.GetTempDir(),
|
||||||
c.GetTempDir(),
|
fhs.AbsTmp,
|
||||||
fhs.AbsTmp,
|
std.BindWritable|std.BindEnsure,
|
||||||
std.BindWritable|std.BindEnsure,
|
)
|
||||||
)
|
|
||||||
}
|
|
||||||
z.Proc(fhs.AbsProc).Dev(fhs.AbsDev, true)
|
z.Proc(fhs.AbsProc).Dev(fhs.AbsDev, true)
|
||||||
|
|
||||||
if err = z.Start(); err != nil {
|
if err = z.Start(); err != nil {
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"hakurei.app/container/check"
|
"hakurei.app/container/check"
|
||||||
"hakurei.app/container/fhs"
|
|
||||||
"hakurei.app/container/stub"
|
"hakurei.app/container/stub"
|
||||||
"hakurei.app/hst"
|
"hakurei.app/hst"
|
||||||
"hakurei.app/internal/pkg"
|
"hakurei.app/internal/pkg"
|
||||||
@@ -50,20 +49,20 @@ func TestExec(t *testing.T) {
|
|||||||
check.MustAbs("/opt/bin/testtool"),
|
check.MustAbs("/opt/bin/testtool"),
|
||||||
[]string{"testtool"},
|
[]string{"testtool"},
|
||||||
|
|
||||||
pkg.MustPath("/file", newStubFile(
|
pkg.MustPath("/file", false, newStubFile(
|
||||||
pkg.KindHTTPGet,
|
pkg.KindHTTPGet,
|
||||||
pkg.ID{0xfe, 0},
|
pkg.ID{0xfe, 0},
|
||||||
nil,
|
nil,
|
||||||
nil, nil,
|
nil, nil,
|
||||||
)),
|
)),
|
||||||
pkg.MustPath("/.hakurei", stubArtifact{
|
pkg.MustPath("/.hakurei", false, stubArtifact{
|
||||||
kind: pkg.KindTar,
|
kind: pkg.KindTar,
|
||||||
params: []byte("empty directory"),
|
params: []byte("empty directory"),
|
||||||
cure: func(c *pkg.CureContext) error {
|
cure: func(c *pkg.CureContext) error {
|
||||||
return os.MkdirAll(c.GetWorkDir().String(), 0700)
|
return os.MkdirAll(c.GetWorkDir().String(), 0700)
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
pkg.MustPath("/opt", testtool),
|
pkg.MustPath("/opt", false, testtool),
|
||||||
), ignorePathname, wantChecksumOffline, nil},
|
), ignorePathname, wantChecksumOffline, nil},
|
||||||
|
|
||||||
{"error passthrough", pkg.NewExec(
|
{"error passthrough", pkg.NewExec(
|
||||||
@@ -76,7 +75,7 @@ func TestExec(t *testing.T) {
|
|||||||
check.MustAbs("/opt/bin/testtool"),
|
check.MustAbs("/opt/bin/testtool"),
|
||||||
[]string{"testtool"},
|
[]string{"testtool"},
|
||||||
|
|
||||||
pkg.MustPath("/proc/nonexistent", stubArtifact{
|
pkg.MustPath("/proc/nonexistent", false, stubArtifact{
|
||||||
kind: pkg.KindTar,
|
kind: pkg.KindTar,
|
||||||
params: []byte("doomed artifact"),
|
params: []byte("doomed artifact"),
|
||||||
cure: func(c *pkg.CureContext) error {
|
cure: func(c *pkg.CureContext) error {
|
||||||
@@ -95,7 +94,7 @@ func TestExec(t *testing.T) {
|
|||||||
check.MustAbs("/opt/bin/testtool"),
|
check.MustAbs("/opt/bin/testtool"),
|
||||||
[]string{"testtool"},
|
[]string{"testtool"},
|
||||||
|
|
||||||
pkg.ExecContainerPath{},
|
pkg.ExecPath{},
|
||||||
), nil, pkg.Checksum{}, os.ErrInvalid},
|
), nil, pkg.Checksum{}, os.ErrInvalid},
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -116,7 +115,7 @@ func TestExec(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
testtoolDestroy(t, base, c)
|
testtoolDestroy(t, base, c)
|
||||||
}, pkg.MustDecode("7PoPpWLjFPXIymbuIYLZAzOpCYr-2PN4CZ11jFdO-mDlnZNgFO3JyOtK8HW8Jxvm")},
|
}, pkg.MustDecode("UiV6kMz7KrTsc_yphiyQzFLqjRanHxUOwrBMtkKuWo4mOO6WgPFAcoUEeSp7eVIW")},
|
||||||
|
|
||||||
{"net", nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
{"net", nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
||||||
c.SetStrict(true)
|
c.SetStrict(true)
|
||||||
@@ -139,25 +138,25 @@ func TestExec(t *testing.T) {
|
|||||||
check.MustAbs("/opt/bin/testtool"),
|
check.MustAbs("/opt/bin/testtool"),
|
||||||
[]string{"testtool", "net"},
|
[]string{"testtool", "net"},
|
||||||
|
|
||||||
pkg.MustPath("/file", newStubFile(
|
pkg.MustPath("/file", false, newStubFile(
|
||||||
pkg.KindHTTPGet,
|
pkg.KindHTTPGet,
|
||||||
pkg.ID{0xfe, 0},
|
pkg.ID{0xfe, 0},
|
||||||
nil,
|
nil,
|
||||||
nil, nil,
|
nil, nil,
|
||||||
)),
|
)),
|
||||||
pkg.MustPath("/.hakurei", stubArtifact{
|
pkg.MustPath("/.hakurei", false, stubArtifact{
|
||||||
kind: pkg.KindTar,
|
kind: pkg.KindTar,
|
||||||
params: []byte("empty directory"),
|
params: []byte("empty directory"),
|
||||||
cure: func(c *pkg.CureContext) error {
|
cure: func(c *pkg.CureContext) error {
|
||||||
return os.MkdirAll(c.GetWorkDir().String(), 0700)
|
return os.MkdirAll(c.GetWorkDir().String(), 0700)
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
pkg.MustPath("/opt", testtool),
|
pkg.MustPath("/opt", false, testtool),
|
||||||
), ignorePathname, wantChecksum, nil},
|
), ignorePathname, wantChecksum, nil},
|
||||||
})
|
})
|
||||||
|
|
||||||
testtoolDestroy(t, base, c)
|
testtoolDestroy(t, base, c)
|
||||||
}, pkg.MustDecode("bBQVFIt0FnOulljgpLnGtuzHSFgwiCMjc4pmc4rHRqXKQ60Q5aBVYp5f6aH9VdZi")},
|
}, pkg.MustDecode("ek4K-0d4iRSArkY2TCs3WK34DbiYeOmhE_4vsJTSu_6roY4ZF3YG6eKRooal-i1o")},
|
||||||
|
|
||||||
{"overlay root", nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
{"overlay root", nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
||||||
c.SetStrict(true)
|
c.SetStrict(true)
|
||||||
@@ -177,61 +176,19 @@ func TestExec(t *testing.T) {
|
|||||||
check.MustAbs("/opt/bin/testtool"),
|
check.MustAbs("/opt/bin/testtool"),
|
||||||
[]string{"testtool"},
|
[]string{"testtool"},
|
||||||
|
|
||||||
pkg.MustPath("/", stubArtifact{
|
pkg.MustPath("/", true, stubArtifact{
|
||||||
kind: pkg.KindTar,
|
kind: pkg.KindTar,
|
||||||
params: []byte("empty directory"),
|
params: []byte("empty directory"),
|
||||||
cure: func(c *pkg.CureContext) error {
|
cure: func(c *pkg.CureContext) error {
|
||||||
return os.MkdirAll(c.GetWorkDir().String(), 0700)
|
return os.MkdirAll(c.GetWorkDir().String(), 0700)
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
pkg.MustPath("/opt", testtool),
|
pkg.MustPath("/opt", false, testtool),
|
||||||
), ignorePathname, wantChecksumOffline, nil},
|
), ignorePathname, wantChecksumOffline, nil},
|
||||||
})
|
})
|
||||||
|
|
||||||
testtoolDestroy(t, base, c)
|
testtoolDestroy(t, base, c)
|
||||||
}, pkg.MustDecode("gFT9kprYBqEJKifJIl2sHn_3TgULWVLTU4DrYAHiGcRmcdFRZ0YtjiROW820cAEc")},
|
}, pkg.MustDecode("VIqqpf0ip9jcyw63i6E8lCMGUcLivQBe4Bevt3WusNac-1MSy5bzB647qGUBzl-W")},
|
||||||
|
|
||||||
{"overlay temp", 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())
|
|
||||||
|
|
||||||
cureMany(t, c, []cureStep{
|
|
||||||
{"container", pkg.NewExec(
|
|
||||||
t.Context(),
|
|
||||||
msg,
|
|
||||||
0,
|
|
||||||
nil,
|
|
||||||
pkg.AbsWork,
|
|
||||||
[]string{"HAKUREI_TEST=1", "HAKUREI_ROOT=1"},
|
|
||||||
check.MustAbs("/tmp/bin/testtool"),
|
|
||||||
[]string{"testtool"},
|
|
||||||
|
|
||||||
pkg.MustPath("/", stubArtifact{
|
|
||||||
kind: pkg.KindTar,
|
|
||||||
params: []byte("empty directory"),
|
|
||||||
cure: func(c *pkg.CureContext) error {
|
|
||||||
return os.MkdirAll(c.GetWorkDir().String(), 0700)
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
pkg.MustPath("/tmp/", stubArtifact{
|
|
||||||
kind: pkg.KindTar,
|
|
||||||
params: []byte("empty directory"),
|
|
||||||
cure: func(c *pkg.CureContext) error {
|
|
||||||
return os.MkdirAll(c.GetWorkDir().String(), 0700)
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
pkg.ExecContainerPath{
|
|
||||||
P: fhs.AbsTmp,
|
|
||||||
A: testtool,
|
|
||||||
},
|
|
||||||
), ignorePathname, wantChecksumOffline, nil},
|
|
||||||
})
|
|
||||||
|
|
||||||
testtoolDestroy(t, base, c)
|
|
||||||
}, pkg.MustDecode("_r1IBeMWCkLwQ9Im9w0tV9_CWIOfQlXkkP2CogPHLmZp_AB6W3_8HVZqDV00dNAm")},
|
|
||||||
|
|
||||||
{"overlay work", nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
{"overlay work", nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
||||||
c.SetStrict(true)
|
c.SetStrict(true)
|
||||||
@@ -251,29 +208,24 @@ func TestExec(t *testing.T) {
|
|||||||
check.MustAbs("/work/bin/testtool"),
|
check.MustAbs("/work/bin/testtool"),
|
||||||
[]string{"testtool"},
|
[]string{"testtool"},
|
||||||
|
|
||||||
pkg.MustPath("/", stubArtifact{
|
pkg.MustPath("/", true, stubArtifact{
|
||||||
kind: pkg.KindTar,
|
kind: pkg.KindTar,
|
||||||
params: []byte("empty directory"),
|
params: []byte("empty directory"),
|
||||||
cure: func(c *pkg.CureContext) error {
|
cure: func(c *pkg.CureContext) error {
|
||||||
return os.MkdirAll(c.GetWorkDir().String(), 0700)
|
return os.MkdirAll(c.GetWorkDir().String(), 0700)
|
||||||
},
|
},
|
||||||
}),
|
}), pkg.MustPath("/work/", false, stubArtifact{
|
||||||
pkg.MustPath("/work/", stubArtifact{
|
|
||||||
kind: pkg.KindTar,
|
kind: pkg.KindTar,
|
||||||
params: []byte("empty directory"),
|
params: []byte("empty directory"),
|
||||||
cure: func(c *pkg.CureContext) error {
|
cure: func(c *pkg.CureContext) error {
|
||||||
return os.MkdirAll(c.GetWorkDir().String(), 0700)
|
return os.MkdirAll(c.GetWorkDir().String(), 0700)
|
||||||
},
|
},
|
||||||
}),
|
}), pkg.Path(pkg.AbsWork, false /* ignored */, testtool),
|
||||||
pkg.ExecContainerPath{
|
|
||||||
P: pkg.AbsWork,
|
|
||||||
A: testtool,
|
|
||||||
},
|
|
||||||
), ignorePathname, wantChecksumOffline, nil},
|
), ignorePathname, wantChecksumOffline, nil},
|
||||||
})
|
})
|
||||||
|
|
||||||
testtoolDestroy(t, base, c)
|
testtoolDestroy(t, base, c)
|
||||||
}, pkg.MustDecode("-DrfvuB9gUAT-Tgw6V1KjFyosYGMGKJW7KMZFF1Ew8jZ9LJ82FtXf0wTgM3fO0oD")},
|
}, pkg.MustDecode("RibudsoY1X4_dtshfvL5LYfCPcxVnP0ikOn3yBHzOrt6BpevQiANLJF6Xua76-gM")},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
44
internal/pkg/testdata/main.go
vendored
44
internal/pkg/testdata/main.go
vendored
@@ -24,6 +24,7 @@ func main() {
|
|||||||
wantArgs := []string{"testtool"}
|
wantArgs := []string{"testtool"}
|
||||||
if len(os.Args) == 2 {
|
if len(os.Args) == 2 {
|
||||||
hostNet = true
|
hostNet = true
|
||||||
|
log.SetPrefix("testtool(net): ")
|
||||||
wantArgs = []string{"testtool", "net"}
|
wantArgs = []string{"testtool", "net"}
|
||||||
}
|
}
|
||||||
if !slices.Equal(os.Args, wantArgs) {
|
if !slices.Equal(os.Args, wantArgs) {
|
||||||
@@ -34,27 +35,25 @@ func main() {
|
|||||||
wantEnv := []string{"HAKUREI_TEST=1"}
|
wantEnv := []string{"HAKUREI_TEST=1"}
|
||||||
if len(os.Environ()) == 2 {
|
if len(os.Environ()) == 2 {
|
||||||
overlayRoot = true
|
overlayRoot = true
|
||||||
|
log.SetPrefix("testtool(overlay root): ")
|
||||||
wantEnv = []string{"HAKUREI_TEST=1", "HAKUREI_ROOT=1"}
|
wantEnv = []string{"HAKUREI_TEST=1", "HAKUREI_ROOT=1"}
|
||||||
}
|
}
|
||||||
if !slices.Equal(wantEnv, os.Environ()) {
|
if !slices.Equal(wantEnv, os.Environ()) {
|
||||||
log.Fatalf("Environ: %q, want %q", os.Environ(), wantEnv)
|
log.Fatalf("Environ: %q, want %q", os.Environ(), wantEnv)
|
||||||
}
|
}
|
||||||
|
|
||||||
var overlayTmp, overlayWork bool
|
var overlayWork bool
|
||||||
const (
|
const (
|
||||||
wantExec = "/opt/bin/testtool"
|
wantExec = "/opt/bin/testtool"
|
||||||
wantExecTmp = "/tmp/bin/testtool"
|
|
||||||
wantExecWork = "/work/bin/testtool"
|
wantExecWork = "/work/bin/testtool"
|
||||||
)
|
)
|
||||||
if got, err := os.Executable(); err != nil {
|
if got, err := os.Executable(); err != nil {
|
||||||
log.Fatalf("Executable: error = %v", err)
|
log.Fatalf("Executable: error = %v", err)
|
||||||
} else if got != wantExec {
|
} else if got != wantExec {
|
||||||
switch got {
|
switch got {
|
||||||
case wantExecTmp:
|
|
||||||
overlayTmp = true
|
|
||||||
|
|
||||||
case wantExecWork:
|
case wantExecWork:
|
||||||
overlayWork = true
|
overlayWork = true
|
||||||
|
log.SetPrefix("testtool(overlay work): ")
|
||||||
|
|
||||||
default:
|
default:
|
||||||
log.Fatalf("Executable: %q, want %q", got, wantExec)
|
log.Fatalf("Executable: %q, want %q", got, wantExec)
|
||||||
@@ -99,12 +98,12 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const checksumEmptyDir = "MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU"
|
const checksumEmptyDir = "MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU"
|
||||||
ident := "oHuqV7p0v1Vd8IdAzjyYM8sfCS0P2LR5tfv5cb6Gbf2ZWUm8Ec-7hYPJ_qr183m7"
|
ident := "U2cbgVgEtjfRuvHfE1cQnZ3t8yoexULQyo_VLgvxAVJSsobMcNaFIsuDWtmt7kzK"
|
||||||
log.Println(m)
|
log.Println(m)
|
||||||
next := func() { m = m.Next; log.Println(m) }
|
next := func() { m = m.Next; log.Println(m) }
|
||||||
|
|
||||||
if overlayRoot {
|
if overlayRoot {
|
||||||
ident = "cIjP14zs5el6W_BQhufL_c0vWg-V6Z6pDpsbEa3sYtZ1381u1bKnH3N16RIrw-1S"
|
ident = "5ey2wpmMpj483YYa7ZZQciYLA2cx3_l167JCqWW4Pd-5DVp81dj9EsBtVTwYptF6"
|
||||||
|
|
||||||
if m.Root != "/" || m.Target != "/" ||
|
if m.Root != "/" || m.Target != "/" ||
|
||||||
m.Source != "overlay" || m.FsType != "overlay" {
|
m.Source != "overlay" || m.FsType != "overlay" {
|
||||||
@@ -122,7 +121,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if hostNet {
|
if hostNet {
|
||||||
ident = "I3T53NtN6HPAyyodHtq2B0clcsoS1nPdvCEb-Zc5K-hoqFGL2od1mftHhwG7gX1S"
|
ident = "QdsJhGgnk5N2xdUNGcndXQxFKifxf1V_2t9X8CQ-pDcg24x6mGJC_BiLfGbs6Qml"
|
||||||
}
|
}
|
||||||
|
|
||||||
if m.Root != "/sysroot" || m.Target != "/" {
|
if m.Root != "/sysroot" || m.Target != "/" {
|
||||||
@@ -140,28 +139,11 @@ func main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !overlayTmp {
|
next() // testtool artifact
|
||||||
next() // testtool artifact
|
|
||||||
} else {
|
|
||||||
ident = "3ELJ8l42g6XeIoLGR9LheVhMIwSIleD6VrhsliBuon5DAdBOwFSMqd7aiUI4fll7"
|
|
||||||
|
|
||||||
next()
|
|
||||||
if path.Base(m.Root) != checksumEmptyDir || m.Target != "/tmp" {
|
|
||||||
log.Fatal("unexpected artifact checksum")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if overlayTmp {
|
|
||||||
next() // testtool artifact
|
|
||||||
if m.Root != "/" || m.Target != "/tmp" ||
|
|
||||||
m.Source != "overlay" || m.FsType != "overlay" {
|
|
||||||
log.Fatal("unexpected temp mount entry")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
next()
|
next()
|
||||||
if overlayWork {
|
if overlayWork {
|
||||||
ident = "VMCurZKCA_MV80zb-ZBWVytfl3rhYOKJeo2u9l-OuaytQ_w_r4EsqgJ2nfO93x5_"
|
ident = "5ynpgDp5mcAmbFndOESXjQnOy_RG6furIxDpQz6c0bImBBLMAI8FouNbAB0uNs6f"
|
||||||
if m.Root != "/" || m.Target != "/work" ||
|
if m.Root != "/" || m.Target != "/work" ||
|
||||||
m.Source != "overlay" || m.FsType != "overlay" {
|
m.Source != "overlay" || m.FsType != "overlay" {
|
||||||
log.Fatal("unexpected work mount entry")
|
log.Fatal("unexpected work mount entry")
|
||||||
@@ -172,11 +154,9 @@ func main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !overlayTmp {
|
next()
|
||||||
next()
|
if path.Base(m.Root) != ident || m.Target != "/tmp" {
|
||||||
if path.Base(m.Root) != ident || m.Target != "/tmp" {
|
log.Fatal("unexpected temp mount entry")
|
||||||
log.Fatal("unexpected temp mount entry")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
next()
|
next()
|
||||||
|
|||||||
Reference in New Issue
Block a user