I have created a Mutating Webhook for a Namespaced CRD. In this Webhook, I would like to dynamically change the namespace of the resource, no matter what the user specified.
When I try to create a resource, I get the following error:
Error from server (BadRequest): error when creating "crd.yaml": the namespace of the provided object does not match the namespace sent on the request
Is it possible to perform this change and, if so, am I missing any configuration?
Sadly, it might not be possible: looking at the code here, you can see that if the resource you're attempting to create already has a namespace (the request), and your webhook attempts to mutate the object to replace the namespace (the object), then there will be a mismatch.
if err := EnsureObjectNamespaceMatchesRequestNamespace(ExpectedNamespaceForScope(requestNamespace, strategy.NamespaceScoped()), objectMeta); err != nil {
return err
}
You can see that the function EnsureObjectNamespaceMatchesRequestNamespace
takes in two things: the expected namespace from the request and the object's metadata. If the request coming in is namespaced, then the request's namespace will be returned.
If you look at the function, you can see that your case falls through to the default case:
switch {
case objNamespace == requestNamespace:
// already matches, no-op
return nil
case objNamespace == metav1.NamespaceNone:
// unset, default to request namespace
obj.SetNamespace(requestNamespace)
return nil
case requestNamespace == metav1.NamespaceNone:
// cluster-scoped, clear namespace
obj.SetNamespace(metav1.NamespaceNone)
return nil
default:
// mismatch, error
return errors.NewBadRequest("the namespace of the provided object does not match the namespace sent on the request")
}
Did you end up figuring out a workaround for yourself?