hst/fs: implement link fstype
All checks were successful
Test / Create distribution (push) Successful in 34s
Test / Sandbox (push) Successful in 2m16s
Test / Hpkg (push) Successful in 4m8s
Test / Sandbox (race detector) (push) Successful in 4m24s
Test / Hakurei (race detector) (push) Successful in 5m9s
Test / Hakurei (push) Successful in 2m31s
Test / Flake checks (push) Successful in 1m40s
All checks were successful
Test / Create distribution (push) Successful in 34s
Test / Sandbox (push) Successful in 2m16s
Test / Hpkg (push) Successful in 4m8s
Test / Sandbox (race detector) (push) Successful in 4m24s
Test / Hakurei (race detector) (push) Successful in 5m9s
Test / Hakurei (push) Successful in 2m31s
Test / Flake checks (push) Successful in 1m40s
Symlinks do not require special treatment, and doing this allows placing links in order. Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
parent
125f150784
commit
26cafe3e80
@ -95,6 +95,12 @@ func (f *FilesystemConfigJSON) MarshalJSON() ([]byte, error) {
|
|||||||
*FSOverlay
|
*FSOverlay
|
||||||
}{fsType{FilesystemOverlay}, cv}
|
}{fsType{FilesystemOverlay}, cv}
|
||||||
|
|
||||||
|
case *FSLink:
|
||||||
|
v = &struct {
|
||||||
|
fsType
|
||||||
|
*FSLink
|
||||||
|
}{fsType{FilesystemLink}, cv}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return nil, FSImplError{f.FilesystemConfig}
|
return nil, FSImplError{f.FilesystemConfig}
|
||||||
}
|
}
|
||||||
@ -120,6 +126,9 @@ func (f *FilesystemConfigJSON) UnmarshalJSON(data []byte) error {
|
|||||||
case FilesystemOverlay:
|
case FilesystemOverlay:
|
||||||
*f = FilesystemConfigJSON{new(FSOverlay)}
|
*f = FilesystemConfigJSON{new(FSOverlay)}
|
||||||
|
|
||||||
|
case FilesystemLink:
|
||||||
|
*f = FilesystemConfigJSON{new(FSLink)}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return FSTypeError(t.Type)
|
return FSTypeError(t.Type)
|
||||||
}
|
}
|
||||||
|
@ -70,6 +70,16 @@ func TestFilesystemConfigJSON(t *testing.T) {
|
|||||||
}, nil,
|
}, nil,
|
||||||
`{"type":"overlay","dst":"/nix/store","lower":["/mnt-root/nix/.ro-store"],"upper":"/mnt-root/nix/.rw-store/upper","work":"/mnt-root/nix/.rw-store/work"}`,
|
`{"type":"overlay","dst":"/nix/store","lower":["/mnt-root/nix/.ro-store"],"upper":"/mnt-root/nix/.rw-store/upper","work":"/mnt-root/nix/.rw-store/work"}`,
|
||||||
`{"fs":{"type":"overlay","dst":"/nix/store","lower":["/mnt-root/nix/.ro-store"],"upper":"/mnt-root/nix/.rw-store/upper","work":"/mnt-root/nix/.rw-store/work"},"magic":3236757504}`},
|
`{"fs":{"type":"overlay","dst":"/nix/store","lower":["/mnt-root/nix/.ro-store"],"upper":"/mnt-root/nix/.rw-store/upper","work":"/mnt-root/nix/.rw-store/work"},"magic":3236757504}`},
|
||||||
|
|
||||||
|
{"link", hst.FilesystemConfigJSON{
|
||||||
|
FilesystemConfig: &hst.FSLink{
|
||||||
|
Target: m("/run/current-system"),
|
||||||
|
Linkname: "/run/current-system",
|
||||||
|
Dereference: true,
|
||||||
|
},
|
||||||
|
}, nil,
|
||||||
|
`{"type":"link","dst":"/run/current-system","linkname":"/run/current-system","dereference":true}`,
|
||||||
|
`{"fs":{"type":"link","dst":"/run/current-system","linkname":"/run/current-system","dereference":true},"magic":3236757504}`},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
|
58
hst/fslink.go
Normal file
58
hst/fslink.go
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
package hst
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/gob"
|
||||||
|
"path"
|
||||||
|
|
||||||
|
"hakurei.app/container"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() { gob.Register(new(FSLink)) }
|
||||||
|
|
||||||
|
// FilesystemLink is the type string of a symbolic link.
|
||||||
|
const FilesystemLink = "link"
|
||||||
|
|
||||||
|
// FSLink represents a symlink in the container filesystem.
|
||||||
|
type FSLink struct {
|
||||||
|
// link path in container
|
||||||
|
Target *container.Absolute `json:"dst"`
|
||||||
|
// linkname the symlink points to
|
||||||
|
Linkname string `json:"linkname"`
|
||||||
|
// whether to dereference linkname before creating the link
|
||||||
|
Dereference bool `json:"dereference,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *FSLink) Valid() bool {
|
||||||
|
if l == nil || l.Target == nil || l.Linkname == "" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return !l.Dereference || path.IsAbs(l.Linkname)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *FSLink) Path() *container.Absolute {
|
||||||
|
if !l.Valid() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return l.Target
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *FSLink) Host() []*container.Absolute { return nil }
|
||||||
|
|
||||||
|
func (l *FSLink) Apply(z *ApplyState) {
|
||||||
|
if !l.Valid() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
z.Link(l.Target, l.Linkname, l.Dereference)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *FSLink) String() string {
|
||||||
|
if !l.Valid() {
|
||||||
|
return "<invalid>"
|
||||||
|
}
|
||||||
|
|
||||||
|
dereference := ""
|
||||||
|
if l.Dereference {
|
||||||
|
dereference = "*"
|
||||||
|
}
|
||||||
|
return "&" + l.Target.String() + ":" + dereference + l.Linkname
|
||||||
|
}
|
49
hst/fslink_test.go
Normal file
49
hst/fslink_test.go
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
package hst_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"hakurei.app/container"
|
||||||
|
"hakurei.app/hst"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestFSLink(t *testing.T) {
|
||||||
|
checkFs(t, []fsTestCase{
|
||||||
|
{"nil", (*hst.FSLink)(nil), false, nil, nil, nil, "<invalid>"},
|
||||||
|
{"zero", new(hst.FSLink), false, nil, nil, nil, "<invalid>"},
|
||||||
|
|
||||||
|
{"deref rel", &hst.FSLink{Target: m("/"), Linkname: ":3", Dereference: true}, false, nil, nil, nil, "<invalid>"},
|
||||||
|
{"deref", &hst.FSLink{
|
||||||
|
Target: m("/run/current-system"),
|
||||||
|
Linkname: "/run/current-system",
|
||||||
|
Dereference: true,
|
||||||
|
}, true, container.Ops{
|
||||||
|
&container.SymlinkOp{
|
||||||
|
Target: m("/run/current-system"),
|
||||||
|
LinkName: "/run/current-system",
|
||||||
|
Dereference: true,
|
||||||
|
},
|
||||||
|
}, m("/run/current-system"), nil,
|
||||||
|
"&/run/current-system:*/run/current-system"},
|
||||||
|
|
||||||
|
{"direct", &hst.FSLink{
|
||||||
|
Target: m("/etc/mtab"),
|
||||||
|
Linkname: "/proc/mounts",
|
||||||
|
}, true, container.Ops{
|
||||||
|
&container.SymlinkOp{
|
||||||
|
Target: m("/etc/mtab"),
|
||||||
|
LinkName: "/proc/mounts",
|
||||||
|
},
|
||||||
|
}, m("/etc/mtab"), nil, "&/etc/mtab:/proc/mounts"},
|
||||||
|
|
||||||
|
{"direct rel", &hst.FSLink{
|
||||||
|
Target: m("/etc/mtab"),
|
||||||
|
Linkname: "../proc/mounts",
|
||||||
|
}, true, container.Ops{
|
||||||
|
&container.SymlinkOp{
|
||||||
|
Target: m("/etc/mtab"),
|
||||||
|
LinkName: "../proc/mounts",
|
||||||
|
},
|
||||||
|
}, m("/etc/mtab"), nil, "&/etc/mtab:../proc/mounts"},
|
||||||
|
})
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user