Repository: minio/minio (language: go)

Issue:
Bucket DNS entry added in ETCD when using DeleteBucket on a non-existing bucket

<!--- Provide a general summary of the issue in the Title above -->
When using Minio with ETCD, whenever a delete bucket order is emitted on a bucket that doesn't exist, the bucket entry gets recreated, causing the bucket name to become unusable until the next restart of minio server.

## Expected Behavior
<!--- If you're describing a bug, tell us what should happen -->
<!--- If you're suggesting a change/improvement, tell us how it should work -->
Only a delete command emitted in etcd, instead of DELETE then PUT

## Current Behavior
<!--- If describing a bug, tell us what happens instead of the expected behavior -->
<!--- If suggesting a change/improvement, explain the difference from current behavior -->
We're watching the /skydns prefix on etcd, here is what we see:
```
DELETE "/skydns/storagedomain/bucketthatdoesntexist/node1" : ""
PUT "/skydns/storagedomain/bucketthatdoesntexist/node1" : "{\"host\":\"node1\",\"port\":9000,\"ttl\":30,\"creationDate\":\"2023-04-20T10:49:34.372812919Z\"}"
```

## Possible Solution
<!--- Not obligatory, but suggest a fix/reason for the bug, -->
<!--- or ideas how to implement the addition or change -->
N/D

## Steps to Reproduce (for bugs)
<!--- Provide a link to a live example, or an unambiguous set of steps to -->
<!--- reproduce this bug. Include code to reproduce, if relevant -->
<!--- and make sure you have followed https://github.com/minio/minio/tree/release/docs/debugging to capture relevant logs -->

1. aws --profile minio --endpoint-url http://storagedomain s3 rb s3://bucketthatdoesntexist
```
remove_bucket failed: s3://bucketthatdoesntexist An error occurred (NoSuchBucket) when calling the DeleteBucket operation: The specified bucket does not exist
```
2. aws --profile minio --endpoint-url http://storagedomain s3 mb s3://bucketthatdoesntexist
```
make_bucket failed: s3://bucketthatdoesntexist An error occurred (BucketAlreadyOwnedByYou) when calling the CreateBucket operation: Your previous request to create the named bucket succeeded and you already own it.
```
3. systemctl restart minio
-> The key for that bucket gets deleted on start, and the functionality is restored

## Context
<!--- How has this issue affected you? What are you trying to accomplish? -->
<!--- Providing context helps us come up with a solution that is most useful in the real world -->
We're using ETCD for storing DNS and IAM entries, and we've observed this side-effect which breaks functionality

## Regression
<!-- Is this issue a regression? (Yes / No) -->
<!-- If Yes, optionally please include minio version or commit id or PR# that caused this regression, if you have these details. -->
N/D

## Your Environment
<!--- Include as many relevant details about the environment you experienced the bug in -->
* Version used (`minio --version`):
* Server setup and configuration:
* Operating System and version (`uname -a`):
```
minio --version
minio version RELEASE.2023-04-13T03-08-07Z (commit-id=a42650c065fe22c6a6d3ce526d80c5354d4bceac)
Runtime: go1.20.3 linux/amd64
License: GNU AGPLv3 <https://www.gnu.org/licenses/agpl-3.0.html>
Copyright: 2015-2023 MinIO, Inc.
```

```
MINIO_ETCD_ENDPOINTS=[...]
MINIO_DOMAIN=storagedomain
MINIO_ETCD_PATH_PREFIX=/tenant/
```

```
uname -a
Linux node1 5.10.0-20-amd64 #1 SMP Debian 5.10.158-2 (2022-12-13) x86_64 GNU/Linux
```


Discussion / hints:

Fix patch:
diff --git a/cmd/bucket-handlers.go b/cmd/bucket-handlers.go
index 40f417aa189ec..d96593ae570c4 100644
--- a/cmd/bucket-handlers.go
+++ b/cmd/bucket-handlers.go
@@ -1324,14 +1324,6 @@ func (api objectAPIHandlers) DeleteBucketHandler(w http.ResponseWriter, r *http.
 		}
 	}
 
-	if globalDNSConfig != nil {
-		if err := globalDNSConfig.Delete(bucket); err != nil {
-			logger.LogIf(ctx, fmt.Errorf("Unable to delete bucket DNS entry %w, please delete it manually", err))
-			writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
-			return
-		}
-	}
-
 	deleteBucket := objectAPI.DeleteBucket
 
 	// Attempt to delete bucket.
@@ -1345,15 +1337,18 @@ func (api objectAPIHandlers) DeleteBucketHandler(w http.ResponseWriter, r *http.
 				apiErr.Description = "The bucket you tried to delete is not empty. You must delete all versions in the bucket."
 			}
 		}
-		if globalDNSConfig != nil {
-			if err2 := globalDNSConfig.Put(bucket); err2 != nil {
-				logger.LogIf(ctx, fmt.Errorf("Unable to restore bucket DNS entry %w, please fix it manually", err2))
-			}
-		}
 		writeErrorResponse(ctx, w, apiErr, r.URL)
 		return
 	}
 
+	if globalDNSConfig != nil {
+		if err := globalDNSConfig.Delete(bucket); err != nil {
+			logger.LogIf(ctx, fmt.Errorf("Unable to delete bucket DNS entry %w, please delete it manually, bucket on MinIO no longer exists", err))
+			writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
+			return
+		}
+	}
+
 	globalNotificationSys.DeleteBucketMetadata(ctx, bucket)
 	globalReplicationPool.deleteResyncMetadata(ctx, bucket)
 


Test patch: