allow forcibly creating metadata on buckets (#14820)

introduce x-minio-force-create environment variable
to force create a bucket and its metadata as required,
it is useful in some situations when bucket metadata
needs recovery.
This commit is contained in:
Harshavardhana 2022-04-27 04:44:07 -07:00 committed by GitHub
parent fe1fbe0005
commit 5a9a898ba2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 36 additions and 4 deletions

View File

@ -115,10 +115,12 @@ func (a adminAPIHandlers) SRPeerBucketOps(w http.ResponseWriter, r *http.Request
case madmin.MakeWithVersioningBktOp:
_, isLockEnabled := r.Form["lockEnabled"]
_, isVersioningEnabled := r.Form["versioningEnabled"]
_, isForceCreate := r.Form["forceCreate"]
opts := BucketOptions{
Location: r.Form.Get("location"),
LockEnabled: isLockEnabled,
VersioningEnabled: isVersioningEnabled,
ForceCreate: isForceCreate,
}
err = globalSiteReplicationSys.PeerBucketMakeWithVersioningHandler(ctx, bucket, opts)
case madmin.ConfigureReplBktOp:

View File

@ -706,13 +706,27 @@ func (api objectAPIHandlers) PutBucketHandler(w http.ResponseWriter, r *http.Req
bucket := vars["bucket"]
objectLockEnabled := false
if vs, found := r.Header[http.CanonicalHeaderKey("x-amz-bucket-object-lock-enabled")]; found {
v := strings.ToLower(strings.Join(vs, ""))
if v != "true" && v != "false" {
if vs := r.Header.Get(xhttp.AmzObjectLockEnabled); len(vs) > 0 {
v := strings.ToLower(vs)
switch v {
case "true", "false":
objectLockEnabled = v == "true"
default:
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrInvalidRequest), r.URL)
return
}
}
forceCreate := false
if vs := r.Header.Get(xhttp.MinIOForceCreate); len(vs) > 0 {
v := strings.ToLower(vs)
switch v {
case "true", "false":
forceCreate = v == "true"
default:
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrInvalidRequest), r.URL)
return
}
objectLockEnabled = v == "true"
}
if s3Error := checkRequestAuthType(ctx, r, policy.CreateBucketAction, bucket, ""); s3Error != ErrNone {
@ -737,6 +751,7 @@ func (api objectAPIHandlers) PutBucketHandler(w http.ResponseWriter, r *http.Req
opts := BucketOptions{
Location: location,
LockEnabled: objectLockEnabled,
ForceCreate: forceCreate,
}
if globalDNSConfig != nil {

View File

@ -55,6 +55,11 @@ func (er erasureObjects) MakeBucketWithLocation(ctx context.Context, bucket stri
g.Go(func() error {
if storageDisks[index] != nil {
if err := storageDisks[index].MakeVol(ctx, bucket); err != nil {
if opts.ForceCreate && errors.Is(err, errVolumeExists) {
// No need to return error when force create was
// requested.
return nil
}
if !errors.Is(err, errVolumeExists) {
logger.LogIf(ctx, err)
}

View File

@ -98,6 +98,7 @@ type BucketOptions struct {
Location string
LockEnabled bool
VersioningEnabled bool
ForceCreate bool // Create buckets even if they are already created.
}
// DeleteBucketOptions provides options for DeleteBucket calls.

View File

@ -625,6 +625,9 @@ func (c *SiteReplicationSys) MakeBucketHook(ctx context.Context, bucket string,
if opts.VersioningEnabled {
optsMap["versioningEnabled"] = "true"
}
if opts.ForceCreate {
optsMap["forceCreate"] = "true"
}
// Create bucket and enable versioning on all peers.
makeBucketConcErr := c.concDo(

View File

@ -91,6 +91,9 @@ const (
AmzBucketReplicationStatus = "X-Amz-Replication-Status"
AmzSnowballExtract = "X-Amz-Meta-Snowball-Auto-Extract"
// Object lock enabled
AmzObjectLockEnabled = "x-amz-bucket-object-lock-enabled"
// Multipart parts count
AmzMpPartsCount = "x-amz-mp-parts-count"
@ -144,6 +147,9 @@ const (
// Delete special flag to force delete a bucket or a prefix
MinIOForceDelete = "x-minio-force-delete"
// Create special flag to force create a bucket
MinIOForceCreate = "x-minio-force-create"
// Header indicates if the mtime should be preserved by client
MinIOSourceMTime = "x-minio-source-mtime"