First attempt for Oculus
ci/woodpecker/push/woodpecker Pipeline failed
Details
ci/woodpecker/push/woodpecker Pipeline failed
Details
This commit is contained in:
parent
56f168efb7
commit
804d00b763
|
|
@ -0,0 +1,145 @@
|
||||||
|
# build 1
|
||||||
|
labels:
|
||||||
|
hostname: "macmini7"
|
||||||
|
clone:
|
||||||
|
git:
|
||||||
|
image: woodpeckerci/plugin-git
|
||||||
|
settings:
|
||||||
|
partial: false
|
||||||
|
depth: 1
|
||||||
|
steps:
|
||||||
|
# Build Step for staging Branch
|
||||||
|
build-staging:
|
||||||
|
name: build-staging
|
||||||
|
image: woodpeckerci/plugin-docker-buildx
|
||||||
|
secrets: [REGISTRY_USER, REGISTRY_PASSWORD]
|
||||||
|
volumes:
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
commands:
|
||||||
|
- echo "Building application for staging branch"
|
||||||
|
- echo "$${REGISTRY_PASSWORD}" | docker login -u "$${REGISTRY_USER}" --password-stdin git.nixc.us
|
||||||
|
- echo compose build
|
||||||
|
- docker compose -f docker-compose.staging.yml build --no-cache
|
||||||
|
when:
|
||||||
|
branch: main
|
||||||
|
event: push
|
||||||
|
# path:
|
||||||
|
# include: [ 'stack.production.yml', 'stack.staging.yml', 'docker-compose.staging.yml', 'docker-compose.production.yml', 'Dockerfile', '*.tests.ts' ]
|
||||||
|
|
||||||
|
deploy-new:
|
||||||
|
name: deploy-new
|
||||||
|
when:
|
||||||
|
branch: main
|
||||||
|
# path:
|
||||||
|
# include: [ 'stack.production.yml', 'stack.staging.yml', 'docker-compose.staging.yml', 'docker-compose.production.yml', 'Dockerfile', '*.tests.ts' ]
|
||||||
|
image: woodpeckerci/plugin-docker-buildx
|
||||||
|
secrets: [REGISTRY_USER, REGISTRY_PASSWORD]
|
||||||
|
volumes:
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
commands:
|
||||||
|
- echo "$${REGISTRY_PASSWORD}" | docker login -u "$${REGISTRY_USER}" --password-stdin git.nixc.us
|
||||||
|
- echo compose push
|
||||||
|
- docker compose -f docker-compose.staging.yml push
|
||||||
|
# - docker stack deploy --with-registry-auth -c ./stack.staging.yml $${CI_REPO_NAME}-staging
|
||||||
|
|
||||||
|
# # Wait for Deploy to Complete
|
||||||
|
# wait-for-deploy-staging:
|
||||||
|
# name: wait-for-deploy-staging
|
||||||
|
# image: woodpeckerci/plugin-git
|
||||||
|
# commands:
|
||||||
|
# - echo "Waiting for staging deploy step to complete rollout."
|
||||||
|
# - sleep 60
|
||||||
|
# when:
|
||||||
|
# - branch: main
|
||||||
|
# - event: push
|
||||||
|
|
||||||
|
# # Run Automated Tests on staging Branch
|
||||||
|
# test-staging:
|
||||||
|
# name: run-tests-staging
|
||||||
|
# image: git.nixc.us/colin/playwright:latest
|
||||||
|
# secrets: [ base_url ]
|
||||||
|
# when:
|
||||||
|
# - branch: main
|
||||||
|
# - event: push
|
||||||
|
# - path:
|
||||||
|
# include: [ 'tests/', 'src/','docker-compose.staging.yml', 'docker-compose.production.yml', '*.tests.ts' ] # Specify paths relevant to tests
|
||||||
|
# volumes:
|
||||||
|
# - /var/run/docker.sock:/var/run/docker.sock:ro
|
||||||
|
|
||||||
|
cleanup-staging:
|
||||||
|
name: cleanup-staging
|
||||||
|
when:
|
||||||
|
branch: main
|
||||||
|
# path:
|
||||||
|
# include: [ 'stack.production.yml', 'stack.staging.yml', 'docker-compose.staging.yml', 'docker-compose.production.yml', 'Dockerfile', '*.tests.ts' ]
|
||||||
|
image: woodpeckerci/plugin-docker-buildx
|
||||||
|
secrets: [REGISTRY_USER, REGISTRY_PASSWORD]
|
||||||
|
volumes:
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
commands:
|
||||||
|
# - docker stack rm $${CI_REPO_NAME}-staging
|
||||||
|
## added fault tolerance for docker stack rm
|
||||||
|
- for i in {1..5}; do docker stack rm ${CI_REPO_NAME}-staging && break || sleep 10; done
|
||||||
|
- docker compose -f docker-compose.staging.yml down
|
||||||
|
- docker compose -f docker-compose.staging.yml rm -f
|
||||||
|
|
||||||
|
# Build Step for staging Branch
|
||||||
|
build-push-production:
|
||||||
|
name: build-push-production
|
||||||
|
image: woodpeckerci/plugin-docker-buildx
|
||||||
|
secrets: [REGISTRY_USER, REGISTRY_PASSWORD]
|
||||||
|
volumes:
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
commands:
|
||||||
|
- echo "Building application for staging branch"
|
||||||
|
- echo "$${REGISTRY_PASSWORD}" | docker login -u "$${REGISTRY_USER}" --password-stdin git.nixc.us
|
||||||
|
- echo compose build
|
||||||
|
- docker compose -f docker-compose.production.yml build --no-cache
|
||||||
|
- docker compose -f docker-compose.production.yml push
|
||||||
|
when:
|
||||||
|
branch: main
|
||||||
|
event: [push, cron]
|
||||||
|
# path:
|
||||||
|
# include: [ 'stack.production.yml', 'stack.staging.yml', 'docker-compose.staging.yml', 'docker-compose.production.yml', 'Dockerfile', '*.tests.ts' ]
|
||||||
|
|
||||||
|
# Deploy to Production Branch
|
||||||
|
deploy-production:
|
||||||
|
name: deploy-production
|
||||||
|
image: woodpeckerci/plugin-docker-buildx
|
||||||
|
secrets: [REGISTRY_USER, REGISTRY_PASSWORD]
|
||||||
|
volumes:
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
commands:
|
||||||
|
- echo "$${REGISTRY_PASSWORD}" | docker login -u "$${REGISTRY_USER}" --password-stdin git.nixc.us
|
||||||
|
- docker stack deploy --with-registry-auth -c ./stack.production.yml $${CI_REPO_NAME}
|
||||||
|
# - docker image rm git.nixc.us/colin/$${CI_REPO_NAME}:production
|
||||||
|
when:
|
||||||
|
branch: main
|
||||||
|
event: [push, cron]
|
||||||
|
# path:
|
||||||
|
# include: [ 'stack.production.yml', 'stack.staging.yml', 'docker-compose.staging.yml', 'docker-compose.production.yml', 'Dockerfile', '*.tests.ts' ]
|
||||||
|
|
||||||
|
|
||||||
|
# # Wait for Deploy to Complete
|
||||||
|
# wait-for-deploy-production:
|
||||||
|
# name: wait-for-deploy-production
|
||||||
|
# image: woodpeckerci/plugin-git
|
||||||
|
# commands:
|
||||||
|
# - echo "Waiting for deploy step to complete rollout."
|
||||||
|
# - sleep 60
|
||||||
|
# when:
|
||||||
|
# branch: main
|
||||||
|
# event: push
|
||||||
|
|
||||||
|
# # Run Post-Deployment Smoke Tests
|
||||||
|
# post-deploy-smoke-tests-git-nixc-us:
|
||||||
|
# name: run-post-deploy-smoke-tests-git-nixc-us
|
||||||
|
# image: git.nixc.us/colin/playwright:latest
|
||||||
|
# # secrets: [TEST_USER, TEST_PASSWORD]
|
||||||
|
# environment:
|
||||||
|
# - BASE_URL=https://git.nixc.us
|
||||||
|
# when:
|
||||||
|
# branch: main
|
||||||
|
# event: push
|
||||||
|
# # path:
|
||||||
|
# # include: [ 'stack.production.yml', 'stack.staging.yml', 'docker-compose.staging.yml', 'docker-compose.production.yml', 'Dockerfile', '*.tests.ts' ]
|
||||||
|
|
@ -1,6 +1,2 @@
|
||||||
# command-line-arguments
|
# command-line-arguments
|
||||||
./main.go:9:5: "os" imported and not used
|
./main.go:34:67: undefined: types.ContainerListOptions
|
||||||
./main.go:11:5: "strings" imported and not used
|
|
||||||
./main.go:12:5: "time" imported and not used
|
|
||||||
./main.go:15:5: "github.com/docker/docker/api/types/events" imported and not used
|
|
||||||
./main.go:34:70: undefined: types.ContainerListOptions
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,2 @@
|
||||||
# command-line-arguments
|
# command-line-arguments
|
||||||
./main.go:9:5: "os" imported and not used
|
./main.go:34:67: undefined: types.ContainerListOptions
|
||||||
./main.go:11:5: "strings" imported and not used
|
|
||||||
./main.go:12:5: "time" imported and not used
|
|
||||||
./main.go:15:5: "github.com/docker/docker/api/types/events" imported and not used
|
|
||||||
./main.go:34:70: undefined: types.ContainerListOptions
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,2 @@
|
||||||
# command-line-arguments
|
# command-line-arguments
|
||||||
./main.go:9:5: "os" imported and not used
|
./main.go:34:67: undefined: types.ContainerListOptions
|
||||||
./main.go:11:5: "strings" imported and not used
|
|
||||||
./main.go:12:5: "time" imported and not used
|
|
||||||
./main.go:15:5: "github.com/docker/docker/api/types/events" imported and not used
|
|
||||||
./main.go:34:70: undefined: types.ContainerListOptions
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,2 @@
|
||||||
# command-line-arguments
|
# command-line-arguments
|
||||||
./main.go:9:5: "os" imported and not used
|
./main.go:34:67: undefined: types.ContainerListOptions
|
||||||
./main.go:11:5: "strings" imported and not used
|
|
||||||
./main.go:12:5: "time" imported and not used
|
|
||||||
./main.go:15:5: "github.com/docker/docker/api/types/events" imported and not used
|
|
||||||
./main.go:34:70: undefined: types.ContainerListOptions
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,2 @@
|
||||||
# command-line-arguments
|
# command-line-arguments
|
||||||
./main.go:9:5: "os" imported and not used
|
./main.go:34:67: undefined: types.ContainerListOptions
|
||||||
./main.go:11:5: "strings" imported and not used
|
|
||||||
./main.go:12:5: "time" imported and not used
|
|
||||||
./main.go:15:5: "github.com/docker/docker/api/types/events" imported and not used
|
|
||||||
./main.go:34:70: undefined: types.ContainerListOptions
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,2 @@
|
||||||
# command-line-arguments
|
# command-line-arguments
|
||||||
./main.go:9:5: "os" imported and not used
|
./main.go:34:67: undefined: types.ContainerListOptions
|
||||||
./main.go:11:5: "strings" imported and not used
|
|
||||||
./main.go:12:5: "time" imported and not used
|
|
||||||
./main.go:15:5: "github.com/docker/docker/api/types/events" imported and not used
|
|
||||||
./main.go:34:70: undefined: types.ContainerListOptions
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,2 @@
|
||||||
# command-line-arguments
|
# command-line-arguments
|
||||||
./main.go:9:5: "os" imported and not used
|
./main.go:34:67: undefined: types.ContainerListOptions
|
||||||
./main.go:11:5: "strings" imported and not used
|
|
||||||
./main.go:12:5: "time" imported and not used
|
|
||||||
./main.go:15:5: "github.com/docker/docker/api/types/events" imported and not used
|
|
||||||
./main.go:34:70: undefined: types.ContainerListOptions
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,2 @@
|
||||||
# command-line-arguments
|
# command-line-arguments
|
||||||
./main.go:9:5: "os" imported and not used
|
./main.go:34:67: undefined: types.ContainerListOptions
|
||||||
./main.go:11:5: "strings" imported and not used
|
|
||||||
./main.go:12:5: "time" imported and not used
|
|
||||||
./main.go:15:5: "github.com/docker/docker/api/types/events" imported and not used
|
|
||||||
./main.go:34:70: undefined: types.ContainerListOptions
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
services:
|
||||||
|
oculus:
|
||||||
|
build:
|
||||||
|
context: ./docker/oculus/
|
||||||
|
dockerfile: Dockerfile.production
|
||||||
|
image: git.nixc.us/colin/oculus:production
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
services:
|
||||||
|
oculus:
|
||||||
|
build:
|
||||||
|
context: ./docker/oculus/
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
image: git.nixc.us/colin/oculus:staging
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
FROM alpine:latest
|
||||||
|
RUN apk update && apk add --no-cache curl bash
|
||||||
|
RUN curl -sSL https://git.nixc.us/colin/Oculus/raw/branch/main/install.sh | bash
|
||||||
|
RUN curl -sSL https://git.nixc.us/Nixius/go-glitch/src/branch/master/install.sh | bash
|
||||||
|
COPY notify.sh /notify.sh
|
||||||
|
RUN chmod +x /notify.sh
|
||||||
|
ENV GLITCHTIP_DSN=""
|
||||||
|
CMD ["./oculus"]
|
||||||
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
FROM git.nixc.us/colin/oculus:staging
|
||||||
5
go.mod
5
go.mod
|
|
@ -2,10 +2,7 @@ module yourmodule
|
||||||
|
|
||||||
go 1.21.1
|
go 1.21.1
|
||||||
|
|
||||||
require (
|
require github.com/docker/docker v26.1.4+incompatible
|
||||||
github.com/docker/docker v26.1.4+incompatible
|
|
||||||
github.com/robfig/cron/v3 v3.0.1
|
|
||||||
)
|
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/Microsoft/go-winio v0.4.14 // indirect
|
github.com/Microsoft/go-winio v0.4.14 // indirect
|
||||||
|
|
|
||||||
2
go.sum
2
go.sum
|
|
@ -47,8 +47,6 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
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 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
|
|
||||||
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
|
|
||||||
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
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 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||||
|
|
|
||||||
105
main.go
105
main.go
|
|
@ -8,18 +8,18 @@ import (
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
"github.com/docker/docker/api/types/events"
|
|
||||||
"github.com/docker/docker/api/types/filters"
|
"github.com/docker/docker/api/types/filters"
|
||||||
"github.com/docker/docker/client"
|
"github.com/docker/docker/client"
|
||||||
"github.com/robfig/cron/v3"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
notifyScript = "/notify.sh"
|
notifyScript = "/notify.sh"
|
||||||
|
logDir = "/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ContainerDiff represents the state of a container
|
// ContainerDiff represents the state of a container
|
||||||
|
|
@ -72,6 +72,42 @@ func loadDiffs(filePath string) ([]ContainerDiff, error) {
|
||||||
return diffs, err
|
return diffs, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// shouldIgnore checks if the change should be ignored based on the ignore list
|
||||||
|
func shouldIgnore(change string, ignoreList []string) bool {
|
||||||
|
for _, ignore := range ignoreList {
|
||||||
|
if strings.Contains(change, ignore) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// logDetection logs detection events to a file and sends to Go Glitch
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
// sendToGlitchtip sends the log file content to Go Glitch
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// profileContainers logs the current state of containers to a file
|
// profileContainers logs the current state of containers to a file
|
||||||
func profileContainers(cli *client.Client) {
|
func profileContainers(cli *client.Client) {
|
||||||
diffs, err := getRunningContainers(cli)
|
diffs, err := getRunningContainers(cli)
|
||||||
|
|
@ -108,27 +144,36 @@ func compareContainers(cli *client.Client) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ignoreList := strings.Split(current.Labels["oculus.ignorelist"], ",")
|
||||||
|
|
||||||
if len(savedDiffs) > 0 {
|
if len(savedDiffs) > 0 {
|
||||||
saved := savedDiffs[0]
|
saved := savedDiffs[0]
|
||||||
if current.Image != saved.Image {
|
if current.Image != saved.Image && !shouldIgnore(current.Image, ignoreList) {
|
||||||
log.Printf("Container %s changed: Image %s -> %s", current.ID, saved.Image, current.Image)
|
message := fmt.Sprintf("Container %s changed: Image %s -> %s", current.ID, saved.Image, current.Image)
|
||||||
runNotifyScript(current.ID, current.Image, saved.Image)
|
logDetection(current.Labels["oculus.containerid"], message)
|
||||||
|
runNotifyScript(filepath.Join(logDir, fmt.Sprintf("%s.log", current.Labels["oculus.containerid"])))
|
||||||
}
|
}
|
||||||
if current.Labels["oculus.ignorelist"] != saved.Labels["oculus.ignorelist"] {
|
if current.Labels["oculus.ignorelist"] != saved.Labels["oculus.ignorelist"] {
|
||||||
log.Printf("Container %s ignore list changed: %s -> %s", current.ID, saved.Labels["oculus.ignorelist"], current.Labels["oculus.ignorelist"])
|
message := fmt.Sprintf("Container %s ignore list changed: %s -> %s", current.ID, saved.Labels["oculus.ignorelist"], current.Labels["oculus.ignorelist"])
|
||||||
runNotifyScript(current.ID, current.Image, saved.Image)
|
if !shouldIgnore(message, ignoreList) {
|
||||||
|
logDetection(current.Labels["oculus.containerid"], message)
|
||||||
|
runNotifyScript(filepath.Join(logDir, fmt.Sprintf("%s.log", current.Labels["oculus.containerid"])))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log.Printf("New container detected: ID %s, Image %s", current.ID, current.Image)
|
message := fmt.Sprintf("New container detected: ID %s, Image %s", current.ID, current.Image)
|
||||||
runNotifyScript(current.ID, current.Image, "")
|
if !shouldIgnore(current.Image, ignoreList) {
|
||||||
|
logDetection(current.Labels["oculus.containerid"], message)
|
||||||
|
runNotifyScript(filepath.Join(logDir, fmt.Sprintf("%s.log", current.Labels["oculus.containerid"])))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// runNotifyScript executes the notification script with the container details
|
// runNotifyScript executes the notification script with the container details
|
||||||
func runNotifyScript(containerID, newImage, oldImage string) {
|
func runNotifyScript(logFilePath string) {
|
||||||
cmd := exec.Command(notifyScript, containerID, newImage, oldImage)
|
cmd := exec.Command(notifyScript, logFilePath)
|
||||||
err := cmd.Run()
|
err := cmd.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Error running notify script: %v", err)
|
log.Printf("Error running notify script: %v", err)
|
||||||
|
|
@ -159,24 +204,44 @@ func watchDockerEvents(cli *client.Client) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// scheduler sets up the cron jobs for profiling
|
// monitorContainers sets up monitoring for containers based on the specified interval
|
||||||
func scheduler(cli *client.Client) {
|
func monitorContainers(cli *client.Client, interval time.Duration) {
|
||||||
c := cron.New()
|
ticker := time.NewTicker(interval)
|
||||||
c.AddFunc("@every 1h", func() { profileContainers(cli) })
|
defer ticker.Stop()
|
||||||
c.Start()
|
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-ticker.C:
|
||||||
|
compareContainers(cli)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
|
cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
|
||||||
if (err != nil) {
|
if err != nil {
|
||||||
log.Fatalf("Error creating Docker client: %v", err)
|
log.Fatalf("Error creating Docker client: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
go scheduler(cli)
|
|
||||||
|
|
||||||
go watchDockerEvents(cli)
|
go watchDockerEvents(cli)
|
||||||
|
|
||||||
|
// Get running containers and set up monitoring intervals
|
||||||
|
containers, err := getRunningContainers(cli)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Error getting running containers: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, container := range containers {
|
||||||
|
if container.Labels["oculus.mode"] == "monitor" {
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
go monitorContainers(cli, interval)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Keep the program running
|
// Keep the program running
|
||||||
select {}
|
select {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
services:
|
||||||
|
oculus:
|
||||||
|
image: git.nixc.us/nixius/oculus:production
|
||||||
|
networks:
|
||||||
|
- traefik
|
||||||
|
environment:
|
||||||
|
GLITCHTIP_DSN: ""
|
||||||
|
volumes:
|
||||||
|
- /mnt/tank/persist/nixc.us/oculus/production/data:/log
|
||||||
|
- "/var/run/docker.sock:/var/run/docker.sock:ro"
|
||||||
|
deploy:
|
||||||
|
placement:
|
||||||
|
constraints:
|
||||||
|
- node.role == manager
|
||||||
|
labels:
|
||||||
|
traefik.enable: "false"
|
||||||
|
oculus.containerid: "oculus"
|
||||||
|
oculus.ignorelist: "/log/,/tmp/"
|
||||||
|
oculus.mode: "monitor"
|
||||||
|
oculus.interval: "60s"
|
||||||
|
update_config:
|
||||||
|
order: stop-first
|
||||||
|
failure_action: rollback
|
||||||
|
delay: 0s
|
||||||
|
parallelism: 1
|
||||||
|
restart_policy:
|
||||||
|
condition: on-failure
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
services:
|
||||||
|
oculus:
|
||||||
|
image: git.nixc.us/nixius/oculus:staging
|
||||||
|
networks:
|
||||||
|
- traefik
|
||||||
|
environment:
|
||||||
|
GLITCHTIP_DSN: ""
|
||||||
|
# volumes:
|
||||||
|
# - /mnt/tank/persist/nixc.us/oculus/staging/data:/log
|
||||||
|
deploy:
|
||||||
|
# placement:
|
||||||
|
# constraints:
|
||||||
|
# - node.hostname == macmini14
|
||||||
|
labels:
|
||||||
|
traefik.enable: "false"
|
||||||
|
update_config:
|
||||||
|
order: stop-first
|
||||||
|
failure_action: rollback
|
||||||
|
delay: 0s
|
||||||
|
parallelism: 1
|
||||||
|
restart_policy:
|
||||||
|
condition: on-failure
|
||||||
Loading…
Reference in New Issue