mirror of
https://github.com/gomods/athens
synced 2026-02-03 07:30:32 +00:00
feat: GCP checksum (#2052)
This commit is contained in:
@@ -127,7 +127,7 @@ func TestListMerge(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
for _, v := range tc.strVersions {
|
for _, v := range tc.strVersions {
|
||||||
s.Save(ctx, testModName, v, bts, io.NopCloser(bytes.NewReader(bts)), bts)
|
s.Save(ctx, testModName, v, bts, io.NopCloser(bytes.NewReader(bts)), nil, bts)
|
||||||
}
|
}
|
||||||
defer clearStorage(s, testModName, tc.strVersions)
|
defer clearStorage(s, testModName, tc.strVersions)
|
||||||
dp := New(&Opts{s, nil, &listerMock{versions: tc.goVersions, err: tc.goErr}, nil, Strict})
|
dp := New(&Opts{s, nil, &listerMock{versions: tc.goVersions, err: tc.goErr}, nil, Strict})
|
||||||
|
|||||||
@@ -165,7 +165,7 @@ func TestListMode(t *testing.T) {
|
|||||||
networkMode: tc.networkmode,
|
networkMode: tc.networkmode,
|
||||||
}
|
}
|
||||||
for _, tag := range tc.storageTags {
|
for _, tag := range tc.storageTags {
|
||||||
err := strg.Save(ctx, tc.path, tag, []byte("mod"), bytes.NewReader([]byte("zip")), []byte("info"))
|
err := strg.Save(ctx, tc.path, tag, []byte("mod"), bytes.NewReader([]byte("zip")), nil, []byte("info"))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
@@ -429,7 +429,7 @@ func TestDownloadProtocolWhenFetchFails(t *testing.T) {
|
|||||||
}
|
}
|
||||||
fakeMod := testMod{"github.com/athens-artifacts/samplelib", "v1.0.0"}
|
fakeMod := testMod{"github.com/athens-artifacts/samplelib", "v1.0.0"}
|
||||||
bts := []byte(fakeMod.mod + "@" + fakeMod.ver)
|
bts := []byte(fakeMod.mod + "@" + fakeMod.ver)
|
||||||
err = s.Save(context.Background(), fakeMod.mod, fakeMod.ver, bts, io.NopCloser(bytes.NewReader(bts)), bts)
|
err = s.Save(context.Background(), fakeMod.mod, fakeMod.ver, bts, io.NopCloser(bytes.NewReader(bts)), nil, bts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -472,7 +472,7 @@ type mockStasher struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (ms *mockStasher) Stash(ctx context.Context, mod string, ver string) (string, error) {
|
func (ms *mockStasher) Stash(ctx context.Context, mod string, ver string) (string, error) {
|
||||||
err := ms.s.Save(ctx, mod, ver, []byte("mod"), strings.NewReader("zip"), []byte("info"))
|
err := ms.s.Save(ctx, mod, ver, []byte("mod"), strings.NewReader("zip"), nil, []byte("info"))
|
||||||
ms.ch <- true // signal async stashing is done
|
ms.ch <- true // signal async stashing is done
|
||||||
return ver, err
|
return ver, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,8 +3,10 @@ package module
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
|
"crypto/md5" //nolint:gosec
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@@ -96,6 +98,26 @@ func (g *goGetFetcher) Fetch(ctx context.Context, mod, ver string) (*storage.Ver
|
|||||||
}
|
}
|
||||||
storageVer.Mod = gomod
|
storageVer.Mod = gomod
|
||||||
|
|
||||||
|
zipMD5, err := func() ([]byte, error) {
|
||||||
|
// Perform in a separate function to ensure file is closed
|
||||||
|
zipForChecksum, err := g.fs.Open(m.Zip)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.E(op, err)
|
||||||
|
}
|
||||||
|
defer zipForChecksum.Close()
|
||||||
|
|
||||||
|
//nolint:gosec
|
||||||
|
hash := md5.New()
|
||||||
|
if _, err := io.Copy(hash, zipForChecksum); err != nil {
|
||||||
|
return nil, errors.E(op, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return hash.Sum(nil), nil
|
||||||
|
}()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
zip, err := g.fs.Open(m.Zip)
|
zip, err := g.fs.Open(m.Zip)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.E(op, err)
|
return nil, errors.E(op, err)
|
||||||
@@ -105,6 +127,7 @@ func (g *goGetFetcher) Fetch(ctx context.Context, mod, ver string) (*storage.Ver
|
|||||||
// if we close, then the caller will panic, and the alternative to make this work is
|
// if we close, then the caller will panic, and the alternative to make this work is
|
||||||
// that we read into memory and return an io.ReadCloser that reads out of memory
|
// that we read into memory and return an io.ReadCloser that reads out of memory
|
||||||
storageVer.Zip = &zipReadCloser{zip, g.fs, goPathRoot}
|
storageVer.Zip = &zipReadCloser{zip, g.fs, goPathRoot}
|
||||||
|
storageVer.ZipMD5 = zipMD5
|
||||||
|
|
||||||
return &storageVer, nil
|
return &storageVer, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ func (s *stasher) Stash(ctx context.Context, mod, ver string) (string, error) {
|
|||||||
return v.Semver, nil
|
return v.Semver, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
err = s.storage.Save(ctx, mod, v.Semver, v.Mod, v.Zip, v.Info)
|
err = s.storage.Save(ctx, mod, v.Semver, v.Mod, v.Zip, v.ZipMD5, v.Info)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", errors.E(op, err)
|
return "", errors.E(op, err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ type mockStorage struct {
|
|||||||
existsResponse bool
|
existsResponse bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ms *mockStorage) Save(ctx context.Context, module, version string, mod []byte, zip io.Reader, info []byte) error {
|
func (ms *mockStorage) Save(ctx context.Context, module, version string, mod []byte, zip io.Reader, zipMD5 []byte, info []byte) error {
|
||||||
ms.saveCalled = true
|
ms.saveCalled = true
|
||||||
ms.givenVersion = version
|
ms.givenVersion = version
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -73,6 +73,7 @@ func (ms *mockAzureBlobStasher) Stash(ctx context.Context, mod, ver string) (str
|
|||||||
ver,
|
ver,
|
||||||
[]byte("mod file"),
|
[]byte("mod file"),
|
||||||
strings.NewReader("zip file"),
|
strings.NewReader("zip file"),
|
||||||
|
nil,
|
||||||
[]byte("info file"),
|
[]byte("info file"),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -119,7 +119,7 @@ func TestWithGCSPartialFailure(t *testing.T) {
|
|||||||
}
|
}
|
||||||
s := gs(ms)
|
s := gs(ms)
|
||||||
// We simulate a failure by manually passing an io.Reader that will fail.
|
// We simulate a failure by manually passing an io.Reader that will fail.
|
||||||
err = ms.strg.Save(ctx, "stashmod", "v1.0.0", []byte(ms.content), fr, []byte(ms.content))
|
err = ms.strg.Save(ctx, "stashmod", "v1.0.0", []byte(ms.content), fr, nil, []byte(ms.content))
|
||||||
if err == nil {
|
if err == nil {
|
||||||
// We *want* to fail.
|
// We *want* to fail.
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@@ -172,6 +172,7 @@ func (ms *mockGCPStasher) Stash(ctx context.Context, mod, ver string) (string, e
|
|||||||
ver,
|
ver,
|
||||||
[]byte(ms.content),
|
[]byte(ms.content),
|
||||||
strings.NewReader(ms.content),
|
strings.NewReader(ms.content),
|
||||||
|
nil,
|
||||||
[]byte(ms.content),
|
[]byte(ms.content),
|
||||||
)
|
)
|
||||||
return "", err
|
return "", err
|
||||||
|
|||||||
@@ -210,6 +210,7 @@ func (ms *mockRedisStasher) Stash(ctx context.Context, mod, ver string) (string,
|
|||||||
ver,
|
ver,
|
||||||
[]byte("mod file"),
|
[]byte("mod file"),
|
||||||
strings.NewReader("zip file"),
|
strings.NewReader("zip file"),
|
||||||
|
nil,
|
||||||
[]byte("info file"),
|
[]byte("info file"),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Save implements the (./pkg/storage).Saver interface.
|
// Save implements the (./pkg/storage).Saver interface.
|
||||||
func (s *Storage) Save(ctx context.Context, module, version string, mod []byte, zip io.Reader, info []byte) error {
|
func (s *Storage) Save(ctx context.Context, module, version string, mod []byte, zip io.Reader, zipMD5, info []byte) error {
|
||||||
const op errors.Op = "azureblob.Save"
|
const op errors.Op = "azureblob.Save"
|
||||||
ctx, span := observ.StartSpan(ctx, op.String())
|
ctx, span := observ.StartSpan(ctx, op.String())
|
||||||
defer span.End()
|
defer span.End()
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ func benchList(b *testing.B, s storage.Backend, reset func() error) {
|
|||||||
version,
|
version,
|
||||||
mock.Mod,
|
mock.Mod,
|
||||||
mock.Zip,
|
mock.Zip,
|
||||||
|
mock.ZipMD5,
|
||||||
mock.Info,
|
mock.Info,
|
||||||
)
|
)
|
||||||
require.NoError(b, err, "save for storage failed")
|
require.NoError(b, err, "save for storage failed")
|
||||||
@@ -65,6 +66,7 @@ func benchSave(b *testing.B, s storage.Backend, reset func() error) {
|
|||||||
version,
|
version,
|
||||||
mock.Mod,
|
mock.Mod,
|
||||||
bytes.NewReader(zipBts),
|
bytes.NewReader(zipBts),
|
||||||
|
mock.ZipMD5,
|
||||||
mock.Info,
|
mock.Info,
|
||||||
)
|
)
|
||||||
require.NoError(b, err)
|
require.NoError(b, err)
|
||||||
@@ -87,7 +89,7 @@ func benchDelete(b *testing.B, s storage.Backend, reset func() error) {
|
|||||||
b.Run("delete", func(b *testing.B) {
|
b.Run("delete", func(b *testing.B) {
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
name := fmt.Sprintf("del-%s-%d", module, i)
|
name := fmt.Sprintf("del-%s-%d", module, i)
|
||||||
err := s.Save(ctx, name, version, mock.Mod, bytes.NewReader(zipBts), mock.Info)
|
err := s.Save(ctx, name, version, mock.Mod, bytes.NewReader(zipBts), mock.ZipMD5, mock.Info)
|
||||||
require.NoError(b, err, "saving %s for storage failed", name)
|
require.NoError(b, err, "saving %s for storage failed", name)
|
||||||
err = s.Delete(ctx, name, version)
|
err = s.Delete(ctx, name, version)
|
||||||
require.NoError(b, err, "delete failed: %s", name)
|
require.NoError(b, err, "delete failed: %s", name)
|
||||||
@@ -104,7 +106,7 @@ func benchExists(b *testing.B, s storage.Backend, reset func() error) {
|
|||||||
mock := getMockModule()
|
mock := getMockModule()
|
||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
err := s.Save(ctx, module, version, mock.Mod, mock.Zip, mock.Info)
|
err := s.Save(ctx, module, version, mock.Mod, mock.Zip, mock.ZipMD5, mock.Info)
|
||||||
require.NoError(b, err)
|
require.NoError(b, err)
|
||||||
|
|
||||||
b.Run("exists", func(b *testing.B) {
|
b.Run("exists", func(b *testing.B) {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package compliance
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
|
"crypto/md5"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
@@ -76,6 +77,7 @@ func testListSuffix(t *testing.T, b storage.Backend) {
|
|||||||
version,
|
version,
|
||||||
mock.Mod,
|
mock.Mod,
|
||||||
mock.Zip,
|
mock.Zip,
|
||||||
|
mock.ZipMD5,
|
||||||
mock.Info,
|
mock.Info,
|
||||||
)
|
)
|
||||||
require.NoError(t, err, "Save for storage failed")
|
require.NoError(t, err, "Save for storage failed")
|
||||||
@@ -114,6 +116,7 @@ func testList(t *testing.T, b storage.Backend) {
|
|||||||
version,
|
version,
|
||||||
mock.Mod,
|
mock.Mod,
|
||||||
mock.Zip,
|
mock.Zip,
|
||||||
|
mock.ZipMD5,
|
||||||
mock.Info,
|
mock.Info,
|
||||||
)
|
)
|
||||||
require.NoError(t, err, "Save for storage failed")
|
require.NoError(t, err, "Save for storage failed")
|
||||||
@@ -135,7 +138,7 @@ func testGet(t *testing.T, b storage.Backend) {
|
|||||||
ver := "v1.2.3"
|
ver := "v1.2.3"
|
||||||
mock := getMockModule()
|
mock := getMockModule()
|
||||||
zipBts, _ := io.ReadAll(mock.Zip)
|
zipBts, _ := io.ReadAll(mock.Zip)
|
||||||
b.Save(ctx, modname, ver, mock.Mod, bytes.NewReader(zipBts), mock.Info)
|
b.Save(ctx, modname, ver, mock.Mod, bytes.NewReader(zipBts), mock.ZipMD5, mock.Info)
|
||||||
defer b.Delete(ctx, modname, ver)
|
defer b.Delete(ctx, modname, ver)
|
||||||
|
|
||||||
info, err := b.Info(ctx, modname, ver)
|
info, err := b.Info(ctx, modname, ver)
|
||||||
@@ -160,7 +163,7 @@ func testExists(t *testing.T, b storage.Backend) {
|
|||||||
ver := "v1.2.3"
|
ver := "v1.2.3"
|
||||||
mock := getMockModule()
|
mock := getMockModule()
|
||||||
zipBts, _ := io.ReadAll(mock.Zip)
|
zipBts, _ := io.ReadAll(mock.Zip)
|
||||||
b.Save(ctx, modname, ver, mock.Mod, bytes.NewReader(zipBts), mock.Info)
|
b.Save(ctx, modname, ver, mock.Mod, bytes.NewReader(zipBts), mock.ZipMD5, mock.Info)
|
||||||
defer b.Delete(ctx, modname, ver)
|
defer b.Delete(ctx, modname, ver)
|
||||||
checker := storage.WithChecker(b)
|
checker := storage.WithChecker(b)
|
||||||
exists, err := checker.Exists(ctx, modname, ver)
|
exists, err := checker.Exists(ctx, modname, ver)
|
||||||
@@ -174,7 +177,7 @@ func testShouldNotExist(t *testing.T, b storage.Backend) {
|
|||||||
ver := "v1.2.3-pre.1"
|
ver := "v1.2.3-pre.1"
|
||||||
mock := getMockModule()
|
mock := getMockModule()
|
||||||
zipBts, _ := io.ReadAll(mock.Zip)
|
zipBts, _ := io.ReadAll(mock.Zip)
|
||||||
err := b.Save(ctx, mod, ver, mock.Mod, bytes.NewReader(zipBts), mock.Info)
|
err := b.Save(ctx, mod, ver, mock.Mod, bytes.NewReader(zipBts), mock.ZipMD5, mock.Info)
|
||||||
require.NoError(t, err, "should successfully safe a mock module")
|
require.NoError(t, err, "should successfully safe a mock module")
|
||||||
defer b.Delete(ctx, mod, ver)
|
defer b.Delete(ctx, mod, ver)
|
||||||
|
|
||||||
@@ -196,7 +199,7 @@ func testDelete(t *testing.T, b storage.Backend) {
|
|||||||
version := fmt.Sprintf("%s%d", "delete", rand.Int())
|
version := fmt.Sprintf("%s%d", "delete", rand.Int())
|
||||||
|
|
||||||
mock := getMockModule()
|
mock := getMockModule()
|
||||||
err := b.Save(ctx, modname, version, mock.Mod, mock.Zip, mock.Info)
|
err := b.Save(ctx, modname, version, mock.Mod, mock.Zip, mock.ZipMD5, mock.Info)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
err = b.Delete(ctx, modname, version)
|
err = b.Delete(ctx, modname, version)
|
||||||
@@ -209,8 +212,9 @@ func testDelete(t *testing.T, b storage.Backend) {
|
|||||||
|
|
||||||
func getMockModule() *storage.Version {
|
func getMockModule() *storage.Version {
|
||||||
return &storage.Version{
|
return &storage.Version{
|
||||||
Info: []byte("123"),
|
Info: []byte("123"),
|
||||||
Mod: []byte("456"),
|
Mod: []byte("456"),
|
||||||
Zip: io.NopCloser(bytes.NewReader([]byte("789"))),
|
Zip: io.NopCloser(bytes.NewReader([]byte("789"))),
|
||||||
|
ZipMD5: md5.New().Sum([]byte("789")),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+1
-1
@@ -81,7 +81,7 @@ func (s *service) Zip(ctx context.Context, mod, ver string) (storage.SizeReadClo
|
|||||||
return storage.NewSizer(body, size), nil
|
return storage.NewSizer(body, size), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *service) Save(ctx context.Context, mod, ver string, modFile []byte, zip io.Reader, info []byte) error {
|
func (s *service) Save(ctx context.Context, mod, ver string, modFile []byte, zip io.Reader, zipMD5, info []byte) error {
|
||||||
const op errors.Op = "external.Save"
|
const op errors.Op = "external.Save"
|
||||||
var err error
|
var err error
|
||||||
mod, err = module.EscapePath(mod)
|
mod, err = module.EscapePath(mod)
|
||||||
|
|||||||
Vendored
+1
-1
@@ -109,7 +109,7 @@ func NewServer(strg storage.Backend) http.Handler {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer func() { _ = modZ.Close() }()
|
defer func() { _ = modZ.Close() }()
|
||||||
err = strg.Save(r.Context(), params.Module, params.Version, modFile, modZ, info)
|
err = strg.Save(r.Context(), params.Module, params.Version, modFile, modZ, nil, info)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import (
|
|||||||
"github.com/spf13/afero"
|
"github.com/spf13/afero"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *storageImpl) Save(ctx context.Context, module, version string, mod []byte, zip io.Reader, info []byte) error {
|
func (s *storageImpl) Save(ctx context.Context, module, version string, mod []byte, zip io.Reader, zipMD5, info []byte) error {
|
||||||
const op errors.Op = "fs.Save"
|
const op errors.Op = "fs.Save"
|
||||||
_, span := observ.StartSpan(ctx, op.String())
|
_, span := observ.StartSpan(ctx, op.String())
|
||||||
defer span.End()
|
defer span.End()
|
||||||
|
|||||||
@@ -20,11 +20,11 @@ import (
|
|||||||
//
|
//
|
||||||
// Uploaded files are publicly accessible in the storage bucket as per
|
// Uploaded files are publicly accessible in the storage bucket as per
|
||||||
// an ACL rule.
|
// an ACL rule.
|
||||||
func (s *Storage) Save(ctx context.Context, module, version string, mod []byte, zip io.Reader, info []byte) error {
|
func (s *Storage) Save(ctx context.Context, module, version string, mod []byte, zip io.Reader, zipMD5, info []byte) error {
|
||||||
const op errors.Op = "gcp.save"
|
const op errors.Op = "gcp.save"
|
||||||
ctx, span := observ.StartSpan(ctx, op.String())
|
ctx, span := observ.StartSpan(ctx, op.String())
|
||||||
defer span.End()
|
defer span.End()
|
||||||
err := s.save(ctx, module, version, mod, zip, info)
|
err := s.save(ctx, module, version, mod, zip, zipMD5, info)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.E(op, err)
|
return errors.E(op, err)
|
||||||
}
|
}
|
||||||
@@ -37,26 +37,26 @@ func (s *Storage) SetStaleThreshold(threshold time.Duration) {
|
|||||||
s.staleThreshold = threshold
|
s.staleThreshold = threshold
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Storage) save(ctx context.Context, module, version string, mod []byte, zip io.Reader, info []byte) error {
|
func (s *Storage) save(ctx context.Context, module, version string, mod []byte, zip io.Reader, zipMD5, info []byte) error {
|
||||||
const op errors.Op = "gcp.save"
|
const op errors.Op = "gcp.save"
|
||||||
ctx, span := observ.StartSpan(ctx, op.String())
|
ctx, span := observ.StartSpan(ctx, op.String())
|
||||||
defer span.End()
|
defer span.End()
|
||||||
|
|
||||||
gomodPath := config.PackageVersionedName(module, version, "mod")
|
gomodPath := config.PackageVersionedName(module, version, "mod")
|
||||||
err := s.upload(ctx, gomodPath, bytes.NewReader(mod), false)
|
err := s.upload(ctx, gomodPath, bytes.NewReader(mod), nil, false)
|
||||||
// KindAlreadyExists means the file is uploaded (somewhere else) successfully.
|
// KindAlreadyExists means the file is uploaded (somewhere else) successfully.
|
||||||
if err != nil && !errors.Is(err, errors.KindAlreadyExists) {
|
if err != nil && !errors.Is(err, errors.KindAlreadyExists) {
|
||||||
return errors.E(op, err)
|
return errors.E(op, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
zipPath := config.PackageVersionedName(module, version, "zip")
|
zipPath := config.PackageVersionedName(module, version, "zip")
|
||||||
err = s.upload(ctx, zipPath, zip, true)
|
err = s.upload(ctx, zipPath, zip, zipMD5, true)
|
||||||
if err != nil && !errors.Is(err, errors.KindAlreadyExists) {
|
if err != nil && !errors.Is(err, errors.KindAlreadyExists) {
|
||||||
return errors.E(op, err)
|
return errors.E(op, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
infoPath := config.PackageVersionedName(module, version, "info")
|
infoPath := config.PackageVersionedName(module, version, "info")
|
||||||
err = s.upload(ctx, infoPath, bytes.NewReader(info), false)
|
err = s.upload(ctx, infoPath, bytes.NewReader(info), nil, false)
|
||||||
if err != nil && !errors.Is(err, errors.KindAlreadyExists) {
|
if err != nil && !errors.Is(err, errors.KindAlreadyExists) {
|
||||||
return errors.E(op, err)
|
return errors.E(op, err)
|
||||||
}
|
}
|
||||||
@@ -64,7 +64,7 @@ func (s *Storage) save(ctx context.Context, module, version string, mod []byte,
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Storage) upload(ctx context.Context, path string, stream io.Reader, checkBefore bool) error {
|
func (s *Storage) upload(ctx context.Context, path string, stream io.Reader, md5 []byte, checkBefore bool) error {
|
||||||
const op errors.Op = "gcp.upload"
|
const op errors.Op = "gcp.upload"
|
||||||
ctx, span := observ.StartSpan(ctx, op.String())
|
ctx, span := observ.StartSpan(ctx, op.String())
|
||||||
defer span.End()
|
defer span.End()
|
||||||
@@ -90,6 +90,10 @@ func (s *Storage) upload(ctx context.Context, path string, stream io.Reader, che
|
|||||||
DoesNotExist: true,
|
DoesNotExist: true,
|
||||||
}).NewWriter(cancelCtx)
|
}).NewWriter(cancelCtx)
|
||||||
|
|
||||||
|
if len(md5) > 0 {
|
||||||
|
wc.MD5 = md5
|
||||||
|
}
|
||||||
|
|
||||||
// NOTE: content type is auto detected on GCP side and ACL defaults to public
|
// NOTE: content type is auto detected on GCP side and ACL defaults to public
|
||||||
// Once we support private storage buckets this may need refactoring
|
// Once we support private storage buckets this may need refactoring
|
||||||
// unless there is a way to set the default perms in the project.
|
// unless there is a way to set the default perms in the project.
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import (
|
|||||||
minio "github.com/minio/minio-go/v6"
|
minio "github.com/minio/minio-go/v6"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *storageImpl) Save(ctx context.Context, module, vsn string, mod []byte, zip io.Reader, info []byte) error {
|
func (s *storageImpl) Save(ctx context.Context, module, vsn string, mod []byte, zip io.Reader, zipMD5, info []byte) error {
|
||||||
const op errors.Op = "storage.minio.Save"
|
const op errors.Op = "storage.minio.Save"
|
||||||
_, span := observ.StartSpan(ctx, op.String())
|
_, span := observ.StartSpan(ctx, op.String())
|
||||||
defer span.End()
|
defer span.End()
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ func TestQueryModuleVersionExists(t *testing.T) {
|
|||||||
backend := getStorage(t)
|
backend := getStorage(t)
|
||||||
|
|
||||||
zipBts, _ := io.ReadAll(mock.Zip)
|
zipBts, _ := io.ReadAll(mock.Zip)
|
||||||
backend.Save(ctx, modname, ver, mock.Mod, bytes.NewReader(zipBts), mock.Info)
|
backend.Save(ctx, modname, ver, mock.Mod, bytes.NewReader(zipBts), mock.ZipMD5, mock.Info)
|
||||||
defer backend.Delete(ctx, modname, ver)
|
defer backend.Delete(ctx, modname, ver)
|
||||||
|
|
||||||
info, err := query(ctx, backend, modname, ver)
|
info, err := query(ctx, backend, modname, ver)
|
||||||
@@ -80,7 +80,7 @@ func TestQueryKindNotFoundErrorCases(t *testing.T) {
|
|||||||
backend := getStorage(t)
|
backend := getStorage(t)
|
||||||
|
|
||||||
zipBts, _ := io.ReadAll(mock.Zip)
|
zipBts, _ := io.ReadAll(mock.Zip)
|
||||||
backend.Save(ctx, modname, ver, mock.Mod, bytes.NewReader(zipBts), mock.Info)
|
backend.Save(ctx, modname, ver, mock.Mod, bytes.NewReader(zipBts), nil, mock.Info)
|
||||||
defer backend.Delete(ctx, modname, ver)
|
defer backend.Delete(ctx, modname, ver)
|
||||||
|
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Save stores a module in mongo storage.
|
// Save stores a module in mongo storage.
|
||||||
func (s *ModuleStore) Save(ctx context.Context, module, version string, mod []byte, zip io.Reader, info []byte) error {
|
func (s *ModuleStore) Save(ctx context.Context, module, version string, mod []byte, zip io.Reader, zipMD5, info []byte) error {
|
||||||
const op errors.Op = "mongo.Save"
|
const op errors.Op = "mongo.Save"
|
||||||
ctx, span := observ.StartSpan(ctx, op.String())
|
ctx, span := observ.StartSpan(ctx, op.String())
|
||||||
defer span.End()
|
defer span.End()
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Save implements the (github.com/gomods/athens/pkg/storage).Saver interface.
|
// Save implements the (github.com/gomods/athens/pkg/storage).Saver interface.
|
||||||
func (s *Storage) Save(ctx context.Context, module, version string, mod []byte, zip io.Reader, info []byte) error {
|
func (s *Storage) Save(ctx context.Context, module, version string, mod []byte, zip io.Reader, zipMD5, info []byte) error {
|
||||||
const op errors.Op = "s3.Save"
|
const op errors.Op = "s3.Save"
|
||||||
ctx, span := observ.StartSpan(ctx, op.String())
|
ctx, span := observ.StartSpan(ctx, op.String())
|
||||||
defer span.End()
|
defer span.End()
|
||||||
|
|||||||
@@ -7,5 +7,9 @@ import (
|
|||||||
|
|
||||||
// Saver saves module metadata and its source to underlying storage.
|
// Saver saves module metadata and its source to underlying storage.
|
||||||
type Saver interface {
|
type Saver interface {
|
||||||
Save(ctx context.Context, module, version string, mod []byte, zip io.Reader, info []byte) error
|
// Save saves the module metadata and its source to the storage.
|
||||||
|
//
|
||||||
|
// The caller MAY call zipMD5 with a nil value if the checksum is not available.
|
||||||
|
// The storage implementation MAY use the zipMD5 to verify the integrity of the zip file.
|
||||||
|
Save(ctx context.Context, module, version string, mod []byte, zip io.Reader, zipMD5, info []byte) error
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import "io"
|
|||||||
type Version struct {
|
type Version struct {
|
||||||
Mod []byte
|
Mod []byte
|
||||||
Zip io.ReadCloser
|
Zip io.ReadCloser
|
||||||
|
ZipMD5 []byte
|
||||||
Info []byte
|
Info []byte
|
||||||
Semver string
|
Semver string
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user