pkg/jobmanager/job.go (113 lines of code) (raw):
// Copyright (c) Facebook, Inc. and its affiliates.
//
// This source code is licensed under the MIT license found in the
// LICENSE file in the root directory of this source tree.
package jobmanager
import (
"encoding/json"
"errors"
"fmt"
"time"
pkg_config "github.com/facebookincubator/contest/pkg/config"
"github.com/facebookincubator/contest/pkg/job"
"github.com/facebookincubator/contest/pkg/pluginregistry"
"github.com/facebookincubator/contest/pkg/storage/limits"
"github.com/facebookincubator/contest/pkg/test"
"github.com/facebookincubator/contest/pkg/xcontext"
)
func newJob(ctx xcontext.Context, registry *pluginregistry.PluginRegistry, jobDescriptor *job.Descriptor, resolver stepsResolver) (*job.Job, error) {
if resolver == nil {
return nil, fmt.Errorf("cannot create job without resolver")
}
if jobDescriptor == nil {
return nil, errors.New("JobDescriptor cannot be nil")
}
jobName := jobDescriptor.JobName
if err := limits.NewValidator().ValidateJobName(jobName); err != nil {
return nil, err
}
if err := jobDescriptor.Validate(); err != nil {
return nil, fmt.Errorf("could not validate job descriptor: %w", err)
}
runReportersBundle, finalReportersBundle, err := newReportingBundles(registry, jobDescriptor)
if err != nil {
return nil, fmt.Errorf("error while building reporters bundles: %w", err)
}
tests := make([]*test.Test, 0, len(jobDescriptor.TestDescriptors))
stepsDescriptors, err := resolver.GetStepsDescriptors(ctx)
if err != nil {
return nil, fmt.Errorf("could not get steps descriptors: %w", err)
}
if len(stepsDescriptors) != len(jobDescriptor.TestDescriptors) {
return nil, fmt.Errorf("length of steps descriptor must match lenght of test descriptors")
}
for index, td := range jobDescriptor.TestDescriptors {
thisTestStepsDescriptors := stepsDescriptors[index]
if err := td.Validate(); err != nil {
return nil, fmt.Errorf("could not validate test descriptor: %w", err)
}
bundleTargetManager, err := registry.NewTargetManagerBundle(td)
if err != nil {
return nil, err
}
bundleTestFetcher, err := registry.NewTestFetcherBundle(ctx, td)
if err != nil {
return nil, err
}
bundleTest, err := newStepBundles(ctx, thisTestStepsDescriptors, registry)
if err != nil {
return nil, fmt.Errorf("could not create step bundles: %w", err)
}
testName := thisTestStepsDescriptors.TestName
if err := limits.NewValidator().ValidateTestName(testName); err != nil {
return nil, err
}
test := test.Test{
Name: testName,
TargetManagerBundle: bundleTargetManager,
TestFetcherBundle: bundleTestFetcher,
TestStepsBundles: bundleTest,
}
tests = append(tests, &test)
}
extendedDescriptor := job.ExtendedDescriptor{
Descriptor: *jobDescriptor,
TestStepsDescriptors: stepsDescriptors,
}
var targetManagerAcquireTimeout = pkg_config.TargetManagerAcquireTimeout
if jobDescriptor.TargetManagerAcquireTimeout != nil {
targetManagerAcquireTimeout = time.Duration(*jobDescriptor.TargetManagerAcquireTimeout)
}
var targetManagerReleaseTimeout = pkg_config.TargetManagerReleaseTimeout
if jobDescriptor.TargetManagerReleaseTimeout != nil {
targetManagerReleaseTimeout = time.Duration(*jobDescriptor.TargetManagerReleaseTimeout)
}
// The ID of the job object defaults to zero, and it's populated as soon as the job
// is persisted in storage.
job := job.Job{
ExtendedDescriptor: &extendedDescriptor,
Name: jobDescriptor.JobName,
Tags: jobDescriptor.Tags,
Runs: jobDescriptor.Runs,
RunInterval: time.Duration(jobDescriptor.RunInterval),
TargetManagerAcquireTimeout: targetManagerAcquireTimeout,
TargetManagerReleaseTimeout: targetManagerReleaseTimeout,
Tests: tests,
RunReporterBundles: runReportersBundle,
FinalReporterBundles: finalReportersBundle,
}
return &job, nil
}
// NewJobFromDescriptor creates a job object from a job descriptor
func NewJobFromDescriptor(ctx xcontext.Context, registry *pluginregistry.PluginRegistry, jobDescriptor *job.Descriptor) (*job.Job, error) {
resolver := fetcherStepsResolver{jobDescriptor: jobDescriptor, registry: registry}
return newJob(ctx, registry, jobDescriptor, resolver)
}
// NewJobFromExtendedDescriptor creates a job object from an extended job descriptor
func NewJobFromExtendedDescriptor(ctx xcontext.Context, registry *pluginregistry.PluginRegistry, jobDescriptor *job.ExtendedDescriptor) (*job.Job, error) {
resolver := literalStepsResolver{stepsDescriptors: jobDescriptor.TestStepsDescriptors}
return newJob(ctx, registry, &jobDescriptor.Descriptor, resolver)
}
// NewJobFromJSONDescriptor builds a descriptor object from a JSON serialization
func NewJobFromJSONDescriptor(ctx xcontext.Context, registry *pluginregistry.PluginRegistry, jobDescriptorJSON string) (*job.Job, error) {
var jd *job.Descriptor
if err := json.Unmarshal([]byte(jobDescriptorJSON), &jd); err != nil {
return nil, err
}
j, err := NewJobFromDescriptor(ctx, registry, jd)
if err != nil {
return nil, err
}
return j, nil
}