Option to restrict informer cache to a namespace#136
Conversation
|
@DirectXMan12 PTAL |
|
|
||
| // Create the cache for the cached read client and registering informers | ||
| cache, err := options.newCache(config, cache.Options{Scheme: options.Scheme, Mapper: mapper, Resync: options.SyncPeriod}) | ||
| cache, err := options.newCache(config, cache.Options{Scheme: options.Scheme, Mapper: mapper, Resync: options.SyncPeriod, Namespace: options.Namespace}) |
There was a problem hiding this comment.
When I need to watch all namespace events, set nil to options.Namespace or set other value?
Thanks.
There was a problem hiding this comment.
To watch all namespaces you set options.Namespaces = "" or metav1.NamespaceAll which is the same thing.
But since the default string value is empty you can just not set the Namespace option in cache.Options and it should watch all namespaces by default.
| ListFunc: func(opts metav1.ListOptions) (runtime.Object, error) { | ||
| res := listObj.DeepCopyObject() | ||
| err := client.Get().Resource(mapping.Resource.Resource).VersionedParams(&opts, ip.paramCodec).Do().Into(res) | ||
| err := client.Get().Namespace(ip.namespace).Resource(mapping.Resource.Resource).VersionedParams(&opts, ip.paramCodec).Do().Into(res) |
There was a problem hiding this comment.
does this need to be NamespaceIfScoped(ip.namespace, ip.namespace == "")?
There was a problem hiding this comment.
You could do without NamespaceIfScoped since the URL constructed ignores namespaces if namespace == "".
https://github.com/kubernetes/client-go/blob/master/rest/request.go#L424
But that behavior is implicit so I've added NamespaceIfScoped(ip.namespace, ip.namespace != "") to make the distinction more clear.
cb979d2 to
9ddd976
Compare
|
@DirectXMan12 The request is explicitly namespace scoped now. PTAL. |
|
@droot can you please review this in case @DirectXMan12 is busy. |
|
@hasbro17 change looks good to me. @DirectXMan12 , would you like to take a final look ? |
|
@droot thanks. I think @DirectXMan12 should be back on Monday to take a look. |
9ddd976 to
b976451
Compare
|
Rebased and added another namespaced cache test for an unstructured object. |
| Expect(out.Items).Should(HaveLen(1)) | ||
| Expect(out.Items[0].GetNamespace()).To(Equal(testNamespaceOne)) | ||
| }) | ||
|
|
| LeaderElectionID string | ||
|
|
||
| // Namespace if specified restricts the manager's cache to watch the desired namespace | ||
| // Defaults to all namespaces |
There was a problem hiding this comment.
May be make it more explicit:
watch
objectsin the desired namespace
Also one more q: if I specify the namespace here and later setup a watch for a cluster scoped resource (say Node), will I get error, what would be the UX ?
We should document that behavior here probably.
There was a problem hiding this comment.
I tested it out by specifying the manager's namespace and added a controller to watch nodes:
$ ./main --namespace=default
{"level":"info","ts":1537598131.6718707,"logger":"kubebuilder.controller","caller":"controller/controller.go:120","msg":"Starting EventSource","Controller":"node-controller","Source":{"Type":{"metadata":{"creationTimestamp":null},"spec":{},"status":{"daemonEndpoints":{"kubeletEndpoint":{"Port":0}},"nodeInfo":{"machineID":"","systemUUID":"","bootID":"","kernelVersion":"","osImage":"","containerRuntimeVersion":"","kubeletVersion":"","kubeProxyVersion":"","operatingSystem":"","architecture":""}}}}}
E0921 23:35:31.674413 15574 reflector.go:205] sigs.k8s.io/controller-runtime/pkg/cache/internal/informers_map.go:126: Failed to list *v1.Node: the server could not find the requested resource
E0921 23:35:32.680154 15574 reflector.go:205] sigs.k8s.io/controller-runtime/pkg/cache/internal/informers_map.go:126: Failed to list *v1.Node: the server could not find the requested resourceAs expected the ListWatcher fails to List the nodes because when the namespace is set it will form an incorrect request to list Nodes by adding the namespace in the REST path.
https://github.com/kubernetes-sigs/controller-runtime/pull/136/files#diff-fc36bd1640f2ed10bc9e4f4d24789edfR235
The behavior seems consistent with the need for namespacing the manager i.e you don't expect to Watch cluster-scoped resources if your permissions are restricted to a namespace.
I've updated the comment to document this behavior.
b976451 to
495a3d8
Compare
DirectXMan12
left a comment
There was a problem hiding this comment.
realized that we also should check if the resource is namespaced in the first place.
| ListFunc: func(opts metav1.ListOptions) (runtime.Object, error) { | ||
| res := listObj.DeepCopyObject() | ||
| err := client.Get().Resource(mapping.Resource.Resource).VersionedParams(&opts, ip.paramCodec).Do().Into(res) | ||
| err := client.Get().NamespaceIfScoped(ip.namespace, ip.namespace != "").Resource(mapping.Resource.Resource).VersionedParams(&opts, ip.paramCodec).Do().Into(res) |
There was a problem hiding this comment.
it occurs to me that there's one last wrinkle for this -- we need to also check if the resource is namespace-scoped to begin with using the rest mapping -- i.e. you should be able to watch nodes when watching pods in a specific namespace.
There was a problem hiding this comment.
so this should be NamespaceIfScoped(ip.namespace, ip.namespace != "" && mapping.Scope == apimeta.RESTScopeNameRoot)
There was a problem hiding this comment.
and below (in the watch)
There was a problem hiding this comment.
Fixed. Minor nit being it's:
ip.namespace != "" && mapping.Scope != apimeta.RESTScopeNameRoot| // Create a new ListWatch for the obj | ||
| return &cache.ListWatch{ | ||
| ListFunc: func(opts metav1.ListOptions) (runtime.Object, error) { | ||
| if ip.namespace != "" { |
There was a problem hiding this comment.
ditto here on the "is this namespaced"
495a3d8 to
6e82d0f
Compare
A namespace option can be passed from the manager to the cache which restricts the ListWatch for all informers to the desired namespace. This way a manager can be run with a Role instead of a ClusterRole.
6e82d0f to
ca13e86
Compare
|
@DirectXMan12 I've updated the ListWatchers to check if the resource is namespace scoped before making a namespaced request. I've updated the tests with the additional case of ensuring a namespaced cache will still let you List a cluster-scoped resource( |
|
/lgtm |
|
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: DirectXMan12, hasbro17 The full list of commands accepted by this bot can be found here. The pull request process is described here DetailsNeeds approval from an approver in each of these files:
Approvers can indicate their approval by writing |
…rs-namespaced Option to restrict informer cache to a namespace
Use "dep" to import dependencies for generated project
Fixes #124
A namespace option can be passed from the manager to the cache which restricts the ListWatch for all informers to the desired namespace.
This way a manager can be run with a Role instead of a ClusterRole.