Skip to content

Commit

Permalink
[content-service] Implement UsageReportService.GetDownloadURL
Browse files Browse the repository at this point in the history
  • Loading branch information
easyCZ authored and roboquat committed Aug 26, 2022
1 parent 3037016 commit cf9e765
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 9 deletions.
60 changes: 52 additions & 8 deletions components/content-service/pkg/service/usage-report-service.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ package service

import (
"context"

"errors"
"github.com/opentracing/opentracing-go"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
Expand Down Expand Up @@ -42,20 +42,64 @@ func (us *UsageReportService) UploadURL(ctx context.Context, req *api.UsageRepor
span.SetTag("name", req.Name)
defer tracing.FinishSpan(span, &err)

err = us.s.EnsureExists(ctx, us.bucketName)
if req.GetName() == "" {
return nil, status.Error(codes.InvalidArgument, "Name is required but got empty.")
}

logger := log.WithField("name", req.Name).
WithField("bucket", us.bucketName)

err = us.ensureBucketExists(ctx)
if err != nil {
return nil, status.Error(codes.NotFound, err.Error())
return nil, err
}

info, err := us.s.SignUpload(ctx, us.bucketName, req.Name, &storage.SignedURLOptions{
ContentType: "application/json",
})
if err != nil {
log.WithField("name", req.Name).
WithField("bucket", us.bucketName).
WithError(err).
Error("Error getting UsageReport SignUpload URL")
return nil, status.Error(codes.Unknown, err.Error())
logger.WithError(err).Error("Error getting UsageReport SignUpload URL")
return nil, status.Error(codes.Internal, err.Error())
}
return &api.UsageReportUploadURLResponse{Url: info.URL}, nil
}

func (us *UsageReportService) DownloadURL(ctx context.Context, req *api.UsageReportDownloadURLRequest) (resp *api.UsageReportDownloadURLResponse, err error) {
span, ctx := opentracing.StartSpanFromContext(ctx, "UsageReport.DownloadURL")
span.SetTag("name", req.Name)
defer tracing.FinishSpan(span, &err)

if req.GetName() == "" {
return nil, status.Error(codes.InvalidArgument, "Name is required but got empty.")
}

err = us.ensureBucketExists(ctx)
if err != nil {
return nil, err
}

download, err := us.s.SignDownload(ctx, us.bucketName, req.GetName(), &storage.SignedURLOptions{
ContentType: "application/json",
})
if err != nil {
if errors.Is(err, storage.ErrNotFound) {
return nil, status.Errorf(codes.NotFound, "Object %s does not exist.", req.GetName())
}

return nil, status.Errorf(codes.Internal, "Failed to generate download URL for usage report: %s", err.Error())
}

return &api.UsageReportDownloadURLResponse{
Url: download.URL,
}, nil
}

func (us *UsageReportService) ensureBucketExists(ctx context.Context) error {
err := us.s.EnsureExists(ctx, us.bucketName)
if err != nil {
log.WithError(err).Errorf("Bucket %s does not exist", us.bucketName)
return status.Error(codes.Internal, err.Error())
}

return nil
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,24 @@ func TestUploadURL(t *testing.T) {
require.NoError(t, err)
require.Equal(t, "http://example.com/some-path", resp.Url)
}

func TestDownloadURL(t *testing.T) {
const (
fileName = "some-report-filename"
bucketName = "gitpod-usage-reports"
)

ctrl := gomock.NewController(t)
s := storagemock.NewMockPresignedAccess(ctrl)

s.EXPECT().EnsureExists(gomock.Any(), bucketName).
Return(nil)
s.EXPECT().SignDownload(gomock.Any(), bucketName, fileName, gomock.Any()).
Return(&storage.DownloadInfo{URL: "http://example.com/some-path"}, nil)

svc := &UsageReportService{cfg: config.StorageConfig{}, s: s, bucketName: bucketName}
resp, err := svc.DownloadURL(context.Background(), &api.UsageReportDownloadURLRequest{Name: fileName})

require.NoError(t, err)
require.Equal(t, "http://example.com/some-path", resp.Url)
}
2 changes: 1 addition & 1 deletion components/content-service/pkg/storage/storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ const (

var (
// ErrNotFound is returned when an object is not found
ErrNotFound = xerrors.Errorf("not found")
ErrNotFound = fmt.Errorf("not found")
)

// BucketNamer provides names for storage buckets
Expand Down

0 comments on commit cf9e765

Please sign in to comment.