Merge pull request #12462 from chlins/feat/preheat-execution-api

Feat/preheat execution api
This commit is contained in:
疯魔慕薇 2020-07-13 20:55:12 +08:00 committed by GitHub
commit 3b43162b6d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 840 additions and 7 deletions

View File

@ -1013,6 +1013,151 @@ paths:
$ref: '#/responses/403'
'500':
$ref: '#/responses/500'
/projects/{project_name}/preheat/policies/{preheat_policy_name}/executions:
get:
summary: List executions for the given policy
description: List executions for the given policy
tags:
- preheat
operationId: ListExecutions
parameters:
- $ref: '#/parameters/requestId'
- $ref: '#/parameters/projectName'
- $ref: '#/parameters/preheatPolicyName'
- $ref: '#/parameters/page'
- $ref: '#/parameters/pageSize'
- $ref: '#/parameters/query'
responses:
'200':
description: List executions success
schema:
type: array
items:
$ref: '#/definitions/Execution'
'400':
$ref: '#/responses/400'
'401':
$ref: '#/responses/401'
'404':
$ref: '#/responses/404'
'403':
$ref: '#/responses/403'
'500':
$ref: '#/responses/500'
/projects/{project_name}/preheat/policies/{preheat_policy_name}/executions/{execution_id}:
get:
summary: Get a execution detail by id
description: Get a execution detail by id
tags:
- preheat
operationId: GetExecution
parameters:
- $ref: '#/parameters/requestId'
- $ref: '#/parameters/projectName'
- $ref: '#/parameters/preheatPolicyName'
- $ref: '#/parameters/executionId'
responses:
'200':
description: Get execution success
schema:
$ref: '#/definitions/Execution'
'400':
$ref: '#/responses/400'
'401':
$ref: '#/responses/401'
'404':
$ref: '#/responses/404'
'403':
$ref: '#/responses/403'
'500':
$ref: '#/responses/500'
patch:
summary: Stop a execution
description: Stop a execution
tags:
- preheat
operationId: StopExecution
parameters:
- $ref: '#/parameters/requestId'
- $ref: '#/parameters/projectName'
- $ref: '#/parameters/preheatPolicyName'
- $ref: '#/parameters/executionId'
- name: execution
description: The data of execution
in: body
required: true
schema:
$ref: '#/definitions/Execution'
responses:
'200':
$ref: '#/responses/200'
'400':
$ref: '#/responses/400'
'401':
$ref: '#/responses/401'
'404':
$ref: '#/responses/404'
'403':
$ref: '#/responses/403'
'500':
$ref: '#/responses/500'
/projects/{project_name}/preheat/policies/{preheat_policy_name}/executions/{execution_id}/tasks:
get:
summary: List all the related tasks for the given execution
description: List all the related tasks for the given execution
tags:
- preheat
operationId: ListTasks
parameters:
- $ref: '#/parameters/requestId'
- $ref: '#/parameters/projectName'
- $ref: '#/parameters/preheatPolicyName'
- $ref: '#/parameters/executionId'
responses:
'200':
description: List tasks success
schema:
type: array
items:
$ref: '#/definitions/Task'
'400':
$ref: '#/responses/400'
'401':
$ref: '#/responses/401'
'404':
$ref: '#/responses/404'
'403':
$ref: '#/responses/403'
'500':
$ref: '#/responses/500'
/projects/{project_name}/preheat/policies/{preheat_policy_name}/executions/{execution_id}/tasks/{task_id}/logs:
get:
summary: Get the log text stream of the specified task for the given execution
description: Get the log text stream of the specified task for the given execution
tags:
- preheat
operationId: GetLog
parameters:
- $ref: '#/parameters/requestId'
- $ref: '#/parameters/projectName'
- $ref: '#/parameters/preheatPolicyName'
- $ref: '#/parameters/executionId'
- $ref: '#/parameters/taskId'
responses:
'200':
description: Get log success
schema:
type: string
'400':
$ref: '#/responses/400'
'401':
$ref: '#/responses/401'
'404':
$ref: '#/responses/404'
'403':
$ref: '#/responses/403'
'500':
$ref: '#/responses/500'
parameters:
query:
name: q
@ -1085,7 +1230,18 @@ parameters:
description: Preheat Policy Name
required: true
type: string
executionId:
name: execution_id
in: path
description: Execution ID
required: true
type: integer
taskId:
name: task_id
in: path
description: Task ID
required: true
type: integer
responses:
'200':
description: Success
@ -1601,3 +1757,90 @@ definitions:
type: string
format: date-time
description: The Update Time of preheat policy
Metrics:
type: object
properties:
task_count:
type: integer
description: The count of task
success_task_count:
type: integer
description: The count of success task
error_task_count:
type: integer
description: The count of error task
pending_task_count:
type: integer
description: The count of pending task
running_task_count:
type: integer
description: The count of running task
scheduled_task_count:
type: integer
description: The count of scheduled task
stopped_task_count:
type: integer
description: The count of stopped task
Execution:
type: object
properties:
id:
type: integer
description: The ID of execution
vendor_type:
type: string
description: The vendor type of execution
vendor_id:
type: integer
description: The vendor id of execution
status:
type: string
description: The status of execution
status_message:
type: string
description: The status message of execution
metrics:
$ref: '#/definitions/Metrics'
trigger:
type: string
description: The trigger of execution
extra_attrs:
$ref: '#/definitions/ExtraAttrs'
start_time:
type: string
description: The start time of execution
end_time:
type: string
description: The end time of execution
Task:
type: object
properties:
id:
type: integer
description: The ID of task
execution_id:
type: integer
description: The ID of task execution
status:
type: string
description: The status of task
status_message:
type: string
description: The status message of task
run_count:
type: integer
description: The count of task run
extra_attrs:
$ref: '#/definitions/ExtraAttrs'
creation_time:
type: string
description: The creation time of task
update_time:
type: string
description: The update time of task
start_time:
type: string
description: The start time of task
end_time:
type: string
description: The end time of task

