Manager: implement job check endpoint

This commit is contained in:
Sybren A. Stüvel 2022-10-20 13:13:35 +02:00
parent c439bc3a1e
commit 7a60bb70e0
2 changed files with 98 additions and 17 deletions

View File

@ -3,6 +3,7 @@ package api_impl
// SPDX-License-Identifier: GPL-3.0-or-later
import (
"context"
"errors"
"fmt"
"math"
@ -76,25 +77,10 @@ func (f *Flamenco) SubmitJob(e echo.Context) error {
logger.Info().Msg("new Flamenco job received")
ctx := e.Request().Context()
submittedJob := api.SubmittedJob(job)
// Replace the special "manager" platform with the Manager's actual platform.
if submittedJob.SubmitterPlatform == "manager" {
submittedJob.SubmitterPlatform = runtime.GOOS
}
if submittedJob.TypeEtag == nil || *submittedJob.TypeEtag == "" {
logger.Warn().Msg("job submitted without job type etag, refresh the job types in the Blender add-on")
}
// Before compiling the job, replace the two-way variables. This ensures all
// the tasks also use those.
replaceTwoWayVariables(f.config, &submittedJob)
authoredJob, err := f.jobCompiler.Compile(ctx, submittedJob)
authoredJob, err := f.compileSubmittedJob(ctx, logger, api.SubmittedJob(job))
switch {
case errors.Is(err, job_compilers.ErrJobTypeBadEtag):
logger.Warn().Err(err).Msg("rejecting submitted job because its settings are outdated, refresh the job type")
logger.Info().Err(err).Msg("rejecting submitted job because its settings are outdated, refresh the job type")
return sendAPIError(e, http.StatusPreconditionFailed, "rejecting job because its settings are outdated, refresh the job type")
case err != nil:
logger.Warn().Err(err).Msg("error compiling job")
@ -125,6 +111,55 @@ func (f *Flamenco) SubmitJob(e echo.Context) error {
return e.JSON(http.StatusOK, apiJob)
}
func (f *Flamenco) SubmitJobCheck(e echo.Context) error {
logger := requestLogger(e)
var job api.SubmitJobCheckJSONRequestBody
if err := e.Bind(&job); err != nil {
logger.Warn().Err(err).Msg("bad request received")
return sendAPIError(e, http.StatusBadRequest, "invalid format")
}
logger = logger.With().
Str("type", job.Type).
Str("name", job.Name).
Logger()
logger.Info().Msg("checking Flamenco job")
ctx := e.Request().Context()
submittedJob := api.SubmittedJob(job)
_, err := f.compileSubmittedJob(ctx, logger, submittedJob)
switch {
case errors.Is(err, job_compilers.ErrJobTypeBadEtag):
logger.Warn().Err(err).Msg("rejecting submitted job because its settings are outdated, refresh the job type")
return sendAPIError(e, http.StatusPreconditionFailed, "rejecting job because its settings are outdated, refresh the job type")
case err != nil:
logger.Warn().Err(err).Msg("error compiling job")
// TODO: make this a more specific error object for this API call.
return sendAPIError(e, http.StatusBadRequest, err.Error())
}
return e.NoContent(http.StatusNoContent)
}
// compileSubmittedJob performs some processing of the job and compiles it.
func (f *Flamenco) compileSubmittedJob(ctx context.Context, logger zerolog.Logger, submittedJob api.SubmittedJob) (*job_compilers.AuthoredJob, error) {
// Replace the special "manager" platform with the Manager's actual platform.
if submittedJob.SubmitterPlatform == "manager" {
submittedJob.SubmitterPlatform = runtime.GOOS
}
if submittedJob.TypeEtag == nil || *submittedJob.TypeEtag == "" {
logger.Warn().Msg("job submitted without job type etag, refresh the job types in the Blender add-on")
}
// Before compiling the job, replace the two-way variables. This ensures all
// the tasks also use those.
replaceTwoWayVariables(f.config, &submittedJob)
return f.jobCompiler.Compile(ctx, submittedJob)
}
// SetJobStatus is used by the web interface to change a job's status.
func (f *Flamenco) SetJobStatus(e echo.Context, jobID string) error {
logger := requestLogger(e)

View File

@ -283,6 +283,52 @@ func TestGetJobTypeUnknown(t *testing.T) {
})
}
func TestSubmitJobCheckWithEtag(t *testing.T) {
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()
mf := newMockedFlamenco(mockCtrl)
submittedJob := api.SubmittedJob{
Name: "поднео посао",
Type: "test",
Priority: 50,
SubmitterPlatform: "linux",
TypeEtag: ptr("bad etag"),
}
mf.jobCompiler.EXPECT().Compile(gomock.Any(), submittedJob).
Return(nil, job_compilers.ErrJobTypeBadEtag)
mf.expectConvertTwoWayVariables(t, config.VariableAudienceWorkers, "linux", map[string]string{}).AnyTimes()
// Expect the job to be rejected.
{
echoCtx := mf.prepareMockedJSONRequest(submittedJob)
err := mf.flamenco.SubmitJobCheck(echoCtx)
assert.NoError(t, err)
assertResponseAPIError(t, echoCtx,
http.StatusPreconditionFailed, "rejecting job because its settings are outdated, refresh the job type")
}
// Expect the job compiler to be called.
authoredJob := job_compilers.AuthoredJob{
JobID: "afc47568-bd9d-4368-8016-e91d945db36d",
Name: submittedJob.Name,
JobType: submittedJob.Type,
Priority: submittedJob.Priority,
Status: api.JobStatusUnderConstruction,
Created: mf.clock.Now(),
}
mf.jobCompiler.EXPECT().Compile(gomock.Any(), gomock.Any()).Return(&authoredJob, nil)
{ // Expect the job with the right etag to be accepted.
submittedJob.TypeEtag = ptr("correct etag")
echoCtx := mf.prepareMockedJSONRequest(submittedJob)
err := mf.flamenco.SubmitJobCheck(echoCtx)
assert.NoError(t, err)
}
}
func TestGetJobTypeError(t *testing.T) {
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()