diff --git a/module/catalogue/iml.go b/module/catalogue/iml.go index ea1d1ac0..5720277c 100644 --- a/module/catalogue/iml.go +++ b/module/catalogue/iml.go @@ -229,24 +229,7 @@ func (i *imlCatalogueModule) ServiceDetail(ctx context.Context, sid string) (*ca return nil, fmt.Errorf("get running release failed: %w", err) } - _, docCommits, _, err := i.releaseService.GetReleaseInfos(ctx, r.UUID) - if err != nil { - return nil, fmt.Errorf("get release apis failed: %w", err) - } - apiMap := make(map[string]*release.APIDocumentCommit) - apiIds := make([]string, 0, len(docCommits)) - for _, v := range docCommits { - apiIds = append(apiIds, v.API) - apiMap[v.API] = v - } - //apiList, err := i.apiService.ListInfo(ctx, apiIds...) - //if err != nil { - // return nil, err - //} - //apiNum := 0 - //if len(docCommits) > 0 { - // i.apiDocService.ListDocCommit(ctx,docCommits[0].Commit) - //} + countMap, err := i.subscribeService.CountMapByService(ctx, subscribe.ApplyStatusSubscribe, sid) if err != nil { return nil, err @@ -260,13 +243,27 @@ func (i *imlCatalogueModule) ServiceDetail(ctx context.Context, sid string) (*ca }, func(t *service_tag.Tag) bool { return t.Sid == sid }) + _, _, docCommits, _, err := i.releaseService.GetReleaseInfos(ctx, r.UUID) + if err != nil { + return nil, fmt.Errorf("get release apis failed: %w", err) + } + var apiDoc string + var apiNum int + if len(docCommits) > 0 { + commit, err := i.apiDocService.GetDocCommit(ctx, docCommits[0].Commit) + if err != nil { + return nil, err + } + apiDoc = commit.Data.Content + apiNum = int(commit.Data.APICount) + } return &catalogue_dto.ServiceDetail{ Name: s.Name, Description: s.Description, Document: docStr, Basic: &catalogue_dto.ServiceBasic{ - Team: auto.UUID(s.Team), - //ApiNum: len(apis), + Team: auto.UUID(s.Team), + ApiNum: apiNum, AppNum: int(countMap[s.Id]), Tags: auto.List(tagIds), Catalogue: auto.UUID(s.Catalogue), @@ -274,6 +271,7 @@ func (i *imlCatalogueModule) ServiceDetail(ctx context.Context, sid string) (*ca UpdateTime: auto.TimeLabel(r.CreateAt), Logo: s.Logo, }, + APIDoc: apiDoc, }, nil } diff --git a/module/release/iml.go b/module/release/iml.go index 045024c5..6ea163d3 100644 --- a/module/release/iml.go +++ b/module/release/iml.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + api_doc "github.com/APIParkLab/APIPark/service/api-doc" "github.com/APIParkLab/APIPark/service/cluster" "github.com/APIParkLab/APIPark/service/service" @@ -33,6 +34,7 @@ type imlReleaseModule struct { projectDiffModule serviceDiff.IServiceDiffModule `autowired:""` releaseService release.IReleaseService `autowired:""` apiService api.IAPIService `autowired:""` + apiDocService api_doc.IAPIDocService `autowired:""` upstreamService upstream.IUpstreamService `autowired:""` publishService publish.IPublishService `autowired:""` transaction store.ITransaction `autowired:""` @@ -54,7 +56,7 @@ func (m *imlReleaseModule) Create(ctx context.Context, serviceId string, input * return "", fmt.Errorf("cluster not set:%w", err) } - apis, err := m.apiService.ListForService(ctx, proInfo.Id) + apis, err := m.apiService.ListInfoForService(ctx, proInfo.Id) if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return "", errors.New("api not found") @@ -64,7 +66,7 @@ func (m *imlReleaseModule) Create(ctx context.Context, serviceId string, input * if len(apis) == 0 { return "", errors.New("api not found") } - apiUUIDS := utils.SliceToSlice(apis, func(a *api.API) string { + apiUUIDS := utils.SliceToSlice(apis, func(a *api.Info) string { return a.UUID }) apiProxy, err := m.apiService.ListLatestCommitProxy(ctx, apiUUIDS...) @@ -77,16 +79,7 @@ func (m *imlReleaseModule) Create(ctx context.Context, serviceId string, input * if len(apis) != len(apiProxy) { return "", errors.New("api or document not found") } - //apiDocs, err := m.apiService.ListLatestCommitDocument(ctx, apiUUIDS...) - //if err != nil { - // if errors.Is(err, gorm.ErrRecordNotFound) { - // return "", errors.New("api config or document not found") - // } - // return "", err - //} - //if len(apis) != len(apiDocs) { - // return "", errors.New("api or document not found") - //} + upstreams, err := m.upstreamService.ListLatestCommit(ctx, serviceId) if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { @@ -98,9 +91,7 @@ func (m *imlReleaseModule) Create(ctx context.Context, serviceId string, input * apiProxyCommits := utils.SliceToMapO(apiProxy, func(c *commit.Commit[api.Proxy]) (string, string) { return c.Target, c.UUID }) - //apiDocumentCommits := utils.SliceToMapO(apiDocs, func(c *commit.Commit[api.Document]) (string, string) { - // return c.Target, c.UUID - //}) + upstreamCommits := utils.SliceToMapArray(upstreams, func(c *commit.Commit[upstream.Config]) string { return c.Target }) @@ -109,15 +100,56 @@ func (m *imlReleaseModule) Create(ctx context.Context, serviceId string, input * return c.Key, c.UUID }) }) - if !m.releaseService.Completeness(utils.SliceToSlice(clusters, func(s *cluster.Cluster) string { - return s.Uuid - }), apiUUIDS, apiProxy, nil, upstreams) { - return "", errors.New("completeness check failed") - } - newRelease, err := m.releaseService.CreateRelease(ctx, serviceId, input.Version, input.Remark, apiProxyCommits, nil, upstreamCommitsForUKC) + + var newRelease *release.Release + err = m.transaction.Transaction(ctx, func(ctx context.Context) error { + for _, a := range apis { + err = m.apiService.SaveRequest(ctx, a.UUID, &api.Request{ + Path: a.Path, + Methods: a.Methods, + Protocols: a.Protocols, + Match: a.Match, + Disable: a.Disable, + }) + if err != nil { + return err + } + } + requestCommits, err := m.apiService.ListLatestCommitRequest(ctx, apiUUIDS...) + if err != nil { + return err + } + + doc, err := m.apiDocService.GetDoc(ctx, serviceId) + if err != nil { + return err + } + err = m.apiDocService.CommitDoc(ctx, serviceId, doc) + if err != nil { + return err + } + docCommit, err := m.apiDocService.LatestDocCommit(ctx, serviceId) + if err != nil { + return err + } + docCommitMap := map[string]string{ + docCommit.Target: docCommit.UUID, + } + if !m.releaseService.Completeness(utils.SliceToSlice(clusters, func(s *cluster.Cluster) string { + return s.Uuid + }), apiUUIDS, requestCommits, apiProxy, upstreams) { + return errors.New("completeness check failed") + } + requestCommitMap := utils.SliceToMapO(requestCommits, func(c *commit.Commit[api.Request]) (string, string) { + return c.Target, c.UUID + }) + newRelease, err = m.releaseService.CreateRelease(ctx, serviceId, input.Version, input.Remark, requestCommitMap, apiProxyCommits, docCommitMap, nil, upstreamCommitsForUKC) + return err + }) if err != nil { return "", err } + return newRelease.UUID, err } diff --git a/resources/access/access.yaml b/resources/access/access.yaml index 9748dfba..90ac8375 100644 --- a/resources/access/access.yaml +++ b/resources/access/access.yaml @@ -94,7 +94,7 @@ system: - "PUT:/api/v1/catalogue/sort" dependents: - system.api_market.service_classification.view - - name: devops + - name: Devops cname: 运维 value: 'devops' children: @@ -132,6 +132,22 @@ system: - "POST:/api/v1/certificate" - "PUT:/api/v1/certificate" - "DELETE:/api/v1/certificate" + - name: Data Source + cname: '数据源' + value: 'data_source' + children: + - name: view + cname: '查看' + value: 'view' + guest_allow: true + apis: + - "GET:/api/v1/monitor/config" + - name: manager + cname: '管理' + value: 'manager' + apis: + - "POST:/api/v1/monitor/config" + - "PUT:/api/v1/monitor/config" - name: log configuration cname: 日志 value: 'log_configuration' diff --git a/resources/access/role.yaml b/resources/access/role.yaml index 406b1006..8f5991fb 100644 --- a/resources/access/role.yaml +++ b/resources/access/role.yaml @@ -11,8 +11,8 @@ system: - system.devops.log_configuration.view - system.devops.ssl_certificate.manager - system.devops.ssl_certificate.view - - system.devops.monitor.manager - - system.devops.monitor.view + - system.devops.data_source.manager + - system.devops.data_source.view - system.organization.member.manager - system.organization.member.view - system.organization.role.view_system_role @@ -46,8 +46,8 @@ system: - system.devops.log_configuration.view - system.devops.ssl_certificate.manager - system.devops.ssl_certificate.view - - system.devops.monitor.manager - - system.devops.monitor.view + - system.devops.data_source.manager + - system.devops.data_source.view - system.workspace.api_market.view - system.workspace.application.view_all - system.workspace.service.view_all diff --git a/service/api-doc/iml.go b/service/api-doc/iml.go index 90563cd9..df6b0bde 100644 --- a/service/api-doc/iml.go +++ b/service/api-doc/iml.go @@ -19,6 +19,10 @@ type imlAPIDocService struct { commitService commit.ICommitWithKeyService[DocCommit] `autowired:""` } +func (i *imlAPIDocService) GetDocCommit(ctx context.Context, commitId string) (*commit.Commit[DocCommit], error) { + return i.commitService.Get(ctx, commitId) +} + func (i *imlAPIDocService) ListDocCommit(ctx context.Context, commitIds ...string) ([]*commit.Commit[DocCommit], error) { return i.commitService.List(ctx, commitIds...) } @@ -103,6 +107,17 @@ func (i *imlAPIDocService) LatestDocCommit(ctx context.Context, serviceId string return i.commitService.Latest(ctx, serviceId) } -func (i *imlAPIDocService) CommitDoc(ctx context.Context, serviceId string, data *DocCommit) error { - return i.commitService.Save(ctx, serviceId, data) +func (i *imlAPIDocService) CommitDoc(ctx context.Context, serviceId string, data *Doc) error { + doc, err := NewDocLoader(data.Content) + if err != nil { + return err + } + if err := doc.Valid(); err != nil { + return err + } + + return i.commitService.Save(ctx, serviceId, &DocCommit{ + Content: data.Content, + APICount: doc.APICount(), + }) } diff --git a/service/api-doc/service.go b/service/api-doc/service.go index d726f02a..9baf9549 100644 --- a/service/api-doc/service.go +++ b/service/api-doc/service.go @@ -15,10 +15,13 @@ type IAPIDocService interface { // GetDoc 获取文档 GetDoc(ctx context.Context, serviceId string) (*Doc, error) + CommitDoc(ctx context.Context, serviceId string, data *Doc) error + APICountByServices(ctx context.Context, serviceIds ...string) (map[string]int64, error) + + GetDocCommit(ctx context.Context, commitId string) (*commit.Commit[DocCommit], error) // LatestDocCommit 获取最新文档 LatestDocCommit(ctx context.Context, serviceId string) (*commit.Commit[DocCommit], error) - CommitDoc(ctx context.Context, serviceId string, data *DocCommit) error ListLatestDocCommit(ctx context.Context, serviceIds ...string) ([]*commit.Commit[DocCommit], error) ListDocCommit(ctx context.Context, commitIds ...string) ([]*commit.Commit[DocCommit], error) LatestAPICountByServices(ctx context.Context, serviceIds ...string) (map[string]int64, error) diff --git a/service/release/iml.go b/service/release/iml.go index b82b8e0e..991bfa28 100644 --- a/service/release/iml.go +++ b/service/release/iml.go @@ -28,22 +28,21 @@ type imlReleaseService struct { releaseRuntime release.IReleaseRuntime `autowired:""` } -func (s *imlReleaseService) Completeness(partitions []string, apis []string, proxyCommits []*commit.Commit[api.Proxy], documentCommits []*commit.Commit[api.Document], upstreamCommits []*commit.Commit[upstream.Config]) bool { +func (s *imlReleaseService) Completeness(partitions []string, apis []string, apiRequestCommits []*commit.Commit[api.Request], proxyCommits []*commit.Commit[api.Proxy], upstreamCommits []*commit.Commit[upstream.Config]) bool { + requests := utils.SliceToMap(apiRequestCommits, func(o *commit.Commit[api.Request]) string { + return o.Target + }) proxys := utils.SliceToMap(proxyCommits, func(o *commit.Commit[api.Proxy]) string { return o.Target }) - documents := utils.SliceToMap(documentCommits, func(o *commit.Commit[api.Document]) string { - return o.Target - }) for _, aid := range apis { - _, has := proxys[aid] + _, has := requests[aid] if !has { return false } - - _, has = documents[aid] + _, has = proxys[aid] if !has { return false } @@ -267,10 +266,19 @@ func (s *imlReleaseService) SetRunning(ctx context.Context, service string, id s } -func (s *imlReleaseService) CreateRelease(ctx context.Context, service string, version string, remark string, apisProxyCommits, apiDocCommits map[string]string, upstreams map[string]map[string]string) (*Release, error) { +func (s *imlReleaseService) CreateRelease(ctx context.Context, service string, version string, remark string, apiRequestCommit, apisProxyCommits, apiDocCommits, serviceDocCommits map[string]string, upstreams map[string]map[string]string) (*Release, error) { operator := utils.UserId(ctx) releaseId := uuid.NewString() commits := make([]*release.Commit, 0, len(apisProxyCommits)+len(apiDocCommits)+len(upstreams)) + for apiId, commitUUID := range apiRequestCommit { + commits = append(commits, &release.Commit{ + Type: CommitApiRequest, + Target: apiId, + Release: releaseId, + Key: CommitApiRequest, + Commit: commitUUID, + }) + } for aid, commitUUID := range apisProxyCommits { commits = append(commits, &release.Commit{ Type: CommitApiProxy, @@ -408,28 +416,35 @@ func (s *imlReleaseService) List(ctx context.Context, service string) ([]*Releas return utils.SliceToSlice(list, FromEntity), nil } -func (s *imlReleaseService) GetReleaseInfos(ctx context.Context, id string) ([]*APIProxyCommit, []*APIDocumentCommit, []*UpstreamCommit, error) { +func (s *imlReleaseService) GetReleaseInfos(ctx context.Context, id string) ([]*APICommit, []*APICommit, []*APICommit, []*UpstreamCommit, error) { commits, err := s.commitStore.List(ctx, map[string]interface{}{ "release": id, }) if err != nil { - return nil, nil, nil, err + return nil, nil, nil, nil, err } - apiProxyCommits := make([]*APIProxyCommit, 0, len(commits)) - apiDocumentCommits := make([]*APIDocumentCommit, 0, len(commits)) + apiRequestCommits := make([]*APICommit, 0, len(commits)) + apiProxyCommits := make([]*APICommit, 0, len(commits)) + apiDocumentCommits := make([]*APICommit, 0, len(commits)) upstreamCommits := make([]*UpstreamCommit, 0, len(commits)) for _, v := range commits { switch v.Type { + case CommitApiRequest: + apiRequestCommits = append(apiRequestCommits, &APICommit{ + Release: v.Release, + API: v.Target, + Commit: v.Commit, + }) case CommitApiProxy: - apiProxyCommits = append(apiProxyCommits, &APIProxyCommit{ + apiProxyCommits = append(apiProxyCommits, &APICommit{ Release: v.Release, API: v.Target, Commit: v.Commit, }) case CommitApiDocument: - apiDocumentCommits = append(apiDocumentCommits, &APIDocumentCommit{ + apiDocumentCommits = append(apiDocumentCommits, &APICommit{ Release: v.Release, API: v.Target, Commit: v.Commit, @@ -446,7 +461,7 @@ func (s *imlReleaseService) GetReleaseInfos(ctx context.Context, id string) ([]* } - return apiProxyCommits, apiDocumentCommits, upstreamCommits, nil + return apiRequestCommits, apiProxyCommits, apiDocumentCommits, upstreamCommits, nil } func (s *imlReleaseService) GetRunning(ctx context.Context, service string) (*Release, error) { diff --git a/service/release/model.go b/service/release/model.go index 24fb9bc3..226d3eaa 100644 --- a/service/release/model.go +++ b/service/release/model.go @@ -26,16 +26,12 @@ func FromEntity(e *release.Release) *Release { } } -type APIProxyCommit struct { - Release string - API string - Commit string -} -type APIDocumentCommit struct { +type APICommit struct { Release string API string Commit string } + type UpstreamCommit struct { Release string Upstream string diff --git a/service/release/service.go b/service/release/service.go index 77ce0d30..a01e7955 100644 --- a/service/release/service.go +++ b/service/release/service.go @@ -14,18 +14,16 @@ type IReleaseService interface { // GetRelease 获取发布信息 GetRelease(ctx context.Context, id string) (*Release, error) // CreateRelease 创建发布 - CreateRelease(ctx context.Context, service string, version string, remark string, apisProxyCommits, apiDocCommits map[string]string, upstreams map[string]map[string]string) (*Release, error) + CreateRelease(ctx context.Context, service string, version string, remark string, apiRequestCommit, apisProxyCommits, apiDocCommits, serviceDocCommits map[string]string, upstreams map[string]map[string]string) (*Release, error) // DeleteRelease 删除发布 DeleteRelease(ctx context.Context, id string) error List(ctx context.Context, service string) ([]*Release, error) - //GetApiProxyCommit(ctx context.Context, id string, apiUUID string) (string, error) - //GetApiDocCommit(ctx context.Context, id string, apiUUID string) (string, error) - GetReleaseInfos(ctx context.Context, id string) ([]*APIProxyCommit, []*APIDocumentCommit, []*UpstreamCommit, error) + GetReleaseInfos(ctx context.Context, id string) ([]*APICommit, []*APICommit, []*APICommit, []*UpstreamCommit, error) GetCommits(ctx context.Context, id string) ([]*ProjectCommits, error) GetRunningApiDocCommit(ctx context.Context, service string, apiUUID string) (string, error) GetRunningApiProxyCommit(ctx context.Context, service string, apiUUID string) (string, error) - Completeness(partitions []string, apis []string, proxyCommits []*commit.Commit[api.Proxy], documentCommits []*commit.Commit[api.Document], upstreamCommits []*commit.Commit[upstream.Config]) bool + Completeness(partitions []string, apis []string, requestCommits []*commit.Commit[api.Request], proxyCommits []*commit.Commit[api.Proxy], upstreamCommits []*commit.Commit[upstream.Config]) bool // GetRunning gets the running release with the given service. // diff --git a/stores/release/release.go b/stores/release/release.go index 8dfadce1..9e23a33c 100644 --- a/stores/release/release.go +++ b/stores/release/release.go @@ -22,7 +22,7 @@ func (r *Release) TableName() string { type Commit struct { Id int64 `gorm:"column:id;type:BIGINT(20);AUTO_INCREMENT;NOT NULL;comment:id;primary_key;comment:主键ID;"` Release string `gorm:"type:varchar(36);not null;column:release;comment:release id; index:release; uniqueIndex:type_release_type_key"` - Type string `gorm:"type:varchar(10);not null;column:type;comment:类型;index:type;uniqueIndex:type_release_type_key"` + Type string `gorm:"type:varchar(30);not null;column:type;comment:类型;index:type;uniqueIndex:type_release_type_key"` Target string `gorm:"type:varchar(36);not null;column:target;comment:目标;index:target;uniqueIndex:type_release_type_key"` Key string `gorm:"type:varchar(36);not null;column:api;comment:api id;uniqueIndex:type_release_type_key"` Commit string `gorm:"type:varchar(36);not null;column:commit;comment:commit;"`