All checks were successful
		
		
	
	Test / Create distribution (push) Successful in 34s
				
			Test / Sandbox (push) Successful in 2m9s
				
			Test / Hpkg (push) Successful in 3m58s
				
			Test / Sandbox (race detector) (push) Successful in 4m31s
				
			Test / Hakurei (race detector) (push) Successful in 5m19s
				
			Test / Hakurei (push) Successful in 2m12s
				
			Test / Flake checks (push) Successful in 1m31s
				
			This corrects minor mistakes in doc comments and adds them for undocumented constants. Signed-off-by: Ophestra <cat@gensokyo.uk>
		
			
				
	
	
		
			161 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			161 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package hst
 | |
| 
 | |
| import (
 | |
| 	"encoding/json"
 | |
| 	"errors"
 | |
| 	"fmt"
 | |
| 	"os"
 | |
| 	"reflect"
 | |
| 
 | |
| 	"hakurei.app/container/check"
 | |
| )
 | |
| 
 | |
| // FilesystemConfig is an abstract representation of a mount point.
 | |
| type FilesystemConfig interface {
 | |
| 	// Valid returns whether the configuration is valid.
 | |
| 	Valid() bool
 | |
| 	// Path returns the target path in the container.
 | |
| 	Path() *check.Absolute
 | |
| 	// Host returns a slice of all host paths used by this operation.
 | |
| 	Host() []*check.Absolute
 | |
| 	// Apply appends the [container.Op] implementing this operation.
 | |
| 	Apply(z *ApplyState)
 | |
| 
 | |
| 	fmt.Stringer
 | |
| }
 | |
| 
 | |
| // The Ops interface enables [FilesystemConfig] to queue container ops without depending on the container package.
 | |
| type Ops interface {
 | |
| 	// Tmpfs appends an op that mounts tmpfs on a container path.
 | |
| 	Tmpfs(target *check.Absolute, size int, perm os.FileMode) Ops
 | |
| 	// Readonly appends an op that mounts read-only tmpfs on a container path.
 | |
| 	Readonly(target *check.Absolute, perm os.FileMode) Ops
 | |
| 
 | |
| 	// Bind appends an op that bind mounts a host path on a container path.
 | |
| 	Bind(source, target *check.Absolute, flags int) Ops
 | |
| 	// Overlay appends an op that mounts the overlay pseudo filesystem.
 | |
| 	Overlay(target, state, work *check.Absolute, layers ...*check.Absolute) Ops
 | |
| 	// OverlayReadonly appends an op that mounts the overlay pseudo filesystem readonly.
 | |
| 	OverlayReadonly(target *check.Absolute, layers ...*check.Absolute) Ops
 | |
| 
 | |
| 	// Link appends an op that creates a symlink in the container filesystem.
 | |
| 	Link(target *check.Absolute, linkName string, dereference bool) Ops
 | |
| 
 | |
| 	// Root appends an op that expands a directory into a toplevel bind mount mirror on container root.
 | |
| 	Root(host *check.Absolute, flags int) Ops
 | |
| 	// Etc appends an op that expands host /etc into a toplevel symlink mirror with /etc semantics.
 | |
| 	Etc(host *check.Absolute, prefix string) Ops
 | |
| }
 | |
| 
 | |
| // ApplyState holds the address of [Ops] and any relevant application state.
 | |
| type ApplyState struct {
 | |
| 	// AutoEtcPrefix is the prefix for [FSBind] in autoetc [FSBind.Special] condition.
 | |
| 	AutoEtcPrefix string
 | |
| 
 | |
| 	Ops
 | |
| }
 | |
| 
 | |
| // ErrFSNull is returned by [json] on encountering a null [FilesystemConfig] value.
 | |
| var ErrFSNull = errors.New("unexpected null in mount point")
 | |
| 
 | |
| // FSTypeError is returned when [ContainerConfig.Filesystem] contains an entry with invalid type.
 | |
| type FSTypeError string
 | |
| 
 | |
| func (f FSTypeError) Error() string { return fmt.Sprintf("invalid filesystem type %q", string(f)) }
 | |
