Simplify remote tier validation in lifecycle rule validation (#12329)

This commit is contained in:
Krishnan Parthasarathi 2021-05-19 18:51:23 -07:00 committed by GitHub
parent 2ca9c533ef
commit cfa94cc35c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 46 additions and 23 deletions

View File

@ -1814,6 +1814,8 @@ func toAPIErrorCode(ctx context.Context, err error) (apiErr APIErrorCode) {
apiErr = ErrAdminInvalidAccessKey apiErr = ErrAdminInvalidAccessKey
case auth.ErrInvalidSecretKeyLength: case auth.ErrInvalidSecretKeyLength:
apiErr = ErrAdminInvalidSecretKey apiErr = ErrAdminInvalidSecretKey
case errInvalidStorageClass:
apiErr = ErrInvalidStorageClass
// SSE errors // SSE errors
case errInvalidEncryptionParameters: case errInvalidEncryptionParameters:
apiErr = ErrInvalidEncryptionParameters apiErr = ErrInvalidEncryptionParameters

View File

@ -80,7 +80,7 @@ func (api objectAPIHandlers) PutBucketLifecycleHandler(w http.ResponseWriter, r
} }
// Validate the transition storage ARNs // Validate the transition storage ARNs
if err = validateLifecycleTransition(ctx, bucket, bucketLifecycle); err != nil { if err = validateTransitionTier(ctx, bucketLifecycle); err != nil {
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r)) writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
return return
} }

View File

@ -20,6 +20,7 @@ package cmd
import ( import (
"context" "context"
"encoding/xml" "encoding/xml"
"errors"
"fmt" "fmt"
"io" "io"
"net/http" "net/http"
@ -175,28 +176,16 @@ func initBackgroundTransition(ctx context.Context, objectAPI ObjectLayer) {
} }
} }
func validateLifecycleTransition(ctx context.Context, bucket string, lfc *lifecycle.Lifecycle) error { var errInvalidStorageClass = errors.New("invalid storage class")
for _, rule := range lfc.Rules {
if rule.Transition.StorageClass != "" {
err := validateTransitionDestination(rule.Transition.StorageClass)
if err != nil {
return err
}
}
}
return nil
}
// validateTransitionDestination returns error if transition destination bucket missing or not configured func validateTransitionTier(ctx context.Context, lfc *lifecycle.Lifecycle) error {
// It also returns true if transition destination is same as this server. for _, rule := range lfc.Rules {
func validateTransitionDestination(sc string) error { if rule.Transition.StorageClass == "" {
backend, err := globalTierConfigMgr.getDriver(sc) continue
if err != nil { }
return TransitionStorageClassNotFound{} if valid := globalTierConfigMgr.IsTierValid(rule.Transition.StorageClass); !valid {
} return errInvalidStorageClass
_, err = backend.Get(context.Background(), "probeobject", WarmBackendGetOpts{}) }
if !isErrObjectNotFound(err) {
return err
} }
return nil return nil
} }

View File

@ -18,6 +18,8 @@
package cmd package cmd
import ( import (
"bytes"
"context"
"net/http" "net/http"
"testing" "testing"
"time" "time"
@ -214,3 +216,33 @@ func TestObjectIsRemote(t *testing.T) {
t.Fatalf("Expected object not to be remote but got %v", got) t.Fatalf("Expected object not to be remote but got %v", got)
} }
} }
func TestValidateTransitionTier(t *testing.T) {
globalTierConfigMgr = NewTierConfigMgr()
testCases := []struct {
xml []byte
expectedErr error
}{
{
// non-existent storage-class
xml: []byte(`<LifecycleConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/"><Rule><ID>rule</ID><Prefix /><Status>Enabled</Status><Transition><Days>1</Days><StorageClass>"NONEXISTENT"</StorageClass></Transition></Rule></LifecycleConfiguration>`),
expectedErr: errInvalidStorageClass,
},
{
// no transition rule
xml: []byte(`<LifecycleConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/"><Rule><ID>rule</ID><Prefix /><Status>Enabled</Status><Expiration><Days>1</Days></Expiration></Rule></LifecycleConfiguration>`),
expectedErr: nil,
},
}
for i, tc := range testCases {
lc, err := lifecycle.ParseLifecycleConfig(bytes.NewReader(tc.xml))
if err != nil {
t.Fatalf("Test %d: Failed to parse lifecycle config %v", i+1, err)
}
err = validateTransitionTier(context.Background(), lc)
if err != tc.expectedErr {
t.Fatalf("Test %d: Expected %v but got %v", i+1, tc.expectedErr, err)
}
}
}

View File

@ -129,7 +129,7 @@ func (t *Transition) UnmarshalXML(d *xml.Decoder, startElement xml.StartElement)
return nil return nil
} }
// Validate - validates the "Expiration" element // Validate - validates the "Transition" element
func (t Transition) Validate() error { func (t Transition) Validate() error {
if !t.set { if !t.set {
return nil return nil