feat(go): add Phase 1 parity sidecar
This commit is contained in:
parent
65f5be6420
commit
f02509aab5
22 changed files with 947 additions and 6 deletions
75
go-agent/cmd/enodia-sentinel-go/main.go
Normal file
75
go-agent/cmd/enodia-sentinel-go/main.go
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// enodia-sentinel-go is the experimental Phase 1 sidecar. Python remains the
|
||||
// production implementation and behavioral oracle until parity is complete.
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"codeberg.org/anassaeneroi/enodia-sentinal/go-agent/internal/agent"
|
||||
"codeberg.org/anassaeneroi/enodia-sentinal/go-agent/internal/config"
|
||||
"codeberg.org/anassaeneroi/enodia-sentinal/go-agent/internal/model"
|
||||
"codeberg.org/anassaeneroi/enodia-sentinal/go-agent/internal/system"
|
||||
)
|
||||
|
||||
func main() {
|
||||
if err := run(); err != nil {
|
||||
fmt.Fprintln(os.Stderr, "enodia-sentinel-go:", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func run() error {
|
||||
once := flag.Bool("once", false, "emit one sweep and exit")
|
||||
configPath := flag.String("config", "", "Sentinel TOML path (default: ENODIA_CONFIG or /etc/enodia-sentinel.toml)")
|
||||
procRoot := flag.String("proc-root", "/proc", "procfs root")
|
||||
fixture := flag.String("fixture", "", "JSON SystemState fixture (parity/testing only)")
|
||||
host := flag.String("host", "", "override hostname (parity/testing only)")
|
||||
timestamp := flag.String("timestamp", "", "override RFC3339 timestamp (parity/testing only)")
|
||||
flag.Parse()
|
||||
|
||||
cfg, err := config.Load(*configPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
capture := func() (model.State, error) { return system.Capture(*procRoot) }
|
||||
if *fixture != "" {
|
||||
capture = func() (model.State, error) {
|
||||
var state model.State
|
||||
raw, err := os.ReadFile(*fixture)
|
||||
if err != nil {
|
||||
return state, err
|
||||
}
|
||||
err = json.Unmarshal(raw, &state)
|
||||
return state, err
|
||||
}
|
||||
}
|
||||
|
||||
runner := agent.New(cfg, capture)
|
||||
if *host != "" {
|
||||
runner.Host = func() (string, error) { return *host, nil }
|
||||
}
|
||||
if *timestamp != "" {
|
||||
fixed, err := time.Parse(time.RFC3339Nano, *timestamp)
|
||||
if err != nil {
|
||||
return fmt.Errorf("timestamp: %w", err)
|
||||
}
|
||||
runner.Now = func() time.Time { return fixed }
|
||||
}
|
||||
|
||||
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
|
||||
defer stop()
|
||||
encoder := json.NewEncoder(os.Stdout)
|
||||
encoder.SetEscapeHTML(false)
|
||||
return runner.Run(ctx, *once, func(event map[string]any) error {
|
||||
return encoder.Encode(event)
|
||||
})
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue