Skip to content

Commit

Permalink
feat: check pipelines' tokens before executing/creating pipeline (#8055
Browse files Browse the repository at this point in the history
…) (#8069)

* feat: check pipelines' tokens before executing/creating pipeline (#8055)

* feat(pipeline): check pipelines' tokens before executing/creating pipeline

* fix(framework): fix lint errors

* fix(framework): fix lint errors

* feat(github): check multi tokens when creating pipelines

* feat(project): add token check result in project check API (#8099)

* Dev 1 (#8100)

* feat(project): add token check result in project check API

* feat(project): update token check API response

* Dev 1 (#8101)

* feat(project): add token check result in project check API

* feat(project): update token check API response

* fix(project): fix api doc

* fix(project): update project check api doc

* fix(project): update check project api doc

* feat: add connection token check before collect data

* feat(blueprint): add new api to check connection tokens (#8102)

* fix: adjust the api for connections token check

* feat: add a component connection-form-modal

* feat: add a component connection-name

* fix: show connection form modal when connection token check failed

* refactor: improve the component connection-name

* fix: error check connection token failed list

* refactor: extract the function in the panel to bp detail

* fix: not call onCancel function when updating connection

* fix: search local items error

---------

Co-authored-by: mintsweet <[email protected]>
  • Loading branch information
d4x1 and mintsweet authored Sep 30, 2024
1 parent 47a9fcd commit 11db8e9
Show file tree
Hide file tree
Showing 68 changed files with 827 additions and 269 deletions.
9 changes: 9 additions & 0 deletions backend/core/models/blueprint.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,3 +92,12 @@ type SyncPolicy struct {
TimeAfter *time.Time `json:"timeAfter"`
TriggerSyncPolicy
}

type ConnectionTokenCheckResult struct {
PluginName string `json:"pluginName" mapstructure:"pluginName"`
ConnectionID uint64 `json:"connectionId" mapstructure:"connectionId"`
Success bool `json:"success" mapstructure:"success"`
Message string `json:"message" mapstructure:"message"`
}

type ApiBlueprintConnectionTokenCheck []ConnectionTokenCheckResult
4 changes: 4 additions & 0 deletions backend/core/plugin/plugin_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@ type PluginApi interface {
ApiResources() map[string]map[string]ApiResourceHandler
}

type PluginTestConnectionAPI interface {
TestConnection(id uint64) errors.Error
}

const wrapResponseError = "WRAP_RESPONSE_ERROR"

func WrapTestConnectionErrResp(basicRes context.BasicRes, err errors.Error) errors.Error {
Expand Down
10 changes: 10 additions & 0 deletions backend/core/plugin/plugin_blueprint.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,16 @@ type ProjectMapper interface {
MapProject(projectName string, scopes []Scope) (models.PipelinePlan, errors.Error)
}

type ProjectTokenCheckerConnection struct {
PluginName string
ConnectionId uint64
}

// ProjectTokenChecker is implemented by the plugin org, which generate a task tp check all connection's tokens
type ProjectTokenChecker interface {
MakePipeline(skipCollectors bool, projectName string, scopes []ProjectTokenCheckerConnection) (models.PipelinePlan, errors.Error)
}

// CompositeDataSourcePluginBlueprintV200 is for unit test
type CompositeDataSourcePluginBlueprintV200 interface {
PluginMeta
Expand Down
10 changes: 10 additions & 0 deletions backend/helpers/pluginhelper/api/misc_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@ limitations under the License.
package api

import (
"fmt"
"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"
)

// CallDB wraps DB calls with this signature, and handles the case if the struct is wrapped in a models.DynamicTabler.
Expand All @@ -31,3 +33,11 @@ func CallDB(f func(any, ...dal.Clause) errors.Error, x any, clauses ...dal.Claus
}
return f(x, clauses...)
}

func GenerateTestingConnectionApiResourceInput(connectionID uint64) *plugin.ApiResourceInput {
return &plugin.ApiResourceInput{
Params: map[string]string{
"connectionId": fmt.Sprintf("%d", connectionID),
},
}
}
5 changes: 5 additions & 0 deletions backend/plugins/ae/impl/impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,11 @@ func (p AE) MigrationScripts() []plugin.MigrationScript {
return migrationscripts.All()
}

func (p AE) TestConnection(id uint64) errors.Error {
_, err := api.TestExistingConnection(helper.GenerateTestingConnectionApiResourceInput(id))
return err
}

func (p AE) ApiResources() map[string]map[string]plugin.ApiResourceHandler {
return map[string]map[string]plugin.ApiResourceHandler{
"test": {
Expand Down
5 changes: 5 additions & 0 deletions backend/plugins/azuredevops_go/impl/impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,11 @@ func (p Azuredevops) ApiResources() map[string]map[string]plugin.ApiResourceHand
}
}

func (p Azuredevops) TestConnection(id uint64) errors.Error {
_, err := api.TestExistingConnection(helper.GenerateTestingConnectionApiResourceInput(id))
return err
}

func (p Azuredevops) MakeDataSourcePipelinePlanV200(
connectionId uint64,
scopes []*coreModels.BlueprintScope,
Expand Down
5 changes: 5 additions & 0 deletions backend/plugins/bamboo/impl/impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,11 @@ func (p Bamboo) MigrationScripts() []plugin.MigrationScript {
return migrationscripts.All()
}

func (p Bamboo) TestConnection(id uint64) errors.Error {
_, err := api.TestExistingConnection(helper.GenerateTestingConnectionApiResourceInput(id))
return err
}

func (p Bamboo) ApiResources() map[string]map[string]plugin.ApiResourceHandler {
return map[string]map[string]plugin.ApiResourceHandler{
"test": {
Expand Down
5 changes: 5 additions & 0 deletions backend/plugins/bitbucket/impl/impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,11 @@ func (p Bitbucket) MakeDataSourcePipelinePlanV200(
return api.MakeDataSourcePipelinePlanV200(p.SubTaskMetas(), connectionId, scopes, skipCollectors)
}

func (p Bitbucket) TestConnection(id uint64) errors.Error {
_, err := api.TestExistingConnection(helper.GenerateTestingConnectionApiResourceInput(id))
return err
}

func (p Bitbucket) ApiResources() map[string]map[string]plugin.ApiResourceHandler {
return map[string]map[string]plugin.ApiResourceHandler{
"test": {
Expand Down
5 changes: 5 additions & 0 deletions backend/plugins/bitbucket_server/impl/impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,11 @@ func (p BitbucketServer) MakeDataSourcePipelinePlanV200(
return api.MakeDataSourcePipelinePlanV200(p.SubTaskMetas(), connectionId, scopes, skipCollectors)
}

func (p BitbucketServer) TestConnection(id uint64) errors.Error {
_, err := api.TestExistingConnection(helper.GenerateTestingConnectionApiResourceInput(id))
return err
}

func (p BitbucketServer) ApiResources() map[string]map[string]plugin.ApiResourceHandler {
return map[string]map[string]plugin.ApiResourceHandler{
"connections/:connectionId/test": {
Expand Down
5 changes: 5 additions & 0 deletions backend/plugins/circleci/impl/impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,11 @@ func (p Circleci) MigrationScripts() []plugin.MigrationScript {
return migrationscripts.All()
}

func (p Circleci) TestConnection(id uint64) errors.Error {
_, err := api.TestExistingConnection(helper.GenerateTestingConnectionApiResourceInput(id))
return err
}

func (p Circleci) ApiResources() map[string]map[string]plugin.ApiResourceHandler {
return map[string]map[string]plugin.ApiResourceHandler{
"test": {
Expand Down
4 changes: 4 additions & 0 deletions backend/plugins/customize/impl/impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,3 +110,7 @@ func (p Customize) ApiResources() map[string]map[string]plugin.ApiResourceHandle
},
}
}

func (p Customize) TestConnection(id uint64) errors.Error {
return nil
}
4 changes: 4 additions & 0 deletions backend/plugins/dbt/impl/impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,3 +74,7 @@ func (p Dbt) RootPkgPath() string {
func (p Dbt) Name() string {
return "dbt"
}

func (p Dbt) TestConnection(id uint64) errors.Error {
return nil
}
5 changes: 4 additions & 1 deletion backend/plugins/dora/impl/impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ package impl

import (
"encoding/json"

"github.com/apache/incubator-devlake/core/dal"
"github.com/apache/incubator-devlake/core/errors"
coreModels "github.com/apache/incubator-devlake/core/models"
Expand Down Expand Up @@ -168,3 +167,7 @@ func (p Dora) MakeMetricPluginPipelinePlanV200(projectName string, options json.
}
return plan, nil
}

func (p Dora) TestConnection(id uint64) errors.Error {
return nil
}
5 changes: 5 additions & 0 deletions backend/plugins/feishu/impl/impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,11 @@ func (p Feishu) MigrationScripts() []plugin.MigrationScript {
return migrationscripts.All()
}

func (p Feishu) TestConnection(id uint64) errors.Error {
_, err := api.TestExistingConnection(helper.GenerateTestingConnectionApiResourceInput(id))
return err
}

func (p Feishu) ApiResources() map[string]map[string]plugin.ApiResourceHandler {
return map[string]map[string]plugin.ApiResourceHandler{
"test": {
Expand Down
5 changes: 5 additions & 0 deletions backend/plugins/gitee/impl/impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,11 @@ func (p Gitee) MigrationScripts() []plugin.MigrationScript {
return migrationscripts.All()
}

func (p Gitee) TestConnection(id uint64) errors.Error {
_, err := api.TestExistingConnection(helper.GenerateTestingConnectionApiResourceInput(id))
return err
}

func (p Gitee) ApiResources() map[string]map[string]plugin.ApiResourceHandler {
return map[string]map[string]plugin.ApiResourceHandler{
"test": {
Expand Down
4 changes: 4 additions & 0 deletions backend/plugins/gitextractor/impl/impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,3 +122,7 @@ func (p GitExtractor) Close(taskCtx plugin.TaskContext) errors.Error {
func (p GitExtractor) RootPkgPath() string {
return "github.com/apache/incubator-devlake/plugins/gitextractor"
}

func (p GitExtractor) TestConnection(id uint64) errors.Error {
return nil
}
42 changes: 42 additions & 0 deletions backend/plugins/github/api/shared.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
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 api

import (
"context"
"fmt"
"github.com/apache/incubator-devlake/core/errors"
"github.com/apache/incubator-devlake/core/plugin"
)

func TestExistingConnectionForTokenCheck(input *plugin.ApiResourceInput) errors.Error {
connection, err := dsHelper.ConnApi.GetMergedConnection(input)
if err != nil {
return err
}
testConnectionResult, testConnectionErr := testExistingConnection(context.TODO(), connection.GithubConn)
if testConnectionErr != nil {
return testConnectionErr
}
for _, token := range testConnectionResult.Tokens {
if !token.Success {
return errors.Default.New(fmt.Sprintf("token %s failed with msg: %s", token.Token, token.Message))
}
}
return nil
}
4 changes: 4 additions & 0 deletions backend/plugins/github/impl/impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,10 @@ func (p Github) MigrationScripts() []plugin.MigrationScript {
return migrationscripts.All()
}

func (p Github) TestConnection(id uint64) errors.Error {
return api.TestExistingConnectionForTokenCheck(helper.GenerateTestingConnectionApiResourceInput(id))
}

func (p Github) ApiResources() map[string]map[string]plugin.ApiResourceHandler {
return map[string]map[string]plugin.ApiResourceHandler{
"test": {
Expand Down
5 changes: 5 additions & 0 deletions backend/plugins/gitlab/impl/impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,11 @@ func (p Gitlab) MigrationScripts() []plugin.MigrationScript {
return migrationscripts.All()
}

func (p Gitlab) TestConnection(id uint64) errors.Error {
_, err := api.TestExistingConnection(helper.GenerateTestingConnectionApiResourceInput(id))
return err
}

func (p Gitlab) ApiResources() map[string]map[string]plugin.ApiResourceHandler {
return map[string]map[string]plugin.ApiResourceHandler{
"test": {
Expand Down
4 changes: 4 additions & 0 deletions backend/plugins/icla/impl/impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,10 @@ func (p Icla) ApiResources() map[string]map[string]plugin.ApiResourceHandler {
return nil
}

func (p Icla) TestConnection(id uint64) errors.Error {
return nil
}

func (p Icla) Close(taskCtx plugin.TaskContext) errors.Error {
data, ok := taskCtx.GetData().(*tasks.IclaTaskData)
if !ok {
Expand Down
5 changes: 4 additions & 1 deletion backend/plugins/issue_trace/impl/enricher.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ package impl

import (
"encoding/json"

"github.com/apache/incubator-devlake/core/context"
"github.com/apache/incubator-devlake/core/dal"
"github.com/apache/incubator-devlake/core/errors"
Expand Down Expand Up @@ -151,6 +150,10 @@ func (p IssueTrace) GetTablesInfo() []dal.Tabler {
}
}

func (p IssueTrace) TestConnection(id uint64) errors.Error {
return nil
}

func (p IssueTrace) MakeMetricPluginPipelinePlanV200(projectName string, options json.RawMessage) (coreModels.PipelinePlan, errors.Error) {
op := &tasks.Options{}
if options != nil && string(options) != "\"\"" {
Expand Down
5 changes: 5 additions & 0 deletions backend/plugins/jenkins/impl/impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,11 @@ func (p Jenkins) MakeDataSourcePipelinePlanV200(
return api.MakeDataSourcePipelinePlanV200(p.SubTaskMetas(), connectionId, scopes, skipCollectors)
}

func (p Jenkins) TestConnection(id uint64) errors.Error {
_, err := api.TestExistingConnection(helper.GenerateTestingConnectionApiResourceInput(id))
return err
}

func (p Jenkins) ApiResources() map[string]map[string]plugin.ApiResourceHandler {
return map[string]map[string]plugin.ApiResourceHandler{
"test": {
Expand Down
5 changes: 5 additions & 0 deletions backend/plugins/jira/impl/impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,11 @@ func (p Jira) MigrationScripts() []plugin.MigrationScript {
return migrationscripts.All()
}

func (p Jira) TestConnection(id uint64) errors.Error {
_, err := api.TestExistingConnection(helper.GenerateTestingConnectionApiResourceInput(id))
return err
}

func (p Jira) ApiResources() map[string]map[string]plugin.ApiResourceHandler {
return map[string]map[string]plugin.ApiResourceHandler{
"test": {
Expand Down
4 changes: 4 additions & 0 deletions backend/plugins/linker/impl/impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,3 +125,7 @@ func (p Linker) MakeMetricPluginPipelinePlanV200(projectName string, options jso
}
return plan, nil
}

func (p Linker) TestConnection(id uint64) errors.Error {
return nil
}
5 changes: 5 additions & 0 deletions backend/plugins/opsgenie/impl/impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,11 @@ func (p Opsgenie) Close(taskCtx plugin.TaskContext) errors.Error {
return nil
}

func (p Opsgenie) TestConnection(id uint64) errors.Error {
_, err := api.TestExistingConnection(helper.GenerateTestingConnectionApiResourceInput(id))
return err
}

func (p Opsgenie) ApiResources() map[string]map[string]plugin.ApiResourceHandler {
return map[string]map[string]plugin.ApiResourceHandler{
"test": {
Expand Down
22 changes: 22 additions & 0 deletions backend/plugins/org/impl/impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,33 @@ func (p Org) Name() string {

func (p Org) SubTaskMetas() []plugin.SubTaskMeta {
return []plugin.SubTaskMeta{
tasks.TaskCheckTokenMeta,
tasks.ConnectUserAccountsExactMeta,
tasks.SetProjectMappingMeta,
}
}

func (p Org) MakePipeline(skipCollectors bool, projectName string, connections []plugin.ProjectTokenCheckerConnection) (coreModels.PipelinePlan, errors.Error) {
var plan coreModels.PipelinePlan
var stage coreModels.PipelineStage

// construct task options for Org
options := make(map[string]interface{})
if !skipCollectors {
options["projectConnections"] = connections
}

stage = append(stage, &coreModels.PipelineTask{
Plugin: p.Name(),
Subtasks: []string{
tasks.TaskCheckTokenMeta.Name,
},
Options: options,
})
plan = append(plan, stage)
return plan, nil
}

func (p Org) MapProject(projectName string, scopes []plugin.Scope) (coreModels.PipelinePlan, errors.Error) {
var plan coreModels.PipelinePlan
var stage coreModels.PipelineStage
Expand Down
Loading

0 comments on commit 11db8e9

Please sign in to comment.