Skip to content

Commit

Permalink
gateway/runservice: add api to delete step logs
Browse files Browse the repository at this point in the history
  • Loading branch information
camandel committed Oct 30, 2019
1 parent ec67b26 commit 13ca376
Show file tree
Hide file tree
Showing 6 changed files with 208 additions and 1 deletion.
30 changes: 29 additions & 1 deletion internal/services/gateway/action/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ const (
)

var (
SkipRunMessage = regexp.MustCompile(`.*\[ci skip\].*`)
SkipRunMessage = regexp.MustCompile(`.*\[ci skip\].*`)
)

func (h *ActionHandler) GetRun(ctx context.Context, runID string) (*rsapitypes.RunResponse, error) {
Expand Down Expand Up @@ -145,6 +145,34 @@ func (h *ActionHandler) GetLogs(ctx context.Context, req *GetLogsRequest) (*http
return resp, nil
}

type DeleteLogsRequest struct {
RunID string
TaskID string
Setup bool
Step int
}

func (h *ActionHandler) DeleteLogs(ctx context.Context, req *DeleteLogsRequest) error {
runResp, resp, err := h.runserviceClient.GetRun(ctx, req.RunID, nil)
if err != nil {
return ErrFromRemote(resp, err)
}
canGetRun, err := h.CanGetRun(ctx, runResp.RunConfig.Group)
if err != nil {
return errors.Errorf("failed to determine permissions: %w", err)
}
if !canGetRun {
return util.NewErrForbidden(errors.Errorf("user not authorized"))
}

resp, err = h.runserviceClient.DeleteLogs(ctx, req.RunID, req.TaskID, req.Setup, req.Step)
if err != nil {
return ErrFromRemote(resp, err)
}

return nil
}

type RunActionType string

const (
Expand Down
60 changes: 60 additions & 0 deletions internal/services/gateway/api/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -488,3 +488,63 @@ func sendLogs(w io.Writer, r io.Reader) error {
}
}
}

type LogsDeleteHandler struct {
log *zap.SugaredLogger
ah *action.ActionHandler
}

func NewLogsDeleteHandler(logger *zap.Logger, ah *action.ActionHandler) *LogsDeleteHandler {
return &LogsDeleteHandler{log: logger.Sugar(), ah: ah}
}

