CLI + live dashboard wrapping aws/docker/git/awsmfa for local dev: AWS MFA auth status + expiry, dev compose stack control, container drift vs the dev repo, git repo status, prod-data and DB-access tools. Config-driven (~/.config/mydev/config.yaml). Dashboard runs commands via a command palette with captured/interactive modes. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
58 lines
1.4 KiB
Go
58 lines
1.4 KiB
Go
package checks
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"os/exec"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
// Container is one docker container's summary state.
|
|
type Container struct {
|
|
Name string
|
|
Image string
|
|
State string // running, exited, ...
|
|
Status string // human string, e.g. "Up 3 hours"
|
|
}
|
|
|
|
// Containers runs `docker ps -a` and parses the line-delimited JSON output.
|
|
// Returns ([], "") when docker works but no containers exist.
|
|
func Containers(ctx context.Context) ([]Container, string) {
|
|
ctx, cancel := context.WithTimeout(ctx, 8*time.Second)
|
|
defer cancel()
|
|
|
|
// docker emits one JSON object per line with --format json.
|
|
out, err := exec.CommandContext(ctx, "docker", "ps", "-a", "--format", "json").Output()
|
|
if err != nil {
|
|
msg := err.Error()
|
|
if ee, ok := err.(*exec.ExitError); ok && len(ee.Stderr) > 0 {
|
|
msg = strings.TrimSpace(string(ee.Stderr))
|
|
}
|
|
return nil, msg
|
|
}
|
|
|
|
var list []Container
|
|
for _, line := range strings.Split(strings.TrimSpace(string(out)), "\n") {
|
|
if line == "" {
|
|
continue
|
|
}
|
|
var row struct {
|
|
Names string `json:"Names"`
|
|
Image string `json:"Image"`
|
|
State string `json:"State"`
|
|
Status string `json:"Status"`
|
|
}
|
|
if err := json.Unmarshal([]byte(line), &row); err != nil {
|
|
continue
|
|
}
|
|
list = append(list, Container{
|
|
Name: row.Names,
|
|
Image: row.Image,
|
|
State: row.State,
|
|
Status: row.Status,
|
|
})
|
|
}
|
|
return list, ""
|
|
}
|