mirror of
https://github.com/ultravioletrs/cocos.git
synced 2026-08-07 07:14:50 +00:00
b44780df95
CI / lint (push) Has been cancelled
CI / test (agent) (push) Has been cancelled
CI / test (cli) (push) Has been cancelled
CI / test (cmd) (push) Has been cancelled
CI / test (internal) (push) Has been cancelled
CI / test (manager, true) (push) Has been cancelled
CI / test (pkg) (push) Has been cancelled
CI / upload-coverage (push) Has been cancelled
* feat: Enhance OCI image extraction to return algorithm and requirements paths, and add deferred cleanup for temporary files. Signed-off-by: Sammy Oina <sammyoina@gmail.com> * feat: implement deterministic zipping and enhance checksum verification for resources Signed-off-by: Sammy Oina <sammyoina@gmail.com> * feat: Update component build sources, add gRPC health checks to the CVM server, and refine algorithm argument handling and documentation. Signed-off-by: Sammy Oina <sammyoina@gmail.com> * docs: Update remote resources testing guide with `sudo` for KBS, algorithm result saving, `requirements.txt`, and `algo-args` for RVPS. Signed-off-by: Sammy Oina <sammyoina@gmail.com> * refactor: Explicitly ignore `stderr.Write` return values and add minor whitespace in tests. Signed-off-by: Sammy Oina <sammyoina@gmail.com> * test: add comprehensive error path and edge case tests for file, zip, OCI, and agent components. Signed-off-by: Sammy Oina <sammyoina@gmail.com> * feat: Add mutexes for thread-safe algorithm execution and expand recognized data file extensions to include common archive formats. Signed-off-by: Sammy Oina <sammyoina@gmail.com> * feat: Add OCI extraction tests for Python algorithms and multi-layer datasets, refactor algorithm execution for testability, and enhance algorithm stop and error handling tests. Signed-off-by: Sammy Oina <sammyoina@gmail.com> * test: Add error assertions to OCI extraction test helpers and remove an unused mock exec command. Signed-off-by: Sammy Oina <sammyoina@gmail.com> * test: Improve error handling test coverage for algorithm execution and OCI resource extraction. Signed-off-by: Sammy Oina <sammyoina@gmail.com> * fix: Improve algorithm process termination, enhance computation error handling, and add concurrency safety to agent service. Signed-off-by: Sammy Oina <sammyoina@gmail.com> --------- Signed-off-by: Sammy Oina <sammyoina@gmail.com>
120 lines
3.0 KiB
Go
120 lines
3.0 KiB
Go
// Copyright (c) Ultraviolet
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package server
|
|
|
|
import (
|
|
"fmt"
|
|
"log/slog"
|
|
"net"
|
|
"os"
|
|
"sync"
|
|
|
|
"github.com/ultravioletrs/cocos/agent"
|
|
agentgrpc "github.com/ultravioletrs/cocos/agent/api/grpc"
|
|
"github.com/ultravioletrs/cocos/agent/auth"
|
|
"go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
|
|
"google.golang.org/grpc"
|
|
"google.golang.org/grpc/credentials/insecure"
|
|
"google.golang.org/grpc/health"
|
|
"google.golang.org/grpc/health/grpc_health_v1"
|
|
"google.golang.org/grpc/reflection"
|
|
)
|
|
|
|
const (
|
|
svcName = "agent"
|
|
defSvcGRPCSocket = "/run/cocos/agent.sock"
|
|
)
|
|
|
|
type AgentServer interface {
|
|
Start(cfg agent.AgentConfig, cmp agent.Computation) error
|
|
Stop() error
|
|
}
|
|
|
|
type agentServer struct {
|
|
mu sync.Mutex
|
|
gs *grpc.Server
|
|
logger *slog.Logger
|
|
svc agent.Service
|
|
host string
|
|
}
|
|
|
|
func NewServer(logger *slog.Logger, svc agent.Service, host string) AgentServer {
|
|
return &agentServer{
|
|
logger: logger,
|
|
svc: svc,
|
|
host: host,
|
|
}
|
|
}
|
|
|
|
func (as *agentServer) Start(cfg agent.AgentConfig, cmp agent.Computation) error {
|
|
authSvc, err := auth.New(cmp)
|
|
if err != nil {
|
|
as.logger.WithGroup(cmp.ID).Error(fmt.Sprintf("failed to create auth service %s", err.Error()))
|
|
return err
|
|
}
|
|
|
|
grpcServerOptions := []grpc.ServerOption{
|
|
grpc.StatsHandler(otelgrpc.NewServerHandler()),
|
|
}
|
|
|
|
// Add authentication interceptors
|
|
unary, stream := agentgrpc.NewAuthInterceptor(authSvc)
|
|
grpcServerOptions = append(grpcServerOptions, grpc.UnaryInterceptor(unary))
|
|
grpcServerOptions = append(grpcServerOptions, grpc.StreamInterceptor(stream))
|
|
|
|
// Internal Unix socket is pure plaintext HTTP/2; Ingress Proxy handles external aTLS termination
|
|
grpcServerOptions = append(grpcServerOptions, grpc.Creds(insecure.NewCredentials()))
|
|
|
|
as.mu.Lock()
|
|
as.gs = grpc.NewServer(grpcServerOptions...)
|
|
gs := as.gs
|
|
as.mu.Unlock()
|
|
|
|
reflection.Register(gs)
|
|
agent.RegisterAgentServiceServer(gs, agentgrpc.NewServer(as.svc))
|
|
|
|
healthServer := health.NewServer()
|
|
healthServer.SetServingStatus("agent", grpc_health_v1.HealthCheckResponse_SERVING)
|
|
grpc_health_v1.RegisterHealthServer(gs, healthServer)
|
|
|
|
socketPath := as.host
|
|
if socketPath == "" || socketPath == "0.0.0.0" {
|
|
socketPath = defSvcGRPCSocket
|
|
}
|
|
|
|
var listener net.Listener
|
|
if socketPath[0] == '/' || socketPath[0] == '.' {
|
|
// Remove existing socket file if it exists
|
|
_ = os.Remove(socketPath)
|
|
listener, err = net.Listen("unix", socketPath)
|
|
} else {
|
|
listener, err = net.Listen("tcp", socketPath)
|
|
}
|
|
|
|
if err != nil {
|
|
as.logger.Error(fmt.Sprintf("failed to listen on %s: %s", socketPath, err))
|
|
return err
|
|
}
|
|
|
|
as.logger.Info(fmt.Sprintf("agent service gRPC server listening at %s without TLS", socketPath))
|
|
|
|
go func() {
|
|
err := gs.Serve(listener)
|
|
if err != nil && err != grpc.ErrServerStopped {
|
|
as.logger.Error(fmt.Sprintf("failed to start grpc server %s", err.Error()))
|
|
}
|
|
}()
|
|
|
|
return nil
|
|
}
|
|
|
|
func (as *agentServer) Stop() error {
|
|
as.mu.Lock()
|
|
defer as.mu.Unlock()
|
|
if as.gs != nil {
|
|
as.gs.GracefulStop()
|
|
}
|
|
return nil
|
|
}
|