Path: blob/main/components/content-service/pkg/service/workspace-service.go
2499 views
// Copyright (c) 2021 Gitpod GmbH. All rights reserved.1// Licensed under the GNU Affero General Public License (AGPL).2// See License.AGPL.txt in the project root for license information.34package service56import (7"context"8"errors"9"strings"1011"github.com/opentracing/opentracing-go"12"google.golang.org/grpc/codes"13"google.golang.org/grpc/status"1415"github.com/gitpod-io/gitpod/common-go/log"16"github.com/gitpod-io/gitpod/common-go/tracing"17"github.com/gitpod-io/gitpod/content-service/api"18"github.com/gitpod-io/gitpod/content-service/api/config"19"github.com/gitpod-io/gitpod/content-service/pkg/storage"20)2122// WorkspaceService implements WorkspaceServiceServer23type WorkspaceService struct {24cfg config.StorageConfig25s storage.PresignedAccess2627api.UnimplementedWorkspaceServiceServer28}2930// NewWorkspaceService create a new content service31func NewWorkspaceService(cfg config.StorageConfig) (res *WorkspaceService, err error) {32s, err := storage.NewPresignedAccess(&cfg)33if err != nil {34return nil, err35}36return &WorkspaceService{cfg: cfg, s: s}, nil37}3839// WorkspaceDownloadURL provides a URL from where the content of a workspace can be downloaded from40func (cs *WorkspaceService) WorkspaceDownloadURL(ctx context.Context, req *api.WorkspaceDownloadURLRequest) (resp *api.WorkspaceDownloadURLResponse, err error) {41span, ctx := opentracing.StartSpanFromContext(ctx, "WorkspaceDownloadURL")42span.SetTag("user", req.OwnerId)43span.SetTag("workspaceId", req.WorkspaceId)44defer tracing.FinishSpan(span, &err)4546blobName := cs.s.BackupObject(req.OwnerId, req.WorkspaceId, storage.DefaultBackup)4748info, err := cs.s.SignDownload(ctx, cs.s.Bucket(req.OwnerId), blobName, &storage.SignedURLOptions{})49if err != nil {50log.WithFields(log.OWI(req.OwnerId, req.WorkspaceId, "")).51WithField("bucket", cs.s.Bucket(req.OwnerId)).52WithField("blobName", blobName).53WithError(err).54Error("error getting SignDownload URL")55if errors.Is(err, storage.ErrNotFound) {56return nil, status.Error(codes.NotFound, err.Error())57}58return nil, status.Error(codes.Unknown, err.Error())59}6061return &api.WorkspaceDownloadURLResponse{62Url: info.URL,63}, nil64}6566// DeleteWorkspace deletes the content of a single workspace67func (cs *WorkspaceService) DeleteWorkspace(ctx context.Context, req *api.DeleteWorkspaceRequest) (resp *api.DeleteWorkspaceResponse, err error) {68span, ctx := opentracing.StartSpanFromContext(ctx, "DeleteWorkspace")69span.SetTag("user", req.OwnerId)70span.SetTag("workspaceId", req.WorkspaceId)71span.SetTag("includeSnapshots", req.IncludeSnapshots)72defer tracing.FinishSpan(span, &err)7374if req.IncludeSnapshots {75prefix := cs.s.BackupObject(req.OwnerId, req.WorkspaceId, "")76if !strings.HasSuffix(prefix, "/") {77prefix = prefix + "/"78}79err = cs.s.DeleteObject(ctx, cs.s.Bucket(req.OwnerId), &storage.DeleteObjectQuery{Prefix: prefix})80if err != nil {81if errors.Is(err, storage.ErrNotFound) {82log.WithError(err).Debug("deleting workspace backup: NotFound")83return &api.DeleteWorkspaceResponse{}, nil84}85log.WithError(err).Error("error deleting workspace backup")86return nil, status.Error(codes.Unknown, err.Error())87}88return &api.DeleteWorkspaceResponse{}, nil89}9091blobName := cs.s.BackupObject(req.OwnerId, req.WorkspaceId, storage.DefaultBackup)92err = cs.s.DeleteObject(ctx, cs.s.Bucket(req.OwnerId), &storage.DeleteObjectQuery{Name: blobName})93if err != nil {94if errors.Is(err, storage.ErrNotFound) {95log.WithError(err).Debug("deleting workspace backup: NotFound, ", blobName)96return &api.DeleteWorkspaceResponse{}, nil97}98log.WithError(err).Error("error deleting workspace backup: ", blobName)99return nil, status.Error(codes.Unknown, err.Error())100}101102trailPrefix := cs.s.BackupObject(req.OwnerId, req.WorkspaceId, "trail-")103err = cs.s.DeleteObject(ctx, cs.s.Bucket(req.OwnerId), &storage.DeleteObjectQuery{Prefix: trailPrefix})104if err != nil {105if errors.Is(err, storage.ErrNotFound) {106log.WithError(err).Debug("deleting workspace backup: NotFound, ", trailPrefix)107return &api.DeleteWorkspaceResponse{}, nil108}109log.WithError(err).Error("error deleting workspace backup: ", trailPrefix)110return nil, status.Error(codes.Unknown, err.Error())111}112113return &api.DeleteWorkspaceResponse{}, nil114}115116func (cs *WorkspaceService) WorkspaceSnapshotExists(ctx context.Context, req *api.WorkspaceSnapshotExistsRequest) (resp *api.WorkspaceSnapshotExistsResponse, err error) {117span, ctx := opentracing.StartSpanFromContext(ctx, "WorkspaceObjectExists")118span.SetTag("user", req.OwnerId)119span.SetTag("workspaceId", req.WorkspaceId)120span.SetTag("filename", req.Filename)121defer tracing.FinishSpan(span, &err)122123exists, err := cs.s.ObjectExists(ctx, cs.s.Bucket(req.OwnerId), cs.s.BackupObject(req.OwnerId, req.WorkspaceId, req.Filename))124if err != nil {125return nil, status.Error(codes.Unknown, err.Error())126}127return &api.WorkspaceSnapshotExistsResponse{128Exists: exists,129}, nil130}131132133