From fa27190c01fe46745a171089c65bee498675e3e3 Mon Sep 17 00:00:00 2001 From: Walid Baruni Date: Wed, 22 May 2024 18:04:51 +0300 Subject: [PATCH] make job name optional (#4005) --- pkg/models/job.go | 4 + pkg/models/job_test.go | 164 ++++++++++++++++++++++++++++++++++++ testdata/data.go | 11 ++- testdata/jobs/nameless.yaml | 6 ++ 4 files changed, 183 insertions(+), 2 deletions(-) create mode 100644 pkg/models/job_test.go create mode 100644 testdata/jobs/nameless.yaml diff --git a/pkg/models/job.go b/pkg/models/job.go index 4a6639b348..c8c9c0d52d 100644 --- a/pkg/models/job.go +++ b/pkg/models/job.go @@ -162,6 +162,10 @@ func (j *Job) Normalize() { j.Namespace = DefaultNamespace } + if j.Name == "" { + j.Name = j.ID + } + if (j.Type == JobTypeDaemon || j.Type == JobTypeOps) && j.Count == 0 { j.Count = 1 } diff --git a/pkg/models/job_test.go b/pkg/models/job_test.go new file mode 100644 index 0000000000..0767b711b6 --- /dev/null +++ b/pkg/models/job_test.go @@ -0,0 +1,164 @@ +//go:build unit || !integration + +package models_test + +import ( + "testing" + "time" + + "github.com/stretchr/testify/suite" + + "github.com/bacalhau-project/bacalhau/pkg/models" + "github.com/bacalhau-project/bacalhau/pkg/test/mock" +) + +type JobTestSuite struct { + suite.Suite +} + +func (suite *JobTestSuite) TestJobNormalization() { + testCases := []struct { + jobType string + expectedCount int + }{ + {models.JobTypeBatch, 0}, + {models.JobTypeService, 0}, + {models.JobTypeOps, 1}, + {models.JobTypeDaemon, 1}, + } + + for _, tc := range testCases { + job := &models.Job{ + ID: "test-job", + Type: tc.jobType, + Name: "", + Namespace: "", + Meta: nil, + Labels: nil, + Constraints: nil, + Tasks: nil, + } + + job.Normalize() + + suite.Equal(models.DefaultNamespace, job.Namespace) + suite.Equal("test-job", job.Name) + suite.Equal(tc.jobType, job.Type) + suite.Equal(tc.expectedCount, job.Count) + suite.NotNil(job.Meta) + suite.NotNil(job.Labels) + suite.NotNil(job.Constraints) + suite.NotNil(job.Tasks) + } +} + +func (suite *JobTestSuite) TestJobValidation() { + job := &models.Job{ + ID: "invalid job id", + Name: "", + Namespace: "", + } + + err := job.Validate() + suite.Error(err) + suite.Contains(err.Error(), "missing job name") + suite.Contains(err.Error(), "job ID contains a space") + suite.Contains(err.Error(), "job must be in a namespace") +} + +func (suite *JobTestSuite) TestJobSanitization() { + job := &models.Job{ + ID: "test-job", + Name: "test-job", + Namespace: "default", + State: models.State[models.JobStateType]{StateType: models.JobStateTypeRunning}, + Revision: 1, + Version: 1, + CreateTime: time.Now().UnixNano(), + ModifyTime: time.Now().UnixNano(), + Tasks: []*models.Task{ + { + Name: "test-task", + }, + }, + } + + warnings := job.SanitizeSubmission() + + suite.NotEmpty(warnings) + suite.Equal(models.JobStateTypeUndefined, job.State.StateType) + suite.Equal(uint64(0), job.Revision) + suite.Equal(uint64(0), job.Version) + suite.Equal(int64(0), job.CreateTime) + suite.Equal(int64(0), job.ModifyTime) +} + +func (suite *JobTestSuite) TestJobCopy() { + job := mock.Job() + cpy := job.Copy() + + suite.NotNil(cpy) + suite.Equal(job, cpy, "The job and its copy should be deeply equal") + suite.NotSame(job, cpy, "The job and its copy should not be the same instance") + + // Ensure nested objects are deeply copied + for i := range job.Tasks { + suite.NotSame(job.Tasks[i], cpy.Tasks[i], "The tasks in the job and its copy should not be the same instance") + } +} + +func (suite *JobTestSuite) TestJobTask() { + job := mock.Job() + suite.Equal(job.Tasks[0], job.Task()) +} + +func (suite *JobTestSuite) TestIsTerminal() { + job := &models.Job{ + State: models.State[models.JobStateType]{StateType: models.JobStateTypeCompleted}, + } + suite.True(job.IsTerminal()) + + job.State.StateType = models.JobStateTypeFailed + suite.True(job.IsTerminal()) + + job.State.StateType = models.JobStateTypeStopped + suite.True(job.IsTerminal()) + + job.State.StateType = models.JobStateTypeRunning + suite.False(job.IsTerminal()) +} + +func (suite *JobTestSuite) TestNamespacedID() { + job := mock.Job() + nsID := job.NamespacedID() + suite.Equal(job.ID, nsID.ID) + suite.Equal(job.Namespace, nsID.Namespace) +} + +func (suite *JobTestSuite) TestAllStorageTypes() { + job := mock.Job() + job.Tasks = []*models.Task{ + { + InputSources: []*models.InputSource{ + { + Source: &models.SpecConfig{ + Type: "s3", + }, + }, + { + Source: &models.SpecConfig{ + Type: "url", + }, + }, + }, + }, + } + + storageTypes := job.AllStorageTypes() + suite.ElementsMatch([]string{"s3", "url"}, storageTypes) +} + +// Run the test suite +func TestJobTestSuite(t *testing.T) { + suite.Run(t, new(JobTestSuite)) +} diff --git a/testdata/data.go b/testdata/data.go index 2f8837534e..61b8fd1375 100644 --- a/testdata/data.go +++ b/testdata/data.go @@ -6,11 +6,12 @@ import ( "os" "testing" - "github.com/bacalhau-project/bacalhau/pkg/lib/marshaller" - "github.com/bacalhau-project/bacalhau/pkg/models" "github.com/ipld/go-ipld-prime/codec/json" "github.com/stretchr/testify/require" + "github.com/bacalhau-project/bacalhau/pkg/lib/marshaller" + "github.com/bacalhau-project/bacalhau/pkg/models" + "github.com/bacalhau-project/bacalhau/pkg/model" ) @@ -65,6 +66,9 @@ var dockerS3YAML []byte //go:embed jobs/empty.yaml var emptyJobYAML []byte +//go:embed jobs/nameless.yaml +var namelessJobYAML []byte + //go:embed jobs/noop.yaml var noopJobYAML []byte @@ -92,6 +96,7 @@ var ( DockerOutputJSON *Fixture DockerS3YAML *Fixture EmptyJobYAML *Fixture + NamelessJobYAML *Fixture NoopJobYAML *Fixture WasmJobYAML *Fixture ) @@ -121,6 +126,7 @@ func init() { DockerOutputJSON = NewJobFixture("docker with output json", dockerOutputJSON, false) DockerS3YAML = NewJobFixture("docker with s3", dockerS3YAML, false) EmptyJobYAML = NewJobFixture("empty job", emptyJobYAML, true) + NamelessJobYAML = NewJobFixture("nameless job", namelessJobYAML, false) NoopJobYAML = NewJobFixture("noop", noopJobYAML, false) WasmJobYAML = NewJobFixture("wasm", wasmJobYAML, false) } @@ -139,6 +145,7 @@ func AllFixtures() []*Fixture { DockerOutputJSON, DockerS3YAML, EmptyJobYAML, + NamelessJobYAML, NoopJobYAML, WasmJobYAML, } diff --git a/testdata/jobs/nameless.yaml b/testdata/jobs/nameless.yaml new file mode 100644 index 0000000000..c0722d6aee --- /dev/null +++ b/testdata/jobs/nameless.yaml @@ -0,0 +1,6 @@ +Type: batch +Count: 1 +Tasks: + - Name: main + Engine: + Type: noop