From 14a7205981f34f3d3638d540cfe91e07a084a0c3 Mon Sep 17 00:00:00 2001 From: Maximilian Pass <22845248+mpass99@users.noreply.github.com> Date: Wed, 21 Aug 2024 16:30:44 +0200 Subject: [PATCH] Catch List FS Link permission denied error --- internal/runner/nomad_runner.go | 14 +++++++++----- pkg/nullio/ls2json.go | 8 ++++++-- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/internal/runner/nomad_runner.go b/internal/runner/nomad_runner.go index 91b768e5..3946a6ac 100644 --- a/internal/runner/nomad_runner.go +++ b/internal/runner/nomad_runner.go @@ -166,21 +166,25 @@ func (r *NomadJob) ListFileSystem( } ls2json := &nullio.Ls2JsonWriter{Target: content, Ctx: ctx} - defer ls2json.Close() retrieveCommand := (&dto.ExecutionRequest{Command: fmt.Sprintf("%s %q", command, path)}).FullCommand() exitCode, err := r.api.ExecuteCommand(ctx, r.id, retrieveCommand, false, privilegedExecution, &nullio.Reader{Ctx: ctx}, ls2json, io.Discard) + writerErr := ls2json.Close() + switch { case ls2json.HasStartedWriting() && err == nil && exitCode == 0: // Successful. Nothing to do. + case ls2json.HasStartedWriting() && err == nil && errors.Is(writerErr, nullio.ErrLinkTargetPermissionDenied): + // Nothing to do. All available information has been returned. case ls2json.HasStartedWriting(): // if HasStartedWriting the status code of the response is already sent. // Therefore, we cannot notify CodeOcean about an error at this point anymore. - log.WithError(err).WithField("exitCode", exitCode).Warn("Ignoring error of listing the file system") + log.WithError(err).WithField("writerError", writerErr).WithField("exitCode", exitCode). + Warn("Ignoring error of listing the file system") err = nil - case err != nil: - err = fmt.Errorf("%w: nomad error during retrieve file headers: %w", - nomad.ErrExecutorCommunicationFailed, err) + case err != nil || writerErr != nil: + err = fmt.Errorf("%w: nomad error during retrieve file headers: %w, %w", + nomad.ErrExecutorCommunicationFailed, err, writerErr) case exitCode != 0: err = ErrFileNotFound case !ls2json.HasStartedWriting(): diff --git a/pkg/nullio/ls2json.go b/pkg/nullio/ls2json.go index 16c8ece2..b95c162a 100644 --- a/pkg/nullio/ls2json.go +++ b/pkg/nullio/ls2json.go @@ -4,6 +4,7 @@ import ( "bytes" "context" "encoding/json" + "errors" "fmt" "io" "regexp" @@ -20,6 +21,7 @@ var ( pathLineRegex = regexp.MustCompile(`(.*):$`) headerLineRegex = regexp. MustCompile(`([-aAbcCdDlMnpPsw?])([-rwxXsStT]{9})(\+?) +\d+ +(.+?) +(.+?) +(\d+) +(\d+) +(.*)$`) + ErrLinkTargetPermissionDenied = errors.New("permission denied for reading link target") ) const ( @@ -44,6 +46,7 @@ type Ls2JsonWriter struct { remaining []byte latestPath []byte sentrySpan *sentry.Span + err error } func (w *Ls2JsonWriter) HasStartedWriting() bool { @@ -101,7 +104,7 @@ func (w *Ls2JsonWriter) initializeJSONObject() (count int, err error) { return count, err } -func (w *Ls2JsonWriter) Close() { +func (w *Ls2JsonWriter) Close() error { if w.jsonStartSent { count, err := w.Target.Write([]byte("]}")) if count == 0 || err != nil { @@ -109,6 +112,7 @@ func (w *Ls2JsonWriter) Close() { } w.sentrySpan.Finish() } + return w.err } func (w *Ls2JsonWriter) writeLine(line []byte) (count int, err error) { @@ -169,7 +173,7 @@ func (w *Ls2JsonWriter) parseFileHeader(matches [][]byte) ([]byte, error) { linkTarget = dto.FilePath(parts[1]) case 1: // This case happens when a user tries to read the target of a link without permission. See #596. - // Nothing to do. The target remains empty. The name is set. + w.err = errors.Join(w.err, ErrLinkTargetPermissionDenied) default: log.WithContext(w.sentrySpan.Context()).WithField("name", name).Error("could not split link into name and target") }