147 lines
3.1 KiB
Go
147 lines
3.1 KiB
Go
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
|
|
}
|