Skip to content

Commit 9e753c2

Browse files
feat: add archive checksum
1 parent 4a386e5 commit 9e753c2

File tree

4 files changed

+34
-20
lines changed

4 files changed

+34
-20
lines changed

internal/batch/download.go

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -56,28 +56,30 @@ func downloadFileAndVerifyChecksum(ctx context.Context, tarWriter *tar.Writer, f
5656
return nil
5757
}
5858

59-
func DownloadFilesAndTarGz(ctx context.Context, batchResponse *registry.BatchResponse) (string, error) {
60-
tarFile, err := os.CreateTemp("", "plugin-archive-*.tar.gz")
59+
func DownloadFilesAndTarGz(ctx context.Context, batchResponse *registry.BatchResponse) (string, string, error) {
60+
tgzFile, err := os.CreateTemp("", "plugin-archive-*.tar.gz")
6161
if err != nil {
62-
return "", fmt.Errorf("failed to create temp file: %w", err)
62+
return "", "", fmt.Errorf("failed to create temp file: %w", err)
6363
}
64-
defer tarFile.Close()
65-
gzipWriter := gzip.NewWriter(tarFile)
64+
defer tgzFile.Close()
65+
66+
tgzHash := sha256.New()
67+
gzipWriter := gzip.NewWriter(io.MultiWriter(tgzFile, tgzHash))
6668
tarWriter := tar.NewWriter(gzipWriter)
6769
for _, plugin := range batchResponse.Plugins {
6870
fileName := fmt.Sprintf("%s_%s/%s/%s/%s", batchResponse.OS, batchResponse.Arch, plugin.FullName, plugin.Version, plugin.FileName)
6971
err = downloadFileAndVerifyChecksum(ctx, tarWriter, fileName, plugin.URL, plugin.Checksum)
7072
if err != nil {
71-
return "", fmt.Errorf("failed to add file to tar archive: %w", err)
73+
return "", "", fmt.Errorf("failed to add file to tar archive: %w", err)
7274
}
7375
}
7476
err = tarWriter.Close()
7577
if err != nil {
76-
return "", fmt.Errorf("failed to close tar writer: %w", err)
78+
return "", "", fmt.Errorf("failed to close tar writer: %w", err)
7779
}
7880
err = gzipWriter.Close()
7981
if err != nil {
80-
return "", fmt.Errorf("failed to close gzip writer: %w", err)
82+
return "", "", fmt.Errorf("failed to close gzip writer: %w", err)
8183
}
82-
return tarFile.Name(), nil
84+
return tgzFile.Name(), hex.EncodeToString(tgzHash.Sum(nil)), nil
8385
}

internal/batch/download_test.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import (
55
"bytes"
66
"compress/gzip"
77
"context"
8+
"crypto/sha256"
9+
"encoding/hex"
810
"fmt"
911
"io"
1012
"net/http"
@@ -74,14 +76,18 @@ func TestDownloadFilesAndTarGz(t *testing.T) {
7476
Plugins: plugins,
7577
}
7678

77-
tgzFileName, err := DownloadFilesAndTarGz(context.Background(), batchResponse)
79+
tgzFileName, tgzChecksum, err := DownloadFilesAndTarGz(context.Background(), batchResponse)
7880
require.NoError(t, err)
7981
require.NotEmpty(t, tgzFileName)
8082
defer os.Remove(tgzFileName)
8183

8284
tgzFile, err := os.ReadFile(tgzFileName)
8385
require.NoError(t, err)
8486

87+
tarHash := sha256.New()
88+
tarHash.Write(tgzFile)
89+
require.Equal(t, tgzChecksum, hex.EncodeToString(tarHash.Sum(nil)))
90+
8591
gzipReader, err := gzip.NewReader(bytes.NewReader(tgzFile))
8692
require.NoError(t, err)
8793
defer gzipReader.Close()

internal/server/handler_batch.go

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -107,13 +107,14 @@ func (s *Server) batchGetPlugins(w http.ResponseWriter, r *http.Request) {
107107
// the download url is deterministic, so we can set it here
108108
batchResponse.DownloadURL = s.config.GetPublicPluginCacheDownloadURL(archiveKey)
109109

110-
_, err = s.storage.HeadObject(r.Context(), &s3.HeadObjectInput{
110+
headRes, err := s.storage.HeadObject(r.Context(), &s3.HeadObjectInput{
111111
Bucket: s.config.GetBucket(),
112112
Key: &archiveKey,
113113
})
114114
if err == nil {
115115
// the archive already exists, return the response
116116
s.log.Infof("found cached archive %s", archiveKey)
117+
batchResponse.DownloadChecksum = headRes.Metadata["checksum"]
117118
s.setInCache(batchRequestCacheKey, batchResponse)
118119
s.writeJSON(w, batchResponse)
119120
return
@@ -126,13 +127,14 @@ func (s *Server) batchGetPlugins(w http.ResponseWriter, r *http.Request) {
126127
}
127128

128129
s.log.Infof("plugin archive %s not found, creating...", archiveKey)
129-
tarFileName, err := batch.DownloadFilesAndTarGz(r.Context(), batchResponse)
130+
tgzFileName, tgzChecksum, err := batch.DownloadFilesAndTarGz(r.Context(), batchResponse)
130131
if err != nil {
131132
s.writeJSONError(w, r, http.StatusInternalServerError, err, "could not create plugin archive")
132133
return
133134
}
134-
s.log.Infof("created plugin archive %s, uploading...", tarFileName)
135-
tarFile, err := os.Open(tarFileName)
135+
batchResponse.DownloadChecksum = tgzChecksum
136+
s.log.Infof("created plugin archive %s, uploading...", tgzFileName)
137+
tarFile, err := os.Open(tgzFileName)
136138
if err != nil {
137139
s.writeJSONError(w, r, http.StatusInternalServerError, err, "could not open plugin archive")
138140
return
@@ -143,6 +145,9 @@ func (s *Server) batchGetPlugins(w http.ResponseWriter, r *http.Request) {
143145
Key: &archiveKey,
144146
Body: tarFile,
145147
ContentType: aws.String("application/gzip"),
148+
Metadata: map[string]string{
149+
"checksum": tgzChecksum,
150+
},
146151
})
147152
if closeErr := tarFile.Close(); closeErr != nil {
148153
s.log.Errorf("could not close plugin archive file: %v", closeErr)
@@ -153,7 +158,7 @@ func (s *Server) batchGetPlugins(w http.ResponseWriter, r *http.Request) {
153158
}
154159

155160
s.log.Infof("uploaded plugin archive.")
156-
if rmErr := os.Remove(tarFileName); rmErr != nil {
161+
if rmErr := os.Remove(tgzFileName); rmErr != nil {
157162
s.log.Errorf("could not remove plugin archive file: %v", rmErr)
158163
}
159164

pkg/registry/registry.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -125,11 +125,12 @@ func (b BatchResponsePlugins) Has(fullName string) bool {
125125
}
126126

127127
type BatchResponse struct {
128-
OS string
129-
Arch string
130-
Plugins BatchResponsePlugins
131-
DownloadHash string
132-
DownloadURL string
128+
OS string
129+
Arch string
130+
Plugins BatchResponsePlugins
131+
DownloadHash string
132+
DownloadURL string
133+
DownloadChecksum string
133134
}
134135

135136
func NewBatchResponse(req *BatchRequest, plugins BatchResponsePlugins) *BatchResponse {

0 commit comments

Comments
 (0)