View File

@ -0,0 +1,71 @@
// Copyright Project Harbor Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package task
import (
"context"
"github.com/goharbor/harbor/src/lib/q"
"github.com/goharbor/harbor/src/pkg/task"
)
var (
// Ctl is a global task controller instance
Ctl = NewController()
)
// Controller manages the task
type Controller interface {
// Stop the specified task.
Stop(ctx context.Context, id int64) (err error)
// Get the specified task.
Get(ctx context.Context, id int64) (task *task.Task, err error)
// List the tasks according to the query.
List(ctx context.Context, query *q.Query) (tasks []*task.Task, err error)
// Get the log of the specified task.
GetLog(ctx context.Context, id int64) (log []byte, err error)
}
// NewController creates an instance of the default task controller.
func NewController() Controller {
return &controller{
mgr: task.Mgr,
}
}
// controller defines the default task controller.
type controller struct {
mgr task.Manager
}
// Stop the specified task.
func (c *controller) Stop(ctx context.Context, id int64) (err error) {
return c.mgr.Stop(ctx, id)
}
// Get the specified task.
func (c *controller) Get(ctx context.Context, id int64) (task *task.Task, err error) {
return c.mgr.Get(ctx, id)
}
// List the tasks according to the query.
func (c *controller) List(ctx context.Context, query *q.Query) (tasks []*task.Task, err error) {
return c.mgr.List(ctx, query)
}
// Get the log of the specified task.
func (c *controller) GetLog(ctx context.Context, id int64) (log []byte, err error) {
return c.mgr.GetLog(ctx, id)
}

View File