| 
 | |
| // FSImplError is returned for unsupported implementations of [FilesystemConfig].
 | |
| type FSImplError struct{ Value FilesystemConfig }
 | |
| 
 | |
| func (f FSImplError) Error() string {
 | |
| 	implType := reflect.TypeOf(f.Value)
 | |
| 	var name string
 | |
| 	for implType != nil && implType.Kind() == reflect.Ptr {
 | |
| 		name += "*"
 | |
| 		implType = implType.Elem()
 | |
| 	}
 | |
| 	if implType != nil {
 | |
| 		name += implType.Name()
 | |
| 	} else {
 | |
| 		name += "nil"
 | |
| 	}
 | |
| 	return fmt.Sprintf("implementation %s not supported", name)
 | |
| }
 | |
| 
 | |
| // FilesystemConfigJSON is the [json] adapter for [FilesystemConfig].
 | |
| type FilesystemConfigJSON struct{ FilesystemConfig }
 | |
| 
 | |
| // Valid returns whether the [FilesystemConfigJSON] is valid.
 | |
| func (f *FilesystemConfigJSON) Valid() bool {
 | |
| 	return f != nil && f.FilesystemConfig != nil && f.FilesystemConfig.Valid()
 | |
| }
 | |
| 
 | |
| // fsType holds the string representation of the concrete type of [FilesystemConfig].
 | |
| type fsType struct {
 | |
| 	Type string `json:"type"`
 | |
| }
 | |
| 
 | |
| func (f *FilesystemConfigJSON) MarshalJSON() ([]byte, error) {
 | |
| 	if f == nil || f.FilesystemConfig == nil {
 | |
| 		return nil, ErrFSNull
 | |
| 	}
 | |
| 	var v any
 | |
| 	switch cv := f.FilesystemConfig.(type) {
 | |
| 	case *FSBind:
 | |
| 		v = &struct {
 | |
| 			fsType
 | |
| 			*FSBind
 | |
| 		}{fsType{FilesystemBind}, cv}
 | |
| 
 | |
| 	case *FSEphemeral:
 | |
| 		v = &struct {
 | |
| 			fsType
 | |
| 			*FSEphemeral
 | |
| 		}{fsType{FilesystemEphemeral}, cv}
 | |
| 
 | |
| 	case *FSOverlay:
 | |
| 		v = &struct {
 | |
| 			fsType
 | |
| 			*FSOverlay
 | |
| 		}{fsType{FilesystemOverlay}, cv}
 | |
| 
 | |
| 	case *FSLink:
 | |
| 		v = &struct {
 | |
| 			fsType
 | |
| 			*FSLink
 | |
| 		}{fsType{FilesystemLink}, cv}
 | |
| 
 | |
| 	default:
 | |
| 		return nil, FSImplError{f.FilesystemConfig}
 | |
| 	}
 | |
| 
 | |
| 	return json.Marshal(v)
 | |
| }
 | |
| 
 | |
| func (f *FilesystemConfigJSON) UnmarshalJSON(data []byte) error {
 | |
| 	t := new(fsType)
 | |
| 	if err := json.Unmarshal(data, &t); err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 	if t == nil {
 | |
| 		return ErrFSNull
 | |
| 	}
 | |
| 	switch t.Type {
 | |
| 	case FilesystemBind:
 | |
| 		*f = FilesystemConfigJSON{new(FSBind)}
 | |
| 
 | |
| 	case FilesystemEphemeral:
 | |
| 		*f = FilesystemConfigJSON{new(FSEphemeral)}
 | |
| 
 | |
| 	case FilesystemOverlay:
 | |
| 		*f = FilesystemConfigJSON{new(FSOverlay)}
 | |
| 
 | |
| 	case FilesystemLink:
 | |
| 		*f = FilesystemConfigJSON{new(FSLink)}
 | |
| 
 | |
| 	default:
 | |
| 		return FSTypeError(t.Type)
 | |
| 	}
 | |
| 
 | |
| 	return json.Unmarshal(data, f.FilesystemConfig)
 | |
| }
 |