66"net/http"
77"os"
88"path/filepath"
9+ "sort"
910"strconv"
1011
1112"github.com/gaia-pipeline/gaia"
@@ -21,6 +22,7 @@ const (
2122type jobLogs struct {
2223Log string `json:"log"`
2324StartPos int `json:"start"`
25+ Finished bool `json:"finished"`
2426}
2527
2628// PipelineRunGet returns details about a specific pipeline run.
@@ -68,6 +70,7 @@ func PipelineGetAllRuns(c echo.Context) error {
6870}
6971
7072// GetJobLogs returns logs and new start position for the given job.
73+ // If no jobID is given, a collection of all jobs logs will be returned.
7174//
7275// Required parameters:
7376// pipelineid - Related pipeline id
@@ -95,32 +98,87 @@ func GetJobLogs(c echo.Context) error {
9598return c .String (http .StatusBadRequest ,fmt .Sprintf ("invalid maxbufferlen provided. Max number is %d" ,maxMaxBufferLen ))
9699}
97100
101+ // Transform pipelineid to int
102+ p ,err := strconv .Atoi (pipelineID )
103+ if err != nil {
104+ return c .String (http .StatusBadRequest ,"invalid pipeline id given" )
105+ }
106+
107+ // Transform pipelinerunid to int
108+ r ,err := strconv .Atoi (pipelineRunID )
109+ if err != nil {
110+ return c .String (http .StatusBadRequest ,"invalid pipeline run id given" )
111+ }
112+
113+ // Get pipeline run from store
114+ run ,err := storeService .PipelineGetRunByPipelineIDAndID (p ,r )
115+ if err != nil {
116+ return c .String (http .StatusBadRequest ,"cannot find pipeline run with given pipeline id and pipeline run id" )
117+ }
118+
119+ // jobID is not empty, just return the logs from this job
120+ if jobID != "" {
121+ for _ ,job := range run .Jobs {
122+ if strconv .FormatUint (uint64 (job .ID ),10 )== jobID {
123+ // Get logs
124+ jL ,err := getLogs (pipelineID ,pipelineRunID ,jobID ,startPos ,maxBufferLen )
125+ if err != nil {
126+ return c .String (http .StatusBadRequest ,err .Error ())
127+ }
128+
129+ return c .JSON (http .StatusOK ,* jL )
130+ }
131+ }
132+
133+ // Logs for given job id not found
134+ return c .String (http .StatusBadRequest ,"cannot find job with given job id" )
135+ }
136+
137+ // Sort the slice. This is important for the order of the returned logs.
138+ sort .Slice (run .Jobs ,func (i ,j int )bool {
139+ return run .Jobs [i ].Priority < run .Jobs [j ].Priority
140+ })
141+
142+ // Return a collection of all logs
143+ jobs := []jobLogs {}
144+ for _ ,job := range run .Jobs {
145+ // Get logs
146+ jL ,err := getLogs (pipelineID ,pipelineRunID ,strconv .FormatUint (uint64 (job .ID ),10 ),startPos ,maxBufferLen )
147+ if err != nil {
148+ return c .String (http .StatusBadRequest ,err .Error ())
149+ }
150+
151+ jobs = append (jobs ,* jL )
152+ }
153+
154+ // Return logs
155+ return c .JSON (http .StatusOK ,jobs )
156+ }
157+
158+ func getLogs (pipelineID ,pipelineRunID ,jobID string ,startPos ,maxBufferLen int ) (* jobLogs ,error ) {
98159// Lookup log file
99160logFilePath := filepath .Join (gaia .Cfg .WorkspacePath ,pipelineID ,pipelineRunID ,gaia .LogsFolderName ,jobID )
100161if _ ,err := os .Stat (logFilePath );os .IsNotExist (err ) {
101- return c . String ( http . StatusNotFound , errLogNotFound . Error ())
162+ return nil , err
102163}
103164
104165// Open file
105166file ,err := os .Open (logFilePath )
106167if err != nil {
107- return c . String ( http . StatusInternalServerError ,err . Error ())
168+ return nil ,err
108169}
109170defer file .Close ()
110171
111172// Read file
112173buf := make ([]byte ,maxBufferLen )
113174bytesRead ,err := file .ReadAt (buf ,int64 (startPos ))
114175if err != io .EOF && err != nil {
115- return c . String ( http . StatusInternalServerError ,err . Error ())
176+ return nil ,err
116177}
117178
118179// Create return struct
119- j := jobLogs {
180+ return & jobLogs {
120181Log :string (buf [:]),
121182StartPos :startPos + bytesRead ,
122- }
123-
124- // Return logs
125- return c .JSON (http .StatusOK ,j )
183+ },nil
126184}