This is an automated email from the ASF dual-hosted git repository.
likyh pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-devlake.git
The following commit(s) were added to refs/heads/main by this push:
new 63f3aaf65 Feat(whole): use gorm tag replace encrypt/decrypt (#4227)
63f3aaf65 is described below
commit 63f3aaf655b68872d4bf072f9fb1d927e517c3f4
Author: Warren Chen <[email protected]>
AuthorDate: Wed Jan 18 15:05:38 2023 +0800
Feat(whole): use gorm tag replace encrypt/decrypt (#4227)
* feat(framwork): use gorm tag to rplace
* fix(connections): replace dec or enc by gorm tag
* style(whole): clear unused annotation
* fix(framework): update for review
---
backend/core/models/blueprint.go | 25 +---
backend/core/models/pipeline.go | 52 +++------
backend/core/runner/run_pipeline.go | 2 +-
backend/core/runner/run_task.go | 4 +-
backend/helpers/pluginhelper/api/connection.go | 45 +------
backend/impls/dalgorm/encdec_serializer.go | 24 +++-
backend/plugins/dora/impl/impl.go | 1 -
backend/plugins/pagerduty/models/connection.go | 1 -
backend/plugins/sonarqube/api/blueprint.go | 3 -
backend/plugins/sonarqube/api/connection.go | 12 +-
backend/plugins/sonarqube/impl/impl.go | 1 -
backend/plugins/sonarqube/tasks/task_data.go | 1 -
backend/plugins/tapd/models/connection.go | 13 +--
.../20230115_encode_connection_token.go | 65 +++++++++++
.../tapd/models/migrationscripts/register.go | 1 +
backend/plugins/zentao/api/blueprint.go | 2 -
backend/plugins/zentao/api/connection.go | 43 ++++---
backend/plugins/zentao/impl/impl.go | 1 -
.../plugins/zentao/models/archived/connection.go | 4 +-
backend/plugins/zentao/models/connection.go | 4 +-
backend/plugins/zentao/tasks/account_collector.go | 6 +-
backend/plugins/zentao/tasks/account_convertor.go | 1 -
backend/plugins/zentao/tasks/api_client.go | 2 -
backend/plugins/zentao/tasks/bug_collector.go | 6 +-
backend/plugins/zentao/tasks/bug_convertor.go | 1 -
.../plugins/zentao/tasks/department_collector.go | 7 +-
.../plugins/zentao/tasks/execution_collector.go | 3 +-
.../plugins/zentao/tasks/execution_convertor.go | 1 -
backend/plugins/zentao/tasks/product_collector.go | 4 +-
backend/plugins/zentao/tasks/product_convertor.go | 1 -
backend/plugins/zentao/tasks/project_collector.go | 3 +-
backend/plugins/zentao/tasks/story_collector.go | 6 +-
backend/plugins/zentao/tasks/task_collector.go | 6 +-
backend/plugins/zentao/tasks/task_data.go | 1 -
backend/server/services/blueprint.go | 59 ++--------
backend/server/services/blueprint_helper.go | 130 ++++-----------------
backend/server/services/pipeline.go | 46 +++-----
backend/server/services/pipeline_helper.go | 116 +++---------------
backend/server/services/pipeline_runner.go | 4 +-
backend/server/services/project.go | 4 +-
backend/test/services/pipeline_runner_e2e_test.go | 2 +-
41 files changed, 237 insertions(+), 476 deletions(-)
diff --git a/backend/core/models/blueprint.go b/backend/core/models/blueprint.go
index c6c922bac..69438acf7 100644
--- a/backend/core/models/blueprint.go
+++ b/backend/core/models/blueprint.go
@@ -35,14 +35,14 @@ type Blueprint struct {
Name string `json:"name" validate:"required"`
ProjectName string `json:"projectName"
gorm:"type:varchar(255)"`
Mode string `json:"mode" gorm:"varchar(20)"
validate:"required,oneof=NORMAL ADVANCED"`
- Plan json.RawMessage `json:"plan"`
+ Plan json.RawMessage `json:"plan" gorm:"serializer:encdec"`
Enable bool `json:"enable"`
//please check this https://crontab.guru/ for detail
CronConfig string `json:"cronConfig" format:"* * * * *"
example:"0 0 * * 1"`
IsManual bool `json:"isManual"`
SkipOnFail bool `json:"skipOnFail"`
- Labels []string `json:"labels"`
- Settings json.RawMessage `json:"settings"
swaggertype:"array,string" example:"please check api:
/blueprints/<PLUGIN_NAME>/blueprint-setting"`
+ Labels []string `json:"labels" gorm:"-"`
+ Settings json.RawMessage `json:"settings"
swaggertype:"array,string" example:"please check api:
/blueprints/<PLUGIN_NAME>/blueprint-setting" gorm:"serializer:encdec"`
common.Model `swaggerignore:"true"`
}
@@ -64,24 +64,7 @@ func (bp *Blueprint) UnmarshalPlan() (plugin.PipelinePlan,
errors.Error) {
return plan, nil
}
-// @Description CronConfig
-type DbBlueprint struct {
- Name string `json:"name" validate:"required"`
- ProjectName string `json:"projectName" gorm:"type:varchar(255)"`
- Mode string `json:"mode" gorm:"varchar(20)"
validate:"required,oneof=NORMAL ADVANCED"`
- Plan string `json:"plan" encrypt:"yes"`
- Enable bool `json:"enable"`
- //please check this https://crontab.guru/ for detail
- CronConfig string `json:"cronConfig" format:"* * * * *" example:"0 0
* * 1"`
- IsManual bool `json:"isManual"`
- SkipOnFail bool `json:"skipOnFail"`
- Settings string `json:"settings" encrypt:"yes"
swaggertype:"array,string" example:"please check api:
/blueprints/<PLUGIN_NAME>/blueprint-setting"`
- common.Model `swaggerignore:"true"`
-
- Labels []DbBlueprintLabel `json:"-" gorm:"-"`
-}
-
-func (DbBlueprint) TableName() string {
+func (Blueprint) TableName() string {
return "_devlake_blueprints"
}
diff --git a/backend/core/models/pipeline.go b/backend/core/models/pipeline.go
index 3d1feef28..13e9b974d 100644
--- a/backend/core/models/pipeline.go
+++ b/backend/core/models/pipeline.go
@@ -18,30 +18,29 @@ limitations under the License.
package models
import (
+ "encoding/json"
"time"
"github.com/apache/incubator-devlake/core/models/common"
"github.com/apache/incubator-devlake/core/plugin"
-
- "gorm.io/datatypes"
)
type Pipeline struct {
common.Model
- Name string `json:"name" gorm:"index"`
- BlueprintId uint64 `json:"blueprintId"`
- Plan datatypes.JSON `json:"plan"`
- TotalTasks int `json:"totalTasks"`
- FinishedTasks int `json:"finishedTasks"`
- BeganAt *time.Time `json:"beganAt"`
- FinishedAt *time.Time `json:"finishedAt" gorm:"index"`
- Status string `json:"status"`
- Message string `json:"message"`
- ErrorName string `json:"errorName"`
- SpentSeconds int `json:"spentSeconds"`
- Stage int `json:"stage"`
- Labels []string `json:"labels"`
- SkipOnFail bool `json:"skipOnFail"`
+ Name string `json:"name" gorm:"index"`
+ BlueprintId uint64 `json:"blueprintId"`
+ Plan json.RawMessage `json:"plan" gorm:"serializer:encdec"`
+ TotalTasks int `json:"totalTasks"`
+ FinishedTasks int `json:"finishedTasks"`
+ BeganAt *time.Time `json:"beganAt"`
+ FinishedAt *time.Time `json:"finishedAt" gorm:"index"`
+ Status string `json:"status"`
+ Message string `json:"message"`
+ ErrorName string `json:"errorName"`
+ SpentSeconds int `json:"spentSeconds"`
+ Stage int `json:"stage"`
+ Labels []string `json:"labels" gorm:"-"`
+ SkipOnFail bool `json:"skipOnFail"`
}
// We use a 2D array because the request body must be an array of a set of
tasks
@@ -54,26 +53,7 @@ type NewPipeline struct {
BlueprintId uint64
}
-type DbPipeline struct {
- common.Model
- Name string `json:"name" gorm:"index"`
- BlueprintId uint64 `json:"blueprintId"`
- Plan string `json:"plan" encrypt:"yes"`
- TotalTasks int `json:"totalTasks"`
- FinishedTasks int `json:"finishedTasks"`
- BeganAt *time.Time `json:"beganAt"`
- FinishedAt *time.Time `json:"finishedAt" gorm:"index"`
- Status string `json:"status"`
- Message string `json:"message"`
- ErrorName string `json:"errorName"`
- SpentSeconds int `json:"spentSeconds"`
- Stage int `json:"stage"`
- SkipOnFail bool `json:"skipOnFail"`
-
- Labels []DbPipelineLabel `json:"-" gorm:"-"`
-}
-
-func (DbPipeline) TableName() string {
+func (Pipeline) TableName() string {
return "_devlake_pipelines"
}
diff --git a/backend/core/runner/run_pipeline.go
b/backend/core/runner/run_pipeline.go
index 0313847fa..20816de7e 100644
--- a/backend/core/runner/run_pipeline.go
+++ b/backend/core/runner/run_pipeline.go
@@ -62,7 +62,7 @@ func runPipelineTasks(
db := basicRes.GetDal()
log := basicRes.GetLogger()
// load pipeline from db
- dbPipeline := &models.DbPipeline{}
+ dbPipeline := &models.Pipeline{}
err := db.First(dbPipeline, dal.Where("id = ?", pipelineId))
if err != nil {
return err
diff --git a/backend/core/runner/run_task.go b/backend/core/runner/run_task.go
index def6c039d..0e4d4678d 100644
--- a/backend/core/runner/run_task.go
+++ b/backend/core/runner/run_task.go
@@ -48,7 +48,7 @@ func RunTask(
if task.Status == models.TASK_COMPLETED {
return errors.Default.New("invalid task status")
}
- dbPipeline := &models.DbPipeline{}
+ dbPipeline := &models.Pipeline{}
if err := db.First(dbPipeline, dal.Where("id = ? ", task.PipelineId));
err != nil {
return err
}
@@ -107,7 +107,7 @@ func RunTask(
}
// update finishedTasks
dbe := db.UpdateColumn(
- &models.DbPipeline{},
+ &models.Pipeline{},
"finished_tasks", dal.Expr("finished_tasks + 1"),
dal.Where("id=?", task.PipelineId),
)
diff --git a/backend/helpers/pluginhelper/api/connection.go
b/backend/helpers/pluginhelper/api/connection.go
index d2e77c9fb..a8843ae1d 100644
--- a/backend/helpers/pluginhelper/api/connection.go
+++ b/backend/helpers/pluginhelper/api/connection.go
@@ -41,8 +41,8 @@ type BaseConnection struct {
// BasicAuth FIXME ...
type BasicAuth struct {
- Username string `mapstructure:"username" validate:"required"
json:"username" encrypt:"yes"`
- Password string `mapstructure:"password" validate:"required"
json:"password"`
+ Username string `mapstructure:"username" validate:"required"
json:"username"`
+ Password string `mapstructure:"password" validate:"required"
json:"password" gorm:"serializer:encdec"`
}
// GetEncodedToken FIXME ...
@@ -52,7 +52,7 @@ func (ba BasicAuth) GetEncodedToken() string {
// AccessToken FIXME ...
type AccessToken struct {
- Token string `mapstructure:"token" validate:"required" json:"token"
encrypt:"yes"`
+ Token string `mapstructure:"token" validate:"required" json:"token"
gorm:"serializer:encdec"`
}
// AppKey FIXME ...
@@ -132,25 +132,12 @@ func (c *ConnectionApiHelper) First(connection
interface{}, params map[string]st
// FirstById finds connection from db by id and decrypt it
func (c *ConnectionApiHelper) FirstById(connection interface{}, id uint64)
errors.Error {
- err := c.db.First(connection, dal.Where("id = ?", id))
- if err != nil {
- return err
- }
- c.decrypt(connection)
- return nil
+ return c.db.First(connection, dal.Where("id = ?", id))
}
// List returns all connections with password/token decrypted
func (c *ConnectionApiHelper) List(connections interface{}) errors.Error {
- err := c.db.All(connections)
- if err != nil {
- return err
- }
- conns := reflect.ValueOf(connections).Elem()
- for i := 0; i < conns.Len(); i++ {
- c.decrypt(conns.Index(i).Addr().Interface())
- }
- return nil
+ return c.db.All(connections)
}
// Delete connection
@@ -163,8 +150,6 @@ func (c *ConnectionApiHelper) merge(connection interface{},
body map[string]inte
}
func (c *ConnectionApiHelper) save(connection interface{}) errors.Error {
- c.encrypt(connection)
-
err := c.db.CreateOrUpdate(connection)
if err != nil {
if strings.Contains(strings.ToLower(err.Error()), "duplicate") {
@@ -172,29 +157,9 @@ func (c *ConnectionApiHelper) save(connection interface{})
errors.Error {
}
return err
}
-
- c.decrypt(connection)
return nil
}
-func (c *ConnectionApiHelper) decrypt(connection interface{}) {
- err := UpdateEncryptFields(connection, func(encrypted string) (string,
errors.Error) {
- return plugin.Decrypt(c.encKey, encrypted)
- })
- if err != nil {
- c.log.Error(err, "failed to decrypt")
- }
-}
-
-func (c *ConnectionApiHelper) encrypt(connection interface{}) {
- err := UpdateEncryptFields(connection, func(plaintext string) (string,
errors.Error) {
- return plugin.Encrypt(c.encKey, plaintext)
- })
- if err != nil {
- c.log.Error(err, "failed to encrypt")
- }
-}
-
// UpdateEncryptFields update fields of val with tag `encrypt:"yes|true"`
func UpdateEncryptFields(val interface{}, update func(in string) (string,
errors.Error)) errors.Error {
v := reflect.ValueOf(val)
diff --git a/backend/impls/dalgorm/encdec_serializer.go
b/backend/impls/dalgorm/encdec_serializer.go
index 53a198889..af3011107 100644
--- a/backend/impls/dalgorm/encdec_serializer.go
+++ b/backend/impls/dalgorm/encdec_serializer.go
@@ -19,6 +19,7 @@ package dalgorm
import (
"context"
+ "encoding/json"
"fmt"
"github.com/apache/incubator-devlake/core/plugin"
"reflect"
@@ -36,6 +37,7 @@ type EncDecSerializer struct {
// Scan implements serializer interface
func (es *EncDecSerializer) Scan(ctx context.Context, field *schema.Field, dst
reflect.Value, dbValue interface{}) (err error) {
+ fieldValue := reflect.New(field.FieldType)
if dbValue != nil {
var base64str string
switch v := dbValue.(type) {
@@ -51,14 +53,32 @@ func (es *EncDecSerializer) Scan(ctx context.Context, field
*schema.Field, dst r
if err != nil {
return err
}
- field.ReflectValueOf(ctx, dst).SetString(decrypted)
+ switch fieldValue.Elem().Kind() {
+ case reflect.Slice:
+ bytes := []byte(decrypted)
+ _ = json.Unmarshal(bytes, fieldValue.Interface())
+ field.ReflectValueOf(ctx, dst).Set(fieldValue.Elem())
+ case reflect.String:
+ field.ReflectValueOf(ctx, dst).SetString(decrypted)
+ default:
+ return fmt.Errorf("failed to decrypt value: %#v",
dbValue)
+ }
}
return nil
}
// Value implements serializer interface
func (es *EncDecSerializer) Value(ctx context.Context, field *schema.Field,
dst reflect.Value, fieldValue interface{}) (interface{}, error) {
- return plugin.Encrypt(es.encKey, fieldValue.(string))
+ var target string
+ switch v := fieldValue.(type) {
+ case json.RawMessage:
+ target = string(v)
+ case string:
+ target = v
+ default:
+ return nil, fmt.Errorf("failed to encrypt value: %#v",
fieldValue)
+ }
+ return plugin.Encrypt(es.encKey, target)
}
// Init the encdec serializer
diff --git a/backend/plugins/dora/impl/impl.go
b/backend/plugins/dora/impl/impl.go
index 42ca7c2fc..892343acd 100644
--- a/backend/plugins/dora/impl/impl.go
+++ b/backend/plugins/dora/impl/impl.go
@@ -80,7 +80,6 @@ func (p Dora) Settings() interface{} {
}
func (p Dora) SubTaskMetas() []plugin.SubTaskMeta {
- // TODO add your sub task here
return []plugin.SubTaskMeta{
tasks.EnrichTaskEnvMeta,
tasks.CalculateChangeLeadTimeMeta,
diff --git a/backend/plugins/pagerduty/models/connection.go
b/backend/plugins/pagerduty/models/connection.go
index b9d9d63f5..9b3b8ec94 100644
--- a/backend/plugins/pagerduty/models/connection.go
+++ b/backend/plugins/pagerduty/models/connection.go
@@ -21,7 +21,6 @@ import (
helper "github.com/apache/incubator-devlake/helpers/pluginhelper/api"
)
-// TODO Please modify the following code to fit your needs
// This object conforms to what the frontend currently sends.
type PagerDutyConnection struct {
helper.BaseConnection `mapstructure:",squash"`
diff --git a/backend/plugins/sonarqube/api/blueprint.go
b/backend/plugins/sonarqube/api/blueprint.go
index b98582a66..5d26b6b27 100644
--- a/backend/plugins/sonarqube/api/blueprint.go
+++ b/backend/plugins/sonarqube/api/blueprint.go
@@ -35,9 +35,6 @@ func MakePipelinePlan(subtaskMetas []plugin.SubTaskMeta,
connectionId uint64, sc
return nil, errors.Default.Wrap(err, "error
unmarshalling task options")
}
taskOptions["connectionId"] = connectionId
-
- //TODO Add transformation rules to task options
-
/*
var transformationRules tasks.TransformationRules
if len(scopeElem.Transformation) > 0 {
diff --git a/backend/plugins/sonarqube/api/connection.go
b/backend/plugins/sonarqube/api/connection.go
index c66a85173..0dea3fcbf 100644
--- a/backend/plugins/sonarqube/api/connection.go
+++ b/backend/plugins/sonarqube/api/connection.go
@@ -122,14 +122,14 @@ func ListConnections(input *plugin.ApiResourceInput)
(*plugin.ApiResourceOutput,
return &plugin.ApiResourceOutput{Body: connections, Status:
http.StatusOK}, nil
}
-//TODO Please modify the folowing code to adapt to your plugin
/*
GET /plugins/Sonarqube/connections/:connectionId
-{
- "name": "Sonarqube data connection name",
- "endpoint": "Sonarqube api endpoint, i.e. http://host:port/api/",
- "token": "Sonarqube user token"
-}
+
+ {
+ "name": "Sonarqube data connection name",
+ "endpoint": "Sonarqube api endpoint, i.e.
http://host:port/api/",
+ "token": "Sonarqube user token"
+ }
*/
func GetConnection(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput,
errors.Error) {
connection := &models.SonarqubeConnection{}
diff --git a/backend/plugins/sonarqube/impl/impl.go
b/backend/plugins/sonarqube/impl/impl.go
index 99b0e661b..04679ab82 100644
--- a/backend/plugins/sonarqube/impl/impl.go
+++ b/backend/plugins/sonarqube/impl/impl.go
@@ -50,7 +50,6 @@ func (p Sonarqube) Init(br context.BasicRes) errors.Error {
}
func (p Sonarqube) SubTaskMetas() []plugin.SubTaskMeta {
- // TODO add your sub task here
return []plugin.SubTaskMeta{}
}
diff --git a/backend/plugins/sonarqube/tasks/task_data.go
b/backend/plugins/sonarqube/tasks/task_data.go
index 08b11e839..67dbdbd01 100644
--- a/backend/plugins/sonarqube/tasks/task_data.go
+++ b/backend/plugins/sonarqube/tasks/task_data.go
@@ -26,7 +26,6 @@ type SonarqubeApiParams struct {
}
type SonarqubeOptions struct {
- // TODO add some custom options here if necessary
// options means some custom params required by plugin running.
// Such As How many rows do your want
// You can use it in sub tasks and you need pass it in main.go and
pipelines.
diff --git a/backend/plugins/tapd/models/connection.go
b/backend/plugins/tapd/models/connection.go
index d5d2608e2..77be688e6 100644
--- a/backend/plugins/tapd/models/connection.go
+++ b/backend/plugins/tapd/models/connection.go
@@ -18,8 +18,6 @@ limitations under the License.
package models
import (
- "encoding/base64"
- "fmt"
helper "github.com/apache/incubator-devlake/helpers/pluginhelper/api"
)
@@ -35,18 +33,9 @@ type WorkspaceResponse struct {
Value string
}
-type BasicAuth struct {
- Username string `mapstructure:"username" validate:"required"
json:"username"`
- Password string `mapstructure:"password" validate:"required"
json:"password"`
-}
-
-func (ba BasicAuth) GetEncodedToken() string {
- return base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%v:%v",
ba.Username, ba.Password)))
-}
-
type TapdConnection struct {
helper.RestConnection `mapstructure:",squash"`
- BasicAuth `mapstructure:",squash"`
+ helper.BasicAuth `mapstructure:",squash"`
}
type TapdConnectionDetail struct {
diff --git
a/backend/plugins/tapd/models/migrationscripts/20230115_encode_connection_token.go
b/backend/plugins/tapd/models/migrationscripts/20230115_encode_connection_token.go
new file mode 100644
index 000000000..7b7c245a6
--- /dev/null
+++
b/backend/plugins/tapd/models/migrationscripts/20230115_encode_connection_token.go
@@ -0,0 +1,65 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements. See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You 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 migrationscripts
+
+import (
+ "github.com/apache/incubator-devlake/core/config"
+ "github.com/apache/incubator-devlake/core/context"
+ "github.com/apache/incubator-devlake/core/errors"
+ "github.com/apache/incubator-devlake/core/plugin"
+ "github.com/apache/incubator-devlake/helpers/migrationhelper"
+
"github.com/apache/incubator-devlake/plugins/tapd/models/migrationscripts/archived"
+)
+
+type encodeConnToken struct{}
+
+func (script *encodeConnToken) Up(basicRes context.BasicRes) errors.Error {
+ encKey := config.GetConfig().GetString(plugin.EncodeKeyEnvStr)
+ if encKey == "" {
+ return errors.BadInput.New("jira v0.11 invalid encKey")
+ }
+
+ return migrationhelper.TransformColumns(
+ basicRes,
+ script,
+ "_tool_tapd_connections",
+ []string{},
+ func(old *archived.TapdConnection) (*archived.TapdConnection,
errors.Error) {
+ var err errors.Error
+ conn := &archived.TapdConnection{}
+ conn.ID = old.ID
+ conn.Name = old.Name
+ conn.Endpoint = old.Endpoint
+ conn.Proxy = old.Proxy
+ conn.RateLimitPerHour = old.RateLimitPerHour
+ conn.Username = old.Username
+ conn.Password, err = plugin.Encrypt(encKey,
old.Password)
+ if err != nil {
+ return nil, err
+ }
+ return conn, nil
+ })
+}
+
+func (*encodeConnToken) Version() uint64 {
+ return 20230115201138
+}
+
+func (*encodeConnToken) Name() string {
+ return "Tapd encode connection token"
+}
diff --git a/backend/plugins/tapd/models/migrationscripts/register.go
b/backend/plugins/tapd/models/migrationscripts/register.go
index ec054748c..04bf2dbea 100644
--- a/backend/plugins/tapd/models/migrationscripts/register.go
+++ b/backend/plugins/tapd/models/migrationscripts/register.go
@@ -25,5 +25,6 @@ import (
func All() []plugin.MigrationScript {
return []plugin.MigrationScript{
new(addInitTables),
+ new(encodeConnToken),
}
}
diff --git a/backend/plugins/zentao/api/blueprint.go
b/backend/plugins/zentao/api/blueprint.go
index fb6df52bd..fc0625597 100644
--- a/backend/plugins/zentao/api/blueprint.go
+++ b/backend/plugins/zentao/api/blueprint.go
@@ -36,8 +36,6 @@ func MakePipelinePlan(subtaskMetas []plugin.SubTaskMeta,
connectionId uint64, sc
}
taskOptions["connectionId"] = connectionId
- //TODO Add transformation rules to task options
-
/*
var transformationRules tasks.JiraTransformationRule
if len(scopeElem.Transformation) > 0 {
diff --git a/backend/plugins/zentao/api/connection.go
b/backend/plugins/zentao/api/connection.go
index a6df6a273..f92d88262 100644
--- a/backend/plugins/zentao/api/connection.go
+++ b/backend/plugins/zentao/api/connection.go
@@ -27,7 +27,6 @@ import (
"net/http"
)
-// TODO Please modify the following code to fit your needs
func TestConnection(input *plugin.ApiResourceInput)
(*plugin.ApiResourceOutput, errors.Error) {
// process input
var params models.TestConnectionRequest
@@ -67,15 +66,15 @@ func TestConnection(input *plugin.ApiResourceInput)
(*plugin.ApiResourceOutput,
return nil, nil
}
-//TODO Please modify the folowing code to adapt to your plugin
/*
POST /plugins/Zentao/connections
-{
- "name": "Zentao data connection name",
- "endpoint": "Zentao api endpoint, i.e. https://example.com",
- "username": "username, usually should be email address",
- "password": "Zentao api access token"
-}
+
+ {
+ "name": "Zentao data connection name",
+ "endpoint": "Zentao api endpoint, i.e. https://example.com",
+ "username": "username, usually should be email address",
+ "password": "Zentao api access token"
+ }
*/
func PostConnections(input *plugin.ApiResourceInput)
(*plugin.ApiResourceOutput, errors.Error) {
// update from request and save to database
@@ -87,15 +86,15 @@ func PostConnections(input *plugin.ApiResourceInput)
(*plugin.ApiResourceOutput,
return &plugin.ApiResourceOutput{Body: connection, Status:
http.StatusOK}, nil
}
-//TODO Please modify the folowing code to adapt to your plugin
/*
PATCH /plugins/Zentao/connections/:connectionId
-{
- "name": "Zentao data connection name",
- "endpoint": "Zentao api endpoint, i.e. https://example.com",
- "username": "username, usually should be email address",
- "password": "Zentao api access token"
-}
+
+ {
+ "name": "Zentao data connection name",
+ "endpoint": "Zentao api endpoint, i.e. https://example.com",
+ "username": "username, usually should be email address",
+ "password": "Zentao api access token"
+ }
*/
func PatchConnection(input *plugin.ApiResourceInput)
(*plugin.ApiResourceOutput, errors.Error) {
connection := &models.ZentaoConnection{}
@@ -131,15 +130,15 @@ func ListConnections(input *plugin.ApiResourceInput)
(*plugin.ApiResourceOutput,
return &plugin.ApiResourceOutput{Body: connections, Status:
http.StatusOK}, nil
}
-//TODO Please modify the folowing code to adapt to your plugin
/*
GET /plugins/Zentao/connections/:connectionId
-{
- "name": "Zentao data connection name",
- "endpoint": "Zentao api endpoint, i.e.
https://merico.atlassian.net/rest",
- "username": "username, usually should be email address",
- "password": "Zentao api access token"
-}
+
+ {
+ "name": "Zentao data connection name",
+ "endpoint": "Zentao api endpoint, i.e.
https://merico.atlassian.net/rest",
+ "username": "username, usually should be email address",
+ "password": "Zentao api access token"
+ }
*/
func GetConnection(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput,
errors.Error) {
connection := &models.ZentaoConnection{}
diff --git a/backend/plugins/zentao/impl/impl.go
b/backend/plugins/zentao/impl/impl.go
index 89247f522..66359d068 100644
--- a/backend/plugins/zentao/impl/impl.go
+++ b/backend/plugins/zentao/impl/impl.go
@@ -49,7 +49,6 @@ func (p Zentao) Init(basicRes context.BasicRes) errors.Error {
}
func (p Zentao) SubTaskMetas() []plugin.SubTaskMeta {
- // TODO add your sub task here
return []plugin.SubTaskMeta{
tasks.CollectProductMeta,
tasks.ExtractProductMeta,
diff --git a/backend/plugins/zentao/models/archived/connection.go
b/backend/plugins/zentao/models/archived/connection.go
index f04d9a252..3b6caa485 100644
--- a/backend/plugins/zentao/models/archived/connection.go
+++ b/backend/plugins/zentao/models/archived/connection.go
@@ -21,12 +21,10 @@ import (
"github.com/apache/incubator-devlake/core/models/migrationscripts/archived"
)
-// TODO Please modify the following code to fit your needs
// This object conforms to what the frontend currently sends.
type ZentaoConnection struct {
RestConnection `mapstructure:",squash"`
- //TODO you may need to use api.BasicAuth instead of api.AccessToken
- BasicAuth `mapstructure:",squash"`
+ BasicAuth `mapstructure:",squash"`
}
type TestConnectionRequest struct {
diff --git a/backend/plugins/zentao/models/connection.go
b/backend/plugins/zentao/models/connection.go
index 75c7c3bfa..de1dedb73 100644
--- a/backend/plugins/zentao/models/connection.go
+++ b/backend/plugins/zentao/models/connection.go
@@ -21,12 +21,10 @@ import (
helper "github.com/apache/incubator-devlake/helpers/pluginhelper/api"
)
-// TODO Please modify the following code to fit your needs
// This object conforms to what the frontend currently sends.
type ZentaoConnection struct {
helper.RestConnection `mapstructure:",squash"`
- //TODO you may need to use api.BasicAuth instead of api.AccessToken
- helper.BasicAuth `mapstructure:",squash"`
+ helper.BasicAuth `mapstructure:",squash"`
}
type TestConnectionRequest struct {
diff --git a/backend/plugins/zentao/tasks/account_collector.go
b/backend/plugins/zentao/tasks/account_collector.go
index ac279531a..176073cc5 100644
--- a/backend/plugins/zentao/tasks/account_collector.go
+++ b/backend/plugins/zentao/tasks/account_collector.go
@@ -44,10 +44,8 @@ func CollectAccount(taskCtx plugin.SubTaskContext)
errors.Error {
},
Table: RAW_ACCOUNT_TABLE,
},
- ApiClient: data.ApiClient,
-
- PageSize: 100,
- // TODO write which api would you want request
+ ApiClient: data.ApiClient,
+ PageSize: 100,
UrlTemplate: "/users",
Query: func(reqData *api.RequestData) (url.Values,
errors.Error) {
query := url.Values{}
diff --git a/backend/plugins/zentao/tasks/account_convertor.go
b/backend/plugins/zentao/tasks/account_convertor.go
index 80d4099bc..eb7b44e15 100644
--- a/backend/plugins/zentao/tasks/account_convertor.go
+++ b/backend/plugins/zentao/tasks/account_convertor.go
@@ -67,7 +67,6 @@ func ConvertAccount(taskCtx plugin.SubTaskContext)
errors.Error {
},
Convert: func(inputRow interface{}) ([]interface{},
errors.Error) {
toolEntity := inputRow.(*models.ZentaoAccount)
-
domainEntity := &crossdomain.Account{
DomainEntity: domainlayer.DomainEntity{
Id:
accountIdGen.Generate(toolEntity.ConnectionId, toolEntity.ID),
diff --git a/backend/plugins/zentao/tasks/api_client.go
b/backend/plugins/zentao/tasks/api_client.go
index 09b7b9a0d..871b4a9ec 100644
--- a/backend/plugins/zentao/tasks/api_client.go
+++ b/backend/plugins/zentao/tasks/api_client.go
@@ -33,7 +33,6 @@ func NewZentaoApiClient(taskCtx plugin.TaskContext,
connection *models.ZentaoCon
if err != nil {
return nil, err
}
-
// request for access token
tokenReqBody := &models.ApiAccessTokenRequest{
Account: connection.Username,
@@ -60,7 +59,6 @@ func NewZentaoApiClient(taskCtx plugin.TaskContext,
connection *models.ZentaoCon
apiClient.SetHeaders(map[string]string{
"Token": fmt.Sprintf("%v", tokenResBody.Token),
})
-
// create rate limit calculator
rateLimiter := &api.ApiRateLimitCalculator{
UserRateLimitPerHour: connection.RateLimitPerHour,
diff --git a/backend/plugins/zentao/tasks/bug_collector.go
b/backend/plugins/zentao/tasks/bug_collector.go
index 5f7681d8c..0b8ca0255 100644
--- a/backend/plugins/zentao/tasks/bug_collector.go
+++ b/backend/plugins/zentao/tasks/bug_collector.go
@@ -44,10 +44,8 @@ func CollectBug(taskCtx plugin.SubTaskContext) errors.Error {
},
Table: RAW_BUG_TABLE,
},
- ApiClient: data.ApiClient,
-
- PageSize: 100,
- // TODO write which api would you want request
+ ApiClient: data.ApiClient,
+ PageSize: 100,
UrlTemplate: "/products/{{ .Params.ProductId }}/bugs",
Query: func(reqData *api.RequestData) (url.Values,
errors.Error) {
query := url.Values{}
diff --git a/backend/plugins/zentao/tasks/bug_convertor.go
b/backend/plugins/zentao/tasks/bug_convertor.go
index efab59665..fefd7145f 100644
--- a/backend/plugins/zentao/tasks/bug_convertor.go
+++ b/backend/plugins/zentao/tasks/bug_convertor.go
@@ -108,7 +108,6 @@ func ConvertBug(taskCtx plugin.SubTaskContext) errors.Error
{
return results, nil
},
})
-
if err != nil {
return err
}
diff --git a/backend/plugins/zentao/tasks/department_collector.go
b/backend/plugins/zentao/tasks/department_collector.go
index 43c77ee43..294673ba2 100644
--- a/backend/plugins/zentao/tasks/department_collector.go
+++ b/backend/plugins/zentao/tasks/department_collector.go
@@ -44,10 +44,8 @@ func CollectDepartment(taskCtx plugin.SubTaskContext)
errors.Error {
},
Table: RAW_DEPARTMENT_TABLE,
},
- ApiClient: data.ApiClient,
-
- PageSize: 100,
- // TODO write which api would you want request
+ ApiClient: data.ApiClient,
+ PageSize: 100,
UrlTemplate: "/users",
Query: func(reqData *api.RequestData) (url.Values,
errors.Error) {
query := url.Values{}
@@ -70,7 +68,6 @@ func CollectDepartment(taskCtx plugin.SubTaskContext)
errors.Error {
if err != nil {
return err
}
-
return collector.Execute()
}
diff --git a/backend/plugins/zentao/tasks/execution_collector.go
b/backend/plugins/zentao/tasks/execution_collector.go
index 1ca9f9d52..d6775c2c5 100644
--- a/backend/plugins/zentao/tasks/execution_collector.go
+++ b/backend/plugins/zentao/tasks/execution_collector.go
@@ -45,8 +45,7 @@ func CollectExecution(taskCtx plugin.SubTaskContext)
errors.Error {
},
Table: RAW_EXECUTION_TABLE,
},
- ApiClient: data.ApiClient,
- // TODO write which api would you want request
+ ApiClient: data.ApiClient,
UrlTemplate: "executions/{{ .Params.ExecutionId }}",
Query: func(reqData *api.RequestData) (url.Values,
errors.Error) {
query := url.Values{}
diff --git a/backend/plugins/zentao/tasks/execution_convertor.go
b/backend/plugins/zentao/tasks/execution_convertor.go
index 06d1073e4..fbc78d563 100644
--- a/backend/plugins/zentao/tasks/execution_convertor.go
+++ b/backend/plugins/zentao/tasks/execution_convertor.go
@@ -78,7 +78,6 @@ func ConvertExecutions(taskCtx plugin.SubTaskContext)
errors.Error {
CreatedDate:
toolExecution.OpenedDate.ToNullableTime(),
Type: toolExecution.Type,
}
-
results := make([]interface{}, 0)
results = append(results, domainBoard)
return results, nil
diff --git a/backend/plugins/zentao/tasks/product_collector.go
b/backend/plugins/zentao/tasks/product_collector.go
index 30418a00c..56fbf839f 100644
--- a/backend/plugins/zentao/tasks/product_collector.go
+++ b/backend/plugins/zentao/tasks/product_collector.go
@@ -45,8 +45,7 @@ func CollectProduct(taskCtx plugin.SubTaskContext)
errors.Error {
},
Table: RAW_PRODUCT_TABLE,
},
- ApiClient: data.ApiClient,
- // TODO write which api would you want request
+ ApiClient: data.ApiClient,
UrlTemplate: "products/{{ .Params.ProductId }}",
Query: func(reqData *api.RequestData) (url.Values,
errors.Error) {
query := url.Values{}
@@ -66,7 +65,6 @@ func CollectProduct(taskCtx plugin.SubTaskContext)
errors.Error {
if err != nil {
return err
}
-
return collector.Execute()
}
diff --git a/backend/plugins/zentao/tasks/product_convertor.go
b/backend/plugins/zentao/tasks/product_convertor.go
index 75b97d63e..eeb66baa5 100644
--- a/backend/plugins/zentao/tasks/product_convertor.go
+++ b/backend/plugins/zentao/tasks/product_convertor.go
@@ -77,7 +77,6 @@ func ConvertProducts(taskCtx plugin.SubTaskContext)
errors.Error {
CreatedDate:
toolProduct.CreatedDate.ToNullableTime(),
Type: toolProduct.Type,
}
-
results := make([]interface{}, 0)
results = append(results, domainBoard)
return results, nil
diff --git a/backend/plugins/zentao/tasks/project_collector.go
b/backend/plugins/zentao/tasks/project_collector.go
index 39bbee1b7..579075a14 100644
--- a/backend/plugins/zentao/tasks/project_collector.go
+++ b/backend/plugins/zentao/tasks/project_collector.go
@@ -44,8 +44,7 @@ func CollectProject(taskCtx plugin.SubTaskContext)
errors.Error {
},
Table: RAW_PROJECT_TABLE,
},
- ApiClient: data.ApiClient,
- // TODO write which api would you want request
+ ApiClient: data.ApiClient,
UrlTemplate: "projects",
Query: func(reqData *api.RequestData) (url.Values,
errors.Error) {
query := url.Values{}
diff --git a/backend/plugins/zentao/tasks/story_collector.go
b/backend/plugins/zentao/tasks/story_collector.go
index 870a27a10..6c05b5250 100644
--- a/backend/plugins/zentao/tasks/story_collector.go
+++ b/backend/plugins/zentao/tasks/story_collector.go
@@ -44,10 +44,8 @@ func CollectStory(taskCtx plugin.SubTaskContext)
errors.Error {
},
Table: RAW_STORY_TABLE,
},
- ApiClient: data.ApiClient,
-
- PageSize: 100,
- // TODO write which api would you want request
+ ApiClient: data.ApiClient,
+ PageSize: 100,
UrlTemplate: "/products/{{ .Params.ProductId }}/stories",
Query: func(reqData *api.RequestData) (url.Values,
errors.Error) {
query := url.Values{}
diff --git a/backend/plugins/zentao/tasks/task_collector.go
b/backend/plugins/zentao/tasks/task_collector.go
index a6a62515f..cb0974989 100644
--- a/backend/plugins/zentao/tasks/task_collector.go
+++ b/backend/plugins/zentao/tasks/task_collector.go
@@ -44,9 +44,8 @@ func CollectTask(taskCtx plugin.SubTaskContext) errors.Error {
},
Table: RAW_TASK_TABLE,
},
- ApiClient: data.ApiClient,
- PageSize: 100,
- // TODO write which api would you want request
+ ApiClient: data.ApiClient,
+ PageSize: 100,
UrlTemplate: "/executions/{{ .Params.ExecutionId }}/tasks",
Query: func(reqData *api.RequestData) (url.Values,
errors.Error) {
query := url.Values{}
@@ -69,7 +68,6 @@ func CollectTask(taskCtx plugin.SubTaskContext) errors.Error {
if err != nil {
return err
}
-
return collector.Execute()
}
diff --git a/backend/plugins/zentao/tasks/task_data.go
b/backend/plugins/zentao/tasks/task_data.go
index 18a2e8a4c..81b9936da 100644
--- a/backend/plugins/zentao/tasks/task_data.go
+++ b/backend/plugins/zentao/tasks/task_data.go
@@ -31,7 +31,6 @@ type ZentaoApiParams struct {
}
type ZentaoOptions struct {
- // TODO add some custom options here if necessary
// options means some custom params required by plugin running.
// Such As How many rows do your want
// You can use it in sub tasks and you need pass it in main.go and
pipelines.
diff --git a/backend/server/services/blueprint.go
b/backend/server/services/blueprint.go
index 813ed6e1e..e8def9bb8 100644
--- a/backend/server/services/blueprint.go
+++ b/backend/server/services/blueprint.go
@@ -48,16 +48,10 @@ func CreateBlueprint(blueprint *models.Blueprint)
errors.Error {
if err != nil {
return err
}
- dbBlueprint := parseDbBlueprint(blueprint)
- dbBlueprint, err = encryptDbBlueprint(dbBlueprint)
+ err = SaveDbBlueprint(blueprint)
if err != nil {
return err
}
- err = SaveDbBlueprint(dbBlueprint)
- if err != nil {
- return err
- }
- blueprint.Model = dbBlueprint.Model
err = ReloadBlueprints(cronManager)
if err != nil {
return errors.Internal.Wrap(err, "error reloading blueprints")
@@ -67,36 +61,22 @@ func CreateBlueprint(blueprint *models.Blueprint)
errors.Error {
// GetBlueprints returns a paginated list of Blueprints based on `query`
func GetBlueprints(query *BlueprintQuery) ([]*models.Blueprint, int64,
errors.Error) {
- dbBlueprints, count, err := GetDbBlueprints(query)
+ blueprints, count, err := GetDbBlueprints(query)
if err != nil {
return nil, 0, errors.Convert(err)
}
- blueprints := make([]*models.Blueprint, 0)
- for _, dbBlueprint := range dbBlueprints {
- dbBlueprint, err = decryptDbBlueprint(dbBlueprint)
- if err != nil {
- return nil, 0, err
- }
- blueprint := parseBlueprint(dbBlueprint)
- blueprints = append(blueprints, blueprint)
- }
return blueprints, count, nil
}
// GetBlueprint returns the detail of a given Blueprint ID
func GetBlueprint(blueprintId uint64) (*models.Blueprint, errors.Error) {
- dbBlueprint, err := GetDbBlueprint(blueprintId)
+ blueprint, err := GetDbBlueprint(blueprintId)
if err != nil {
if db.IsErrorNotFound(err) {
return nil, errors.NotFound.New("blueprint not found")
}
return nil, errors.Internal.Wrap(err, "error getting the
blueprint from database")
}
- dbBlueprint, err = decryptDbBlueprint(dbBlueprint)
- if err != nil {
- return nil, err
- }
- blueprint := parseBlueprint(dbBlueprint)
return blueprint, nil
}
@@ -105,7 +85,7 @@ func GetBlueprintByProjectName(projectName string)
(*models.Blueprint, errors.Er
if projectName == "" {
return nil, errors.Internal.New("can not use the empty
projectName to search the unique blueprint")
}
- dbBlueprint, err := GetDbBlueprintByProjectName(projectName)
+ blueprint, err := GetDbBlueprintByProjectName(projectName)
if err != nil {
// Allow specific projectName to fail to find the corresponding
blueprint
if db.IsErrorNotFound(err) {
@@ -113,15 +93,13 @@ func GetBlueprintByProjectName(projectName string)
(*models.Blueprint, errors.Er
}
return nil, errors.Internal.Wrap(err, fmt.Sprintf("error
getting the blueprint from database with project %s", projectName))
}
- dbBlueprint, err = decryptDbBlueprint(dbBlueprint)
- if err != nil {
- return nil, err
- }
- blueprint := parseBlueprint(dbBlueprint)
return blueprint, nil
}
func validateBlueprintAndMakePlan(blueprint *models.Blueprint) errors.Error {
+ if len(blueprint.Settings) == 0 {
+ blueprint.Settings = nil
+ }
// validation
err := vld.Struct(blueprint)
if err != nil {
@@ -175,7 +153,6 @@ func validateBlueprintAndMakePlan(blueprint
*models.Blueprint) errors.Error {
return errors.Default.Wrap(err, "failed to markshal
plan")
}
}
-
return nil
}
@@ -185,14 +162,7 @@ func saveBlueprint(blueprint *models.Blueprint)
(*models.Blueprint, errors.Error
if err != nil {
return nil, errors.BadInput.WrapRaw(err)
}
-
- // save
- dbBlueprint := parseDbBlueprint(blueprint)
- dbBlueprint, err = encryptDbBlueprint(dbBlueprint)
- if err != nil {
- return nil, err
- }
- err = SaveDbBlueprint(dbBlueprint)
+ err = SaveDbBlueprint(blueprint)
if err != nil {
return nil, err
}
@@ -236,7 +206,7 @@ func PatchBlueprint(id uint64, body map[string]interface{})
(*models.Blueprint,
func ReloadBlueprints(c *cron.Cron) errors.Error {
enable := true
isManual := false
- dbBlueprints, _, err := GetDbBlueprints(&BlueprintQuery{Enable:
&enable, IsManual: &isManual})
+ blueprints, _, err := GetDbBlueprints(&BlueprintQuery{Enable: &enable,
IsManual: &isManual})
if err != nil {
return err
}
@@ -244,12 +214,7 @@ func ReloadBlueprints(c *cron.Cron) errors.Error {
c.Remove(e.ID)
}
c.Stop()
- for _, dbBlueprint := range dbBlueprints {
- dbBlueprint, err = decryptDbBlueprint(dbBlueprint)
- if err != nil {
- return err
- }
- blueprint := parseBlueprint(dbBlueprint)
+ for _, blueprint := range blueprints {
if err != nil {
blueprintLog.Error(err, failToCreateCronJob)
return err
@@ -266,10 +231,10 @@ func ReloadBlueprints(c *cron.Cron) errors.Error {
return errors.Default.Wrap(err, "created cron job
failed")
}
}
- if len(dbBlueprints) > 0 {
+ if len(blueprints) > 0 {
c.Start()
}
- logger.Info("total %d blueprints were scheduled", len(dbBlueprints))
+ logger.Info("total %d blueprints were scheduled", len(blueprints))
return nil
}
diff --git a/backend/server/services/blueprint_helper.go
b/backend/server/services/blueprint_helper.go
index d0403398f..adf5f6f39 100644
--- a/backend/server/services/blueprint_helper.go
+++ b/backend/server/services/blueprint_helper.go
@@ -19,33 +19,35 @@ package services
import (
"fmt"
- "github.com/apache/incubator-devlake/core/config"
"github.com/apache/incubator-devlake/core/dal"
"github.com/apache/incubator-devlake/core/errors"
"github.com/apache/incubator-devlake/core/models"
- "github.com/apache/incubator-devlake/core/plugin"
)
// SaveDbBlueprint accepts a Blueprint instance and upsert it to database
-func SaveDbBlueprint(dbBlueprint *models.DbBlueprint) errors.Error {
+func SaveDbBlueprint(blueprint *models.Blueprint) errors.Error {
var err error
- if dbBlueprint.ID != 0 {
- err = db.Update(&dbBlueprint)
+ if blueprint.ID != 0 {
+ err = db.Update(&blueprint)
} else {
- err = db.Create(&dbBlueprint)
+ err = db.Create(&blueprint)
}
if err != nil {
return errors.Default.Wrap(err, "error creating DB blueprint")
}
- err = db.Delete(&models.DbBlueprintLabel{}, dal.Where(`blueprint_id =
?`, dbBlueprint.ID))
+ err = db.Delete(&models.DbBlueprintLabel{}, dal.Where(`blueprint_id =
?`, blueprint.ID))
if err != nil {
return errors.Default.Wrap(err, "error delete DB blueprint's
old labelModels")
}
- if len(dbBlueprint.Labels) > 0 {
- for i := range dbBlueprint.Labels {
- dbBlueprint.Labels[i].BlueprintId = dbBlueprint.ID
+ if len(blueprint.Labels) > 0 {
+ blueprintLabels := make([]*models.DbBlueprintLabel, 0)
+ for i := range blueprint.Labels {
+ blueprintLabels = append(blueprintLabels,
&models.DbBlueprintLabel{
+ BlueprintId: blueprint.ID,
+ Name: blueprint.Labels[i],
+ })
}
- err = db.Create(&dbBlueprint.Labels)
+ err = db.Create(&blueprintLabels)
if err != nil {
return errors.Default.Wrap(err, "error creating DB
blueprint's labelModels")
}
@@ -54,9 +56,9 @@ func SaveDbBlueprint(dbBlueprint *models.DbBlueprint)
errors.Error {
}
// GetDbBlueprints returns a paginated list of Blueprints based on `query`
-func GetDbBlueprints(query *BlueprintQuery) ([]*models.DbBlueprint, int64,
errors.Error) {
+func GetDbBlueprints(query *BlueprintQuery) ([]*models.Blueprint, int64,
errors.Error) {
// process query parameters
- clauses := []dal.Clause{dal.From(&models.DbBlueprint{})}
+ clauses := []dal.Clause{dal.From(&models.Blueprint{})}
if query.Enable != nil {
clauses = append(clauses, dal.Where("enable = ?",
*query.Enable))
}
@@ -82,7 +84,7 @@ func GetDbBlueprints(query *BlueprintQuery)
([]*models.DbBlueprint, int64, error
dal.Offset(query.GetSkip()),
dal.Limit(query.GetPageSize()),
)
- dbBlueprints := make([]*models.DbBlueprint, 0)
+ dbBlueprints := make([]*models.Blueprint, 0)
err = db.All(&dbBlueprints, clauses...)
if err != nil {
return nil, 0, errors.Default.Wrap(err, "error getting DB count
of blueprints")
@@ -100,25 +102,25 @@ func GetDbBlueprints(query *BlueprintQuery)
([]*models.DbBlueprint, int64, error
}
// GetDbBlueprint returns the detail of a given Blueprint ID
-func GetDbBlueprint(dbBlueprintId uint64) (*models.DbBlueprint, errors.Error) {
- dbBlueprint := &models.DbBlueprint{}
- err := db.First(dbBlueprint, dal.Where("id = ?", dbBlueprintId))
+func GetDbBlueprint(blueprintId uint64) (*models.Blueprint, errors.Error) {
+ blueprint := &models.Blueprint{}
+ err := db.First(blueprint, dal.Where("id = ?", blueprintId))
if err != nil {
if db.IsErrorNotFound(err) {
return nil, errors.NotFound.Wrap(err, "could not find
blueprint in DB")
}
return nil, errors.Default.Wrap(err, "error getting blueprint
from DB")
}
- err = fillBlueprintDetail(dbBlueprint)
+ err = fillBlueprintDetail(blueprint)
if err != nil {
return nil, err
}
- return dbBlueprint, nil
+ return blueprint, nil
}
// GetDbBlueprintByProjectName returns the detail of a given projectName
-func GetDbBlueprintByProjectName(projectName string) (*models.DbBlueprint,
errors.Error) {
- dbBlueprint := &models.DbBlueprint{}
+func GetDbBlueprintByProjectName(projectName string) (*models.Blueprint,
errors.Error) {
+ dbBlueprint := &models.Blueprint{}
err := db.First(dbBlueprint, dal.Where("project_name = ?", projectName))
if err != nil {
if db.IsErrorNotFound(err) {
@@ -133,90 +135,8 @@ func GetDbBlueprintByProjectName(projectName string)
(*models.DbBlueprint, error
return dbBlueprint, nil
}
-// parseBlueprint
-func parseBlueprint(dbBlueprint *models.DbBlueprint) *models.Blueprint {
- labelList := []string{}
- for _, labelModel := range dbBlueprint.Labels {
- labelList = append(labelList, labelModel.Name)
- }
- blueprint := models.Blueprint{
- Name: dbBlueprint.Name,
- ProjectName: dbBlueprint.ProjectName,
- Mode: dbBlueprint.Mode,
- Plan: []byte(dbBlueprint.Plan),
- Enable: dbBlueprint.Enable,
- CronConfig: dbBlueprint.CronConfig,
- IsManual: dbBlueprint.IsManual,
- SkipOnFail: dbBlueprint.SkipOnFail,
- Settings: []byte(dbBlueprint.Settings),
- Model: dbBlueprint.Model,
- Labels: labelList,
- }
- if len(blueprint.Settings) == 0 {
- blueprint.Settings = nil
- }
- return &blueprint
-}
-
-// parseDbBlueprint
-func parseDbBlueprint(blueprint *models.Blueprint) *models.DbBlueprint {
- dbBlueprint := models.DbBlueprint{
- Name: blueprint.Name,
- ProjectName: blueprint.ProjectName,
- Mode: blueprint.Mode,
- Plan: string(blueprint.Plan),
- Enable: blueprint.Enable,
- CronConfig: blueprint.CronConfig,
- IsManual: blueprint.IsManual,
- SkipOnFail: blueprint.SkipOnFail,
- Settings: string(blueprint.Settings),
- Model: blueprint.Model,
- }
- dbBlueprint.Labels = []models.DbBlueprintLabel{}
- for _, label := range blueprint.Labels {
- dbBlueprint.Labels = append(dbBlueprint.Labels,
models.DbBlueprintLabel{
- // NOTICE: BlueprintId may be nil
- BlueprintId: blueprint.ID,
- Name: label,
- })
- }
- return &dbBlueprint
-}
-
-// encryptDbBlueprint
-func encryptDbBlueprint(dbBlueprint *models.DbBlueprint) (*models.DbBlueprint,
errors.Error) {
- encKey := config.GetConfig().GetString(plugin.EncodeKeyEnvStr)
- planEncrypt, err := plugin.Encrypt(encKey, dbBlueprint.Plan)
- if err != nil {
- return nil, err
- }
- dbBlueprint.Plan = planEncrypt
- settingsEncrypt, err := plugin.Encrypt(encKey, dbBlueprint.Settings)
- dbBlueprint.Settings = settingsEncrypt
- if err != nil {
- return nil, err
- }
- return dbBlueprint, nil
-}
-
-// decryptDbBlueprint
-func decryptDbBlueprint(dbBlueprint *models.DbBlueprint) (*models.DbBlueprint,
errors.Error) {
- encKey := config.GetConfig().GetString(plugin.EncodeKeyEnvStr)
- plan, err := plugin.Decrypt(encKey, dbBlueprint.Plan)
- if err != nil {
- return nil, err
- }
- dbBlueprint.Plan = plan
- settings, err := plugin.Decrypt(encKey, dbBlueprint.Settings)
- dbBlueprint.Settings = settings
- if err != nil {
- return nil, err
- }
- return dbBlueprint, nil
-}
-
-func fillBlueprintDetail(blueprint *models.DbBlueprint) errors.Error {
- err := db.All(&blueprint.Labels, dal.Where("blueprint_id = ?",
blueprint.ID))
+func fillBlueprintDetail(blueprint *models.Blueprint) errors.Error {
+ err := db.Pluck("name", &blueprint.Labels,
dal.From(&models.DbBlueprintLabel{}), dal.Where("blueprint_id = ?",
blueprint.ID))
if err != nil {
return errors.Internal.Wrap(err, "error getting the blueprint
labels from database")
}
diff --git a/backend/server/services/pipeline.go
b/backend/server/services/pipeline.go
index 4f6e02c4e..cd52e9daa 100644
--- a/backend/server/services/pipeline.go
+++ b/backend/server/services/pipeline.go
@@ -74,7 +74,7 @@ func pipelineServiceInit() {
} else {
// standalone mode: reset pipeline status
err := db.UpdateColumn(
- &models.DbPipeline{},
+ &models.Pipeline{},
"status", models.TASK_FAILED,
dal.Where("status = ?", models.TASK_RUNNING),
)
@@ -110,34 +110,29 @@ func pipelineServiceInit() {
// CreatePipeline and return the model
func CreatePipeline(newPipeline *models.NewPipeline) (*models.Pipeline,
errors.Error) {
- dbPipeline, err := CreateDbPipeline(newPipeline)
+ pipeline, err := CreateDbPipeline(newPipeline)
if err != nil {
return nil, errors.Convert(err)
}
- dbPipeline, err = decryptDbPipeline(dbPipeline)
+ err = fillPipelineDetail(pipeline)
if err != nil {
- return nil, err
+ return nil, errors.Convert(err)
}
- pipeline := parsePipeline(dbPipeline)
return pipeline, nil
}
// GetPipelines by query
func GetPipelines(query *PipelineQuery) ([]*models.Pipeline, int64,
errors.Error) {
- dbPipelines, i, err := GetDbPipelines(query)
+ pipelines, i, err := GetDbPipelines(query)
if err != nil {
return nil, 0, errors.Convert(err)
}
- pipelines := make([]*models.Pipeline, 0)
- for _, dbPipeline := range dbPipelines {
- dbPipeline, err = decryptDbPipeline(dbPipeline)
+ for _, p := range pipelines {
+ err = fillPipelineDetail(p)
if err != nil {
return nil, 0, err
}
- pipeline := parsePipeline(dbPipeline)
- pipelines = append(pipelines, pipeline)
}
-
return pipelines, i, nil
}
@@ -147,12 +142,11 @@ func GetPipeline(pipelineId uint64) (*models.Pipeline,
errors.Error) {
if err != nil {
return nil, err
}
- dbPipeline, err = decryptDbPipeline(dbPipeline)
+ err = fillPipelineDetail(dbPipeline)
if err != nil {
return nil, err
}
- pipeline := parsePipeline(dbPipeline)
- return pipeline, nil
+ return dbPipeline, nil
}
// GetPipelineLogsArchivePath creates an archive for the logs of this pipeline
and returns its file path
@@ -182,7 +176,7 @@ func RunPipelineInQueue(pipelineMaxParallel int64) {
panic(err)
}
globalPipelineLog.Info("get lock and wait next pipeline")
- dbPipeline := &models.DbPipeline{}
+ dbPipeline := &models.Pipeline{}
for {
cronLocker.Lock()
// prepare query to find an appropriate pipeline to
execute
@@ -212,7 +206,7 @@ func RunPipelineInQueue(pipelineMaxParallel int64) {
}
// mark the pipeline running
- err = db.UpdateColumns(&models.DbPipeline{}, []dal.DalSet{
+ err = db.UpdateColumns(&models.Pipeline{}, []dal.DalSet{
{ColumnName: "status", Value: models.TASK_RUNNING},
{ColumnName: "message", Value: ""},
{ColumnName: "began_at", Value: time.Now()},
@@ -221,17 +215,15 @@ func RunPipelineInQueue(pipelineMaxParallel int64) {
panic(err)
}
- // load pipeline
- dbPipeline, err = GetDbPipeline(dbPipeline.ID)
+ // add pipelineParallelLabels to runningParallelLabels
+ var pipelineParallelLabels []string
+ err = fillPipelineDetail(dbPipeline)
if err != nil {
panic(err)
}
-
- // add pipelineParallelLabels to runningParallelLabels
- var pipelineParallelLabels []string
for _, dbLabel := range dbPipeline.Labels {
- if strings.HasPrefix(dbLabel.Name, `parallel/`) {
- pipelineParallelLabels =
append(pipelineParallelLabels, dbLabel.Name)
+ if strings.HasPrefix(dbLabel, `parallel/`) {
+ pipelineParallelLabels =
append(pipelineParallelLabels, dbLabel)
}
}
runningParallelLabelLock.Lock()
@@ -262,7 +254,7 @@ func watchTemporalPipelines() {
// run forever
for range ticker.C {
// load all running pipeline from database
- runningDbPipelines := make([]models.DbPipeline, 0)
+ runningDbPipelines := make([]models.Pipeline, 0)
err := db.All(&runningDbPipelines, dal.Where("status =
?", models.TASK_RUNNING))
if err != nil {
panic(err)
@@ -380,7 +372,7 @@ func CancelPipeline(pipelineId uint64) errors.Error {
// prevent RunPipelineInQueue from consuming pending pipelines
cronLocker.Lock()
defer cronLocker.Unlock()
- pipeline := &models.DbPipeline{}
+ pipeline := &models.Pipeline{}
err := db.First(pipeline, dal.Where("id = ?", pipelineId))
if err != nil {
return errors.BadInput.New("pipeline not found")
@@ -516,7 +508,7 @@ func RerunPipeline(pipelineId uint64, task *models.Task)
([]*models.Task, errors
}
// mark pipline rerun
- err = db.UpdateColumn(&models.DbPipeline{},
+ err = db.UpdateColumn(&models.Pipeline{},
"status", models.TASK_RERUN,
dal.Where("id = ?", pipelineId),
)
diff --git a/backend/server/services/pipeline_helper.go
b/backend/server/services/pipeline_helper.go
index b49ddf819..5884bf532 100644
--- a/backend/server/services/pipeline_helper.go
+++ b/backend/server/services/pipeline_helper.go
@@ -23,19 +23,18 @@ import (
"github.com/apache/incubator-devlake/core/dal"
"github.com/apache/incubator-devlake/core/errors"
"github.com/apache/incubator-devlake/core/models"
- "github.com/apache/incubator-devlake/core/plugin"
)
// ErrBlueprintRunning indicates there is a running pipeline with the
specified blueprint_id
var ErrBlueprintRunning = errors.Default.New("the blueprint is running")
// CreateDbPipeline returns a NewPipeline
-func CreateDbPipeline(newPipeline *models.NewPipeline) (*models.DbPipeline,
errors.Error) {
+func CreateDbPipeline(newPipeline *models.NewPipeline) (*models.Pipeline,
errors.Error) {
cronLocker.Lock()
defer cronLocker.Unlock()
if newPipeline.BlueprintId > 0 {
count, err := db.Count(
- dal.From(&models.DbPipeline{}),
+ dal.From(&models.Pipeline{}),
dal.Where("blueprint_id = ? AND status IN ?",
newPipeline.BlueprintId, models.PendingTaskStatus),
)
if err != nil {
@@ -50,22 +49,18 @@ func CreateDbPipeline(newPipeline *models.NewPipeline)
(*models.DbPipeline, erro
return nil, err
}
// create pipeline object from posted data
- dbPipeline := &models.DbPipeline{
+ dbPipeline := &models.Pipeline{
Name: newPipeline.Name,
FinishedTasks: 0,
Status: models.TASK_CREATED,
Message: "",
SpentSeconds: 0,
- Plan: string(planByte),
+ Plan: planByte,
SkipOnFail: newPipeline.SkipOnFail,
}
if newPipeline.BlueprintId != 0 {
dbPipeline.BlueprintId = newPipeline.BlueprintId
}
- dbPipeline, err = encryptDbPipeline(dbPipeline)
- if err != nil {
- return nil, err
- }
// save pipeline to database
if err := db.Create(&dbPipeline); err != nil {
@@ -73,15 +68,15 @@ func CreateDbPipeline(newPipeline *models.NewPipeline)
(*models.DbPipeline, erro
return nil, errors.Internal.Wrap(err, "create pipeline failed")
}
- dbPipeline.Labels = []models.DbPipelineLabel{}
+ labels := make([]models.DbPipelineLabel, 0)
for _, label := range newPipeline.Labels {
- dbPipeline.Labels = append(dbPipeline.Labels,
models.DbPipelineLabel{
+ labels = append(labels, models.DbPipelineLabel{
PipelineId: dbPipeline.ID,
Name: label,
})
}
- if len(dbPipeline.Labels) > 0 {
- if err := db.Create(&dbPipeline.Labels); err != nil {
+ if len(newPipeline.Labels) > 0 {
+ if err := db.Create(&labels); err != nil {
globalPipelineLog.Error(err, "create pipeline's
labelModels failed: %v", err)
return nil, errors.Internal.Wrap(err, "create
pipeline's labelModels failed")
}
@@ -125,9 +120,9 @@ func CreateDbPipeline(newPipeline *models.NewPipeline)
(*models.DbPipeline, erro
}
// GetDbPipelines by query
-func GetDbPipelines(query *PipelineQuery) ([]*models.DbPipeline, int64,
errors.Error) {
+func GetDbPipelines(query *PipelineQuery) ([]*models.Pipeline, int64,
errors.Error) {
// process query parameters
- clauses := []dal.Clause{dal.From(&models.DbPipeline{})}
+ clauses := []dal.Clause{dal.From(&models.Pipeline{})}
if query.BlueprintId != 0 {
clauses = append(clauses, dal.Where("blueprint_id = ?",
query.BlueprintId))
}
@@ -139,8 +134,8 @@ func GetDbPipelines(query *PipelineQuery)
([]*models.DbPipeline, int64, errors.E
}
if query.Label != "" {
clauses = append(clauses,
- dal.Join("LEFT JOIN _devlake_pipeline_labels bl ON
bl.pipeline_id = _devlake_pipelines.id"),
- dal.Where("bl.name = ?", query.Label),
+ dal.Join("LEFT JOIN _devlake_pipeline_labels pl ON
pl.pipeline_id = _devlake_pipelines.id"),
+ dal.Where("pl.name = ?", query.Label),
)
}
@@ -156,7 +151,7 @@ func GetDbPipelines(query *PipelineQuery)
([]*models.DbPipeline, int64, errors.E
dal.Offset(query.GetSkip()),
dal.Limit(query.GetPageSize()),
)
- dbPipelines := make([]*models.DbPipeline, 0)
+ dbPipelines := make([]*models.Pipeline, 0)
err = db.All(&dbPipelines, clauses...)
if err != nil {
return nil, 0, errors.Default.Wrap(err, "error getting DB count
of pipelines")
@@ -174,8 +169,8 @@ func GetDbPipelines(query *PipelineQuery)
([]*models.DbPipeline, int64, errors.E
}
// GetDbPipeline by id
-func GetDbPipeline(pipelineId uint64) (*models.DbPipeline, errors.Error) {
- dbPipeline := &models.DbPipeline{}
+func GetDbPipeline(pipelineId uint64) (*models.Pipeline, errors.Error) {
+ dbPipeline := &models.Pipeline{}
err := db.First(dbPipeline, dal.Where("id = ?", pipelineId))
if err != nil {
if db.IsErrorNotFound(err) {
@@ -190,85 +185,8 @@ func GetDbPipeline(pipelineId uint64) (*models.DbPipeline,
errors.Error) {
return dbPipeline, nil
}
-// parsePipeline converts DbPipeline to Pipeline
-func parsePipeline(dbPipeline *models.DbPipeline) *models.Pipeline {
- labelList := []string{}
- for _, labelModel := range dbPipeline.Labels {
- labelList = append(labelList, labelModel.Name)
- }
- pipeline := models.Pipeline{
- Model: dbPipeline.Model,
- Name: dbPipeline.Name,
- BlueprintId: dbPipeline.BlueprintId,
- Plan: []byte(dbPipeline.Plan),
- TotalTasks: dbPipeline.TotalTasks,
- FinishedTasks: dbPipeline.FinishedTasks,
- BeganAt: dbPipeline.BeganAt,
- FinishedAt: dbPipeline.FinishedAt,
- Status: dbPipeline.Status,
- Message: dbPipeline.Message,
- ErrorName: dbPipeline.ErrorName,
- SpentSeconds: dbPipeline.SpentSeconds,
- Stage: dbPipeline.Stage,
- SkipOnFail: dbPipeline.SkipOnFail,
- Labels: labelList,
- }
- return &pipeline
-}
-
-// parseDbPipeline converts Pipeline to DbPipeline
-// nolint:unused
-func parseDbPipeline(pipeline *models.Pipeline) *models.DbPipeline {
- dbPipeline := models.DbPipeline{
- Model: pipeline.Model,
- Name: pipeline.Name,
- BlueprintId: pipeline.BlueprintId,
- Plan: string(pipeline.Plan),
- TotalTasks: pipeline.TotalTasks,
- FinishedTasks: pipeline.FinishedTasks,
- BeganAt: pipeline.BeganAt,
- FinishedAt: pipeline.FinishedAt,
- Status: pipeline.Status,
- Message: pipeline.Message,
- SpentSeconds: pipeline.SpentSeconds,
- Stage: pipeline.Stage,
- SkipOnFail: pipeline.SkipOnFail,
- }
- dbPipeline.Labels = []models.DbPipelineLabel{}
- for _, label := range pipeline.Labels {
- dbPipeline.Labels = append(dbPipeline.Labels,
models.DbPipelineLabel{
- // NOTICE: PipelineId may be nil
- PipelineId: pipeline.ID,
- Name: label,
- })
- }
- return &dbPipeline
-}
-
-// encryptDbPipeline encrypts dbPipeline.Plan
-func encryptDbPipeline(dbPipeline *models.DbPipeline) (*models.DbPipeline,
errors.Error) {
- encKey := cfg.GetString(plugin.EncodeKeyEnvStr)
- planEncrypt, err := plugin.Encrypt(encKey, dbPipeline.Plan)
- if err != nil {
- return nil, err
- }
- dbPipeline.Plan = planEncrypt
- return dbPipeline, nil
-}
-
-// encryptDbPipeline decrypts dbPipeline.Plan
-func decryptDbPipeline(dbPipeline *models.DbPipeline) (*models.DbPipeline,
errors.Error) {
- encKey := cfg.GetString(plugin.EncodeKeyEnvStr)
- plan, err := plugin.Decrypt(encKey, dbPipeline.Plan)
- if err != nil {
- return nil, err
- }
- dbPipeline.Plan = plan
- return dbPipeline, nil
-}
-
-func fillPipelineDetail(pipeline *models.DbPipeline) errors.Error {
- err := db.All(&pipeline.Labels, dal.Where("pipeline_id = ?",
pipeline.ID))
+func fillPipelineDetail(pipeline *models.Pipeline) errors.Error {
+ err := basicRes.GetDal().Pluck("name", &pipeline.Labels,
dal.From(&models.DbPipelineLabel{}), dal.Where("pipeline_id = ?", pipeline.ID))
if err != nil {
return errors.Internal.Wrap(err, "error getting the pipeline
labels from database")
}
diff --git a/backend/server/services/pipeline_runner.go
b/backend/server/services/pipeline_runner.go
index 5ab990c2b..cb3d27f4a 100644
--- a/backend/server/services/pipeline_runner.go
+++ b/backend/server/services/pipeline_runner.go
@@ -148,7 +148,7 @@ func runPipeline(pipelineId uint64) errors.Error {
// 1. TASK_COMPLETED: all tasks were executed sucessfully
// 2. TASK_FAILED: SkipOnFail=false with failed task(s)
// 3. TASK_PARTIAL: SkipOnFail=true with failed task(s)
-func ComputePipelineStatus(pipeline *models.DbPipeline, isCancelled bool)
(string, errors.Error) {
+func ComputePipelineStatus(pipeline *models.Pipeline, isCancelled bool)
(string, errors.Error) {
tasks, err := GetLatestTasksOfPipeline(pipeline)
if err != nil {
return "", err
@@ -182,7 +182,7 @@ func ComputePipelineStatus(pipeline *models.DbPipeline,
isCancelled bool) (strin
}
// GetLatestTasksOfPipeline returns latest tasks (reran tasks are excluding)
of specified pipeline
-func GetLatestTasksOfPipeline(pipeline *models.DbPipeline) ([]*models.Task,
errors.Error) {
+func GetLatestTasksOfPipeline(pipeline *models.Pipeline) ([]*models.Task,
errors.Error) {
task := &models.Task{}
cursor, err := db.Cursor(
dal.From(task),
diff --git a/backend/server/services/project.go
b/backend/server/services/project.go
index 0c5c00c36..f57c82de0 100644
--- a/backend/server/services/project.go
+++ b/backend/server/services/project.go
@@ -205,7 +205,7 @@ func PatchProject(name string, body map[string]interface{})
(*models.ApiOutputPr
// Blueprint
err = tx.UpdateColumn(
- &models.DbBlueprint{},
+ &models.Blueprint{},
"project_name", project.Name,
dal.Where("project_name = ?", name),
)
@@ -222,7 +222,7 @@ func PatchProject(name string, body map[string]interface{})
(*models.ApiOutputPr
// Blueprint
err = tx.UpdateColumn(
- &models.DbBlueprint{},
+ &models.Blueprint{},
"enable", projectInput.Enable,
dal.Where("project_name = ?", name),
)
diff --git a/backend/test/services/pipeline_runner_e2e_test.go
b/backend/test/services/pipeline_runner_e2e_test.go
index 337fae224..e3b3768ea 100644
--- a/backend/test/services/pipeline_runner_e2e_test.go
+++ b/backend/test/services/pipeline_runner_e2e_test.go
@@ -28,7 +28,7 @@ import (
func TestComputePipelineStatus(t *testing.T) {
db := services.GetBasicRes().GetDal()
// insert fake tasks to datbase
- pipeline := &models.DbPipeline{
+ pipeline := &models.Pipeline{
TotalTasks: 3,
}
err := db.Create(pipeline)