mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
feat: return better error if file size is too big to upload (#7775)
* feat: return better error if file size is too big to upload * Use a limit writer to capture actual tar size
This commit is contained in:
@@ -8,6 +8,8 @@ import (
|
||||
"strings"
|
||||
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/coder/coder/coderd/util/xio"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -32,8 +34,9 @@ func dirHasExt(dir string, ext string) (bool, error) {
|
||||
|
||||
// Tar archives a Terraform directory.
|
||||
func Tar(w io.Writer, directory string, limit int64) error {
|
||||
// The total bytes written must be under the limit, so use -1
|
||||
w = xio.NewLimitWriter(w, limit-1)
|
||||
tarWriter := tar.NewWriter(w)
|
||||
totalSize := int64(0)
|
||||
|
||||
const tfExt = ".tf"
|
||||
hasTf, err := dirHasExt(directory, tfExt)
|
||||
@@ -95,22 +98,26 @@ func Tar(w io.Writer, directory string, limit int64) error {
|
||||
if !fileInfo.Mode().IsRegular() {
|
||||
return nil
|
||||
}
|
||||
|
||||
data, err := os.Open(file)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer data.Close()
|
||||
wrote, err := io.Copy(tarWriter, data)
|
||||
_, err = io.Copy(tarWriter, data)
|
||||
if err != nil {
|
||||
if xerrors.Is(err, xio.ErrLimitReached) {
|
||||
return xerrors.Errorf("Archive too big. Must be <= %d bytes", limit)
|
||||
}
|
||||
return err
|
||||
}
|
||||
totalSize += wrote
|
||||
if limit != 0 && totalSize >= limit {
|
||||
return xerrors.Errorf("Archive too big. Must be <= %d bytes", limit)
|
||||
}
|
||||
|
||||
return data.Close()
|
||||
})
|
||||
if err != nil {
|
||||
if xerrors.Is(err, xio.ErrLimitReached) {
|
||||
return xerrors.Errorf("Archive too big. Must be <= %d bytes", limit)
|
||||
}
|
||||
return err
|
||||
}
|
||||
err = tarWriter.Flush()
|
||||
|
||||
@@ -15,6 +15,32 @@ import (
|
||||
|
||||
func TestTar(t *testing.T) {
|
||||
t.Parallel()
|
||||
t.Run("HeaderBreakLimit", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
dir := t.TempDir()
|
||||
file, err := os.CreateTemp(dir, "*.tf")
|
||||
require.NoError(t, err)
|
||||
_ = file.Close()
|
||||
// A header is 512 bytes
|
||||
err = provisionersdk.Tar(io.Discard, dir, 100)
|
||||
require.Error(t, err)
|
||||
})
|
||||
t.Run("HeaderAndContent", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
dir := t.TempDir()
|
||||
file, err := os.CreateTemp(dir, "*.tf")
|
||||
require.NoError(t, err)
|
||||
_, _ = file.Write(make([]byte, 100))
|
||||
_ = file.Close()
|
||||
// Pay + header is 1024 bytes (padding)
|
||||
err = provisionersdk.Tar(io.Discard, dir, 1025)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Limit is 1 byte too small (n == limit is a failure, must be under)
|
||||
err = provisionersdk.Tar(io.Discard, dir, 1024)
|
||||
require.Error(t, err)
|
||||
})
|
||||
|
||||
t.Run("NoTF", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
dir := t.TempDir()
|
||||
@@ -97,7 +123,8 @@ func TestTar(t *testing.T) {
|
||||
}
|
||||
}
|
||||
archive := new(bytes.Buffer)
|
||||
err := provisionersdk.Tar(archive, dir, 1024)
|
||||
// Headers are chonky so raise the limit to something reasonable
|
||||
err := provisionersdk.Tar(archive, dir, 1024<<2)
|
||||
require.NoError(t, err)
|
||||
dir = t.TempDir()
|
||||
err = provisionersdk.Untar(dir, archive)
|
||||
|
||||
Reference in New Issue
Block a user