daemon: agent-driven workspace images — repo→image registry (GET/PUT/DELETE /api/repos), spawn resolves custom image, self-healing lvmh-ops control container with docker.sock; 132 tests, e2e 87/87
This commit is contained in:
@@ -47,6 +47,12 @@ type ContainerRow struct {
|
||||
Repo string
|
||||
}
|
||||
|
||||
// RepoImageRow maps a repo path to its registered custom worker image.
|
||||
type RepoImageRow struct {
|
||||
Repo string `json:"repo"`
|
||||
Image string `json:"image"`
|
||||
}
|
||||
|
||||
const dsnParams string = "?_pragma=busy_timeout(5000)&_pragma=journal_mode(WAL)&_pragma=synchronous(NORMAL)"
|
||||
|
||||
const schema string = `
|
||||
@@ -59,6 +65,8 @@ CREATE TABLE IF NOT EXISTS sessions(
|
||||
CREATE TABLE IF NOT EXISTS settings(key TEXT PRIMARY KEY, value TEXT NOT NULL);
|
||||
CREATE TABLE IF NOT EXISTS containers(
|
||||
sessionId TEXT PRIMARY KEY, containerId TEXT NOT NULL, repo TEXT NOT NULL);
|
||||
CREATE TABLE IF NOT EXISTS repo_images(
|
||||
repo TEXT PRIMARY KEY, image TEXT NOT NULL);
|
||||
CREATE INDEX IF NOT EXISTS idx_events_session ON events(sessionId, seq);
|
||||
`
|
||||
|
||||
@@ -278,3 +286,47 @@ func (s *Store) DeleteContainer(sessionID string) error {
|
||||
_, err := s.db.Exec(`DELETE FROM containers WHERE sessionId=?`, sessionID)
|
||||
return err
|
||||
}
|
||||
|
||||
// GetRepoImage returns the custom image registered for a repo, if any.
|
||||
func (s *Store) GetRepoImage(repo string) (string, bool, error) {
|
||||
var image string
|
||||
err := s.db.QueryRow(`SELECT image FROM repo_images WHERE repo=?`, repo).Scan(&image)
|
||||
if err == sql.ErrNoRows {
|
||||
return "", false, nil
|
||||
}
|
||||
if err != nil {
|
||||
return "", false, err
|
||||
}
|
||||
return image, true, nil
|
||||
}
|
||||
|
||||
// SetRepoImage upserts the custom image for a repo.
|
||||
func (s *Store) SetRepoImage(repo, image string) error {
|
||||
_, err := s.db.Exec(`INSERT INTO repo_images(repo, image) VALUES(?,?)
|
||||
ON CONFLICT(repo) DO UPDATE SET image=excluded.image`, repo, image)
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteRepoImage removes a repo's custom image registration (idempotent).
|
||||
func (s *Store) DeleteRepoImage(repo string) error {
|
||||
_, err := s.db.Exec(`DELETE FROM repo_images WHERE repo=?`, repo)
|
||||
return err
|
||||
}
|
||||
|
||||
// ListRepoImages returns every repo→image registration, sorted by repo.
|
||||
func (s *Store) ListRepoImages() ([]RepoImageRow, error) {
|
||||
rows, err := s.db.Query(`SELECT repo, image FROM repo_images ORDER BY repo`)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var out []RepoImageRow
|
||||
for rows.Next() {
|
||||
var row RepoImageRow
|
||||
if err := rows.Scan(&row.Repo, &row.Image); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out = append(out, row)
|
||||
}
|
||||
return out, rows.Err()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user