feat: add task controller

Signed-off-by: chlins <chlins.zhang@gmail.com>
This commit is contained in:
chlins 2020-07-12 13:43:16 +08:00
parent 2efc4f230d
commit 2863e68718
4 changed files with 365 additions and 0 deletions

View File

@ -0,0 +1,80 @@
// 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 {
// Create submits the job to jobservice and creates a corresponding task record.
// An execution must be created first and the task will be linked to it.
// The "extraAttrs" can be used to set the customized attributes.
Create(ctx context.Context, executionID int64, job *task.Job, extraAttrs ...map[string]interface{}) (id int64, err error)
// 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
}
// Create submits the job to jobservice and creates a corresponding task record.
func (c *controller) Create(ctx context.Context, executionID int64, job *task.Job, extraAttrs ...map[string]interface{}) (id int64, err error) {
return c.mgr.Create(ctx, executionID, job, extraAttrs...)
}
// 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,82 @@
// 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}
}
// TestCreate tests create.
func (c *controllerTestSuite) TestCreate() {
c.mgr.On("Create", mock.Anything, mock.Anything, mock.Anything).Return(int64(1), nil)
id, err := c.ctl.Create(nil, 1, nil)
c.NoError(err)
c.Equal(int64(1), id)
}
// 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,105 @@
// 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"
)
// ExecutionController manages the execution.
type ExecutionController interface {
// Create an execution. The "vendorType" specifies the type of vendor (e.g. replication, scan, gc, retention, etc.),
// and the "vendorID" specifies the ID of vendor if needed(e.g. policy ID for replication and retention).
// The "extraAttrs" can be used to set the customized attributes.
Create(ctx context.Context, vendorType string, vendorID int64, trigger string,
extraAttrs ...map[string]interface{}) (id int64, err error)
// MarkDone marks the status of the specified execution as success.
// It must be called to update the execution status if the created execution contains no tasks.
// In other cases, the execution status can be calculated from the referenced tasks automatically
// and no need to update it explicitly.
MarkDone(ctx context.Context, id int64, message string) (err error)
// MarkError marks the status of the specified execution as error.
// It must be called to update the execution status when failed to create tasks.
// In other cases, the execution status can be calculated from the referenced tasks automatically
// and no need to update it explicitly.
MarkError(ctx context.Context, id int64, message string) (err error)
// 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
}
// NewController creates an instance of the default execution controller.
func NewExecutionController() ExecutionController {
return &executionController{
mgr: task.ExecMgr,
}
}
// Create an execution. The "vendorType" specifies the type of vendor (e.g. replication, scan, gc, retention, etc.),
// and the "vendorID" specifies the ID of vendor if needed(e.g. policy ID for replication and retention).
// The "extraAttrs" can be used to set the customized attributes.
func (ec *executionController) Create(ctx context.Context, vendorType string, vendorID int64, trigger string,
extraAttrs ...map[string]interface{}) (id int64, err error) {
return ec.mgr.Create(ctx, vendorType, vendorID, trigger, extraAttrs...)
}
// MarkDone marks the status of the specified execution as success.
// It must be called to update the execution status if the created execution contains no tasks.
// In other cases, the execution status can be calculated from the referenced tasks automatically
// and no need to update it explicitly.
func (ec *executionController) MarkDone(ctx context.Context, id int64, message string) (err error) {
return ec.mgr.MarkDone(ctx, id, message)
}
// MarkError marks the status of the specified execution as error.
// It must be called to update the execution status when failed to create tasks.
// In other cases, the execution status can be calculated from the referenced tasks automatically
// and no need to update it explicitly.
func (ec *executionController) MarkError(ctx context.Context, id int64, message string) (err error) {
return ec.mgr.MarkError(ctx, id, message)
}
// 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,98 @@
// 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,
}
}
// TestCreate tests create.
func (ec *executionControllerTestSuite) TestCreate() {
ec.mgr.On("Create", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(int64(1), nil)
id, err := ec.ctl.Create(nil, "", 1, "")
ec.NoError(err)
ec.Equal(int64(1), id)
}
// TestMarkDown tests mark down.
func (ec *executionControllerTestSuite) TestMarkDone() {
ec.mgr.On("MarkDone", mock.Anything, mock.Anything, mock.Anything).Return(nil)
err := ec.ctl.MarkDone(nil, 1, "")
ec.NoError(err)
}
// TestMarkError tests mark error.
func (ec *executionControllerTestSuite) TestMarkError() {
ec.mgr.On("MarkError", mock.Anything, mock.Anything, mock.Anything).Return(nil)
err := ec.ctl.MarkError(nil, 1, "")
ec.NoError(err)
}
// 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)
}