Borg/pkg/matrix/matrix.go
google-labs-jules[bot] 4e5257ce4a feat: Add Terminal Isolation Matrix feature
This change introduces the "Terminal Isolation Matrix", a new output format that creates a runc-compatible container bundle. This allows for the collected files to be run in an isolated environment. A --format flag has been added to all collect commands to support this new format.
2025-11-02 12:39:46 +00:00

116 lines
2.1 KiB
Go

package matrix
import (
"archive/tar"
"bytes"
"encoding/json"
"io/fs"
"github.com/Snider/Borg/pkg/datanode"
)
// TerminalIsolationMatrix represents a runc bundle.
type TerminalIsolationMatrix struct {
Config []byte
RootFS *datanode.DataNode
}
// New creates a new, empty TerminalIsolationMatrix.
func New() (*TerminalIsolationMatrix, error) {
// Use the default runc spec as a starting point.
// This can be customized later.
spec, err := defaultConfig()
if err != nil {
return nil, err
}
specBytes, err := json.Marshal(spec)
if err != nil {
return nil, err
}
return &TerminalIsolationMatrix{
Config: specBytes,
RootFS: datanode.New(),
}, nil
}
// FromDataNode creates a new TerminalIsolationMatrix from a DataNode.
func FromDataNode(dn *datanode.DataNode) (*TerminalIsolationMatrix, error) {
m, err := New()
if err != nil {
return nil, err
}
m.RootFS = dn
return m, nil
}
// ToTar serializes the TerminalIsolationMatrix to a tarball.
func (m *TerminalIsolationMatrix) ToTar() ([]byte, error) {
buf := new(bytes.Buffer)
tw := tar.NewWriter(buf)
// Add the config.json file.
hdr := &tar.Header{
Name: "config.json",
Mode: 0600,
Size: int64(len(m.Config)),
}
if err := tw.WriteHeader(hdr); err != nil {
return nil, err
}
if _, err := tw.Write(m.Config); err != nil {
return nil, err
}
// Add the rootfs files.
err := m.RootFS.Walk(".", func(path string, d fs.DirEntry, err error) error {
if err != nil {
return err
}
if d.IsDir() {
return nil
}
file, err := m.RootFS.Open(path)
if err != nil {
return err
}
defer file.Close()
info, err := file.Stat()
if err != nil {
return err
}
hdr := &tar.Header{
Name: "rootfs/" + path,
Mode: 0600,
Size: info.Size(),
}
if err := tw.WriteHeader(hdr); err != nil {
return err
}
buf := new(bytes.Buffer)
if _, err := buf.ReadFrom(file); err != nil {
return err
}
if _, err := tw.Write(buf.Bytes()); err != nil {
return err
}
return nil
})
if err != nil {
return nil, err
}
if err := tw.Close(); err != nil {
return nil, err
}
return buf.Bytes(), nil
}