Heric Camargo pushed to branch main at Root / CLI / Mirror Monitor
Commits:
-
bbf91f31
by Heric Camargo at 2025-08-11T18:39:31-03:00
-
97f8a604
by Heric Camargo at 2025-08-11T18:39:53-03:00
8 changed files:
- .gitignore
- Containerfile
- cmd/api/main.go
- + deploy/k8s/deployment.yaml
- + deploy/k8s/ingress.yaml
- + deploy/k8s/service.yaml
- deploy/rsyncuptime.service → deploy/mirror-monitor.service
- shell.nix
Changes:
... | ... | @@ -3,8 +3,7 @@ |
3 | 3 | #
|
4 | 4 | |
5 | 5 | # binaries
|
6 | -rsyncuptime-server
|
|
7 | -rsyncuptime-tui
|
|
6 | +mirror-monitor-tui
|
|
8 | 7 | bin/
|
9 | 8 | |
10 | 9 | # Binaries for programs and plugins
|
... | ... | @@ -3,26 +3,39 @@ FROM golang:1.24 AS builder |
3 | 3 | |
4 | 4 | WORKDIR /app
|
5 | 5 | |
6 | -# Copia os arquivos do projeto
|
|
6 | +# Copia go.mod e go.sum para melhor cache de layers
|
|
7 | +COPY go.mod go.sum ./
|
|
8 | + |
|
9 | +# Download das dependências
|
|
10 | +RUN go mod download
|
|
11 | + |
|
12 | +# Copia o restante dos arquivos do projeto
|
|
7 | 13 | COPY . .
|
8 | 14 | |
9 | 15 | # Compilando o binário da API
|
10 | -RUN go build -o rsyncuptime cmd/api/main.go
|
|
16 | +RUN go build -o mirror-monitor ./cmd/api
|
|
11 | 17 | |
12 | 18 | # Etapa final:
|
13 | 19 | FROM debian:bookworm-slim
|
14 | 20 | |
15 | -# Instalando o rsync:
|
|
21 | +# Instalando o rsync e criando usuário não-root:
|
|
16 | 22 | RUN apt-get update && \
|
17 | - apt-get install -y rsync && \
|
|
18 | - apt-get clean && rm -rf /var/lib/apt/lists/*
|
|
23 | + apt-get install -y rsync ca-certificates && \
|
|
24 | + apt-get clean && rm -rf /var/lib/apt/lists/* && \
|
|
25 | + useradd -r -u 1000 -s /bin/false appuser
|
|
19 | 26 | |
20 | 27 | # Copiando o binário compilado:
|
21 | -COPY --from=builder /app/rsyncuptime /usr/local/bin/rsyncuptime
|
|
28 | +COPY --from=builder /app/mirror-monitor /usr/local/bin/mirror-monitor
|
|
29 | + |
|
30 | +# Tornando o binário executável
|
|
31 | +RUN chmod +x /usr/local/bin/mirror-monitor
|
|
32 | + |
|
33 | +# Mudando para usuário não-root
|
|
34 | +USER 1000
|
|
22 | 35 | |
23 | 36 | # Exponha a porta, se necessário:
|
24 | 37 | #Atenção: se você mudar de porta, esse trecho do código deve-se mudar também!
|
25 | 38 | EXPOSE 8080
|
26 | 39 | |
27 | 40 | # Definindo o comando de entrada:
|
28 | -CMD ["rsyncuptime"] |
|
41 | +CMD ["mirror-monitor"] |
... | ... | @@ -2,6 +2,7 @@ package main |
2 | 2 | |
3 | 3 | import (
|
4 | 4 | "bufio"
|
5 | + "context"
|
|
5 | 6 | "encoding/json"
|
6 | 7 | "errors"
|
7 | 8 | "fmt"
|
... | ... | @@ -9,6 +10,7 @@ import ( |
9 | 10 | "net/http"
|
10 | 11 | "os"
|
11 | 12 | "os/exec"
|
13 | + "os/signal"
|
|
12 | 14 | "regexp"
|
13 | 15 | "strconv"
|
14 | 16 | "strings"
|
... | ... | @@ -332,7 +334,21 @@ func main() { |
332 | 334 | })
|
333 | 335 | |
334 | 336 | log.Printf("Starting monitoring server on :%s using rsync URL '%s'", serverPort, rsyncURL)
|
335 | - if err := http.ListenAndServe(":"+serverPort, mux); err != nil {
|
|
336 | - log.Fatalf("Server failed to start: %s", err)
|
|
337 | + server := &http.Server{Addr: ":" + serverPort, Handler: mux}
|
|
338 | + // Graceful shutdown on SIGINT/SIGTERM
|
|
339 | + stop := make(chan os.Signal, 1)
|
|
340 | + signal.Notify(stop, os.Interrupt)
|
|
341 | + go func() {
|
|
342 | + if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
|
|
343 | + log.Fatalf("Server error: %s", err)
|
|
344 | + }
|
|
345 | + }()
|
|
346 | + <-stop
|
|
347 | + log.Println("Shutting down server...")
|
|
348 | + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
|
349 | + defer cancel()
|
|
350 | + if err := server.Shutdown(ctx); err != nil {
|
|
351 | + log.Fatalf("Server Shutdown Failed:%+v", err)
|
|
337 | 352 | }
|
353 | + log.Println("Server exited gracefully")
|
|
338 | 354 | } |
1 | +# Kubernetes Deployment for the mirror-monitor API service
|
|
2 | +apiVersion: apps/v1
|
|
3 | +kind: Deployment
|
|
4 | +metadata:
|
|
5 | + name: mirror-monitor-api
|
|
6 | + labels:
|
|
7 | + app: mirror-monitor-api
|
|
8 | + version: v1
|
|
9 | + component: api
|
|
10 | +spec:
|
|
11 | + replicas: 1
|
|
12 | + selector:
|
|
13 | + matchLabels:
|
|
14 | + app: mirror-monitor-api
|
|
15 | + template:
|
|
16 | + metadata:
|
|
17 | + labels:
|
|
18 | + app: mirror-monitor-api
|
|
19 | + version: v1
|
|
20 | + component: api
|
|
21 | + spec:
|
|
22 | + containers:
|
|
23 | + - name: api
|
|
24 | + image: mirror-monitor-api:latest
|
|
25 | + imagePullPolicy: IfNotPresent
|
|
26 | + ports:
|
|
27 | + - containerPort: 8080
|
|
28 | + env:
|
|
29 | + - name: RSYNC_URL
|
|
30 | + value: "rsync://sagres.c3sl.ufpr.br/"
|
|
31 | + - name: POLLING_INTERVAL_SECONDS
|
|
32 | + value: "300"
|
|
33 | + - name: PORT
|
|
34 | + value: "8080"
|
|
35 | + resources:
|
|
36 | + requests:
|
|
37 | + memory: "64Mi"
|
|
38 | + cpu: "50m"
|
|
39 | + limits:
|
|
40 | + memory: "128Mi"
|
|
41 | + cpu: "100m"
|
|
42 | + livenessProbe:
|
|
43 | + httpGet:
|
|
44 | + path: /modules
|
|
45 | + port: 8080
|
|
46 | + initialDelaySeconds: 30
|
|
47 | + periodSeconds: 30
|
|
48 | + timeoutSeconds: 5
|
|
49 | + failureThreshold: 3
|
|
50 | + readinessProbe:
|
|
51 | + httpGet:
|
|
52 | + path: /modules
|
|
53 | + port: 8080
|
|
54 | + initialDelaySeconds: 5
|
|
55 | + periodSeconds: 10
|
|
56 | + timeoutSeconds: 3
|
|
57 | + failureThreshold: 3
|
|
58 | + # Security context for better security
|
|
59 | + securityContext:
|
|
60 | + allowPrivilegeEscalation: false
|
|
61 | + runAsNonRoot: true
|
|
62 | + runAsUser: 1000
|
|
63 | + readOnlyRootFilesystem: true
|
|
64 | + capabilities:
|
|
65 | + drop:
|
|
66 | + - ALL |
1 | +# Optional Ingress for exposing the mirror-monitor API externally
|
|
2 | +apiVersion: networking.k8s.io/v1
|
|
3 | +kind: Ingress
|
|
4 | +metadata:
|
|
5 | + name: mirror-monitor-api-ingress
|
|
6 | + annotations:
|
|
7 | + # Remove the rewrite rule since we want to preserve the API paths
|
|
8 | + nginx.ingress.kubernetes.io/ssl-redirect: "false"
|
|
9 | +spec:
|
|
10 | + rules:
|
|
11 | + - host: mirror-monitor.local
|
|
12 | + http:
|
|
13 | + paths:
|
|
14 | + - path: /
|
|
15 | + pathType: Prefix
|
|
16 | + backend:
|
|
17 | + service:
|
|
18 | + name: mirror-monitor-api
|
|
19 | + port:
|
|
20 | + number: 80 |
1 | +# Kubernetes Service for the mirror-monitor API
|
|
2 | +apiVersion: v1
|
|
3 | +kind: Service
|
|
4 | +metadata:
|
|
5 | + name: mirror-monitor-api
|
|
6 | +spec:
|
|
7 | + type: ClusterIP
|
|
8 | + selector:
|
|
9 | + app: mirror-monitor-api
|
|
10 | + ports:
|
|
11 | + - name: http
|
|
12 | + port: 80
|
|
13 | + targetPort: 8080 # Match the containerPort in your Deployment |
1 | -# Nix shell para desenvolvimento do servidor web rsyncuptime
|
|
1 | +# Nix shell para desenvolvimento do servidor web mirror-monitor
|
|
2 | 2 | |
3 | 3 | { pkgs ? import <nixpkgs> {} }:
|
4 | 4 | |
... | ... | @@ -8,6 +8,11 @@ pkgs.mkShell { |
8 | 8 | pkgs.rsync
|
9 | 9 | pkgs.jq
|
10 | 10 | pkgs.mage
|
11 | + |
|
12 | + # kubernetes
|
|
13 | + pkgs.kubectl
|
|
14 | + pkgs.kind
|
|
15 | + pkgs.docker
|
|
11 | 16 | ];
|
12 | 17 | |
13 | 18 | shellHook = ''
|