This is an automated email from the ASF dual-hosted git repository.
hez 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 990c19ded [feat-5517]: Add Delete API for Scope configs (#5558)
990c19ded is described below
commit 990c19ded0f6e23f60aa05cd15bb6bc3e9e66c95
Author: Keon Amini <[email protected]>
AuthorDate: Mon Jun 26 12:43:58 2023 -0500
[feat-5517]: Add Delete API for Scope configs (#5558)
* feat: Add Delete API for scope configs
* feat: deleting a scope-config now nulls out refs from scope tables
* feat: deleting a connection now cascade deletes it scopes and
scope-configs
* refactor: code simplification in IT client
* chore: fix linter nag
* fix: removed cascade deletion of scopes per requirement clarification
* refactor: use dal.UpdateColumn to set scope_config_id = null
---
.../helpers/pluginhelper/api/connection_helper.go | 29 +++++---
.../pluginhelper/api/scope_config_helper.go | 84 +++++++++++++++-------
.../pluginhelper/api/scope_generic_helper.go | 7 +-
backend/plugins/bamboo/api/init.go | 1 +
backend/plugins/bamboo/api/scope_config.go | 14 ++++
backend/plugins/bamboo/impl/impl.go | 5 +-
backend/plugins/bitbucket/api/init.go | 1 +
backend/plugins/bitbucket/api/scope_config.go | 14 ++++
backend/plugins/bitbucket/impl/impl.go | 5 +-
backend/plugins/github/api/init.go | 1 +
backend/plugins/github/api/scope_config.go | 14 ++++
backend/plugins/github/impl/impl.go | 5 +-
backend/plugins/gitlab/api/init.go | 1 +
backend/plugins/gitlab/api/scope_config.go | 14 ++++
backend/plugins/gitlab/impl/impl.go | 5 +-
.../gitlab/tasks/pipeline_commit_convertor.go | 16 ++---
backend/plugins/gitlab/tasks/pipeline_convertor.go | 14 ++--
backend/plugins/jenkins/api/init.go | 1 +
backend/plugins/jenkins/api/scope_config.go | 14 ++++
backend/plugins/jenkins/impl/impl.go | 5 +-
backend/plugins/jira/api/init.go | 1 +
backend/plugins/jira/api/scope_config.go | 14 ++++
backend/plugins/jira/impl/impl.go | 5 +-
backend/plugins/tapd/api/init.go | 1 +
backend/plugins/tapd/api/scope_config.go | 14 ++++
backend/plugins/tapd/impl/impl.go | 5 +-
backend/plugins/trello/api/init.go | 1 +
backend/plugins/trello/api/scope_config.go | 14 ++++
backend/plugins/trello/impl/impl.go | 5 +-
backend/plugins/zentao/api/init.go | 1 +
backend/plugins/zentao/api/scope_config.go | 14 ++++
backend/plugins/zentao/impl/impl.go | 5 +-
.../server/services/remote/plugin/default_api.go | 5 +-
.../services/remote/plugin/scope_config_api.go | 41 ++++++++---
backend/test/e2e/manual/azuredevops/azure_test.go | 18 ++++-
backend/test/e2e/manual/gitlab/gitlab_test.go | 23 ++++--
.../test/e2e/manual/pagerduty/pagerduty_test.go | 8 ++-
backend/test/e2e/remote/python_plugin_test.go | 53 ++++++++++++--
backend/test/helper/api.go | 9 +++
backend/test/helper/client.go | 32 ++++-----
backend/test/helper/client_factory.go | 2 +-
41 files changed, 405 insertions(+), 116 deletions(-)
diff --git a/backend/helpers/pluginhelper/api/connection_helper.go
b/backend/helpers/pluginhelper/api/connection_helper.go
index 70d9dfada..41fb3abf2 100644
--- a/backend/helpers/pluginhelper/api/connection_helper.go
+++ b/backend/helpers/pluginhelper/api/connection_helper.go
@@ -117,13 +117,26 @@ func (c *ConnectionApiHelper) Delete(connection
interface{}) (*services.Blueprin
if len(referencingBps) > 0 {
return services.NewBlueprintProjectPairs(referencingBps),
errors.Conflict.New("Found one or more blueprint/project references to this
connection")
}
- scopeModel := c.getScopeModel()
- count, err := c.db.Count(dal.From(scopeModel.TableName()),
dal.Where("connection_id = ?", connectionId))
+ src, err := c.getPluginSource()
if err != nil {
- return nil, errors.Default.Wrap(err, fmt.Sprintf("error
deleting scopes for plugin %s using connection %d", c.pluginName, connectionId))
+ return nil, err
}
- if count > 0 {
- return nil, errors.Conflict.New("Found one or more scope
references to this connection")
+ if scopeModel := src.Scope(); scopeModel != nil {
+ // ensure the connection has no scopes using it
+ count, err := c.db.Count(dal.From(scopeModel.TableName()),
dal.Where("connection_id = ?", connectionId))
+ if err != nil {
+ return nil, errors.Default.Wrap(err, fmt.Sprintf("error
counting scopes for plugin %s using connection %d", c.pluginName, connectionId))
+ }
+ if count > 0 {
+ return nil, errors.Conflict.New(fmt.Sprintf("Found %d
scopes using connection %d", count, connectionId))
+ }
+ }
+ if scopeConfigModel := src.ScopeConfig(); scopeConfigModel != nil {
+ // remove scope-configs that use this connection
+ err = CallDB(c.db.Delete, scopeConfigModel,
dal.Where("connection_id = ?", connectionId))
+ if err != nil {
+ return nil, errors.Default.Wrap(err, fmt.Sprintf("error
deleting scope-configs for plugin %s using connection %d", c.pluginName,
connectionId))
+ }
}
return nil, CallDB(c.db.Delete, connection)
}
@@ -151,11 +164,11 @@ func (c *ConnectionApiHelper) save(connection
interface{}, method func(entity in
return nil
}
-func (c *ConnectionApiHelper) getScopeModel() plugin.ToolLayerScope {
+func (c *ConnectionApiHelper) getPluginSource() (plugin.PluginSource,
errors.Error) {
pluginMeta, _ := plugin.GetPlugin(c.pluginName)
pluginSrc, ok := pluginMeta.(plugin.PluginSource)
if !ok {
- return nil
+ return nil, errors.Default.New("plugin doesn't implement
PluginSource")
}
- return pluginSrc.Scope()
+ return pluginSrc, nil
}
diff --git a/backend/helpers/pluginhelper/api/scope_config_helper.go
b/backend/helpers/pluginhelper/api/scope_config_helper.go
index c6b5f48d1..7fd0f9070 100644
--- a/backend/helpers/pluginhelper/api/scope_config_helper.go
+++ b/backend/helpers/pluginhelper/api/scope_config_helper.go
@@ -31,61 +31,64 @@ import (
)
// ScopeConfigHelper is used to write the CURD of scope config
-type ScopeConfigHelper[Tr dal.Tabler] struct {
- log log.Logger
- db dal.Dal
- validator *validator.Validate
+type ScopeConfigHelper[ScopeConfig dal.Tabler] struct {
+ log log.Logger
+ db dal.Dal
+ validator *validator.Validate
+ pluginName string
}
// NewScopeConfigHelper creates a ScopeConfigHelper for scope config management
func NewScopeConfigHelper[Tr dal.Tabler](
basicRes context.BasicRes,
vld *validator.Validate,
+ pluginName string,
) *ScopeConfigHelper[Tr] {
if vld == nil {
vld = validator.New()
}
return &ScopeConfigHelper[Tr]{
- log: basicRes.GetLogger(),
- db: basicRes.GetDal(),
- validator: vld,
+ log: basicRes.GetLogger(),
+ db: basicRes.GetDal(),
+ validator: vld,
+ pluginName: pluginName,
}
}
-func (t ScopeConfigHelper[Tr]) Create(input *plugin.ApiResourceInput)
(*plugin.ApiResourceOutput, errors.Error) {
+func (t ScopeConfigHelper[ScopeConfig]) Create(input *plugin.ApiResourceInput)
(*plugin.ApiResourceOutput, errors.Error) {
connectionId, e := strconv.ParseUint(input.Params["connectionId"], 10,
64)
if e != nil || connectionId == 0 {
return nil, errors.Default.Wrap(e, "the connection ID should be
an non-zero integer")
}
- var rule Tr
- if err := DecodeMapStruct(input.Body, &rule, false); err != nil {
+ var config ScopeConfig
+ if err := DecodeMapStruct(input.Body, &config, false); err != nil {
return nil, errors.Default.Wrap(err, "error in decoding scope
config")
}
if t.validator != nil {
- if err := t.validator.Struct(rule); err != nil {
+ if err := t.validator.Struct(config); err != nil {
return nil, errors.Default.Wrap(err, "error validating
scope config")
}
}
- valueConnectionId :=
reflect.ValueOf(&rule).Elem().FieldByName("ConnectionId")
+ valueConnectionId :=
reflect.ValueOf(&config).Elem().FieldByName("ConnectionId")
if valueConnectionId.IsValid() {
valueConnectionId.SetUint(connectionId)
}
- if err := t.db.Create(&rule); err != nil {
+ if err := t.db.Create(&config); err != nil {
if t.db.IsDuplicationError(err) {
return nil, errors.BadInput.New("there was a scope
config with the same name, please choose another name")
}
return nil, errors.BadInput.Wrap(err, "error on saving
ScopeConfig")
}
- return &plugin.ApiResourceOutput{Body: rule, Status: http.StatusOK}, nil
+ return &plugin.ApiResourceOutput{Body: config, Status: http.StatusOK},
nil
}
-func (t ScopeConfigHelper[Tr]) Update(input *plugin.ApiResourceInput)
(*plugin.ApiResourceOutput, errors.Error) {
+func (t ScopeConfigHelper[ScopeConfig]) Update(input *plugin.ApiResourceInput)
(*plugin.ApiResourceOutput, errors.Error) {
scopeConfigId, e := strconv.ParseUint(input.Params["id"], 10, 64)
if e != nil {
return nil, errors.Default.Wrap(e, "the scope config ID should
be an integer")
}
- var old Tr
+ var old ScopeConfig
err := t.db.First(&old, dal.Where("id = ?", scopeConfigId))
if err != nil {
return nil, errors.Default.Wrap(err, "error on saving
ScopeConfig")
@@ -104,29 +107,62 @@ func (t ScopeConfigHelper[Tr]) Update(input
*plugin.ApiResourceInput) (*plugin.A
return &plugin.ApiResourceOutput{Body: old, Status: http.StatusOK}, nil
}
-func (t ScopeConfigHelper[Tr]) Get(input *plugin.ApiResourceInput)
(*plugin.ApiResourceOutput, errors.Error) {
+func (t ScopeConfigHelper[ScopeConfig]) Get(input *plugin.ApiResourceInput)
(*plugin.ApiResourceOutput, errors.Error) {
scopeConfigId, err := strconv.ParseUint(input.Params["id"], 10, 64)
if err != nil {
return nil, errors.Default.Wrap(err, "the scope config ID
should be an integer")
}
- var rule Tr
- err = t.db.First(&rule, dal.Where("id = ?", scopeConfigId))
+ var config ScopeConfig
+ err = t.db.First(&config, dal.Where("id = ?", scopeConfigId))
if err != nil {
return nil, errors.Default.Wrap(err, "error on get ScopeConfig")
}
- return &plugin.ApiResourceOutput{Body: rule, Status: http.StatusOK}, nil
+ return &plugin.ApiResourceOutput{Body: config, Status: http.StatusOK},
nil
}
-func (t ScopeConfigHelper[Tr]) List(input *plugin.ApiResourceInput)
(*plugin.ApiResourceOutput, errors.Error) {
+func (t ScopeConfigHelper[ScopeConfig]) List(input *plugin.ApiResourceInput)
(*plugin.ApiResourceOutput, errors.Error) {
connectionId, e := strconv.ParseUint(input.Params["connectionId"], 10,
64)
if e != nil || connectionId == 0 {
return nil, errors.Default.Wrap(e, "the connection ID should be
an non-zero integer")
}
- var rules []Tr
+ var configs []ScopeConfig
limit, offset := GetLimitOffset(input.Query, "pageSize", "page")
- err := t.db.All(&rules, dal.Where("connection_id = ?", connectionId),
dal.Limit(limit), dal.Offset(offset))
+ err := t.db.All(&configs, dal.Where("connection_id = ?", connectionId),
dal.Limit(limit), dal.Offset(offset))
if err != nil {
return nil, errors.Default.Wrap(err, "error on get ScopeConfig
list")
}
- return &plugin.ApiResourceOutput{Body: rules, Status: http.StatusOK},
nil
+ return &plugin.ApiResourceOutput{Body: configs, Status: http.StatusOK},
nil
+}
+
+func (t ScopeConfigHelper[ScopeConfig]) Delete(input *plugin.ApiResourceInput)
(*plugin.ApiResourceOutput, errors.Error) {
+ scopeConfigId, err :=
errors.Convert01(strconv.ParseUint(input.Params["id"], 10, 64))
+ if err != nil {
+ return nil, errors.Default.Wrap(err, "the scope config ID
should be an integer")
+ }
+ connectionId, err :=
errors.Convert01(strconv.ParseUint(input.Params["connectionId"], 10, 64))
+ if err != nil {
+ return nil, errors.Default.Wrap(err, "the scope connection ID
should be an integer")
+ }
+ var config ScopeConfig
+ err = t.db.Delete(&config, dal.Where("id = ? AND connection_id = ?",
scopeConfigId, connectionId))
+ if err != nil {
+ return nil, errors.Default.Wrap(err, "error deleting
ScopeConfig")
+ }
+ err = t.nullOutScopeReferences(scopeConfigId)
+ if err != nil {
+ return nil, err
+ }
+ return &plugin.ApiResourceOutput{Body: nil, Status: http.StatusOK}, nil
+}
+func (t ScopeConfigHelper[ScopeConfig]) nullOutScopeReferences(scopeConfigId
uint64) errors.Error {
+ p, _ := plugin.GetPlugin(t.pluginName)
+ pluginSrc, ok := p.(plugin.PluginSource)
+ if !ok {
+ return errors.Default.New("plugin doesn't implement
PluginSource")
+ }
+ scopeModel := pluginSrc.Scope()
+ if scopeModel == nil {
+ return nil
+ }
+ return t.db.UpdateColumn(scopeModel.TableName(), "scope_config_id",
nil, dal.Where("scope_config_id = ?", scopeConfigId))
}
diff --git a/backend/helpers/pluginhelper/api/scope_generic_helper.go
b/backend/helpers/pluginhelper/api/scope_generic_helper.go
index 290977b8e..d6ab4642b 100644
--- a/backend/helpers/pluginhelper/api/scope_generic_helper.go
+++ b/backend/helpers/pluginhelper/api/scope_generic_helper.go
@@ -306,15 +306,10 @@ func (gs *GenericScopeApiHelper[Conn, Scope,
ScopeConfig]) DeleteScope(input *pl
if err != nil {
return nil, errors.Default.Wrap(err, fmt.Sprintf("error
verifying connection for connection ID %d", params.connectionId))
}
- // TODO: the Scope type in this helper must implement the
ToolLayerScope interface and we should enforce that.
scope, err := gs.dbHelper.GetScope(params.connectionId, params.scopeId)
if err != nil {
return nil, err
}
- toolScope, ok := interface{}(scope).(plugin.ToolLayerScope)
- if !ok {
- panic(fmt.Errorf("%v does not implement the
plugin.ToolLayerScope interface", scope))
- }
// now we can as scope to state its `Params` for data bloodline
identification
if refs, err := gs.getScopeReferences(params.connectionId,
params.scopeId); err != nil || refs != nil {
if err != nil {
@@ -322,7 +317,7 @@ func (gs *GenericScopeApiHelper[Conn, Scope, ScopeConfig])
DeleteScope(input *pl
}
return refs, errors.Conflict.New("Found one or more references
to this scope")
}
- if err = gs.deleteScopeData(toolScope); err != nil {
+ if err = gs.deleteScopeData(*scope); err != nil {
return nil, err
}
if !params.deleteDataOnly {
diff --git a/backend/plugins/bamboo/api/init.go
b/backend/plugins/bamboo/api/init.go
index 59cf12a83..3122788a3 100644
--- a/backend/plugins/bamboo/api/init.go
+++ b/backend/plugins/bamboo/api/init.go
@@ -64,5 +64,6 @@ func Init(br context.BasicRes, p plugin.PluginMeta) {
scopeConfigHelper = api.NewScopeConfigHelper[models.BambooScopeConfig](
basicRes,
vld,
+ p.Name(),
)
}
diff --git a/backend/plugins/bamboo/api/scope_config.go
b/backend/plugins/bamboo/api/scope_config.go
index 076840b37..01921146d 100644
--- a/backend/plugins/bamboo/api/scope_config.go
+++ b/backend/plugins/bamboo/api/scope_config.go
@@ -81,3 +81,17 @@ func GetScopeConfig(input *plugin.ApiResourceInput)
(*plugin.ApiResourceOutput,
func GetScopeConfigList(input *plugin.ApiResourceInput)
(*plugin.ApiResourceOutput, errors.Error) {
return scopeConfigHelper.List(input)
}
+
+// DeleteScopeConfig delete a scope config
+// @Summary delete a scope config
+// @Description delete a scope config
+// @Tags plugins/bamboo
+// @Param id path int true "id"
+// @Param connectionId path int true "connectionId"
+// @Success 200
+// @Failure 400 {object} shared.ApiBody "Bad Request"
+// @Failure 500 {object} shared.ApiBody "Internal Error"
+// @Router /plugins/bamboo/connections/{connectionId}/scope-configs/{id}
[DELETE]
+func DeleteScopeConfig(input *plugin.ApiResourceInput)
(*plugin.ApiResourceOutput, errors.Error) {
+ return scopeConfigHelper.Delete(input)
+}
diff --git a/backend/plugins/bamboo/impl/impl.go
b/backend/plugins/bamboo/impl/impl.go
index 540048269..1b9484263 100644
--- a/backend/plugins/bamboo/impl/impl.go
+++ b/backend/plugins/bamboo/impl/impl.go
@@ -221,8 +221,9 @@ func (p Bamboo) ApiResources()
map[string]map[string]plugin.ApiResourceHandler {
"GET": api.GetScopeConfigList,
},
"connections/:connectionId/scope-configs/:id": {
- "PATCH": api.UpdateScopeConfig,
- "GET": api.GetScopeConfig,
+ "PATCH": api.UpdateScopeConfig,
+ "GET": api.GetScopeConfig,
+ "DELETE": api.DeleteScopeConfig,
},
"connections/:connectionId/scopes": {
"GET": api.GetScopeList,
diff --git a/backend/plugins/bitbucket/api/init.go
b/backend/plugins/bitbucket/api/init.go
index 205ab59b5..dbdf77b0b 100644
--- a/backend/plugins/bitbucket/api/init.go
+++ b/backend/plugins/bitbucket/api/init.go
@@ -63,5 +63,6 @@ func Init(br context.BasicRes, p plugin.PluginMeta) {
scHelper = api.NewScopeConfigHelper[models.BitbucketScopeConfig](
basicRes,
vld,
+ p.Name(),
)
}
diff --git a/backend/plugins/bitbucket/api/scope_config.go
b/backend/plugins/bitbucket/api/scope_config.go
index 19e52f43d..fc0defde0 100644
--- a/backend/plugins/bitbucket/api/scope_config.go
+++ b/backend/plugins/bitbucket/api/scope_config.go
@@ -81,3 +81,17 @@ func GetScopeConfig(input *plugin.ApiResourceInput)
(*plugin.ApiResourceOutput,
func GetScopeConfigList(input *plugin.ApiResourceInput)
(*plugin.ApiResourceOutput, errors.Error) {
return scHelper.List(input)
}
+
+// DeleteScopeConfig delete a scope config
+// @Summary delete a scope config
+// @Description delete a scope config
+// @Tags plugins/bitbucket
+// @Param id path int true "id"
+// @Param connectionId path int true "connectionId"
+// @Success 200
+// @Failure 400 {object} shared.ApiBody "Bad Request"
+// @Failure 500 {object} shared.ApiBody "Internal Error"
+// @Router /plugins/bitbucket/connections/{connectionId}/scope-configs/{id}
[DELETE]
+func DeleteScopeConfig(input *plugin.ApiResourceInput)
(*plugin.ApiResourceOutput, errors.Error) {
+ return scHelper.Delete(input)
+}
diff --git a/backend/plugins/bitbucket/impl/impl.go
b/backend/plugins/bitbucket/impl/impl.go
index cab8224bf..812e37b8b 100644
--- a/backend/plugins/bitbucket/impl/impl.go
+++ b/backend/plugins/bitbucket/impl/impl.go
@@ -236,8 +236,9 @@ func (p Bitbucket) ApiResources()
map[string]map[string]plugin.ApiResourceHandle
"GET": api.GetScopeConfigList,
},
"connections/:connectionId/scope-configs/:id": {
- "PATCH": api.UpdateScopeConfig,
- "GET": api.GetScopeConfig,
+ "PATCH": api.UpdateScopeConfig,
+ "GET": api.GetScopeConfig,
+ "DELETE": api.DeleteScopeConfig,
},
}
}
diff --git a/backend/plugins/github/api/init.go
b/backend/plugins/github/api/init.go
index 45580331e..53877f920 100644
--- a/backend/plugins/github/api/init.go
+++ b/backend/plugins/github/api/init.go
@@ -77,6 +77,7 @@ func Init(br context.BasicRes, p plugin.PluginMeta) {
scHelper = api.NewScopeConfigHelper[models.GithubScopeConfig](
basicRes,
vld,
+ p.Name(),
)
remoteHelper = api.NewRemoteHelper[models.GithubConnection,
models.GithubRepo, repo, plugin.ApiGroup](
basicRes,
diff --git a/backend/plugins/github/api/scope_config.go
b/backend/plugins/github/api/scope_config.go
index edd3ac727..ee1ee8f8e 100644
--- a/backend/plugins/github/api/scope_config.go
+++ b/backend/plugins/github/api/scope_config.go
@@ -81,3 +81,17 @@ func GetScopeConfig(input *plugin.ApiResourceInput)
(*plugin.ApiResourceOutput,
func GetScopeConfigList(input *plugin.ApiResourceInput)
(*plugin.ApiResourceOutput, errors.Error) {
return scHelper.List(input)
}
+
+// DeleteScopeConfig delete a scope config
+// @Summary delete a scope config
+// @Description delete a scope config
+// @Tags plugins/github
+// @Param id path int true "id"
+// @Param connectionId path int true "connectionId"
+// @Success 200
+// @Failure 400 {object} shared.ApiBody "Bad Request"
+// @Failure 500 {object} shared.ApiBody "Internal Error"
+// @Router /plugins/github/connections/{connectionId}/scope-configs/{id}
[DELETE]
+func DeleteScopeConfig(input *plugin.ApiResourceInput)
(*plugin.ApiResourceOutput, errors.Error) {
+ return scHelper.Delete(input)
+}
diff --git a/backend/plugins/github/impl/impl.go
b/backend/plugins/github/impl/impl.go
index f07e7f096..08f2ef986 100644
--- a/backend/plugins/github/impl/impl.go
+++ b/backend/plugins/github/impl/impl.go
@@ -240,8 +240,9 @@ func (p Github) ApiResources()
map[string]map[string]plugin.ApiResourceHandler {
"GET": api.GetScopeConfigList,
},
"connections/:connectionId/scope-configs/:id": {
- "PATCH": api.UpdateScopeConfig,
- "GET": api.GetScopeConfig,
+ "PATCH": api.UpdateScopeConfig,
+ "GET": api.GetScopeConfig,
+ "DELETE": api.DeleteScopeConfig,
},
"connections/:connectionId/remote-scopes": {
"GET": api.RemoteScopes,
diff --git a/backend/plugins/gitlab/api/init.go
b/backend/plugins/gitlab/api/init.go
index c929569f2..4962c0220 100644
--- a/backend/plugins/gitlab/api/init.go
+++ b/backend/plugins/gitlab/api/init.go
@@ -63,5 +63,6 @@ func Init(br context.BasicRes, p plugin.PluginMeta) {
scHelper = api.NewScopeConfigHelper[models.GitlabScopeConfig](
basicRes,
vld,
+ p.Name(),
)
}
diff --git a/backend/plugins/gitlab/api/scope_config.go
b/backend/plugins/gitlab/api/scope_config.go
index f2681a890..4ef4ed700 100644
--- a/backend/plugins/gitlab/api/scope_config.go
+++ b/backend/plugins/gitlab/api/scope_config.go
@@ -81,3 +81,17 @@ func GetScopeConfig(input *plugin.ApiResourceInput)
(*plugin.ApiResourceOutput,
func GetScopeConfigList(input *plugin.ApiResourceInput)
(*plugin.ApiResourceOutput, errors.Error) {
return scHelper.List(input)
}
+
+// DeleteScopeConfig delete a scope config
+// @Summary delete a scope config
+// @Description delete a scope config
+// @Tags plugins/gitlab
+// @Param id path int true "id"
+// @Param connectionId path int true "connectionId"
+// @Success 200
+// @Failure 400 {object} shared.ApiBody "Bad Request"
+// @Failure 500 {object} shared.ApiBody "Internal Error"
+// @Router /plugins/gitlab/connections/{connectionId}/scope-configs/{id}
[DELETE]
+func DeleteScopeConfig(input *plugin.ApiResourceInput)
(*plugin.ApiResourceOutput, errors.Error) {
+ return scHelper.Delete(input)
+}
diff --git a/backend/plugins/gitlab/impl/impl.go
b/backend/plugins/gitlab/impl/impl.go
index e04079886..835020c24 100644
--- a/backend/plugins/gitlab/impl/impl.go
+++ b/backend/plugins/gitlab/impl/impl.go
@@ -255,8 +255,9 @@ func (p Gitlab) ApiResources()
map[string]map[string]plugin.ApiResourceHandler {
"GET": api.GetScopeConfigList,
},
"connections/:connectionId/scope-configs/:id": {
- "PATCH": api.UpdateScopeConfig,
- "GET": api.GetScopeConfig,
+ "PATCH": api.UpdateScopeConfig,
+ "GET": api.GetScopeConfig,
+ "DELETE": api.DeleteScopeConfig,
},
"connections/:connectionId/proxy/rest/*path": {
"GET": api.Proxy,
diff --git a/backend/plugins/gitlab/tasks/pipeline_commit_convertor.go
b/backend/plugins/gitlab/tasks/pipeline_commit_convertor.go
index 03cab5c88..5e76cad07 100644
--- a/backend/plugins/gitlab/tasks/pipeline_commit_convertor.go
+++ b/backend/plugins/gitlab/tasks/pipeline_commit_convertor.go
@@ -26,7 +26,7 @@ import (
"github.com/apache/incubator-devlake/core/models/domainlayer/didgen"
"github.com/apache/incubator-devlake/core/plugin"
helper "github.com/apache/incubator-devlake/helpers/pluginhelper/api"
- gitlabModels "github.com/apache/incubator-devlake/plugins/gitlab/models"
+ "github.com/apache/incubator-devlake/plugins/gitlab/models"
)
func init() {
@@ -46,40 +46,40 @@ func ConvertPipelineCommits(taskCtx plugin.SubTaskContext)
errors.Error {
db := taskCtx.GetDal()
data := taskCtx.GetData().(*GitlabTaskData)
- repo := &gitlabModels.GitlabProject{}
+ repo := &models.GitlabProject{}
err := db.First(repo, dal.Where("gitlab_id = ? and connection_id = ?",
data.Options.ProjectId, data.Options.ConnectionId))
if err != nil {
return err
}
- cursor, err := db.Cursor(dal.From(gitlabModels.GitlabPipelineProject{}),
+ cursor, err := db.Cursor(dal.From(models.GitlabPipelineProject{}),
dal.Where("project_id = ? and connection_id = ?",
data.Options.ProjectId, data.Options.ConnectionId))
if err != nil {
return err
}
defer cursor.Close()
- pipelineIdGen :=
didgen.NewDomainIdGenerator(&gitlabModels.GitlabPipeline{})
+ pipelineIdGen := didgen.NewDomainIdGenerator(&models.GitlabPipeline{})
converter, err := helper.NewDataConverter(helper.DataConverterArgs{
- InputRowType:
reflect.TypeOf(gitlabModels.GitlabPipelineProject{}),
+ InputRowType: reflect.TypeOf(models.GitlabPipelineProject{}),
Input: cursor,
RawDataSubTaskArgs: helper.RawDataSubTaskArgs{
Ctx: taskCtx,
- Params: gitlabModels.GitlabApiParams{
+ Params: models.GitlabApiParams{
ConnectionId: data.Options.ConnectionId,
ProjectId: data.Options.ProjectId,
},
Table: RAW_PIPELINE_TABLE,
},
Convert: func(inputRow interface{}) ([]interface{},
errors.Error) {
- gitlabPipelineCommit :=
inputRow.(*gitlabModels.GitlabPipelineProject)
+ gitlabPipelineCommit :=
inputRow.(*models.GitlabPipelineProject)
domainPipelineCommit := &devops.CiCDPipelineCommit{
PipelineId:
pipelineIdGen.Generate(data.Options.ConnectionId,
gitlabPipelineCommit.PipelineId),
CommitSha: gitlabPipelineCommit.Sha,
Branch: gitlabPipelineCommit.Ref,
- RepoId:
didgen.NewDomainIdGenerator(&gitlabModels.GitlabProject{}).
+ RepoId:
didgen.NewDomainIdGenerator(&models.GitlabProject{}).
Generate(gitlabPipelineCommit.ConnectionId, gitlabPipelineCommit.ProjectId),
RepoUrl: repo.WebUrl,
}
diff --git a/backend/plugins/gitlab/tasks/pipeline_convertor.go
b/backend/plugins/gitlab/tasks/pipeline_convertor.go
index a8ff94c5d..320a508ed 100644
--- a/backend/plugins/gitlab/tasks/pipeline_convertor.go
+++ b/backend/plugins/gitlab/tasks/pipeline_convertor.go
@@ -29,7 +29,7 @@ import (
"github.com/apache/incubator-devlake/core/models/domainlayer/didgen"
"github.com/apache/incubator-devlake/core/plugin"
helper "github.com/apache/incubator-devlake/helpers/pluginhelper/api"
- gitlabModels "github.com/apache/incubator-devlake/plugins/gitlab/models"
+ "github.com/apache/incubator-devlake/plugins/gitlab/models"
)
func init() {
@@ -49,29 +49,29 @@ func ConvertPipelines(taskCtx plugin.SubTaskContext)
errors.Error {
db := taskCtx.GetDal()
data := taskCtx.GetData().(*GitlabTaskData)
- cursor, err := db.Cursor(dal.From(gitlabModels.GitlabPipeline{}),
+ cursor, err := db.Cursor(dal.From(models.GitlabPipeline{}),
dal.Where("project_id = ? and connection_id = ?",
data.Options.ProjectId, data.Options.ConnectionId))
if err != nil {
return err
}
defer cursor.Close()
- pipelineIdGen :=
didgen.NewDomainIdGenerator(&gitlabModels.GitlabPipeline{})
- projectIdGen :=
didgen.NewDomainIdGenerator(&gitlabModels.GitlabProject{})
+ pipelineIdGen := didgen.NewDomainIdGenerator(&models.GitlabPipeline{})
+ projectIdGen := didgen.NewDomainIdGenerator(&models.GitlabProject{})
converter, err := helper.NewDataConverter(helper.DataConverterArgs{
- InputRowType: reflect.TypeOf(gitlabModels.GitlabPipeline{}),
+ InputRowType: reflect.TypeOf(models.GitlabPipeline{}),
Input: cursor,
RawDataSubTaskArgs: helper.RawDataSubTaskArgs{
Ctx: taskCtx,
- Params: gitlabModels.GitlabApiParams{
+ Params: models.GitlabApiParams{
ConnectionId: data.Options.ConnectionId,
ProjectId: data.Options.ProjectId,
},
Table: RAW_PIPELINE_TABLE,
},
Convert: func(inputRow interface{}) ([]interface{},
errors.Error) {
- gitlabPipeline :=
inputRow.(*gitlabModels.GitlabPipeline)
+ gitlabPipeline := inputRow.(*models.GitlabPipeline)
createdAt := time.Now()
if gitlabPipeline.GitlabCreatedAt != nil {
diff --git a/backend/plugins/jenkins/api/init.go
b/backend/plugins/jenkins/api/init.go
index 457a22049..d36b7f80e 100644
--- a/backend/plugins/jenkins/api/init.go
+++ b/backend/plugins/jenkins/api/init.go
@@ -64,5 +64,6 @@ func Init(br context.BasicRes, p plugin.PluginMeta) {
scHelper = api.NewScopeConfigHelper[models.JenkinsScopeConfig](
basicRes,
vld,
+ p.Name(),
)
}
diff --git a/backend/plugins/jenkins/api/scope_config.go
b/backend/plugins/jenkins/api/scope_config.go
index e9e75174b..fee76e6bb 100644
--- a/backend/plugins/jenkins/api/scope_config.go
+++ b/backend/plugins/jenkins/api/scope_config.go
@@ -81,3 +81,17 @@ func GetScopeConfig(input *plugin.ApiResourceInput)
(*plugin.ApiResourceOutput,
func GetScopeConfigList(input *plugin.ApiResourceInput)
(*plugin.ApiResourceOutput, errors.Error) {
return scHelper.List(input)
}
+
+// DeleteScopeConfig delete a scope config
+// @Summary delete a scope config
+// @Description delete a scope config
+// @Tags plugins/jenkins
+// @Param id path int true "id"
+// @Param connectionId path int true "connectionId"
+// @Success 200
+// @Failure 400 {object} shared.ApiBody "Bad Request"
+// @Failure 500 {object} shared.ApiBody "Internal Error"
+// @Router /plugins/jenkins/connections/{connectionId}/scope-configs/{id}
[DELETE]
+func DeleteScopeConfig(input *plugin.ApiResourceInput)
(*plugin.ApiResourceOutput, errors.Error) {
+ return scHelper.Delete(input)
+}
diff --git a/backend/plugins/jenkins/impl/impl.go
b/backend/plugins/jenkins/impl/impl.go
index c7e186e39..6bb0ed362 100644
--- a/backend/plugins/jenkins/impl/impl.go
+++ b/backend/plugins/jenkins/impl/impl.go
@@ -206,8 +206,9 @@ func (p Jenkins) ApiResources()
map[string]map[string]plugin.ApiResourceHandler
"GET": api.GetScopeConfigList,
},
"connections/:connectionId/scope-configs/:id": {
- "PATCH": api.UpdateScopeConfig,
- "GET": api.GetScopeConfig,
+ "PATCH": api.UpdateScopeConfig,
+ "GET": api.GetScopeConfig,
+ "DELETE": api.DeleteScopeConfig,
},
"connections/:connectionId/proxy/rest/*path": {
"GET": api.Proxy,
diff --git a/backend/plugins/jira/api/init.go b/backend/plugins/jira/api/init.go
index b82191c28..22143ef45 100644
--- a/backend/plugins/jira/api/init.go
+++ b/backend/plugins/jira/api/init.go
@@ -65,5 +65,6 @@ func Init(br context.BasicRes, p plugin.PluginMeta) {
scHelper = api.NewScopeConfigHelper[models.JiraScopeConfig](
basicRes,
vld,
+ p.Name(),
)
}
diff --git a/backend/plugins/jira/api/scope_config.go
b/backend/plugins/jira/api/scope_config.go
index 178c94a32..78ce0937d 100644
--- a/backend/plugins/jira/api/scope_config.go
+++ b/backend/plugins/jira/api/scope_config.go
@@ -177,6 +177,20 @@ func GetScopeConfigList(input *plugin.ApiResourceInput)
(*plugin.ApiResourceOutp
return scHelper.List(input)
}
+// DeleteScopeConfig delete a scope config
+// @Summary delete a scope config
+// @Description delete a scope config
+// @Tags plugins/jira
+// @Param id path int true "id"
+// @Param connectionId path int true "connectionId"
+// @Success 200
+// @Failure 400 {object} shared.ApiBody "Bad Request"
+// @Failure 500 {object} shared.ApiBody "Internal Error"
+// @Router /plugins/jira/connections/{connectionId}/scope-configs/{id} [DELETE]
+func DeleteScopeConfig(input *plugin.ApiResourceInput)
(*plugin.ApiResourceOutput, errors.Error) {
+ return scHelper.Delete(input)
+}
+
// GetApplicationTypes return issue application types
// @Summary return issue application types
// @Description return issue application types
diff --git a/backend/plugins/jira/impl/impl.go
b/backend/plugins/jira/impl/impl.go
index e9b513dea..f2df6626e 100644
--- a/backend/plugins/jira/impl/impl.go
+++ b/backend/plugins/jira/impl/impl.go
@@ -310,8 +310,9 @@ func (p Jira) ApiResources()
map[string]map[string]plugin.ApiResourceHandler {
"GET": api.GetScopeConfigList,
},
"connections/:connectionId/scope-configs/:id": {
- "PATCH": api.UpdateScopeConfig,
- "GET": api.GetScopeConfig,
+ "PATCH": api.UpdateScopeConfig,
+ "GET": api.GetScopeConfig,
+ "DELETE": api.DeleteScopeConfig,
},
"connections/:connectionId/application-types": {
"GET": api.GetApplicationTypes,
diff --git a/backend/plugins/tapd/api/init.go b/backend/plugins/tapd/api/init.go
index 8765f1c17..559acd70b 100644
--- a/backend/plugins/tapd/api/init.go
+++ b/backend/plugins/tapd/api/init.go
@@ -63,5 +63,6 @@ func Init(br context.BasicRes, p plugin.PluginMeta) {
scHelper = api.NewScopeConfigHelper[models.TapdScopeConfig](
basicRes,
vld,
+ p.Name(),
)
}
diff --git a/backend/plugins/tapd/api/scope_config.go
b/backend/plugins/tapd/api/scope_config.go
index 428b416d5..7f64714d0 100644
--- a/backend/plugins/tapd/api/scope_config.go
+++ b/backend/plugins/tapd/api/scope_config.go
@@ -81,3 +81,17 @@ func GetScopeConfig(input *plugin.ApiResourceInput)
(*plugin.ApiResourceOutput,
func GetScopeConfigList(input *plugin.ApiResourceInput)
(*plugin.ApiResourceOutput, errors.Error) {
return scHelper.List(input)
}
+
+// DeleteScopeConfig delete a scope config
+// @Summary delete a scope config
+// @Description delete a scope config
+// @Tags plugins/tapd
+// @Param id path int true "id"
+// @Param connectionId path int true "connectionId"
+// @Success 200
+// @Failure 400 {object} shared.ApiBody "Bad Request"
+// @Failure 500 {object} shared.ApiBody "Internal Error"
+// @Router /plugins/tapd/connections/{connectionId}/scope-configs/{id} [DELETE]
+func DeleteScopeConfig(input *plugin.ApiResourceInput)
(*plugin.ApiResourceOutput, errors.Error) {
+ return scHelper.Delete(input)
+}
diff --git a/backend/plugins/tapd/impl/impl.go
b/backend/plugins/tapd/impl/impl.go
index c6ed4d51b..b77ca2d21 100644
--- a/backend/plugins/tapd/impl/impl.go
+++ b/backend/plugins/tapd/impl/impl.go
@@ -320,8 +320,9 @@ func (p Tapd) ApiResources()
map[string]map[string]plugin.ApiResourceHandler {
"GET": api.GetScopeConfigList,
},
"connections/:connectionId/scope-configs/:id": {
- "PATCH": api.UpdateScopeConfig,
- "GET": api.GetScopeConfig,
+ "PATCH": api.UpdateScopeConfig,
+ "GET": api.GetScopeConfig,
+ "DELETE": api.DeleteScopeConfig,
},
}
}
diff --git a/backend/plugins/trello/api/init.go
b/backend/plugins/trello/api/init.go
index a27808fea..223c5272a 100644
--- a/backend/plugins/trello/api/init.go
+++ b/backend/plugins/trello/api/init.go
@@ -56,5 +56,6 @@ func Init(br context.BasicRes, p plugin.PluginMeta) {
scHelper = api.NewScopeConfigHelper[models.TrelloScopeConfig](
basicRes,
vld,
+ p.Name(),
)
}
diff --git a/backend/plugins/trello/api/scope_config.go
b/backend/plugins/trello/api/scope_config.go
index c8ee64b02..4562ff109 100644
--- a/backend/plugins/trello/api/scope_config.go
+++ b/backend/plugins/trello/api/scope_config.go
@@ -77,3 +77,17 @@ func GetScopeConfig(input *plugin.ApiResourceInput)
(*plugin.ApiResourceOutput,
func GetScopeConfigList(input *plugin.ApiResourceInput)
(*plugin.ApiResourceOutput, errors.Error) {
return scHelper.List(input)
}
+
+// DeleteScopeConfig delete a scope config
+// @Summary delete a scope config
+// @Description delete a scope config
+// @Tags plugins/trello
+// @Param id path int true "id"
+// @Param connectionId path int true "connectionId"
+// @Success 200
+// @Failure 400 {object} shared.ApiBody "Bad Request"
+// @Failure 500 {object} shared.ApiBody "Internal Error"
+// @Router /plugins/trello/connections/{connectionId}/scope-configs/{id}
[DELETE]
+func DeleteScopeConfig(input *plugin.ApiResourceInput)
(*plugin.ApiResourceOutput, errors.Error) {
+ return scHelper.Delete(input)
+}
diff --git a/backend/plugins/trello/impl/impl.go
b/backend/plugins/trello/impl/impl.go
index b49180055..e20e5ad86 100644
--- a/backend/plugins/trello/impl/impl.go
+++ b/backend/plugins/trello/impl/impl.go
@@ -175,8 +175,9 @@ func (p Trello) ApiResources()
map[string]map[string]plugin.ApiResourceHandler {
"GET": api.GetScopeConfigList,
},
"connections/:connectionId/scope-configs/:id": {
- "PATCH": api.UpdateScopeConfig,
- "GET": api.GetScopeConfig,
+ "PATCH": api.UpdateScopeConfig,
+ "GET": api.GetScopeConfig,
+ "DELETE": api.DeleteScopeConfig,
},
"connections/:connectionId/scopes/:boardId": {
"GET": api.GetScope,
diff --git a/backend/plugins/zentao/api/init.go
b/backend/plugins/zentao/api/init.go
index 33d665dfc..944e7f017 100644
--- a/backend/plugins/zentao/api/init.go
+++ b/backend/plugins/zentao/api/init.go
@@ -90,5 +90,6 @@ func Init(br context.BasicRes, p plugin.PluginMeta) {
scHelper = api.NewScopeConfigHelper[models.ZentaoScopeConfig](
basicRes,
vld,
+ p.Name(),
)
}
diff --git a/backend/plugins/zentao/api/scope_config.go
b/backend/plugins/zentao/api/scope_config.go
index b598f52f9..eb11ac6d7 100644
--- a/backend/plugins/zentao/api/scope_config.go
+++ b/backend/plugins/zentao/api/scope_config.go
@@ -81,3 +81,17 @@ func GetScopeConfig(input *plugin.ApiResourceInput)
(*plugin.ApiResourceOutput,
func GetScopeConfigList(input *plugin.ApiResourceInput)
(*plugin.ApiResourceOutput, errors.Error) {
return scHelper.List(input)
}
+
+// DeleteScopeConfig delete a scope config
+// @Summary delete a scope config
+// @Description delete a scope config
+// @Tags plugins/zentao
+// @Param id path int true "id"
+// @Param connectionId path int true "connectionId"
+// @Success 200
+// @Failure 400 {object} shared.ApiBody "Bad Request"
+// @Failure 500 {object} shared.ApiBody "Internal Error"
+// @Router /plugins/zentao/connections/{connectionId}/scope-configs/{id}
[DELETE]
+func DeleteScopeConfig(input *plugin.ApiResourceInput)
(*plugin.ApiResourceOutput, errors.Error) {
+ return scHelper.Delete(input)
+}
diff --git a/backend/plugins/zentao/impl/impl.go
b/backend/plugins/zentao/impl/impl.go
index 7069908c0..cd36ca648 100644
--- a/backend/plugins/zentao/impl/impl.go
+++ b/backend/plugins/zentao/impl/impl.go
@@ -282,8 +282,9 @@ func (p Zentao) ApiResources()
map[string]map[string]plugin.ApiResourceHandler {
"GET": api.GetScopeConfigList,
},
"connections/:connectionId/scope-configs/:id": {
- "PATCH": api.UpdateScopeConfig,
- "GET": api.GetScopeConfig,
+ "PATCH": api.UpdateScopeConfig,
+ "GET": api.GetScopeConfig,
+ "DELETE": api.DeleteScopeConfig,
},
"connections/:connectionId/remote-scopes": {
"GET": api.RemoteScopes,
diff --git a/backend/server/services/remote/plugin/default_api.go
b/backend/server/services/remote/plugin/default_api.go
index 759618a6d..b0c2c6751 100644
--- a/backend/server/services/remote/plugin/default_api.go
+++ b/backend/server/services/remote/plugin/default_api.go
@@ -76,8 +76,9 @@ func GetDefaultAPI(
"GET": papi.ListScopeConfigs,
},
"connections/:connectionId/scope-configs/:id": {
- "GET": papi.GetScopeConfig,
- "PATCH": papi.PatchScopeConfig,
+ "GET": papi.GetScopeConfig,
+ "PATCH": papi.PatchScopeConfig,
+ "DELETE": papi.DeleteScopeConfig,
},
"connections/:connectionId/remote-scopes": {
"GET": papi.GetRemoteScopes,
diff --git a/backend/server/services/remote/plugin/scope_config_api.go
b/backend/server/services/remote/plugin/scope_config_api.go
index 42f1f7cf6..c772e9fa0 100644
--- a/backend/server/services/remote/plugin/scope_config_api.go
+++ b/backend/server/services/remote/plugin/scope_config_api.go
@@ -18,6 +18,7 @@ limitations under the License.
package plugin
import (
+ "github.com/apache/incubator-devlake/server/services/remote/models"
"net/http"
"strconv"
@@ -47,7 +48,7 @@ func (pa *pluginAPI) PostScopeConfigs(input
*plugin.ApiResourceInput) (*plugin.A
}
func (pa *pluginAPI) PatchScopeConfig(input *plugin.ApiResourceInput)
(*plugin.ApiResourceOutput, errors.Error) {
- connectionId, trId, err := extractTrParam(input.Params)
+ connectionId, trId, err := extractConfigParam(input.Params)
if err != nil {
return nil, err
}
@@ -76,11 +77,11 @@ func (pa *pluginAPI) PatchScopeConfig(input
*plugin.ApiResourceInput) (*plugin.A
func (pa *pluginAPI) GetScopeConfig(input *plugin.ApiResourceInput)
(*plugin.ApiResourceOutput, errors.Error) {
scopeConfig := pa.scopeConfigType.New()
db := basicRes.GetDal()
- connectionId, trId, err := extractTrParam(input.Params)
+ connectionId, configId, err := extractConfigParam(input.Params)
if err != nil {
return nil, err
}
- err = api.CallDB(db.First, scopeConfig, dal.Where("connection_id = ?
AND id = ?", connectionId, trId))
+ err = api.CallDB(db.First, scopeConfig, dal.Where("connection_id = ?
AND id = ?", connectionId, configId))
if err != nil {
return nil, errors.Default.Wrap(err, "no scope config with
given id")
}
@@ -103,15 +104,39 @@ func (pa *pluginAPI) ListScopeConfigs(input
*plugin.ApiResourceInput) (*plugin.A
return &plugin.ApiResourceOutput{Body: scopeConfigs.Unwrap()}, nil
}
-func extractTrParam(params map[string]string) (connectionId uint64,
transformationId uint64, err errors.Error) {
+func (pa *pluginAPI) DeleteScopeConfig(input *plugin.ApiResourceInput)
(*plugin.ApiResourceOutput, errors.Error) {
+ connectionId, configId, err := extractConfigParam(input.Params)
+ if err != nil {
+ return nil, err
+ }
+ scopeConfig := pa.scopeConfigType.New()
+ db := basicRes.GetDal()
+ err = api.CallDB(db.Delete, scopeConfig, dal.Where("connection_id = ?
AND id = ?", connectionId, configId))
+ if err != nil {
+ return nil, errors.Default.Wrap(err, "no scope config with
given id")
+ }
+ err = pa.nullOutScopeReferences(configId)
+ if err != nil {
+ return nil, err
+ }
+ return &plugin.ApiResourceOutput{Body: scopeConfig.Unwrap()}, nil
+}
+
+func (pa *pluginAPI) nullOutScopeReferences(scopeConfigId uint64) errors.Error
{
+ scopeModel := models.NewDynamicScopeModel(pa.scopeType)
+ db := basicRes.GetDal()
+ return db.UpdateColumn(scopeModel.TableName(), "scope_config_id", nil,
dal.Where("scope_config_id = ?", scopeConfigId))
+}
+
+func extractConfigParam(params map[string]string) (connectionId uint64,
configId uint64, err errors.Error) {
connectionId, _ = strconv.ParseUint(params["connectionId"], 10, 64)
- transformationId, _ = strconv.ParseUint(params["id"], 10, 64)
+ configId, _ = strconv.ParseUint(params["id"], 10, 64)
if connectionId == 0 {
return 0, 0, errors.BadInput.New("invalid connectionId")
}
- if transformationId == 0 {
- return 0, 0, errors.BadInput.New("invalid transformationId")
+ if configId == 0 {
+ return 0, 0, errors.BadInput.New("invalid configId")
}
- return connectionId, transformationId, nil
+ return connectionId, configId, nil
}
diff --git a/backend/test/e2e/manual/azuredevops/azure_test.go
b/backend/test/e2e/manual/azuredevops/azure_test.go
index 012068700..fe2cdd35b 100644
--- a/backend/test/e2e/manual/azuredevops/azure_test.go
+++ b/backend/test/e2e/manual/azuredevops/azure_test.go
@@ -27,6 +27,8 @@ import (
pluginmodels
"github.com/apache/incubator-devlake/plugins/pagerduty/models"
"github.com/apache/incubator-devlake/test/helper"
"github.com/stretchr/testify/require"
+ "net/http"
+ "strings"
"testing"
"time"
)
@@ -43,8 +45,8 @@ func TestAzure(t *testing.T) {
CreateServer: true,
DropDb: false,
TruncateDb: true,
- Plugins: map[string]plugin.PluginMeta{
- "gitextractor": gitextractor.GitExtractor{},
+ Plugins: []plugin.PluginMeta{
+ gitextractor.GitExtractor{},
},
})
client.SetTimeout(60 * time.Second)
@@ -133,12 +135,16 @@ func TestAzure(t *testing.T) {
require.Equal(t, models.TASK_COMPLETED, pipeline.Status)
createdScopesList := client.ListScopes(azurePlugin,
connection.ID, true)
require.True(t, len(createdScopesList) > 0)
+
client.SetExpectedStatusCode(http.StatusConflict).DeleteConnection(azurePlugin,
connection.ID)
+ client.DeleteScopeConfig(azurePlugin, connection.ID,
repoConfig.ID)
+ client.DeleteBlueprint(bp.ID)
for _, scope := range createdScopesList {
scopeCast :=
helper.Cast[pluginmodels.Service](scope.Scope)
fmt.Printf("Deleting scope %s\n", scopeCast.Id)
client.DeleteScope(azurePlugin, connection.ID,
scopeCast.Id, false)
fmt.Printf("Deleted scope %s\n", scopeCast.Id)
}
+ client.DeleteConnection(azurePlugin, connection.ID)
})
fmt.Println("========DONE=======")
}
@@ -147,8 +153,14 @@ func remoteScopesToScopes(remoteScopes
helper.RemoteScopesOutput, filters []stri
var a []any
for _, c := range remoteScopes.Children {
repo := helper.Cast[AzureGitRepo](c.Data)
- if len(filters) == 0 || helper.Contains(filters, repo.Name) {
+ if len(filters) == 0 {
a = append(a, repo)
+ } else {
+ for _, f := range filters {
+ if len(filters) == 0 ||
strings.Contains(repo.Name, f) {
+ a = append(a, repo)
+ }
+ }
}
}
return a
diff --git a/backend/test/e2e/manual/gitlab/gitlab_test.go
b/backend/test/e2e/manual/gitlab/gitlab_test.go
index c4b0d8ad7..9aea5c7c5 100644
--- a/backend/test/e2e/manual/gitlab/gitlab_test.go
+++ b/backend/test/e2e/manual/gitlab/gitlab_test.go
@@ -29,6 +29,7 @@ import (
pluginmodels "github.com/apache/incubator-devlake/plugins/gitlab/models"
"github.com/apache/incubator-devlake/test/helper"
"github.com/stretchr/testify/require"
+ "net/http"
"testing"
)
@@ -58,15 +59,15 @@ func TestGitlabPlugin(t *testing.T) {
CreateServer: true,
DropDb: false,
TruncateDb: true,
- Plugins: map[string]plugin.PluginMeta{
- "gitlab": gitlab.Gitlab(""),
- "gitextractor": gitextractor.GitExtractor{},
+ Plugins: []plugin.PluginMeta{
+ gitlab.Gitlab(""),
+ gitextractor.GitExtractor{},
},
})
cfg := helper.GetTestConfig[TestConfig]()
connection := createConnection(cfg, client)
t.Run("blueprint v200", func(t *testing.T) {
- rule :=
helper.Cast[pluginmodels.GitlabScopeConfig](client.CreateScopeConfig("gitlab",
connection.ID,
+ scopeConfig :=
helper.Cast[pluginmodels.GitlabScopeConfig](client.CreateScopeConfig("gitlab",
connection.ID,
pluginmodels.GitlabScopeConfig{
ScopeConfig: common.ScopeConfig{
Entities: []string{
@@ -75,7 +76,7 @@ func TestGitlabPlugin(t *testing.T) {
plugin.DOMAIN_TYPE_CODE_REVIEW,
},
},
- Name: "rule-1",
+ Name: "config-1",
PrType: "",
PrComponent: "",
PrBodyClosePattern: "",
@@ -89,7 +90,7 @@ func TestGitlabPlugin(t *testing.T) {
ProductionPattern: ".*", // this
triggers dora
Refdiff: map[string]any{}, // this
is technically a true/false (nil or not)
}))
- _ = rule
+ _ = scopeConfig
remoteScopes := client.RemoteScopes(helper.RemoteScopesQuery{
PluginName: pluginName,
ConnectionId: connection.ID,
@@ -113,7 +114,7 @@ func TestGitlabPlugin(t *testing.T) {
if remoteScope.Type == "scope" {
data :=
helper.Cast[pluginmodels.GitlabProject](remoteScope.Data)
if len(cfg.Projects) == 0 ||
helper.Contains(cfg.Projects, data.Name) {
- data.ScopeConfigId = rule.ID
+ data.ScopeConfigId = scopeConfig.ID
scopeData = append(scopeData, data)
}
}
@@ -150,6 +151,14 @@ func TestGitlabPlugin(t *testing.T) {
fmt.Printf("=========================Triggering blueprint for
project %s =========================\n", outputProject.Name)
pipeline := client.TriggerBlueprint(bp.ID)
require.Equal(t, models.TASK_COMPLETED, pipeline.Status)
+
client.SetExpectedStatusCode(http.StatusConflict).DeleteConnection(pluginName,
connection.ID)
+ client.DeleteScopeConfig(pluginName, connection.ID,
scopeConfig.ID)
+ client.DeleteBlueprint(bp.ID)
+ for _, scope := range listedScopes {
+ project :=
helper.Cast[pluginmodels.GitlabProject](scope.Scope)
+ client.DeleteScope(pluginName, connection.ID,
project.ScopeId(), false)
+ }
+ client.DeleteConnection(pluginName, connection.ID)
})
fmt.Println("======DONE======")
}
diff --git a/backend/test/e2e/manual/pagerduty/pagerduty_test.go
b/backend/test/e2e/manual/pagerduty/pagerduty_test.go
index d8257e2c5..12bd7b2f8 100644
--- a/backend/test/e2e/manual/pagerduty/pagerduty_test.go
+++ b/backend/test/e2e/manual/pagerduty/pagerduty_test.go
@@ -27,6 +27,7 @@ import (
pluginmodels
"github.com/apache/incubator-devlake/plugins/pagerduty/models"
"github.com/apache/incubator-devlake/test/helper"
"github.com/stretchr/testify/require"
+ "net/http"
"testing"
"time"
)
@@ -41,8 +42,8 @@ func TestPagerDutyPlugin(t *testing.T) {
CreateServer: true,
DropDb: false,
TruncateDb: true,
- Plugins: map[string]plugin.PluginMeta{
- pluginName: &impl.PagerDuty{},
+ Plugins: []plugin.PluginMeta{
+ &impl.PagerDuty{},
},
})
client.SetTimeout(0)
@@ -101,12 +102,15 @@ func TestPagerDutyPlugin(t *testing.T) {
require.Equal(t, models.TASK_COMPLETED, pipeline.Status)
createdScopesList := client.ListScopes(pluginName,
connection.ID, true)
require.True(t, len(createdScopesList) > 0)
+
client.SetExpectedStatusCode(http.StatusConflict).DeleteConnection(pluginName,
connection.ID)
+ client.DeleteBlueprint(bp.ID)
for _, scope := range createdScopesList {
scopeCast :=
helper.Cast[pluginmodels.Service](scope.Scope)
fmt.Printf("Deleting scope %s\n", scopeCast.Id)
client.DeleteScope(pluginName, connection.ID,
scopeCast.Id, false)
fmt.Printf("Deleted scope %s\n", scopeCast.Id)
}
+ client.DeleteConnection(pluginName, connection.ID)
})
fmt.Println("======DONE======")
}
diff --git a/backend/test/e2e/remote/python_plugin_test.go
b/backend/test/e2e/remote/python_plugin_test.go
index 3b0bbfc80..10b778ff2 100644
--- a/backend/test/e2e/remote/python_plugin_test.go
+++ b/backend/test/e2e/remote/python_plugin_test.go
@@ -56,19 +56,31 @@ func TestDeleteConnection_Conflict(t *testing.T) {
conns := client.ListConnections(PLUGIN_NAME)
require.Equal(t, 1, len(conns))
require.Equal(t, TOKEN, conns[0].Token)
- refs :=
client.SetExpectedStatusCode(http.StatusConflict).DeleteConnection(PLUGIN_NAME,
conns[0].ID)
+ refs :=
client.SetExpectedStatusCode(http.StatusConflict).DeleteConnection(PLUGIN_NAME,
params.connection.ID)
require.Equal(t, 1, len(refs.Projects))
require.Equal(t, 1, len(refs.Blueprints))
client.DeleteBlueprint(params.blueprints[0].ID)
- refs =
client.SetExpectedStatusCode(http.StatusConflict).DeleteConnection(PLUGIN_NAME,
conns[0].ID)
- // should still conflict because we have scopes tied to this connection
+
client.SetExpectedStatusCode(http.StatusConflict).DeleteConnection(PLUGIN_NAME,
params.connection.ID)
+ client.DeleteScope(PLUGIN_NAME, params.connection.ID, params.scope.Id,
false)
+ client.DeleteConnection(PLUGIN_NAME, conns[0].ID)
+}
+
+func TestDeleteConnection_WithDependentScopesAndConfig(t *testing.T) {
+ client := CreateClient(t)
+ connection := CreateTestConnection(client)
+ config := CreateTestScopeConfig(client, connection.ID)
+ scope := CreateTestScope(client, config, connection.ID)
+ refs :=
client.SetExpectedStatusCode(http.StatusConflict).DeleteConnection(PLUGIN_NAME,
connection.ID)
require.Equal(t, 0, len(refs.Projects))
require.Equal(t, 0, len(refs.Blueprints))
- client.DeleteScope(PLUGIN_NAME, params.connection.ID, params.scope.Id,
false)
- refs = client.DeleteConnection(PLUGIN_NAME, conns[0].ID)
+ client.DeleteScope(PLUGIN_NAME, connection.ID, scope.Id, false)
+ refs = client.DeleteConnection(PLUGIN_NAME, connection.ID)
require.Equal(t, 0, len(refs.Projects))
require.Equal(t, 0, len(refs.Blueprints))
-
+ scopeRes :=
client.SetExpectedStatusCode(http.StatusBadRequest).ListScopes(PLUGIN_NAME,
connection.ID, false)
+ require.Equal(t, 0, len(scopeRes))
+ configs := client.ListScopeConfigs(PLUGIN_NAME, connection.ID)
+ require.Equal(t, 0, len(configs))
}
func TestRemoteScopeGroups(t *testing.T) {
@@ -262,3 +274,32 @@ func TestUpdateScopeConfig(t *testing.T) {
require.Equal(t, "new name", scopeConfig.Name)
require.Equal(t, "new env", scopeConfig.Env)
}
+
+func TestDeleteScopeConfig(t *testing.T) {
+ client := CreateClient(t)
+ connection := CreateTestConnection(client)
+ scopeConfig := FakeScopeConfig{Name: "Scope config", Env: "test env",
Entities: []string{plugin.DOMAIN_TYPE_CICD}}
+ scopeConfig =
helper.Cast[FakeScopeConfig](client.CreateScopeConfig(PLUGIN_NAME,
connection.ID, scopeConfig))
+
+ configs :=
helper.Cast[[]FakeScopeConfig](client.ListScopeConfigs(PLUGIN_NAME,
connection.ID))
+ require.Equal(t, 1, len(configs))
+
+ client.DeleteScopeConfig(PLUGIN_NAME, connection.ID, scopeConfig.Id)
+ configs =
helper.Cast[[]FakeScopeConfig](client.ListScopeConfigs(PLUGIN_NAME,
connection.ID))
+ require.Equal(t, 0, len(configs))
+}
+
+func TestDeleteScopeConfig_WithReferencingScope(t *testing.T) {
+ client := CreateClient(t)
+ connection := CreateTestConnection(client)
+ scopeConfig := FakeScopeConfig{Name: "Scope config", Env: "test env",
Entities: []string{plugin.DOMAIN_TYPE_CICD}}
+ scopeConfig =
helper.Cast[FakeScopeConfig](client.CreateScopeConfig(PLUGIN_NAME,
connection.ID, scopeConfig))
+
+ scope := CreateTestScope(client, &scopeConfig, connection.ID)
+ require.Equal(t, scopeConfig.Id, scope.ScopeConfigId)
+
+ client.DeleteScopeConfig(PLUGIN_NAME, connection.ID, scopeConfig.Id)
+ scope = helper.Cast[*FakeProject](client.GetScope(PLUGIN_NAME,
connection.ID, scope.Id, false))
+ require.Equal(t, uint64(0), scope.ScopeConfigId)
+
+}
diff --git a/backend/test/helper/api.go b/backend/test/helper/api.go
index be6dfd069..f1c15483b 100644
--- a/backend/test/helper/api.go
+++ b/backend/test/helper/api.go
@@ -272,6 +272,15 @@ func (d *DevlakeClient) GetScopeConfig(pluginName string,
connectionId uint64, s
d.Endpoint, pluginName, connectionId, scopeConfigId), nil, nil)
}
+func (d *DevlakeClient) DeleteScopeConfig(pluginName string, connectionId
uint64, scopeConfigId uint64) {
+ sendHttpRequest[any](d.testCtx, d.timeout, &testContext{
+ client: d,
+ printPayload: true,
+ inlineJson: false,
+ }, http.MethodDelete,
fmt.Sprintf("%s/plugins/%s/connections/%d/scope-configs/%d",
+ d.Endpoint, pluginName, connectionId, scopeConfigId), nil, nil)
+}
+
func (d *DevlakeClient) RemoteScopes(query RemoteScopesQuery)
RemoteScopesOutput {
url := fmt.Sprintf("%s/plugins/%s/connections/%d/remote-scopes",
d.Endpoint,
diff --git a/backend/test/helper/client.go b/backend/test/helper/client.go
index ccf9902e4..d29f70572 100644
--- a/backend/test/helper/client.go
+++ b/backend/test/helper/client.go
@@ -94,7 +94,7 @@ type (
CreateServer bool
DropDb bool
TruncateDb bool
- Plugins map[string]plugin.PluginMeta
+ Plugins []plugin.PluginMeta
Timeout time.Duration
PipelineTimeout time.Duration
}
@@ -286,16 +286,15 @@ func (d *DevlakeClient) forceSendHttpRequest(retries
uint, req *http.Request, on
func (d *DevlakeClient) initPlugins(cfg *LocalClientConfig) {
d.testCtx.Helper()
- if cfg.Plugins == nil {
- cfg.Plugins = map[string]plugin.PluginMeta{}
- }
// default plugins
- cfg.Plugins["org"] = org.Org{}
- cfg.Plugins["dora"] = dora.Dora{}
- cfg.Plugins["refdiff"] = refdiff.RefDiff{}
+ cfg.Plugins = append(cfg.Plugins, []plugin.PluginMeta{
+ org.Org{},
+ dora.Dora{},
+ refdiff.RefDiff{},
+ }...)
// register and init plugins
- for name, p := range cfg.Plugins {
- require.NoError(d.testCtx, plugin.RegisterPlugin(name, p))
+ for _, p := range cfg.Plugins {
+ require.NoError(d.testCtx, plugin.RegisterPlugin(p.Name(), p))
}
for _, p := range plugin.AllPlugins() {
if pi, ok := p.(plugin.PluginInit); ok {
@@ -404,18 +403,19 @@ func sendHttpRequest[Res any](t *testing.T, timeout
time.Duration, ctx *testCont
}()
if ctx.client.expectedStatusCode > 0 || response.StatusCode >=
300 {
if ctx.client.expectedStatusCode == 0 ||
ctx.client.expectedStatusCode != response.StatusCode {
- if response.StatusCode >= 300 {
- if err = response.Body.Close(); err !=
nil {
- return false,
errors.Convert(err)
- }
- response.Close = true
- return false,
errors.HttpStatus(response.StatusCode).New(fmt.Sprintf("unexpected http status
code calling [%s] %s: %d", httpMethod, endpoint, response.StatusCode))
+ if err = response.Body.Close(); err != nil {
+ return false, errors.Convert(err)
}
+ response.Close = true
+ return false,
errors.HttpStatus(response.StatusCode).New(fmt.Sprintf("unexpected http status
code calling [%s] %s: %d", httpMethod, endpoint, response.StatusCode))
}
}
b, _ = io.ReadAll(response.Body)
if err = json.Unmarshal(b, &result); err != nil {
- return false, errors.Convert(err)
+ if response.StatusCode < 300 {
+ return false, errors.Convert(err)
+ }
+ // it's probably ok since the request failed anyway
}
if ctx.printPayload {
coloredPrintf("result: %s\n",
ToCleanJson(ctx.inlineJson, b))
diff --git a/backend/test/helper/client_factory.go
b/backend/test/helper/client_factory.go
index a4aa1c4c0..cbd58dc14 100644
--- a/backend/test/helper/client_factory.go
+++ b/backend/test/helper/client_factory.go
@@ -24,7 +24,7 @@ import (
)
// Creates a new in-memory DevLake server with default settings and returns a
client to it
-func StartDevLakeServer(t *testing.T, loadedGoPlugins
map[string]plugin.PluginMeta) *DevlakeClient {
+func StartDevLakeServer(t *testing.T, loadedGoPlugins []plugin.PluginMeta)
*DevlakeClient {
client := ConnectLocalServer(t, &LocalClientConfig{
ServerPort: 8089,
DbURL: config.GetConfig().GetString("E2E_DB_URL"),