diff --git a/presenter/access/html/handlers.go b/presenter/access/html/handlers.go
index 3a2b339..e68b311 100644
--- a/presenter/access/html/handlers.go
+++ b/presenter/access/html/handlers.go
@@ -40,7 +40,7 @@ func (h *handlers) ContainerIndex(c echo.Context) error {
func (h *handlers) VersionIndex(c echo.Context) error {
container := c.Param("container")
- versions, err := h.svc.ListVersions(c.Request().Context(), container)
+ versions, err := h.svc.ListPublishedVersions(c.Request().Context(), container)
if err != nil {
if err == service.ErrNotFound {
return c.Render(http.StatusNotFound, "404.html", nil)
diff --git a/presenter/access/html/handlers_test.go b/presenter/access/html/handlers_test.go
index 3573f63..9eb5e4e 100644
--- a/presenter/access/html/handlers_test.go
+++ b/presenter/access/html/handlers_test.go
@@ -20,7 +20,7 @@ func (s *handlersTestSuite) TestContainerIndex() {
}
func (s *handlersTestSuite) TestVersionIndex() {
- s.serviceMock.On("ListVersions", "test-container-1").Return([]string{"20241011121314"}, nil).Once()
+ s.serviceMock.On("ListPublishedVersions", "test-container-1").Return([]string{"20241011121314"}, nil).Once()
s.compareHTMLResponse(s.srv.URL+"/test-container-1/", "testdata/versions.html.sample")
}
@@ -51,7 +51,7 @@ func (s *handlersTestSuite) TestGetObject() {
}
func (s *handlersTestSuite) TestErrNotFound() {
- s.serviceMock.On("ListVersions", "test-container-1").Return([]string(nil), service.ErrNotFound).Once()
+ s.serviceMock.On("ListPublishedVersions", "test-container-1").Return([]string(nil), service.ErrNotFound).Once()
s.compareHTMLResponse(s.srv.URL+"/test-container-1/", "testdata/404.html.sample")
s.serviceMock.On("ListObjects", "test-container-1", "20240101010101").Return([]string(nil), service.ErrNotFound).Once()
@@ -65,7 +65,7 @@ func (s *handlersTestSuite) TestErrNotFound() {
}
func (s *handlersTestSuite) TestErr5xx() {
- s.serviceMock.On("ListVersions", "test-container-1").Panic("blah").Once()
+ s.serviceMock.On("ListPublishedVersions", "test-container-1").Panic("blah").Once()
s.compareHTMLResponse(s.srv.URL+"/test-container-1/", "testdata/5xx.html.sample")
}
diff --git a/service/mock.go b/service/mock.go
index b23c966..09e4b19 100644
--- a/service/mock.go
+++ b/service/mock.go
@@ -2,12 +2,14 @@ package service
import (
"context"
- "io"
"github.com/stretchr/testify/mock"
)
-var _ ManageService = (*Mock)(nil)
+var (
+ _ ManageService = (*Mock)(nil)
+ _ AccessService = (*Mock)(nil)
+)
type Mock struct {
mock.Mock
@@ -37,7 +39,12 @@ func (m *Mock) CreateVersion(_ context.Context, container string) (id string, er
return args.Get(0).(string), args.Error(1)
}
-func (m *Mock) ListVersions(_ context.Context, container string) ([]string, error) {
+func (m *Mock) ListAllVersions(_ context.Context, container string) ([]string, error) {
+ args := m.Called(container)
+ return args.Get(0).([]string), args.Error(1)
+}
+
+func (m *Mock) ListPublishedVersions(_ context.Context, container string) ([]string, error) {
args := m.Called(container)
return args.Get(0).([]string), args.Error(1)
}
@@ -52,16 +59,16 @@ func (m *Mock) DeleteVersion(_ context.Context, container, id string) error {
return args.Error(0)
}
-func (m *Mock) AddObject(_ context.Context, container, versionID, key string, objReader io.Reader) error {
- data, err := io.ReadAll(objReader)
- if err != nil {
- return err
- }
-
- args := m.Called(container, versionID, key, data)
+func (m *Mock) AddObject(_ context.Context, container, versionID, key, casKey string) error {
+ args := m.Called(container, versionID, key, casKey)
return args.Error(0)
}
+func (m *Mock) EnsureBLOBPresenceOrGetUploadURL(ctx context.Context, checksum string, size int64) (string, error) {
+ args := m.Called(checksum, size)
+ return args.String(0), args.Error(1)
+}
+
func (m *Mock) ListObjects(_ context.Context, container, versionID string) ([]string, error) {
args := m.Called(container, versionID)
return args.Get(0).([]string), args.Error(1)
diff --git a/service/service.go b/service/service.go
index 6daf48e..bfb0c5a 100644
--- a/service/service.go
+++ b/service/service.go
@@ -2,7 +2,6 @@ package service
import (
"context"
- "io"
"github.com/pkg/errors"
@@ -19,17 +18,20 @@ type ManageService interface {
DeleteContainer(ctx context.Context, name string) error
CreateVersion(ctx context.Context, container string) (id string, err error)
+ ListAllVersions(ctx context.Context, container string) ([]string, error)
PublishVersion(ctx context.Context, container, id string) error
DeleteVersion(ctx context.Context, container, id string) error
- AddObject(ctx context.Context, container, versionID, key string, objReader io.Reader) error
+ AddObject(ctx context.Context, container, versionID, key string, casKey string) error
DeleteObject(ctx context.Context, container, versionID, key string) error
+
+ EnsureBLOBPresenceOrGetUploadURL(ctx context.Context, checksum string, size int64) (string, error)
}
type AccessService interface {
ListContainers(ctx context.Context) ([]string, error)
- ListVersions(ctx context.Context, container string) ([]string, error)
+ ListPublishedVersions(ctx context.Context, container string) ([]string, error)
ListObjects(ctx context.Context, container, versionID string) ([]string, error)
GetObjectURL(ctx context.Context, container, versionID, key string) (string, error)
@@ -74,24 +76,31 @@ func (s *service) DeleteContainer(ctx context.Context, name string) error {
}
func (s *service) CreateVersion(ctx context.Context, container string) (id string, err error) {
- panic("not implemented")
+ version, err := s.mdRepo.CreateVersion(ctx, container)
+ return version, mapMetadataErrors(err)
}
-func (s *service) ListVersions(ctx context.Context, container string) ([]string, error) {
+func (s *service) ListPublishedVersions(ctx context.Context, container string) ([]string, error) {
versions, err := s.mdRepo.ListPublishedVersionsByContainer(ctx, container)
return versions, mapMetadataErrors(err)
}
+func (s *service) ListAllVersions(ctx context.Context, container string) ([]string, error) {
+ versions, err := s.mdRepo.ListAllVersionsByContainer(ctx, container)
+ return versions, mapMetadataErrors(err)
+}
+
func (s *service) PublishVersion(ctx context.Context, container, id string) error {
- panic("not implemented")
+ err := s.mdRepo.MarkVersionPublished(ctx, container, id)
+ return mapMetadataErrors(err)
}
func (s *service) DeleteVersion(ctx context.Context, container, id string) error {
panic("not implemented")
}
-func (s *service) AddObject(ctx context.Context, container, versionID, key string, objReader io.Reader) error {
- panic("not implemented")
+func (s *service) AddObject(ctx context.Context, container, versionID, key, casKey string) error {
+ return s.mdRepo.CreateObject(ctx, container, versionID, key, casKey)
}
func (s *service) ListObjects(ctx context.Context, container, versionID string) ([]string, error) {
@@ -108,6 +117,23 @@ func (s *service) GetObjectURL(ctx context.Context, container, versionID, key st
return s.blobRepo.GetBlobURL(ctx, key)
}
+func (s *service) EnsureBLOBPresenceOrGetUploadURL(ctx context.Context, checksum string, size int64) (string, error) {
+ err := s.mdRepo.EnsureBlobKey(ctx, checksum, uint64(size))
+ if err == nil {
+ return "", nil
+ }
+
+ if err == metadata.ErrNotFound {
+ url, err := s.blobRepo.PutBlobURL(ctx, checksum)
+ if err != nil {
+ return "", err
+ }
+ return url, s.mdRepo.CreateBLOB(ctx, checksum, uint64(size), "application/octet-stream")
+ }
+
+ return "", err
+}
+
func (s *service) DeleteObject(ctx context.Context, container, versionID, key string) error {
panic("not implemented")
}
diff --git a/service/service_test.go b/service/service_test.go
index d683325..be6245c 100644
--- a/service/service_test.go
+++ b/service/service_test.go
@@ -8,6 +8,7 @@ import (
"github.com/stretchr/testify/suite"
blobRepoMock "github.com/teran/archived/repositories/blob/mock"
+ "github.com/teran/archived/repositories/metadata"
mdRepoMock "github.com/teran/archived/repositories/metadata/mock"
)
@@ -34,15 +35,18 @@ func (s *serviceTestSuite) TestDeleteContainer() {
}
func (s *serviceTestSuite) TestCreateVersion() {
- s.Require().PanicsWithValue("not implemented", func() {
- s.svc.CreateVersion(s.ctx, "container")
- })
+ s.mdRepoMock.On("CreateVersion", "container").Return("versionID", nil).Once()
+
+ id, err := s.svc.CreateVersion(s.ctx, "container")
+ s.Require().NoError(err)
+ s.Require().Equal("versionID", id)
}
func (s *serviceTestSuite) TestPublishVersion() {
- s.Require().PanicsWithValue("not implemented", func() {
- s.svc.PublishVersion(s.ctx, "container", "version")
- })
+ s.mdRepoMock.On("MarkVersionPublished", "container", "version").Return(nil).Once()
+
+ err := s.svc.PublishVersion(s.ctx, "container", "version")
+ s.Require().NoError(err)
}
func (s *serviceTestSuite) TestDeleteVersion() {
@@ -52,9 +56,10 @@ func (s *serviceTestSuite) TestDeleteVersion() {
}
func (s *serviceTestSuite) TestAddObject() {
- s.Require().PanicsWithValue("not implemented", func() {
- s.svc.AddObject(s.ctx, "container", "versionID", "key", nil)
- })
+ s.mdRepoMock.On("CreateObject", "container", "versionID", "key", "cas_key").Return(nil).Once()
+
+ err := s.svc.AddObject(s.ctx, "container", "versionID", "key", "cas_key")
+ s.Require().NoError(err)
}
func (s *serviceTestSuite) TestDeleteObject() {
@@ -88,7 +93,7 @@ func (s *serviceTestSuite) TestListVersions() {
"version1", "version2",
}, nil).Once()
- versions, err := s.svc.ListVersions(s.ctx, "container")
+ versions, err := s.svc.ListPublishedVersions(s.ctx, "container")
s.Require().NoError(err)
s.Require().Equal([]string{
"version1", "version2",
@@ -125,6 +130,24 @@ func (s *serviceTestSuite) TestGetObjectURL() {
s.Require().Equal("url", url)
}
+func (s *serviceTestSuite) TestEnsureBLOBPresenceOrGetUploadURL() {
+ // Blob exists
+ s.mdRepoMock.On("EnsureBlobKey", "checksum", uint64(1234)).Return(nil).Once()
+
+ url, err := s.svc.EnsureBLOBPresenceOrGetUploadURL(s.ctx, "checksum", 1234)
+ s.Require().NoError(err)
+ s.Require().Equal("", url)
+
+ // Blob doesn't exist
+ s.mdRepoMock.On("EnsureBlobKey", "checksum", uint64(1234)).Return(metadata.ErrNotFound).Once()
+ s.blobRepoMock.On("PutBlobURL", "checksum").Return("https://example.com", nil).Once()
+ s.mdRepoMock.On("CreateBLOB", "checksum", uint64(1234), "application/octet-stream").Return(nil).Once()
+
+ url, err = s.svc.EnsureBLOBPresenceOrGetUploadURL(s.ctx, "checksum", 1234)
+ s.Require().NoError(err)
+ s.Require().Equal("https://example.com", url)
+}
+
// Definitions
type serviceTestSuite struct {
suite.Suite