6677a103c2
This changeset configures the RPC rate metrics that were added in #15515 to all the RPCs that support authenticated HTTP API requests. These endpoints already configured with pre-forwarding authentication in #15870, and a handful of others were done already as part of the proof-of-concept work. So this changeset is entirely copy-and-pasting one method call into a whole mess of handlers. Upcoming PRs will wire up pre-forwarding auth and rate metrics for the remaining set of RPCs that have no API consumers or aren't authenticated, in smaller chunks that can be more thoughtfully reviewed.
81 lines
2.1 KiB
Go
81 lines
2.1 KiB
Go
package nomad
|
|
|
|
import (
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/armon/go-metrics"
|
|
"github.com/hashicorp/go-hclog"
|
|
"github.com/hashicorp/go-memdb"
|
|
|
|
"github.com/hashicorp/nomad/acl"
|
|
"github.com/hashicorp/nomad/nomad/structs"
|
|
)
|
|
|
|
// Periodic endpoint is used for periodic job interactions
|
|
type Periodic struct {
|
|
srv *Server
|
|
ctx *RPCContext
|
|
logger hclog.Logger
|
|
}
|
|
|
|
func NewPeriodicEndpoint(srv *Server, ctx *RPCContext) *Periodic {
|
|
return &Periodic{srv: srv, ctx: ctx, logger: srv.logger.Named("periodic")}
|
|
}
|
|
|
|
// Force is used to force a new instance of a periodic job
|
|
func (p *Periodic) Force(args *structs.PeriodicForceRequest, reply *structs.PeriodicForceResponse) error {
|
|
|
|
authErr := p.srv.Authenticate(p.ctx, args)
|
|
if done, err := p.srv.forward("Periodic.Force", args, args, reply); done {
|
|
return err
|
|
}
|
|
p.srv.MeasureRPCRate("periodic", structs.RateMetricWrite, args)
|
|
if authErr != nil {
|
|
return structs.ErrPermissionDenied
|
|
}
|
|
defer metrics.MeasureSince([]string{"nomad", "periodic", "force"}, time.Now())
|
|
|
|
// Check for write-job permissions
|
|
if aclObj, err := p.srv.ResolveACL(args); err != nil {
|
|
return err
|
|
} else if aclObj != nil && !aclObj.AllowNsOp(args.RequestNamespace(), acl.NamespaceCapabilityDispatchJob) && !aclObj.AllowNsOp(args.RequestNamespace(), acl.NamespaceCapabilitySubmitJob) {
|
|
return structs.ErrPermissionDenied
|
|
}
|
|
|
|
// Validate the arguments
|
|
if args.JobID == "" {
|
|
return fmt.Errorf("missing job ID for evaluation")
|
|
}
|
|
|
|
// Lookup the job
|
|
snap, err := p.srv.fsm.State().Snapshot()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
ws := memdb.NewWatchSet()
|
|
job, err := snap.JobByID(ws, args.RequestNamespace(), args.JobID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if job == nil {
|
|
return fmt.Errorf("job not found")
|
|
}
|
|
|
|
if !job.IsPeriodic() {
|
|
return fmt.Errorf("can't force launch non-periodic job")
|
|
}
|
|
|
|
// Force run the job.
|
|
eval, err := p.srv.periodicDispatcher.ForceRun(args.RequestNamespace(), job.ID)
|
|
if err != nil {
|
|
return fmt.Errorf("force launch for job %q failed: %v", job.ID, err)
|
|
}
|
|
|
|
reply.EvalID = eval.ID
|
|
reply.EvalCreateIndex = eval.CreateIndex
|
|
reply.Index = eval.CreateIndex
|
|
return nil
|
|
}
|