// Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: MPL-2.0 package nomad import ( "time" metrics "github.com/armon/go-metrics" log "github.com/hashicorp/go-hclog" nstructs "github.com/hashicorp/nomad/nomad/structs" "github.com/hashicorp/nomad/client/structs" ) // ClientStats is used to forward RPC requests to the targed Nomad client's // ClientStats endpoint. type ClientStats struct { srv *Server logger log.Logger } func NewClientStatsEndpoint(srv *Server) *ClientStats { return &ClientStats{srv: srv, logger: srv.logger.Named("client_stats")} } func (s *ClientStats) Stats(args *nstructs.NodeSpecificRequest, reply *structs.ClientStatsResponse) error { // We only allow stale reads since the only potentially stale information is // the Node registration and the cost is fairly high for adding another hope // in the forwarding chain. args.QueryOptions.AllowStale = true authErr := s.srv.Authenticate(nil, args) // Potentially forward to a different region. if done, err := s.srv.forward("ClientStats.Stats", args, args, reply); done { return err } s.srv.MeasureRPCRate("client_stats", nstructs.RateMetricRead, args) if authErr != nil { return nstructs.ErrPermissionDenied } defer metrics.MeasureSince([]string{"nomad", "client_stats", "stats"}, time.Now()) // Check node read permissions if aclObj, err := s.srv.ResolveACL(args); err != nil { return err } else if aclObj != nil && !aclObj.AllowNodeRead() { return nstructs.ErrPermissionDenied } return s.srv.forwardClientRPC("ClientStats.Stats", args.NodeID, args, reply) }