Skip to content

Commit 6d1f7b9

Browse files
Merge pull request #40 from hhftechnology/pangolin
Stable-Version-Release-V1.0.0
2 parents a040df8 + 4af9caa commit 6d1f7b9

210 files changed

Lines changed: 22074 additions & 8212 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/docker-publish.yml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@ on:
55
branches:
66
- main
77
- dev
8-
- dev-go
9-
- dev-discord
8+
- pangolin
109
tags:
1110
- 'v*'
1211
pull_request:
@@ -76,4 +75,4 @@ jobs:
7675
labels: ${{ steps.meta.outputs.labels }}
7776
cache-from: type=gha
7877
cache-to: type=gha,mode=max
79-
platforms: linux/amd64,linux/arm64
78+
platforms: linux/amd64,linux/arm64

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
# Node.js
1111
# =====================================================
1212
# Logs
13-
logs
13+
/logs
1414
*.log
1515
npm-debug.log*
1616
yarn-debug.log*

cmd/server/main.go

Lines changed: 93 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,16 @@ import (
1515
"github.com/gin-gonic/gin"
1616

1717
"crowdsec-manager/internal/api"
18+
"crowdsec-manager/internal/api/handlers"
19+
"crowdsec-manager/internal/api/middleware"
1820
"crowdsec-manager/internal/backup"
1921
"crowdsec-manager/internal/config"
22+
"crowdsec-manager/internal/configvalidator"
2023
"crowdsec-manager/internal/cron"
2124
"crowdsec-manager/internal/database"
2225
"crowdsec-manager/internal/docker"
2326
"crowdsec-manager/internal/logger"
27+
"crowdsec-manager/internal/messaging"
2428
)
2529

