diff options
| -rw-r--r-- | account.go | 2 | ||||
| -rw-r--r-- | bulk.go | 12 | ||||
| -rw-r--r-- | container_iterator.go | 2 | ||||
| -rw-r--r-- | download.go | 7 | ||||
| -rw-r--r-- | field_time.go | 4 | ||||
| -rw-r--r-- | field_uint64.go | 4 | ||||
| -rw-r--r-- | gopherschwift/package.go | 3 | ||||
| -rw-r--r-- | largeobject.go | 5 | ||||
| -rw-r--r-- | largeobject_test.go | 8 | ||||
| -rw-r--r-- | object.go | 42 | ||||
| -rw-r--r-- | object_iterator.go | 4 | ||||
| -rw-r--r-- | request.go | 5 | ||||
| -rw-r--r-- | tests/account_test.go | 1 | ||||
| -rw-r--r-- | tests/bulk_upload_test.go | 4 | ||||
| -rw-r--r-- | tests/container_test.go | 2 | ||||
| -rw-r--r-- | tests/field_test.go | 4 | ||||
| -rw-r--r-- | tests/largeobject_test.go | 6 | ||||
| -rw-r--r-- | tests/object_test.go | 4 | ||||
| -rw-r--r-- | tests/shared_test.go | 16 | ||||
| -rwxr-xr-x | util/render_template.go | 4 |
20 files changed, 66 insertions, 73 deletions
@@ -212,7 +212,7 @@ func (a *Account) Capabilities() (Capabilities, error) { func (a *Account) RawCapabilities() ([]byte, error) { //This method is the only one in Schwift that bypasses struct Request since //the request URL is not below the endpoint URL. - req, err := http.NewRequest("GET", a.baseURL+"info", nil) + req, err := http.NewRequest(http.MethodGet, a.baseURL+"info", http.NoBody) if err != nil { return nil, err } @@ -142,7 +142,7 @@ func makeBulkObjectError(fullName string, statusCode int) BulkObjectError { // The objects may be located in multiple containers, but they and the // containers must all be located in the given account. (Otherwise, // ErrAccountMismatch is returned.) -func (a *Account) BulkDelete(objects []*Object, containers []*Container, opts *RequestOptions) (numDeleted int, numNotFound int, deleteError error) { +func (a *Account) BulkDelete(objects []*Object, containers []*Container, opts *RequestOptions) (numDeleted, numNotFound int, deleteError error) { //validate that all given objects are in this account for _, obj := range objects { if !a.IsEqualTo(obj.Container().Account()) { @@ -202,12 +202,8 @@ func (a *Account) BulkDelete(objects []*Object, containers []*Container, opts *R // Implementation of BulkDelete() for servers that *do not* support bulk // deletion. -func (a *Account) bulkDeleteSingle(objects []*Object, containers []*Container, opts *RequestOptions) (int, int, error) { - var ( - numDeleted = 0 - numNotFound = 0 - errs []BulkObjectError - ) +func (a *Account) bulkDeleteSingle(objects []*Object, containers []*Container, opts *RequestOptions) (numDeleted, numNotFound int, err error) { + var errs []BulkObjectError handleSingleError := func(containerName, objectName string, err error) error { if err == nil { @@ -259,7 +255,7 @@ func (a *Account) bulkDeleteSingle(objects []*Object, containers []*Container, o // Implementation of BulkDelete() for servers that *do* support bulk deletion. // This function is called *after* chunking, so `len(names) <= // account.Capabilities.BulkDelete.MaximumDeletesPerRequest`. -func (a *Account) bulkDelete(names []string, opts *RequestOptions) (int, int, error) { +func (a *Account) bulkDelete(names []string, opts *RequestOptions) (numDeleted, numNotFound int, err error) { req := Request{ Method: "DELETE", Body: strings.NewReader(strings.Join(names, "\n") + "\n"), diff --git a/container_iterator.go b/container_iterator.go index 6dd75c2..71f799d 100644 --- a/container_iterator.go +++ b/container_iterator.go @@ -126,7 +126,7 @@ func (i *ContainerIterator) NextPageDetailed(limit int) ([]ContainerInfo, error) result[idx].LastModified, err = time.Parse(time.RFC3339Nano, data.LastModifiedStr+"Z") if err != nil { //this error is sufficiently obscure that we don't need to expose a type for it - return nil, fmt.Errorf("Bad field containers[%d].last_modified: %s", idx, err.Error()) + return nil, fmt.Errorf("bad field containers[%d].last_modified: %s", idx, err.Error()) } } diff --git a/download.go b/download.go index 130df91..8367f3d 100644 --- a/download.go +++ b/download.go @@ -20,7 +20,6 @@ package schwift import ( "io" - "io/ioutil" ) // DownloadedObject is returned by Object.Download(). It wraps the io.ReadCloser @@ -31,7 +30,7 @@ import ( // // //Do NOT do this! // reader, err := obj.Download(nil).AsReadCloser() -// bytes, err := ioutil.ReadAll(reader) +// bytes, err := io.ReadAll(reader) // err := reader.Close() // str := string(bytes) // @@ -66,12 +65,12 @@ func (o DownloadedObject) AsByteSlice() ([]byte, error) { if o.err != nil { return nil, o.err } - slice, err := ioutil.ReadAll(o.r) + slice, err := io.ReadAll(o.r) closeErr := o.r.Close() if err == nil { err = closeErr } - return slice, closeErr + return slice, err } // AsString collects the contents of this downloaded object into a string. diff --git a/field_time.go b/field_time.go index e5fe8cc..8c51f6b 100644 --- a/field_time.go +++ b/field_time.go @@ -162,9 +162,9 @@ func (f FieldUnixTimeReadonly) Exists() bool { // Get returns the value for this header, or the zero value if there is no value // (or if it is not a valid timestamp). func (f FieldUnixTimeReadonly) Get() time.Time { - return FieldUnixTime{f.h, f.k}.Get() + return FieldUnixTime(f).Get() } func (f FieldUnixTimeReadonly) validate() error { - return FieldUnixTime{f.h, f.k}.validate() + return FieldUnixTime(f).validate() } diff --git a/field_uint64.go b/field_uint64.go index d8e63a4..8e1a6c2 100644 --- a/field_uint64.go +++ b/field_uint64.go @@ -97,9 +97,9 @@ func (f FieldUint64Readonly) Exists() bool { // Get returns the value for this header, or 0 if there is no value (or if it is // not a valid uint64). func (f FieldUint64Readonly) Get() uint64 { - return FieldUint64{f.h, f.k}.Get() + return FieldUint64(f).Get() } func (f FieldUint64Readonly) validate() error { - return FieldUint64{f.h, f.k}.validate() + return FieldUint64(f).validate() } diff --git a/gopherschwift/package.go b/gopherschwift/package.go index adeee83..3c89074 100644 --- a/gopherschwift/package.go +++ b/gopherschwift/package.go @@ -41,7 +41,6 @@ package gopherschwift import ( "io" - "io/ioutil" "net/http" "github.com/gophercloud/gophercloud" @@ -107,7 +106,7 @@ func (g *backend) do(req *http.Request, afterReauth bool) (*http.Response, error //detect expired token if resp.StatusCode == http.StatusUnauthorized && !afterReauth { - _, err := io.Copy(ioutil.Discard, resp.Body) + _, err := io.Copy(io.Discard, resp.Body) if err != nil { return nil, err } diff --git a/largeobject.go b/largeobject.go index 637c024..83deddf 100644 --- a/largeobject.go +++ b/largeobject.go @@ -20,7 +20,7 @@ package schwift import ( "bytes" - "crypto/md5" + "crypto/md5" //nolint:gosec // Etag uses md5 "encoding/base64" "encoding/hex" "encoding/json" @@ -422,7 +422,6 @@ func (o *Object) AsNewLargeObject(sopts SegmentingOptions, topts *TruncateOption } case ErrNotLarge: //not an error, continue down below - err = nil default: return nil, err //unexpected error } @@ -686,7 +685,7 @@ func (lo *LargeObject) Append(contents io.Reader, segmentSizeBytes int64, opts * tracker := lengthAndEtagTrackingReader{ Reader: segment, - Hasher: md5.New(), + Hasher: md5.New(), //nolint:gosec // Etag uses md5 } obj := lo.NextSegmentObject() diff --git a/largeobject_test.go b/largeobject_test.go index 724654a..e5b790b 100644 --- a/largeobject_test.go +++ b/largeobject_test.go @@ -20,7 +20,7 @@ package schwift import ( "bytes" - "io/ioutil" + "io" "testing" ) @@ -89,7 +89,7 @@ func TestSegmentingReader(t *testing.T) { t.Errorf("expected segment %q, but NextSegment() returned nil", expected) break } - actual, err := ioutil.ReadAll(segment) + actual, err := io.ReadAll(segment) if err != nil { t.Errorf("expected segment %q, but got read error %q", expected, err.Error()) break @@ -101,8 +101,8 @@ func TestSegmentingReader(t *testing.T) { segment := sr.NextSegment() if segment != nil { - actual, err := ioutil.ReadAll(segment) - if err == nil { + actual, err := io.ReadAll(segment) + if err != nil { t.Errorf("expected no more segments, but got segment producing read error %q", err.Error()) } else { t.Errorf("expected no more segments, but got %q", string(actual)) @@ -21,8 +21,8 @@ package schwift import ( "bytes" "crypto/hmac" - "crypto/md5" - "crypto/sha1" + "crypto/md5" //nolint:gosec // Etag uses md5 + "crypto/sha1" //nolint:gosec // Used by swift "encoding/hex" "fmt" "hash" @@ -128,7 +128,7 @@ func (o *Object) fetchHeaders(opts *RequestOptions) (*ObjectHeaders, error) { Options: opts, //since Openstack LOVES to be inconsistent with everything (incl. itself), //this returns 200 instead of 204 - ExpectStatusCodes: []int{200}, + ExpectStatusCodes: []int{http.StatusOK}, DrainResponseBody: true, }.Do(o.c.a.backend) if err != nil { @@ -151,7 +151,7 @@ func (o *Object) Update(headers ObjectHeaders, opts *RequestOptions) error { ContainerName: o.c.name, ObjectName: o.name, Options: cloneRequestOptions(opts, headers.Headers), - ExpectStatusCodes: []int{202}, + ExpectStatusCodes: []int{http.StatusAccepted}, }.Do(o.c.a.backend) if err == nil { o.Invalidate() @@ -223,11 +223,14 @@ func (o *Object) Upload(content io.Reader, opts *UploadOptions, ropts *RequestOp var hasher hash.Hash if !isManifestUpload { - tryComputeEtag(content, hdr) + err := tryComputeEtag(content, hdr) + if err != nil { + return err + } //could not compute Etag in advance -> need to check on the fly if !hdr.Etag().Exists() { - hasher = md5.New() + hasher = md5.New() //nolint:gosec // Etag uses md5 if content != nil { content = io.TeeReader(content, hasher) } @@ -301,10 +304,11 @@ func tryComputeContentLength(content io.Reader) *uint64 { return nil } -func tryComputeEtag(content io.Reader, headers ObjectHeaders) { +//nolint:gosec // Etag uses md5 +func tryComputeEtag(content io.Reader, headers ObjectHeaders) error { h := headers.Etag() if h.Exists() { - return + return nil } switch r := content.(type) { case nil: @@ -318,11 +322,19 @@ func tryComputeEtag(content io.Reader, headers ObjectHeaders) { case io.ReadSeeker: //bytes.Reader does not have such a method, but it is an io.Seeker, so we //can read the entire thing and then seek back to where we started - hash := md5.New() - n, _ := io.Copy(hash, r) - r.Seek(-n, io.SeekCurrent) - h.Set(hex.EncodeToString(hash.Sum(nil))) + md5Hash := md5.New() + n, err := io.Copy(md5Hash, r) + if err != nil { + return err + } + _, err = r.Seek(-n, io.SeekCurrent) + if err != nil { + return err + } + h.Set(hex.EncodeToString(md5Hash.Sum(nil))) } + + return nil } // UploadFromWriter is a variant of Upload that can be used when the object's @@ -400,7 +412,7 @@ func (o *Object) Delete(opts *DeleteOptions, ropts *RequestOptions) error { ContainerName: o.c.name, ObjectName: o.name, Options: ropts, - ExpectStatusCodes: []int{204}, + ExpectStatusCodes: []int{http.StatusNoContent}, }.Do(o.c.a.backend) if err == nil { o.Invalidate() @@ -439,7 +451,7 @@ func (o *Object) Download(opts *RequestOptions) DownloadedObject { ContainerName: o.c.name, ObjectName: o.name, Options: opts, - ExpectStatusCodes: []int{200}, + ExpectStatusCodes: []int{http.StatusOK}, }.Do(o.c.a.backend) var body io.ReadCloser if err == nil { @@ -490,7 +502,7 @@ func (o *Object) CopyTo(target *Object, opts *CopyOptions, ropts *RequestOptions ContainerName: o.c.name, ObjectName: o.name, Options: ropts, - ExpectStatusCodes: []int{201}, + ExpectStatusCodes: []int{http.StatusCreated}, DrainResponseBody: true, }.Do(o.c.a.backend) if err == nil { diff --git a/object_iterator.go b/object_iterator.go index dcb8443..64b5551 100644 --- a/object_iterator.go +++ b/object_iterator.go @@ -155,13 +155,13 @@ func (i *ObjectIterator) NextPageDetailed(limit int) ([]ObjectInfo, error) { result[idx].LastModified, err = time.Parse(time.RFC3339Nano, data.LastModifiedStr+"Z") if err != nil { //this error is sufficiently obscure that we don't need to expose a type for it - return nil, fmt.Errorf("Bad field objects[%d].last_modified: %s", idx, err.Error()) + return nil, fmt.Errorf("bad field objects[%d].last_modified: %s", idx, err.Error()) } if data.SymlinkPath != "" { match := symlinkPathRx.FindStringSubmatch(data.SymlinkPath) if match == nil { //like above - return nil, fmt.Errorf("Bad field objects[%d].symlink_path: %q", idx, data.SymlinkPath) + return nil, fmt.Errorf("bad field objects[%d].symlink_path: %q", idx, data.SymlinkPath) } a := i.Container.a if a.Name() != match[1] { @@ -21,7 +21,6 @@ package schwift import ( "context" "io" - "io/ioutil" "net/http" "net/url" "strings" @@ -169,7 +168,7 @@ func (r Request) Do(backend Backend) (*http.Response, error) { } func drainResponseBody(r *http.Response) error { - _, err := io.Copy(ioutil.Discard, r.Body) + _, err := io.Copy(io.Discard, r.Body) if err != nil { return err } @@ -177,7 +176,7 @@ func drainResponseBody(r *http.Response) error { } func collectResponseBody(r *http.Response) ([]byte, error) { - buf, err := ioutil.ReadAll(r.Body) + buf, err := io.ReadAll(r.Body) if err != nil { return nil, err } diff --git a/tests/account_test.go b/tests/account_test.go index f5925f0..e4572ea 100644 --- a/tests/account_test.go +++ b/tests/account_test.go @@ -89,6 +89,5 @@ func TestAccountMetadata(t *testing.T) { } expectString(t, hdr.Metadata().Get("schwift-test1"), "") expectString(t, hdr.Metadata().Get("schwift-test2"), "changed") - }) } diff --git a/tests/bulk_upload_test.go b/tests/bulk_upload_test.go index 6cbae42..d810cf5 100644 --- a/tests/bulk_upload_test.go +++ b/tests/bulk_upload_test.go @@ -62,7 +62,7 @@ func TestBulkUploadArchiveError(t *testing.T) { ) expectInt(t, n, 0) expectError(t, err, "400 Bad Request: Invalid Tar File: truncated header") - bulkErr := err.(schwift.BulkError) + bulkErr := err.(schwift.BulkError) //nolint:errcheck expectInt(t, bulkErr.StatusCode, 400) expectString(t, bulkErr.OverallError, "Invalid Tar File: truncated header") expectInt(t, len(bulkErr.ObjectErrors), 0) @@ -87,7 +87,7 @@ func TestBulkUploadObjectError(t *testing.T) { ) expectInt(t, n, 1) expectError(t, err, "400 Bad Request (+1 object errors)") - bulkErr := err.(schwift.BulkError) + bulkErr := err.(schwift.BulkError) //nolint:errcheck expectInt(t, len(bulkErr.ObjectErrors), 1) expectString(t, bulkErr.ObjectErrors[0].ContainerName, c.Name()) expectInt(t, bulkErr.ObjectErrors[0].StatusCode, 400) diff --git a/tests/container_test.go b/tests/container_test.go index 0efc4e6..eed4906 100644 --- a/tests/container_test.go +++ b/tests/container_test.go @@ -63,7 +63,6 @@ func TestContainerLifecycle(t *testing.T) { func TestContainerUpdate(t *testing.T) { testWithContainer(t, func(c *schwift.Container) { - hdr, err := c.Headers() expectSuccess(t, err) expectBool(t, hdr.ObjectCount().Exists(), true) @@ -80,7 +79,6 @@ func TestContainerUpdate(t *testing.T) { expectSuccess(t, err) expectUint64(t, hdr.BytesUsedQuota().Get(), 42) expectUint64(t, hdr.ObjectCountQuota().Get(), 23) - }) } diff --git a/tests/field_test.go b/tests/field_test.go index c8dcf7f..cd27c99 100644 --- a/tests/field_test.go +++ b/tests/field_test.go @@ -70,7 +70,7 @@ func TestFieldTimestamp(t *testing.T) { expectBool(t, hdr.CreatedAt().Exists(), true) actual := float64(hdr.CreatedAt().Get().UnixNano()) / 1e9 - expected, _ := strconv.ParseFloat(hdr.Headers["X-Timestamp"], 64) + expected, _ := strconv.ParseFloat(hdr.Headers["X-Timestamp"], 64) //nolint:errcheck expectFloat64(t, actual, expected) }) @@ -100,7 +100,7 @@ func TestFieldHTTPTimestamp(t *testing.T) { expectBool(t, hdr.UpdatedAt().Exists(), true) actual := hdr.UpdatedAt().Get() - expected, _ := http.ParseTime(hdr.Get("Last-Modified")) + expected, _ := http.ParseTime(hdr.Get("Last-Modified")) //nolint:errcheck expectInt64(t, actual.Unix(), expected.Unix()) }) diff --git a/tests/largeobject_test.go b/tests/largeobject_test.go index b63ccd7..ed61033 100644 --- a/tests/largeobject_test.go +++ b/tests/largeobject_test.go @@ -37,7 +37,7 @@ func TestLargeObjectsBasic(t *testing.T) { testWithContainer(t, func(c *schwift.Container) { foreachLargeObjectStrategy(func(strategy schwift.LargeObjectStrategy, strategyStr string) { obj := c.Object(strategyStr + "-largeobject") - lo, err := obj.AsLargeObject() + _, err := obj.AsLargeObject() expectError(t, err, schwift.ErrNotLarge.Error()) segment1 := getRandomSegmentContent(128) @@ -46,7 +46,7 @@ func TestLargeObjectsBasic(t *testing.T) { segment4 := getRandomSegmentContent(128) //basic write example - lo, err = obj.AsNewLargeObject(schwift.SegmentingOptions{ + lo, err := obj.AsNewLargeObject(schwift.SegmentingOptions{ SegmentContainer: c, SegmentPrefix: strategyStr + "-segments/", Strategy: strategy, @@ -169,7 +169,6 @@ func TestLargeObjectExpiration(t *testing.T) { expectSuccess(t, err) objectExpiration = hdr.ExpiresAt().Get().Format("2006-01-02 15:04:05 +00:00 MST") expectString(t, objectExpiration, expirationTime.Format("2006-01-02 15:04:05 +00:00 MST")) - }) }) } @@ -210,7 +209,6 @@ func TestTruncateDuringOverwrite(t *testing.T) { expectObjectExistence(t, c.Object("segments/0000000000000001"), false) expectObjectExistence(t, c.Object("segments/0000000000000002"), false) - }) }) } diff --git a/tests/object_test.go b/tests/object_test.go index 1575a31..2f22b24 100644 --- a/tests/object_test.go +++ b/tests/object_test.go @@ -21,7 +21,6 @@ package tests import ( "bytes" "io" - "io/ioutil" "net/http" "strings" "testing" @@ -63,7 +62,6 @@ func TestObjectLifecycle(t *testing.T) { func TestObjectUpload(t *testing.T) { testWithContainer(t, func(c *schwift.Container) { - //test upload with bytes.Reader obj := c.Object("upload1") err := obj.Upload(bytes.NewReader(objectExampleContent), nil, nil) @@ -152,7 +150,7 @@ func TestObjectDownload(t *testing.T) { _, err = reader.Read(buf) expectSuccess(t, err) expectString(t, string(buf), string(objectExampleContent[4:8])) - buf, err = ioutil.ReadAll(reader) + buf, err = io.ReadAll(reader) expectSuccess(t, err) expectString(t, string(buf), string(objectExampleContent[8:])) }) diff --git a/tests/shared_test.go b/tests/shared_test.go index 54934ff..d6271a6 100644 --- a/tests/shared_test.go +++ b/tests/shared_test.go @@ -19,7 +19,7 @@ package tests import ( - "crypto/md5" + "crypto/md5" //nolint:gosec // Etag uses md5 "crypto/rand" "encoding/hex" "math" @@ -107,7 +107,7 @@ func testWithContainer(t *testing.T, testCode func(c *schwift.Container)) { //////////////////////////////////////////////////////////////////////////////// func etagOf(buf []byte) string { - hash := md5.Sum(buf) + hash := md5.Sum(buf) //nolint:gosec // Etag uses md5 return hex.EncodeToString(hash[:]) } @@ -124,7 +124,7 @@ func getRandomName() string { return hex.EncodeToString(buf[:]) } -func getRandomSegmentContent(length int) string { +func getRandomSegmentContent(length int) string { //nolint:unparam buf := make([]byte, length/2) _, err := rand.Read(buf) if err != nil { @@ -177,17 +177,13 @@ func expectString(t *testing.T, actual, expected string) { } } -func expectError(t *testing.T, actual error, expected string) (ok bool) { +func expectError(t *testing.T, actual error, expected string) { t.Helper() if actual == nil { t.Errorf("expected error %q, got no error\n", expected) - return false - } - if expected != actual.Error() { + } else if expected != actual.Error() { t.Errorf("expected error %q, got %q instead\n", expected, actual.Error()) - return false } - return true } func expectSuccess(t *testing.T, actual error) (ok bool) { @@ -199,7 +195,7 @@ func expectSuccess(t *testing.T, actual error) (ok bool) { return true } -func expectHeaders(t *testing.T, actual map[string]string, expected map[string]string) { +func expectHeaders(t *testing.T, actual, expected map[string]string) { t.Helper() reported := make(map[string]bool) diff --git a/util/render_template.go b/util/render_template.go index 2898623..03a4628 100755 --- a/util/render_template.go +++ b/util/render_template.go @@ -23,14 +23,14 @@ package main import ( "encoding/json" "fmt" - "io/ioutil" + "io" "os" "strings" "text/template" ) func main() { - input, err := ioutil.ReadAll(os.Stdin) + input, err := io.ReadAll(os.Stdin) failIfError(err) sections := strings.SplitN(string(input), "\n---\n", 2) |