@ -0,0 +1,74 @@
// Copyright Project Harbor Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package task
import (
"testing"
model "github.com/goharbor/harbor/src/pkg/task"
"github.com/goharbor/harbor/src/testing/mock"
"github.com/goharbor/harbor/src/testing/pkg/task"
"github.com/stretchr/testify/suite"
)
type controllerTestSuite struct {
suite.Suite
ctl *controller
mgr *task.FakeManager
}
// TestControllerTestSuite tests controller.
func TestControllerTestSuite(t *testing.T) {
suite.Run(t, &controllerTestSuite{})
}
// SetupTest setups the testing env.
func (c *controllerTestSuite) SetupTest() {
c.mgr = &task.FakeManager{}
c.ctl = &controller{mgr: c.mgr}
}
// TestStop tests stop.
func (c *controllerTestSuite) TestStop() {
c.mgr.On("Stop", mock.Anything, mock.Anything).Return(nil)
err := c.ctl.Stop(nil, 1)
c.NoError(err)
}
// TestGet tests get.
func (c *controllerTestSuite) TestGet() {
c.mgr.On("Get", mock.Anything, int64(1)).Return(&model.Task{ID: 1}, nil)
t, err := c.ctl.Get(nil, 1)
c.NoError(err)
c.Equal(int64(1), t.ID)
}
// TestList tests list.
func (c *controllerTestSuite) TestList() {
c.mgr.On("List", mock.Anything, mock.Anything).Return([]*model.Task{
{ID: 1}, {ID: 2},
}, nil)
ts, err := c.ctl.List(nil, nil)
c.NoError(err)
c.Len(ts, 2)
}
// TestGetLog tests get log.
func (c *controllerTestSuite) TestGetLog() {
c.mgr.On("GetLog", mock.Anything, mock.Anything).Return([]byte("logs"), nil)
l, err := c.ctl.GetLog(nil, 1)
c.NoError(err)
c.Equal([]byte("logs"), l)
}

View File

@ -0,0 +1,71 @@
// Copyright Project Harbor Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package task
import (
"context"
"github.com/goharbor/harbor/src/lib/q"
"github.com/goharbor/harbor/src/pkg/task"
)
var (
// ExecutionCtl is a global execution controller.
ExecutionCtl = NewExecutionController()
)
// ExecutionController manages the execution.
type ExecutionController interface {
// Stop all linked tasks of the specified execution.
Stop(ctx context.Context, id int64) (err error)
// Delete the specified execution and its tasks.
Delete(ctx context.Context, id int64) (err error)
// Get the specified execution.
Get(ctx context.Context, id int64) (execution *task.Execution, err error)
// List executions according to the query.
List(ctx context.Context, query *q.Query) (executions []*task.Execution, err error)
}
// executionController defines the execution controller.
type executionController struct {
mgr task.ExecutionManager
}
// NewExecutionController creates an instance of the default execution controller.
func NewExecutionController() ExecutionController {
return &executionController{
mgr: task.ExecMgr,
}
}
// Stop all linked tasks of the specified execution.
func (ec *executionController) Stop(ctx context.Context, id int64) (err error) {
return ec.mgr.Stop(ctx, id)
}
// Delete the specified execution and its tasks.
func (ec *executionController) Delete(ctx context.Context, id int64) (err error) {
return ec.mgr.Delete(ctx, id)
}
// Get the specified execution.
func (ec *executionController) Get(ctx context.Context, id int64) (execution *task.Execution, err error) {
return ec.mgr.Get(ctx, id)
}
// List executions according to the query.
func (ec *executionController) List(ctx context.Context, query *q.Query) (executions []*task.Execution, err error) {
return ec.mgr.List(ctx, query)
}

View File

