Generalize error messages for remote targets (#10638)

This is to allow remote targets to be generalized
for replication/ILM transition

Also adding a field in BucketTarget to identify
a remote target with a label.
This commit is contained in:
Poorna Krishnamoorthy 2020-10-08 10:54:11 -07:00 committed by GitHub
parent ed6d2a100f
commit 907a171edd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 63 additions and 45 deletions

View File

@ -180,19 +180,19 @@ func registerAdminRouter(router *mux.Router, enableConfigOps, enableIAMOps bool)
// PutBucketQuotaConfig // PutBucketQuotaConfig
adminRouter.Methods(http.MethodPut).Path(adminVersion+"/set-bucket-quota").HandlerFunc( adminRouter.Methods(http.MethodPut).Path(adminVersion+"/set-bucket-quota").HandlerFunc(
httpTraceHdrs(adminAPI.PutBucketQuotaConfigHandler)).Queries("bucket", "{bucket:.*}") httpTraceHdrs(adminAPI.PutBucketQuotaConfigHandler)).Queries("bucket", "{bucket:.*}")
}
// Bucket replication operations
// GetBucketTargetHandler
adminRouter.Methods(http.MethodGet).Path(adminVersion+"/list-remote-targets").HandlerFunc(
httpTraceHdrs(adminAPI.ListRemoteTargetsHandler)).Queries("bucket", "{bucket:.*}", "type", "{type:.*}")
// SetRemoteTargetHandler
adminRouter.Methods(http.MethodPut).Path(adminVersion+"/set-remote-target").HandlerFunc(
httpTraceHdrs(adminAPI.SetRemoteTargetHandler)).Queries("bucket", "{bucket:.*}")
// SetRemoteTargetHandler
adminRouter.Methods(http.MethodDelete).Path(adminVersion+"/remove-remote-target").HandlerFunc(
httpTraceHdrs(adminAPI.RemoveRemoteTargetHandler)).Queries("bucket", "{bucket:.*}", "arn", "{arn:.*}")
}
// Bucket replication operations
// GetBucketTargetHandler
adminRouter.Methods(http.MethodGet).Path(adminVersion+"/list-remote-targets").HandlerFunc(
httpTraceHdrs(adminAPI.ListRemoteTargetsHandler)).Queries("bucket", "{bucket:.*}", "type", "{type:.*}")
// SetRemoteTargetHandler
adminRouter.Methods(http.MethodPut).Path(adminVersion+"/set-remote-target").HandlerFunc(
httpTraceHdrs(adminAPI.SetRemoteTargetHandler)).Queries("bucket", "{bucket:.*}")
// SetRemoteTargetHandler
adminRouter.Methods(http.MethodDelete).Path(adminVersion+"/remove-remote-target").HandlerFunc(
httpTraceHdrs(adminAPI.RemoveRemoteTargetHandler)).Queries("bucket", "{bucket:.*}", "arn", "{arn:.*}")
}
}
// -- Top APIs -- // -- Top APIs --
// Top locks // Top locks
if globalIsDistErasure { if globalIsDistErasure {

View File

@ -106,16 +106,17 @@ const (
ErrNoSuchCORSConfiguration ErrNoSuchCORSConfiguration
ErrNoSuchWebsiteConfiguration ErrNoSuchWebsiteConfiguration
ErrReplicationConfigurationNotFoundError ErrReplicationConfigurationNotFoundError
ErrReplicationDestinationNotFoundError ErrRemoteDestinationNotFoundError
ErrReplicationDestinationMissingLock ErrReplicationDestinationMissingLock
ErrReplicationTargetNotFoundError ErrRemoteTargetNotFoundError
ErrReplicationRemoteConnectionError ErrReplicationRemoteConnectionError
ErrBucketRemoteIdenticalToSource ErrBucketRemoteIdenticalToSource
ErrBucketRemoteAlreadyExists ErrBucketRemoteAlreadyExists
ErrBucketRemoteLabelInUse
ErrBucketRemoteArnTypeInvalid ErrBucketRemoteArnTypeInvalid
ErrBucketRemoteArnInvalid ErrBucketRemoteArnInvalid
ErrBucketRemoteRemoveDisallowed ErrBucketRemoteRemoveDisallowed
ErrReplicationTargetNotVersionedError ErrRemoteTargetNotVersionedError
ErrReplicationSourceNotVersionedError ErrReplicationSourceNotVersionedError
ErrReplicationNeedsVersioningError ErrReplicationNeedsVersioningError
ErrReplicationBucketNeedsVersioningError ErrReplicationBucketNeedsVersioningError
@ -809,9 +810,9 @@ var errorCodes = errorCodeMap{
Description: "The replication configuration was not found", Description: "The replication configuration was not found",
HTTPStatusCode: http.StatusNotFound, HTTPStatusCode: http.StatusNotFound,
}, },
ErrReplicationDestinationNotFoundError: { ErrRemoteDestinationNotFoundError: {
Code: "ReplicationDestinationNotFoundError", Code: "RemoteDestinationNotFoundError",
Description: "The replication destination bucket does not exist", Description: "The remote destination bucket does not exist",
HTTPStatusCode: http.StatusNotFound, HTTPStatusCode: http.StatusNotFound,
}, },
ErrReplicationDestinationMissingLock: { ErrReplicationDestinationMissingLock: {
@ -819,9 +820,9 @@ var errorCodes = errorCodeMap{
Description: "The replication destination bucket does not have object locking enabled", Description: "The replication destination bucket does not have object locking enabled",
HTTPStatusCode: http.StatusBadRequest, HTTPStatusCode: http.StatusBadRequest,
}, },
ErrReplicationTargetNotFoundError: { ErrRemoteTargetNotFoundError: {
Code: "XMinioAdminReplicationTargetNotFoundError", Code: "XMinioAdminRemoteTargetNotFoundError",
Description: "The replication target does not exist", Description: "The remote target does not exist",
HTTPStatusCode: http.StatusNotFound, HTTPStatusCode: http.StatusNotFound,
}, },
ErrReplicationRemoteConnectionError: { ErrReplicationRemoteConnectionError: {
@ -839,9 +840,14 @@ var errorCodes = errorCodeMap{
Description: "The remote target already exists", Description: "The remote target already exists",
HTTPStatusCode: http.StatusBadRequest, HTTPStatusCode: http.StatusBadRequest,
}, },
ErrBucketRemoteLabelInUse: {
Code: "XMinioAdminBucketRemoteLabelInUse",
Description: "The remote target with this label already exists",
HTTPStatusCode: http.StatusBadRequest,
},
ErrBucketRemoteRemoveDisallowed: { ErrBucketRemoteRemoveDisallowed: {
Code: "XMinioAdminRemoteRemoveDisallowed", Code: "XMinioAdminRemoteRemoveDisallowed",
Description: "Replication configuration exists with this ARN.", Description: "This ARN is in use by an existing configuration",
HTTPStatusCode: http.StatusBadRequest, HTTPStatusCode: http.StatusBadRequest,
}, },
ErrBucketRemoteArnTypeInvalid: { ErrBucketRemoteArnTypeInvalid: {
@ -854,9 +860,9 @@ var errorCodes = errorCodeMap{
Description: "The bucket remote ARN does not have correct format", Description: "The bucket remote ARN does not have correct format",
HTTPStatusCode: http.StatusBadRequest, HTTPStatusCode: http.StatusBadRequest,
}, },
ErrReplicationTargetNotVersionedError: { ErrRemoteTargetNotVersionedError: {
Code: "ReplicationTargetNotVersionedError", Code: "RemoteTargetNotVersionedError",
Description: "The replication target does not have versioning enabled", Description: "The remote target does not have versioning enabled",
HTTPStatusCode: http.StatusBadRequest, HTTPStatusCode: http.StatusBadRequest,
}, },
ErrReplicationSourceNotVersionedError: { ErrReplicationSourceNotVersionedError: {
@ -1906,24 +1912,26 @@ func toAPIErrorCode(ctx context.Context, err error) (apiErr APIErrorCode) {
apiErr = ErrAdminNoSuchQuotaConfiguration apiErr = ErrAdminNoSuchQuotaConfiguration
case BucketReplicationConfigNotFound: case BucketReplicationConfigNotFound:
apiErr = ErrReplicationConfigurationNotFoundError apiErr = ErrReplicationConfigurationNotFoundError
case BucketReplicationDestinationNotFound: case BucketRemoteDestinationNotFound:
apiErr = ErrReplicationDestinationNotFoundError apiErr = ErrRemoteDestinationNotFoundError
case BucketReplicationDestinationMissingLock: case BucketReplicationDestinationMissingLock:
apiErr = ErrReplicationDestinationMissingLock apiErr = ErrReplicationDestinationMissingLock
case BucketRemoteTargetNotFound: case BucketRemoteTargetNotFound:
apiErr = ErrReplicationTargetNotFoundError apiErr = ErrRemoteTargetNotFoundError
case BucketRemoteConnectionErr: case BucketRemoteConnectionErr:
apiErr = ErrReplicationRemoteConnectionError apiErr = ErrReplicationRemoteConnectionError
case BucketRemoteAlreadyExists: case BucketRemoteAlreadyExists:
apiErr = ErrBucketRemoteAlreadyExists apiErr = ErrBucketRemoteAlreadyExists
case BucketRemoteLabelInUse:
apiErr = ErrBucketRemoteLabelInUse
case BucketRemoteArnTypeInvalid: case BucketRemoteArnTypeInvalid:
apiErr = ErrBucketRemoteArnTypeInvalid apiErr = ErrBucketRemoteArnTypeInvalid
case BucketRemoteArnInvalid: case BucketRemoteArnInvalid:
apiErr = ErrBucketRemoteArnInvalid apiErr = ErrBucketRemoteArnInvalid
case BucketRemoteRemoveDisallowed: case BucketRemoteRemoveDisallowed:
apiErr = ErrBucketRemoteRemoveDisallowed apiErr = ErrBucketRemoteRemoveDisallowed
case BucketReplicationTargetNotVersioned: case BucketRemoteTargetNotVersioned:
apiErr = ErrReplicationTargetNotVersionedError apiErr = ErrRemoteTargetNotVersionedError
case BucketReplicationSourceNotVersioned: case BucketReplicationSourceNotVersioned:
apiErr = ErrReplicationSourceNotVersionedError apiErr = ErrReplicationSourceNotVersionedError
case BucketQuotaExceeded: case BucketQuotaExceeded:

View File

@ -52,12 +52,12 @@ func getReplicationConfig(ctx context.Context, bucketName string) (rc *replicati
// validateReplicationDestination returns error if replication destination bucket missing or not configured // validateReplicationDestination returns error if replication destination bucket missing or not configured
// It also returns true if replication destination is same as this server. // It also returns true if replication destination is same as this server.
func validateReplicationDestination(ctx context.Context, bucket string, rCfg *replication.Config) (bool, error) { func validateReplicationDestination(ctx context.Context, bucket string, rCfg *replication.Config) (bool, error) {
clnt := globalBucketTargetSys.GetReplicationTargetClient(ctx, rCfg.RoleArn) clnt := globalBucketTargetSys.GetRemoteTargetClient(ctx, rCfg.RoleArn)
if clnt == nil { if clnt == nil {
return false, BucketRemoteTargetNotFound{Bucket: bucket} return false, BucketRemoteTargetNotFound{Bucket: bucket}
} }
if found, _ := clnt.BucketExists(ctx, rCfg.GetDestination().Bucket); !found { if found, _ := clnt.BucketExists(ctx, rCfg.GetDestination().Bucket); !found {
return false, BucketReplicationDestinationNotFound{Bucket: rCfg.GetDestination().Bucket} return false, BucketRemoteDestinationNotFound{Bucket: rCfg.GetDestination().Bucket}
} }
if ret, err := globalBucketObjectLockSys.Get(bucket); err == nil { if ret, err := globalBucketObjectLockSys.Get(bucket); err == nil {
if ret.LockEnabled { if ret.LockEnabled {
@ -182,8 +182,7 @@ func replicateObject(ctx context.Context, objInfo ObjectInfo, objectAPI ObjectLa
logger.LogIf(ctx, err) logger.LogIf(ctx, err)
return return
} }
tgt := globalBucketTargetSys.GetRemoteTargetClient(ctx, cfg.RoleArn)
tgt := globalBucketTargetSys.GetReplicationTargetClient(ctx, cfg.RoleArn)
if tgt == nil { if tgt == nil {
return return
} }

View File

@ -98,10 +98,9 @@ func (sys *BucketTargetSys) SetTarget(ctx context.Context, bucket string, tgt *m
return BucketRemoteConnectionErr{Bucket: tgt.TargetBucket} return BucketRemoteConnectionErr{Bucket: tgt.TargetBucket}
} }
if vcfg.Status != string(versioning.Enabled) { if vcfg.Status != string(versioning.Enabled) {
return BucketReplicationTargetNotVersioned{Bucket: tgt.TargetBucket} return BucketRemoteTargetNotVersioned{Bucket: tgt.TargetBucket}
} }
} }
sys.Lock() sys.Lock()
defer sys.Unlock() defer sys.Unlock()
@ -113,6 +112,9 @@ func (sys *BucketTargetSys) SetTarget(ctx context.Context, bucket string, tgt *m
if t.Arn == tgt.Arn { if t.Arn == tgt.Arn {
return BucketRemoteAlreadyExists{Bucket: t.TargetBucket} return BucketRemoteAlreadyExists{Bucket: t.TargetBucket}
} }
if t.Label == tgt.Label {
return BucketRemoteLabelInUse{Bucket: t.TargetBucket}
}
newtgts[idx] = *tgt newtgts[idx] = *tgt
found = true found = true
continue continue
@ -173,8 +175,8 @@ func (sys *BucketTargetSys) RemoveTarget(ctx context.Context, bucket, arnStr str
return nil return nil
} }
// GetReplicationTargetClient returns minio-go client for replication target instance // GetRemoteTargetClient returns minio-go client for replication target instance
func (sys *BucketTargetSys) GetReplicationTargetClient(ctx context.Context, arn string) *miniogo.Core { func (sys *BucketTargetSys) GetRemoteTargetClient(ctx context.Context, arn string) *miniogo.Core {
sys.RLock() sys.RLock()
defer sys.RUnlock() defer sys.RUnlock()
return sys.arnRemotesMap[arn] return sys.arnRemotesMap[arn]

View File

@ -361,10 +361,10 @@ func (e BucketReplicationConfigNotFound) Error() string {
return "The replication configuration was not found: " + e.Bucket return "The replication configuration was not found: " + e.Bucket
} }
// BucketReplicationDestinationNotFound bucket does not exist. // BucketRemoteDestinationNotFound bucket does not exist.
type BucketReplicationDestinationNotFound GenericError type BucketRemoteDestinationNotFound GenericError
func (e BucketReplicationDestinationNotFound) Error() string { func (e BucketRemoteDestinationNotFound) Error() string {
return "Destination bucket does not exist: " + e.Bucket return "Destination bucket does not exist: " + e.Bucket
} }
@ -396,6 +396,13 @@ func (e BucketRemoteAlreadyExists) Error() string {
return "Remote already exists for this bucket: " + e.Bucket return "Remote already exists for this bucket: " + e.Bucket
} }
// BucketRemoteLabelInUse remote already exists for this target label.
type BucketRemoteLabelInUse GenericError
func (e BucketRemoteLabelInUse) Error() string {
return "Remote with this label already exists for this bucket: " + e.Bucket
}
// BucketRemoteArnTypeInvalid arn type for remote is not valid. // BucketRemoteArnTypeInvalid arn type for remote is not valid.
type BucketRemoteArnTypeInvalid GenericError type BucketRemoteArnTypeInvalid GenericError
@ -417,11 +424,11 @@ func (e BucketRemoteRemoveDisallowed) Error() string {
return "Replication configuration exists with this ARN:" + e.Bucket return "Replication configuration exists with this ARN:" + e.Bucket
} }
// BucketReplicationTargetNotVersioned replication target does not have versioning enabled. // BucketRemoteTargetNotVersioned remote target does not have versioning enabled.
type BucketReplicationTargetNotVersioned GenericError type BucketRemoteTargetNotVersioned GenericError
func (e BucketReplicationTargetNotVersioned) Error() string { func (e BucketRemoteTargetNotVersioned) Error() string {
return "Replication target does not have versioning enabled: " + e.Bucket return "Remote target does not have versioning enabled: " + e.Bucket
} }
// BucketReplicationSourceNotVersioned replication source does not have versioning enabled. // BucketReplicationSourceNotVersioned replication source does not have versioning enabled.

View File

@ -94,6 +94,7 @@ type BucketTarget struct {
Arn string `json:"arn,omitempty"` Arn string `json:"arn,omitempty"`
Type ServiceType `json:"type"` Type ServiceType `json:"type"`
Region string `json:"omitempty"` Region string `json:"omitempty"`
Label string `json:"label,omitempty"`
} }
// Clone returns shallow clone of BucketTarget without secret key in credentials // Clone returns shallow clone of BucketTarget without secret key in credentials
@ -109,6 +110,7 @@ func (t *BucketTarget) Clone() BucketTarget {
Arn: t.Arn, Arn: t.Arn,
Type: t.Type, Type: t.Type,
Region: t.Region, Region: t.Region,
Label: t.Label,
} }
} }