This is an automated email from the ASF dual-hosted git repository. klesh pushed a commit to branch kw-5519-jenkins in repository https://gitbox.apache.org/repos/asf/incubator-devlake.git
commit 6c57b8a23ad9934e0983c14a67631fecbad00dea Author: Klesh Wong <zhenmian.hu...@merico.dev> AuthorDate: Mon Dec 4 13:24:06 2023 +0800 refactor: jenkins adopts new dshelpers --- backend/plugins/jenkins/api/blueprint_v200.go | 79 +++++---- backend/plugins/jenkins/api/blueprint_v200_test.go | 111 ------------- .../api/{connection.go => connection_api.go} | 48 +----- backend/plugins/jenkins/api/init.go | 48 ++---- backend/plugins/jenkins/api/proxy.go | 73 --------- backend/plugins/jenkins/api/remote.go | 182 +++++++++------------ .../plugins/jenkins/api/{scope.go => scope_api.go} | 14 +- .../api/{scope_config.go => scope_config_api.go} | 10 +- backend/plugins/jenkins/impl/impl.go | 10 +- backend/plugins/jenkins/models/response.go | 4 +- 10 files changed, 161 insertions(+), 418 deletions(-) diff --git a/backend/plugins/jenkins/api/blueprint_v200.go b/backend/plugins/jenkins/api/blueprint_v200.go index 10940fb62..9aaf59641 100644 --- a/backend/plugins/jenkins/api/blueprint_v200.go +++ b/backend/plugins/jenkins/api/blueprint_v200.go @@ -18,6 +18,8 @@ limitations under the License. package api import ( + "context" + "github.com/apache/incubator-devlake/core/errors" coreModels "github.com/apache/incubator-devlake/core/models" "github.com/apache/incubator-devlake/core/models/domainlayer" @@ -26,7 +28,9 @@ import ( "github.com/apache/incubator-devlake/core/plugin" "github.com/apache/incubator-devlake/core/utils" helper "github.com/apache/incubator-devlake/helpers/pluginhelper/api" + "github.com/apache/incubator-devlake/helpers/srvhelper" "github.com/apache/incubator-devlake/plugins/jenkins/models" + "github.com/apache/incubator-devlake/plugins/jenkins/tasks" ) func MakeDataSourcePipelinePlanV200( @@ -34,12 +38,28 @@ func MakeDataSourcePipelinePlanV200( connectionId uint64, bpScopes []*coreModels.BlueprintScope, ) (coreModels.PipelinePlan, []plugin.Scope, errors.Error) { - plan := make(coreModels.PipelinePlan, len(bpScopes)) - plan, err := makeDataSourcePipelinePlanV200(subtaskMetas, plan, bpScopes, connectionId) + // load connection, scope and scopeConfig from the db + connection, err := dsHelper.ConnSrv.FindByPk(connectionId) if err != nil { return nil, nil, err } - scopes, err := makeScopesV200(bpScopes, connectionId) + scopeDetails, err := dsHelper.ScopeSrv.MapScopeDetails(connectionId, bpScopes) + if err != nil { + return nil, nil, err + } + + // needed for the connection to populate its access tokens + // if AppKey authentication method is selected + _, err = helper.NewApiClientFromConnection(context.TODO(), basicRes, connection) + if err != nil { + return nil, nil, err + } + + plan, err := makeDataSourcePipelinePlanV200(subtaskMetas, scopeDetails, connection) + if err != nil { + return nil, nil, err + } + scopes, err := makeScopesV200(scopeDetails, connection) if err != nil { return nil, nil, err } @@ -49,59 +69,50 @@ func MakeDataSourcePipelinePlanV200( func makeDataSourcePipelinePlanV200( subtaskMetas []plugin.SubTaskMeta, - plan coreModels.PipelinePlan, - bpScopes []*coreModels.BlueprintScope, - connectionId uint64, + scopeDetails []*srvhelper.ScopeDetail[models.JenkinsJob, models.JenkinsScopeConfig], + connection *models.JenkinsConnection, ) (coreModels.PipelinePlan, errors.Error) { - for i, bpScope := range bpScopes { + plan := make(coreModels.PipelinePlan, len(scopeDetails)) + for i, scopeDetail := range scopeDetails { + jenkinsJob, scopeConfig := scopeDetail.Scope, scopeDetail.ScopeConfig stage := plan[i] if stage == nil { stage = coreModels.PipelineStage{} } - // construct task options for Jenkins - options := make(map[string]interface{}) - options["scopeId"] = bpScope.ScopeId - options["connectionId"] = connectionId - - // get scope config from db - _, scopeConfig, err := scopeHelper.DbHelper().GetScopeAndConfig(connectionId, bpScope.ScopeId) + // construct task options for github + task, err := helper.MakePipelinePlanTask( + "jenkins", + subtaskMetas, + scopeConfig.Entities, + tasks.JenkinsOptions{ + ConnectionId: jenkinsJob.ConnectionId, + ScopeId: jenkinsJob.ScopeId(), + }, + ) if err != nil { return nil, err } - subtasks, err := helper.MakePipelinePlanSubtasks(subtaskMetas, scopeConfig.Entities) - if err != nil { - return nil, err - } - stage = append(stage, &coreModels.PipelineTask{ - Plugin: "jenkins", - Subtasks: subtasks, - Options: options, - }) + stage = append(stage, task) + plan[i] = stage } - return plan, nil } func makeScopesV200( - bpScopes []*coreModels.BlueprintScope, - connectionId uint64, + scopeDetails []*srvhelper.ScopeDetail[models.JenkinsJob, models.JenkinsScopeConfig], + connection *models.JenkinsConnection, ) ([]plugin.Scope, errors.Error) { scopes := make([]plugin.Scope, 0) - for _, bpScope := range bpScopes { - // get job and scope config from db - jenkinsJob, scopeConfig, err := scopeHelper.DbHelper().GetScopeAndConfig(connectionId, bpScope.ScopeId) - if err != nil { - return nil, err - } - + for _, scopeDetail := range scopeDetails { + jenkinsJob, scopeConfig := scopeDetail.Scope, scopeDetail.ScopeConfig // add cicd_scope to scopes if utils.StringsContains(scopeConfig.Entities, plugin.DOMAIN_TYPE_CICD) { scopeCICD := &devops.CicdScope{ DomainEntity: domainlayer.DomainEntity{ - Id: didgen.NewDomainIdGenerator(&models.JenkinsJob{}).Generate(connectionId, jenkinsJob.FullName), + Id: didgen.NewDomainIdGenerator(&models.JenkinsJob{}).Generate(connection.ID, jenkinsJob.FullName), }, Name: jenkinsJob.FullName, } diff --git a/backend/plugins/jenkins/api/blueprint_v200_test.go b/backend/plugins/jenkins/api/blueprint_v200_test.go deleted file mode 100644 index e41a30ddf..000000000 --- a/backend/plugins/jenkins/api/blueprint_v200_test.go +++ /dev/null @@ -1,111 +0,0 @@ -/* -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 ( - "testing" - - coreModels "github.com/apache/incubator-devlake/core/models" - "github.com/apache/incubator-devlake/core/models/common" - "github.com/apache/incubator-devlake/core/models/domainlayer" - "github.com/apache/incubator-devlake/core/models/domainlayer/devops" - "github.com/apache/incubator-devlake/core/plugin" - "github.com/apache/incubator-devlake/helpers/unithelper" - mockdal "github.com/apache/incubator-devlake/mocks/core/dal" - mockplugin "github.com/apache/incubator-devlake/mocks/core/plugin" - "github.com/apache/incubator-devlake/plugins/jenkins/models" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/mock" -) - -func TestMakeDataSourcePipelinePlanV200(t *testing.T) { - mockMeta := mockplugin.NewPluginMeta(t) - mockMeta.On("RootPkgPath").Return("github.com/apache/incubator-devlake/plugins/jenkins") - mockMeta.On("Name").Return("jenkins").Maybe() - err := plugin.RegisterPlugin("jenkins", mockMeta) - assert.Nil(t, err) - bs := &coreModels.BlueprintScope{ - ScopeId: "a/b/ccc", - } - - bpScopes := make([]*coreModels.BlueprintScope, 0) - bpScopes = append(bpScopes, bs) - - mockBasicRes(t) - - plan := make(coreModels.PipelinePlan, len(bpScopes)) - plan, err = makeDataSourcePipelinePlanV200(nil, plan, bpScopes, 1) - assert.Nil(t, err) - scopes, err := makeScopesV200(bpScopes, 1) - assert.Nil(t, err) - - expectPlan := coreModels.PipelinePlan{ - coreModels.PipelineStage{ - { - Plugin: "jenkins", - Subtasks: []string{}, - Options: map[string]interface{}{ - "connectionId": uint64(1), - "scopeId": "a/b/ccc", - }, - }, - }, - } - assert.Equal(t, expectPlan, plan) - - expectScopes := make([]plugin.Scope, 0) - scopeCicd := &devops.CicdScope{ - DomainEntity: domainlayer.DomainEntity{ - Id: "jenkins:JenkinsJob:1:a/b/ccc", - }, - Name: "a/b/ccc", - } - - expectScopes = append(expectScopes, scopeCicd) - assert.Equal(t, expectScopes, scopes) -} - -func mockBasicRes(t *testing.T) { - jenkinsJob := &models.JenkinsJob{ - Scope: common.Scope{ - ConnectionId: 1, - }, - FullName: "a/b/ccc", - } - - scopeConfig := &models.JenkinsScopeConfig{ - ScopeConfig: common.ScopeConfig{ - Entities: []string{"CICD"}, - }, - } - - // Refresh Global Variables and set the sql mock - mockRes := unithelper.DummyBasicRes(func(mockDal *mockdal.Dal) { - mockDal.On("First", mock.AnythingOfType("*models.JenkinsScopeConfig"), mock.Anything).Run(func(args mock.Arguments) { - dst := args.Get(0).(*models.JenkinsScopeConfig) - *dst = *scopeConfig - }).Return(nil) - mockDal.On("First", mock.AnythingOfType("*models.JenkinsJob"), mock.Anything).Run(func(args mock.Arguments) { - dst := args.Get(0).(*models.JenkinsJob) - *dst = *jenkinsJob - }).Return(nil) - }) - p := mockplugin.NewPluginMeta(t) - p.On("Name").Return("dummy").Maybe() - Init(mockRes, p) -} diff --git a/backend/plugins/jenkins/api/connection.go b/backend/plugins/jenkins/api/connection_api.go similarity index 83% rename from backend/plugins/jenkins/api/connection.go rename to backend/plugins/jenkins/api/connection_api.go index 5ea1058da..ea6ee046a 100644 --- a/backend/plugins/jenkins/api/connection.go +++ b/backend/plugins/jenkins/api/connection_api.go @@ -106,8 +106,7 @@ func TestConnection(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, // @Failure 500 {string} errcode.Error "Internal Error" // @Router /plugins/jenkins/{connectionId}/test [POST] func TestExistingConnection(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, errors.Error) { - connection := &models.JenkinsConnection{} - err := connectionHelper.First(connection, input.Params) + connection, err := dsHelper.ConnApi.FindByPk(input) if err != nil { return nil, errors.BadInput.Wrap(err, "find connection from db") } @@ -128,15 +127,7 @@ func TestExistingConnection(input *plugin.ApiResourceInput) (*plugin.ApiResource // @Failure 500 {string} errcode.Error "Internal Error" // @Router /plugins/jenkins/connections [POST] func PostConnections(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, errors.Error) { - // create a new connection - connection := &models.JenkinsConnection{} - - // update from request and save to database - err := connectionHelper.Create(connection, input) - if err != nil { - return nil, err - } - return &plugin.ApiResourceOutput{Body: connection.Sanitize(), Status: http.StatusOK}, nil + return dsHelper.ConnApi.Post(input) } // @Summary patch jenkins connection @@ -148,13 +139,7 @@ func PostConnections(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, // @Failure 500 {string} errcode.Error "Internal Error" // @Router /plugins/jenkins/connections/{connectionId} [PATCH] func PatchConnection(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, errors.Error) { - connection := &models.JenkinsConnection{} - err := connectionHelper.Patch(connection, input) - if err != nil { - return nil, err - } - - return &plugin.ApiResourceOutput{Body: connection.Sanitize()}, nil + return dsHelper.ConnApi.Patch(input) } // @Summary delete a jenkins connection @@ -166,14 +151,7 @@ func PatchConnection(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, // @Failure 500 {string} errcode.Error "Internal Error" // @Router /plugins/jenkins/connections/{connectionId} [DELETE] func DeleteConnection(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, errors.Error) { - conn := &models.JenkinsConnection{} - output, err := connectionHelper.Delete(conn, input) - if err != nil { - return output, err - } - output.Body = conn.Sanitize() - return output, nil - + return dsHelper.ConnApi.Delete(input) } // @Summary get all jenkins connections @@ -184,16 +162,7 @@ func DeleteConnection(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput // @Failure 500 {string} errcode.Error "Internal Error" // @Router /plugins/jenkins/connections [GET] func ListConnections(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, errors.Error) { - var connections []models.JenkinsConnection - err := connectionHelper.List(&connections) - if err != nil { - return nil, err - } - - for idx, c := range connections { - connections[idx] = c.Sanitize() - } - return &plugin.ApiResourceOutput{Body: connections, Status: http.StatusOK}, nil + return dsHelper.ConnApi.GetAll(input) } // @Summary get jenkins connection detail @@ -204,10 +173,5 @@ func ListConnections(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, // @Failure 500 {string} errcode.Error "Internal Error" // @Router /plugins/jenkins/connections/{connectionId} [GET] func GetConnection(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, errors.Error) { - connection := &models.JenkinsConnection{} - err := connectionHelper.First(connection, input.Params) - if err != nil { - return nil, err - } - return &plugin.ApiResourceOutput{Body: connection.Sanitize()}, err + return dsHelper.ConnApi.GetDetail(input) } diff --git a/backend/plugins/jenkins/api/init.go b/backend/plugins/jenkins/api/init.go index 08f78716f..ebcb14c55 100644 --- a/backend/plugins/jenkins/api/init.go +++ b/backend/plugins/jenkins/api/init.go @@ -26,45 +26,29 @@ import ( ) var vld *validator.Validate -var connectionHelper *api.ConnectionApiHelper -var scopeHelper *api.ScopeApiHelper[models.JenkinsConnection, models.JenkinsJob, models.JenkinsScopeConfig] -var remoteHelper *api.RemoteApiHelper[models.JenkinsConnection, models.JenkinsJob, models.Job, models.Job] var basicRes context.BasicRes -var scHelper *api.ScopeConfigHelper[models.JenkinsScopeConfig, *models.JenkinsScopeConfig] +var dsHelper *api.DsHelper[models.JenkinsConnection, models.JenkinsJob, models.JenkinsScopeConfig] +var raProxy *api.DsRemoteApiProxyHelper[models.JenkinsConnection] +var raScopeList *api.DsRemoteApiScopeListHelper[models.JenkinsConnection, models.JenkinsJob, JenkinsRemotePagination] func Init(br context.BasicRes, p plugin.PluginMeta) { - basicRes = br vld = validator.New() - connectionHelper = api.NewConnectionHelper( - basicRes, - vld, + dsHelper = api.NewDataSourceHelper[ + models.JenkinsConnection, + models.JenkinsJob, + models.JenkinsScopeConfig, + ]( + br, p.Name(), - ) - params := &api.ReflectionParameters{ - ScopeIdFieldName: "FullName", - ScopeIdColumnName: "full_name", - RawScopeParamName: "FullName", - SearchScopeParamName: "full_name", - } - scopeHelper = api.NewScopeHelper[models.JenkinsConnection, models.JenkinsJob, models.JenkinsScopeConfig]( - basicRes, - vld, - connectionHelper, - api.NewScopeDatabaseHelperImpl[models.JenkinsConnection, models.JenkinsJob, models.JenkinsScopeConfig]( - basicRes, connectionHelper, params), - params, + []string{"full_name"}, + func(c models.JenkinsConnection) models.JenkinsConnection { + return c.Sanitize() + }, + nil, nil, ) - remoteHelper = api.NewRemoteHelper[models.JenkinsConnection, models.JenkinsJob, models.Job, models.Job]( - basicRes, - vld, - connectionHelper, - ) - scHelper = api.NewScopeConfigHelper[models.JenkinsScopeConfig, *models.JenkinsScopeConfig]( - basicRes, - vld, - p.Name(), - ) + raProxy = api.NewDsRemoteApiProxyHelper[models.JenkinsConnection](dsHelper.ConnApi.ModelApiHelper) + raScopeList = api.NewDsRemoteApiScopeListHelper[models.JenkinsConnection, models.JenkinsJob, JenkinsRemotePagination](raProxy, listJenkinsRemoteScopes) } diff --git a/backend/plugins/jenkins/api/proxy.go b/backend/plugins/jenkins/api/proxy.go deleted file mode 100644 index 0baac8d2f..000000000 --- a/backend/plugins/jenkins/api/proxy.go +++ /dev/null @@ -1,73 +0,0 @@ -/* -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" - "encoding/json" - "fmt" - "github.com/apache/incubator-devlake/core/errors" - "github.com/apache/incubator-devlake/core/plugin" - helper "github.com/apache/incubator-devlake/helpers/pluginhelper/api" - "github.com/apache/incubator-devlake/plugins/jenkins/models" - "io" - "time" -) - -const ( - TimeOut = 10 * time.Second -) - -func Proxy(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, errors.Error) { - connection := &models.JenkinsConnection{} - err := connectionHelper.First(connection, input.Params) - if err != nil { - return nil, err - } - apiClient, err := helper.NewApiClient( - context.TODO(), - connection.Endpoint, - map[string]string{ - "Authorization": fmt.Sprintf("Basic %v", connection.GetEncodedToken()), - }, - TimeOut, - connection.Proxy, - basicRes, - ) - if err != nil { - return nil, err - } - - resp, err := apiClient.Get(input.Params["path"], input.Query, nil) - if err != nil { - return nil, err - } - defer resp.Body.Close() - - body, err := errors.Convert01(io.ReadAll(resp.Body)) - if err != nil { - return nil, err - } - // verify response body is json - var tmp interface{} - err = errors.Convert(json.Unmarshal(body, &tmp)) - if err != nil { - return nil, err - } - return &plugin.ApiResourceOutput{Status: resp.StatusCode, Body: json.RawMessage(body)}, nil -} diff --git a/backend/plugins/jenkins/api/remote.go b/backend/plugins/jenkins/api/remote.go index cd932828a..171336dc8 100644 --- a/backend/plugins/jenkins/api/remote.go +++ b/backend/plugins/jenkins/api/remote.go @@ -18,128 +18,98 @@ limitations under the License. package api import ( - gocontext "context" - "net/http" - "strings" + "fmt" - "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/pluginhelper/api" + dsmodels "github.com/apache/incubator-devlake/helpers/pluginhelper/api/models" "github.com/apache/incubator-devlake/plugins/jenkins/models" ) -// RemoteScopes list all available scope for users -// @Summary list all available scope for users -// @Description list all available scope for users -// @Tags plugins/jenkins -// @Accept application/json -// @Param connectionId path int false "connection ID" -// @Param groupId query string false "group ID" -// @Param pageToken query string false "page Token" -// @Success 200 {object} api.RemoteScopesOutput -// @Failure 400 {object} shared.ApiBody "Bad Request" -// @Failure 500 {object} shared.ApiBody "Internal Error" -// @Router /plugins/jenkins/connections/{connectionId}/remote-scopes [GET] -func RemoteScopes(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, errors.Error) { - getter := func(basicRes context.BasicRes, groupId string, queryData *api.RemoteQueryData, connection models.JenkinsConnection) (*api.RemoteScopesOutput, errors.Error) { - var resBody []api.RemoteScopesChild - apiClient, err := api.NewApiClientFromConnection(gocontext.TODO(), basicRes, &connection) - if err != nil { - return nil, errors.BadInput.Wrap(err, "failed to get create apiClient") - } - getJobsPageCallBack := func(job *models.Job) errors.Error { - if job.Jobs != nil { - // this is a group - job.Path = groupId - groupChild := api.RemoteScopesChild{ - Type: api.TypeGroup, - Id: job.GroupId(), - Name: job.GroupName(), - // don't need to save group into data - Data: nil, - } - groupChild.ParentId = &groupId - if *groupChild.ParentId == "" { - groupChild.ParentId = nil - } - resBody = append(resBody, groupChild) - } else { - // this is a scope - scope := job.ConvertApiScope() - scopeChild := api.RemoteScopesChild{ - Type: api.TypeScope, - Id: scope.ScopeId(), - Name: scope.ScopeName(), - FullName: scope.ScopeFullName(), - Data: &scope, - } - scopeChild.ParentId = &groupId - if *scopeChild.ParentId == "" { - scopeChild.ParentId = nil - } - resBody = append(resBody, scopeChild) - } - return nil - } - _, err = GetJobsPage(apiClient, groupId, queryData.Page-1, queryData.PerPage, getJobsPageCallBack) - if err != nil { - return nil, errors.BadInput.Wrap(err, "failed to GetJobsPage") +type JenkinsRemotePagination struct { + Page int `json:"page"` + PerPage int `json:"per_page"` +} + +func listJenkinsRemoteScopes( + connection *models.JenkinsConnection, + apiClient plugin.ApiClient, + groupId string, + page JenkinsRemotePagination, +) ( + children []dsmodels.DsRemoteApiScopeListEntry[models.JenkinsJob], + nextPage *JenkinsRemotePagination, + err errors.Error, +) { + if page.Page == 0 { + page.Page = 1 + } + if page.PerPage == 0 { + page.PerPage = 100 + } + var parentId *string + if groupId != "" { + parentId = &groupId + } + getJobsPageCallBack := func(job *models.Job) errors.Error { + if job.Jobs != nil { + // this is a group + job.Path = groupId + children = append(children, dsmodels.DsRemoteApiScopeListEntry[models.JenkinsJob]{ + Type: api.RAS_ENTRY_TYPE_GROUP, + Id: fmt.Sprintf("%s/job/%s", job.Path, job.Name), + Name: job.Name, + ParentId: parentId, + }) + } else { + // this is a scope + jenkinsJob := job.ToJenkinsJob() + children = append(children, dsmodels.DsRemoteApiScopeListEntry[models.JenkinsJob]{ + Type: api.RAS_ENTRY_TYPE_SCOPE, + Id: jenkinsJob.ScopeId(), + Name: jenkinsJob.ScopeName(), + FullName: jenkinsJob.ScopeFullName(), + Data: jenkinsJob, + ParentId: parentId, + }) } - return &api.RemoteScopesOutput{ - Children: resBody, - }, nil + return nil } - remoteScopesOutput, err := remoteHelper.GetRemoteScopesOutput(input, getter) + _, err = GetJobsPage(apiClient, groupId, page.Page-1, page.PerPage, getJobsPageCallBack) if err != nil { - return nil, err + return } - return &plugin.ApiResourceOutput{Body: remoteScopesOutput, Status: http.StatusOK}, nil + if len(children) == page.PerPage { + nextPage = &JenkinsRemotePagination{ + Page: page.Page + 1, + PerPage: page.PerPage, + } + } + return } -// SearchRemoteScopes use the Search API and only return project -// @Summary use the Search API and only return project -// @Description use the Search API and only return project -// @Tags plugins/jenkins +// RemoteScopes list all available scopes on the remote server +// @Summary list all available scopes on the remote server +// @Description list all available scopes on the remote server // @Accept application/json // @Param connectionId path int false "connection ID" -// @Param search query string false "search" -// @Param page query int false "page number" -// @Param pageSize query int false "page size per page" -// @Success 200 {object} api.SearchRemoteScopesOutput +// @Param groupId query string false "group ID" +// @Param pageToken query string false "page Token" // @Failure 400 {object} shared.ApiBody "Bad Request" // @Failure 500 {object} shared.ApiBody "Internal Error" -// @Router /plugins/jenkins/connections/{connectionId}/search-remote-scopes [GET] -func SearchRemoteScopes(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, errors.Error) { - return remoteHelper.SearchRemoteScopes(input, - func(basicRes context.BasicRes, queryData *api.RemoteQueryData, connection models.JenkinsConnection) ([]models.Job, errors.Error) { - apiClient, err := api.NewApiClientFromConnection(gocontext.TODO(), basicRes, &connection) - if err != nil { - return nil, errors.BadInput.Wrap(err, "failed to get create apiClient") - } - - var resBody []models.Job - breakError := errors.Default.New("we need break from get all jobs for page full") - count := 0 - pageoOffset := (queryData.Page - 1) * queryData.PerPage - err = GetAllJobs(apiClient, "", "", queryData.PerPage, func(job *models.Job, isPath bool) errors.Error { - if job.Jobs == nil { - if strings.Contains(job.FullName, queryData.Search[0]) { - if count >= pageoOffset { - resBody = append(resBody, *job) - } - count++ - } - if len(resBody) > queryData.PerPage { - return breakError - } - } - return nil - }) - if err != nil && err != breakError { - return nil, errors.BadInput.Wrap(err, "failed to get create apiClient") - } +// @Success 200 {object} dsmodels.DsRemoteApiScopeList[models.JenkinsJob] +// @Tags plugins/jenkins +// @Router /plugins/jenkins/connections/{connectionId}/remote-scopes [GET] +func RemoteScopes(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, errors.Error) { + return raScopeList.Get(input) +} - return resBody, nil - }) +// @Summary Remote server API proxy +// @Description Forward API requests to the specified remote server +// @Param connectionId path int true "connection ID" +// @Param path path string true "path to a API endpoint" +// @Router /plugins/github/connections/{connectionId}/proxy/{path} [GET] +func Proxy(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, errors.Error) { + return raProxy.Proxy(input) } diff --git a/backend/plugins/jenkins/api/scope.go b/backend/plugins/jenkins/api/scope_api.go similarity index 93% rename from backend/plugins/jenkins/api/scope.go rename to backend/plugins/jenkins/api/scope_api.go index 21e07c8f3..e39d9cecc 100644 --- a/backend/plugins/jenkins/api/scope.go +++ b/backend/plugins/jenkins/api/scope_api.go @@ -45,10 +45,10 @@ type ScopeReq api.ScopeReq[models.JenkinsJob] // @Failure 500 {object} shared.ApiBody "Internal Error" // @Router /plugins/jenkins/connections/{connectionId}/scopes [PUT] func PutScope(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, errors.Error) { - return scopeHelper.Put(input) + return dsHelper.ScopeApi.PutMultiple(input) } -// UpdateScope patch to jenkins job +// PatchScope patch to jenkins job // @Summary patch to jenkins job // @Description patch to jenkins job // @Tags plugins/jenkins @@ -60,9 +60,9 @@ func PutScope(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, errors // @Failure 400 {object} shared.ApiBody "Bad Request" // @Failure 500 {object} shared.ApiBody "Internal Error" // @Router /plugins/jenkins/connections/{connectionId}/scopes/{scopeId} [PATCH] -func UpdateScope(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, errors.Error) { +func PatchScope(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, errors.Error) { input.Params["scopeId"] = strings.TrimLeft(input.Params["scopeId"], "/") - return scopeHelper.Update(input) + return dsHelper.ScopeApi.Patch(input) } // GetScopeList get Jenkins jobs @@ -79,7 +79,7 @@ func UpdateScope(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, err // @Failure 500 {object} shared.ApiBody "Internal Error" // @Router /plugins/jenkins/connections/{connectionId}/scopes [GET] func GetScopeList(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, errors.Error) { - return scopeHelper.GetScopeList(input) + return dsHelper.ScopeApi.GetPage(input) } // GetScope get one Jenkins job @@ -94,7 +94,7 @@ func GetScopeList(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, er // @Router /plugins/jenkins/connections/{connectionId}/scopes/{scopeId} [GET] func GetScope(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, errors.Error) { input.Params["scopeId"] = strings.TrimLeft(input.Params["scopeId"], "/") - return scopeHelper.GetScope(input) + return dsHelper.ScopeApi.GetScopeDetail(input) } // DeleteScope delete plugin data associated with the scope and optionally the scope itself @@ -110,5 +110,5 @@ func GetScope(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, errors // @Failure 500 {object} shared.ApiBody "Internal Error" // @Router /plugins/jenkins/connections/{connectionId}/scopes/{scopeId} [DELETE] func DeleteScope(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, errors.Error) { - return scopeHelper.Delete(input) + return dsHelper.ScopeApi.Delete(input) } diff --git a/backend/plugins/jenkins/api/scope_config.go b/backend/plugins/jenkins/api/scope_config_api.go similarity index 94% rename from backend/plugins/jenkins/api/scope_config.go rename to backend/plugins/jenkins/api/scope_config_api.go index fee76e6bb..2a9c82df7 100644 --- a/backend/plugins/jenkins/api/scope_config.go +++ b/backend/plugins/jenkins/api/scope_config_api.go @@ -34,7 +34,7 @@ import ( // @Failure 500 {object} shared.ApiBody "Internal Error" // @Router /plugins/jenkins/connections/{connectionId}/scope-configs [POST] func CreateScopeConfig(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, errors.Error) { - return scHelper.Create(input) + return dsHelper.ScopeConfigApi.Post(input) } // UpdateScopeConfig update scope config for Jenkins @@ -50,7 +50,7 @@ func CreateScopeConfig(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutpu // @Failure 500 {object} shared.ApiBody "Internal Error" // @Router /plugins/jenkins/connections/{connectionId}/scope-configs/{id} [PATCH] func UpdateScopeConfig(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, errors.Error) { - return scHelper.Update(input) + return dsHelper.ScopeConfigApi.Patch(input) } // GetScopeConfig return one scope config @@ -64,7 +64,7 @@ func UpdateScopeConfig(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutpu // @Failure 500 {object} shared.ApiBody "Internal Error" // @Router /plugins/jenkins/connections/{connectionId}/scope-configs/{id} [GET] func GetScopeConfig(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, errors.Error) { - return scHelper.Update(input) + return dsHelper.ScopeConfigApi.GetDetail(input) } // GetScopeConfigList return all scope configs @@ -79,7 +79,7 @@ func GetScopeConfig(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, // @Failure 500 {object} shared.ApiBody "Internal Error" // @Router /plugins/jenkins/connections/{connectionId}/scope-configs [GET] func GetScopeConfigList(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, errors.Error) { - return scHelper.List(input) + return dsHelper.ScopeConfigApi.GetAll(input) } // DeleteScopeConfig delete a scope config @@ -93,5 +93,5 @@ func GetScopeConfigList(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutp // @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) + return dsHelper.ScopeConfigApi.Delete(input) } diff --git a/backend/plugins/jenkins/impl/impl.go b/backend/plugins/jenkins/impl/impl.go index 8dee70297..db5bc2fe0 100644 --- a/backend/plugins/jenkins/impl/impl.go +++ b/backend/plugins/jenkins/impl/impl.go @@ -186,12 +186,12 @@ func (p Jenkins) ApiResources() map[string]map[string]plugin.ApiResourceHandler "connections/:connectionId/test": { "POST": api.TestExistingConnection, }, - "connections/:connectionId/search-remote-scopes": { - "GET": api.SearchRemoteScopes, - }, + // "connections/:connectionId/search-remote-scopes": { + // "GET": api.SearchRemoteScopes, + // }, "connections/:connectionId/scopes/*scopeId": { "GET": api.GetScope, - "PATCH": api.UpdateScope, + "PATCH": api.PatchScope, "DELETE": api.DeleteScope, }, "connections/:connectionId/scopes": { @@ -250,7 +250,7 @@ func EnrichOptions(taskCtx plugin.TaskContext, err = api.GetJob(apiClient, op.JobPath, op.JobName, op.JobFullName, 100, func(job *models.Job, isPath bool) errors.Error { log.Debug(fmt.Sprintf("Current job: %s", job.FullName)) op.JobPath = job.Path - jenkinsJob := job.ConvertApiScope().(*models.JenkinsJob) + jenkinsJob := job.ToJenkinsJob() jenkinsJob.ConnectionId = op.ConnectionId jenkinsJob.ScopeConfigId = op.ScopeConfigId diff --git a/backend/plugins/jenkins/models/response.go b/backend/plugins/jenkins/models/response.go index 42fd079f8..643bec691 100644 --- a/backend/plugins/jenkins/models/response.go +++ b/backend/plugins/jenkins/models/response.go @@ -19,8 +19,6 @@ package models import ( "strings" - - "github.com/apache/incubator-devlake/core/plugin" ) type Job struct { @@ -45,7 +43,7 @@ func (j Job) GroupName() string { return j.Name } -func (j Job) ConvertApiScope() plugin.ToolLayerScope { +func (j Job) ToJenkinsJob() *JenkinsJob { if j.FullName == "" { if j.Name != "" || j.Path != "" { beforeNames := strings.Split(j.Path, "/")