@ -0,0 +1,76 @@
// Copyright Project Harbor Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package task
import (
"testing"
model "github.com/goharbor/harbor/src/pkg/task"
"github.com/goharbor/harbor/src/testing/mock"
"github.com/goharbor/harbor/src/testing/pkg/task"
"github.com/stretchr/testify/suite"
)
type executionControllerTestSuite struct {
suite.Suite
ctl *executionController
mgr *task.FakeExecutionManager
}
// TestExecutionControllerTestSuite tests controller.
func TestExecutionControllerTestSuite(t *testing.T) {
suite.Run(t, &executionControllerTestSuite{})
}
// SetupTest setups the testing env.
func (ec *executionControllerTestSuite) SetupTest() {
ec.mgr = &task.FakeExecutionManager{}
ec.ctl = &executionController{
mgr: ec.mgr,
}
}
// TestStop tests stop.
func (ec *executionControllerTestSuite) TestStop() {
ec.mgr.On("Stop", mock.Anything, mock.Anything).Return(nil)
err := ec.ctl.Stop(nil, 1)
ec.NoError(err)
}
// TestDelete tests delete.
func (ec *executionControllerTestSuite) TestDelete() {
ec.mgr.On("Delete", mock.Anything, mock.Anything).Return(nil)
err := ec.ctl.Delete(nil, 1)
ec.NoError(err)
}
// TestGet tests get.
func (ec *executionControllerTestSuite) TestGet() {
ec.mgr.On("Get", mock.Anything, mock.Anything).Return(&model.Execution{ID: 1}, nil)
e, err := ec.ctl.Get(nil, 1)
ec.NoError(err)
ec.Equal(int64(1), e.ID)
}
// TestList tests list.
func (ec *executionControllerTestSuite) TestList() {
ec.mgr.On("List", mock.Anything, mock.Anything).Return([]*model.Execution{
{ID: 1},
{ID: 2},
}, nil)
es, err := ec.ctl.List(nil, nil)
ec.NoError(err)
ec.Len(es, 2)
}

View File

