Repository: kubernetes/kubernetes (language: go)

Issue:
Improve message `prefer a domain-qualified finalizer name to avoid accidental conflicts with other finalizer writers`
### What happened?

k8s component developers are using FQDNs as finalizers (e.g. `cluster.cluster.x-k8s.io` or `finalizer.acme.cert-manager.io` which triggers an error message that isn't particularly easy for an end user to understand:

`prefer a domain-qualified finalizer name to avoid accidental conflicts with other finalizer writers`

To a naive end user, a fully qualified domain name is a pretty safe thing that is unlikely to conflict with anything else  (as long as it's only used by someone from within the domain that owns it, which is a reasonable assumption).

### What did you expect to happen?

If the finalizer has `.`s inside it but no `/`, the message should suggest that finalizers need a `/`.

Something like:
`prefer a domain-qualified finalizer name including a path (/) to avoid accidental conflicts with other finalizer writers`

### How can we reproduce it (as minimally and precisely as possible)?

Do whatever it is that triggered the warning in https://github.com/kubernetes-sigs/cluster-api/issues/10914 (this is probably simpler than installing cert-manager and asking for a certificate)

### Anything else we need to know?

#119508 introduced: https://github.com/kubernetes/kubernetes/blob/f836773540cc83488250a12637e7d924078ef284/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/validator.go#L89

### Kubernetes version

<details>

```console
Client Version: v1.30.3
Kustomize Version: v5.0.4-0.20230601165947-6ce0bf390ce3
Server Version: v1.29.7-gke.1274000
```

</details>


### Cloud provider

<details>
GKE
</details>


### OS version

<details>

```console
```

</details>


### Install tools

<details>

</details>


### Container runtime (CRI) and version (if applicable)

<details>

</details>


### Related plugins (CNI, CSI, ...) and versions (if applicable)

<details>

</details>



Discussion / hints:

/sig api-machinery


If thats ok I would like to work on that.
/assign

Fix patch:
diff --git a/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/validator.go b/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/validator.go
index 559b3b8f9932b..7e2f6f4d551b0 100644
--- a/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/validator.go
+++ b/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/validator.go
@@ -86,7 +86,11 @@ func validateKubeFinalizerName(stringValue string, fldPath *field.Path) []string
 	}
 	if len(strings.Split(stringValue, "/")) == 1 {
 		if !standardFinalizers.Has(stringValue) {
-			allWarnings = append(allWarnings, fmt.Sprintf("%s: %q: prefer a domain-qualified finalizer name to avoid accidental conflicts with other finalizer writers", fldPath.String(), stringValue))
+			if strings.Contains(stringValue, ".") {
+				allWarnings = append(allWarnings, fmt.Sprintf("%s: %q: prefer a domain-qualified finalizer name including a path (/) to avoid accidental conflicts with other finalizer writers", fldPath.String(), stringValue))
+			} else {
+				allWarnings = append(allWarnings, fmt.Sprintf("%s: %q: prefer a domain-qualified finalizer name to avoid accidental conflicts with other finalizer writers", fldPath.String(), stringValue))
+			}
 		}
 	}
 	return allWarnings


Test patch:
diff --git a/test/integration/apiserver/field_validation_test.go b/test/integration/apiserver/field_validation_test.go
index de9258ce5f17a..dea47eec31115 100644
--- a/test/integration/apiserver/field_validation_test.go
+++ b/test/integration/apiserver/field_validation_test.go
@@ -2937,6 +2937,13 @@ func testFinalizerValidationApplyCreateAndUpdateCRD(t *testing.T, rest rest.Inte
 			name:      "create-crd-with-valid-finalizer",
 			finalizer: []string{"kubernetes.io/valid-finalizer"},
 		},
+		{
+			name:      "create-crd-with-fqdn-like-finalizer-without-path",
+			finalizer: []string{"finalizer.without.valid-path.io"},
+			expectCreateWarnings: []string{
+				`metadata.finalizers: "finalizer.without.valid-path.io": prefer a domain-qualified finalizer name including a path (/) to avoid accidental conflicts with other finalizer writers`,
+			},
+		},
 		{
 			name:             "update-crd-with-invalid-finalizer",
 			finalizer:        []string{"invalid-finalizer"},