diff --git a/pkg/kapis/devops/v1alpha2/devops.go b/pkg/kapis/devops/v1alpha2/devops.go index f9d8ca52c..62c587eed 100644 --- a/pkg/kapis/devops/v1alpha2/devops.go +++ b/pkg/kapis/devops/v1alpha2/devops.go @@ -24,12 +24,14 @@ import ( "k8s.io/apiserver/pkg/authentication/user" log "k8s.io/klog" "kubesphere.io/kubesphere/pkg/api" + "kubesphere.io/kubesphere/pkg/apis/devops/v1alpha3" iamv1alpha2 "kubesphere.io/kubesphere/pkg/apis/iam/v1alpha2" "kubesphere.io/kubesphere/pkg/apiserver/request" "kubesphere.io/kubesphere/pkg/constants" "kubesphere.io/kubesphere/pkg/models/devops" clientDevOps "kubesphere.io/kubesphere/pkg/simple/client/devops" "net/http" + "strconv" "strings" ) @@ -49,15 +51,81 @@ func (h *ProjectPipelineHandler) GetPipeline(req *restful.Request, resp *restful resp.WriteAsJson(res) } +func (h *ProjectPipelineHandler) getPipelinesByRequest(req *restful.Request) (api.ListResult, error) { + // this is a very trick way, but don't have a better solution for now + var ( + err error + start int + limit int + namespace string + ) + + // parse query from the request + query := req.QueryParameter("q") + req.Request.PostForm.Set("limit", "1000") + for _, val := range strings.Split(query, ";") { + if strings.HasPrefix(val, "pipeline:") { + namespace = strings.TrimLeft(val, "pipeline:") + namespace = strings.Split(namespace, "/")[0] + } + } + + // make sure we have an appropriate value + if start, err = strconv.Atoi(req.QueryParameter("start")); err != nil { + start = 0 + } + if limit, err = strconv.Atoi(req.QueryParameter("limit")); err != nil { + limit = 10 + } + + defer req.Request.Form.Set("limit", "10000") // assume the pipelines no more than 10k + + return h.devopsOperator.ListPipelineObj(namespace, func(list []*v1alpha3.Pipeline, i int, j int) bool { + return strings.Compare(list[i].Name, list[j].Name) < 0 + }, limit, start) +} + func (h *ProjectPipelineHandler) ListPipelines(req *restful.Request, resp *restful.Response) { - res, err := h.devopsOperator.ListPipelines(req.Request) + objs, err := h.getPipelinesByRequest(req) if err != nil { parseErr(err, resp) return } + // get all pipelines which come from ks + pipelineList := &clientDevOps.PipelineList{ + Total: objs.TotalItems, + Items: make([]clientDevOps.Pipeline, objs.TotalItems), + } + pipelineMap := make(map[string]int, objs.TotalItems) + for i, item := range objs.Items { + if pipeline, ok := item.(v1alpha3.Pipeline); !ok { + continue + } else { + pip := clientDevOps.Pipeline{ + Name: pipeline.Name, + } + + pipelineMap[pipeline.Name] = i + pipelineList.Items[i] = pip + } + } + + // get all pipelines which come from Jenkins + // fill out the rest fields + res, err := h.devopsOperator.ListPipelines(req.Request) + if err != nil { + log.Error(err) + } else { + for _, item := range res.Items { + if index, ok := pipelineMap[item.Name]; ok { + pipelineList.Items[index] = item + } + } + } + resp.Header().Set(restful.HEADER_ContentType, restful.MIME_JSON) - resp.WriteAsJson(res) + resp.WriteAsJson(pipelineList) } func (h *ProjectPipelineHandler) GetPipelineRun(req *restful.Request, resp *restful.Response) { diff --git a/pkg/kapis/devops/v1alpha3/handler.go b/pkg/kapis/devops/v1alpha3/handler.go index 62314b198..52cb29500 100644 --- a/pkg/kapis/devops/v1alpha3/handler.go +++ b/pkg/kapis/devops/v1alpha3/handler.go @@ -184,7 +184,7 @@ func (h *devopsHandler) ListPipeline(request *restful.Request, response *restful devops := request.PathParameter("devops") limit, offset := params.ParsePaging(request) - objs, err := h.devops.ListPipelineObj(devops, limit, offset) + objs, err := h.devops.ListPipelineObj(devops, nil, limit, offset) if err != nil { klog.Error(err) if errors.IsNotFound(err) { diff --git a/pkg/models/devops/devops.go b/pkg/models/devops/devops.go index 550fc3a33..262fe01cd 100644 --- a/pkg/models/devops/devops.go +++ b/pkg/models/devops/devops.go @@ -41,6 +41,7 @@ import ( resourcesV1alpha3 "kubesphere.io/kubesphere/pkg/models/resources/v1alpha3" "kubesphere.io/kubesphere/pkg/simple/client/devops" "net/http" + "sort" "sync" ) @@ -59,7 +60,7 @@ type DevopsOperator interface { GetPipelineObj(projectName string, pipelineName string) (*v1alpha3.Pipeline, error) DeletePipelineObj(projectName string, pipelineName string) error UpdatePipelineObj(projectName string, pipeline *v1alpha3.Pipeline) (*v1alpha3.Pipeline, error) - ListPipelineObj(projectName string, limit, offset int) (api.ListResult, error) + ListPipelineObj(projectName string, sortFunc func([]*v1alpha3.Pipeline, int, int) bool, limit, offset int) (api.ListResult, error) CreateCredentialObj(projectName string, s *v1.Secret) (*v1.Secret, error) GetCredentialObj(projectName string, secretName string) (*v1.Secret, error) @@ -254,7 +255,7 @@ func (d devopsOperator) UpdatePipelineObj(projectName string, pipeline *v1alpha3 return d.ksclient.DevopsV1alpha3().Pipelines(projectObj.Status.AdminNamespace).Update(pipeline) } -func (d devopsOperator) ListPipelineObj(projectName string, limit, offset int) (api.ListResult, error) { +func (d devopsOperator) ListPipelineObj(projectName string, sortFunc func([]*v1alpha3.Pipeline, int, int) bool, limit, offset int) (api.ListResult, error) { projectObj, err := d.ksInformers.Devops().V1alpha3().DevOpsProjects().Lister().Get(projectName) if err != nil { return api.ListResult{}, err @@ -263,6 +264,14 @@ func (d devopsOperator) ListPipelineObj(projectName string, limit, offset int) ( if err != nil { return api.ListResult{}, err } + + // sort the pipeline list according to the request + if sortFunc != nil { + sort.SliceStable(data, func(i, j int) bool { + return sortFunc(data, i, j) + }) + } + items := make([]interface{}, 0) var result []interface{} for _, item := range data { diff --git a/pkg/simple/client/devops/pipeline.go b/pkg/simple/client/devops/pipeline.go index 0eb78db04..3f0ed64bd 100644 --- a/pkg/simple/client/devops/pipeline.go +++ b/pkg/simple/client/devops/pipeline.go @@ -81,7 +81,7 @@ type Pipeline struct { NumberOfFolders int `json:"numberOfFolders,omitempty" description:"number of folders"` NumberOfPipelines int `json:"numberOfPipelines,omitempty" description:"number of pipelines"` PipelineFolderNames []interface{} `json:"pipelineFolderNames,omitempty" description:"pipeline folder names"` - WeatherScore int `json:"weatherScore,omitempty" description:"the score to description the result of pipeline activity"` + WeatherScore int `json:"weatherScore" description:"the score to description the result of pipeline activity"` BranchNames []string `json:"branchNames,omitempty" description:"branch names"` NumberOfFailingBranches int `json:"numberOfFailingBranches,omitempty" description:"number of failing branches"` NumberOfFailingPullRequests int `json:"numberOfFailingPullRequests,omitempty" description:"number of failing pull requests"`