@ -8,11 +8,18 @@ import (
"regexp"
"time"
"github.com/goharbor/harbor/src/lib/q"
"github.com/goharbor/harbor/src/jobservice/job"
"github.com/goharbor/harbor/src/pkg/task"
"github.com/go-openapi/runtime/middleware"
"github.com/go-openapi/strfmt"
"github.com/goharbor/harbor/src/common/rbac"
preheatCtl "github.com/goharbor/harbor/src/controller/p2p/preheat"
projectCtl "github.com/goharbor/harbor/src/controller/project"
taskCtl "github.com/goharbor/harbor/src/controller/task"
liberrors "github.com/goharbor/harbor/src/lib/errors"
"github.com/goharbor/harbor/src/pkg/p2p/preheat/models/policy"
instanceModel "github.com/goharbor/harbor/src/pkg/p2p/preheat/models/provider"
@ -24,9 +31,11 @@ import (
func newPreheatAPI() *preheatAPI {
return &preheatAPI{
preheatCtl: preheatCtl.Ctl,
projectCtl: projectCtl.Ctl,
enforcer: preheatCtl.Enf,
preheatCtl: preheatCtl.Ctl,
projectCtl: projectCtl.Ctl,
enforcer: preheatCtl.Enf,
executionCtl: taskCtl.ExecutionCtl,
taskCtl: taskCtl.Ctl,
}
}
@ -37,9 +46,11 @@ const nameRegex = "^[A-Za-z0-9]+(?:[._-][A-Za-z0-9]+)*$"
type preheatAPI struct {
BaseAPI
preheatCtl preheatCtl.Controller
projectCtl projectCtl.Controller
enforcer preheatCtl.Enforcer
preheatCtl preheatCtl.Controller
projectCtl projectCtl.Controller
enforcer preheatCtl.Enforcer
executionCtl taskCtl.ExecutionController
taskCtl taskCtl.Controller
}
func (api *preheatAPI) Prepare(ctx context.Context, operation string, params interface{}) middleware.Responder {
@ -473,3 +484,178 @@ func convertParamInstanceToModelInstance(model *models.Instance) (*instanceModel
Vendor: model.Vendor,
}, nil
}
// convertExecutionToPayload converts model execution to swagger model.
func convertExecutionToPayload(model *task.Execution) (*models.Execution, error) {
if model == nil {
return nil, errors.New("execution can not be nil")
}
execution := &models.Execution{
EndTime: model.EndTime.String(),
ExtraAttrs: model.ExtraAttrs,
ID: model.ID,
StartTime: model.StartTime.String(),
Status: model.Status,
StatusMessage: model.StatusMessage,
Trigger: model.Trigger,
VendorID: model.VendorID,
VendorType: model.VendorType,
}
if model.Metrics != nil {
execution.Metrics = &models.Metrics{
ErrorTaskCount: model.Metrics.ErrorTaskCount,
PendingTaskCount: model.Metrics.PendingTaskCount,
RunningTaskCount: model.Metrics.RunningTaskCount,
ScheduledTaskCount: model.Metrics.ScheduledTaskCount,
StoppedTaskCount: model.Metrics.StoppedTaskCount,
SuccessTaskCount: model.Metrics.SuccessTaskCount,
TaskCount: model.Metrics.TaskCount,
}
}
return execution, nil
}
// GetExecution gets an execution.
func (api *preheatAPI) GetExecution(ctx context.Context, params operation.GetExecutionParams) middleware.Responder {
if err := api.RequireProjectAccess(ctx, params.ProjectName, rbac.ActionRead, rbac.ResourcePreatPolicy); err != nil {
return api.SendError(ctx, err)
}
execution, err := api.executionCtl.Get(ctx, params.ExecutionID)
if err != nil {
return api.SendError(ctx, err)
}
payload, err := convertExecutionToPayload(execution)
if err != nil {
return api.SendError(ctx, err)
}
return operation.NewGetExecutionOK().WithPayload(payload)
}
// ListExecutions lists executions.
func (api *preheatAPI) ListExecutions(ctx context.Context, params operation.ListExecutionsParams) middleware.Responder {
if err := api.RequireProjectAccess(ctx, params.ProjectName, rbac.ActionList, rbac.ResourcePreatPolicy); err != nil {
return api.SendError(ctx, err)
}
project, err := api.projectCtl.GetByName(ctx, params.ProjectName)
if err != nil {
return api.SendError(ctx, err)
}
policy, err := api.preheatCtl.GetPolicyByName(ctx, project.ProjectID, params.PreheatPolicyName)
if err != nil {
return api.SendError(ctx, err)
}
query, err := api.BuildQuery(ctx, params.Q, params.Page, params.PageSize)
if err != nil {
return api.SendError(ctx, err)
}
if query != nil {
query.Keywords["vendor_type"] = job.P2PPreheat
query.Keywords["vendor_id"] = policy.ID
}
executions, err := api.executionCtl.List(ctx, query)
if err != nil {
return api.SendError(ctx, err)
}
var payloads []*models.Execution
for _, exec := range executions {
p, err := convertExecutionToPayload(exec)
if err != nil {
return api.SendError(ctx, err)
}
payloads = append(payloads, p)
}
return operation.NewListExecutionsOK().WithPayload(payloads)
}
// StopExecution stops execution.
func (api *preheatAPI) StopExecution(ctx context.Context, params operation.StopExecutionParams) middleware.Responder {
if err := api.RequireProjectAccess(ctx, params.ProjectName, rbac.ActionUpdate, rbac.ResourcePreatPolicy); err != nil {
return api.SendError(ctx, err)
}
if params.Execution.Status == "Stopped" {
err := api.executionCtl.Stop(ctx, params.ExecutionID)
if err != nil {
return api.SendError(ctx, err)
}
return operation.NewStopExecutionOK()
}
return api.SendError(ctx, fmt.Errorf("param status invalid: %#v", params.Execution))
}
// convertTaskToPayload converts task to swagger model.
func convertTaskToPayload(model *task.Task) (*models.Task, error) {
if model == nil {
return nil, errors.New("task model can not be nil")
}
return &models.Task{
CreationTime: model.CreationTime.String(),
EndTime: model.EndTime.String(),
ExecutionID: model.ExecutionID,
ExtraAttrs: model.ExtraAttrs,
ID: model.ID,
RunCount: int64(model.RunCount),
StartTime: model.StartTime.String(),
Status: model.Status,
StatusMessage: model.StatusMessage,
UpdateTime: model.UpdateTime.String(),
}, nil
}
// ListTasks lists tasks.
func (api *preheatAPI) ListTasks(ctx context.Context, params operation.ListTasksParams) middleware.Responder {
if err := api.RequireProjectAccess(ctx, params.ProjectName, rbac.ActionList, rbac.ResourcePreatPolicy); err != nil {
return api.SendError(ctx, err)
}
query := &q.Query{
Keywords: map[string]interface{}{
"execution_id": params.ExecutionID,
},
}
tasks, err := api.taskCtl.List(ctx, query)
if err != nil {
return api.SendError(ctx, err)
}
var payloads []*models.Task
for _, task := range tasks {
p, err := convertTaskToPayload(task)
if err != nil {
return api.SendError(ctx, err)
}
payloads = append(payloads, p)
}
return operation.NewListTasksOK().WithPayload(payloads)
}
// GetLog gets log.
func (api *preheatAPI) GetLog(ctx context.Context, params operation.GetLogParams) middleware.Responder {
if err := api.RequireProjectAccess(ctx, params.ProjectName, rbac.ActionRead, rbac.ResourcePreatPolicy); err != nil {
return api.SendError(ctx, err)
}
l, err := api.taskCtl.GetLog(ctx, params.TaskID)
if err != nil {
return api.SendError(ctx, err)
}
return operation.NewGetLogOK().WithPayload(string(l))
}

View File

@ -5,6 +5,8 @@ import (
"testing"
"time"
"github.com/goharbor/harbor/src/pkg/task"
"github.com/go-openapi/strfmt"
"github.com/goharbor/harbor/src/pkg/p2p/preheat/models/policy"
instanceModel "github.com/goharbor/harbor/src/pkg/p2p/preheat/models/provider"
@ -289,3 +291,113 @@ func Test_convertParamInstanceToModelInstance(t *testing.T) {
})
}
}
func Test_convertExecutionToPayload(t *testing.T) {
tests := []struct {
name string
input *task.Execution
expect *models.Execution
shouldErr bool
}{
{
name: "nil model",
input: nil,
expect: nil,
shouldErr: true,
},
{
name: "should ok",
input: &task.Execution{
ID: 1,
VendorType: "p2p",
VendorID: 1,
Status: "",
StatusMessage: "",
Metrics: nil,
Trigger: "",
ExtraAttrs: nil,
StartTime: time.Time{},
EndTime: time.Time{},
},
expect: &models.Execution{
EndTime: "0001-01-01 00:00:00 +0000 UTC",
ExtraAttrs: nil,
ID: 1,
Metrics: nil,
StartTime: "0001-01-01 00:00:00 +0000 UTC",
Status: "",
StatusMessage: "",
Trigger: "",
VendorID: 1,
VendorType: "p2p",
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := convertExecutionToPayload(tt.input)
if (err != nil) != tt.shouldErr {
t.Errorf("convertExecutionToPayload() error = %v, wantErr %v", err, tt.shouldErr)
return
}
if !reflect.DeepEqual(got, tt.expect) {
t.Errorf("convertExecutionToPayload() = %v, want %v", got, tt.expect)
}
})
}
}
func Test_convertTaskToPayload(t *testing.T) {
tests := []struct {
name string
input *task.Task
expect *models.Task
shouldErr bool
}{
{
name: "nil model",
input: nil,
expect: nil,
shouldErr: true,
},
{
name: "should ok",
input: &task.Task{
ID: 0,
ExecutionID: 0,
Status: "",
StatusMessage: "",
RunCount: 0,
ExtraAttrs: nil,
CreationTime: time.Time{},
StartTime: time.Time{},
UpdateTime: time.Time{},
EndTime: time.Time{},
},
expect: &models.Task{
CreationTime: "0001-01-01 00:00:00 +0000 UTC",
EndTime: "0001-01-01 00:00:00 +0000 UTC",
ExecutionID: 0,
ExtraAttrs: nil,
ID: 0,
RunCount: 0,
StartTime: "0001-01-01 00:00:00 +0000 UTC",
Status: "",
StatusMessage: "",
UpdateTime: "0001-01-01 00:00:00 +0000 UTC",
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := convertTaskToPayload(tt.input)
if (err != nil) != tt.shouldErr {
t.Errorf("convertTaskToPayload() error = %v, wantErr %v", err, tt.shouldErr)
return
}
if !reflect.DeepEqual(got, tt.expect) {
t.Errorf("convertTaskToPayload() = %v, want %v", got, tt.expect)
}
})
}
}