okay it at least compiles dunno if it does anything yet.
ci/woodpecker/push/woodpecker Pipeline was successful
Details
ci/woodpecker/push/woodpecker Pipeline was successful
Details
This commit is contained in:
parent
9428343a52
commit
40ae3fc6fe
12
build.sh
12
build.sh
|
|
@ -1,7 +1,7 @@
|
|||
#!/bin/bash
|
||||
|
||||
ARCHITECTURES=("linux/amd64" "linux/arm64" "darwin/amd64" "windows/amd64")
|
||||
PROJECT_NAME=$(basename "$PWD")
|
||||
ARCHITECTURES=("linux/amd64" "linux/arm64" "darwin/amd64" "darwin/arm64" "windows/amd64")
|
||||
PROJECT_NAME=$(basename "$(pwd)")
|
||||
|
||||
prepare_build() {
|
||||
mkdir -p dist build_logs
|
||||
|
|
@ -15,16 +15,16 @@ build_binary() {
|
|||
local os=$1
|
||||
local arch=$2
|
||||
local output="dist/${PROJECT_NAME}_${os}_${arch}"
|
||||
env GOOS=$os GOARCH=$arch go build -o $output . &> build_logs/${os}_${arch}.log
|
||||
env GOOS=$os GOARCH=$arch go build -o $output . &> "build_logs/${os}_${arch}.log"
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Build failed for $os/$arch" >> build_logs/error.log
|
||||
echo "Build failed for $os/$arch" >> "build_logs/error.log"
|
||||
else
|
||||
echo "Build succeeded for $os/$arch"
|
||||
fi
|
||||
if [ "$os" == "linux" ]; then
|
||||
env GOOS=$os GOARCH=$arch CGO_ENABLED=0 go build -a -ldflags '-extldflags "-static"' -o ${output}_static . &> build_logs/${os}_${arch}_static.log
|
||||
env GOOS=$os GOARCH=$arch CGO_ENABLED=0 go build -a -ldflags '-extldflags "-static"' -o "${output}_static" . &> "build_logs/${os}_${arch}_static.log"
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Static build failed for $os/$arch" >> build_logs/error.log
|
||||
echo "Static build failed for $os/$arch" >> "build_logs/error.log"
|
||||
else
|
||||
echo "Static build succeeded for $os/$arch"
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -1,3 +0,0 @@
|
|||
# oculus
|
||||
./main.go:38:67: undefined: types.ContainerListOptions
|
||||
./main.go:119:4: savedDiffs declared and not used
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
Build failed for linux/amd64
|
||||
Static build failed for linux/amd64
|
||||
Build failed for linux/arm64
|
||||
Static build failed for linux/arm64
|
||||
Build failed for darwin/amd64
|
||||
Build failed for windows/amd64
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
# oculus
|
||||
./main.go:38:67: undefined: types.ContainerListOptions
|
||||
./main.go:119:4: savedDiffs declared and not used
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
# oculus
|
||||
./main.go:38:67: undefined: types.ContainerListOptions
|
||||
./main.go:119:4: savedDiffs declared and not used
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
# oculus
|
||||
./main.go:38:67: undefined: types.ContainerListOptions
|
||||
./main.go:119:4: savedDiffs declared and not used
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
# oculus
|
||||
./main.go:38:67: undefined: types.ContainerListOptions
|
||||
./main.go:119:4: savedDiffs declared and not used
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
# oculus
|
||||
./main.go:38:67: undefined: types.ContainerListOptions
|
||||
./main.go:119:4: savedDiffs declared and not used
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Function to process diffs and check ignores
|
||||
process_container() {
|
||||
local container_id=$1
|
||||
local mode=$2
|
||||
|
||||
# Get the container labels
|
||||
labels=$(docker inspect --format '{{json .Config.Labels}}' "$container_id")
|
||||
cname=$(echo "$labels" | jq -r '.["oculus.cname"]')
|
||||
ignores=$(echo "$labels" | jq -r '.["oculus.ignores"]')
|
||||
|
||||
# Get the diff
|
||||
diff_output=$(docker diff "$container_id")
|
||||
|
||||
# Process ignores
|
||||
if [ "$ignores" != "null" ]; then
|
||||
IFS=',' read -ra ignore_array <<< "$ignores"
|
||||
for ignore in "${ignore_array[@]}"; do
|
||||
diff_output=$(echo "$diff_output" | grep -v "$ignore")
|
||||
done
|
||||
fi
|
||||
|
||||
# Write the diff output to a file
|
||||
echo "$diff_output" > "${cname}.diff"
|
||||
|
||||
if [ "$mode" == "monitor" ]; then
|
||||
# Check if there are any changes left after applying ignores
|
||||
if [ -n "$diff_output" ]; then
|
||||
# Send notification using go-glitch
|
||||
echo "$diff_output" | go-glitch
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
export -f process_container
|
||||
|
||||
# Get the list of running containers
|
||||
containers=$(docker ps -q)
|
||||
|
||||
# Check if there are no running containers
|
||||
if [ -z "$containers" ]; then
|
||||
echo "No running containers found."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Iterate over each container and process based on labels
|
||||
for container in $containers; do
|
||||
labels=$(docker inspect --format '{{json .Config.Labels}}' "$container")
|
||||
enable=$(echo "$labels" | jq -r '.["oculus.enable"]')
|
||||
|
||||
if [ "$enable" == "monitor" ]; then
|
||||
frequency=$(echo "$labels" | jq -r '.["oculus.frequency"]')
|
||||
if [ "$frequency" == "null" ]; then
|
||||
frequency="300s" # Default frequency if not set
|
||||
fi
|
||||
# Run the process_container function with monitor mode
|
||||
echo "$container monitor" | parallel process_container
|
||||
sleep "${frequency}"
|
||||
elif [ "$enable" == "profile" ]; then
|
||||
# Run the process_container function with profile mode
|
||||
echo "$container profile" | parallel process_container
|
||||
fi
|
||||
done
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
29
go.mod
29
go.mod
|
|
@ -1,32 +1,3 @@
|
|||
module oculus
|
||||
|
||||
go 1.21.1
|
||||
|
||||
require github.com/docker/docker v26.1.4+incompatible
|
||||
|
||||
require (
|
||||
github.com/Microsoft/go-winio v0.4.14 // indirect
|
||||
github.com/containerd/log v0.1.0 // indirect
|
||||
github.com/distribution/reference v0.6.0 // indirect
|
||||
github.com/docker/go-connections v0.5.0 // indirect
|
||||
github.com/docker/go-units v0.5.0 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/go-logr/logr v1.4.1 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/moby/docker-image-spec v1.3.1 // indirect
|
||||
github.com/moby/term v0.5.0 // indirect
|
||||
github.com/morikuni/aec v1.0.0 // indirect
|
||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||
github.com/opencontainers/image-spec v1.1.0 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.52.0 // indirect
|
||||
go.opentelemetry.io/otel v1.27.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.27.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.27.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.27.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.27.0 // indirect
|
||||
golang.org/x/sys v0.20.0 // indirect
|
||||
golang.org/x/time v0.5.0 // indirect
|
||||
gotest.tools/v3 v3.5.1 // indirect
|
||||
)
|
||||
|
|
|
|||
121
go.sum
121
go.sum
|
|
@ -1,121 +0,0 @@
|
|||
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
|
||||
github.com/Microsoft/go-winio v0.4.14 h1:+hMXMk01us9KgxGb7ftKQt2Xpf5hH/yky+TDA+qxleU=
|
||||
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
|
||||
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
|
||||
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
|
||||
github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
|
||||
github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
|
||||
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
|
||||
github.com/docker/docker v26.1.4+incompatible h1:vuTpXDuoga+Z38m1OZHzl7NKisKWaWlhjQk7IDPSLsU=
|
||||
github.com/docker/docker v26.1.4+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c=
|
||||
github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc=
|
||||
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
|
||||
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
||||
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
|
||||
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k=
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
|
||||
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
|
||||
github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
|
||||
github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
|
||||
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
|
||||
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
|
||||
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||
github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug=
|
||||
github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.52.0 h1:9l89oX4ba9kHbBol3Xin3leYJ+252h0zszDtBwyKe2A=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.52.0/go.mod h1:XLZfZboOJWHNKUv7eH0inh0E9VV6eWDFB/9yJyTLPp0=
|
||||
go.opentelemetry.io/otel v1.27.0 h1:9BZoF3yMK/O1AafMiQTVu0YDj5Ea4hPhxCs7sGva+cg=
|
||||
go.opentelemetry.io/otel v1.27.0/go.mod h1:DMpAK8fzYRzs+bi3rS5REupisuqTheUlSZJ1WnZaPAQ=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.27.0 h1:R9DE4kQ4k+YtfLI2ULwX82VtNQ2J8yZmA7ZIF/D+7Mc=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.27.0/go.mod h1:OQFyQVrDlbe+R7xrEyDr/2Wr67Ol0hRUgsfA+V5A95s=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.27.0 h1:QY7/0NeRPKlzusf40ZE4t1VlMKbqSNT7cJRYzWuja0s=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.27.0/go.mod h1:HVkSiDhTM9BoUJU8qE6j2eSWLLXvi1USXjyd2BXT8PY=
|
||||
go.opentelemetry.io/otel/metric v1.27.0 h1:hvj3vdEKyeCi4YaYfNjv2NUje8FqKqUY8IlF0FxV/ik=
|
||||
go.opentelemetry.io/otel/metric v1.27.0/go.mod h1:mVFgmRlhljgBiuk/MP/oKylr4hs85GZAylncepAX/ak=
|
||||
go.opentelemetry.io/otel/sdk v1.27.0 h1:mlk+/Y1gLPLn84U4tI8d3GNJmGT/eXe3ZuOXN9kTWmI=
|
||||
go.opentelemetry.io/otel/sdk v1.27.0/go.mod h1:Ha9vbLwJE6W86YstIywK2xFfPjbWlCuwPtMkKdz/Y4A=
|
||||
go.opentelemetry.io/otel/trace v1.27.0 h1:IqYb813p7cmbHk0a5y6pD5JPakbVfftRXABGt5/Rscw=
|
||||
go.opentelemetry.io/otel/trace v1.27.0/go.mod h1:6RiD1hkAprV4/q+yd2ln1HG9GoPx39SuvvstaLBl+l4=
|
||||
go.opentelemetry.io/proto/otlp v1.2.0 h1:pVeZGk7nXDC9O2hncA6nHldxEjm6LByfA2aN8IOkz94=
|
||||
go.opentelemetry.io/proto/otlp v1.2.0/go.mod h1:gGpR8txAl5M03pDhMC79G6SdqNV26naRm/KDsgaHD8A=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
|
||||
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
|
||||
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
|
||||
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
||||
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240520151616-dc85e6b867a5 h1:P8OJ/WCl/Xo4E4zoe4/bifHpSmmKwARqyqE4nW6J2GQ=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240520151616-dc85e6b867a5/go.mod h1:RGnPtTG7r4i8sPlNyDeikXF99hMM+hN6QMm4ooG9g2g=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240515191416-fc5f0ca64291 h1:AgADTJarZTBqgjiUzRgfaBchgYB3/WFTC80GPwsMcRI=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240515191416-fc5f0ca64291/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0=
|
||||
google.golang.org/grpc v1.64.0 h1:KH3VH9y/MgNQg1dE7b3XfVK0GsPSIzJwdF617gUSbvY=
|
||||
google.golang.org/grpc v1.64.0/go.mod h1:oxjF8E3FBnjp+/gVFYdWacaLDx9na1aqy9oovLpxQYg=
|
||||
google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg=
|
||||
google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU=
|
||||
gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU=
|
||||
358
main.go
358
main.go
|
|
@ -1,260 +1,146 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/docker/docker/client"
|
||||
)
|
||||
|
||||
const (
|
||||
notifyScript = "/notify.sh"
|
||||
logDir = "/log"
|
||||
)
|
||||
|
||||
type ContainerDiff struct {
|
||||
ID string
|
||||
Image string
|
||||
Labels map[string]string
|
||||
}
|
||||
|
||||
type FileChange struct {
|
||||
Path string
|
||||
Kind string
|
||||
}
|
||||
|
||||
func getRunningContainers(cli *client.Client) ([]ContainerDiff, error) {
|
||||
containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var diffs []ContainerDiff
|
||||
for _, container := range containers {
|
||||
if _, ok := container.Labels["oculus.cname"]; ok {
|
||||
diffs = append(diffs, ContainerDiff{
|
||||
ID: container.ID,
|
||||
Image: container.Image,
|
||||
Labels: container.Labels,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return diffs, nil
|
||||
}
|
||||
|
||||
func saveDiffs(diffs []FileChange, filePath string) error {
|
||||
data, err := json.Marshal(diffs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return os.WriteFile(filePath, data, 0644)
|
||||
}
|
||||
|
||||
func loadDiffs(filePath string) ([]FileChange, error) {
|
||||
data, err := os.ReadFile(filePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var diffs []FileChange
|
||||
err = json.Unmarshal(data, &diffs)
|
||||
return diffs, err
|
||||
}
|
||||
|
||||
func shouldIgnore(change string, ignoreList []string) bool {
|
||||
for _, ignore := range ignoreList {
|
||||
if strings.Contains(change, ignore) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func logDetection(containerID, message string) {
|
||||
logFilePath := filepath.Join(logDir, fmt.Sprintf("%s.log", containerID))
|
||||
f, err := os.OpenFile(logFilePath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
||||
if err != nil {
|
||||
log.Printf("Error opening log file: %v", err)
|
||||
return
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
log.SetOutput(f)
|
||||
log.Println(message)
|
||||
sendToGlitchtip(logFilePath)
|
||||
}
|
||||
|
||||
func sendToGlitchtip(logFilePath string) {
|
||||
if dsn := os.Getenv("GLITCHTIP_DSN"); dsn != "" {
|
||||
cmd := exec.Command("go-glitch", logFilePath)
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
log.Printf("Error sending to Go Glitch: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func compareContainers(cli *client.Client, mode string) {
|
||||
currentDiffs, err := getRunningContainers(cli)
|
||||
if err != nil {
|
||||
log.Fatalf("Error getting current containers: %v", err)
|
||||
}
|
||||
|
||||
for _, current := range currentDiffs {
|
||||
if current.Labels["oculus.mode"] == mode {
|
||||
filePath := filepath.Join(logDir, fmt.Sprintf("%s.json", current.Labels["oculus.cname"]))
|
||||
savedDiffs, err := loadDiffs(filePath)
|
||||
if err != nil {
|
||||
log.Printf("Error loading saved diffs for %s: %v", current.ID, err)
|
||||
savedDiffs = []FileChange{} // Initialize to an empty slice
|
||||
}
|
||||
|
||||
ignoreList := strings.Split(current.Labels["oculus.ignorelist"], ",")
|
||||
|
||||
currentChanges, err := cli.ContainerDiff(context.Background(), current.ID)
|
||||
if err != nil {
|
||||
log.Printf("Error getting container diff for %s: %v", current.ID, err)
|
||||
continue
|
||||
}
|
||||
|
||||
var changes []FileChange
|
||||
for _, change := range currentChanges {
|
||||
path := change.Path
|
||||
kind := ""
|
||||
switch change.Kind {
|
||||
case 0:
|
||||
kind = "Modified"
|
||||
case 1:
|
||||
kind = "Added"
|
||||
case 2:
|
||||
kind = "Deleted"
|
||||
}
|
||||
|
||||
if !shouldIgnore(path, ignoreList) {
|
||||
changes = append(changes, FileChange{
|
||||
Path: path,
|
||||
Kind: kind,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if mode == "monitor" {
|
||||
err = saveDiffs(changes, filePath)
|
||||
if err != nil {
|
||||
log.Fatalf("Error saving diffs: %v", err)
|
||||
}
|
||||
} else if mode == "report" {
|
||||
for _, change := range changes {
|
||||
message := fmt.Sprintf("Container %s changed: %s %s", current.ID, change.Kind, change.Path)
|
||||
logDetection(current.Labels["oculus.cname"], message)
|
||||
runNotifyScript(filepath.Join(logDir, fmt.Sprintf("%s.log", current.Labels["oculus.cname"])))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func runNotifyScript(logFilePath string) {
|
||||
cmd := exec.Command(notifyScript, logFilePath)
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
log.Printf("Error running notify script: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func watchDockerEvents(cli *client.Client) {
|
||||
eventFilter := filters.NewArgs()
|
||||
eventFilter.Add("type", "container")
|
||||
eventFilter.Add("event", "start")
|
||||
eventFilter.Add("event", "stop")
|
||||
eventFilter.Add("event", "destroy")
|
||||
|
||||
messages, errs := cli.Events(context.Background(), types.EventsOptions{
|
||||
Filters: eventFilter,
|
||||
})
|
||||
|
||||
for {
|
||||
select {
|
||||
case event := <-messages:
|
||||
log.Printf("Docker event received: %s for container %s", event.Action, event.ID)
|
||||
compareContainers(cli, "monitor")
|
||||
case err := <-errs:
|
||||
log.Printf("Error watching Docker events: %v", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func monitorContainers(cli *client.Client, interval time.Duration) {
|
||||
ticker := time.NewTicker(interval)
|
||||
defer ticker.Stop()
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ticker.C:
|
||||
compareContainers(cli, "monitor")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func reportContainers(cli *client.Client, interval time.Duration) {
|
||||
ticker := time.NewTicker(interval)
|
||||
defer ticker.Stop()
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ticker.C:
|
||||
compareContainers(cli, "report")
|
||||
}
|
||||
}
|
||||
type ContainerInfo struct {
|
||||
ID string
|
||||
Name string
|
||||
Interval time.Duration
|
||||
Ignores []string
|
||||
}
|
||||
|
||||
func main() {
|
||||
cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
|
||||
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 {
|
||||
log.Fatalf("Error creating Docker client: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
go watchDockerEvents(cli)
|
||||
lines := strings.Split(string(output), "\n")
|
||||
var containers []ContainerInfo
|
||||
|
||||
// Get running containers and set up monitoring intervals
|
||||
containers, err := getRunningContainers(cli)
|
||||
if err != nil {
|
||||
log.Fatalf("Error getting running containers: %v", err)
|
||||
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,
|
||||
})
|
||||
}
|
||||
|
||||
for _, container := range containers {
|
||||
if mode, ok := container.Labels["oculus.mode"]; ok {
|
||||
intervalStr := container.Labels["oculus.interval"]
|
||||
interval, err := time.ParseDuration(intervalStr)
|
||||
if err != nil {
|
||||
log.Fatalf("Invalid interval format for container %s: %v", container.ID, err)
|
||||
}
|
||||
return containers, nil
|
||||
}
|
||||
|
||||
if mode == "monitor" {
|
||||
go monitorContainers(cli, interval)
|
||||
} else if mode == "report" {
|
||||
go reportContainers(cli, interval)
|
||||
}
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
// Graceful shutdown handling
|
||||
sigs := make(chan os.Signal, 1)
|
||||
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
|
||||
<-sigs
|
||||
log.Println("Shutting down...")
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,34 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Function to process diffs and check ignores
|
||||
process_diff() {
|
||||
local container_id=$1
|
||||
local cname=$2
|
||||
local ignores=$3
|
||||
|
||||
# Get the diff
|
||||
diff_output=$(docker diff $container_id)
|
||||
|
||||
# Process ignores
|
||||
if [ -n "$ignores" ]; then
|
||||
IFS=',' read -ra ignore_array <<< "$ignores"
|
||||
for ignore in "${ignore_array[@]}"; do
|
||||
diff_output=$(echo "$diff_output" | grep -v "$ignore")
|
||||
done
|
||||
fi
|
||||
|
||||
# Write the diff output to a file
|
||||
echo "$diff_output" > "${cname}.diff"
|
||||
|
||||
# Check if there are any changes left after applying ignores
|
||||
if [ -n "$diff_output" ]; then
|
||||
# Send notification using go-glitch
|
||||
echo "$diff_output" | go-glitch
|
||||
fi
|
||||
}
|
||||
|
||||
export -f process_diff
|
||||
|
||||
# Read containers.txt and process each line in parallel
|
||||
cat containers.txt | parallel --colsep ' ' 'process_diff {1} {2} {3}'
|
||||
./
|
||||
Loading…
Reference in New Issue