package main import ( "fmt" "log" "os" "os/exec" "strings" "time" ) type ContainerInfo struct { ID string Name string Interval time.Duration Ignores []string } func main() { for { containers, err := getContainers() if err != nil { log.Printf("Error listing containers: %v", err) time.Sleep(1 * time.Minute) continue } for _, container := range containers { go monitorContainer(container) } // Sleep for 1 minute before checking for new containers again time.Sleep(1 * time.Minute) } } func getContainers() ([]ContainerInfo, error) { output, err := exec.Command("docker", "ps", "--format", "{{.ID}} {{.Label \"oculus.enable\"}} {{.Label \"oculus.interval\"}} {{.Label \"oculus.cname\"}} {{.Label \"oculus.ignores\"}}").Output() if err != nil { return nil, err } lines := strings.Split(string(output), "\n") var containers []ContainerInfo for _, line := range lines { if line == "" { continue } parts := strings.Fields(line) if len(parts) < 2 || parts[1] == "" { continue } id := parts[0] intervalStr := "300s" if len(parts) > 2 && parts[2] != "" { intervalStr = parts[2] } interval, err := time.ParseDuration(intervalStr) if err != nil { log.Printf("Invalid interval format for container %s: %v", id, err) continue } cname := id if len(parts) > 3 && parts[3] != "" { cname = parts[3] } ignores := []string{} if len(parts) > 4 && parts[4] != "" { ignores = strings.Split(parts[4], ",") } containers = append(containers, ContainerInfo{ ID: id, Name: cname, Interval: interval, Ignores: ignores, }) } return containers, nil } func monitorContainer(container ContainerInfo) { for { checkDiff(container) time.Sleep(container.Interval) } } func checkDiff(container ContainerInfo) { cmd := exec.Command("docker", "diff", container.ID) output, err := cmd.Output() if err != nil { log.Printf("Error running docker diff for container %s: %v", container.ID, err) return } diffOutput := string(output) for _, ignore := range container.Ignores { diffOutput = removeIgnoredPaths(diffOutput, ignore) } if diffOutput != "" { // Write diff output to a file filename := fmt.Sprintf("%s.diff", container.Name) err = writeToFile(filename, diffOutput) if err != nil { log.Printf("Error writing diff to file for container %s: %v", container.ID, err) } // Send notification using go-glitch cmd = exec.Command("go-glitch") cmd.Stdin = strings.NewReader(diffOutput) err = cmd.Run() if err != nil { log.Printf("Error sending notification for container %s: %v", container.ID, err) } } } func removeIgnoredPaths(diffOutput string, ignore string) string { lines := strings.Split(diffOutput, "\n") filteredLines := []string{} for _, line := range lines { if !strings.Contains(line, ignore) { filteredLines = append(filteredLines, line) } } return strings.Join(filteredLines, "\n") } func writeToFile(filename, content string) error { file, err := os.Create(filename) if err != nil { return err } defer file.Close() _, err = file.WriteString(content) return err }