Skip to content

Commit 990dd33

Browse files
csweichelroboquat
authored andcommitted
[content-init] Propagate sensible error messages
when the content initializer fails
1 parent 0a47ea4 commit 990dd33

File tree

4 files changed

+32
-5
lines changed

4 files changed

+32
-5
lines changed

components/content-service/pkg/initializer/initializer.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ func NewFromRequest(ctx context.Context, loc string, rs storage.DirectDownloader
142142
initializer = &EmptyInitializer{}
143143
}
144144
if err != nil {
145-
return nil, status.Error(codes.Internal, fmt.Sprintf("cannot initialize workspace: %v", err))
145+
return nil, status.Error(codes.InvalidArgument, err.Error())
146146
}
147147
return initializer, nil
148148
}

components/ws-daemon/cmd/content-initializer/main.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
package main
66

77
import (
8+
"fmt"
89
"os"
910

1011
"github.com/gitpod-io/gitpod/common-go/log"
@@ -18,6 +19,9 @@ func main() {
1819

1920
err := content.RunInitializerChild()
2021
if err != nil {
22+
errfd := os.NewFile(uintptr(3), "errout")
23+
_, _ = fmt.Fprintf(errfd, err.Error())
24+
2125
os.Exit(42)
2226
}
2327
}

components/ws-daemon/pkg/content/initializer.go

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,14 @@ import (
99
"context"
1010
"encoding/json"
1111
"errors"
12+
"io/ioutil"
1213
"net/http"
1314
"os"
1415
"os/exec"
1516
"path/filepath"
1617
"strings"
1718
"syscall"
19+
"time"
1820

1921
"github.com/google/uuid"
2022
"github.com/opencontainers/runc/libcontainer/specconv"
@@ -237,22 +239,43 @@ func RunInitializer(ctx context.Context, destination string, initializer *csapi.
237239
name = "init-ws-" + opts.OWI.InstanceID
238240
}
239241

240-
args = append(args, "--log-format", "json", "run", name)
242+
args = append(args, "--log-format", "json", "run")
243+
args = append(args, "--preserve-fds", "1")
244+
args = append(args, name)
245+
246+
errIn, errOut, err := os.Pipe()
247+
if err != nil {
248+
return err
249+
}
250+
errch := make(chan []byte, 1)
251+
go func() {
252+
errmsg, _ := ioutil.ReadAll(errIn)
253+
errch <- errmsg
254+
}()
241255

242256
var cmdOut bytes.Buffer
243257
cmd := exec.Command("runc", args...)
244258
cmd.Dir = tmpdir
245259
cmd.Stdout = &cmdOut
246260
cmd.Stderr = os.Stderr
247261
cmd.Stdin = os.Stdin
262+
cmd.ExtraFiles = []*os.File{errOut}
248263
err = cmd.Run()
249264
log.FromBuffer(&cmdOut, log.WithFields(opts.OWI.Fields()))
265+
errOut.Close()
266+
267+
var errmsg []byte
268+
select {
269+
case errmsg = <-errch:
270+
case <-time.After(1 * time.Second):
271+
errmsg = []byte("failed to read content initializer response")
272+
}
250273
if err != nil {
251274
if exiterr, ok := err.(*exec.ExitError); ok {
252275
// The program has exited with an exit code != 0. If it's 42, it was deliberate.
253276
if status, ok := exiterr.Sys().(syscall.WaitStatus); ok && status.ExitStatus() == 42 {
254277
log.WithError(err).WithField("exitCode", status.ExitStatus()).WithField("args", args).Error("content init failed")
255-
return xerrors.Errorf("content initializer failed")
278+
return xerrors.Errorf(string(errmsg))
256279
}
257280
}
258281

components/ws-daemon/pkg/content/service.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -235,15 +235,15 @@ func (s *WorkspaceService) InitWorkspace(ctx context.Context, req *api.InitWorks
235235
err = RunInitializer(ctx, workspace.Location, req.Initializer, remoteContent, opts)
236236
if err != nil {
237237
log.WithError(err).WithField("workspaceId", req.Id).Error("cannot initialize workspace")
238-
return nil, status.Error(codes.Internal, fmt.Sprintf("cannot initialize workspace: %s", err.Error()))
238+
return nil, status.Error(codes.FailedPrecondition, err.Error())
239239
}
240240
}
241241

242242
// Tell the world we're done
243243
err = workspace.MarkInitDone(ctx)
244244
if err != nil {
245245
log.WithError(err).WithField("workspaceId", req.Id).Error("cannot initialize workspace")
246-
return nil, status.Error(codes.Internal, fmt.Sprintf("cannot finish workspace init: %v", err))
246+
return nil, status.Error(codes.FailedPrecondition, fmt.Sprintf("cannot finish workspace init: %v", err))
247247
}
248248

249249
return &api.InitWorkspaceResponse{}, nil

0 commit comments

Comments
 (0)