mirror of
https://github.com/minio/minio.git
synced 2024-12-24 06:05:55 -05:00
Introduce staticcheck for stricter builds (#7035)
This commit is contained in:
parent
4ba77a916d
commit
df35d7db9d
32
Makefile
32
Makefile
@ -14,43 +14,32 @@ checks:
|
||||
|
||||
getdeps:
|
||||
@echo "Installing golint" && go get -u golang.org/x/lint/golint
|
||||
@echo "Installing gocyclo" && go get -u github.com/fzipp/gocyclo
|
||||
@echo "Installing deadcode" && go get -u github.com/remyoudompheng/go-misc/deadcode
|
||||
@echo "Installing staticcheck" && go get -u honnef.co/go/tools/...
|
||||
@echo "Installing misspell" && go get -u github.com/client9/misspell/cmd/misspell
|
||||
@echo "Installing ineffassign" && go get -u github.com/gordonklaus/ineffassign
|
||||
|
||||
crosscompile:
|
||||
@(env bash $(PWD)/buildscripts/cross-compile.sh)
|
||||
|
||||
verifiers: getdeps vet fmt lint cyclo deadcode spelling
|
||||
verifiers: getdeps vet fmt lint staticcheck spelling
|
||||
|
||||
vet:
|
||||
@echo "Running $@"
|
||||
@go tool vet cmd
|
||||
@go tool vet pkg
|
||||
@go vet github.com/minio/minio/...
|
||||
|
||||
fmt:
|
||||
@echo "Running $@"
|
||||
@gofmt -d cmd
|
||||
@gofmt -d pkg
|
||||
@gofmt -d cmd/
|
||||
@gofmt -d pkg/
|
||||
|
||||
lint:
|
||||
@echo "Running $@"
|
||||
@${GOPATH}/bin/golint -set_exit_status github.com/minio/minio/cmd...
|
||||
@${GOPATH}/bin/golint -set_exit_status github.com/minio/minio/pkg...
|
||||
@${GOPATH}/bin/golint -set_exit_status github.com/minio/minio/cmd/...
|
||||
@${GOPATH}/bin/golint -set_exit_status github.com/minio/minio/pkg/...
|
||||
|
||||
ineffassign:
|
||||
staticcheck:
|
||||
@echo "Running $@"
|
||||
@${GOPATH}/bin/ineffassign .
|
||||
|
||||
cyclo:
|
||||
@echo "Running $@"
|
||||
@${GOPATH}/bin/gocyclo -over 200 cmd
|
||||
@${GOPATH}/bin/gocyclo -over 200 pkg
|
||||
|
||||
deadcode:
|
||||
@echo "Running $@"
|
||||
@${GOPATH}/bin/deadcode -test $(shell go list ./...) || true
|
||||
@${GOPATH}/bin/staticcheck github.com/minio/minio/cmd/...
|
||||
@${GOPATH}/bin/staticcheck github.com/minio/minio/pkg/...
|
||||
|
||||
spelling:
|
||||
@${GOPATH}/bin/misspell -locale US -error `find cmd/`
|
||||
@ -105,6 +94,7 @@ install: build
|
||||
clean:
|
||||
@echo "Cleaning up all the generated files"
|
||||
@find . -name '*.test' | xargs rm -fv
|
||||
@find . -name '*~' | xargs rm -fv
|
||||
@rm -rvf minio
|
||||
@rm -rvf build
|
||||
@rm -rvf release
|
||||
|
@ -381,7 +381,6 @@ func (a adminAPIHandlers) PerfInfoHandler(w http.ResponseWriter, r *http.Request
|
||||
} else {
|
||||
writeErrorResponseJSON(w, errorCodes.ToAPIErr(ErrMethodNotAllowed), r.URL)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func newLockEntry(l lockRequesterInfo, resource, server string) *madmin.LockEntry {
|
||||
@ -437,12 +436,20 @@ func (a adminAPIHandlers) TopLocksHandler(w http.ResponseWriter, r *http.Request
|
||||
return
|
||||
}
|
||||
|
||||
// Method only allowed in XL mode.
|
||||
// Method only allowed in Distributed XL mode.
|
||||
if !globalIsDistXL {
|
||||
writeErrorResponseJSON(w, errorCodes.ToAPIErr(ErrMethodNotAllowed), r.URL)
|
||||
return
|
||||
}
|
||||
|
||||
// Authenticate request
|
||||
// Setting the region as empty so as the mc server info command is irrespective to the region.
|
||||
adminAPIErr := checkAdminRequestAuthType(ctx, r, "")
|
||||
if adminAPIErr != ErrNone {
|
||||
writeErrorResponseJSON(w, errorCodes.ToAPIErr(adminAPIErr), r.URL)
|
||||
return
|
||||
}
|
||||
|
||||
thisAddr, err := xnet.ParseHost(GetLocalPeer(globalEndpoints))
|
||||
if err != nil {
|
||||
writeErrorResponseJSON(w, toAdminAPIErr(ctx, err), r.URL)
|
||||
|
@ -29,7 +29,6 @@ import (
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/minio/minio/pkg/auth"
|
||||
@ -231,10 +230,9 @@ var (
|
||||
// adminXLTestBed - encapsulates subsystems that need to be setup for
|
||||
// admin-handler unit tests.
|
||||
type adminXLTestBed struct {
|
||||
configPath string
|
||||
xlDirs []string
|
||||
objLayer ObjectLayer
|
||||
router *mux.Router
|
||||
xlDirs []string
|
||||
objLayer ObjectLayer
|
||||
router *mux.Router
|
||||
}
|
||||
|
||||
// prepareAdminXLTestBed - helper function that setups a single-node
|
||||
@ -773,7 +771,7 @@ func TestSetConfigHandler(t *testing.T) {
|
||||
|
||||
rec := httptest.NewRecorder()
|
||||
adminTestBed.router.ServeHTTP(rec, req)
|
||||
respBody := string(rec.Body.Bytes())
|
||||
respBody := rec.Body.String()
|
||||
if rec.Code != http.StatusBadRequest ||
|
||||
!strings.Contains(respBody, "Configuration data provided exceeds the allowed maximum of") {
|
||||
t.Errorf("Got unexpected response code or body %d - %s", rec.Code, respBody)
|
||||
@ -792,7 +790,7 @@ func TestSetConfigHandler(t *testing.T) {
|
||||
|
||||
rec := httptest.NewRecorder()
|
||||
adminTestBed.router.ServeHTTP(rec, req)
|
||||
respBody := string(rec.Body.Bytes())
|
||||
respBody := rec.Body.String()
|
||||
if rec.Code != http.StatusBadRequest ||
|
||||
!strings.Contains(respBody, "JSON configuration provided is of incorrect format") {
|
||||
t.Errorf("Got unexpected response code or body %d - %s", rec.Code, respBody)
|
||||
@ -879,90 +877,3 @@ func TestToAdminAPIErrCode(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func mkHealStartReq(t *testing.T, bucket, prefix string,
|
||||
opts madmin.HealOpts) *http.Request {
|
||||
|
||||
body, err := json.Marshal(opts)
|
||||
if err != nil {
|
||||
t.Fatalf("Unable marshal heal opts")
|
||||
}
|
||||
|
||||
path := fmt.Sprintf("/minio/admin/v1/heal/%s", bucket)
|
||||
if bucket != "" && prefix != "" {
|
||||
path += "/" + prefix
|
||||
}
|
||||
|
||||
req, err := newTestRequest("POST", path,
|
||||
int64(len(body)), bytes.NewReader(body))
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to construct request - %v", err)
|
||||
}
|
||||
cred := globalServerConfig.GetCredential()
|
||||
err = signRequestV4(req, cred.AccessKey, cred.SecretKey)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to sign request - %v", err)
|
||||
}
|
||||
|
||||
return req
|
||||
}
|
||||
|
||||
func mkHealStatusReq(t *testing.T, bucket, prefix,
|
||||
clientToken string) *http.Request {
|
||||
|
||||
path := fmt.Sprintf("/minio/admin/v1/heal/%s", bucket)
|
||||
if bucket != "" && prefix != "" {
|
||||
path += "/" + prefix
|
||||
}
|
||||
path += fmt.Sprintf("?clientToken=%s", clientToken)
|
||||
|
||||
req, err := newTestRequest("POST", path, 0, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to construct request - %v", err)
|
||||
}
|
||||
cred := globalServerConfig.GetCredential()
|
||||
err = signRequestV4(req, cred.AccessKey, cred.SecretKey)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to sign request - %v", err)
|
||||
}
|
||||
|
||||
return req
|
||||
}
|
||||
|
||||
func collectHealResults(t *testing.T, adminTestBed *adminXLTestBed, bucket,
|
||||
prefix, clientToken string, timeLimitSecs int) madmin.HealTaskStatus {
|
||||
|
||||
var res, cur madmin.HealTaskStatus
|
||||
|
||||
// loop and fetch heal status. have a time-limit to loop over
|
||||
// all statuses.
|
||||
timeLimit := UTCNow().Add(time.Second * time.Duration(timeLimitSecs))
|
||||
for cur.Summary != healStoppedStatus && cur.Summary != healFinishedStatus {
|
||||
if UTCNow().After(timeLimit) {
|
||||
t.Fatalf("heal-status loop took too long - clientToken: %s", clientToken)
|
||||
}
|
||||
req := mkHealStatusReq(t, bucket, prefix, clientToken)
|
||||
rec := httptest.NewRecorder()
|
||||
adminTestBed.router.ServeHTTP(rec, req)
|
||||
if http.StatusOK != rec.Code {
|
||||
t.Errorf("Unexpected status code - got %d but expected %d",
|
||||
rec.Code, http.StatusOK)
|
||||
break
|
||||
}
|
||||
err := json.NewDecoder(rec.Body).Decode(&cur)
|
||||
if err != nil {
|
||||
t.Errorf("unable to unmarshal resp: %v", err)
|
||||
break
|
||||
}
|
||||
|
||||
// all results are accumulated into a slice
|
||||
// and returned to caller in the end
|
||||
allItems := append(res.Items, cur.Items...)
|
||||
res = cur
|
||||
res.Items = allItems
|
||||
|
||||
time.Sleep(time.Millisecond * 200)
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
@ -100,7 +100,6 @@ func runPutObjectPartBenchmark(b *testing.B, obj ObjectLayer, partSize int) {
|
||||
b.Fatal(err)
|
||||
}
|
||||
|
||||
md5hex := getMD5Hash(textData)
|
||||
sha256hex := ""
|
||||
|
||||
var textPartData []byte
|
||||
@ -117,7 +116,7 @@ func runPutObjectPartBenchmark(b *testing.B, obj ObjectLayer, partSize int) {
|
||||
} else {
|
||||
textPartData = textData[j*partSize:]
|
||||
}
|
||||
md5hex = getMD5Hash([]byte(textPartData))
|
||||
md5hex := getMD5Hash([]byte(textPartData))
|
||||
var partInfo PartInfo
|
||||
partInfo, err = obj.PutObjectPart(context.Background(), bucket, object, uploadID, j,
|
||||
mustGetPutObjReader(b, bytes.NewBuffer(textPartData), int64(len(textPartData)), md5hex, sha256hex), ObjectOptions{})
|
||||
@ -230,10 +229,8 @@ func getRandomByte() []byte {
|
||||
const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
// seeding the random number generator.
|
||||
rand.Seed(UTCNow().UnixNano())
|
||||
var b byte
|
||||
// pick a character randomly.
|
||||
b = letterBytes[rand.Intn(len(letterBytes))]
|
||||
return []byte{b}
|
||||
return []byte{letterBytes[rand.Intn(len(letterBytes))]}
|
||||
}
|
||||
|
||||
// picks a random byte and repeats it to size bytes.
|
||||
|
@ -146,7 +146,7 @@ func (b *streamingBitrotReader) ReadAt(buf []byte, offset int64) (int, error) {
|
||||
}
|
||||
b.h.Write(buf)
|
||||
|
||||
if bytes.Compare(b.h.Sum(nil), b.hashBytes) != 0 {
|
||||
if !bytes.Equal(b.h.Sum(nil), b.hashBytes) {
|
||||
err = hashMismatchError{hex.EncodeToString(b.hashBytes), hex.EncodeToString(b.h.Sum(nil))}
|
||||
logger.LogIf(context.Background(), err)
|
||||
return 0, err
|
||||
|
@ -95,12 +95,12 @@ func testGetBucketLocationHandler(obj ObjectLayer, instanceType, bucketName stri
|
||||
t.Errorf("Test %d: %s: Expected the response status to be `%d`, but instead found `%d`", i+1, instanceType, testCase.expectedRespStatus, rec.Code)
|
||||
}
|
||||
if !bytes.Equal(testCase.locationResponse, rec.Body.Bytes()) && testCase.shouldPass {
|
||||
t.Errorf("Test %d: %s: Expected the response to be `%s`, but instead found `%s`", i+1, instanceType, string(testCase.locationResponse), string(rec.Body.Bytes()))
|
||||
t.Errorf("Test %d: %s: Expected the response to be `%s`, but instead found `%s`", i+1, instanceType, string(testCase.locationResponse), rec.Body.String())
|
||||
}
|
||||
errorResponse := APIErrorResponse{}
|
||||
err = xml.Unmarshal(rec.Body.Bytes(), &errorResponse)
|
||||
if err != nil && !testCase.shouldPass {
|
||||
t.Fatalf("Test %d: %s: Unable to marshal response body %s", i+1, instanceType, string(rec.Body.Bytes()))
|
||||
t.Fatalf("Test %d: %s: Unable to marshal response body %s", i+1, instanceType, rec.Body.String())
|
||||
}
|
||||
if errorResponse.Resource != testCase.errorResponse.Resource {
|
||||
t.Errorf("Test %d: %s: Expected the error resource to be `%s`, but instead found `%s`", i+1, instanceType, testCase.errorResponse.Resource, errorResponse.Resource)
|
||||
@ -131,7 +131,7 @@ func testGetBucketLocationHandler(obj ObjectLayer, instanceType, bucketName stri
|
||||
errorResponse = APIErrorResponse{}
|
||||
err = xml.Unmarshal(recV2.Body.Bytes(), &errorResponse)
|
||||
if err != nil && !testCase.shouldPass {
|
||||
t.Fatalf("Test %d: %s: Unable to marshal response body %s", i+1, instanceType, string(recV2.Body.Bytes()))
|
||||
t.Fatalf("Test %d: %s: Unable to marshal response body %s", i+1, instanceType, recV2.Body.String())
|
||||
}
|
||||
if errorResponse.Resource != testCase.errorResponse.Resource {
|
||||
t.Errorf("Test %d: %s: Expected the error resource to be `%s`, but instead found `%s`", i+1, instanceType, testCase.errorResponse.Resource, errorResponse.Resource)
|
||||
|
@ -263,9 +263,6 @@ type serverConfigV7 struct {
|
||||
|
||||
// Notification queue configuration.
|
||||
Notify notifierV1 `json:"notify"`
|
||||
|
||||
// Read Write mutex.
|
||||
rwMutex *sync.RWMutex
|
||||
}
|
||||
|
||||
// serverConfigV8 server configuration version '8'. Adds NATS notifier
|
||||
@ -282,9 +279,6 @@ type serverConfigV8 struct {
|
||||
|
||||
// Notification queue configuration.
|
||||
Notify notifierV1 `json:"notify"`
|
||||
|
||||
// Read Write mutex.
|
||||
rwMutex *sync.RWMutex
|
||||
}
|
||||
|
||||
// serverConfigV9 server configuration version '9'. Adds PostgreSQL
|
||||
@ -301,9 +295,6 @@ type serverConfigV9 struct {
|
||||
|
||||
// Notification queue configuration.
|
||||
Notify notifierV1 `json:"notify"`
|
||||
|
||||
// Read Write mutex.
|
||||
rwMutex *sync.RWMutex
|
||||
}
|
||||
|
||||
type loggerV7 struct {
|
||||
|
@ -127,23 +127,18 @@ func (sys *ConfigSys) Init(objAPI ObjectLayer) error {
|
||||
// of the object layer.
|
||||
// - Write quorum not met when upgrading configuration
|
||||
// version is needed.
|
||||
retryTimerCh := newRetryTimerSimple(doneCh)
|
||||
for {
|
||||
select {
|
||||
case _ = <-retryTimerCh:
|
||||
err := initConfig(objAPI)
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), InsufficientReadQuorum{}.Error()) ||
|
||||
strings.Contains(err.Error(), InsufficientWriteQuorum{}.Error()) {
|
||||
logger.Info("Waiting for configuration to be initialized..")
|
||||
continue
|
||||
}
|
||||
return err
|
||||
for range newRetryTimerSimple(doneCh) {
|
||||
if err := initConfig(objAPI); err != nil {
|
||||
if strings.Contains(err.Error(), InsufficientReadQuorum{}.Error()) ||
|
||||
strings.Contains(err.Error(), InsufficientWriteQuorum{}.Error()) {
|
||||
logger.Info("Waiting for configuration to be initialized..")
|
||||
continue
|
||||
}
|
||||
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
break
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewConfigSys - creates new config system object.
|
||||
|
@ -1,167 +0,0 @@
|
||||
/*
|
||||
* Minio Cloud Storage, (C) 2018 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"github.com/minio/minio/pkg/madmin"
|
||||
"github.com/minio/minio/pkg/policy"
|
||||
)
|
||||
|
||||
type DummyObjectLayer struct{}
|
||||
|
||||
func (api *DummyObjectLayer) Shutdown(context.Context) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (api *DummyObjectLayer) StorageInfo(context.Context) (si StorageInfo) {
|
||||
return
|
||||
}
|
||||
|
||||
func (api *DummyObjectLayer) MakeBucketWithLocation(ctx context.Context, bucket string, location string) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (api *DummyObjectLayer) GetBucketInfo(ctx context.Context, bucket string) (bucketInfo BucketInfo, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (api *DummyObjectLayer) ListBuckets(ctx context.Context) (buckets []BucketInfo, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (api *DummyObjectLayer) DeleteBucket(ctx context.Context, bucket string) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (api *DummyObjectLayer) ListObjects(ctx context.Context, bucket, prefix, marker, delimiter string, maxKeys int) (result ListObjectsInfo, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (api *DummyObjectLayer) ListObjectsV2(ctx context.Context, bucket, prefix, continuationToken, delimiter string, maxKeys int, fetchOwner bool, startAfter string) (result ListObjectsV2Info, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (api *DummyObjectLayer) GetObjectNInfo(ctx context.Context, bucket, object string, rs *HTTPRangeSpec, h http.Header, lock LockType, opts ObjectOptions) (gr *GetObjectReader, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (api *DummyObjectLayer) GetObject(ctx context.Context, bucket, object string, startOffset int64, length int64, writer io.Writer, etag string, opts ObjectOptions) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (api *DummyObjectLayer) GetObjectInfo(ctx context.Context, bucket, object string, opts ObjectOptions) (objInfo ObjectInfo, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (api *DummyObjectLayer) PutObject(ctx context.Context, bucket, object string, data *PutObjReader, opts ObjectOptions) (objInfo ObjectInfo, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (api *DummyObjectLayer) CopyObject(ctx context.Context, srcBucket, srcObject, destBucket, destObject string, srcInfo ObjectInfo, srcOpts, dstOpts ObjectOptions) (objInfo ObjectInfo, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (api *DummyObjectLayer) DeleteObject(ctx context.Context, bucket, object string) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (api *DummyObjectLayer) ListMultipartUploads(ctx context.Context, bucket, prefix, keyMarker, uploadIDMarker, delimiter string, maxUploads int) (result ListMultipartsInfo, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (api *DummyObjectLayer) NewMultipartUpload(ctx context.Context, bucket, object string, opts ObjectOptions) (uploadID string, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (api *DummyObjectLayer) CopyObjectPart(ctx context.Context, srcBucket, srcObject, destBucket, destObject string, uploadID string, partID int, startOffset int64, length int64, srcInfo ObjectInfo, srcOpts, dstOpts ObjectOptions) (info PartInfo, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (api *DummyObjectLayer) PutObjectPart(ctx context.Context, bucket, object, uploadID string, partID int, data *PutObjReader, opts ObjectOptions) (info PartInfo, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (api *DummyObjectLayer) ListObjectParts(ctx context.Context, bucket, object, uploadID string, partNumberMarker int, maxParts int, opts ObjectOptions) (result ListPartsInfo, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (api *DummyObjectLayer) AbortMultipartUpload(ctx context.Context, bucket, object, uploadID string) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (api *DummyObjectLayer) CompleteMultipartUpload(ctx context.Context, bucket, object, uploadID string, uploadedParts []CompletePart, opts ObjectOptions) (objInfo ObjectInfo, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (api *DummyObjectLayer) ReloadFormat(ctx context.Context, dryRun bool) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (api *DummyObjectLayer) HealFormat(ctx context.Context, dryRun bool) (item madmin.HealResultItem, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (api *DummyObjectLayer) HealBucket(ctx context.Context, bucket string, dryRun, remove bool) (items madmin.HealResultItem, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (api *DummyObjectLayer) HealObject(ctx context.Context, bucket, object string, dryRun, remove bool) (item madmin.HealResultItem, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (api *DummyObjectLayer) ListBucketsHeal(ctx context.Context) (buckets []BucketInfo, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (api *DummyObjectLayer) ListObjectsHeal(ctx context.Context, bucket, prefix, marker, delimiter string, maxKeys int) (info ListObjectsInfo, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (api *DummyObjectLayer) SetBucketPolicy(context.Context, string, *policy.Policy) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (api *DummyObjectLayer) GetBucketPolicy(context.Context, string) (bucketPolicy *policy.Policy, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (api *DummyObjectLayer) RefreshBucketPolicy(context.Context, string) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (api *DummyObjectLayer) DeleteBucketPolicy(context.Context, string) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (api *DummyObjectLayer) IsNotificationSupported() (b bool) {
|
||||
return
|
||||
}
|
||||
func (api *DummyObjectLayer) IsListenBucketSupported() (b bool) {
|
||||
return
|
||||
}
|
||||
|
||||
func (api *DummyObjectLayer) IsEncryptionSupported() (b bool) {
|
||||
return
|
||||
}
|
||||
|
||||
func (api *DummyObjectLayer) IsCompressionSupported() (b bool) {
|
||||
return
|
||||
}
|
@ -742,7 +742,7 @@ func DecryptBlocksRequest(client io.Writer, r *http.Request, bucket, object stri
|
||||
return writer, encStartOffset, encLength, nil
|
||||
}
|
||||
|
||||
seqNumber, encStartOffset, encLength = getEncryptedMultipartsOffsetLength(startOffset, length, objInfo)
|
||||
_, encStartOffset, encLength = getEncryptedMultipartsOffsetLength(startOffset, length, objInfo)
|
||||
|
||||
var partStartIndex int
|
||||
var partStartOffset = startOffset
|
||||
|
@ -94,7 +94,7 @@ func NewEndpoint(arg string) (ep Endpoint, e error) {
|
||||
// - Scheme field must contain "http" or "https"
|
||||
// - All field should be empty except Host and Path.
|
||||
if !((u.Scheme == "http" || u.Scheme == "https") &&
|
||||
u.User == nil && u.Opaque == "" && u.ForceQuery == false && u.RawQuery == "" && u.Fragment == "") {
|
||||
u.User == nil && u.Opaque == "" && !u.ForceQuery && u.RawQuery == "" && u.Fragment == "") {
|
||||
return ep, fmt.Errorf("invalid URL endpoint format")
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,7 @@ import (
|
||||
humanize "github.com/dustin/go-humanize"
|
||||
)
|
||||
|
||||
func (d badDisk) ReadFile(volume string, path string, offset int64, buf []byte, verifier *BitrotVerifier) (n int64, err error) {
|
||||
func (a badDisk) ReadFile(volume string, path string, offset int64, buf []byte, verifier *BitrotVerifier) (n int64, err error) {
|
||||
return 0, errFaultyDisk
|
||||
}
|
||||
|
||||
|
@ -341,35 +341,35 @@ func formatFSFixDeploymentID(fsFormatPath string) error {
|
||||
doneCh := make(chan struct{})
|
||||
defer close(doneCh)
|
||||
|
||||
retryTimerCh := newRetryTimerSimple(doneCh)
|
||||
for {
|
||||
select {
|
||||
case <-retryTimerCh:
|
||||
var wlk *lock.LockedFile
|
||||
for range newRetryTimerSimple(doneCh) {
|
||||
wlk, err = lock.TryLockedOpenFile(fsFormatPath, os.O_RDWR, 0)
|
||||
if err == lock.ErrAlreadyLocked {
|
||||
// Lock already present, sleep and attempt again
|
||||
logger.Info("Another minio process(es) might be holding a lock to the file %s. Please kill that minio process(es) (elapsed %s)\n", fsFormatPath, getElapsedTime())
|
||||
continue
|
||||
}
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
|
||||
wlk, err := lock.TryLockedOpenFile(fsFormatPath, os.O_RDWR, 0)
|
||||
if err == lock.ErrAlreadyLocked {
|
||||
// Lock already present, sleep and attempt again
|
||||
if err = jsonLoad(wlk, format); err != nil {
|
||||
break
|
||||
}
|
||||
|
||||
logger.Info("Another minio process(es) might be holding a lock to the file %s. Please kill that minio process(es) (elapsed %s)\n", fsFormatPath, getElapsedTime())
|
||||
continue
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer wlk.Close()
|
||||
// Check if format needs to be updated
|
||||
if format.ID != "" {
|
||||
err = nil
|
||||
break
|
||||
}
|
||||
|
||||
err = jsonLoad(wlk, format)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Check if it needs to be updated
|
||||
if format.ID != "" {
|
||||
return nil
|
||||
}
|
||||
format.ID = mustGetUUID()
|
||||
return jsonSave(wlk, format)
|
||||
format.ID = mustGetUUID()
|
||||
if err = jsonSave(wlk, format); err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if wlk != nil {
|
||||
wlk.Close()
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
@ -522,7 +522,7 @@ func TestGetXLID(t *testing.T) {
|
||||
}
|
||||
|
||||
formats[2].ID = "bad-id"
|
||||
if id, err = formatXLGetDeploymentID(quorumFormat, formats); err != errCorruptedFormat {
|
||||
if _, err = formatXLGetDeploymentID(quorumFormat, formats); err != errCorruptedFormat {
|
||||
t.Fatal("Unexpected Success")
|
||||
}
|
||||
}
|
||||
|
@ -294,7 +294,7 @@ func fsOpenFile(ctx context.Context, readPath string, offset int64) (io.ReadClos
|
||||
|
||||
// Seek to the requested offset.
|
||||
if offset > 0 {
|
||||
_, err = fr.Seek(offset, os.SEEK_SET)
|
||||
_, err = fr.Seek(offset, io.SeekStart)
|
||||
if err != nil {
|
||||
logger.LogIf(ctx, err)
|
||||
return nil, 0, err
|
||||
|
@ -532,8 +532,7 @@ func (fs *FSObjects) GetObjectNInfo(ctx context.Context, bucket, object string,
|
||||
nsUnlocker()
|
||||
return nil, toObjectErr(err, bucket, object)
|
||||
}
|
||||
var reader io.Reader
|
||||
reader = io.LimitReader(readCloser, length)
|
||||
reader := io.LimitReader(readCloser, length)
|
||||
closeFn := func() {
|
||||
readCloser.Close()
|
||||
}
|
||||
|
@ -740,6 +740,9 @@ func (a *azureObjects) PutObject(ctx context.Context, bucket, object string, r *
|
||||
if data.Size() < azureBlockSize/10 {
|
||||
blob := a.client.GetContainerReference(bucket).GetBlobReference(object)
|
||||
blob.Metadata, blob.Properties, err = s3MetaToAzureProperties(ctx, opts.UserDefined)
|
||||
if err != nil {
|
||||
return objInfo, azureToObjectError(err, bucket, object)
|
||||
}
|
||||
if err = blob.CreateBlockBlobFromReader(data, nil); err != nil {
|
||||
return objInfo, azureToObjectError(err, bucket, object)
|
||||
}
|
||||
|
@ -888,6 +888,7 @@ func (l *gcsGateway) PutObject(ctx context.Context, bucket string, key string, r
|
||||
object := l.client.Bucket(bucket).Object(key)
|
||||
|
||||
w := object.NewWriter(ctx)
|
||||
|
||||
// Disable "chunked" uploading in GCS client if the size of the data to be uploaded is below
|
||||
// the current chunk-size of the writer. This avoids an unnecessary memory allocation.
|
||||
if data.Size() < int64(w.ChunkSize) {
|
||||
|
@ -111,9 +111,8 @@ func TestOSSToObjectError(t *testing.T) {
|
||||
|
||||
func TestS3MetaToOSSOptions(t *testing.T) {
|
||||
var err error
|
||||
var headers map[string]string
|
||||
|
||||
headers = map[string]string{
|
||||
headers := map[string]string{
|
||||
"x-amz-meta-invalid_meta": "value",
|
||||
}
|
||||
_, err = appendS3MetaToOSSOptions(context.Background(), nil, headers)
|
||||
|
@ -367,11 +367,9 @@ func getResource(path string, host string, domain string) (string, error) {
|
||||
// If none of the http routes match respond with MethodNotAllowed, in JSON
|
||||
func notFoundHandlerJSON(w http.ResponseWriter, r *http.Request) {
|
||||
writeErrorResponseJSON(w, errorCodes.ToAPIErr(ErrMethodNotAllowed), r.URL)
|
||||
return
|
||||
}
|
||||
|
||||
// If none of the http routes match respond with MethodNotAllowed
|
||||
func notFoundHandler(w http.ResponseWriter, r *http.Request) {
|
||||
writeErrorResponse(w, errorCodes.ToAPIErr(ErrMethodNotAllowed), r.URL, guessIsBrowserReq(r))
|
||||
return
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ func TestGoroutineCountCheck(t *testing.T) {
|
||||
// Make goroutines -- to make sure number of go-routines is higher than threshold
|
||||
if tt.threshold == 5 || tt.threshold == 6 {
|
||||
for i := 0; i < 6; i++ {
|
||||
go time.Sleep(5)
|
||||
go time.Sleep(5 * time.Nanosecond)
|
||||
}
|
||||
}
|
||||
if err := goroutineCountCheck(tt.threshold); (err != nil) != tt.wantErr {
|
||||
|
@ -19,16 +19,8 @@ package http
|
||||
import (
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var b512pool = sync.Pool{
|
||||
New: func() interface{} {
|
||||
buf := make([]byte, 512)
|
||||
return &buf
|
||||
},
|
||||
}
|
||||
|
||||
// DrainBody close non nil response with any response Body.
|
||||
// convenient wrapper to drain any remaining data on response body.
|
||||
//
|
||||
|
25
cmd/iam.go
25
cmd/iam.go
@ -94,23 +94,20 @@ func (sys *IAMSys) Init(objAPI ObjectLayer) error {
|
||||
// the following reasons:
|
||||
// - Read quorum is lost just after the initialization
|
||||
// of the object layer.
|
||||
retryTimerCh := newRetryTimerSimple(doneCh)
|
||||
for {
|
||||
select {
|
||||
case _ = <-retryTimerCh:
|
||||
// Load IAMSys once during boot.
|
||||
if err := sys.refresh(objAPI); err != nil {
|
||||
if err == errDiskNotFound ||
|
||||
strings.Contains(err.Error(), InsufficientReadQuorum{}.Error()) ||
|
||||
strings.Contains(err.Error(), InsufficientWriteQuorum{}.Error()) {
|
||||
logger.Info("Waiting for IAM subsystem to be initialized..")
|
||||
continue
|
||||
}
|
||||
return err
|
||||
for range newRetryTimerSimple(doneCh) {
|
||||
// Load IAMSys once during boot.
|
||||
if err := sys.refresh(objAPI); err != nil {
|
||||
if err == errDiskNotFound ||
|
||||
strings.Contains(err.Error(), InsufficientReadQuorum{}.Error()) ||
|
||||
strings.Contains(err.Error(), InsufficientWriteQuorum{}.Error()) {
|
||||
logger.Info("Waiting for IAM subsystem to be initialized..")
|
||||
continue
|
||||
}
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
break
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeleteCannedPolicy - deletes a canned policy.
|
||||
|
@ -145,11 +145,9 @@ func (l *localLocker) ForceUnlock(args dsync.LockArgs) (reply bool, err error) {
|
||||
if len(args.UID) != 0 {
|
||||
return false, fmt.Errorf("ForceUnlock called with non-empty UID: %s", args.UID)
|
||||
}
|
||||
if _, ok := l.lockMap[args.Resource]; ok {
|
||||
// Only clear lock when it is taken
|
||||
// Remove the lock (irrespective of write or read lock)
|
||||
delete(l.lockMap, args.Resource)
|
||||
}
|
||||
// Only clear lock when it is taken
|
||||
// Remove the lock (irrespective of write or read lock)
|
||||
delete(l.lockMap, args.Resource)
|
||||
return true, nil
|
||||
}
|
||||
|
||||
@ -159,11 +157,7 @@ func (l *localLocker) DupLockMap() map[string][]lockRequesterInfo {
|
||||
|
||||
lockCopy := make(map[string][]lockRequesterInfo)
|
||||
for k, v := range l.lockMap {
|
||||
var lockSlice []lockRequesterInfo
|
||||
for _, lockInfo := range v {
|
||||
lockSlice = append(lockSlice, lockInfo)
|
||||
}
|
||||
lockCopy[k] = lockSlice
|
||||
lockCopy[k] = append(lockCopy[k], v...)
|
||||
}
|
||||
return lockCopy
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ func TestLockRpcServerRemoveEntryIfExists(t *testing.T) {
|
||||
// first test by simulating item has already been deleted
|
||||
locker.ll.removeEntryIfExists(nlrip)
|
||||
{
|
||||
gotLri, _ := locker.ll.lockMap["name"]
|
||||
gotLri := locker.ll.lockMap["name"]
|
||||
expectedLri := []lockRequesterInfo(nil)
|
||||
if !reflect.DeepEqual(expectedLri, gotLri) {
|
||||
t.Errorf("Expected %#v, got %#v", expectedLri, gotLri)
|
||||
@ -52,7 +52,7 @@ func TestLockRpcServerRemoveEntryIfExists(t *testing.T) {
|
||||
locker.ll.lockMap["name"] = []lockRequesterInfo{lri} // add item
|
||||
locker.ll.removeEntryIfExists(nlrip)
|
||||
{
|
||||
gotLri, _ := locker.ll.lockMap["name"]
|
||||
gotLri := locker.ll.lockMap["name"]
|
||||
expectedLri := []lockRequesterInfo(nil)
|
||||
if !reflect.DeepEqual(expectedLri, gotLri) {
|
||||
t.Errorf("Expected %#v, got %#v", expectedLri, gotLri)
|
||||
@ -87,7 +87,7 @@ func TestLockRpcServerRemoveEntry(t *testing.T) {
|
||||
lockRequesterInfo2,
|
||||
}
|
||||
|
||||
lri, _ := locker.ll.lockMap["name"]
|
||||
lri := locker.ll.lockMap["name"]
|
||||
|
||||
// test unknown uid
|
||||
if locker.ll.removeEntry("name", "unknown-uid", &lri) {
|
||||
@ -97,7 +97,7 @@ func TestLockRpcServerRemoveEntry(t *testing.T) {
|
||||
if !locker.ll.removeEntry("name", "0123-4567", &lri) {
|
||||
t.Errorf("Expected %#v, got %#v", true, false)
|
||||
} else {
|
||||
gotLri, _ := locker.ll.lockMap["name"]
|
||||
gotLri := locker.ll.lockMap["name"]
|
||||
expectedLri := []lockRequesterInfo{lockRequesterInfo2}
|
||||
if !reflect.DeepEqual(expectedLri, gotLri) {
|
||||
t.Errorf("Expected %#v, got %#v", expectedLri, gotLri)
|
||||
@ -107,7 +107,7 @@ func TestLockRpcServerRemoveEntry(t *testing.T) {
|
||||
if !locker.ll.removeEntry("name", "89ab-cdef", &lri) {
|
||||
t.Errorf("Expected %#v, got %#v", true, false)
|
||||
} else {
|
||||
gotLri, _ := locker.ll.lockMap["name"]
|
||||
gotLri := locker.ll.lockMap["name"]
|
||||
expectedLri := []lockRequesterInfo(nil)
|
||||
if !reflect.DeepEqual(expectedLri, gotLri) {
|
||||
t.Errorf("Expected %#v, got %#v", expectedLri, gotLri)
|
||||
|
@ -94,7 +94,7 @@ func TestLockRpcServerLock(t *testing.T) {
|
||||
if !result {
|
||||
t.Errorf("Expected %#v, got %#v", true, result)
|
||||
} else {
|
||||
gotLri, _ := locker.ll.lockMap["name"]
|
||||
gotLri := locker.ll.lockMap["name"]
|
||||
expectedLri := []lockRequesterInfo{
|
||||
{
|
||||
Writer: true,
|
||||
@ -174,7 +174,7 @@ func TestLockRpcServerUnlock(t *testing.T) {
|
||||
if !result {
|
||||
t.Errorf("Expected %#v, got %#v", true, result)
|
||||
} else {
|
||||
gotLri, _ := locker.ll.lockMap["name"]
|
||||
gotLri := locker.ll.lockMap["name"]
|
||||
expectedLri := []lockRequesterInfo(nil)
|
||||
if !testLockEquality(expectedLri, gotLri) {
|
||||
t.Errorf("Expected %#v, got %#v", expectedLri, gotLri)
|
||||
@ -210,7 +210,7 @@ func TestLockRpcServerRLock(t *testing.T) {
|
||||
if !result {
|
||||
t.Errorf("Expected %#v, got %#v", true, result)
|
||||
} else {
|
||||
gotLri, _ := locker.ll.lockMap["name"]
|
||||
gotLri := locker.ll.lockMap["name"]
|
||||
expectedLri := []lockRequesterInfo{
|
||||
{
|
||||
Writer: false,
|
||||
@ -312,7 +312,7 @@ func TestLockRpcServerRUnlock(t *testing.T) {
|
||||
if !result {
|
||||
t.Errorf("Expected %#v, got %#v", true, result)
|
||||
} else {
|
||||
gotLri, _ := locker.ll.lockMap["name"]
|
||||
gotLri := locker.ll.lockMap["name"]
|
||||
expectedLri := []lockRequesterInfo{
|
||||
{
|
||||
Writer: false,
|
||||
@ -336,7 +336,7 @@ func TestLockRpcServerRUnlock(t *testing.T) {
|
||||
if !result {
|
||||
t.Errorf("Expected %#v, got %#v", true, result)
|
||||
} else {
|
||||
gotLri, _ := locker.ll.lockMap["name"]
|
||||
gotLri := locker.ll.lockMap["name"]
|
||||
expectedLri := []lockRequesterInfo(nil)
|
||||
if !testLockEquality(expectedLri, gotLri) {
|
||||
t.Errorf("Expected %#v, got %#v", expectedLri, gotLri)
|
||||
@ -531,9 +531,6 @@ func TestLockServerInit(t *testing.T) {
|
||||
globalIsDistXL = testCase.isDistXL
|
||||
globalLockServer = nil
|
||||
_, _ = newDsyncNodes(testCase.endpoints)
|
||||
if err != nil {
|
||||
t.Fatalf("Got unexpected error initializing lock servers: %v", err)
|
||||
}
|
||||
if globalLockServer == nil && testCase.isDistXL {
|
||||
t.Errorf("Test %d: Expected initialized lock RPC receiver, but got uninitialized", i+1)
|
||||
}
|
||||
|
@ -1,55 +0,0 @@
|
||||
/*
|
||||
* Minio Cloud Storage, (C) 2016 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package cmd
|
||||
|
||||
// lockStat - encapsulates total, blocked and granted lock counts.
|
||||
type lockStat struct {
|
||||
total int64
|
||||
blocked int64
|
||||
granted int64
|
||||
}
|
||||
|
||||
// lockWaiting - updates lock stat when a lock becomes blocked.
|
||||
func (ls *lockStat) lockWaiting() {
|
||||
ls.blocked++
|
||||
ls.total++
|
||||
}
|
||||
|
||||
// lockGranted - updates lock stat when a lock is granted.
|
||||
func (ls *lockStat) lockGranted() {
|
||||
ls.blocked--
|
||||
ls.granted++
|
||||
}
|
||||
|
||||
// lockTimedOut - updates lock stat when a lock is timed out.
|
||||
func (ls *lockStat) lockTimedOut() {
|
||||
ls.blocked--
|
||||
ls.total--
|
||||
}
|
||||
|
||||
// lockRemoved - updates lock stat when a lock is removed, by Unlock
|
||||
// or ForceUnlock.
|
||||
func (ls *lockStat) lockRemoved(granted bool) {
|
||||
if granted {
|
||||
ls.granted--
|
||||
ls.total--
|
||||
|
||||
} else {
|
||||
ls.blocked--
|
||||
ls.total--
|
||||
}
|
||||
}
|
@ -56,12 +56,11 @@ func (l *logOnceType) logOnceIf(ctx context.Context, err error, id interface{})
|
||||
// Cleanup the map every 30 minutes so that the log message is printed again for the user to notice.
|
||||
func (l *logOnceType) cleanupRoutine() {
|
||||
for {
|
||||
select {
|
||||
case <-time.After(time.Minute * 30):
|
||||
l.Lock()
|
||||
l.IDMap = make(map[interface{}]error)
|
||||
l.Unlock()
|
||||
}
|
||||
l.Lock()
|
||||
l.IDMap = make(map[interface{}]error)
|
||||
l.Unlock()
|
||||
|
||||
time.Sleep(30 * time.Minute)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -50,6 +50,9 @@ func (h *Target) startHTTPLogger() {
|
||||
}
|
||||
|
||||
req, err := gohttp.NewRequest("POST", h.endpoint, bytes.NewBuffer(logJSON))
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
|
||||
resp, err := h.client.Do(req)
|
||||
|
@ -102,7 +102,6 @@ func newNSLock(isDistXL bool) *nsLockMap {
|
||||
nsMutex := nsLockMap{
|
||||
isDistXL: isDistXL,
|
||||
lockMap: make(map[nsParam]*nsLock),
|
||||
counters: &lockStat{},
|
||||
}
|
||||
return &nsMutex
|
||||
}
|
||||
@ -127,9 +126,6 @@ type nsLock struct {
|
||||
// nsLockMap - namespace lock map, provides primitives to Lock,
|
||||
// Unlock, RLock and RUnlock.
|
||||
type nsLockMap struct {
|
||||
// Lock counter used for lock debugging.
|
||||
counters *lockStat
|
||||
|
||||
// Indicates if namespace is part of a distributed setup.
|
||||
isDistXL bool
|
||||
lockMap map[nsParam]*nsLock
|
||||
@ -259,11 +255,8 @@ func (n *nsLockMap) ForceUnlock(volume, path string) {
|
||||
dsync.NewDRWMutex(pathJoin(volume, path), globalDsync).ForceUnlock()
|
||||
}
|
||||
|
||||
param := nsParam{volume, path}
|
||||
if _, found := n.lockMap[param]; found {
|
||||
// Remove lock from the map.
|
||||
delete(n.lockMap, param)
|
||||
}
|
||||
// Remove lock from the map.
|
||||
delete(n.lockMap, nsParam{volume, path})
|
||||
}
|
||||
|
||||
// lockInstance - frontend/top-level interface for namespace locks.
|
||||
|
@ -47,7 +47,6 @@ func TestNamespaceLockTest(t *testing.T) {
|
||||
unlk func(s1, s2, s3 string)
|
||||
rlk func(s1, s2, s3 string, t time.Duration) bool
|
||||
runlk func(s1, s2, s3 string)
|
||||
lkCount int
|
||||
lockedRefCount uint
|
||||
unlockedRefCount uint
|
||||
shouldPass bool
|
||||
|
@ -271,6 +271,9 @@ func (sys *NotificationSys) DownloadProfilingData(ctx context.Context, writer io
|
||||
isDir: false,
|
||||
sys: nil,
|
||||
})
|
||||
if zerr != nil {
|
||||
return profilingDataFound
|
||||
}
|
||||
|
||||
zwriter, zerr := zipWriter.CreateHeader(header)
|
||||
if zerr != nil {
|
||||
@ -602,22 +605,19 @@ func (sys *NotificationSys) Init(objAPI ObjectLayer) error {
|
||||
// the following reasons:
|
||||
// - Read quorum is lost just after the initialization
|
||||
// of the object layer.
|
||||
retryTimerCh := newRetryTimerSimple(doneCh)
|
||||
for {
|
||||
select {
|
||||
case _ = <-retryTimerCh:
|
||||
if err := sys.refresh(objAPI); err != nil {
|
||||
if err == errDiskNotFound ||
|
||||
strings.Contains(err.Error(), InsufficientReadQuorum{}.Error()) ||
|
||||
strings.Contains(err.Error(), InsufficientWriteQuorum{}.Error()) {
|
||||
logger.Info("Waiting for notification subsystem to be initialized..")
|
||||
continue
|
||||
}
|
||||
return err
|
||||
for range newRetryTimerSimple(doneCh) {
|
||||
if err := sys.refresh(objAPI); err != nil {
|
||||
if err == errDiskNotFound ||
|
||||
strings.Contains(err.Error(), InsufficientReadQuorum{}.Error()) ||
|
||||
strings.Contains(err.Error(), InsufficientWriteQuorum{}.Error()) {
|
||||
logger.Info("Waiting for notification subsystem to be initialized..")
|
||||
continue
|
||||
}
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
break
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddRulesMap - adds rules map for bucket name.
|
||||
|
@ -211,10 +211,7 @@ func checkPreconditions(w http.ResponseWriter, r *http.Request, objInfo ObjectIn
|
||||
func ifModifiedSince(objTime time.Time, givenTime time.Time) bool {
|
||||
// The Date-Modified header truncates sub-second precision, so
|
||||
// use mtime < t+1s instead of mtime <= t to check for unmodified.
|
||||
if objTime.After(givenTime.Add(1 * time.Second)) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
return objTime.After(givenTime.Add(1 * time.Second))
|
||||
}
|
||||
|
||||
// canonicalizeETag returns ETag with leading and trailing double-quotes removed,
|
||||
|
@ -838,7 +838,7 @@ func (api objectAPIHandlers) CopyObjectHandler(w http.ResponseWriter, r *http.Re
|
||||
reader = pipeReader
|
||||
length = -1
|
||||
|
||||
snappyWriter := snappy.NewWriter(pipeWriter)
|
||||
snappyWriter := snappy.NewBufferedWriter(pipeWriter)
|
||||
|
||||
go func() {
|
||||
// Compress the decompressed source object.
|
||||
@ -1217,7 +1217,7 @@ func (api objectAPIHandlers) PutObjectHandler(w http.ResponseWriter, r *http.Req
|
||||
metadata[ReservedMetadataPrefix+"actual-size"] = strconv.FormatInt(size, 10)
|
||||
|
||||
pipeReader, pipeWriter := io.Pipe()
|
||||
snappyWriter := snappy.NewWriter(pipeWriter)
|
||||
snappyWriter := snappy.NewBufferedWriter(pipeWriter)
|
||||
|
||||
var actualReader *hash.Reader
|
||||
actualReader, err = hash.NewReader(reader, size, md5hex, sha256hex, actualSize)
|
||||
@ -1660,7 +1660,7 @@ func (api objectAPIHandlers) CopyObjectPartHandler(w http.ResponseWriter, r *htt
|
||||
reader = pipeReader
|
||||
length = -1
|
||||
|
||||
snappyWriter := snappy.NewWriter(pipeWriter)
|
||||
snappyWriter := snappy.NewBufferedWriter(pipeWriter)
|
||||
|
||||
go func() {
|
||||
// Compress the decompressed source object.
|
||||
@ -1902,7 +1902,7 @@ func (api objectAPIHandlers) PutObjectPartHandler(w http.ResponseWriter, r *http
|
||||
isCompressed := false
|
||||
if objectAPI.IsCompressionSupported() && compressPart {
|
||||
pipeReader, pipeWriter = io.Pipe()
|
||||
snappyWriter := snappy.NewWriter(pipeWriter)
|
||||
snappyWriter := snappy.NewBufferedWriter(pipeWriter)
|
||||
|
||||
var actualReader *hash.Reader
|
||||
actualReader, err = hash.NewReader(reader, size, md5hex, sha256hex, actualSize)
|
||||
|
@ -855,6 +855,7 @@ func testAPIPutObjectStreamSigV4Handler(obj ObjectLayer, instanceType, bucketNam
|
||||
accessKey: credentials.AccessKey,
|
||||
secretKey: credentials.SecretKey,
|
||||
shouldPass: true,
|
||||
fault: None,
|
||||
},
|
||||
// Test case - 2
|
||||
// Small chunk size.
|
||||
@ -869,6 +870,7 @@ func testAPIPutObjectStreamSigV4Handler(obj ObjectLayer, instanceType, bucketNam
|
||||
accessKey: credentials.AccessKey,
|
||||
secretKey: credentials.SecretKey,
|
||||
shouldPass: true,
|
||||
fault: None,
|
||||
},
|
||||
// Test case - 3
|
||||
// Empty data
|
||||
@ -897,6 +899,7 @@ func testAPIPutObjectStreamSigV4Handler(obj ObjectLayer, instanceType, bucketNam
|
||||
accessKey: "",
|
||||
secretKey: "",
|
||||
shouldPass: false,
|
||||
fault: None,
|
||||
},
|
||||
// Test case - 5
|
||||
// Wrong auth header returns as bad request.
|
||||
@ -912,6 +915,7 @@ func testAPIPutObjectStreamSigV4Handler(obj ObjectLayer, instanceType, bucketNam
|
||||
secretKey: credentials.SecretKey,
|
||||
shouldPass: false,
|
||||
removeAuthHeader: true,
|
||||
fault: None,
|
||||
},
|
||||
// Test case - 6
|
||||
// Large chunk size.. also passes.
|
||||
@ -926,6 +930,7 @@ func testAPIPutObjectStreamSigV4Handler(obj ObjectLayer, instanceType, bucketNam
|
||||
accessKey: credentials.AccessKey,
|
||||
secretKey: credentials.SecretKey,
|
||||
shouldPass: true,
|
||||
fault: None,
|
||||
},
|
||||
// Test case - 7
|
||||
// Chunk with malformed encoding.
|
||||
@ -1017,6 +1022,7 @@ func testAPIPutObjectStreamSigV4Handler(obj ObjectLayer, instanceType, bucketNam
|
||||
secretKey: credentials.SecretKey,
|
||||
shouldPass: true,
|
||||
contentEncoding: "aws-chunked,gzip",
|
||||
fault: None,
|
||||
},
|
||||
}
|
||||
// Iterating over the cases, fetching the object validating the response.
|
||||
|
@ -465,7 +465,7 @@ func testObjectOverwriteWorks(obj ObjectLayer, instanceType string, t TestErrHan
|
||||
if err != nil {
|
||||
t.Fatalf("%s: <ERROR> %s", instanceType, err)
|
||||
}
|
||||
if string(bytesBuffer.Bytes()) != "The specified multipart upload does not exist. The upload ID might be invalid, or the multipart upload might have been aborted or completed." {
|
||||
if bytesBuffer.String() != "The specified multipart upload does not exist. The upload ID might be invalid, or the multipart upload might have been aborted or completed." {
|
||||
t.Errorf("%s: Invalid upload ID error mismatch.", instanceType)
|
||||
}
|
||||
}
|
||||
|
@ -158,23 +158,20 @@ func (sys *PolicySys) Init(objAPI ObjectLayer) error {
|
||||
// the following reasons:
|
||||
// - Read quorum is lost just after the initialization
|
||||
// of the object layer.
|
||||
retryTimerCh := newRetryTimerSimple(doneCh)
|
||||
for {
|
||||
select {
|
||||
case _ = <-retryTimerCh:
|
||||
// Load PolicySys once during boot.
|
||||
if err := sys.refresh(objAPI); err != nil {
|
||||
if err == errDiskNotFound ||
|
||||
strings.Contains(err.Error(), InsufficientReadQuorum{}.Error()) ||
|
||||
strings.Contains(err.Error(), InsufficientWriteQuorum{}.Error()) {
|
||||
logger.Info("Waiting for policy subsystem to be initialized..")
|
||||
continue
|
||||
}
|
||||
return err
|
||||
for range newRetryTimerSimple(doneCh) {
|
||||
// Load PolicySys once during boot.
|
||||
if err := sys.refresh(objAPI); err != nil {
|
||||
if err == errDiskNotFound ||
|
||||
strings.Contains(err.Error(), InsufficientReadQuorum{}.Error()) ||
|
||||
strings.Contains(err.Error(), InsufficientWriteQuorum{}.Error()) {
|
||||
logger.Info("Waiting for policy subsystem to be initialized..")
|
||||
continue
|
||||
}
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
break
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewPolicySys - creates new policy system.
|
||||
|
@ -860,7 +860,7 @@ func (s *posix) ReadFile(volume, path string, offset int64, buffer []byte, verif
|
||||
return 0, err
|
||||
}
|
||||
|
||||
if bytes.Compare(h.Sum(nil), verifier.sum) != 0 {
|
||||
if !bytes.Equal(h.Sum(nil), verifier.sum) {
|
||||
return 0, hashMismatchError{hex.EncodeToString(verifier.sum), hex.EncodeToString(h.Sum(nil))}
|
||||
}
|
||||
|
||||
|
@ -188,7 +188,7 @@ func TestPosixIsDirEmpty(t *testing.T) {
|
||||
|
||||
// Should give false on non-existent directory.
|
||||
dir1 := slashpath.Join(tmp, "non-existent-directory")
|
||||
if isDirEmpty(dir1) != false {
|
||||
if isDirEmpty(dir1) {
|
||||
t.Error("expected false for non-existent directory, got true")
|
||||
}
|
||||
|
||||
@ -199,7 +199,7 @@ func TestPosixIsDirEmpty(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if isDirEmpty(dir2) != false {
|
||||
if isDirEmpty(dir2) {
|
||||
t.Error("expected false for a file, got true")
|
||||
}
|
||||
|
||||
@ -210,7 +210,7 @@ func TestPosixIsDirEmpty(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if isDirEmpty(dir3) != true {
|
||||
if !isDirEmpty(dir3) {
|
||||
t.Error("expected true for empty dir, got false")
|
||||
}
|
||||
}
|
||||
|
@ -21,13 +21,6 @@ import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
var b512pool = sync.Pool{
|
||||
New: func() interface{} {
|
||||
buf := make([]byte, 512)
|
||||
return &buf
|
||||
},
|
||||
}
|
||||
|
||||
// A Pool is a type-safe wrapper around a sync.Pool.
|
||||
type Pool struct {
|
||||
p *sync.Pool
|
||||
|
@ -77,11 +77,6 @@ func (t mytype) Foo(a *Auth, b *int) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// incompatible method because of unexported method.
|
||||
func (t mytype) foo(a *Auth, b *int) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// incompatible method because of first argument is not Authenticator.
|
||||
func (t *mytype) Bar(a, b *int) error {
|
||||
return nil
|
||||
|
@ -285,10 +285,8 @@ func TestRPCClientCall(t *testing.T) {
|
||||
case1ExpectedResult := 19 * 8
|
||||
|
||||
testCases := []struct {
|
||||
serviceMethod string
|
||||
args interface {
|
||||
SetAuthArgs(args AuthArgs)
|
||||
}
|
||||
serviceMethod string
|
||||
args *Args
|
||||
result interface{}
|
||||
changeConfig bool
|
||||
expectedResult interface{}
|
||||
|
@ -186,9 +186,8 @@ func doesV4PresignParamsExist(query url.Values) APIErrorCode {
|
||||
|
||||
// Parses all the presigned signature values into separate elements.
|
||||
func parsePreSignV4(query url.Values, region string) (psv preSignValues, aec APIErrorCode) {
|
||||
var err APIErrorCode
|
||||
// verify whether the required query params exist.
|
||||
err = doesV4PresignParamsExist(query)
|
||||
err := doesV4PresignParamsExist(query)
|
||||
if err != ErrNone {
|
||||
return psv, err
|
||||
}
|
||||
|
@ -306,7 +306,6 @@ type TestServer struct {
|
||||
SecretKey string
|
||||
Server *httptest.Server
|
||||
Obj ObjectLayer
|
||||
endpoints EndpointList
|
||||
}
|
||||
|
||||
// UnstartedTestServer - Configures a temp FS/XL backend,
|
||||
@ -949,7 +948,7 @@ func preSignV2(req *http.Request, accessKeyID, secretAccessKey string, expires i
|
||||
|
||||
// Sign given request using Signature V2.
|
||||
func signRequestV2(req *http.Request, accessKey, secretKey string) error {
|
||||
req = s3signer.SignV2(*req, accessKey, secretKey, false)
|
||||
s3signer.SignV2(*req, accessKey, secretKey, false)
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -1305,36 +1304,6 @@ func getRandomBucketName() string {
|
||||
|
||||
}
|
||||
|
||||
// TruncateWriter - Writes `n` bytes, then returns with number of bytes written.
|
||||
// differs from iotest.TruncateWriter, the difference is commented in the Write method.
|
||||
func TruncateWriter(w io.Writer, n int64) io.Writer {
|
||||
return &truncateWriter{w, n}
|
||||
}
|
||||
|
||||
type truncateWriter struct {
|
||||
w io.Writer
|
||||
n int64
|
||||
}
|
||||
|
||||
func (t *truncateWriter) Write(p []byte) (n int, err error) {
|
||||
if t.n <= 0 {
|
||||
return len(p), nil
|
||||
}
|
||||
// real write
|
||||
n = len(p)
|
||||
if int64(n) > t.n {
|
||||
n = int(t.n)
|
||||
}
|
||||
n, err = t.w.Write(p[0:n])
|
||||
t.n -= int64(n)
|
||||
// Removed from iotest.TruncateWriter.
|
||||
// Need the Write method to return truncated number of bytes written, not the size of the buffer requested to be written.
|
||||
// if err == nil {
|
||||
// n = len(p)
|
||||
// }
|
||||
return
|
||||
}
|
||||
|
||||
// NewEOFWriter returns a Writer that writes to w,
|
||||
// but returns EOF error after writing n bytes.
|
||||
func NewEOFWriter(w io.Writer, n int64) io.Writer {
|
||||
@ -1696,11 +1665,10 @@ func initAPIHandlerTest(obj ObjectLayer, endpoints []string) (string, http.Handl
|
||||
// Register the API end points with XL object layer.
|
||||
// Registering only the GetObject handler.
|
||||
apiRouter := initTestAPIEndPoints(obj, endpoints)
|
||||
var f http.HandlerFunc
|
||||
f = func(w http.ResponseWriter, r *http.Request) {
|
||||
f := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
r.RequestURI = r.URL.RequestURI()
|
||||
apiRouter.ServeHTTP(w, r)
|
||||
}
|
||||
})
|
||||
return bucketName, f, nil
|
||||
}
|
||||
|
||||
@ -2173,40 +2141,6 @@ func initTestWebRPCEndPoint(objLayer ObjectLayer) http.Handler {
|
||||
return muxRouter
|
||||
}
|
||||
|
||||
func StartTestS3PeerRPCServer(t TestErrHandler) (TestServer, []string) {
|
||||
// init disks
|
||||
objLayer, fsDirs, err := prepareXL16()
|
||||
if err != nil {
|
||||
t.Fatalf("%s", err)
|
||||
}
|
||||
|
||||
// Create an instance of TestServer.
|
||||
testRPCServer := TestServer{}
|
||||
|
||||
if err = newTestConfig(globalMinioDefaultRegion, objLayer); err != nil {
|
||||
t.Fatalf("%s", err)
|
||||
}
|
||||
|
||||
// Fetch credentials for the test server.
|
||||
credentials := globalServerConfig.GetCredential()
|
||||
testRPCServer.AccessKey = credentials.AccessKey
|
||||
testRPCServer.SecretKey = credentials.SecretKey
|
||||
|
||||
// set object layer
|
||||
testRPCServer.Obj = objLayer
|
||||
globalObjLayerMutex.Lock()
|
||||
globalObjectAPI = objLayer
|
||||
globalObjLayerMutex.Unlock()
|
||||
|
||||
// Register router on a new mux
|
||||
muxRouter := mux.NewRouter().SkipClean(true)
|
||||
registerPeerRPCRouter(muxRouter)
|
||||
|
||||
// Initialize and run the TestServer.
|
||||
testRPCServer.Server = httptest.NewServer(muxRouter)
|
||||
return testRPCServer, fsDirs
|
||||
}
|
||||
|
||||
// generateTLSCertKey creates valid key/cert with registered DNS or IP address
|
||||
// depending on the passed parameter. That way, we can use tls config without
|
||||
// passing InsecureSkipVerify flag. This code is a simplified version of
|
||||
|
15
cmd/utils.go
15
cmd/utils.go
@ -228,11 +228,7 @@ func getProfileData() ([]byte, error) {
|
||||
}
|
||||
|
||||
// Starts a profiler returns nil if profiler is not enabled, caller needs to handle this.
|
||||
func startProfiler(profilerType, dirPath string) (interface {
|
||||
Stop()
|
||||
Path() string
|
||||
}, error) {
|
||||
|
||||
func startProfiler(profilerType, dirPath string) (minioProfiler, error) {
|
||||
var err error
|
||||
if dirPath == "" {
|
||||
dirPath, err = ioutil.TempDir("", "profile")
|
||||
@ -277,14 +273,17 @@ func startProfiler(profilerType, dirPath string) (interface {
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Global profiler to be used by service go-routine.
|
||||
var globalProfiler interface {
|
||||
// minioProfiler - minio profiler interface.
|
||||
type minioProfiler interface {
|
||||
// Stop the profiler
|
||||
Stop()
|
||||
// Return the path of the profiling file
|
||||
Path() string
|
||||
}
|
||||
|
||||
// Global profiler to be used by service go-routine.
|
||||
var globalProfiler minioProfiler
|
||||
|
||||
// dump the request into a string in JSON format.
|
||||
func dumpRequest(r *http.Request) string {
|
||||
header := cloneHeader(r.Header)
|
||||
@ -307,7 +306,7 @@ func dumpRequest(r *http.Request) string {
|
||||
}
|
||||
|
||||
// Formatted string.
|
||||
return strings.TrimSpace(string(buffer.Bytes()))
|
||||
return strings.TrimSpace(buffer.String())
|
||||
}
|
||||
|
||||
// isFile - returns whether given path is a file or not.
|
||||
|
@ -913,7 +913,7 @@ func (web *webAPIHandlers) Upload(w http.ResponseWriter, r *http.Request) {
|
||||
metadata[ReservedMetadataPrefix+"actual-size"] = strconv.FormatInt(size, 10)
|
||||
|
||||
pipeReader, pipeWriter := io.Pipe()
|
||||
snappyWriter := snappy.NewWriter(pipeWriter)
|
||||
snappyWriter := snappy.NewBufferedWriter(pipeWriter)
|
||||
|
||||
var actualReader *hash.Reader
|
||||
actualReader, err = hash.NewReader(reader, size, "", "", actualSize)
|
||||
@ -1313,14 +1313,15 @@ func (web *webAPIHandlers) DownloadZip(w http.ResponseWriter, r *http.Request) {
|
||||
// Response writer should be limited early on for decryption upto required length,
|
||||
// additionally also skipping mod(offset)64KiB boundaries.
|
||||
writer = ioutil.LimitedWriter(writer, startOffset%(64*1024), length)
|
||||
writer, startOffset, length, err = DecryptBlocksRequest(writer, r, args.BucketName, objectName, startOffset, length, info, false)
|
||||
writer, startOffset, length, err = DecryptBlocksRequest(writer, r,
|
||||
args.BucketName, objectName, startOffset, length, info, false)
|
||||
if err != nil {
|
||||
writeWebErrorResponse(w, err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
httpWriter := ioutil.WriteOnClose(writer)
|
||||
if err = getObject(ctx, args.BucketName, objectName, 0, length, httpWriter, "", opts); err != nil {
|
||||
if err = getObject(ctx, args.BucketName, objectName, startOffset, length, httpWriter, "", opts); err != nil {
|
||||
httpWriter.Close()
|
||||
if info.IsCompressed() {
|
||||
// Wait for decompression go-routine to retire.
|
||||
|
@ -120,7 +120,7 @@ func TestWriteWebErrorResponse(t *testing.T) {
|
||||
recvDesc := buffer.Bytes()
|
||||
// Check if the written desc is same as the one expected.
|
||||
if !bytes.Equal(recvDesc, []byte(desc)) {
|
||||
t.Errorf("Test %d: Unexpected response, expecting %s, got %s", i+1, desc, string(buffer.Bytes()))
|
||||
t.Errorf("Test %d: Unexpected response, expecting %s, got %s", i+1, desc, buffer.String())
|
||||
}
|
||||
buffer.Reset()
|
||||
}
|
||||
@ -491,23 +491,23 @@ func testListObjectsWebHandler(obj ObjectLayer, instanceType string, t TestErrHa
|
||||
t.Fatalf("Was not able to upload an object, %v", err)
|
||||
}
|
||||
|
||||
test := func(token string) (error, *ListObjectsRep) {
|
||||
test := func(token string) (*ListObjectsRep, error) {
|
||||
listObjectsRequest := ListObjectsArgs{BucketName: bucketName, Prefix: ""}
|
||||
listObjectsReply := &ListObjectsRep{}
|
||||
var req *http.Request
|
||||
req, err = newTestWebRPCRequest("Web.ListObjects", token, listObjectsRequest)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create HTTP request: <ERROR> %v", err)
|
||||
return nil, err
|
||||
}
|
||||
apiRouter.ServeHTTP(rec, req)
|
||||
if rec.Code != http.StatusOK {
|
||||
return fmt.Errorf("Expected the response status to be 200, but instead found `%d`", rec.Code), listObjectsReply
|
||||
return listObjectsReply, fmt.Errorf("Expected the response status to be 200, but instead found `%d`", rec.Code)
|
||||
}
|
||||
err = getTestWebRPCResponse(rec, &listObjectsReply)
|
||||
if err != nil {
|
||||
return err, listObjectsReply
|
||||
return listObjectsReply, err
|
||||
}
|
||||
return nil, listObjectsReply
|
||||
return listObjectsReply, nil
|
||||
}
|
||||
verifyReply := func(reply *ListObjectsRep) {
|
||||
if len(reply.Objects) == 0 {
|
||||
@ -522,14 +522,14 @@ func testListObjectsWebHandler(obj ObjectLayer, instanceType string, t TestErrHa
|
||||
}
|
||||
|
||||
// Authenticated ListObjects should succeed.
|
||||
err, reply := test(authorization)
|
||||
reply, err := test(authorization)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
verifyReply(reply)
|
||||
|
||||
// Unauthenticated ListObjects should fail.
|
||||
err, _ = test("")
|
||||
_, err = test("")
|
||||
if err == nil {
|
||||
t.Fatalf("Expected error `%s`", err)
|
||||
}
|
||||
@ -552,7 +552,7 @@ func testListObjectsWebHandler(obj ObjectLayer, instanceType string, t TestErrHa
|
||||
defer globalPolicySys.Remove(bucketName)
|
||||
|
||||
// Unauthenticated ListObjects with READ bucket policy should succeed.
|
||||
err, reply = test("")
|
||||
reply, err = test("")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -1559,7 +1559,7 @@ func TestWebCheckAuthorization(t *testing.T) {
|
||||
if rec.Code != http.StatusForbidden {
|
||||
t.Fatalf("Expected the response status to be 403, but instead found `%d`", rec.Code)
|
||||
}
|
||||
resp := string(rec.Body.Bytes())
|
||||
resp := rec.Body.String()
|
||||
if !strings.EqualFold(resp, errAuthentication.Error()) {
|
||||
t.Fatalf("Unexpected error message, expected: %s, found: `%s`", errAuthentication, resp)
|
||||
}
|
||||
@ -1580,7 +1580,7 @@ func TestWebCheckAuthorization(t *testing.T) {
|
||||
if rec.Code != http.StatusForbidden {
|
||||
t.Fatalf("Expected the response status to be 403, but instead found `%d`", rec.Code)
|
||||
}
|
||||
resp = string(rec.Body.Bytes())
|
||||
resp = rec.Body.String()
|
||||
if !strings.EqualFold(resp, errAuthentication.Error()) {
|
||||
t.Fatalf("Unexpected error message, expected: `%s`, found: `%s`", errAuthentication, resp)
|
||||
}
|
||||
|
@ -1111,16 +1111,8 @@ func (s *xlSets) HealFormat(ctx context.Context, dryRun bool) (res madmin.HealRe
|
||||
res.Before.Drives = make([]madmin.HealDriveInfo, len(beforeDrives))
|
||||
// Copy "after" drive state too from before.
|
||||
for k, v := range beforeDrives {
|
||||
res.Before.Drives[k] = madmin.HealDriveInfo{
|
||||
UUID: v.UUID,
|
||||
Endpoint: v.Endpoint,
|
||||
State: v.State,
|
||||
}
|
||||
res.After.Drives[k] = madmin.HealDriveInfo{
|
||||
UUID: v.UUID,
|
||||
Endpoint: v.Endpoint,
|
||||
State: v.State,
|
||||
}
|
||||
res.Before.Drives[k] = madmin.HealDriveInfo(v)
|
||||
res.After.Drives[k] = madmin.HealDriveInfo(v)
|
||||
}
|
||||
|
||||
for index, sErr := range sErrs {
|
||||
@ -1253,12 +1245,8 @@ func (s *xlSets) HealBucket(ctx context.Context, bucket string, dryRun, remove b
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
for _, v := range healResult.Before.Drives {
|
||||
result.Before.Drives = append(result.Before.Drives, v)
|
||||
}
|
||||
for _, v := range healResult.After.Drives {
|
||||
result.After.Drives = append(result.After.Drives, v)
|
||||
}
|
||||
result.Before.Drives = append(result.Before.Drives, healResult.Before.Drives...)
|
||||
result.After.Drives = append(result.After.Drives, healResult.After.Drives...)
|
||||
}
|
||||
|
||||
for _, endpoint := range s.endpoints {
|
||||
@ -1326,10 +1314,7 @@ func (s *xlSets) ListBucketsHeal(ctx context.Context) ([]BucketInfo, error) {
|
||||
return nil, err
|
||||
}
|
||||
for _, currBucket := range buckets {
|
||||
healBuckets[currBucket.Name] = BucketInfo{
|
||||
Name: currBucket.Name,
|
||||
Created: currBucket.Created,
|
||||
}
|
||||
healBuckets[currBucket.Name] = BucketInfo(currBucket)
|
||||
}
|
||||
}
|
||||
for _, bucketInfo := range healBuckets {
|
||||
|
@ -130,11 +130,7 @@ func (xl xlObjects) getBucketInfo(ctx context.Context, bucketName string) (bucke
|
||||
}
|
||||
volInfo, serr := disk.StatVol(bucketName)
|
||||
if serr == nil {
|
||||
bucketInfo = BucketInfo{
|
||||
Name: volInfo.Name,
|
||||
Created: volInfo.Created,
|
||||
}
|
||||
return bucketInfo, nil
|
||||
return BucketInfo(volInfo), nil
|
||||
}
|
||||
err = serr
|
||||
// For any reason disk went offline continue and pick the next one.
|
||||
@ -185,10 +181,7 @@ func (xl xlObjects) listBuckets(ctx context.Context) (bucketsInfo []BucketInfo,
|
||||
if isReservedOrInvalidBucket(volInfo.Name) {
|
||||
continue
|
||||
}
|
||||
bucketsInfo = append(bucketsInfo, BucketInfo{
|
||||
Name: volInfo.Name,
|
||||
Created: volInfo.Created,
|
||||
})
|
||||
bucketsInfo = append(bucketsInfo, BucketInfo(volInfo))
|
||||
}
|
||||
// For buckets info empty, loop once again to check
|
||||
// if we have, can happen if disks were down.
|
||||
|
@ -278,7 +278,7 @@ func TestDisksWithAllParts(t *testing.T) {
|
||||
t.Fatalf("Failed to putObject %v", err)
|
||||
}
|
||||
|
||||
partsMetadata, errs := readAllXLMetadata(ctx, xlDisks, bucket, object)
|
||||
_, errs := readAllXLMetadata(ctx, xlDisks, bucket, object)
|
||||
readQuorum := len(xl.storageDisks) / 2
|
||||
if reducedErr := reduceReadQuorumErrs(ctx, errs, objectOpIgnoredErrs, readQuorum); reducedErr != nil {
|
||||
t.Fatalf("Failed to read xl meta data %v", reducedErr)
|
||||
@ -286,7 +286,7 @@ func TestDisksWithAllParts(t *testing.T) {
|
||||
|
||||
// Test that all disks are returned without any failures with
|
||||
// unmodified meta data
|
||||
partsMetadata, errs = readAllXLMetadata(ctx, xlDisks, bucket, object)
|
||||
partsMetadata, errs := readAllXLMetadata(ctx, xlDisks, bucket, object)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to read xl meta data %v", err)
|
||||
}
|
||||
|
22
cmd/xl-v1.go
22
cmd/xl-v1.go
@ -120,28 +120,18 @@ func getStorageInfo(disks []StorageAPI) StorageInfo {
|
||||
return StorageInfo{}
|
||||
}
|
||||
|
||||
_, sscParity := getRedundancyCount(standardStorageClass, len(disks))
|
||||
_, rrscparity := getRedundancyCount(reducedRedundancyStorageClass, len(disks))
|
||||
|
||||
// Total number of online data drives available
|
||||
// This is the number of drives we report free and total space for
|
||||
availableDataDisks := uint64(onlineDisks - sscParity)
|
||||
|
||||
// Available data disks can be zero when onlineDisks is equal to parity,
|
||||
// at that point we simply choose online disks to calculate the size.
|
||||
if availableDataDisks == 0 {
|
||||
availableDataDisks = uint64(onlineDisks)
|
||||
}
|
||||
|
||||
storageInfo := StorageInfo{}
|
||||
|
||||
// Combine all disks to get total usage.
|
||||
var used uint64
|
||||
for _, di := range validDisksInfo {
|
||||
used = used + di.Used
|
||||
}
|
||||
storageInfo.Used = used
|
||||
|
||||
_, sscParity := getRedundancyCount(standardStorageClass, len(disks))
|
||||
_, rrscparity := getRedundancyCount(reducedRedundancyStorageClass, len(disks))
|
||||
|
||||
storageInfo := StorageInfo{
|
||||
Used: used,
|
||||
}
|
||||
storageInfo.Backend.Type = BackendErasure
|
||||
storageInfo.Backend.OnlineDisks = onlineDisks
|
||||
storageInfo.Backend.OfflineDisks = offlineDisks
|
||||
|
@ -60,7 +60,7 @@ func TestCertNew(t *testing.T) {
|
||||
if !reflect.DeepEqual(gcert.Certificate, expectedCert.Certificate) {
|
||||
t.Error("certificate doesn't match expected certificate")
|
||||
}
|
||||
c, err = certs.New("server.crt", "server2.key", tls.LoadX509KeyPair)
|
||||
_, err = certs.New("server.crt", "server2.key", tls.LoadX509KeyPair)
|
||||
if err == nil {
|
||||
t.Fatal("Expected to fail but got success")
|
||||
}
|
||||
|
@ -38,18 +38,6 @@ func TestFree(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if di.Total <= 0 {
|
||||
t.Error("Unexpected Total", di.Total)
|
||||
}
|
||||
if di.Free <= 0 {
|
||||
t.Error("Unexpected Free", di.Free)
|
||||
}
|
||||
if di.Files <= 0 {
|
||||
t.Error("Unexpected Files", di.Files)
|
||||
}
|
||||
if di.Ffree <= 0 {
|
||||
t.Error("Unexpected Ffree", di.Ffree)
|
||||
}
|
||||
if di.FSType == "UNKNOWN" {
|
||||
t.Error("Unexpected FSType", di.FSType)
|
||||
}
|
||||
|
@ -38,10 +38,10 @@ var (
|
||||
// `{1...64}`
|
||||
// `{33...64}`
|
||||
func parseEllipsesRange(pattern string) (seq []string, err error) {
|
||||
if strings.Index(pattern, openBraces) == -1 {
|
||||
if !strings.Contains(pattern, openBraces) {
|
||||
return nil, errors.New("Invalid argument")
|
||||
}
|
||||
if strings.Index(pattern, closeBraces) == -1 {
|
||||
if !strings.Contains(pattern, closeBraces) {
|
||||
return nil, errors.New("Invalid argument")
|
||||
}
|
||||
|
||||
@ -145,7 +145,7 @@ func (p Pattern) Expand() []string {
|
||||
case p.Suffix != "" && p.Prefix == "":
|
||||
labels = append(labels, fmt.Sprintf("%s%s", p.Seq[i], p.Suffix))
|
||||
case p.Suffix == "" && p.Prefix == "":
|
||||
labels = append(labels, fmt.Sprintf("%s", p.Seq[i]))
|
||||
labels = append(labels, p.Seq[i])
|
||||
default:
|
||||
labels = append(labels, fmt.Sprintf("%s%s%s", p.Prefix, p.Seq[i], p.Suffix))
|
||||
}
|
||||
|
@ -191,13 +191,11 @@ func (q Queue) ToRulesMap() RulesMap {
|
||||
|
||||
// Unused. Available for completion.
|
||||
type lambda struct {
|
||||
common
|
||||
ARN string `xml:"CloudFunction"`
|
||||
}
|
||||
|
||||
// Unused. Available for completion.
|
||||
type topic struct {
|
||||
common
|
||||
ARN string `xml:"Topic" json:"Topic"`
|
||||
}
|
||||
|
||||
|
@ -199,8 +199,7 @@ func TestQueueUnmarshalXML(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestQueueValidate(t *testing.T) {
|
||||
var data []byte
|
||||
data = []byte(`
|
||||
data := []byte(`
|
||||
<QueueConfiguration>
|
||||
<Id>1</Id>
|
||||
<Filter></Filter>
|
||||
@ -281,8 +280,7 @@ func TestQueueValidate(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestQueueSetRegion(t *testing.T) {
|
||||
var data []byte
|
||||
data = []byte(`
|
||||
data := []byte(`
|
||||
<QueueConfiguration>
|
||||
<Id>1</Id>
|
||||
<Filter></Filter>
|
||||
@ -341,8 +339,7 @@ func TestQueueSetRegion(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestQueueToRulesMap(t *testing.T) {
|
||||
var data []byte
|
||||
data = []byte(`
|
||||
data := []byte(`
|
||||
<QueueConfiguration>
|
||||
<Id>1</Id>
|
||||
<Filter></Filter>
|
||||
@ -520,8 +517,7 @@ func TestConfigUnmarshalXML(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestConfigValidate(t *testing.T) {
|
||||
var data []byte
|
||||
data = []byte(`
|
||||
data := []byte(`
|
||||
<NotificationConfiguration>
|
||||
<QueueConfiguration>
|
||||
<Id>1</Id>
|
||||
@ -628,8 +624,7 @@ func TestConfigValidate(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestConfigSetRegion(t *testing.T) {
|
||||
var data []byte
|
||||
data = []byte(`
|
||||
data := []byte(`
|
||||
<NotificationConfiguration>
|
||||
<QueueConfiguration>
|
||||
<Id>1</Id>
|
||||
@ -733,8 +728,7 @@ func TestConfigSetRegion(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestConfigToRulesMap(t *testing.T) {
|
||||
var data []byte
|
||||
data = []byte(`
|
||||
data := []byte(`
|
||||
<NotificationConfiguration>
|
||||
<QueueConfiguration>
|
||||
<Id>1</Id>
|
||||
|
@ -142,13 +142,13 @@ Test-Header: TestHeaderValue
|
||||
status, testCase.expectedStatus)
|
||||
}
|
||||
|
||||
matched, err := regexp.MatchString(testCase.expectedLogRegexp, string(logOutput.Bytes()))
|
||||
matched, err := regexp.MatchString(testCase.expectedLogRegexp, logOutput.String())
|
||||
if err != nil {
|
||||
t.Fatalf("Test %d: Incorrect regexp: %v", i+1, err)
|
||||
}
|
||||
|
||||
if !matched {
|
||||
t.Fatalf("Test %d: Unexpected log content, found: `%s`", i+1, string(logOutput.Bytes()))
|
||||
t.Fatalf("Test %d: Unexpected log content, found: `%s`", i+1, logOutput.String())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -60,6 +60,9 @@ func TestHashReaderHelperMethods(t *testing.T) {
|
||||
t.Errorf("Expected md5hex \"e2fc714c4727ee9395f324cd2e7f331f\", got %s", hex.EncodeToString(r.MD5Current()))
|
||||
}
|
||||
expectedSHA256, err := hex.DecodeString("88d4266fd4e6338d13b845fcf289579d209c897823b9217da3e161936f031589")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !bytes.Equal(r.SHA256(), expectedSHA256) {
|
||||
t.Errorf("Expected md5hex \"88d4266fd4e6338d13b845fcf289579d209c897823b9217da3e161936f031589\", got %s", r.SHA256HexString())
|
||||
}
|
||||
|
@ -22,7 +22,6 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"math/rand"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"net/url"
|
||||
@ -61,9 +60,6 @@ type AdminClient struct {
|
||||
// Advanced functionality.
|
||||
isTraceEnabled bool
|
||||
traceOutput io.Writer
|
||||
|
||||
// Random seed.
|
||||
random *rand.Rand
|
||||
}
|
||||
|
||||
// Global constants.
|
||||
@ -118,21 +114,17 @@ func privateNew(endpoint, accessKeyID, secretAccessKey string, secure bool) (*Ad
|
||||
}
|
||||
|
||||
// SetAppInfo - add application details to user agent.
|
||||
func (c *AdminClient) SetAppInfo(appName string, appVersion string) {
|
||||
func (adm *AdminClient) SetAppInfo(appName string, appVersion string) {
|
||||
// if app name and version is not set, we do not a new user
|
||||
// agent.
|
||||
if appName != "" && appVersion != "" {
|
||||
c.appInfo = struct {
|
||||
appName string
|
||||
appVersion string
|
||||
}{}
|
||||
c.appInfo.appName = appName
|
||||
c.appInfo.appVersion = appVersion
|
||||
adm.appInfo.appName = appName
|
||||
adm.appInfo.appVersion = appVersion
|
||||
}
|
||||
}
|
||||
|
||||
// SetCustomTransport - set new custom transport.
|
||||
func (c *AdminClient) SetCustomTransport(customHTTPTransport http.RoundTripper) {
|
||||
func (adm *AdminClient) SetCustomTransport(customHTTPTransport http.RoundTripper) {
|
||||
// Set this to override default transport
|
||||
// ``http.DefaultTransport``.
|
||||
//
|
||||
@ -147,28 +139,28 @@ func (c *AdminClient) SetCustomTransport(customHTTPTransport http.RoundTripper)
|
||||
// }
|
||||
// api.SetTransport(tr)
|
||||
//
|
||||
if c.httpClient != nil {
|
||||
c.httpClient.Transport = customHTTPTransport
|
||||
if adm.httpClient != nil {
|
||||
adm.httpClient.Transport = customHTTPTransport
|
||||
}
|
||||
}
|
||||
|
||||
// TraceOn - enable HTTP tracing.
|
||||
func (c *AdminClient) TraceOn(outputStream io.Writer) {
|
||||
func (adm *AdminClient) TraceOn(outputStream io.Writer) {
|
||||
// if outputStream is nil then default to os.Stdout.
|
||||
if outputStream == nil {
|
||||
outputStream = os.Stdout
|
||||
}
|
||||
// Sets a new output stream.
|
||||
c.traceOutput = outputStream
|
||||
adm.traceOutput = outputStream
|
||||
|
||||
// Enable tracing.
|
||||
c.isTraceEnabled = true
|
||||
adm.isTraceEnabled = true
|
||||
}
|
||||
|
||||
// TraceOff - disable HTTP tracing.
|
||||
func (c *AdminClient) TraceOff() {
|
||||
func (adm *AdminClient) TraceOff() {
|
||||
// Disable tracing.
|
||||
c.isTraceEnabled = false
|
||||
adm.isTraceEnabled = false
|
||||
}
|
||||
|
||||
// requestMetadata - is container for all the values to make a
|
||||
@ -181,7 +173,7 @@ type requestData struct {
|
||||
}
|
||||
|
||||
// Filter out signature value from Authorization header.
|
||||
func (c AdminClient) filterSignature(req *http.Request) {
|
||||
func (adm AdminClient) filterSignature(req *http.Request) {
|
||||
/// Signature V4 authorization header.
|
||||
|
||||
// Save the original auth.
|
||||
@ -197,19 +189,18 @@ func (c AdminClient) filterSignature(req *http.Request) {
|
||||
|
||||
// Set a temporary redacted auth
|
||||
req.Header.Set("Authorization", newAuth)
|
||||
return
|
||||
}
|
||||
|
||||
// dumpHTTP - dump HTTP request and response.
|
||||
func (c AdminClient) dumpHTTP(req *http.Request, resp *http.Response) error {
|
||||
func (adm AdminClient) dumpHTTP(req *http.Request, resp *http.Response) error {
|
||||
// Starts http dump.
|
||||
_, err := fmt.Fprintln(c.traceOutput, "---------START-HTTP---------")
|
||||
_, err := fmt.Fprintln(adm.traceOutput, "---------START-HTTP---------")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Filter out Signature field from Authorization header.
|
||||
c.filterSignature(req)
|
||||
adm.filterSignature(req)
|
||||
|
||||
// Only display request header.
|
||||
reqTrace, err := httputil.DumpRequestOut(req, false)
|
||||
@ -218,7 +209,7 @@ func (c AdminClient) dumpHTTP(req *http.Request, resp *http.Response) error {
|
||||
}
|
||||
|
||||
// Write request to trace output.
|
||||
_, err = fmt.Fprint(c.traceOutput, string(reqTrace))
|
||||
_, err = fmt.Fprint(adm.traceOutput, string(reqTrace))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -254,24 +245,24 @@ func (c AdminClient) dumpHTTP(req *http.Request, resp *http.Response) error {
|
||||
}
|
||||
}
|
||||
// Write response to trace output.
|
||||
_, err = fmt.Fprint(c.traceOutput, strings.TrimSuffix(string(respTrace), "\r\n"))
|
||||
_, err = fmt.Fprint(adm.traceOutput, strings.TrimSuffix(string(respTrace), "\r\n"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Ends the http dump.
|
||||
_, err = fmt.Fprintln(c.traceOutput, "---------END-HTTP---------")
|
||||
_, err = fmt.Fprintln(adm.traceOutput, "---------END-HTTP---------")
|
||||
return err
|
||||
}
|
||||
|
||||
// do - execute http request.
|
||||
func (c AdminClient) do(req *http.Request) (*http.Response, error) {
|
||||
func (adm AdminClient) do(req *http.Request) (*http.Response, error) {
|
||||
var resp *http.Response
|
||||
var err error
|
||||
// Do the request in a loop in case of 307 http is met since golang still doesn't
|
||||
// handle properly this situation (https://github.com/golang/go/issues/7912)
|
||||
for {
|
||||
resp, err = c.httpClient.Do(req)
|
||||
resp, err = adm.httpClient.Do(req)
|
||||
if err != nil {
|
||||
// Handle this specifically for now until future Golang
|
||||
// versions fix this issue properly.
|
||||
@ -304,8 +295,8 @@ func (c AdminClient) do(req *http.Request) (*http.Response, error) {
|
||||
}
|
||||
|
||||
// If trace is enabled, dump http request and response.
|
||||
if c.isTraceEnabled {
|
||||
err = c.dumpHTTP(req, resp)
|
||||
if adm.isTraceEnabled {
|
||||
err = adm.dumpHTTP(req, resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -323,7 +314,7 @@ var successStatus = []int{
|
||||
// executeMethod - instantiates a given method, and retries the
|
||||
// request upon any error up to maxRetries attempts in a binomially
|
||||
// delayed manner using a standard back off algorithm.
|
||||
func (c AdminClient) executeMethod(method string, reqData requestData) (res *http.Response, err error) {
|
||||
func (adm AdminClient) executeMethod(method string, reqData requestData) (res *http.Response, err error) {
|
||||
|
||||
// Create a done channel to control 'ListObjects' go routine.
|
||||
doneCh := make(chan struct{}, 1)
|
||||
@ -333,13 +324,13 @@ func (c AdminClient) executeMethod(method string, reqData requestData) (res *htt
|
||||
|
||||
// Instantiate a new request.
|
||||
var req *http.Request
|
||||
req, err = c.newRequest(method, reqData)
|
||||
req, err = adm.newRequest(method, reqData)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Initiate the request.
|
||||
res, err = c.do(req)
|
||||
res, err = adm.do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -368,15 +359,15 @@ func (c AdminClient) executeMethod(method string, reqData requestData) (res *htt
|
||||
}
|
||||
|
||||
// set User agent.
|
||||
func (c AdminClient) setUserAgent(req *http.Request) {
|
||||
func (adm AdminClient) setUserAgent(req *http.Request) {
|
||||
req.Header.Set("User-Agent", libraryUserAgent)
|
||||
if c.appInfo.appName != "" && c.appInfo.appVersion != "" {
|
||||
req.Header.Set("User-Agent", libraryUserAgent+" "+c.appInfo.appName+"/"+c.appInfo.appVersion)
|
||||
if adm.appInfo.appName != "" && adm.appInfo.appVersion != "" {
|
||||
req.Header.Set("User-Agent", libraryUserAgent+" "+adm.appInfo.appName+"/"+adm.appInfo.appVersion)
|
||||
}
|
||||
}
|
||||
|
||||
// newRequest - instantiate a new HTTP request for a given method.
|
||||
func (c AdminClient) newRequest(method string, reqData requestData) (req *http.Request, err error) {
|
||||
func (adm AdminClient) newRequest(method string, reqData requestData) (req *http.Request, err error) {
|
||||
// If no method is supplied default to 'POST'.
|
||||
if method == "" {
|
||||
method = "POST"
|
||||
@ -386,7 +377,7 @@ func (c AdminClient) newRequest(method string, reqData requestData) (req *http.R
|
||||
location := ""
|
||||
|
||||
// Construct a new target URL.
|
||||
targetURL, err := c.makeTargetURL(reqData)
|
||||
targetURL, err := adm.makeTargetURL(reqData)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -397,7 +388,7 @@ func (c AdminClient) newRequest(method string, reqData requestData) (req *http.R
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c.setUserAgent(req)
|
||||
adm.setUserAgent(req)
|
||||
for k, v := range reqData.customHeaders {
|
||||
req.Header.Set(k, v[0])
|
||||
}
|
||||
@ -407,15 +398,15 @@ func (c AdminClient) newRequest(method string, reqData requestData) (req *http.R
|
||||
req.Header.Set("X-Amz-Content-Sha256", hex.EncodeToString(sum256(reqData.content)))
|
||||
req.Body = ioutil.NopCloser(bytes.NewReader(reqData.content))
|
||||
|
||||
req = s3signer.SignV4(*req, c.accessKeyID, c.secretAccessKey, "", location)
|
||||
req = s3signer.SignV4(*req, adm.accessKeyID, adm.secretAccessKey, "", location)
|
||||
return req, nil
|
||||
}
|
||||
|
||||
// makeTargetURL make a new target url.
|
||||
func (c AdminClient) makeTargetURL(r requestData) (*url.URL, error) {
|
||||
func (adm AdminClient) makeTargetURL(r requestData) (*url.URL, error) {
|
||||
|
||||
host := c.endpointURL.Host
|
||||
scheme := c.endpointURL.Scheme
|
||||
host := adm.endpointURL.Host
|
||||
scheme := adm.endpointURL.Scheme
|
||||
|
||||
urlStr := scheme + "://" + host + libraryAdminURLPrefix + r.relPath
|
||||
|
||||
|
@ -31,9 +31,8 @@ func TestMimeLookup(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestTypeByExtension(t *testing.T) {
|
||||
var contentType string
|
||||
// Test TypeByExtension.
|
||||
contentType = TypeByExtension(".txt")
|
||||
contentType := TypeByExtension(".txt")
|
||||
if contentType != "text/plain" {
|
||||
t.Fatalf("Invalid content type are found expected \"text/plain\", got %s", contentType)
|
||||
}
|
||||
|
@ -62,17 +62,16 @@ func FormatJSONSyntaxError(data io.Reader, offset int64) (highlight string) {
|
||||
if readBytes > offset {
|
||||
break
|
||||
}
|
||||
switch b {
|
||||
case '\n':
|
||||
if b == '\n' {
|
||||
readLine.Reset()
|
||||
errLine++
|
||||
case '\t':
|
||||
continue
|
||||
} else if b == '\t' {
|
||||
readLine.WriteByte(' ')
|
||||
case '\r':
|
||||
} else if b == '\r' {
|
||||
break
|
||||
default:
|
||||
readLine.WriteByte(b)
|
||||
}
|
||||
readLine.WriteByte(b)
|
||||
}
|
||||
|
||||
lineLen := readLine.Len()
|
||||
|
@ -307,7 +307,6 @@ func (writer *messageWriter) start() {
|
||||
case <-recordStagingTicker.C:
|
||||
if !writer.flushRecords() {
|
||||
quitFlag = true
|
||||
break
|
||||
}
|
||||
|
||||
case <-keepAliveTicker.C:
|
||||
|
@ -408,9 +408,7 @@ func (s3Select *S3Select) Evaluate(w http.ResponseWriter) {
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
if serr := writer.FinishWithError("InternalError", err.Error()); serr != nil {
|
||||
// FIXME: log errors.
|
||||
}
|
||||
_ = writer.FinishWithError("InternalError", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -274,10 +274,6 @@ func (e *FuncExpr) aggregateRow(r Record) error {
|
||||
// called after calling aggregateRow() on each input row, to calculate
|
||||
// the final aggregate result.
|
||||
|
||||
func (e *Expression) getAggregate() (*Value, error) {
|
||||
return e.evalNode(nil)
|
||||
}
|
||||
|
||||
func (e *FuncExpr) getAggregate() (*Value, error) {
|
||||
switch e.getFunctionName() {
|
||||
case aggFnCount:
|
||||
|
@ -234,7 +234,9 @@ func handleDateAdd(r Record, d *DateAddFunc) (*Value, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
inferTypeAsTimestamp(ts)
|
||||
if err = inferTypeAsTimestamp(ts); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
t, ok := ts.ToTimestamp()
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("%s() expects a timestamp argument", sqlFnDateAdd)
|
||||
@ -248,7 +250,9 @@ func handleDateDiff(r Record, d *DateDiffFunc) (*Value, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
inferTypeAsTimestamp(tval1)
|
||||
if err = inferTypeAsTimestamp(tval1); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ts1, ok := tval1.ToTimestamp()
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("%s() expects two timestamp arguments", sqlFnDateDiff)
|
||||
@ -258,7 +262,9 @@ func handleDateDiff(r Record, d *DateDiffFunc) (*Value, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
inferTypeAsTimestamp(tval2)
|
||||
if err = inferTypeAsTimestamp(tval2); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ts2, ok := tval2.ToTimestamp()
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("%s() expects two timestamp arguments", sqlFnDateDiff)
|
||||
@ -363,7 +369,9 @@ func handleSQLExtract(r Record, e *ExtractFunc) (res *Value, err error) {
|
||||
return nil, verr
|
||||
}
|
||||
|
||||
inferTypeAsTimestamp(timeVal)
|
||||
if err = inferTypeAsTimestamp(timeVal); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
t, ok := timeVal.ToTimestamp()
|
||||
if !ok {
|
||||
|
@ -83,8 +83,6 @@ type Select struct {
|
||||
type SelectExpression struct {
|
||||
All bool `parser:" @\"*\""`
|
||||
Expressions []*AliasedExpression `parser:"| @@ { \",\" @@ }"`
|
||||
|
||||
prop qProp
|
||||
}
|
||||
|
||||
// TableExpression represents the FROM clause
|
||||
|
@ -38,7 +38,6 @@ var (
|
||||
layoutSecond,
|
||||
layoutNanosecond,
|
||||
}
|
||||
oneNanoSecond = 1
|
||||
)
|
||||
|
||||
func parseSQLTimestamp(s string) (t time.Time, err error) {
|
||||
|
@ -248,7 +248,7 @@ func (v *Value) CSVString() string {
|
||||
case typeBool:
|
||||
return fmt.Sprintf("%v", v.value.(bool))
|
||||
case typeString:
|
||||
return fmt.Sprintf("%s", v.value.(string))
|
||||
return v.value.(string)
|
||||
case typeInt:
|
||||
return fmt.Sprintf("%v", v.value.(int64))
|
||||
case typeFloat:
|
||||
@ -610,22 +610,22 @@ func (v *Value) minmax(a *Value, isMax, isFirstRow bool) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func inferTypeAsTimestamp(v *Value) {
|
||||
func inferTypeAsTimestamp(v *Value) error {
|
||||
if s, ok := v.ToString(); ok {
|
||||
t, err := parseSQLTimestamp(s)
|
||||
if err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
v.setTimestamp(t)
|
||||
} else if b, ok := v.ToBytes(); ok {
|
||||
s := string(b)
|
||||
t, err := parseSQLTimestamp(s)
|
||||
if err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
v.setTimestamp(t)
|
||||
}
|
||||
return
|
||||
return nil
|
||||
}
|
||||
|
||||
// inferTypeAsString is used to convert untyped values to string - it
|
||||
|
@ -22,8 +22,7 @@ import (
|
||||
|
||||
// Simply make sure creating a new tree works.
|
||||
func TestNewTrie(t *testing.T) {
|
||||
var trie *Trie
|
||||
trie = NewTrie()
|
||||
trie := NewTrie()
|
||||
|
||||
if trie.size != 0 {
|
||||
t.Errorf("expected size 0, got: %d", trie.size)
|
||||
@ -32,8 +31,7 @@ func TestNewTrie(t *testing.T) {
|
||||
|
||||
// Ensure that we can insert new keys into the tree, then check the size.
|
||||
func TestInsert(t *testing.T) {
|
||||
var trie *Trie
|
||||
trie = NewTrie()
|
||||
trie := NewTrie()
|
||||
|
||||
// We need to have an empty tree to begin with.
|
||||
if trie.size != 0 {
|
||||
@ -51,8 +49,7 @@ func TestInsert(t *testing.T) {
|
||||
|
||||
// Ensure that PrefixMatch gives us the correct two keys in the tree.
|
||||
func TestPrefixMatch(t *testing.T) {
|
||||
var trie *Trie
|
||||
trie = NewTrie()
|
||||
trie := NewTrie()
|
||||
|
||||
// Feed it some fodder: only 'minio' and 'miny-os' should trip the matcher.
|
||||
trie.Insert("minio")
|
||||
|
@ -26,7 +26,6 @@ func TestMinimum(t *testing.T) {
|
||||
type testCase struct {
|
||||
listval []int
|
||||
expected int
|
||||
pass bool
|
||||
}
|
||||
testCases := []testCase{
|
||||
{listval: []int{3, 4, 15}, expected: 3},
|
||||
|
1
staticcheck.conf
Normal file
1
staticcheck.conf
Normal file
@ -0,0 +1 @@
|
||||
checks = ["all", "-ST1005", "-ST1000", "-SA4000", "-SA9004", "-SA1019"]
|
Loading…
Reference in New Issue
Block a user