2630
// Main entry point for the CrowdSec Manager server
@@ -35,6 +39,7 @@ func main() {
3539

3640
// Initialize structured logger with configured level and output file
3741
logger.Init(cfg.LogLevel, cfg.LogFile)
42+
defer logger.Sync()
3843

3944
// Initialize SQLite database connection with automatic schema migration
4045
db, err := database.New(cfg.DatabasePath)
@@ -44,12 +49,15 @@ func main() {
4449
defer db.Close()
4550
logger.Info("Database initialized", "path", cfg.DatabasePath)
4651

47-
// Initialize Docker API client with automatic version negotiation
48-
dockerClient, err := docker.NewClient()
52+
// Initialize multi-host Docker client (falls back to single host if DOCKER_HOSTS is empty)
53+
multiHost, err := docker.NewMultiHostClient(cfg.DockerHosts)
4954
if err != nil {
5055
logger.Fatal("Failed to initialize Docker client", "error", err)
5156
}
52-
defer dockerClient.Close()
57+
defer multiHost.Close()
58+
59+
// Default client for backward compatibility with existing handler signatures
60+
dockerClient := multiHost.DefaultClient()
5361

5462
dataDir := cfg.ConfigDir
5563

@@ -61,6 +69,29 @@ func main() {
6169
cronScheduler.Start()
6270
defer cronScheduler.Stop()
6371

72+
// Initialize WebSocket/SSE hub (always available for real-time events)
73+
hub := messaging.NewHub()
74+
go hub.Run()
75+
defer hub.Stop()
76+
77+
// Initialize config validator for drift detection and recovery
78+
validator := configvalidator.NewValidator(db, dockerClient, hub, cfg)
79+
handlers.SetConfigValidator(validator)
80+
81+
// Snapshot all configs on startup (populates DB if empty)
82+
validator.SnapshotAll()
83+
84+
// Validate configs and warn about drift
85+
if report := validator.ValidateAll(); report.Overall != "ok" {
86+
logger.Warn("Config drift detected on startup", "overall", report.Overall)
87+
}
88+
89+
// Initialize NATS messaging (optional — nil-safe when disabled)
90+
publisher, natsCleanup := initMessaging(cfg, hub)
91+
if natsCleanup != nil {
92+
defer natsCleanup()
93+
}
94+
6495
// Configure HTTP router with recovery middleware and custom logger
6596
router := gin.New()
6697
router.Use(gin.Recovery())
@@ -70,7 +101,7 @@ func main() {
70101
router.Use(cors.New(cors.Config{
71102
AllowOrigins: []string{"http://localhost:3000", "http://localhost:5173"},
72103
AllowMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},
73-
AllowHeaders: []string{"Origin", "Content-Type", "Authorization"},
104+
AllowHeaders: []string{"Origin", "Content-Type", "Authorization", "X-Docker-Host"},
74105
ExposeHeaders: []string{"Content-Length"},
75106
AllowCredentials: true,
76107
MaxAge: 12 * time.Hour,
@@ -83,6 +114,13 @@ func main() {
83114

84115
// Register all API route groups under /api prefix
85116
apiGroup := router.Group("/api")
117+
118+
// Add rate limiting middleware (100 requests per minute per IP)
119+
apiGroup.Use(middleware.RateLimiter(100))
120+
121+
// Add Docker host selector middleware for multi-host support
122+
apiGroup.Use(middleware.DockerHostSelector(multiHost))
123+
86124
{
87125
api.RegisterHealthRoutes(apiGroup, dockerClient, db, cfg)
88126
api.RegisterIPRoutes(apiGroup, dockerClient, cfg)
@@ -97,8 +135,29 @@ func main() {
97135
api.RegisterServicesRoutes(apiGroup, dockerClient, db, cfg)
98136
api.RegisterNotificationRoutes(apiGroup, dockerClient, db, cfg)
99137
api.RegisterProfileRoutes(apiGroup, db, cfg, dockerClient)
138+
api.RegisterHostRoutes(apiGroup, multiHost)
139+
api.RegisterTerminalRoutes(apiGroup, dockerClient)
140+
141+
// Hub browser routes
142+
api.RegisterHubRoutes(apiGroup, dockerClient, db, cfg)
143+
144+
// Simulation mode routes
145+
api.RegisterSimulationRoutes(apiGroup, dockerClient, cfg)
146+
147+
// Event routes (hub is always available for SSE/WebSocket)
148+
api.RegisterEventRoutes(apiGroup, hub)
149+
150+
// Config validation routes
151+
api.RegisterConfigValidationRoutes(apiGroup, validator)
100152
}
101153

154+
// Bridge NATS events to WebSocket hub (if both are available)
155+
if publisher != nil && hub != nil {
156+
go bridgeNATSToHub(cfg, hub)
157+
}
158+
// Suppress unused variable warnings — publisher will be used by handlers in Phase 4
159+
_ = publisher
160+
102161
// Serve React frontend static assets and handle client-side routing
103162
router.Static("/assets", "./web/dist/assets")
104163
router.StaticFile("/", "./web/dist/index.html")
@@ -141,6 +200,36 @@ func main() {
141200
logger.Info("Server exited")
142201
}
143202

203+
// initMessaging initializes NATS client and publisher.
204+
// Returns nil values when NATS is disabled — all are nil-safe.
205+
func initMessaging(cfg *config.Config, hub *messaging.Hub) (*messaging.Publisher, func()) {
206+
if !cfg.NatsEnabled || cfg.NatsURL == "" {
207+
logger.Info("NATS messaging disabled")
208+
return nil, nil
209+
}
210+
211+
natsClient, err := messaging.NewClient(cfg.NatsURL, cfg.NatsToken)
212+
if err != nil {
213+
logger.Error("Failed to connect to NATS (messaging disabled)", "error", err)
214+
return nil, nil
215+
}
216+
217+
publisher := messaging.NewPublisher(natsClient)
218+
219+
logger.Info("NATS messaging initialized", "url", cfg.NatsURL)
220+
221+
cleanup := func() {
222+
natsClient.Close()
223+
}
224+
return publisher, cleanup
225+
}
226+
227+
// bridgeNATSToHub subscribes to NATS subjects and forwards events to the WebSocket hub
228+
func bridgeNATSToHub(cfg *config.Config, hub *messaging.Hub) {
229+
// This will be wired up when NATS client Subscribe is implemented
230+
logger.Info("NATS-to-WebSocket bridge started")
231+
}
232+
144233
// checkPrerequisites verifies that Docker daemon is running and required containers exist
145234
// This function is defined but not currently called in main - consider adding prerequisite checks if needed
146235
func checkPrerequisites(client *docker.Client, cfg *config.Config) error {
File renamed without changes.

docker-compose.dev.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ services:
5353
cd /app &&
5454
go install github.com/cosmtrek/air@latest &&
5555
cd /app/web && npm install && npm run dev &
56-
cd /app && air
56+
cd /app && air -c configs/.air.toml
5757
"
5858
5959
# Pangolin service

go.mod

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
11
module crowdsec-manager
22

3-
go 1.23
3+
go 1.23.0
44

55
require (
66
github.com/buger/jsonparser v1.1.1
77
github.com/compose-spec/compose-go/v2 v2.9.1
88
github.com/docker/docker v28.0.2+incompatible
99
github.com/gin-contrib/cors v1.7.2
1010
github.com/gin-gonic/gin v1.10.0
11-
github.com/goccy/go-yaml v1.19.0
11+
github.com/google/uuid v1.6.0
1212
github.com/gorilla/websocket v1.5.3
1313
github.com/mattn/go-sqlite3 v1.14.32
14+
github.com/nats-io/nats.go v1.48.0
1415
github.com/robfig/cron/v3 v3.0.1
15-
github.com/sirupsen/logrus v1.9.3
16+
go.uber.org/zap v1.27.0
1617
gopkg.in/yaml.v3 v3.0.1
1718
)
1819

@@ -37,6 +38,7 @@ require (
3738
github.com/goccy/go-json v0.10.4 // indirect
3839
github.com/gogo/protobuf v1.3.2 // indirect
3940
github.com/json-iterator/go v1.1.12 // indirect
41+
github.com/klauspost/compress v1.18.0 // indirect
4042
github.com/klauspost/cpuid/v2 v2.2.9 // indirect
4143
github.com/leodido/go-urn v1.4.0 // indirect
4244
github.com/mattn/go-isatty v0.0.20 // indirect
@@ -46,11 +48,14 @@ require (
4648
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
4749
github.com/modern-go/reflect2 v1.0.2 // indirect
4850
github.com/morikuni/aec v1.0.0 // indirect
51+
github.com/nats-io/nkeys v0.4.11 // indirect
52+
github.com/nats-io/nuid v1.0.1 // indirect
4953
github.com/opencontainers/go-digest v1.0.0 // indirect
5054
github.com/opencontainers/image-spec v1.1.0 // indirect
5155
github.com/pelletier/go-toml/v2 v2.2.3 // indirect
5256
github.com/pkg/errors v0.9.1 // indirect
5357
github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 // indirect
58+
github.com/sirupsen/logrus v1.9.3 // indirect
5459
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
5560
github.com/ugorji/go/codec v1.2.12 // indirect
5661
github.com/xhit/go-str2duration/v2 v2.1.0 // indirect
@@ -61,13 +66,14 @@ require (
6166
go.opentelemetry.io/otel/metric v1.33.0 // indirect
6267
go.opentelemetry.io/otel/sdk v1.33.0 // indirect
6368
go.opentelemetry.io/otel/trace v1.33.0 // indirect
69+
go.uber.org/multierr v1.10.0 // indirect
6470
go.yaml.in/yaml/v3 v3.0.4 // indirect
6571
golang.org/x/arch v0.12.0 // indirect
66-
golang.org/x/crypto v0.32.0 // indirect
72+
golang.org/x/crypto v0.37.0 // indirect
6773
golang.org/x/net v0.34.0 // indirect
68-
golang.org/x/sync v0.10.0 // indirect
69-
golang.org/x/sys v0.29.0 // indirect
70-
golang.org/x/text v0.21.0 // indirect
74+
golang.org/x/sync v0.13.0 // indirect
75+
golang.org/x/sys v0.32.0 // indirect
76+
golang.org/x/text v0.24.0 // indirect
7177
golang.org/x/time v0.9.0 // indirect
7278
google.golang.org/protobuf v1.36.4 // indirect
7379
gotest.tools/v3 v3.5.1 // indirect

go.sum

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,6 @@ github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9L
5858
github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
5959
github.com/goccy/go-json v0.10.4 h1:JSwxQzIqKfmFX1swYPpUThQZp/Ka4wzJdK0LWVytLPM=
6060
github.com/goccy/go-json v0.10.4/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
61-
github.com/goccy/go-yaml v1.19.0 h1:EmkZ9RIsX+Uq4DYFowegAuJo8+xdX3T/2dwNPXbxEYE=
62-
github.com/goccy/go-yaml v1.19.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
6361
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
6462
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
6563
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
@@ -75,6 +73,8 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr
7573
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
7674
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
7775
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
76+
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
77+
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
7878
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
7979
github.com/klauspost/cpuid/v2 v2.2.9 h1:66ze0taIn2H33fBvCkXuv9BmCwDfafmiIVpKV9kKGuY=
8080
github.com/klauspost/cpuid/v2 v2.2.9/go.mod h1:rqkxqrZ1EhYM9G+hXH7YdowN5R5RGN6NK4QwQ3WMXF8=
@@ -102,6 +102,12 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G
102102
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
103103
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
104104
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
105+
github.com/nats-io/nats.go v1.48.0 h1:pSFyXApG+yWU/TgbKCjmm5K4wrHu86231/w84qRVR+U=
106+
github.com/nats-io/nats.go v1.48.0/go.mod h1:iRWIPokVIFbVijxuMQq4y9ttaBTMe0SFdlZfMDd+33g=
107+
github.com/nats-io/nkeys v0.4.11 h1:q44qGV008kYd9W1b1nEBkNzvnWxtRSQ7A8BoqRrcfa0=
108+
github.com/nats-io/nkeys v0.4.11/go.mod h1:szDimtgmfOi9n25JpfIdGw12tZFYXqhGxjhVxsatHVE=
109+
github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
110+
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
105111
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
106112
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
107113
github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug=
@@ -156,15 +162,21 @@ go.opentelemetry.io/otel/trace v1.33.0 h1:cCJuF7LRjUFso9LPnEAHJDB2pqzp+hbO8eu1qq
156162
go.opentelemetry.io/otel/trace v1.33.0/go.mod h1:uIcdVUZMpTAmz0tI1z04GoVSezK37CbGV4fr1f2nBck=
157163
go.opentelemetry.io/proto/otlp v1.4.0 h1:TA9WRvW6zMwP+Ssb6fLoUIuirti1gGbP28GcKG1jgeg=
158164
go.opentelemetry.io/proto/otlp v1.4.0/go.mod h1:PPBWZIP98o2ElSqI35IHfu7hIhSwvc5N38Jw8pXuGFY=
165+
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
166+
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
167+
go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ=
168+
go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
169+
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
170+
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
159171
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
160172
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
161173
golang.org/x/arch v0.12.0 h1:UsYJhbzPYGsT0HbEdmYcqtCv8UNGvnaL561NnIUvaKg=
162174
golang.org/x/arch v0.12.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
163175
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
164176
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
165177
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
166-
golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc=
167-
golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc=
178+
golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE=
179+
golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc=
168180
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
169181
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
170182
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
@@ -176,19 +188,19 @@ golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
176188
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
177189
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
178190
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
179-
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
180-
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
191+
golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610=
192+
golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
181193
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
182194
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
183195
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
184196
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
185197
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
186-
golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
187-
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
198+
golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
199+
golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
188200
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
189201
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
190-
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
191-
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
202+
golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0=
203+
golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU=
192204
golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY=
193205
golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
194206
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=

0 commit comments

Comments
 (0)