func (h *LogsDeleteHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()

q := r.URL.Query()

runID := q.Get("runID")
if runID == "" {
httpError(w, util.NewErrBadRequest(errors.Errorf("empty run id")))
return
}
taskID := q.Get("taskID")
if taskID == "" {
httpError(w, util.NewErrBadRequest(errors.Errorf("empty task id")))
return
}

_, setup := q["setup"]
stepStr := q.Get("step")
if !setup && stepStr == "" {
httpError(w, util.NewErrBadRequest(errors.Errorf("no setup or step number provided")))
return
}
if setup && stepStr != "" {
httpError(w, util.NewErrBadRequest(errors.Errorf("both setup and step number provided")))
return
}

var step int
if stepStr != "" {
var err error
step, err = strconv.Atoi(stepStr)
if err != nil {
httpError(w, util.NewErrBadRequest(errors.Errorf("cannot parse step number: %w", err)))
return
}
}

areq := &action.DeleteLogsRequest{
RunID: runID,
TaskID: taskID,
Setup: setup,
Step: step,
}

err := h.ah.DeleteLogs(ctx, areq)
if httpError(w, err) {
h.log.Errorf("err: %+v", err)
return
}
}
2 changes: 2 additions & 0 deletions internal/services/gateway/gateway.go
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@ func (g *Gateway) Run(ctx context.Context) error {
runTaskActionsHandler := api.NewRunTaskActionsHandler(logger, g.ah)

logsHandler := api.NewLogsHandler(logger, g.ah)
logsDeleteHandler := api.NewLogsDeleteHandler(logger, g.ah)

userRemoteReposHandler := api.NewUserRemoteReposHandler(logger, g.ah, g.configstoreClient)

Expand All @@ -235,6 +236,7 @@ func (g *Gateway) Run(ctx context.Context) error {
router.PathPrefix("/api/v1alpha").Handler(apirouter)

apirouter.Handle("/logs", authOptionalHandler(logsHandler)).Methods("GET")
apirouter.Handle("/logs", authForcedHandler(logsDeleteHandler)).Methods("DELETE")

//apirouter.Handle("/projectgroups", authForcedHandler(projectsHandler)).Methods("GET")
apirouter.Handle("/projectgroups/{projectgroupref}", authForcedHandler(projectGroupHandler)).Methods("GET")
Expand Down
102 changes: 102 additions & 0 deletions internal/services/runservice/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,108 @@ func sendLogs(w http.ResponseWriter, r io.Reader) error {
}
}

type LogsDeleteHandler struct {
log *zap.SugaredLogger
e *etcd.Store
ost *objectstorage.ObjStorage
dm *datamanager.DataManager
}

func NewLogsDeleteHandler(logger *zap.Logger, e *etcd.Store, ost *objectstorage.ObjStorage, dm *datamanager.DataManager) *LogsDeleteHandler {
return &LogsDeleteHandler{
log: logger.Sugar(),
e: e,
ost: ost,
dm: dm,
}
}

func (h *LogsDeleteHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()

q := r.URL.Query()

runID := q.Get("runid")
if runID == "" {
http.Error(w, "", http.StatusBadRequest)
return
}
taskID := q.Get("taskid")
if taskID == "" {
http.Error(w, "", http.StatusBadRequest)
return
}

_, setup := q["setup"]
stepStr := q.Get("step")
if !setup && stepStr == "" {
http.Error(w, "", http.StatusBadRequest)
return
}
if setup && stepStr != "" {
http.Error(w, "", http.StatusBadRequest)
return
}

var step int
if stepStr != "" {
var err error
step, err = strconv.Atoi(stepStr)
if err != nil {
http.Error(w, "", http.StatusBadRequest)
return
}
}

if err, deleteError := h.deleteTaskLogs(ctx, runID, taskID, setup, step, w); err != nil {
h.log.Errorf("err: %+v", err)
if deleteError {
switch err.(type) {
case common.ErrNotExist:
http.Error(w, err.Error(), http.StatusNotFound)
default:
http.Error(w, err.Error(), http.StatusInternalServerError)
}
}
}
}

func (h *LogsDeleteHandler) deleteTaskLogs(ctx context.Context, runID, taskID string, setup bool, step int, w http.ResponseWriter) (error, bool) {
r, err := store.GetRunEtcdOrOST(ctx, h.e, h.dm, runID)
if err != nil {
return err, true
}
if r == nil {
return errors.Errorf("no such run with id: %s", runID), true
}

task, ok := r.Tasks[taskID]
if !ok {
return errors.Errorf("no such task with ID %s in run %s", taskID, runID), true
}
if len(task.Steps) <= step {
return errors.Errorf("no such step for task %s in run %s", taskID, runID), true
}

if task.Steps[step].LogPhase == types.RunTaskFetchPhaseFinished {
var logPath string
if setup {
logPath = store.OSTRunTaskSetupLogPath(task.ID)
} else {
logPath = store.OSTRunTaskStepLogPath(task.ID, step)
}
err := h.ost.DeleteObject(logPath)
if err != nil {
if err == ostypes.ErrNotExist {
return common.NewErrNotExist(err), true
}
return err, true
}
return nil, false
}
return errors.Errorf("no logs on OST for for task %s in run %s", taskID, runID), true
}

type ChangeGroupsUpdateTokensHandler struct {
log *zap.SugaredLogger
readDB *readdb.ReadDB
Expand Down
2 changes: 2 additions & 0 deletions internal/services/runservice/runservice.go
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@ func (s *Runservice) setupDefaultRouter(etCh chan *types.ExecutorTask) http.Hand
executorDeleteHandler := api.NewExecutorDeleteHandler(logger, s.ah)

logsHandler := api.NewLogsHandler(logger, s.e, s.ost, s.dm)
logsDeleteHandler := api.NewLogsDeleteHandler(logger, s.e, s.ost, s.dm)

runHandler := api.NewRunHandler(logger, s.e, s.dm, s.readDB)
runTaskActionsHandler := api.NewRunTaskActionsHandler(logger, s.ah)
Expand Down Expand Up @@ -248,6 +249,7 @@ func (s *Runservice) setupDefaultRouter(etCh chan *types.ExecutorTask) http.Hand
apirouter.Handle("/executor/caches/{key}", cacheCreateHandler).Methods("POST")

apirouter.Handle("/logs", logsHandler).Methods("GET")
apirouter.Handle("/logs", logsDeleteHandler).Methods("DELETE")

apirouter.Handle("/runs/events", runEventsHandler).Methods("GET")
apirouter.Handle("/runs/{runid}", runHandler).Methods("GET")
Expand Down
13 changes: 13 additions & 0 deletions services/runservice/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,19 @@ func (c *Client) GetLogs(ctx context.Context, runID, taskID string, setup bool,
return c.getResponse(ctx, "GET", "/logs", q, -1, nil, nil)
}

func (c *Client) DeleteLogs(ctx context.Context, runID, taskID string, setup bool, step int) (*http.Response, error) {
q := url.Values{}
q.Add("runid", runID)
q.Add("taskid", taskID)
if setup {
q.Add("setup", "")
} else {
q.Add("step", strconv.Itoa(step))
}

return c.getResponse(ctx, "DELETE", "/logs", q, -1, nil, nil)
}

func (c *Client) GetRunEvents(ctx context.Context, startRunEventID string) (*http.Response, error) {
q := url.Values{}
q.Add("startruneventid", startRunEventID)
Expand Down

0 comments on commit 13ca376

Please sign in to comment.