From 3c2ae2cda2b3fb916aaabbf92276da7ee8e5553f Mon Sep 17 00:00:00 2001 From: milx Date: Mon, 6 Jul 2026 20:30:22 +0330 Subject: [PATCH 01/18] Fix: Add Missing grpc field for created at --- pkg/scheduler/controlv1/control.pb.go | 107 ++++++++++++--------- pkg/scheduler/controlv1/control_grpc.pb.go | 2 +- 2 files changed, 60 insertions(+), 49 deletions(-) diff --git a/pkg/scheduler/controlv1/control.pb.go b/pkg/scheduler/controlv1/control.pb.go index 1aabe2a..a2d0fc4 100644 --- a/pkg/scheduler/controlv1/control.pb.go +++ b/pkg/scheduler/controlv1/control.pb.go @@ -3630,6 +3630,7 @@ type WorkloadView struct { LastUpdated *timestamppb.Timestamp `protobuf:"bytes,11,opt,name=last_updated,json=lastUpdated,proto3" json:"last_updated,omitempty"` Reason *ReasonDetail `protobuf:"bytes,12,opt,name=reason,proto3" json:"reason,omitempty"` Usage *WorkloadUsageSnapshot `protobuf:"bytes,13,opt,name=usage,proto3" json:"usage,omitempty"` + CreatedAt *timestamppb.Timestamp `protobuf:"bytes,14,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -3755,6 +3756,13 @@ func (x *WorkloadView) GetUsage() *WorkloadUsageSnapshot { return nil } +func (x *WorkloadView) GetCreatedAt() *timestamppb.Timestamp { + if x != nil { + return x.CreatedAt + } + return nil +} + type GetClusterSummaryRequest struct { state protoimpl.MessageState `protogen:"open.v1"` unknownFields protoimpl.UnknownFields @@ -4314,7 +4322,7 @@ const file_control_proto_rawDesc = "" + "\x15ListWorkloadsResponse\x12=\n" + "\tworkloads\x18\x01 \x03(\v2\x1f.persys.control.v1.WorkloadViewR\tworkloads\"R\n" + "\x13GetWorkloadResponse\x12;\n" + - "\bworkload\x18\x01 \x01(\v2\x1f.persys.control.v1.WorkloadViewR\bworkload\"\xbf\x04\n" + + "\bworkload\x18\x01 \x01(\v2\x1f.persys.control.v1.WorkloadViewR\bworkload\"\xfa\x04\n" + "\fWorkloadView\x12\x1f\n" + "\vworkload_id\x18\x01 \x01(\tR\n" + "workloadId\x12\x12\n" + @@ -4331,7 +4339,9 @@ const file_control_proto_rawDesc = "" + " \x01(\tR\rfailureReason\x12=\n" + "\flast_updated\x18\v \x01(\v2\x1a.google.protobuf.TimestampR\vlastUpdated\x127\n" + "\x06reason\x18\f \x01(\v2\x1f.persys.control.v1.ReasonDetailR\x06reason\x12>\n" + - "\x05usage\x18\r \x01(\v2(.persys.control.v1.WorkloadUsageSnapshotR\x05usage\"\x1a\n" + + "\x05usage\x18\r \x01(\v2(.persys.control.v1.WorkloadUsageSnapshotR\x05usage\x129\n" + + "\n" + + "created_at\x18\x0e \x01(\v2\x1a.google.protobuf.TimestampR\tcreatedAt\"\x1a\n" + "\x18GetClusterSummaryRequest\"\x9f\x03\n" + "\x19GetClusterSummaryResponse\x12\x1f\n" + "\vtotal_nodes\x18\x01 \x01(\x05R\n" + @@ -4524,52 +4534,53 @@ var file_control_proto_depIdxs = []int32{ 63, // 53: persys.control.v1.WorkloadView.last_updated:type_name -> google.protobuf.Timestamp 28, // 54: persys.control.v1.WorkloadView.reason:type_name -> persys.control.v1.ReasonDetail 27, // 55: persys.control.v1.WorkloadView.usage:type_name -> persys.control.v1.WorkloadUsageSnapshot - 63, // 56: persys.control.v1.GetClusterSummaryResponse.generated_at:type_name -> google.protobuf.Timestamp - 5, // 57: persys.control.v1.ControlMessage.register:type_name -> persys.control.v1.RegisterNodeRequest - 9, // 58: persys.control.v1.ControlMessage.heartbeat:type_name -> persys.control.v1.HeartbeatRequest - 12, // 59: persys.control.v1.ControlMessage.apply:type_name -> persys.control.v1.ApplyWorkloadRequest - 14, // 60: persys.control.v1.ControlMessage.delete:type_name -> persys.control.v1.DeleteWorkloadRequest - 5, // 61: persys.control.v1.AgentControl.RegisterNode:input_type -> persys.control.v1.RegisterNodeRequest - 9, // 62: persys.control.v1.AgentControl.Heartbeat:input_type -> persys.control.v1.HeartbeatRequest - 12, // 63: persys.control.v1.AgentControl.ApplyWorkload:input_type -> persys.control.v1.ApplyWorkloadRequest - 14, // 64: persys.control.v1.AgentControl.DeleteWorkload:input_type -> persys.control.v1.DeleteWorkloadRequest - 30, // 65: persys.control.v1.AgentControl.RetryWorkload:input_type -> persys.control.v1.RetryWorkloadRequest - 32, // 66: persys.control.v1.AgentControl.DrainNode:input_type -> persys.control.v1.DrainNodeRequest - 34, // 67: persys.control.v1.AgentControl.UndrainNode:input_type -> persys.control.v1.UndrainNodeRequest - 37, // 68: persys.control.v1.AgentControl.TaintNode:input_type -> persys.control.v1.TaintNodeRequest - 39, // 69: persys.control.v1.AgentControl.UntaintNode:input_type -> persys.control.v1.UntaintNodeRequest - 41, // 70: persys.control.v1.AgentControl.SetNodeLabel:input_type -> persys.control.v1.SetNodeLabelRequest - 43, // 71: persys.control.v1.AgentControl.DeleteNodeLabel:input_type -> persys.control.v1.DeleteNodeLabelRequest - 3, // 72: persys.control.v1.AgentControl.SubmitAutomationSuggestion:input_type -> persys.control.v1.SubmitAutomationSuggestionRequest - 45, // 73: persys.control.v1.AgentControl.ListNodes:input_type -> persys.control.v1.ListNodesRequest - 46, // 74: persys.control.v1.AgentControl.GetNode:input_type -> persys.control.v1.GetNodeRequest - 50, // 75: persys.control.v1.AgentControl.ListWorkloads:input_type -> persys.control.v1.ListWorkloadsRequest - 51, // 76: persys.control.v1.AgentControl.GetWorkload:input_type -> persys.control.v1.GetWorkloadRequest - 55, // 77: persys.control.v1.AgentControl.GetClusterSummary:input_type -> persys.control.v1.GetClusterSummaryRequest - 57, // 78: persys.control.v1.AgentControl.ControlStream:input_type -> persys.control.v1.ControlMessage - 8, // 79: persys.control.v1.AgentControl.RegisterNode:output_type -> persys.control.v1.RegisterNodeResponse - 11, // 80: persys.control.v1.AgentControl.Heartbeat:output_type -> persys.control.v1.HeartbeatResponse - 13, // 81: persys.control.v1.AgentControl.ApplyWorkload:output_type -> persys.control.v1.ApplyWorkloadResponse - 15, // 82: persys.control.v1.AgentControl.DeleteWorkload:output_type -> persys.control.v1.DeleteWorkloadResponse - 31, // 83: persys.control.v1.AgentControl.RetryWorkload:output_type -> persys.control.v1.RetryWorkloadResponse - 33, // 84: persys.control.v1.AgentControl.DrainNode:output_type -> persys.control.v1.DrainNodeResponse - 35, // 85: persys.control.v1.AgentControl.UndrainNode:output_type -> persys.control.v1.UndrainNodeResponse - 38, // 86: persys.control.v1.AgentControl.TaintNode:output_type -> persys.control.v1.TaintNodeResponse - 40, // 87: persys.control.v1.AgentControl.UntaintNode:output_type -> persys.control.v1.UntaintNodeResponse - 42, // 88: persys.control.v1.AgentControl.SetNodeLabel:output_type -> persys.control.v1.SetNodeLabelResponse - 44, // 89: persys.control.v1.AgentControl.DeleteNodeLabel:output_type -> persys.control.v1.DeleteNodeLabelResponse - 4, // 90: persys.control.v1.AgentControl.SubmitAutomationSuggestion:output_type -> persys.control.v1.SubmitAutomationSuggestionResponse - 47, // 91: persys.control.v1.AgentControl.ListNodes:output_type -> persys.control.v1.ListNodesResponse - 48, // 92: persys.control.v1.AgentControl.GetNode:output_type -> persys.control.v1.GetNodeResponse - 52, // 93: persys.control.v1.AgentControl.ListWorkloads:output_type -> persys.control.v1.ListWorkloadsResponse - 53, // 94: persys.control.v1.AgentControl.GetWorkload:output_type -> persys.control.v1.GetWorkloadResponse - 56, // 95: persys.control.v1.AgentControl.GetClusterSummary:output_type -> persys.control.v1.GetClusterSummaryResponse - 57, // 96: persys.control.v1.AgentControl.ControlStream:output_type -> persys.control.v1.ControlMessage - 79, // [79:97] is the sub-list for method output_type - 61, // [61:79] is the sub-list for method input_type - 61, // [61:61] is the sub-list for extension type_name - 61, // [61:61] is the sub-list for extension extendee - 0, // [0:61] is the sub-list for field type_name + 63, // 56: persys.control.v1.WorkloadView.created_at:type_name -> google.protobuf.Timestamp + 63, // 57: persys.control.v1.GetClusterSummaryResponse.generated_at:type_name -> google.protobuf.Timestamp + 5, // 58: persys.control.v1.ControlMessage.register:type_name -> persys.control.v1.RegisterNodeRequest + 9, // 59: persys.control.v1.ControlMessage.heartbeat:type_name -> persys.control.v1.HeartbeatRequest + 12, // 60: persys.control.v1.ControlMessage.apply:type_name -> persys.control.v1.ApplyWorkloadRequest + 14, // 61: persys.control.v1.ControlMessage.delete:type_name -> persys.control.v1.DeleteWorkloadRequest + 5, // 62: persys.control.v1.AgentControl.RegisterNode:input_type -> persys.control.v1.RegisterNodeRequest + 9, // 63: persys.control.v1.AgentControl.Heartbeat:input_type -> persys.control.v1.HeartbeatRequest + 12, // 64: persys.control.v1.AgentControl.ApplyWorkload:input_type -> persys.control.v1.ApplyWorkloadRequest + 14, // 65: persys.control.v1.AgentControl.DeleteWorkload:input_type -> persys.control.v1.DeleteWorkloadRequest + 30, // 66: persys.control.v1.AgentControl.RetryWorkload:input_type -> persys.control.v1.RetryWorkloadRequest + 32, // 67: persys.control.v1.AgentControl.DrainNode:input_type -> persys.control.v1.DrainNodeRequest + 34, // 68: persys.control.v1.AgentControl.UndrainNode:input_type -> persys.control.v1.UndrainNodeRequest + 37, // 69: persys.control.v1.AgentControl.TaintNode:input_type -> persys.control.v1.TaintNodeRequest + 39, // 70: persys.control.v1.AgentControl.UntaintNode:input_type -> persys.control.v1.UntaintNodeRequest + 41, // 71: persys.control.v1.AgentControl.SetNodeLabel:input_type -> persys.control.v1.SetNodeLabelRequest + 43, // 72: persys.control.v1.AgentControl.DeleteNodeLabel:input_type -> persys.control.v1.DeleteNodeLabelRequest + 3, // 73: persys.control.v1.AgentControl.SubmitAutomationSuggestion:input_type -> persys.control.v1.SubmitAutomationSuggestionRequest + 45, // 74: persys.control.v1.AgentControl.ListNodes:input_type -> persys.control.v1.ListNodesRequest + 46, // 75: persys.control.v1.AgentControl.GetNode:input_type -> persys.control.v1.GetNodeRequest + 50, // 76: persys.control.v1.AgentControl.ListWorkloads:input_type -> persys.control.v1.ListWorkloadsRequest + 51, // 77: persys.control.v1.AgentControl.GetWorkload:input_type -> persys.control.v1.GetWorkloadRequest + 55, // 78: persys.control.v1.AgentControl.GetClusterSummary:input_type -> persys.control.v1.GetClusterSummaryRequest + 57, // 79: persys.control.v1.AgentControl.ControlStream:input_type -> persys.control.v1.ControlMessage + 8, // 80: persys.control.v1.AgentControl.RegisterNode:output_type -> persys.control.v1.RegisterNodeResponse + 11, // 81: persys.control.v1.AgentControl.Heartbeat:output_type -> persys.control.v1.HeartbeatResponse + 13, // 82: persys.control.v1.AgentControl.ApplyWorkload:output_type -> persys.control.v1.ApplyWorkloadResponse + 15, // 83: persys.control.v1.AgentControl.DeleteWorkload:output_type -> persys.control.v1.DeleteWorkloadResponse + 31, // 84: persys.control.v1.AgentControl.RetryWorkload:output_type -> persys.control.v1.RetryWorkloadResponse + 33, // 85: persys.control.v1.AgentControl.DrainNode:output_type -> persys.control.v1.DrainNodeResponse + 35, // 86: persys.control.v1.AgentControl.UndrainNode:output_type -> persys.control.v1.UndrainNodeResponse + 38, // 87: persys.control.v1.AgentControl.TaintNode:output_type -> persys.control.v1.TaintNodeResponse + 40, // 88: persys.control.v1.AgentControl.UntaintNode:output_type -> persys.control.v1.UntaintNodeResponse + 42, // 89: persys.control.v1.AgentControl.SetNodeLabel:output_type -> persys.control.v1.SetNodeLabelResponse + 44, // 90: persys.control.v1.AgentControl.DeleteNodeLabel:output_type -> persys.control.v1.DeleteNodeLabelResponse + 4, // 91: persys.control.v1.AgentControl.SubmitAutomationSuggestion:output_type -> persys.control.v1.SubmitAutomationSuggestionResponse + 47, // 92: persys.control.v1.AgentControl.ListNodes:output_type -> persys.control.v1.ListNodesResponse + 48, // 93: persys.control.v1.AgentControl.GetNode:output_type -> persys.control.v1.GetNodeResponse + 52, // 94: persys.control.v1.AgentControl.ListWorkloads:output_type -> persys.control.v1.ListWorkloadsResponse + 53, // 95: persys.control.v1.AgentControl.GetWorkload:output_type -> persys.control.v1.GetWorkloadResponse + 56, // 96: persys.control.v1.AgentControl.GetClusterSummary:output_type -> persys.control.v1.GetClusterSummaryResponse + 57, // 97: persys.control.v1.AgentControl.ControlStream:output_type -> persys.control.v1.ControlMessage + 80, // [80:98] is the sub-list for method output_type + 62, // [62:80] is the sub-list for method input_type + 62, // [62:62] is the sub-list for extension type_name + 62, // [62:62] is the sub-list for extension extendee + 0, // [0:62] is the sub-list for field type_name } func init() { file_control_proto_init() } diff --git a/pkg/scheduler/controlv1/control_grpc.pb.go b/pkg/scheduler/controlv1/control_grpc.pb.go index b0a2355..4a70e36 100644 --- a/pkg/scheduler/controlv1/control_grpc.pb.go +++ b/pkg/scheduler/controlv1/control_grpc.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: -// - protoc-gen-go-grpc v1.6.2 +// - protoc-gen-go-grpc v1.6.1 // - protoc v3.21.12 // source: control.proto From 43ad60d1858db17d579246ae21028f4905a522a5 Mon Sep 17 00:00:00 2001 From: milx Date: Mon, 6 Jul 2026 20:31:32 +0330 Subject: [PATCH 02/18] Update: Use Global pkg/certmanager for automatic cert management --- persys-forgery/cmd/main.go | 28 ++++++- persys-forgery/go.mod | 33 ++++---- persys-forgery/go.sum | 86 ++++++++++---------- persys-forgery/internal/certmanager/vault.go | 12 +-- persys-forgery/utils/config.go | 14 ++-- 5 files changed, 94 insertions(+), 79 deletions(-) diff --git a/persys-forgery/cmd/main.go b/persys-forgery/cmd/main.go index 3d8e987..223a2b5 100644 --- a/persys-forgery/cmd/main.go +++ b/persys-forgery/cmd/main.go @@ -16,7 +16,7 @@ import ( "time" "github.com/persys-dev/persys-cloud/persys-forgery/internal/build" - "github.com/persys-dev/persys-cloud/persys-forgery/internal/certmanager" + "github.com/persys-dev/persys-cloud/pkg/certmanager" "github.com/persys-dev/persys-cloud/persys-forgery/internal/db" forgeryv1 "github.com/persys-dev/persys-cloud/persys-forgery/internal/forgeryv1" "github.com/persys-dev/persys-cloud/persys-forgery/internal/grpcapi" @@ -63,8 +63,30 @@ func main() { go queue.StartRedisWorker(cfg, orchestrator) go queue.StartWebhookWorker(cfg) - certMgr, err := certmanager.NewFromConfig(cfg, logrus.New()) - if err != nil { + certcfg := certmanager.Config{ + TLSEnabled: cfg.TLS.Enabled, + + TLSCertPath: cfg.TLS.CertPath, + TLSKeyPath: cfg.TLS.KeyPath, + TLSCAPath: cfg.TLS.CAPath, + + VaultEnabled: cfg.Vault.Enabled, + VaultManagerAddr: cfg.Vault.ManagerAddr, + VaultAddr: cfg.Vault.Addr, + VaultAuthMethod: cfg.Vault.AuthMethod, + VaultToken: cfg.Vault.Token, + VaultAppRoleID: cfg.Vault.AppRoleID, + VaultAppSecretID: cfg.Vault.AppSecretID, + VaultPKIMount: cfg.Vault.PKIMount, + VaultPKIRole: cfg.Vault.PKIRole, + VaultCertTTL: cfg.Vault.CertTTL, + VaultServiceName: cfg.Vault.ServiceName, + VaultServiceDomain: cfg.Vault.ServiceDomain, + VaultRetryInterval: cfg.Vault.RetryInterval, + } + + certMgr := certmanager.NewManager(certcfg, logrus.New()) + if certMgr == nil { log.Fatalf("failed to initialize cert manager: %v", err) } if err := certMgr.Start(ctx); err != nil { diff --git a/persys-forgery/go.mod b/persys-forgery/go.mod index 36a5c49..6fc7aa0 100644 --- a/persys-forgery/go.mod +++ b/persys-forgery/go.mod @@ -1,19 +1,20 @@ module github.com/persys-dev/persys-cloud/persys-forgery -go 1.24.2 +go 1.24.13 require ( github.com/docker/docker v28.3.2+incompatible github.com/gin-gonic/gin v1.10.1 github.com/hashicorp/vault/api v1.22.0 + github.com/persys-dev/persys-cloud/pkg v0.0.0-20260701205454-9cb94822d71f github.com/redis/go-redis/v9 v9.11.0 - github.com/sirupsen/logrus v1.9.3 - go.opentelemetry.io/otel v1.37.0 + github.com/sirupsen/logrus v1.9.4 + go.opentelemetry.io/otel v1.39.0 go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.37.0 - go.opentelemetry.io/otel/sdk v1.37.0 - go.opentelemetry.io/otel/trace v1.37.0 - google.golang.org/grpc v1.73.0 - google.golang.org/protobuf v1.36.6 + go.opentelemetry.io/otel/sdk v1.39.0 + go.opentelemetry.io/otel/trace v1.39.0 + google.golang.org/grpc v1.79.1 + google.golang.org/protobuf v1.36.11 gopkg.in/yaml.v3 v3.0.1 gorm.io/driver/mysql v1.6.0 gorm.io/driver/sqlite v1.6.0 @@ -39,7 +40,7 @@ require ( github.com/felixge/httpsnoop v1.0.4 // indirect github.com/gabriel-vasile/mimetype v1.4.9 // indirect github.com/gin-contrib/sse v1.1.0 // indirect - github.com/go-jose/go-jose/v4 v4.1.1 // indirect + github.com/go-jose/go-jose/v4 v4.1.3 // indirect github.com/go-logr/logr v1.4.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-playground/locales v0.14.1 // indirect @@ -81,18 +82,18 @@ require ( github.com/ryanuber/go-glob v1.0.0 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/ugorji/go/codec v1.3.0 // indirect - go.opentelemetry.io/auto/sdk v1.1.0 // indirect + go.opentelemetry.io/auto/sdk v1.2.1 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.62.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.37.0 // indirect - go.opentelemetry.io/otel/metric v1.37.0 // indirect + go.opentelemetry.io/otel/metric v1.39.0 // indirect go.opentelemetry.io/proto/otlp v1.7.0 // indirect golang.org/x/arch v0.18.0 // indirect - golang.org/x/crypto v0.40.0 // indirect - golang.org/x/net v0.42.0 // indirect - golang.org/x/sys v0.34.0 // indirect - golang.org/x/text v0.27.0 // indirect + golang.org/x/crypto v0.46.0 // indirect + golang.org/x/net v0.48.0 // indirect + golang.org/x/sys v0.39.0 // indirect + golang.org/x/text v0.32.0 // indirect golang.org/x/time v0.12.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 // indirect gotest.tools/v3 v3.5.2 // indirect ) diff --git a/persys-forgery/go.sum b/persys-forgery/go.sum index 9391019..3ad769d 100644 --- a/persys-forgery/go.sum +++ b/persys-forgery/go.sum @@ -51,8 +51,8 @@ github.com/gin-contrib/sse v1.1.0 h1:n0w2GMuUpWDVp7qSpvze6fAu9iRxJY4Hmj6AmBOU05w github.com/gin-contrib/sse v1.1.0/go.mod h1:hxRZ5gVpWMT7Z0B0gSNYqqsSCNIJMjzvm6fqCz9vjwM= github.com/gin-gonic/gin v1.10.1 h1:T0ujvqyCSqRopADpgPgiTT63DUQVSfojyME59Ei63pQ= github.com/gin-gonic/gin v1.10.1/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y= -github.com/go-jose/go-jose/v4 v4.1.1 h1:JYhSgy4mXXzAdF3nUx3ygx347LRXJRrpgyU3adRmkAI= -github.com/go-jose/go-jose/v4 v4.1.1/go.mod h1:BdsZGqgdO3b6tTc6LSE56wcDbMMLuPsw5d4ZD5f94kA= +github.com/go-jose/go-jose/v4 v4.1.3 h1:CVLmWDhDVRa6Mi/IgCgaopNosCaHz7zrMeF9MlZRkrs= +github.com/go-jose/go-jose/v4 v4.1.3/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= @@ -78,10 +78,6 @@ github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= -github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY= -github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= -github.com/google/go-querystring v1.1.0 h1:F5BGlho2WTbPXY4G8xysM4OWSgFs5lRNU6HfsUEsGdc= -github.com/google/go-querystring v1.1.0/go.mod h1:RNUa4/1jA6PqHWo8BfRYYVvMdrM5fdanYoon2ouLSgA= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -160,6 +156,8 @@ github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJw github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M= github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= +github.com/persys-dev/persys-cloud/pkg v0.0.0-20260701205454-9cb94822d71f h1:lKC6ntuESIn5yp2GcWQwyE+vMCh+lges3gbjF/Zxk3A= +github.com/persys-dev/persys-cloud/pkg v0.0.0-20260701205454-9cb94822d71f/go.mod h1:BKpHun2lgyknFnBmitTCxZ9pNXiF91HO2Kd2WDJAH8w= 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= @@ -167,13 +165,13 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/redis/go-redis/v9 v9.11.0 h1:E3S08Gl/nJNn5vkxd2i78wZxWAPNZgUNTp8WIJUAiIs= github.com/redis/go-redis/v9 v9.11.0/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw= -github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= -github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= +github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= +github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk= github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= 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/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w= +github.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC42RjbV2g= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= @@ -184,52 +182,51 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= -github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= github.com/ugorji/go/codec v1.3.0 h1:Qd2W2sQawAfG8XSvzwhBeoGq71zXOC/Q1E9y/wUcsUA= github.com/ugorji/go/codec v1.3.0/go.mod h1:pRBVtBSKl77K30Bv8R2P+cLSGaTtex6fsA2Wjqmfxj4= 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/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= -go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= +go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= +go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.62.0 h1:Hf9xI/XLML9ElpiHVDNwvqI0hIFlzV8dgIr35kV1kRU= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.62.0/go.mod h1:NfchwuyNoMcZ5MLHwPrODwUF1HWCXWrL31s8gSAdIKY= -go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ= -go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I= +go.opentelemetry.io/otel v1.39.0 h1:8yPrr/S0ND9QEfTfdP9V+SiwT4E0G7Y5MO7p85nis48= +go.opentelemetry.io/otel v1.39.0/go.mod h1:kLlFTywNWrFyEdH0oj2xK0bFYZtHRYUdv1NklR/tgc8= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.37.0 h1:Ahq7pZmv87yiyn3jeFz/LekZmPLLdKejuO3NcK9MssM= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.37.0/go.mod h1:MJTqhM0im3mRLw1i8uGHnCvUEeS7VwRyxlLC78PA18M= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.37.0 h1:bDMKF3RUSxshZ5OjOTi8rsHGaPKsAt76FaqgvIUySLc= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.37.0/go.mod h1:dDT67G/IkA46Mr2l9Uj7HsQVwsjASyV9SjGofsiUZDA= -go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE= -go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E= -go.opentelemetry.io/otel/sdk v1.37.0 h1:ItB0QUqnjesGRvNcmAcU0LyvkVyGJ2xftD29bWdDvKI= -go.opentelemetry.io/otel/sdk v1.37.0/go.mod h1:VredYzxUvuo2q3WRcDnKDjbdvmO0sCzOvVAiY+yUkAg= -go.opentelemetry.io/otel/sdk/metric v1.37.0 h1:90lI228XrB9jCMuSdA0673aubgRobVZFhbjxHHspCPc= -go.opentelemetry.io/otel/sdk/metric v1.37.0/go.mod h1:cNen4ZWfiD37l5NhS+Keb5RXVWZWpRE+9WyVCpbo5ps= -go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4= -go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0= +go.opentelemetry.io/otel/metric v1.39.0 h1:d1UzonvEZriVfpNKEVmHXbdf909uGTOQjA0HF0Ls5Q0= +go.opentelemetry.io/otel/metric v1.39.0/go.mod h1:jrZSWL33sD7bBxg1xjrqyDjnuzTUB0x1nBERXd7Ftcs= +go.opentelemetry.io/otel/sdk v1.39.0 h1:nMLYcjVsvdui1B/4FRkwjzoRVsMK8uL/cj0OyhKzt18= +go.opentelemetry.io/otel/sdk v1.39.0/go.mod h1:vDojkC4/jsTJsE+kh+LXYQlbL8CgrEcwmt1ENZszdJE= +go.opentelemetry.io/otel/sdk/metric v1.39.0 h1:cXMVVFVgsIf2YL6QkRF4Urbr/aMInf+2WKg+sEJTtB8= +go.opentelemetry.io/otel/sdk/metric v1.39.0/go.mod h1:xq9HEVH7qeX69/JnwEfp6fVq5wosJsY1mt4lLfYdVew= +go.opentelemetry.io/otel/trace v1.39.0 h1:2d2vfpEDmCJ5zVYz7ijaJdOF59xLomrvj7bjt6/qCJI= +go.opentelemetry.io/otel/trace v1.39.0/go.mod h1:88w4/PnZSazkGzz/w84VHpQafiU4EtqqlVdxWy+rNOA= go.opentelemetry.io/proto/otlp v1.7.0 h1:jX1VolD6nHuFzOYso2E73H85i92Mv8JQYk0K9vz09os= go.opentelemetry.io/proto/otlp v1.7.0/go.mod h1:fSKjH6YJ7HDlwzltzyMj036AJ3ejJLCgCSHGj4efDDo= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= golang.org/x/arch v0.18.0 h1:WN9poc33zL4AzGxqf8VtpKUnGvMi8O9lhNyBMF/85qc= golang.org/x/arch v0.18.0/go.mod h1:bdwinDaKcfZUGpH09BB7ZmOfhalA8lQdzl62l8gGWsk= 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/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM= -golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY= +golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU= +golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0= 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.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs= -golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8= -golang.org/x/oauth2 v0.27.0 h1:da9Vo7/tDv5RH/7nZDz1eMGS/q1Vv1N/7FCrBhI9I3M= -golang.org/x/oauth2 v0.27.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= -golang.org/x/oauth2 v0.28.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= +golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU= +golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY= 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= @@ -238,14 +235,13 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h 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.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA= -golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk= +golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= 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.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4= -golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU= +golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU= +golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY= golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE= golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -256,14 +252,16 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T 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-20250603155806-513f23925822 h1:oWVWY3NzT7KJppx2UKhKmzPq4SRe0LdCijVRwvGeikY= -google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822/go.mod h1:h3c4v36UTKzUiuaOKQ6gr3S+0hovBtUrXzTG/i3+XEc= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 h1:fc6jSaCT0vBduLYZHYrBBNY4dsWuvgyff9noRNDdBeE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= -google.golang.org/grpc v1.73.0 h1:VIWSmpI2MegBtTuFt5/JWy2oXxtjJ/e89Z70ImfD2ok= -google.golang.org/grpc v1.73.0/go.mod h1:50sbHOUqWoCQGI8V2HQLJM0B+LMlIUjNSZmow7EVBQc= -google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= -google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= +gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= +gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= +google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217 h1:fCvbg86sFXwdrl5LgVcTEvNC+2txB5mgROGmRL5mrls= +google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217/go.mod h1:+rXWjjaukWZun3mLfjmVnQi18E1AsFbDN9QdJ5YXLto= +google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 h1:gRkg/vSppuSQoDjxyiGfN4Upv/h/DQmIR10ZU8dh4Ww= +google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk= +google.golang.org/grpc v1.79.1 h1:zGhSi45ODB9/p3VAawt9a+O/MULLl9dpizzNNpq7flY= +google.golang.org/grpc v1.79.1/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ= +google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= +google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/persys-forgery/internal/certmanager/vault.go b/persys-forgery/internal/certmanager/vault.go index 0eeee87..d0f40ec 100644 --- a/persys-forgery/internal/certmanager/vault.go +++ b/persys-forgery/internal/certmanager/vault.go @@ -69,14 +69,6 @@ func NewManager(cfg Config, logger *logrus.Logger) *Manager { } func NewFromConfig(cfg *utils.Config, logger *logrus.Logger) (*Manager, error) { - certTTL, err := time.ParseDuration(cfg.Vault.CertTTL) - if err != nil { - return nil, fmt.Errorf("invalid vault.cert_ttl: %w", err) - } - retryInterval, err := time.ParseDuration(cfg.Vault.RetryInterval) - if err != nil { - return nil, fmt.Errorf("invalid vault.retry_interval: %w", err) - } return NewManager(Config{ TLSEnabled: cfg.TLS.Enabled, @@ -91,10 +83,10 @@ func NewFromConfig(cfg *utils.Config, logger *logrus.Logger) (*Manager, error) { VaultAppSecretID: cfg.Vault.AppSecretID, VaultPKIMount: cfg.Vault.PKIMount, VaultPKIRole: cfg.Vault.PKIRole, - VaultCertTTL: certTTL, + VaultCertTTL: cfg.Vault.CertTTL, VaultServiceName: cfg.Vault.ServiceName, VaultServiceDomain: cfg.Vault.ServiceDomain, - VaultRetryInterval: retryInterval, + VaultRetryInterval: cfg.Vault.RetryInterval, BindHost: cfg.Vault.BindHost, }, logger), nil } diff --git a/persys-forgery/utils/config.go b/persys-forgery/utils/config.go index 79c0abf..fdd2028 100644 --- a/persys-forgery/utils/config.go +++ b/persys-forgery/utils/config.go @@ -3,6 +3,7 @@ package utils import ( "os" "strings" + "time" "gopkg.in/yaml.v3" ) @@ -35,14 +36,15 @@ type TLSConfig struct { type VaultConfig struct { Enabled bool `yaml:"enabled"` Addr string `yaml:"addr"` + ManagerAddr string `yaml:"manager_addr"` AuthMethod string `yaml:"auth_method"` Token string `yaml:"token"` AppRoleID string `yaml:"approle_id"` AppSecretID string `yaml:"approle_secret_id"` PKIMount string `yaml:"pki_mount"` PKIRole string `yaml:"pki_role"` - CertTTL string `yaml:"cert_ttl"` - RetryInterval string `yaml:"retry_interval"` + CertTTL time.Duration `yaml:"cert_ttl"` + RetryInterval time.Duration `yaml:"retry_interval"` ServiceName string `yaml:"service_name"` ServiceDomain string `yaml:"service_domain"` BindHost string `yaml:"bind_host"` @@ -97,11 +99,11 @@ func (c *Config) applyDefaults() { if c.Vault.AuthMethod == "" { c.Vault.AuthMethod = "token" } - if c.Vault.CertTTL == "" { - c.Vault.CertTTL = "24h" + if c.Vault.CertTTL == 0 { + c.Vault.CertTTL = 24 * time.Hour } - if c.Vault.RetryInterval == "" { - c.Vault.RetryInterval = "30s" + if c.Vault.RetryInterval == 0 { + c.Vault.RetryInterval = 30 * time.Second } if c.Vault.ServiceName == "" { c.Vault.ServiceName = "persys-forgery" From 51b9243eb71db276cc631022123629511e279e66 Mon Sep 17 00:00:00 2001 From: milx Date: Mon, 6 Jul 2026 20:32:05 +0330 Subject: [PATCH 03/18] Add: alloy config --- infra/docker/alloy/alloy-config.alloy | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 infra/docker/alloy/alloy-config.alloy diff --git a/infra/docker/alloy/alloy-config.alloy b/infra/docker/alloy/alloy-config.alloy new file mode 100644 index 0000000..5d6211b --- /dev/null +++ b/infra/docker/alloy/alloy-config.alloy @@ -0,0 +1,14 @@ +pyroscope.scrape "persys_cloud" { + targets = [ + {"__address__" = "persys-scheduler:8084", "service_name" = "persys-cloud.persys-scheduler"}, + {"__address__" = "compute-agent:8089", "service_name" = "persys-cloud.compute-agent"}, + {"__address__" = "persys-gateway:6060", "service_name" = "persys-cloud.persys-gateway"}, + ] + forward_to = [pyroscope.write.local.receiver] +} + +pyroscope.write "local" { + endpoint { + url = "http://pyroscope:4040" + } +} \ No newline at end of file From d9181818f377cca521b8bc31b85f06126903c3ee Mon Sep 17 00:00:00 2001 From: milx Date: Mon, 6 Jul 2026 20:34:53 +0330 Subject: [PATCH 04/18] Feat: Wire Automation + Intelligence Routes / Add pprof / use global pkg/certmanager for auto cert management --- persys-gateway/cmd/main.go | 99 +++++++++++--- persys-gateway/config/config.go | 55 +++++++- .../controllers/automation.controller.go | 113 ++++++++++++++++ persys-gateway/internal/certmanager/vault.go | 10 +- persys-gateway/routes/automation.routes.go | 29 ++++ persys-gateway/routes/intelligence.routes.go | 65 +++++++++ persys-gateway/services/automation.service.go | 124 ++++++++++++++++++ persys-gateway/utils/proxy.go | 89 +++++++++++++ 8 files changed, 549 insertions(+), 35 deletions(-) create mode 100644 persys-gateway/controllers/automation.controller.go create mode 100644 persys-gateway/routes/automation.routes.go create mode 100644 persys-gateway/routes/intelligence.routes.go create mode 100644 persys-gateway/services/automation.service.go create mode 100644 persys-gateway/utils/proxy.go diff --git a/persys-gateway/cmd/main.go b/persys-gateway/cmd/main.go index 6930a96..ca82671 100755 --- a/persys-gateway/cmd/main.go +++ b/persys-gateway/cmd/main.go @@ -7,6 +7,7 @@ import ( "fmt" "log" "net/http" + "net/http/pprof" "os" "os/signal" "syscall" @@ -16,7 +17,7 @@ import ( "github.com/gin-gonic/gin" "github.com/persys-dev/persys-cloud/persys-gateway/config" "github.com/persys-dev/persys-cloud/persys-gateway/controllers" - "github.com/persys-dev/persys-cloud/persys-gateway/internal/certmanager" + "github.com/persys-dev/persys-cloud/pkg/certmanager" "github.com/persys-dev/persys-cloud/persys-gateway/internal/middleware" "github.com/persys-dev/persys-cloud/persys-gateway/routes" "github.com/persys-dev/persys-cloud/persys-gateway/services" @@ -36,21 +37,23 @@ import ( ) type App struct { - server *gin.Engine - authCollection *mongo.Collection - sessionCollection *mongo.Collection - clusterCollection *mongo.Collection - githubCollection *mongo.Collection - prowCollection *mongo.Collection - webhookCollection *mongo.Collection - authService services.AuthService - githubService services.GithubService - prowService *services.ProwService - webhookService services.WebhookService - authController controllers.AuthController - githubController controllers.GithubController - prowController *controllers.ProwController - webhookController *controllers.WebhookController + server *gin.Engine + authCollection *mongo.Collection + sessionCollection *mongo.Collection + clusterCollection *mongo.Collection + githubCollection *mongo.Collection + prowCollection *mongo.Collection + webhookCollection *mongo.Collection + authService services.AuthService + githubService services.GithubService + prowService *services.ProwService + webhookService services.WebhookService + automationService *services.AutomationService + authController controllers.AuthController + githubController controllers.GithubController + prowController *controllers.ProwController + webhookController *controllers.WebhookController + automationController *controllers.AutomationController } func setupTracer(endpoint string, serviceName string) func() { @@ -93,7 +96,29 @@ func main() { log.Printf("bootstrapping %s", cnf.ServiceName) - vaultCertManager, err := certmanager.NewFromConfig(cnf, logrus.New()) + certcnf := certmanager.Config{ + TLSEnabled: cnf.TLS.Enabled, + + TLSCertPath: cnf.TLS.CertPath, + TLSKeyPath: cnf.TLS.KeyPath, + TLSCAPath: cnf.TLS.CAPath, + + VaultEnabled: cnf.Vault.Enabled, + VaultManagerAddr: cnf.Vault.ManagerAddr, + VaultAddr: cnf.Vault.Addr, + VaultAuthMethod: cnf.Vault.AuthMethod, + VaultToken: cnf.Vault.Token, + VaultAppRoleID: cnf.Vault.AppRoleID, + VaultAppSecretID: cnf.Vault.AppSecretID, + VaultPKIMount: cnf.Vault.PKIMount, + VaultPKIRole: cnf.Vault.PKIRole, + VaultCertTTL: cnf.Vault.CertTTL, + VaultServiceName: cnf.Vault.ServiceName, + VaultServiceDomain: cnf.Vault.ServiceDomain, + VaultRetryInterval: cnf.Vault.RetryInterval, + } + + vaultCertManager := certmanager.NewManager(certcnf, logrus.New()) if err != nil { log.Fatalf("failed to initialize vault cert manager: %v", err) } @@ -133,10 +158,16 @@ func main() { } app.webhookService.Start(ctx) + app.automationService, err = services.NewAutomationService(cnf, webhookTLS) + if err != nil { + log.Fatalf("failed to initialize automation service: %v", err) + } + app.authController = controllers.NewAuthController(app.authService, ctx, app.githubService, app.authCollection, app.sessionCollection) app.githubController = controllers.NewGithubController(app.authService, ctx, app.githubService, app.githubCollection, cnf) app.prowController = controllers.NewProwController(app.prowService, app.authService, ctx) app.webhookController = controllers.NewWebhookController(app.webhookService) + app.automationController = controllers.NewAutomationController(app.automationService) corsConfig := cors.DefaultConfig() corsConfig.AllowOrigins = []string{"*"} @@ -170,11 +201,15 @@ func main() { githubRouteController := routes.NewGithubRouteController(app.githubController) prowRouteController := routes.NewProwRouteController(app.prowController) webhookRouteController := routes.NewWebhookRouteController(app.webhookController) + automationRouteController := routes.NewAutomationRouteController(app.automationController) + intelligenceRouteController := routes.NewIntelligenceRouteController(cnf) authRouteController.AuthRoute(mtlsGroup) githubRouteController.GithubRoute(mtlsGroup) prowRouteController.ProwRoute(mtlsGroup) webhookRouteController.WebhookRoute(nonMTLSGroup, cnf.Webhook.PublicPath) + automationRouteController.AutomationRoute(mtlsGroup) + intelligenceRouteController.IntelligenceRoute(mtlsGroup) caCert, err := os.ReadFile(cnf.TLS.CAPath) if err != nil { @@ -200,6 +235,27 @@ func main() { mtlsServer := &http.Server{Addr: cnf.App.HTTPAddr, Handler: mtlsRouter, TLSConfig: tlsConfig} nonMTLSServer := &http.Server{Addr: cnf.App.HTTPAddrPublic, Handler: nonMTLSRouter} + debugMux := http.NewServeMux() + debugMux.HandleFunc("/debug/pprof/", pprof.Index) + debugMux.HandleFunc("/debug/pprof/cmdline", pprof.Cmdline) + debugMux.HandleFunc("/debug/pprof/profile", pprof.Profile) + debugMux.HandleFunc("/debug/pprof/symbol", pprof.Symbol) + debugMux.HandleFunc("/debug/pprof/trace", pprof.Trace) + // goroutine, heap, allocs, block, mutex, threadcreate are served via pprof.Index + // through /debug/pprof/{profile-name} automatically once Index is registered + + debugServer := &http.Server{ + Addr: "0.0.0.0:6060", + Handler: debugMux, + } + + go func() { + log.Printf("starting debug/pprof server on %s", debugServer.Addr) + if err := debugServer.ListenAndServe(); err != nil && err != http.ErrServerClosed { + log.Printf("debug server failed: %v", err) + } + }() + go func() { log.Printf("starting mTLS server on %s", cnf.App.HTTPAddr) if err := mtlsServer.ListenAndServeTLS(cnf.TLS.CertPath, cnf.TLS.KeyPath); err != nil && err != http.ErrServerClosed { @@ -227,6 +283,9 @@ func main() { if err := nonMTLSServer.Shutdown(shutdownCtx); err != nil { log.Printf("public server shutdown failed: %v", err) } + if err := debugServer.Shutdown(shutdownCtx); err != nil { + log.Printf("debug server shutdown failed: %v", err) +} log.Println("servers exited gracefully") } @@ -242,12 +301,12 @@ func setupMongoDB(ctx context.Context, uri string) (*mongo.Client, error) { return client, nil } -func buildMTLSClientConfig(cfg *config.Config) (*tls.Config, error) { - cert, err := tls.LoadX509KeyPair(cfg.TLS.CertPath, cfg.TLS.KeyPath) +func buildMTLSClientConfig(cnf *config.Config) (*tls.Config, error) { + cert, err := tls.LoadX509KeyPair(cnf.TLS.CertPath, cnf.TLS.KeyPath) if err != nil { return nil, err } - caCert, err := os.ReadFile(cfg.TLS.CAPath) + caCert, err := os.ReadFile(cnf.TLS.CAPath) if err != nil { return nil, err } diff --git a/persys-gateway/config/config.go b/persys-gateway/config/config.go index 346c98e..d61b0cf 100755 --- a/persys-gateway/config/config.go +++ b/persys-gateway/config/config.go @@ -4,6 +4,7 @@ import ( "fmt" "os" "strings" + "time" "gopkg.in/yaml.v3" ) @@ -25,6 +26,8 @@ type Config struct { GitHub GitHubConfig `yaml:"github"` Webhook WebhookConfig `yaml:"webhook"` Forgery ForgeryConfig `yaml:"forgery"` + Automation AutomationConfig `yaml:"automation"` + Intelligence IntelligenceConfig `yaml:"intelligence"` Log LogConfig `yaml:"log"` Telemetry TelemetryConfig `yaml:"telemetry"` } @@ -54,6 +57,7 @@ type TLSConfig struct { type VaultConfig struct { Enabled bool `yaml:"enabled"` + ManagerAddr string `yaml:"manager_addr"` Addr string `yaml:"addr"` AuthMethod string `yaml:"auth_method"` Token string `yaml:"token"` @@ -61,8 +65,8 @@ type VaultConfig struct { AppSecretID string `yaml:"approle_secret_id"` PKIMount string `yaml:"pki_mount"` PKIRole string `yaml:"pki_role"` - CertTTL string `yaml:"cert_ttl"` - RetryInterval string `yaml:"retry_interval"` + CertTTL time.Duration `yaml:"cert_ttl"` + RetryInterval time.Duration `yaml:"retry_interval"` ServiceName string `yaml:"service_name"` ServiceDomain string `yaml:"service_domain"` BindHost string `yaml:"bind_host"` @@ -125,6 +129,17 @@ type ForgeryConfig struct { WebhookForwardURL string `yaml:"webhook_forward_url"` } +type AutomationConfig struct { + GRPCAddr string `yaml:"grpc_addr"` + GRPCServerName string `yaml:"grpc_server_name"` + RequestTimeout string `yaml:"request_timeout"` +} + +type IntelligenceConfig struct { + HTTPAddr string `yaml:"http_addr"` + RequestTimeout string `yaml:"request_timeout"` +} + type LogConfig struct { LokiEndpoint string `yaml:"loki_endpoint"` Level string `yaml:"level"` @@ -205,17 +220,35 @@ func (c *Config) applyDefaults() { if strings.TrimSpace(c.Forgery.GRPCServerName) == "" { c.Forgery.GRPCServerName = "persys-forgery.persys.local" } + if strings.TrimSpace(c.Automation.GRPCAddr) == "" { + c.Automation.GRPCAddr = "persys-automation:8091" + } + if strings.TrimSpace(c.Automation.GRPCServerName) == "" { + c.Automation.GRPCServerName = "persys-automation.persys.local" + } + if strings.TrimSpace(c.Automation.RequestTimeout) == "" { + c.Automation.RequestTimeout = "15s" + } + if strings.TrimSpace(c.Intelligence.HTTPAddr) == "" { + c.Intelligence.HTTPAddr = "http://persys-intelligence:8093" + } + if strings.TrimSpace(c.Intelligence.RequestTimeout) == "" { + c.Intelligence.RequestTimeout = "10s" + } if strings.TrimSpace(c.App.OAuthRedirectURL) == "" { - c.App.OAuthRedirectURL = "http://localhost:8585/auth" + c.App.OAuthRedirectURL = "http://persys-gateway:8585/auth" } if strings.TrimSpace(c.Vault.AuthMethod) == "" { c.Vault.AuthMethod = "approle" } - if strings.TrimSpace(c.Vault.CertTTL) == "" { - c.Vault.CertTTL = "24h" + if strings.TrimSpace(c.Vault.ManagerAddr) == "" { + c.Vault.ManagerAddr = "vault-manager:50069" } - if strings.TrimSpace(c.Vault.RetryInterval) == "" { - c.Vault.RetryInterval = "30s" + if c.Vault.CertTTL == time.Duration(0) { + c.Vault.CertTTL = 24 * time.Hour + } + if c.Vault.RetryInterval == time.Duration(0) { + c.Vault.RetryInterval = 30 * time.Second } if strings.TrimSpace(c.Vault.ServiceName) == "" { c.Vault.ServiceName = c.ServiceName @@ -281,6 +314,7 @@ func (c *Config) applyEnvOverrides() { // Vault c.Vault.Addr = envOrFile("PERSYS_GATEWAY_VAULT_ADDR", c.Vault.Addr) + c.Vault.ManagerAddr = envOrFile("PERSYS_VAULT_MANAGER_ADDR", c.Vault.ManagerAddr) c.Vault.AuthMethod = envOrFile("PERSYS_GATEWAY_VAULT_AUTH_METHOD", c.Vault.AuthMethod) c.Vault.Token = envOrFile("PERSYS_GATEWAY_VAULT_TOKEN", c.Vault.Token) c.Vault.AppRoleID = envOrFile("PERSYS_GATEWAY_VAULT_ROLE_ID", c.Vault.AppRoleID) @@ -295,6 +329,13 @@ func (c *Config) applyEnvOverrides() { c.Forgery.GRPCAddr = envOrFile("PERSYS_GATEWAY_FORGERY_GRPC_ADDR", c.Forgery.GRPCAddr) c.Forgery.GRPCServerName = envOrFile("PERSYS_GATEWAY_FORGERY_GRPC_SERVER_NAME", c.Forgery.GRPCServerName) + // Automation routing + c.Automation.GRPCAddr = envOrFile("PERSYS_GATEWAY_AUTOMATION_GRPC_ADDR", c.Automation.GRPCAddr) + c.Automation.GRPCServerName = envOrFile("PERSYS_GATEWAY_AUTOMATION_GRPC_SERVER_NAME", c.Automation.GRPCServerName) + + // Intelligence routing + c.Intelligence.HTTPAddr = envOrFile("PERSYS_GATEWAY_INTELLIGENCE_HTTP_ADDR", c.Intelligence.HTTPAddr) + // Telemetry c.Telemetry.OTLPEndpoint = envOrFile("PERSYS_GATEWAY_OTLP_ENDPOINT", c.Telemetry.OTLPEndpoint) if c.Telemetry.OTLPEndpoint == "" { diff --git a/persys-gateway/controllers/automation.controller.go b/persys-gateway/controllers/automation.controller.go new file mode 100644 index 0000000..0fa84d7 --- /dev/null +++ b/persys-gateway/controllers/automation.controller.go @@ -0,0 +1,113 @@ +package controllers + +import ( + "net/http" + "strconv" + + "github.com/gin-gonic/gin" + automationv1 "github.com/persys-dev/persys-cloud/pkg/automation/automationv1" + "github.com/persys-dev/persys-cloud/persys-gateway/services" +) + +type AutomationController struct { + automationService *services.AutomationService +} + +func NewAutomationController(automationService *services.AutomationService) *AutomationController { + return &AutomationController{automationService: automationService} +} + +func (c *AutomationController) writeProxyError(ctx *gin.Context, err error) { + ctx.JSON(http.StatusBadGateway, gin.H{"error": err.Error()}) +} + +func (c *AutomationController) CreatePolicyHandler() gin.HandlerFunc { + return func(ctx *gin.Context) { + req := &automationv1.CreatePolicyRequest{} + if !decodeProtoBody(ctx, req) { + return + } + resp, err := c.automationService.CreatePolicy(ctx.Request.Context(), req) + if err != nil { + c.writeProxyError(ctx, err) + return + } + writeProtoJSON(ctx, http.StatusOK, resp) + } +} + +func (c *AutomationController) ListPoliciesHandler() gin.HandlerFunc { + return func(ctx *gin.Context) { + req := &automationv1.ListPoliciesRequest{ + IncludeDisabled: ctx.Query("include_disabled") == "true", + } + resp, err := c.automationService.ListPolicies(ctx.Request.Context(), req) + if err != nil { + c.writeProxyError(ctx, err) + return + } + writeProtoJSON(ctx, http.StatusOK, resp) + } +} + +func (c *AutomationController) EnablePolicyHandler() gin.HandlerFunc { + return func(ctx *gin.Context) { + req := &automationv1.EnablePolicyRequest{PolicyId: ctx.Param("id")} + resp, err := c.automationService.EnablePolicy(ctx.Request.Context(), req) + if err != nil { + c.writeProxyError(ctx, err) + return + } + writeProtoJSON(ctx, http.StatusOK, resp) + } +} + +func (c *AutomationController) DisablePolicyHandler() gin.HandlerFunc { + return func(ctx *gin.Context) { + req := &automationv1.DisablePolicyRequest{PolicyId: ctx.Param("id")} + resp, err := c.automationService.DisablePolicy(ctx.Request.Context(), req) + if err != nil { + c.writeProxyError(ctx, err) + return + } + writeProtoJSON(ctx, http.StatusOK, resp) + } +} + +func (c *AutomationController) EvaluateNowHandler() gin.HandlerFunc { + return func(ctx *gin.Context) { + req := &automationv1.EvaluateNowRequest{PolicyId: ctx.Param("id")} + resp, err := c.automationService.EvaluateNow(ctx.Request.Context(), req) + if err != nil { + c.writeProxyError(ctx, err) + return + } + writeProtoJSON(ctx, http.StatusOK, resp) + } +} + +func (c *AutomationController) ListAuditLogHandler() gin.HandlerFunc { + return func(ctx *gin.Context) { + limit := uint32(100) + if v := ctx.Query("limit"); v != "" { + if parsed, err := parseUint32(v); err == nil { + limit = parsed + } + } + req := &automationv1.ListAuditLogRequest{Limit: limit} + resp, err := c.automationService.ListAuditLog(ctx.Request.Context(), req) + if err != nil { + c.writeProxyError(ctx, err) + return + } + writeProtoJSON(ctx, http.StatusOK, resp) + } +} + +func parseUint32(s string) (uint32, error) { + n, err := strconv.ParseUint(s, 10, 32) + if err != nil { + return 0, err + } + return uint32(n), nil +} diff --git a/persys-gateway/internal/certmanager/vault.go b/persys-gateway/internal/certmanager/vault.go index f1b75b1..4e1d6f2 100644 --- a/persys-gateway/internal/certmanager/vault.go +++ b/persys-gateway/internal/certmanager/vault.go @@ -69,14 +69,8 @@ func NewManager(cfg Config, logger *logrus.Logger) *Manager { } func NewFromConfig(cfg *config.Config, logger *logrus.Logger) (*Manager, error) { - certTTL, err := time.ParseDuration(cfg.Vault.CertTTL) - if err != nil { - return nil, fmt.Errorf("invalid vault.cert_ttl: %w", err) - } - retryInterval, err := time.ParseDuration(cfg.Vault.RetryInterval) - if err != nil { - return nil, fmt.Errorf("invalid vault.retry_interval: %w", err) - } + certTTL:= cfg.Vault.CertTTL + retryInterval := cfg.Vault.RetryInterval return NewManager(Config{ TLSEnabled: cfg.TLS.Enabled, diff --git a/persys-gateway/routes/automation.routes.go b/persys-gateway/routes/automation.routes.go new file mode 100644 index 0000000..351cfaf --- /dev/null +++ b/persys-gateway/routes/automation.routes.go @@ -0,0 +1,29 @@ +package routes + +import ( + "github.com/gin-gonic/gin" + "github.com/persys-dev/persys-cloud/persys-gateway/controllers" +) + +type AutomationRouteController struct { + automationController *controllers.AutomationController +} + +func NewAutomationRouteController(automationController *controllers.AutomationController) AutomationRouteController { + return AutomationRouteController{automationController: automationController} +} + +func (rc *AutomationRouteController) AutomationRoute(rg *gin.RouterGroup) { + automation := rg.Group("/automation") + { + policies := automation.Group("/policies") + { + policies.POST("", rc.automationController.CreatePolicyHandler()) + policies.GET("", rc.automationController.ListPoliciesHandler()) + policies.POST("/:id/enable", rc.automationController.EnablePolicyHandler()) + policies.POST("/:id/disable", rc.automationController.DisablePolicyHandler()) + policies.POST("/:id/evaluate", rc.automationController.EvaluateNowHandler()) + } + automation.GET("/audit-log", rc.automationController.ListAuditLogHandler()) + } +} diff --git a/persys-gateway/routes/intelligence.routes.go b/persys-gateway/routes/intelligence.routes.go new file mode 100644 index 0000000..2fe02f5 --- /dev/null +++ b/persys-gateway/routes/intelligence.routes.go @@ -0,0 +1,65 @@ +package routes + +import ( + "strings" + "time" + + "github.com/gin-gonic/gin" + "github.com/persys-dev/persys-cloud/persys-gateway/config" + "github.com/persys-dev/persys-cloud/persys-gateway/utils" +) + +type IntelligenceRouteController struct { + cfg *config.Config +} + +func NewIntelligenceRouteController(cfg *config.Config) IntelligenceRouteController { + return IntelligenceRouteController{cfg: cfg} +} + +func (rc *IntelligenceRouteController) IntelligenceRoute(rg *gin.RouterGroup) { + ai := rg.Group("/ai") + { + ai.POST("/query", rc.proxy("/ai/query")) + ai.POST("/internal/evaluate", rc.proxy("/internal/evaluate")) + ai.GET("/recommendations", rc.proxy("/recommendations")) + ai.GET("/recommendations/pending", rc.proxy("/recommendations/pending")) + ai.POST("/recommendations/:id/approve", rc.proxyDynamic()) + ai.POST("/recommendations/:id/reject", rc.proxyDynamic()) + ai.POST("/recommendations/:id/apply", rc.proxyDynamic()) + } +} + +func (rc *IntelligenceRouteController) timeout() time.Duration { + d, err := time.ParseDuration(rc.cfg.Intelligence.RequestTimeout) + if err != nil || d <= 0 { + return 10 * time.Second + } + return d +} + +// proxy forwards to a fixed upstream path on persys-intelligence. +func (rc *IntelligenceRouteController) proxy(path string) gin.HandlerFunc { + return func(c *gin.Context) { + target := rc.cfg.Intelligence.HTTPAddr + path + utils.ProxyRequest(c, target, &utils.ProxyOptions{ + Timeout: rc.timeout(), + Headers: map[string]string{"X-Forwarded-For": c.ClientIP()}, + }) + } +} + +// proxyDynamic forwards to persys-intelligence by stripping the gateway's +// "/ai" prefix from the inbound path (e.g. /ai/recommendations/:id/approve +// -> upstream /recommendations/:id/approve), since the upstream handler +// parses the id and action out of the URL itself. +func (rc *IntelligenceRouteController) proxyDynamic() gin.HandlerFunc { + return func(c *gin.Context) { + upstreamPath := strings.TrimPrefix(c.Request.URL.Path, "/ai") + target := rc.cfg.Intelligence.HTTPAddr + upstreamPath + utils.ProxyRequest(c, target, &utils.ProxyOptions{ + Timeout: rc.timeout(), + Headers: map[string]string{"X-Forwarded-For": c.ClientIP()}, + }) + } +} diff --git a/persys-gateway/services/automation.service.go b/persys-gateway/services/automation.service.go new file mode 100644 index 0000000..807b3e6 --- /dev/null +++ b/persys-gateway/services/automation.service.go @@ -0,0 +1,124 @@ +package services + +import ( + "context" + "crypto/tls" + "fmt" + "time" + + "github.com/persys-dev/persys-cloud/persys-gateway/config" + automationv1 "github.com/persys-dev/persys-cloud/pkg/automation/automationv1" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials" +) + +// AutomationService proxies gRPC calls from the gateway to persys-automation. +type AutomationService struct { + config *config.Config + clientTLS *tls.Config + timeout time.Duration +} + +// NewAutomationService builds an AutomationService, reusing the gateway's own +// mTLS client identity to dial persys-automation (same pattern as forgery). +func NewAutomationService(cfg *config.Config, clientTLS *tls.Config) (*AutomationService, error) { + timeout, err := time.ParseDuration(cfg.Automation.RequestTimeout) + if err != nil || timeout <= 0 { + timeout = 15 * time.Second + } + return &AutomationService{config: cfg, clientTLS: clientTLS, timeout: timeout}, nil +} + +func (s *AutomationService) CreatePolicy(ctx context.Context, req *automationv1.CreatePolicyRequest) (*automationv1.CreatePolicyResponse, error) { + resp, err := s.invoke(ctx, func(client automationv1.AutomationControlClient) (any, error) { + return client.CreatePolicy(ctx, req) + }) + if err != nil { + return nil, err + } + return resp.(*automationv1.CreatePolicyResponse), nil +} + +func (s *AutomationService) ListPolicies(ctx context.Context, req *automationv1.ListPoliciesRequest) (*automationv1.ListPoliciesResponse, error) { + resp, err := s.invoke(ctx, func(client automationv1.AutomationControlClient) (any, error) { + return client.ListPolicies(ctx, req) + }) + if err != nil { + return nil, err + } + return resp.(*automationv1.ListPoliciesResponse), nil +} + +func (s *AutomationService) EnablePolicy(ctx context.Context, req *automationv1.EnablePolicyRequest) (*automationv1.EnablePolicyResponse, error) { + resp, err := s.invoke(ctx, func(client automationv1.AutomationControlClient) (any, error) { + return client.EnablePolicy(ctx, req) + }) + if err != nil { + return nil, err + } + return resp.(*automationv1.EnablePolicyResponse), nil +} + +func (s *AutomationService) DisablePolicy(ctx context.Context, req *automationv1.DisablePolicyRequest) (*automationv1.DisablePolicyResponse, error) { + resp, err := s.invoke(ctx, func(client automationv1.AutomationControlClient) (any, error) { + return client.DisablePolicy(ctx, req) + }) + if err != nil { + return nil, err + } + return resp.(*automationv1.DisablePolicyResponse), nil +} + +func (s *AutomationService) EvaluateNow(ctx context.Context, req *automationv1.EvaluateNowRequest) (*automationv1.EvaluateNowResponse, error) { + resp, err := s.invoke(ctx, func(client automationv1.AutomationControlClient) (any, error) { + return client.EvaluateNow(ctx, req) + }) + if err != nil { + return nil, err + } + return resp.(*automationv1.EvaluateNowResponse), nil +} + +func (s *AutomationService) ListAuditLog(ctx context.Context, req *automationv1.ListAuditLogRequest) (*automationv1.ListAuditLogResponse, error) { + resp, err := s.invoke(ctx, func(client automationv1.AutomationControlClient) (any, error) { + return client.ListAuditLog(ctx, req) + }) + if err != nil { + return nil, err + } + return resp.(*automationv1.ListAuditLogResponse), nil +} + +func (s *AutomationService) invoke(ctx context.Context, call func(automationv1.AutomationControlClient) (any, error)) (any, error) { + if ctx == nil { + ctx = context.Background() + } + callCtx, cancel := context.WithTimeout(ctx, s.timeout) + defer cancel() + + var automationTLS *tls.Config + if s.clientTLS != nil { + automationTLS = s.clientTLS.Clone() + } else { + automationTLS = &tls.Config{} + } + if serverName := s.config.Automation.GRPCServerName; serverName != "" { + automationTLS.ServerName = serverName + } + + conn, err := grpc.DialContext(callCtx, s.config.Automation.GRPCAddr, + grpc.WithTransportCredentials(credentials.NewTLS(automationTLS)), + grpc.WithBlock(), + ) + if err != nil { + return nil, fmt.Errorf("dial automation %s: %w", s.config.Automation.GRPCAddr, err) + } + defer conn.Close() + + client := automationv1.NewAutomationControlClient(conn) + resp, err := call(client) + if err != nil { + return nil, err + } + return resp, nil +} diff --git a/persys-gateway/utils/proxy.go b/persys-gateway/utils/proxy.go new file mode 100644 index 0000000..7c082de --- /dev/null +++ b/persys-gateway/utils/proxy.go @@ -0,0 +1,89 @@ +package utils + +import ( + "bytes" + "crypto/tls" + "io" + "net/http" + "time" + + "github.com/gin-gonic/gin" +) + +// ProxyOptions configures an outbound proxied request made on behalf of an +// inbound gin request. +type ProxyOptions struct { + // Timeout bounds the outbound request. Defaults to 10s if zero. + Timeout time.Duration + // Headers are added to the outbound request (in addition to the + // forwarded inbound headers). + Headers map[string]string + // TLSConfig, if set, is used for the outbound HTTP client (e.g. mTLS). + // If nil, a plain HTTP client is used. + TLSConfig *tls.Config +} + +// ProxyRequest forwards the inbound gin request to target (a full URL), +// preserving method, query string, body, and most headers, and streams the +// upstream response (status, headers, body) back to the client. +func ProxyRequest(c *gin.Context, target string, opts *ProxyOptions) { + if opts == nil { + opts = &ProxyOptions{} + } + timeout := opts.Timeout + if timeout <= 0 { + timeout = 10 * time.Second + } + + var body io.Reader + if c.Request.Body != nil { + data, err := io.ReadAll(c.Request.Body) + if err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": "failed to read request body"}) + return + } + body = bytes.NewReader(data) + } + + req, err := http.NewRequestWithContext(c.Request.Context(), c.Request.Method, target, body) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to build upstream request"}) + return + } + req.URL.RawQuery = c.Request.URL.RawQuery + + for key, values := range c.Request.Header { + for _, v := range values { + req.Header.Add(key, v) + } + } + for k, v := range opts.Headers { + req.Header.Set(k, v) + } + + transport := &http.Transport{} + if opts.TLSConfig != nil { + transport.TLSClientConfig = opts.TLSConfig + } + client := &http.Client{Timeout: timeout, Transport: transport} + + resp, err := client.Do(req) + if err != nil { + c.JSON(http.StatusBadGateway, gin.H{"error": "upstream request failed: " + err.Error()}) + return + } + defer resp.Body.Close() + + respBody, err := io.ReadAll(resp.Body) + if err != nil { + c.JSON(http.StatusBadGateway, gin.H{"error": "failed to read upstream response"}) + return + } + + for key, values := range resp.Header { + for _, v := range values { + c.Writer.Header().Add(key, v) + } + } + c.Data(resp.StatusCode, resp.Header.Get("Content-Type"), respBody) +} From 7f557e0e962822474109398f7d075219a74483a3 Mon Sep 17 00:00:00 2001 From: milx Date: Mon, 6 Jul 2026 20:35:14 +0330 Subject: [PATCH 05/18] Update: persys-gateway modules --- persys-gateway/go.mod | 50 ++++++++++----------- persys-gateway/go.sum | 101 ++++++++++++++++++++---------------------- 2 files changed, 71 insertions(+), 80 deletions(-) diff --git a/persys-gateway/go.mod b/persys-gateway/go.mod index d6a8461..828d2d6 100755 --- a/persys-gateway/go.mod +++ b/persys-gateway/go.mod @@ -1,31 +1,29 @@ module github.com/persys-dev/persys-cloud/persys-gateway -go 1.23.0 - -toolchain go1.24.2 +go 1.24.13 require ( github.com/dgrijalva/jwt-go v3.2.0+incompatible github.com/gin-contrib/cors v1.5.0 github.com/gin-gonic/gin v1.9.1 - github.com/go-playground/webhooks/v6 v6.0.1 - github.com/golang/glog v1.2.4 + github.com/golang/glog v1.2.5 github.com/google/go-github v17.0.0+incompatible + github.com/google/uuid v1.6.0 github.com/hashicorp/vault/api v1.22.0 - github.com/sirupsen/logrus v1.9.3 - github.com/stretchr/testify v1.10.0 + github.com/persys-dev/persys-cloud/pkg v0.0.0-20260701205454-9cb94822d71f + github.com/sirupsen/logrus v1.9.4 + github.com/stretchr/testify v1.11.1 github.com/zsais/go-gin-prometheus v0.1.0 go.mongodb.org/mongo-driver v1.13.1 go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin v0.46.1 - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1 - go.opentelemetry.io/otel v1.36.0 + go.opentelemetry.io/otel v1.39.0 go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.36.0 - go.opentelemetry.io/otel/sdk v1.36.0 - go.opentelemetry.io/otel/trace v1.36.0 + go.opentelemetry.io/otel/sdk v1.39.0 + go.opentelemetry.io/otel/trace v1.39.0 go.uber.org/zap v1.21.0 - golang.org/x/oauth2 v0.27.0 - google.golang.org/grpc v1.72.1 - google.golang.org/protobuf v1.36.6 + golang.org/x/oauth2 v0.34.0 + google.golang.org/grpc v1.79.1 + google.golang.org/protobuf v1.36.11 gopkg.in/yaml.v3 v3.0.1 ) @@ -38,11 +36,10 @@ require ( github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect github.com/chenzhuoyu/iasm v0.9.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/felixge/httpsnoop v1.0.4 // indirect github.com/gabriel-vasile/mimetype v1.4.3 // indirect github.com/gin-contrib/sse v0.1.0 // indirect - github.com/go-jose/go-jose/v4 v4.1.1 // indirect - github.com/go-logr/logr v1.4.2 // indirect + github.com/go-jose/go-jose/v4 v4.1.3 // indirect + github.com/go-logr/logr v1.4.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect @@ -51,7 +48,6 @@ require ( github.com/golang/protobuf v1.5.4 // indirect github.com/golang/snappy v0.0.4 // indirect github.com/google/go-querystring v1.1.0 // indirect - github.com/google/uuid v1.6.0 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect @@ -87,19 +83,19 @@ require ( github.com/xdg-go/scram v1.1.2 // indirect github.com/xdg-go/stringprep v1.0.4 // indirect github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a // indirect - go.opentelemetry.io/auto/sdk v1.1.0 // indirect + go.opentelemetry.io/auto/sdk v1.2.1 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.36.0 // indirect - go.opentelemetry.io/otel/metric v1.36.0 // indirect + go.opentelemetry.io/otel/metric v1.39.0 // indirect go.opentelemetry.io/proto/otlp v1.6.0 // indirect go.uber.org/atomic v1.11.0 // indirect go.uber.org/multierr v1.8.0 // indirect golang.org/x/arch v0.6.0 // indirect - golang.org/x/crypto v0.40.0 // indirect - golang.org/x/net v0.42.0 // indirect - golang.org/x/sync v0.16.0 // indirect - golang.org/x/sys v0.34.0 // indirect - golang.org/x/text v0.27.0 // indirect + golang.org/x/crypto v0.46.0 // indirect + golang.org/x/net v0.48.0 // indirect + golang.org/x/sync v0.19.0 // indirect + golang.org/x/sys v0.39.0 // indirect + golang.org/x/text v0.32.0 // indirect golang.org/x/time v0.12.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 // indirect ) diff --git a/persys-gateway/go.sum b/persys-gateway/go.sum index 01a573d..56f7ac4 100755 --- a/persys-gateway/go.sum +++ b/persys-gateway/go.sum @@ -26,8 +26,6 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumC github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= -github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= -github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= github.com/gin-contrib/cors v1.5.0 h1:DgGKV7DDoOn36DFkNtbHrjoRiT5ExCe+PC9/xp7aKvk= @@ -36,11 +34,11 @@ github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg= github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU= -github.com/go-jose/go-jose/v4 v4.1.1 h1:JYhSgy4mXXzAdF3nUx3ygx347LRXJRrpgyU3adRmkAI= -github.com/go-jose/go-jose/v4 v4.1.1/go.mod h1:BdsZGqgdO3b6tTc6LSE56wcDbMMLuPsw5d4ZD5f94kA= +github.com/go-jose/go-jose/v4 v4.1.3 h1:CVLmWDhDVRa6Mi/IgCgaopNosCaHz7zrMeF9MlZRkrs= +github.com/go-jose/go-jose/v4 v4.1.3/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= -github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/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/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= @@ -51,15 +49,12 @@ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJn github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= github.com/go-playground/validator/v10 v10.16.0 h1:x+plE831WK4vaKHO/jpgUGsvLKIqRRkz6M78GuJAfGE= github.com/go-playground/validator/v10 v10.16.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= -github.com/go-playground/webhooks/v6 v6.0.1 h1:ssqgU7vZ+xK+/Uwx4zkf5tfmzOHnLBpzSp5bJ4cX3rg= -github.com/go-playground/webhooks/v6 v6.0.1/go.mod h1:GCocmfMtpJdkEOM1uG9p2nXzg1kY5X/LtvQgtPHUaaA= github.com/go-test/deep v1.1.1 h1:0r/53hagsehfO4bzD2Pgr/+RgHqhmf+k1Bpse2cTu1U= github.com/go-test/deep v1.1.1/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= -github.com/gogits/go-gogs-client v0.0.0-20200905025246-8bb8a50cb355/go.mod h1:cY2AIrMgHm6oOHmR7jY+9TtjzSjQ3iG7tURJG3Y6XH0= -github.com/golang/glog v1.2.4 h1:CNNw5U8lSiiBk7druxtSHHTsRWcxKoac6kZKm2peBBc= -github.com/golang/glog v1.2.4/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= +github.com/golang/glog v1.2.5 h1:DrW6hGnjIhtvhOIiAKT6Psh/Kd/ldepEa81DKeiRJ5I= +github.com/golang/glog v1.2.5/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= @@ -139,6 +134,8 @@ github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8 github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= +github.com/persys-dev/persys-cloud/pkg v0.0.0-20260701205454-9cb94822d71f h1:lKC6ntuESIn5yp2GcWQwyE+vMCh+lges3gbjF/Zxk3A= +github.com/persys-dev/persys-cloud/pkg v0.0.0-20260701205454-9cb94822d71f/go.mod h1:BKpHun2lgyknFnBmitTCxZ9pNXiF91HO2Kd2WDJAH8w= 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= @@ -152,25 +149,24 @@ github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdO github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI= github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY= -github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= -github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= +github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= +github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk= github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= -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.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w= +github.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC42RjbV2g= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= -github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= @@ -190,28 +186,26 @@ github.com/zsais/go-gin-prometheus v0.1.0 h1:bkLv1XCdzqVgQ36ScgRi09MA2UC1t3tAB6n github.com/zsais/go-gin-prometheus v0.1.0/go.mod h1:Slirjzuz8uM8Cw0jmPNqbneoqcUtY2GGjn2bEd4NRLY= go.mongodb.org/mongo-driver v1.13.1 h1:YIc7HTYsKndGK4RFzJ3covLz1byri52x0IoMB0Pt/vk= go.mongodb.org/mongo-driver v1.13.1/go.mod h1:wcDf1JBCXy2mOW0bWHwO/IOYqdca1MPCwDtFu/Z9+eo= -go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= -go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= +go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= +go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin v0.46.1 h1:mMv2jG58h6ZI5t5S9QCVGdzCmAsTakMa3oxVgpSD44g= go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin v0.46.1/go.mod h1:oqRuNKG0upTaDPbLVCG8AD0G2ETrfDtmh7jViy7ox6M= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1 h1:aFJWCqJMNjENlcleuuOkGAPH82y0yULBScfXcIEdS24= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1/go.mod h1:sEGXWArGqc3tVa+ekntsN65DmVbVeW+7lTKTjZF3/Fo= go.opentelemetry.io/contrib/propagators/b3 v1.21.1 h1:WPYiUgmw3+b7b3sQ1bFBFAf0q+Di9dvNc3AtYfnT4RQ= go.opentelemetry.io/contrib/propagators/b3 v1.21.1/go.mod h1:EmzokPoSqsYMBVK4nRnhsfm5mbn8J1eDuz/U1UaQaWg= -go.opentelemetry.io/otel v1.36.0 h1:UumtzIklRBY6cI/lllNZlALOF5nNIzJVb16APdvgTXg= -go.opentelemetry.io/otel v1.36.0/go.mod h1:/TcFMXYjyRNh8khOAO9ybYkqaDBb/70aVwkNML4pP8E= +go.opentelemetry.io/otel v1.39.0 h1:8yPrr/S0ND9QEfTfdP9V+SiwT4E0G7Y5MO7p85nis48= +go.opentelemetry.io/otel v1.39.0/go.mod h1:kLlFTywNWrFyEdH0oj2xK0bFYZtHRYUdv1NklR/tgc8= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.36.0 h1:dNzwXjZKpMpE2JhmO+9HsPl42NIXFIFSUSSs0fiqra0= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.36.0/go.mod h1:90PoxvaEB5n6AOdZvi+yWJQoE95U8Dhhw2bSyRqnTD0= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.36.0 h1:nRVXXvf78e00EwY6Wp0YII8ww2JVWshZ20HfTlE11AM= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.36.0/go.mod h1:r49hO7CgrxY9Voaj3Xe8pANWtr0Oq916d0XAmOoCZAQ= -go.opentelemetry.io/otel/metric v1.36.0 h1:MoWPKVhQvJ+eeXWHFBOPoBOi20jh6Iq2CcCREuTYufE= -go.opentelemetry.io/otel/metric v1.36.0/go.mod h1:zC7Ks+yeyJt4xig9DEw9kuUFe5C3zLbVjV2PzT6qzbs= -go.opentelemetry.io/otel/sdk v1.36.0 h1:b6SYIuLRs88ztox4EyrvRti80uXIFy+Sqzoh9kFULbs= -go.opentelemetry.io/otel/sdk v1.36.0/go.mod h1:+lC+mTgD+MUWfjJubi2vvXWcVxyr9rmlshZni72pXeY= -go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce1EK0Gyvahk= -go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w= -go.opentelemetry.io/otel/trace v1.36.0 h1:ahxWNuqZjpdiFAyrIoQ4GIiAIhxAunQR6MUoKrsNd4w= -go.opentelemetry.io/otel/trace v1.36.0/go.mod h1:gQ+OnDZzrybY4k4seLzPAWNwVBBVlF2szhehOBB/tGA= +go.opentelemetry.io/otel/metric v1.39.0 h1:d1UzonvEZriVfpNKEVmHXbdf909uGTOQjA0HF0Ls5Q0= +go.opentelemetry.io/otel/metric v1.39.0/go.mod h1:jrZSWL33sD7bBxg1xjrqyDjnuzTUB0x1nBERXd7Ftcs= +go.opentelemetry.io/otel/sdk v1.39.0 h1:nMLYcjVsvdui1B/4FRkwjzoRVsMK8uL/cj0OyhKzt18= +go.opentelemetry.io/otel/sdk v1.39.0/go.mod h1:vDojkC4/jsTJsE+kh+LXYQlbL8CgrEcwmt1ENZszdJE= +go.opentelemetry.io/otel/sdk/metric v1.39.0 h1:cXMVVFVgsIf2YL6QkRF4Urbr/aMInf+2WKg+sEJTtB8= +go.opentelemetry.io/otel/sdk/metric v1.39.0/go.mod h1:xq9HEVH7qeX69/JnwEfp6fVq5wosJsY1mt4lLfYdVew= +go.opentelemetry.io/otel/trace v1.39.0 h1:2d2vfpEDmCJ5zVYz7ijaJdOF59xLomrvj7bjt6/qCJI= +go.opentelemetry.io/otel/trace v1.39.0/go.mod h1:88w4/PnZSazkGzz/w84VHpQafiU4EtqqlVdxWy+rNOA= go.opentelemetry.io/proto/otlp v1.6.0 h1:jQjP+AQyTf+Fe7OKj/MfkDrmK4MNVtw2NpXsf9fefDI= go.opentelemetry.io/proto/otlp v1.6.0/go.mod h1:cicgGehlFuNdgZkcALOCh3VE6K/u2tAjzlRhDwmVpZc= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= @@ -233,8 +227,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM= -golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY= +golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU= +golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= @@ -245,16 +239,16 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs= -golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8= -golang.org/x/oauth2 v0.27.0 h1:da9Vo7/tDv5RH/7nZDz1eMGS/q1Vv1N/7FCrBhI9I3M= -golang.org/x/oauth2 v0.27.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= +golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU= +golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY= +golang.org/x/oauth2 v0.34.0 h1:hqK/t4AKgbqWkdkcAeI8XLmbK+4m4G5YeQRrmiotGlw= +golang.org/x/oauth2 v0.34.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= -golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= +golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= 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-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -263,12 +257,11 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA= -golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk= +golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -277,8 +270,8 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4= -golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU= +golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU= +golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY= golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE= golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -290,14 +283,16 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T 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-20250519155744-55703ea1f237 h1:Kog3KlB4xevJlAcbbbzPfRG0+X9fdoGM+UBRKVz6Wr0= -google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237/go.mod h1:ezi0AVyMKDWy5xAncvjLWH7UcLBB5n7y2fQ8MzjJcto= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 h1:cJfm9zPbe1e873mHJzmQ1nwVEeRDU/T1wXDK2kUSU34= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= -google.golang.org/grpc v1.72.1 h1:HR03wO6eyZ7lknl75XlxABNVLLFc2PAb6mHlYh756mA= -google.golang.org/grpc v1.72.1/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM= -google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= -google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= +gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= +gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= +google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217 h1:fCvbg86sFXwdrl5LgVcTEvNC+2txB5mgROGmRL5mrls= +google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217/go.mod h1:+rXWjjaukWZun3mLfjmVnQi18E1AsFbDN9QdJ5YXLto= +google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 h1:gRkg/vSppuSQoDjxyiGfN4Upv/h/DQmIR10ZU8dh4Ww= +google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk= +google.golang.org/grpc v1.79.1 h1:zGhSi45ODB9/p3VAawt9a+O/MULLl9dpizzNNpq7flY= +google.golang.org/grpc v1.79.1/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ= +google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= +google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= From 71fa4a6acd64d0641b657fab8d3867e5f95fdd81 Mon Sep 17 00:00:00 2001 From: milx Date: Mon, 6 Jul 2026 20:36:35 +0330 Subject: [PATCH 06/18] Feat: Add pprof to intelligence service --- persys-intelligence/cmd/intelligence/main.go | 1 + 1 file changed, 1 insertion(+) diff --git a/persys-intelligence/cmd/intelligence/main.go b/persys-intelligence/cmd/intelligence/main.go index cb007a5..84c80df 100644 --- a/persys-intelligence/cmd/intelligence/main.go +++ b/persys-intelligence/cmd/intelligence/main.go @@ -7,6 +7,7 @@ import ( "log" "net" "net/http" + _ "net/http/pprof" "os/signal" "strconv" "syscall" From da47c07603b3b651d5e14d6b7008124798ecb793 Mon Sep 17 00:00:00 2001 From: milx Date: Mon, 6 Jul 2026 21:13:14 +0330 Subject: [PATCH 07/18] Fix: Add missing Created_at field to scheduler proto scheme --- persys-scheduler/api/proto/control.proto | 1 + 1 file changed, 1 insertion(+) diff --git a/persys-scheduler/api/proto/control.proto b/persys-scheduler/api/proto/control.proto index 5557402..b7ae24f 100644 --- a/persys-scheduler/api/proto/control.proto +++ b/persys-scheduler/api/proto/control.proto @@ -431,6 +431,7 @@ message WorkloadView { google.protobuf.Timestamp last_updated = 11; ReasonDetail reason = 12; WorkloadUsageSnapshot usage = 13; + google.protobuf.Timestamp created_at = 14; } message GetClusterSummaryRequest {} From da762792bb045f4c92353d660a46966c33536ed8 Mon Sep 17 00:00:00 2001 From: milx Date: Mon, 6 Jul 2026 21:52:32 +0330 Subject: [PATCH 08/18] Chore: Separate Persys Monitoring Stack --- infra/docker/docker-compose.monitoring.yml | 108 +++++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 infra/docker/docker-compose.monitoring.yml diff --git a/infra/docker/docker-compose.monitoring.yml b/infra/docker/docker-compose.monitoring.yml new file mode 100644 index 0000000..bd1437f --- /dev/null +++ b/infra/docker/docker-compose.monitoring.yml @@ -0,0 +1,108 @@ +# Persys Cloud Monitoring Stack + +services: + # --- Prometheus (Metrics collection) --- + prometheus: + image: prom/prometheus:latest + volumes: + - /etc/localtime:/etc/localtime:ro + - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro + - prometheus_data:/prometheus + command: + - '--config.file=/etc/prometheus/prometheus.yml' + - '--storage.tsdb.path=/prometheus' + - '--web.console.libraries=/usr/share/prometheus/console_libraries' + - '--web.console.templates=/usr/share/prometheus/consoles' + ports: + - "9090:9090" + networks: + - persys-cloud-net + + # --- Grafana (Metrics visualization) --- + grafana: + image: grafana/grafana:latest + container_name: grafana_container + volumes: + - /etc/localtime:/etc/localtime:ro + - ./grafana/provisioning:/etc/grafana/provisioning + - grafana_data:/var/lib/grafana + environment: + - GF_SECURITY_ADMIN_USER=${GF_SECURITY_ADMIN_USER:-admin} + - GF_SECURITY_ADMIN_PASSWORD=${GF_SECURITY_ADMIN_PASSWORD:-admin} + - GF_USERS_ALLOW_SIGN_UP=${GF_USERS_ALLOW_SIGN_UP:-false} + ports: + - "3000:3000" + networks: + - persys-cloud-net + depends_on: + - prometheus + + # --- Pyroscope (Profiling) --- + pyroscope: + image: grafana/pyroscope:latest + ports: + - "4040:4040" + command: ["server"] + networks: + - persys-cloud-net + volumes: + - /etc/localtime:/etc/localtime:ro + - pyroscope_data:/data + + # --- Alloy (Profile Scraping) --- + alloy: + image: grafana/alloy:latest + volumes: + - ./alloy/alloy-config.alloy:/etc/alloy/config.alloy + - /etc/localtime:/etc/localtime:ro + command: ["run", "/etc/alloy/config.alloy"] + networks: + - persys-cloud-net + depends_on: + - pyroscope + + # --- Jaeger (Distributed tracing) --- + jaeger: + image: jaegertracing/all-in-one:latest + environment: + - COLLECTOR_OTLP_ENABLED=${COLLECTOR_OTLP_ENABLED:-true} + ports: + - "5775:5775/udp" + - "6831:6831/udp" + - "6832:6832/udp" + - "5778:5778" + - "16686:16686" + - "14250:14250" + - "14268:14268" + - "14269:14269" + - "4317:4317" + - "4318:4318" + volumes: + - /etc/localtime:/etc/localtime:ro + networks: + - persys-cloud-net + + # --- Node Exporter (Host metrics for Prometheus) --- + node_exporter: + container_name: node_exporter_container + restart: always + image: prom/node-exporter + ports: + - '9100:9100' + volumes: + - /proc:/host/proc:ro + - /sys:/host/sys:ro + - /:/rootfs:ro + networks: + - persys-cloud-net + +# --- Volumes for persistent data --- +volumes: + pyroscope_data: + prometheus_data: + grafana_data: + +# --- Shared overlay network for all services --- +networks: + persys-cloud-net: + driver: bridge From 2331fa9ff6b1f14d74a58e2751f827ffcf5e0af3 Mon Sep 17 00:00:00 2001 From: milx Date: Mon, 6 Jul 2026 21:53:09 +0330 Subject: [PATCH 09/18] Chore: Remove Monitoring + Cleanup --- infra/docker/docker-compose.yml | 90 +++------------------------------ 1 file changed, 7 insertions(+), 83 deletions(-) diff --git a/infra/docker/docker-compose.yml b/infra/docker/docker-compose.yml index 728af66..59ce21d 100644 --- a/infra/docker/docker-compose.yml +++ b/infra/docker/docker-compose.yml @@ -1,7 +1,7 @@ # Persys Cloud Full Stack Docker Compose # # This file defines all core services for local development and integration: -# - Persys Gateway, Persys Scheduler, Persys Automation, Persys Forgery, Persys Federation, Persys Intelligence,CoreDNS, Hashicorp Vault, MongoDB, MySQL, Postgres, Prometheus, Grafana, Jaeger, etcd, Node Exporter +# - Persys Gateway, Persys Scheduler, Persys Automation, Persys Forgery, Persys Federation, Persys Intelligence, CoreDNS, Hashicorp Vault, MongoDB, MySQL, Postgres, etcd # - All services are connected via the 'persys-cloud-net' bridge network services: @@ -12,10 +12,10 @@ services: ports: - 8551:8551 depends_on: + - vault-manager - mongodb - vault - coredns - - jaeger environment: - OTEL_EXPORTER_JAEGER_ENDPOINT=${OTEL_EXPORTER_JAEGER_ENDPOINT:-jaeger:4318} - OTEL_EXPORTER_OTLP_ENDPOINT=${OTEL_EXPORTER_OTLP_ENDPOINT:-jaeger:4318} @@ -47,9 +47,8 @@ services: - 8085:8085 # gRPC + mTLS API depends_on: - etcd - - vault + - vault-manager - coredns - - jaeger - redis environment: - ETCD_ENDPOINTS=${ETCD_ENDPOINTS:-etcd:2379} @@ -80,7 +79,7 @@ services: ports: - 8087:8087 depends_on: - - vault + - vault-manager - mysql - redis environment: @@ -112,7 +111,6 @@ services: - 8092:8092 depends_on: - persys-scheduler - - prometheus - postgres - persys-intelligence environment: @@ -165,7 +163,6 @@ services: - 8094:8094 depends_on: - persys-scheduler - - prometheus environment: - INTELLIGENCE_HTTP_ADDR=0.0.0.0 - INTELLIGENCE_HTTP_PORT=8093 @@ -230,11 +227,11 @@ services: - /etc/localtime:/etc/localtime:ro - ${DOCKER_SOCK_PATH:-/var/run/docker.sock}:/var/run/docker.sock depends_on: - - vault + - vault-manager - persys-scheduler ports: - "50051:50051" - - "8089:8080" + - "8089:8089" networks: - persys-cloud-net @@ -258,7 +255,7 @@ services: networks: - persys-cloud-net - # --- Vault Bootstrap (runs once to initialize/provision Vault) --- + # --- Vault Manager (Vault Automatic Management) --- vault-manager: build: ../../vault-manager restart: "no" @@ -290,77 +287,6 @@ services: networks: - persys-cloud-net - # --- Prometheus (Metrics collection) --- - prometheus: - image: prom/prometheus:latest - volumes: - - /etc/localtime:/etc/localtime:ro - - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro - - prometheus_data:/prometheus - command: - - '--config.file=/etc/prometheus/prometheus.yml' - - '--storage.tsdb.path=/prometheus' - - '--web.console.libraries=/usr/share/prometheus/console_libraries' - - '--web.console.templates=/usr/share/prometheus/consoles' - ports: - - "9090:9090" - networks: - - persys-cloud-net - - # --- Grafana (Metrics visualization) --- - grafana: - image: grafana/grafana:latest - container_name: grafana_container - volumes: - - /etc/localtime:/etc/localtime:ro - - ./grafana/provisioning:/etc/grafana/provisioning - - grafana_data:/var/lib/grafana - environment: - - GF_SECURITY_ADMIN_USER=${GF_SECURITY_ADMIN_USER:-admin} - - GF_SECURITY_ADMIN_PASSWORD=${GF_SECURITY_ADMIN_PASSWORD:-admin} - - GF_USERS_ALLOW_SIGN_UP=${GF_USERS_ALLOW_SIGN_UP:-false} - ports: - - "3000:3000" - networks: - - persys-cloud-net - depends_on: - - prometheus - - # --- Jaeger (Distributed tracing) --- - jaeger: - image: jaegertracing/all-in-one:latest - environment: - - COLLECTOR_OTLP_ENABLED=${COLLECTOR_OTLP_ENABLED:-true} - ports: - - "5775:5775/udp" - - "6831:6831/udp" - - "6832:6832/udp" - - "5778:5778" - - "16686:16686" - - "14250:14250" - - "14268:14268" - - "14269:14269" - - "4317:4317" - - "4318:4318" - volumes: - - /etc/localtime:/etc/localtime:ro - networks: - - persys-cloud-net - - # --- Node Exporter (Host metrics for Prometheus) --- - node_exporter: - container_name: node_exporter_container - restart: always - image: prom/node-exporter - ports: - - '9100:9100' - volumes: - - /proc:/host/proc:ro - - /sys:/host/sys:ro - - /:/rootfs:ro - networks: - - persys-cloud-net - # --- MySQL (Forgery persistence) --- mysql: image: mysql:8.0 @@ -444,8 +370,6 @@ volumes: mysql_data: redis_data: automation_postgres_data: - prometheus_data: - grafana_data: vault_data: etcd_data: From a5f1e3e5ea6258a03ce39fe03b103fb69cb4f6ef Mon Sep 17 00:00:00 2001 From: milx Date: Mon, 6 Jul 2026 21:54:06 +0330 Subject: [PATCH 10/18] Feat: Add Retries To FetchCredentials (Wait for vault-manager for 40 seconds hardcoded) --- pkg/certmanager/vault.go | 62 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 59 insertions(+), 3 deletions(-) diff --git a/pkg/certmanager/vault.go b/pkg/certmanager/vault.go index fd34275..1bf72e5 100644 --- a/pkg/certmanager/vault.go +++ b/pkg/certmanager/vault.go @@ -246,9 +246,10 @@ func (m *Manager) newVaultClient() (*vault.Client, error) { ctx := context.Background() // ONLY PLACE WE FETCH Vault Role_ID + Secret ID from Vault-manager - if err := m.fetchCredentials(ctx, false); err != nil { - m.logger.WithError(err).Warn("Vault Manager not reachable during credential fetch") - return nil, fmt.Errorf("failed to fetch AppRole credentials from VaultManager: %w", err) + if err := WithRetry(4, 10*time.Second, func() error { + return m.fetchCredentials(ctx, false) + }); err != nil { + return nil, fmt.Errorf("failed to fetch credentials from vault-manager after retries: %w", err) } m.logger.Debug("we sent a request to vault manager at it was successful") @@ -624,3 +625,58 @@ func writeCertBundleAtomic(certPath, certPEM, keyPath, keyPEM, caPath, caPEM str } return nil } + +func WithRetry(attempts int, delay time.Duration, fn func() error) error { + if attempts <= 0 { + logrus.Warn("WithRetry called with attempts <= 0; treating as a single attempt") + attempts = 1 + } + + var lastErr error + start := time.Now() + + for i := 0; i < attempts; i++ { + attemptNum := i + 1 + logrus.WithFields(logrus.Fields{ + "attempt": attemptNum, + "max_attempts": attempts, + }).Debug("WithRetry: starting attempt") + + attemptStart := time.Now() + err := fn() + attemptElapsed := time.Since(attemptStart) + + if err == nil { + logrus.WithFields(logrus.Fields{ + "attempt": attemptNum, + "max_attempts": attempts, + "elapsed_ms": attemptElapsed.Milliseconds(), + "total_elapsed_ms": time.Since(start).Milliseconds(), + }).Debug("WithRetry: attempt succeeded") + return nil + } + + lastErr = err + logrus.WithError(err).WithFields(logrus.Fields{ + "attempt": attemptNum, + "max_attempts": attempts, + "elapsed_ms": attemptElapsed.Milliseconds(), + }).Warn("WithRetry: attempt failed") + + if i < attempts-1 { + logrus.WithFields(logrus.Fields{ + "attempt": attemptNum, + "next_attempt": attemptNum + 1, + "delay": delay.String(), + }).Debug("WithRetry: waiting before next attempt") + time.Sleep(delay) + } + } + + logrus.WithError(lastErr).WithFields(logrus.Fields{ + "max_attempts": attempts, + "total_elapsed_ms": time.Since(start).Milliseconds(), + }).Error("WithRetry: all attempts exhausted, giving up") + + return fmt.Errorf("all %d attempts failed: %w", attempts, lastErr) +} \ No newline at end of file From 79c4e56ae42c2fa4e210d062b09f321775e00821 Mon Sep 17 00:00:00 2001 From: milx Date: Mon, 6 Jul 2026 21:56:00 +0330 Subject: [PATCH 11/18] Feat: Add a redis stream for per workload usage metrics --- .../internal/scheduler/usage_stream.go | 106 ++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 persys-scheduler/internal/scheduler/usage_stream.go diff --git a/persys-scheduler/internal/scheduler/usage_stream.go b/persys-scheduler/internal/scheduler/usage_stream.go new file mode 100644 index 0000000..9bd8343 --- /dev/null +++ b/persys-scheduler/internal/scheduler/usage_stream.go @@ -0,0 +1,106 @@ +package scheduler + +import ( + "context" + "encoding/json" + "time" + + "github.com/google/uuid" + "github.com/persys-dev/persys-cloud/persys-scheduler/internal/models" + "github.com/redis/go-redis/v9" + "github.com/sirupsen/logrus" +) + +// defaultMeterStreamName is used if configuration doesn't specify one. +const defaultMeterStreamName = "persys:usage:stream" + +// usageStreamEvent is the wire format published to the meter ingestion stream. +// persys-meter (or any other consumer) reads this via a Redis Streams +// consumer group (XREADGROUP) and is expected to deduplicate on EventID, or +// on the (NodeID, WorkloadID, ReportedAt) tuple as a fallback. +type usageStreamEvent struct { + EventID string `json:"event_id"` + NodeID string `json:"node_id"` + WorkloadID string `json:"workload_id"` + RevisionID string `json:"revision_id,omitempty"` + ReportedAt string `json:"reported_at"` + Usage *models.WorkloadUsage `json:"usage"` +} + +// publishUsageEvent publishes a per-workload usage snapshot onto the Redis +// Stream consumed by persys-meter. +// +// This is intentionally best-effort and never blocks or fails the caller +// (heartbeat processing): if Redis isn't configured, unreachable, or the +// stream feature is disabled, the event is silently dropped after a warning +// log. The scheduler's own state - queried live via ListWorkloads/GetWorkload +// - remains the source of truth regardless of whether this publish succeeds, +// so no usage data is lost from the scheduler's perspective; only the +// meter's near-real-time feed would miss a sample. +func (s *Scheduler) publishUsageEvent(nodeID, workloadID, revisionID string, usage *models.WorkloadUsage) { + if usage == nil || workloadID == "" { + return + } + if s.redisClient == nil || s.cfg == nil || !s.cfg.MeterStreamEnabled { + return + } + + streamName := s.cfg.MeterStreamName + if streamName == "" { + streamName = defaultMeterStreamName + } + + reportedAt := usage.CollectedAt + if reportedAt.IsZero() { + reportedAt = time.Now().UTC() + } + reportedAtText := reportedAt.UTC().Format(time.RFC3339Nano) + + event := usageStreamEvent{ + EventID: uuid.NewString(), + NodeID: nodeID, + WorkloadID: workloadID, + RevisionID: revisionID, + ReportedAt: reportedAtText, + Usage: usage, + } + + payload, err := json.Marshal(event) + if err != nil { + redisLogger.WithError(err).WithFields(logrus.Fields{ + "workload_id": workloadID, + }).Warn("failed to marshal usage event for meter stream; dropping sample") + return + } + + maxLen := int64(100000) + if s.cfg.MeterStreamMaxLen > 0 { + maxLen = s.cfg.MeterStreamMaxLen + } + + ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) + defer cancel() + + // MaxLen+Approx trims the stream approximately (cheap, no full scan) so it + // can't grow unbounded if persys-meter is behind or offline; consumer + // groups still get at-least-once delivery for anything not yet trimmed. + err = s.redisClient.XAdd(ctx, &redis.XAddArgs{ + Stream: streamName, + MaxLen: maxLen, + Approx: true, + Values: map[string]interface{}{ + "event_id": event.EventID, + "node_id": event.NodeID, + "workload_id": event.WorkloadID, + "revision_id": event.RevisionID, + "reported_at": event.ReportedAt, + "payload": string(payload), + }, + }).Err() + if err != nil { + redisLogger.WithError(err).WithFields(logrus.Fields{ + "stream": streamName, + "workload_id": workloadID, + }).Warn("failed to publish usage event to meter stream") + } +} From ce4c5fafa78c145ea01fe3b876cf75d81d219a5b Mon Sep 17 00:00:00 2001 From: milx Date: Mon, 6 Jul 2026 21:57:06 +0330 Subject: [PATCH 12/18] Feat: Add Node ID to identify workload owner + Publish events to redis stream for upstream services --- persys-scheduler/internal/scheduler/scheduler.go | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/persys-scheduler/internal/scheduler/scheduler.go b/persys-scheduler/internal/scheduler/scheduler.go index c4b1c38..d75e05b 100644 --- a/persys-scheduler/internal/scheduler/scheduler.go +++ b/persys-scheduler/internal/scheduler/scheduler.go @@ -918,7 +918,10 @@ func (s *Scheduler) UpdateWorkloadMetadata(workloadID string, metadata map[strin } // UpdateWorkloadRuntimeDetails stores structured reason and latest usage for a workload. -func (s *Scheduler) UpdateWorkloadRuntimeDetails(workloadID string, reason *models.WorkloadReason, usage *models.WorkloadUsage) error { +// nodeID identifies the agent that reported this sample (from the heartbeat +// envelope) and is used only for the meter usage-stream event; it is not +// persisted on the workload record. +func (s *Scheduler) UpdateWorkloadRuntimeDetails(workloadID, nodeID string, reason *models.WorkloadReason, usage *models.WorkloadUsage) error { if err := s.requireWritable(); err != nil { return err } @@ -972,6 +975,15 @@ func (s *Scheduler) UpdateWorkloadRuntimeDetails(workloadID string, reason *mode if err := s.saveWorkload(workload); err != nil { return fmt.Errorf("failed to update workload %s runtime details: %v", workloadID, err) } + + if usage != nil { + reportingNode := strings.TrimSpace(nodeID) + if reportingNode == "" { + reportingNode = workload.NodeID + } + s.publishUsageEvent(reportingNode, workload.ID, workload.RevisionID, usage) + } + return nil } From a76e4ac89e6759bc701fa03997560a7903954929 Mon Sep 17 00:00:00 2001 From: milx Date: Mon, 6 Jul 2026 21:58:08 +0330 Subject: [PATCH 13/18] Feat: Add Node ID to node heartbeat --- persys-scheduler/internal/grpcapi/service.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/persys-scheduler/internal/grpcapi/service.go b/persys-scheduler/internal/grpcapi/service.go index 1708396..ec1152c 100644 --- a/persys-scheduler/internal/grpcapi/service.go +++ b/persys-scheduler/internal/grpcapi/service.go @@ -180,7 +180,7 @@ func (s *Service) Heartbeat(ctx context.Context, in *controlv1.HeartbeatRequest) reason := reasonFromProto(ws.GetReason(), ws.GetLastTransition()) usage := usageFromProto(ws.GetUsage(), ws.GetWorkloadId(), "") if reason != nil || usage != nil { - _ = s.sched.UpdateWorkloadRuntimeDetails(ws.GetWorkloadId(), reason, usage) + _ = s.sched.UpdateWorkloadRuntimeDetails(ws.GetWorkloadId(), in.GetNodeId(), reason, usage) } } @@ -191,7 +191,7 @@ func (s *Service) Heartbeat(ctx context.Context, in *controlv1.HeartbeatRequest) } modelUsage := usageFromProto(usage, workloadID, "") if modelUsage != nil { - _ = s.sched.UpdateWorkloadRuntimeDetails(workloadID, nil, modelUsage) + _ = s.sched.UpdateWorkloadRuntimeDetails(workloadID, in.GetNodeId(), nil, modelUsage) } } From 4a6e8e90944c1d79b67656f5b41d73fc10d651dc Mon Sep 17 00:00:00 2001 From: milx Date: Mon, 6 Jul 2026 21:58:33 +0330 Subject: [PATCH 14/18] Fix: Add Missing Created At Field --- .../internal/controlv1/control.pb.go | 107 ++++++++++-------- .../internal/controlv1/control_grpc.pb.go | 2 +- 2 files changed, 60 insertions(+), 49 deletions(-) diff --git a/persys-scheduler/internal/controlv1/control.pb.go b/persys-scheduler/internal/controlv1/control.pb.go index 1aabe2a..a2d0fc4 100644 --- a/persys-scheduler/internal/controlv1/control.pb.go +++ b/persys-scheduler/internal/controlv1/control.pb.go @@ -3630,6 +3630,7 @@ type WorkloadView struct { LastUpdated *timestamppb.Timestamp `protobuf:"bytes,11,opt,name=last_updated,json=lastUpdated,proto3" json:"last_updated,omitempty"` Reason *ReasonDetail `protobuf:"bytes,12,opt,name=reason,proto3" json:"reason,omitempty"` Usage *WorkloadUsageSnapshot `protobuf:"bytes,13,opt,name=usage,proto3" json:"usage,omitempty"` + CreatedAt *timestamppb.Timestamp `protobuf:"bytes,14,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -3755,6 +3756,13 @@ func (x *WorkloadView) GetUsage() *WorkloadUsageSnapshot { return nil } +func (x *WorkloadView) GetCreatedAt() *timestamppb.Timestamp { + if x != nil { + return x.CreatedAt + } + return nil +} + type GetClusterSummaryRequest struct { state protoimpl.MessageState `protogen:"open.v1"` unknownFields protoimpl.UnknownFields @@ -4314,7 +4322,7 @@ const file_control_proto_rawDesc = "" + "\x15ListWorkloadsResponse\x12=\n" + "\tworkloads\x18\x01 \x03(\v2\x1f.persys.control.v1.WorkloadViewR\tworkloads\"R\n" + "\x13GetWorkloadResponse\x12;\n" + - "\bworkload\x18\x01 \x01(\v2\x1f.persys.control.v1.WorkloadViewR\bworkload\"\xbf\x04\n" + + "\bworkload\x18\x01 \x01(\v2\x1f.persys.control.v1.WorkloadViewR\bworkload\"\xfa\x04\n" + "\fWorkloadView\x12\x1f\n" + "\vworkload_id\x18\x01 \x01(\tR\n" + "workloadId\x12\x12\n" + @@ -4331,7 +4339,9 @@ const file_control_proto_rawDesc = "" + " \x01(\tR\rfailureReason\x12=\n" + "\flast_updated\x18\v \x01(\v2\x1a.google.protobuf.TimestampR\vlastUpdated\x127\n" + "\x06reason\x18\f \x01(\v2\x1f.persys.control.v1.ReasonDetailR\x06reason\x12>\n" + - "\x05usage\x18\r \x01(\v2(.persys.control.v1.WorkloadUsageSnapshotR\x05usage\"\x1a\n" + + "\x05usage\x18\r \x01(\v2(.persys.control.v1.WorkloadUsageSnapshotR\x05usage\x129\n" + + "\n" + + "created_at\x18\x0e \x01(\v2\x1a.google.protobuf.TimestampR\tcreatedAt\"\x1a\n" + "\x18GetClusterSummaryRequest\"\x9f\x03\n" + "\x19GetClusterSummaryResponse\x12\x1f\n" + "\vtotal_nodes\x18\x01 \x01(\x05R\n" + @@ -4524,52 +4534,53 @@ var file_control_proto_depIdxs = []int32{ 63, // 53: persys.control.v1.WorkloadView.last_updated:type_name -> google.protobuf.Timestamp 28, // 54: persys.control.v1.WorkloadView.reason:type_name -> persys.control.v1.ReasonDetail 27, // 55: persys.control.v1.WorkloadView.usage:type_name -> persys.control.v1.WorkloadUsageSnapshot - 63, // 56: persys.control.v1.GetClusterSummaryResponse.generated_at:type_name -> google.protobuf.Timestamp - 5, // 57: persys.control.v1.ControlMessage.register:type_name -> persys.control.v1.RegisterNodeRequest - 9, // 58: persys.control.v1.ControlMessage.heartbeat:type_name -> persys.control.v1.HeartbeatRequest - 12, // 59: persys.control.v1.ControlMessage.apply:type_name -> persys.control.v1.ApplyWorkloadRequest - 14, // 60: persys.control.v1.ControlMessage.delete:type_name -> persys.control.v1.DeleteWorkloadRequest - 5, // 61: persys.control.v1.AgentControl.RegisterNode:input_type -> persys.control.v1.RegisterNodeRequest - 9, // 62: persys.control.v1.AgentControl.Heartbeat:input_type -> persys.control.v1.HeartbeatRequest - 12, // 63: persys.control.v1.AgentControl.ApplyWorkload:input_type -> persys.control.v1.ApplyWorkloadRequest - 14, // 64: persys.control.v1.AgentControl.DeleteWorkload:input_type -> persys.control.v1.DeleteWorkloadRequest - 30, // 65: persys.control.v1.AgentControl.RetryWorkload:input_type -> persys.control.v1.RetryWorkloadRequest - 32, // 66: persys.control.v1.AgentControl.DrainNode:input_type -> persys.control.v1.DrainNodeRequest - 34, // 67: persys.control.v1.AgentControl.UndrainNode:input_type -> persys.control.v1.UndrainNodeRequest - 37, // 68: persys.control.v1.AgentControl.TaintNode:input_type -> persys.control.v1.TaintNodeRequest - 39, // 69: persys.control.v1.AgentControl.UntaintNode:input_type -> persys.control.v1.UntaintNodeRequest - 41, // 70: persys.control.v1.AgentControl.SetNodeLabel:input_type -> persys.control.v1.SetNodeLabelRequest - 43, // 71: persys.control.v1.AgentControl.DeleteNodeLabel:input_type -> persys.control.v1.DeleteNodeLabelRequest - 3, // 72: persys.control.v1.AgentControl.SubmitAutomationSuggestion:input_type -> persys.control.v1.SubmitAutomationSuggestionRequest - 45, // 73: persys.control.v1.AgentControl.ListNodes:input_type -> persys.control.v1.ListNodesRequest - 46, // 74: persys.control.v1.AgentControl.GetNode:input_type -> persys.control.v1.GetNodeRequest - 50, // 75: persys.control.v1.AgentControl.ListWorkloads:input_type -> persys.control.v1.ListWorkloadsRequest - 51, // 76: persys.control.v1.AgentControl.GetWorkload:input_type -> persys.control.v1.GetWorkloadRequest - 55, // 77: persys.control.v1.AgentControl.GetClusterSummary:input_type -> persys.control.v1.GetClusterSummaryRequest - 57, // 78: persys.control.v1.AgentControl.ControlStream:input_type -> persys.control.v1.ControlMessage - 8, // 79: persys.control.v1.AgentControl.RegisterNode:output_type -> persys.control.v1.RegisterNodeResponse - 11, // 80: persys.control.v1.AgentControl.Heartbeat:output_type -> persys.control.v1.HeartbeatResponse - 13, // 81: persys.control.v1.AgentControl.ApplyWorkload:output_type -> persys.control.v1.ApplyWorkloadResponse - 15, // 82: persys.control.v1.AgentControl.DeleteWorkload:output_type -> persys.control.v1.DeleteWorkloadResponse - 31, // 83: persys.control.v1.AgentControl.RetryWorkload:output_type -> persys.control.v1.RetryWorkloadResponse - 33, // 84: persys.control.v1.AgentControl.DrainNode:output_type -> persys.control.v1.DrainNodeResponse - 35, // 85: persys.control.v1.AgentControl.UndrainNode:output_type -> persys.control.v1.UndrainNodeResponse - 38, // 86: persys.control.v1.AgentControl.TaintNode:output_type -> persys.control.v1.TaintNodeResponse - 40, // 87: persys.control.v1.AgentControl.UntaintNode:output_type -> persys.control.v1.UntaintNodeResponse - 42, // 88: persys.control.v1.AgentControl.SetNodeLabel:output_type -> persys.control.v1.SetNodeLabelResponse - 44, // 89: persys.control.v1.AgentControl.DeleteNodeLabel:output_type -> persys.control.v1.DeleteNodeLabelResponse - 4, // 90: persys.control.v1.AgentControl.SubmitAutomationSuggestion:output_type -> persys.control.v1.SubmitAutomationSuggestionResponse - 47, // 91: persys.control.v1.AgentControl.ListNodes:output_type -> persys.control.v1.ListNodesResponse - 48, // 92: persys.control.v1.AgentControl.GetNode:output_type -> persys.control.v1.GetNodeResponse - 52, // 93: persys.control.v1.AgentControl.ListWorkloads:output_type -> persys.control.v1.ListWorkloadsResponse - 53, // 94: persys.control.v1.AgentControl.GetWorkload:output_type -> persys.control.v1.GetWorkloadResponse - 56, // 95: persys.control.v1.AgentControl.GetClusterSummary:output_type -> persys.control.v1.GetClusterSummaryResponse - 57, // 96: persys.control.v1.AgentControl.ControlStream:output_type -> persys.control.v1.ControlMessage - 79, // [79:97] is the sub-list for method output_type - 61, // [61:79] is the sub-list for method input_type - 61, // [61:61] is the sub-list for extension type_name - 61, // [61:61] is the sub-list for extension extendee - 0, // [0:61] is the sub-list for field type_name + 63, // 56: persys.control.v1.WorkloadView.created_at:type_name -> google.protobuf.Timestamp + 63, // 57: persys.control.v1.GetClusterSummaryResponse.generated_at:type_name -> google.protobuf.Timestamp + 5, // 58: persys.control.v1.ControlMessage.register:type_name -> persys.control.v1.RegisterNodeRequest + 9, // 59: persys.control.v1.ControlMessage.heartbeat:type_name -> persys.control.v1.HeartbeatRequest + 12, // 60: persys.control.v1.ControlMessage.apply:type_name -> persys.control.v1.ApplyWorkloadRequest + 14, // 61: persys.control.v1.ControlMessage.delete:type_name -> persys.control.v1.DeleteWorkloadRequest + 5, // 62: persys.control.v1.AgentControl.RegisterNode:input_type -> persys.control.v1.RegisterNodeRequest + 9, // 63: persys.control.v1.AgentControl.Heartbeat:input_type -> persys.control.v1.HeartbeatRequest + 12, // 64: persys.control.v1.AgentControl.ApplyWorkload:input_type -> persys.control.v1.ApplyWorkloadRequest + 14, // 65: persys.control.v1.AgentControl.DeleteWorkload:input_type -> persys.control.v1.DeleteWorkloadRequest + 30, // 66: persys.control.v1.AgentControl.RetryWorkload:input_type -> persys.control.v1.RetryWorkloadRequest + 32, // 67: persys.control.v1.AgentControl.DrainNode:input_type -> persys.control.v1.DrainNodeRequest + 34, // 68: persys.control.v1.AgentControl.UndrainNode:input_type -> persys.control.v1.UndrainNodeRequest + 37, // 69: persys.control.v1.AgentControl.TaintNode:input_type -> persys.control.v1.TaintNodeRequest + 39, // 70: persys.control.v1.AgentControl.UntaintNode:input_type -> persys.control.v1.UntaintNodeRequest + 41, // 71: persys.control.v1.AgentControl.SetNodeLabel:input_type -> persys.control.v1.SetNodeLabelRequest + 43, // 72: persys.control.v1.AgentControl.DeleteNodeLabel:input_type -> persys.control.v1.DeleteNodeLabelRequest + 3, // 73: persys.control.v1.AgentControl.SubmitAutomationSuggestion:input_type -> persys.control.v1.SubmitAutomationSuggestionRequest + 45, // 74: persys.control.v1.AgentControl.ListNodes:input_type -> persys.control.v1.ListNodesRequest + 46, // 75: persys.control.v1.AgentControl.GetNode:input_type -> persys.control.v1.GetNodeRequest + 50, // 76: persys.control.v1.AgentControl.ListWorkloads:input_type -> persys.control.v1.ListWorkloadsRequest + 51, // 77: persys.control.v1.AgentControl.GetWorkload:input_type -> persys.control.v1.GetWorkloadRequest + 55, // 78: persys.control.v1.AgentControl.GetClusterSummary:input_type -> persys.control.v1.GetClusterSummaryRequest + 57, // 79: persys.control.v1.AgentControl.ControlStream:input_type -> persys.control.v1.ControlMessage + 8, // 80: persys.control.v1.AgentControl.RegisterNode:output_type -> persys.control.v1.RegisterNodeResponse + 11, // 81: persys.control.v1.AgentControl.Heartbeat:output_type -> persys.control.v1.HeartbeatResponse + 13, // 82: persys.control.v1.AgentControl.ApplyWorkload:output_type -> persys.control.v1.ApplyWorkloadResponse + 15, // 83: persys.control.v1.AgentControl.DeleteWorkload:output_type -> persys.control.v1.DeleteWorkloadResponse + 31, // 84: persys.control.v1.AgentControl.RetryWorkload:output_type -> persys.control.v1.RetryWorkloadResponse + 33, // 85: persys.control.v1.AgentControl.DrainNode:output_type -> persys.control.v1.DrainNodeResponse + 35, // 86: persys.control.v1.AgentControl.UndrainNode:output_type -> persys.control.v1.UndrainNodeResponse + 38, // 87: persys.control.v1.AgentControl.TaintNode:output_type -> persys.control.v1.TaintNodeResponse + 40, // 88: persys.control.v1.AgentControl.UntaintNode:output_type -> persys.control.v1.UntaintNodeResponse + 42, // 89: persys.control.v1.AgentControl.SetNodeLabel:output_type -> persys.control.v1.SetNodeLabelResponse + 44, // 90: persys.control.v1.AgentControl.DeleteNodeLabel:output_type -> persys.control.v1.DeleteNodeLabelResponse + 4, // 91: persys.control.v1.AgentControl.SubmitAutomationSuggestion:output_type -> persys.control.v1.SubmitAutomationSuggestionResponse + 47, // 92: persys.control.v1.AgentControl.ListNodes:output_type -> persys.control.v1.ListNodesResponse + 48, // 93: persys.control.v1.AgentControl.GetNode:output_type -> persys.control.v1.GetNodeResponse + 52, // 94: persys.control.v1.AgentControl.ListWorkloads:output_type -> persys.control.v1.ListWorkloadsResponse + 53, // 95: persys.control.v1.AgentControl.GetWorkload:output_type -> persys.control.v1.GetWorkloadResponse + 56, // 96: persys.control.v1.AgentControl.GetClusterSummary:output_type -> persys.control.v1.GetClusterSummaryResponse + 57, // 97: persys.control.v1.AgentControl.ControlStream:output_type -> persys.control.v1.ControlMessage + 80, // [80:98] is the sub-list for method output_type + 62, // [62:80] is the sub-list for method input_type + 62, // [62:62] is the sub-list for extension type_name + 62, // [62:62] is the sub-list for extension extendee + 0, // [0:62] is the sub-list for field type_name } func init() { file_control_proto_init() } diff --git a/persys-scheduler/internal/controlv1/control_grpc.pb.go b/persys-scheduler/internal/controlv1/control_grpc.pb.go index b0a2355..4a70e36 100644 --- a/persys-scheduler/internal/controlv1/control_grpc.pb.go +++ b/persys-scheduler/internal/controlv1/control_grpc.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: -// - protoc-gen-go-grpc v1.6.2 +// - protoc-gen-go-grpc v1.6.1 // - protoc v3.21.12 // source: control.proto From ae88777a0e1a8d8e12afda36b1e17c57bf8f0f73 Mon Sep 17 00:00:00 2001 From: milx Date: Mon, 6 Jul 2026 21:59:10 +0330 Subject: [PATCH 15/18] Feat: Add pprof / switch to global pkg/certmanager --- persys-scheduler/cmd/scheduler/main.go | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/persys-scheduler/cmd/scheduler/main.go b/persys-scheduler/cmd/scheduler/main.go index d2ed68a..ec4a731 100644 --- a/persys-scheduler/cmd/scheduler/main.go +++ b/persys-scheduler/cmd/scheduler/main.go @@ -9,6 +9,7 @@ import ( "fmt" "net" "net/http" + _ "net/http/pprof" "os" "os/signal" "strconv" @@ -16,7 +17,8 @@ import ( "syscall" "time" - "github.com/persys-dev/persys-cloud/persys-scheduler/internal/auth" + // "github.com/persys-dev/persys-cloud/persys-scheduler/internal/auth" + "github.com/persys-dev/persys-cloud/pkg/certmanager" cfgpkg "github.com/persys-dev/persys-cloud/persys-scheduler/internal/config" controlv1 "github.com/persys-dev/persys-cloud/persys-scheduler/internal/controlv1" "github.com/persys-dev/persys-cloud/persys-scheduler/internal/grpcapi" @@ -52,7 +54,7 @@ func main() { var tlsConfig *tls.Config var certCancel context.CancelFunc if !cfg.Insecure { - certCfg := auth.Config{ + certCfg := certmanager.Config{ TLSEnabled: cfg.TLSEnabled, ExternalIP: cfg.ExternalIP, TLSCertPath: cfg.TLSCertPath, @@ -60,6 +62,7 @@ func main() { TLSCAPath: cfg.TLSCAPath, VaultEnabled: cfg.VaultEnabled, + VaultManagerAddr: cfg.VaultManagerAddr, VaultAddr: cfg.VaultAddr, VaultAuthMethod: cfg.VaultAuthMethod, VaultToken: cfg.VaultToken, @@ -74,7 +77,7 @@ func main() { BindHost: cfg.GRPCAddr, } - certMgr := auth.NewManager(certCfg, logger.Logger) + certMgr := certmanager.NewManager(certCfg, logger.Logger) certCtx, cancel := context.WithCancel(context.Background()) certCancel = cancel if err := certMgr.Start(certCtx); err != nil { @@ -152,6 +155,7 @@ func main() { }) _, _ = w.Write(payload) }), "scheduler.health")) + metricsMux.Handle("/debug/pprof/", http.DefaultServeMux) metricsServer := &http.Server{Addr: net.JoinHostPort(cfg.GRPCAddr, metricsPort), Handler: metricsMux} serverErrCh := make(chan error, 2) From cecdb4b119dd68ad468f0b3f1d17f73c8d493a3a Mon Sep 17 00:00:00 2001 From: milx Date: Mon, 6 Jul 2026 21:59:48 +0330 Subject: [PATCH 16/18] Add: meter stream configurations + Vault manager addr --- persys-scheduler/internal/config/config.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/persys-scheduler/internal/config/config.go b/persys-scheduler/internal/config/config.go index 886c9be..8ea944e 100644 --- a/persys-scheduler/internal/config/config.go +++ b/persys-scheduler/internal/config/config.go @@ -34,6 +34,14 @@ type Config struct { RedisEventTTL time.Duration RedisEventMaxEntries int64 + // Meter usage stream (Redis Streams ingestion feed for persys-meter). + // Publishing is best-effort: if Redis isn't configured/reachable, usage + // simply isn't published to the stream, but remains available as always + // via the scheduler's own ListWorkloads/GetWorkload gRPC API. + MeterStreamEnabled bool + MeterStreamName string + MeterStreamMaxLen int64 + // TLS TLSEnabled bool TLSCAPath string @@ -42,6 +50,7 @@ type Config struct { // Vault certificate manager VaultEnabled bool + VaultManagerAddr string VaultAddr string VaultAuthMethod string VaultToken string @@ -97,6 +106,9 @@ func Load(insecureFlag bool) (*Config, error) { RedisReconcileTTL: envDurationOrFlexibleSeconds("REDIS_RECONCILE_TTL", 24*time.Hour), RedisEventTTL: envDurationOrFlexibleSeconds("REDIS_EVENT_TTL", 24*time.Hour), RedisEventMaxEntries: int64(envIntOr("REDIS_EVENT_MAX_ENTRIES", 1000)), + MeterStreamEnabled: envBoolOr("METER_REDIS_STREAM_ENABLED", true), + MeterStreamName: envOr("METER_REDIS_STREAM", "persys:usage:stream"), + MeterStreamMaxLen: int64(envIntOr("METER_REDIS_STREAM_MAXLEN", 100000)), Domain: envOr("DOMAIN", "persys.local"), AgentsDiscoveryDomain: envOr("AGENTS_DISCOVERY_DOMAIN", "agents.persys.cloud"), SchedulerShardKey: envOr("SCHEDULER_SHARD_KEY", "genesis"), @@ -109,6 +121,7 @@ func Load(insecureFlag bool) (*Config, error) { TLSKeyPath: envOr("PERSYS_TLS_KEY", "/etc/persys/certs/persys_scheduler/persys_scheduler-key.key"), VaultEnabled: envBoolOr("PERSYS_VAULT_ENABLED", true), + VaultManagerAddr: envOr("PERSYS_VAULT_MANAGER_ADDR","vault-manager:50069"), VaultAddr: envOr("PERSYS_VAULT_ADDR", "http://localhost:8200"), VaultAuthMethod: strings.ToLower(envOr("PERSYS_VAULT_AUTH_METHOD", "token")), VaultToken: strings.TrimSpace(os.Getenv("PERSYS_VAULT_TOKEN")), From 5c056256df76c1e977ae4864ccb0dc65c5fff438 Mon Sep 17 00:00:00 2001 From: milx Date: Mon, 6 Jul 2026 22:00:02 +0330 Subject: [PATCH 17/18] Chore: Update Go mod --- persys-scheduler/go.mod | 20 +++++++------- persys-scheduler/go.sum | 59 +++++++++++++++++------------------------ 2 files changed, 34 insertions(+), 45 deletions(-) diff --git a/persys-scheduler/go.mod b/persys-scheduler/go.mod index 0ba853b..cc62d8a 100644 --- a/persys-scheduler/go.mod +++ b/persys-scheduler/go.mod @@ -1,13 +1,14 @@ module github.com/persys-dev/persys-cloud/persys-scheduler -go 1.24.1 +go 1.24.13 require ( github.com/google/uuid v1.6.0 - github.com/hashicorp/vault/api v1.16.0 + github.com/hashicorp/vault/api v1.22.0 + github.com/persys-dev/persys-cloud/pkg v0.0.0-20260701205454-9cb94822d71f github.com/prometheus/client_golang v1.11.1 github.com/redis/go-redis/v9 v9.19.0 - github.com/sirupsen/logrus v1.6.0 + github.com/sirupsen/logrus v1.9.4 go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.65.0 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1 go.opentelemetry.io/otel v1.40.0 @@ -15,7 +16,7 @@ require ( go.opentelemetry.io/otel/sdk v1.40.0 go.opentelemetry.io/otel/trace v1.40.0 go.uber.org/zap v1.17.0 - google.golang.org/grpc v1.78.0 + google.golang.org/grpc v1.79.1 ) require ( @@ -35,13 +36,12 @@ require ( github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect - github.com/hashicorp/go-retryablehttp v0.7.7 // indirect + github.com/hashicorp/go-retryablehttp v0.7.8 // indirect github.com/hashicorp/go-rootcerts v1.0.2 // indirect - github.com/hashicorp/go-secure-stdlib/parseutil v0.1.6 // indirect + github.com/hashicorp/go-secure-stdlib/parseutil v0.2.0 // indirect github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 // indirect - github.com/hashicorp/go-sockaddr v1.0.2 // indirect - github.com/hashicorp/hcl v1.0.0 // indirect - github.com/konsorten/go-windows-terminal-sequences v1.0.3 // indirect + github.com/hashicorp/go-sockaddr v1.0.7 // indirect + github.com/hashicorp/hcl v1.0.1-vault-7 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect @@ -57,7 +57,7 @@ require ( go.opentelemetry.io/proto/otlp v1.9.0 // indirect go.uber.org/atomic v1.11.0 // indirect go.uber.org/multierr v1.6.0 // indirect - golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1 // indirect + golang.org/x/time v0.12.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20260128011058-8636f8732409 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20260128011058-8636f8732409 // indirect ) diff --git a/persys-scheduler/go.sum b/persys-scheduler/go.sum index c11a7fd..3ea3cd1 100644 --- a/persys-scheduler/go.sum +++ b/persys-scheduler/go.sum @@ -4,12 +4,10 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c= github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= @@ -28,9 +26,8 @@ github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 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/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= -github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= +github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/go-jose/go-jose/v4 v4.1.3 h1:CVLmWDhDVRa6Mi/IgCgaopNosCaHz7zrMeF9MlZRkrs= @@ -47,8 +44,8 @@ github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ4 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/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-test/deep v1.0.2 h1:onZX1rnHT3Wv6cqNgYyFOOlgVKJrksuCMCRvJStbMYw= -github.com/go-test/deep v1.0.2/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= +github.com/go-test/deep v1.1.1 h1:0r/53hagsehfO4bzD2Pgr/+RgHqhmf+k1Bpse2cTu1U= +github.com/go-test/deep v1.1.1/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= @@ -84,24 +81,22 @@ github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9n github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k= github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= -github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= -github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU= -github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk= +github.com/hashicorp/go-retryablehttp v0.7.8 h1:ylXZWnqa7Lhqpk0L1P1LzDtGcCR0rPVUrx/c8Unxc48= +github.com/hashicorp/go-retryablehttp v0.7.8/go.mod h1:rjiScheydd+CxvumBsIrFKlx3iS0jrZ7LvzFGFmuKbw= github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc= github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= -github.com/hashicorp/go-secure-stdlib/parseutil v0.1.6 h1:om4Al8Oy7kCm/B86rLCLah4Dt5Aa0Fr5rYBG60OzwHQ= -github.com/hashicorp/go-secure-stdlib/parseutil v0.1.6/go.mod h1:QmrqtbKuxxSWTN3ETMPuB+VtEiBJ/A9XhoYGv8E1uD8= -github.com/hashicorp/go-secure-stdlib/strutil v0.1.1/go.mod h1:gKOamz3EwoIoJq7mlMIRBpVTAUn8qPCrEclOKKWhD3U= +github.com/hashicorp/go-secure-stdlib/parseutil v0.2.0 h1:U+kC2dOhMFQctRfhK0gRctKAPTloZdMU5ZJxaesJ/VM= +github.com/hashicorp/go-secure-stdlib/parseutil v0.2.0/go.mod h1:Ll013mhdmsVDuoIXVfBtvgGJsXDYkTw1kooNcoCXuE0= github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 h1:kes8mmyCpxJsI7FTwtzRqEy9CdjCtrXrXGuOpxEA7Ts= github.com/hashicorp/go-secure-stdlib/strutil v0.1.2/go.mod h1:Gou2R9+il93BqX25LAKCLuM+y9U2T4hlwvT1yprcna4= -github.com/hashicorp/go-sockaddr v1.0.2 h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0SyteCQc= -github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A= -github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= -github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/hashicorp/vault/api v1.16.0 h1:nbEYGJiAPGzT9U4oWgaaB0g+Rj8E59QuHKyA5LhwQN4= -github.com/hashicorp/vault/api v1.16.0/go.mod h1:KhuUhzOD8lDSk29AtzNjgAu2kxRA9jL9NAbkFlqvkBA= +github.com/hashicorp/go-sockaddr v1.0.7 h1:G+pTkSO01HpR5qCxg7lxfsFEZaG+C0VssTy/9dbT+Fw= +github.com/hashicorp/go-sockaddr v1.0.7/go.mod h1:FZQbEYa1pxkQ7WLpyXJ6cbjpT8q0YgQaK/JakXqGyWw= +github.com/hashicorp/hcl v1.0.1-vault-7 h1:ag5OxFVy3QYTFTJODRzTKVZ6xvdfLLCA1cy/Y6xGI0I= +github.com/hashicorp/hcl v1.0.1-vault-7/go.mod h1:XYhtn6ijBSAj6n4YqAaf7RBPS4I06AItNorpy+MoQNM= +github.com/hashicorp/vault/api v1.22.0 h1:+HYFquE35/B74fHoIeXlZIP2YADVboaPjaSicHEZiH0= +github.com/hashicorp/vault/api v1.22.0/go.mod h1:IUZA2cDvr4Ok3+NtK2Oq/r+lJeXkeCrHRmqdyWfpmGM= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= @@ -113,25 +108,19 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o github.com/klauspost/cpuid/v2 v2.2.10 h1:tBs3QSyvjDyFTq3uoc/9xFpCuOsJQFNPiAhYdw2skhE= github.com/klauspost/cpuid/v2 v2.2.10/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= -github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= -github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= +github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= -github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -140,13 +129,14 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/persys-dev/persys-cloud/pkg v0.0.0-20260701205454-9cb94822d71f h1:lKC6ntuESIn5yp2GcWQwyE+vMCh+lges3gbjF/Zxk3A= +github.com/persys-dev/persys-cloud/pkg v0.0.0-20260701205454-9cb94822d71f/go.mod h1:BKpHun2lgyknFnBmitTCxZ9pNXiF91HO2Kd2WDJAH8w= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 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/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= @@ -167,13 +157,13 @@ github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3x github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/redis/go-redis/v9 v9.19.0 h1:XPVaaPSnG6RhYf7p+rmSa9zZfeVAnWsH5h3lxthOm/k= github.com/redis/go-redis/v9 v9.19.0/go.mod h1:v/M13XI1PVCDcm01VtPFOADfZtHf8YW3baQf57KlIkA= -github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk= github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= +github.com/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w= +github.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC42RjbV2g= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 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= @@ -247,7 +237,6 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ 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/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -267,8 +256,8 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE= golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8= -golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1 h1:NusfzzA6yGQ+ua51ck7E3omNUX/JuqbFSaRGqU8CcLI= -golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE= +golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= 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= @@ -284,8 +273,8 @@ google.golang.org/genproto/googleapis/api v0.0.0-20260128011058-8636f8732409 h1: google.golang.org/genproto/googleapis/api v0.0.0-20260128011058-8636f8732409/go.mod h1:fl8J1IvUjCilwZzQowmw2b7HQB2eAuYBabMXzWurF+I= google.golang.org/genproto/googleapis/rpc v0.0.0-20260128011058-8636f8732409 h1:H86B94AW+VfJWDqFeEbBPhEtHzJwJfTbgE2lZa54ZAQ= google.golang.org/genproto/googleapis/rpc v0.0.0-20260128011058-8636f8732409/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ= -google.golang.org/grpc v1.78.0 h1:K1XZG/yGDJnzMdd/uZHAkVqJE+xIDOcmdSFZkBUicNc= -google.golang.org/grpc v1.78.0/go.mod h1:I47qjTo4OKbMkjA/aOOwxDIiPSBofUtQUI5EfpWvW7U= +google.golang.org/grpc v1.79.1 h1:zGhSi45ODB9/p3VAawt9a+O/MULLl9dpizzNNpq7flY= +google.golang.org/grpc v1.79.1/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= From 2e0cc734c63b7852eea0b5bda4de96488fbaabf6 Mon Sep 17 00:00:00 2001 From: milx Date: Mon, 6 Jul 2026 22:00:20 +0330 Subject: [PATCH 18/18] Chore: Update Submodules --- compute-agent | 2 +- persysctl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/compute-agent b/compute-agent index db5f442..cbdbc95 160000 --- a/compute-agent +++ b/compute-agent @@ -1 +1 @@ -Subproject commit db5f442131e461ec03764f3288c9c88a3baf20f4 +Subproject commit cbdbc959a786f1844cb975e8ecd8f3e4939b9026 diff --git a/persysctl b/persysctl index 4d7a3b6..674e8bd 160000 --- a/persysctl +++ b/persysctl @@ -1 +1 @@ -Subproject commit 4d7a3b6fe5b2339b8e62f8600ddfa53c443feb7d +Subproject commit 674e8bd8706aeb098defe7af865459557a3943f3