Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions pkg/api/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,9 @@ const (

// RecentFailedPipelineRecordCount represents the count of recent failed pipeline records.
RecentFailedPipelineRecordCount string = "recentFailedCount"

// Download represents the flag whether download pipeline record logs.
Download string = "download"
)

// ErrorResponse represents response of error.
Expand Down
31 changes: 31 additions & 0 deletions pkg/server/manager/pipelineRecord.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package manager
import (
"fmt"

"github.com/zoumo/logdog"
"gopkg.in/mgo.v2"

"github.com/caicloud/cyclone/api/conversion"
Expand All @@ -35,6 +36,7 @@ type PipelineRecordManager interface {
UpdatePipelineRecord(pipelineRecordID string, pipelineRecord *api.PipelineRecord) (*api.PipelineRecord, error)
DeletePipelineRecord(pipelineRecordID string) error
ClearPipelineRecordsOfPipeline(pipelineID string) error
GetPipelineRecordLogs(pipelineRecordID string) (string, error)
}

// pipelineRecordManager represents the manager for pipeline record.
Expand All @@ -60,6 +62,9 @@ func (m *pipelineRecordManager) CreatePipelineRecord(pipelineRecord *api.Pipelin
func (m *pipelineRecordManager) GetPipelineRecord(pipelineRecordID string) (*api.PipelineRecord, error) {
version, err := m.dataStore.FindVersionByID(pipelineRecordID)
if err != nil {
if err == mgo.ErrNotFound {
return nil, httperror.ErrorContentNotFound.Format(fmt.Sprintf("pipeline record %s", pipelineRecordID))
}
return nil, err
}

Expand Down Expand Up @@ -156,3 +161,29 @@ func (m *pipelineRecordManager) ClearPipelineRecordsOfPipeline(pipelineID string

return nil
}

// GetPipelineRecordLogs gets the pipeline record logs by id.
func (m *pipelineRecordManager) GetPipelineRecordLogs(pipelineRecordID string) (string, error) {
pipelineRecord, err := m.GetPipelineRecord(pipelineRecordID)
if err != nil {
return "", err
}

logdog.Debugf("Pipeline record is %s", pipelineRecord)

status := pipelineRecord.Status
if status != api.Success && status != api.Failed {
return "", fmt.Errorf("Can not get the logs as pipeline record %s is %s, please try after it finishes",
pipelineRecordID, status)
}

log, err := m.dataStore.FindVersionLogByVersionID(pipelineRecordID)
if err != nil {
if err == mgo.ErrNotFound {
return "", httperror.ErrorContentNotFound.Format(fmt.Sprintf("log of pipeline record %s", pipelineRecordID))
}
return "", fmt.Errorf("Fail to get the log for pipeline record %s as %s", pipelineRecordID, err.Error())
}

return log.Logs, nil
}
26 changes: 26 additions & 0 deletions pkg/server/router/pipelineRecord.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,3 +143,29 @@ func (router *router) updatePipelineRecordStatus(request *restful.Request, respo

response.WriteHeaderAndEntity(http.StatusOK, pipelineRecord)
}

// getPipelineRecordLogs handles the request to get pipeline record logs, only supports finished pipeline records.
func (router *router) getPipelineRecordLogs(request *restful.Request, response *restful.Response) {
projectName := request.PathParameter(projectPathParameterName)
pipelineName := request.PathParameter(pipelinePathParameterName)
pipelineRecordID := request.PathParameter(pipelineRecordPathParameterName)
download, err := httputil.DownloadQueryParamsFromRequest(request)
if err != nil {
httputil.ResponseWithError(response, err)
return
}

logs, err := router.pipelineRecordManager.GetPipelineRecordLogs(pipelineRecordID)
if err != nil {
httputil.ResponseWithError(response, err)
return
}

response.AddHeader(restful.HEADER_ContentType, "text/plain")
if download {
logFileName := fmt.Sprintf("%s-%s-%s-log.txt", projectName, pipelineName, pipelineRecordID)
response.AddHeader("Content-Disposition", fmt.Sprintf("attachment; filename=%s", logFileName))
}

response.Write([]byte(logs))
}
10 changes: 9 additions & 1 deletion pkg/server/router/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,15 @@ func (router *router) registerPipelineRecordAPIs(ws *restful.WebService) {
ws.Route(ws.PATCH("/projects/{project}/pipelines/{pipeline}/records/{recordId}/status").To(router.updatePipelineRecordStatus).
Doc("Update the status of pipeline record, only support to set the status as Aborted for running pipeline record").
Param(ws.PathParameter("project", "name of the project").DataType("string")).
Param(ws.PathParameter("pipeline", "name of the pipeline").DataType("string")))
Param(ws.PathParameter("pipeline", "name of the pipeline").DataType("string")).
Param(ws.PathParameter("recordId", "id of the pipeline record").DataType("string")))

// GET /api/v1/projects/{project}/pipelines/{pipeline}/records/{recordId}/logs
ws.Route(ws.GET("/projects/{project}/pipelines/{pipeline}/records/{recordId}/logs").To(router.getPipelineRecordLogs).
Doc("Get the pipeline record log").
Param(ws.PathParameter("project", "name of the project").DataType("string")).
Param(ws.PathParameter("pipeline", "name of the pipeline").DataType("string")).
Param(ws.PathParameter("recordId", "id of the pipeline record").DataType("string")))
}

// registerScmAPIs registers scm related endpoints.
Expand Down
21 changes: 19 additions & 2 deletions pkg/util/http/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ func ResponseWithList(list interface{}, total int) api.ListResponse {
}
}

// QueryParamsFromRequest reads the query params from request body.
// QueryParamsFromRequest reads the query params from request.
func QueryParamsFromRequest(request *restful.Request) (qp api.QueryParams, err error) {
limitStr := request.QueryParameter(api.Limit)
startStr := request.QueryParameter(api.Start)
Expand Down Expand Up @@ -102,7 +102,7 @@ func QueryParamsFromRequest(request *restful.Request) (qp api.QueryParams, err e
return qp, nil
}

// RecordCountQueryParamsFromRequest reads the query params of pipeline record count from request body.
// RecordCountQueryParamsFromRequest reads the query params of pipeline record count from request.
func RecordCountQueryParamsFromRequest(request *restful.Request) (recentCount, recentSuccessCount, recentFailedCount int, err error) {
recentCountStr := request.QueryParameter(api.RecentPipelineRecordCount)
recentSuccessCountStr := request.QueryParameter(api.RecentSuccessPipelineRecordCount)
Expand All @@ -129,3 +129,20 @@ func RecordCountQueryParamsFromRequest(request *restful.Request) (recentCount, r

return
}

// DownloadQueryParamsFromRequest reads the query param whether download pipeline record logs from request.
func DownloadQueryParamsFromRequest(request *restful.Request) (bool, error) {
downloadStr := request.QueryParameter(api.Download)

if downloadStr != "" {
download, err := strconv.ParseBool(downloadStr)
if err != nil {
logdog.Errorf("Download param's value is %s", downloadStr)
return false, httperror.ErrorParamTypeError.Format(api.Download, "bool", "string")
}

return download, nil
}

return false, nil
}