feat: big ahh commit
- agent+proto+backend: transfer service status - agent: fix returning empty message on nonzero exit status - backend: refactor collector+commander and handlers dependent on them: implement agent accounting via grpc stats handler
This commit is contained in:
+1
-1
@@ -3,7 +3,7 @@ module gitea.d3m0k1d.ru/d3m0k1d/HellreigN/agent
|
||||
go 1.26.1
|
||||
|
||||
require (
|
||||
gitea.d3m0k1d.ru/d3m0k1d/HellreigN/proto v0.0.0-20260403214837-94be9799f47d
|
||||
gitea.d3m0k1d.ru/d3m0k1d/HellreigN/proto v0.0.0-20260404174628-3389df740c20
|
||||
github.com/hpcloud/tail v1.0.0
|
||||
github.com/samber/lo v1.53.0
|
||||
golang.org/x/sync v0.20.0
|
||||
|
||||
@@ -47,8 +47,14 @@ func (*CommandExecutor) Execute(command *proto.Command) (fc *proto.FinishedComma
|
||||
_, err := io.Copy(stderrbuf, stderr)
|
||||
return err
|
||||
})
|
||||
if err := cmd.Wait(); err != nil {
|
||||
return nil, err
|
||||
if waitErr := cmd.Wait(); waitErr != nil {
|
||||
var exitErr *exec.ExitError
|
||||
if !errors.As(waitErr, &exitErr) {
|
||||
return nil, waitErr
|
||||
}
|
||||
fc.Status = int32(exitErr.ExitCode())
|
||||
} else {
|
||||
fc.Status = int32(cmd.ProcessState.ExitCode())
|
||||
}
|
||||
if err := eg.Wait(); err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -22,6 +22,7 @@ import (
|
||||
"github.com/samber/lo"
|
||||
"golang.org/x/sync/errgroup"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials"
|
||||
"google.golang.org/grpc/metadata"
|
||||
)
|
||||
|
||||
@@ -110,6 +111,13 @@ func main() {
|
||||
return ccli.HandleCommands(ctx, grpcAddr, creds)
|
||||
})
|
||||
|
||||
// Start services update stream
|
||||
if len(cfg.Services) > 0 {
|
||||
wg.Go(func() error {
|
||||
return reportServices(ctx, grpcAddr, creds, cfg.Label, cfg.Services, lgr)
|
||||
})
|
||||
}
|
||||
|
||||
// Start log collectors
|
||||
if len(cfg.Services) > 0 {
|
||||
wg.Go(func() error {
|
||||
@@ -301,3 +309,52 @@ func reconnectStream(
|
||||
|
||||
return fmt.Errorf("failed to reconnect after 5 attempts for service %s", service)
|
||||
}
|
||||
|
||||
// reportServices periodically sends service status updates to the backend via gRPC.
|
||||
// For now, all configured services are reported as "up" every 5 seconds.
|
||||
func reportServices(
|
||||
ctx context.Context,
|
||||
grpcAddr string,
|
||||
creds credentials.TransportCredentials,
|
||||
label string,
|
||||
services []config.ServiceConfig,
|
||||
lgr *logger.Logger,
|
||||
) error {
|
||||
conn, err := grpc.NewClient(grpcAddr, grpc.WithTransportCredentials(creds))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to connect for services report: %w", err)
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
ccli := proto.NewCollectorClient(conn)
|
||||
ticker := time.NewTicker(5 * time.Second)
|
||||
defer ticker.Stop()
|
||||
|
||||
// Send immediately on start, then every 5 seconds
|
||||
for {
|
||||
svcUpdates := make([]*proto.ServicesUpdate_ServiceUpdate, 0, len(services))
|
||||
for _, svc := range services {
|
||||
svcUpdates = append(svcUpdates, &proto.ServicesUpdate_ServiceUpdate{
|
||||
Name: svc.Name,
|
||||
Status: "up",
|
||||
})
|
||||
}
|
||||
|
||||
md := metadata.New(map[string]string{"whoami": label})
|
||||
_, err := ccli.ReportServices(
|
||||
metadata.NewOutgoingContext(ctx, md),
|
||||
&proto.ServicesUpdate{Services: svcUpdates},
|
||||
)
|
||||
if err != nil {
|
||||
lgr.Warn("Failed to report services", "err", err)
|
||||
} else {
|
||||
lgr.Debug("Services reported successfully", "count", len(services))
|
||||
}
|
||||
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
case <-ticker.C:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user