This is an automated email from the ASF dual-hosted git repository.

zhangliang2022 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 8a934843 info api and domain layer info (#2761)
8a934843 is described below

commit 8a934843b5f72f1fd81eeccc5c4f0231cbd8ee06
Author: mappjzc <[email protected]>
AuthorDate: Fri Aug 19 13:26:19 2022 +0800

    info api and domain layer info (#2761)
    
    * feat: get domain tables info
    
    Add GetDomainTablesInfo for get the domain tables info.
    
    Nddtfjiang <[email protected]>
    
    * feat: api plugin info
    
    Add api /plugininfo for get the infomation about domainlayer's tables and 
plugininfos.
    
    Nddtfjiang <[email protected]>
    
    * feat: add dbname to field
    
    Add dbname to field.
    
    Nddtfjiang <[email protected]>
    
    * style: change api struct of return
    
    lowcase the api return json.
    remove key of plugin and tables and field.
    
    Nddtfjiang <[email protected]>
---
 api/plugininfo/plugininifo.go               | 179 ++++++++++++++++++++++++++++
 api/router.go                               |   3 +
 models/domainlayer/domaininfo/domaininfo.go |  79 ++++++++++++
 plugins/core/hub.go                         |  12 ++
 4 files changed, 273 insertions(+)

diff --git a/api/plugininfo/plugininifo.go b/api/plugininfo/plugininifo.go
new file mode 100644
index 00000000..f5261f1d
--- /dev/null
+++ b/api/plugininfo/plugininifo.go
@@ -0,0 +1,179 @@
+/*
+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 plugininfo
+
+import (
+       "net/http"
+       "reflect"
+       "sync"
+
+       "github.com/apache/incubator-devlake/api/shared"
+       "github.com/apache/incubator-devlake/models/domainlayer/domaininfo"
+       "github.com/apache/incubator-devlake/plugins/core"
+       "github.com/apache/incubator-devlake/utils"
+       "github.com/gin-gonic/gin"
+       "gorm.io/gorm/schema"
+)
+
+type SubTaskMeta struct {
+       Name             string   `json:"name"`
+       Required         bool     `json:"required"`
+       EnabledByDefault bool     `json:"enabled_by_default"`
+       Description      string   `json:"description"`
+       DomainTypes      []string `json:"domain_types"`
+}
+
+func CreateSubTaskMeta(subTaskMeta []core.SubTaskMeta) []SubTaskMeta {
+       ret := make([]SubTaskMeta, 0, len(subTaskMeta))
+       for _, meta := range subTaskMeta {
+               ret = append(ret, SubTaskMeta{
+                       Name:             meta.Name,
+                       Required:         meta.Required,
+                       EnabledByDefault: meta.EnabledByDefault,
+                       Description:      meta.Description,
+                       DomainTypes:      meta.DomainTypes,
+               })
+       }
+       return ret
+}
+
+type TableInfo struct {
+       Name         string `json:"name"`
+       Tags         string `json:"tags"`
+       DbName       string `json:"db_name"`
+       DataType     string `json:"data_type"`
+       GORMDataType string `json:"gorm_data_type"`
+}
+
+type TableInfos struct {
+       TableName string       `json:"table_name"`
+       Field     []*TableInfo `json:"field"`
+       Error     *string      `json:"error"`
+}
+
+func NewTableInfos(table core.Tabler) *TableInfos {
+       tableInfos := &TableInfos{
+               TableName: table.TableName(),
+               Error:     nil,
+       }
+
+       fieldInfos := utils.WalkFields(reflect.TypeOf(table), nil)
+       schema, err := schema.Parse(table, &sync.Map{}, schema.NamingStrategy{})
+       if err != nil {
+               errstr := err.Error()
+               tableInfos.Error = &errstr
+       }
+
+       tableInfos.Field = make([]*TableInfo, 0, len(fieldInfos))
+       for _, field := range fieldInfos {
+               dbName := ""
+               dataType := ""
+               gormDataType := ""
+               if schema != nil {
+                       if dbfield, ok := schema.FieldsByName[field.Name]; ok {
+                               dbName = dbfield.DBName
+                               dataType = string(dbfield.DataType)
+                               gormDataType = string(dbfield.GORMDataType)
+                       }
+               }
+               tableInfos.Field = append(tableInfos.Field, &TableInfo{
+                       Name:         field.Name,
+                       Tags:         string(field.Tag),
+                       DbName:       dbName,
+                       DataType:     dataType,
+                       GORMDataType: gormDataType,
+               })
+       }
+
+       return tableInfos
+}
+
+type PluginInfo struct {
+       Name        string        `json:"name"`
+       Description string        `json:"description"`
+       Tables      []*TableInfos `json:"tables"`
+       TaskMeta    []SubTaskMeta `json:"task_mata"`
+}
+
+func NewPluginInfo() *PluginInfo {
+       return &PluginInfo{
+               Tables: make([]*TableInfos, 0),
+       }
+}
+
+type TotalInfo struct {
+       DomainInfos []*TableInfos
+       PluginInfos []*PluginInfo
+}
+
+func NewTotalInfo() *TotalInfo {
+       return &TotalInfo{
+               DomainInfos: make([]*TableInfos, 0),
+               PluginInfos: make([]*PluginInfo, 0),
+       }
+}
+
+// @Get detail info of plugins
+// @Description GET /plugininfo
+// @Description RETURN SAMPLE
+// @Tags framework/plugininfo
+// @Success 200
+// @Failure 400  {string} errcode.Error "Bad Request"
+// @Router /plugininfo [get]
+func Get(c *gin.Context) {
+       info := NewTotalInfo()
+
+       // set the domain layer tables info.
+       domaininfo := domaininfo.GetDomainTablesInfo()
+       for _, table := range domaininfo {
+               tableInfo := NewTableInfos(table)
+               info.DomainInfos = append(info.DomainInfos, tableInfo)
+       }
+
+       // plugin info
+       err := core.TraversalPlugin(func(name string, plugin core.PluginMeta) 
error {
+               infoPlugin := NewPluginInfo()
+               info.PluginInfos = append(info.PluginInfos, infoPlugin)
+
+               // plugin name and description
+               infoPlugin.Name = name
+               infoPlugin.Description = plugin.Description()
+
+               // if this plugin has the plugin task info
+               if pt, ok := plugin.(core.PluginTask); ok {
+                       infoPlugin.TaskMeta = 
CreateSubTaskMeta(pt.SubTaskMetas())
+               }
+
+               // if this plugin has the plugin model info
+               if pm, ok := plugin.(core.PluginModel); ok {
+                       tables := pm.GetTablesInfo()
+                       for _, table := range tables {
+                               TableInfos := NewTableInfos(table)
+                               infoPlugin.Tables = append(infoPlugin.Tables, 
TableInfos)
+                       }
+               }
+
+               return nil
+       })
+
+       if err != nil {
+               shared.ApiOutputError(c, err, http.StatusBadRequest)
+       }
+
+       shared.ApiOutputSuccess(c, info, http.StatusOK)
+}
diff --git a/api/router.go b/api/router.go
index 0d4eb08b..0972c6d2 100644
--- a/api/router.go
+++ b/api/router.go
@@ -26,6 +26,7 @@ import (
        "github.com/apache/incubator-devlake/api/domainlayer"
        "github.com/apache/incubator-devlake/api/ping"
        "github.com/apache/incubator-devlake/api/pipelines"
+       "github.com/apache/incubator-devlake/api/plugininfo"
        "github.com/apache/incubator-devlake/api/push"
        "github.com/apache/incubator-devlake/api/shared"
        "github.com/apache/incubator-devlake/api/task"
@@ -57,6 +58,8 @@ func RegisterRouter(r *gin.Engine) {
        r.POST("/push/:tableName", push.Post)
        r.GET("/domainlayer/repos", domainlayer.ReposIndex)
 
+       r.GET("/plugininfo", plugininfo.Get)
+
        // mount all api resources for all plugins
        pluginsApiResources, err := services.GetPluginsApiResources()
        if err != nil {
diff --git a/models/domainlayer/domaininfo/domaininfo.go 
b/models/domainlayer/domaininfo/domaininfo.go
new file mode 100644
index 00000000..4a8c5b30
--- /dev/null
+++ b/models/domainlayer/domaininfo/domaininfo.go
@@ -0,0 +1,79 @@
+/*
+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 domaininfo
+
+import (
+       "github.com/apache/incubator-devlake/models/domainlayer/code"
+       "github.com/apache/incubator-devlake/models/domainlayer/crossdomain"
+       "github.com/apache/incubator-devlake/models/domainlayer/devops"
+       "github.com/apache/incubator-devlake/models/domainlayer/ticket"
+)
+
+type Tabler interface {
+       TableName() string
+}
+
+func GetDomainTablesInfo() []Tabler {
+       return []Tabler{
+               // code
+               &code.Commit{},
+               &code.CommitFile{},
+               &code.CommitFileComponent{},
+               &code.CommitParent{},
+               &code.Component{},
+               &code.PullRequest{},
+               &code.PullRequestComment{},
+               &code.PullRequestCommit{},
+               &code.PullRequestLabel{},
+               &code.Ref{},
+               &code.RefsCommitsDiff{},
+               &code.RefsPrCherrypick{},
+               &code.Repo{},
+               &code.RepoCommit{},
+               &code.RepoLanguage{},
+               // crossdomain
+               &crossdomain.Account{},
+               &crossdomain.BoardRepo{},
+               &crossdomain.IssueCommit{},
+               &crossdomain.IssueRepoCommit{},
+               &crossdomain.ProjectMapping{},
+               &crossdomain.PullRequestIssue{},
+               &crossdomain.RefsIssuesDiffs{},
+               &crossdomain.Team{},
+               &crossdomain.TeamUser{},
+               &crossdomain.User{},
+               &crossdomain.UserAccount{},
+               // devops
+               &devops.Build{},
+               &devops.CICDPipeline{},
+               &devops.CICDTask{},
+               &devops.Job{},
+               // didgen no table
+               // ticket
+               &ticket.Board{},
+               &ticket.BoardIssue{},
+               &ticket.BoardSprint{},
+               &ticket.Issue{},
+               &ticket.IssueChangelogs{},
+               &ticket.IssueComment{},
+               &ticket.IssueLabel{},
+               &ticket.IssueWorklog{},
+               &ticket.Sprint{},
+               &ticket.SprintIssue{},
+       }
+}
diff --git a/plugins/core/hub.go b/plugins/core/hub.go
index 9d3416fc..6ce4c826 100644
--- a/plugins/core/hub.go
+++ b/plugins/core/hub.go
@@ -45,6 +45,18 @@ func GetPlugin(name string) (PluginMeta, error) {
        return nil, fmt.Errorf("Plugin `%s` doesn't exist", name)
 }
 
+type PluginCallBack func(name string, plugin PluginMeta) error
+
+func TraversalPlugin(handle PluginCallBack) error {
+       for name, plugin := range plugins {
+               err := handle(name, plugin)
+               if err != nil {
+                       return err
+               }
+       }
+       return nil
+}
+
 func AllPlugins() map[string]PluginMeta {
        return plugins
 }

Reply via email to