diff options
Diffstat (limited to 'hst/instance.go')
| -rw-r--r-- | hst/instance.go | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/hst/instance.go b/hst/instance.go new file mode 100644 index 00000000..5d15df6b --- /dev/null +++ b/hst/instance.go @@ -0,0 +1,84 @@ +package hst + +import ( + "crypto/rand" + "encoding/binary" + "encoding/hex" + "errors" + "fmt" + "time" +) + +// An ID is a unique identifier held by a running hakurei container. +type ID [16]byte + +// ErrIdentifierLength is returned when encountering a [hex] representation of [ID] with unexpected length. +var ErrIdentifierLength = errors.New("identifier string has unexpected length") + +// IdentifierDecodeError is returned by [ID.UnmarshalText] to provide relevant error descriptions. +type IdentifierDecodeError struct{ Err error } + +func (e IdentifierDecodeError) Unwrap() error { return e.Err } +func (e IdentifierDecodeError) Error() string { + var invalidByteError hex.InvalidByteError + switch { + case errors.As(e.Err, &invalidByteError): + return fmt.Sprintf("got invalid byte %#U in identifier", rune(invalidByteError)) + case errors.Is(e.Err, hex.ErrLength): + return "odd length identifier hex string" + + default: + return e.Err.Error() + } +} + +// String returns the [hex] string representation of [ID]. +func (a *ID) String() string { return hex.EncodeToString(a[:]) } + +// CreationTime returns the point in time [ID] was created. +func (a *ID) CreationTime() time.Time { + return time.Unix(0, int64(binary.BigEndian.Uint64(a[:8]))).UTC() +} + +// NewInstanceID creates a new unique [ID]. +func NewInstanceID(id *ID) error { return newInstanceID(id, uint64(time.Now().UnixNano())) } + +// newInstanceID creates a new unique [ID] with the specified timestamp. +func newInstanceID(id *ID, p uint64) error { + binary.BigEndian.PutUint64(id[:8], p) + _, err := rand.Read(id[8:]) + return err +} + +// MarshalText encodes the [hex] representation of [ID]. +func (a *ID) MarshalText() (text []byte, err error) { + text = make([]byte, hex.EncodedLen(len(a))) + hex.Encode(text, a[:]) + return +} + +// UnmarshalText decodes a [hex] representation of [ID]. +func (a *ID) UnmarshalText(text []byte) error { + dl := hex.DecodedLen(len(text)) + if dl != len(a) { + return IdentifierDecodeError{ErrIdentifierLength} + } + _, err := hex.Decode(a[:], text) + if err == nil { + return nil + } + return IdentifierDecodeError{err} +} + +// A State describes a running hakurei container. +type State struct { + // Unique instance id, created by [NewInstanceID]. + ID ID `json:"instance"` + // Shim process pid. Runs as the target user. + PID int `json:"pid"` + // Configuration used to start the container. + Config *Config `json:"config"` + + // Point in time the shim process was created. + Time time.Time `json:"time"` +} |
