Description
Most of the resource entries in internal/config/default_config.go use the singular Kubernetes kind name where the API expects the plural resource name. Kubernetes API paths are keyed by the plural resource, so those informers watch a path that does not exist and never sync anything. The affected resources are silently absent from MeshSync data.
43 of the 71 entries in Pipelines have a singular first segment. The first block (namespaces, configmaps, nodes, secrets, pods, services, deployments, replicasets, statefulsets, daemonsets, ingresses, endpoints, endpointslices, persistentvolumes, persistentvolumeclaims) is correctly plural, and so is every entry in the local whitelist in internal/config/config_local.go (cronjobs.v1.batch, storageclasses.v1.storage.k8s.io, clusterroles.v1.rbac.authorization.k8s.io, volumeattachments.v1.storage.k8s.io, apiservices.v1.apiregistration.k8s.io). The later block in default_config.go is the one that diverges.
The clearest single piece of evidence is that nodes.v1. and node.v1. are both registered, at default_config.go:31 and default_config.go:261. Only the first can work.
Why the singular names cannot work
internal/pipeline/step.go:46 parses the entry and hands the result straight to the dynamic informer, with no RESTMapper and no discovery lookup:
gvr, _ := schema.ParseResourceArg(ri.config.Name)
if gvr == nil { ... }
iclient := ri.informer.ForResource(*gvr)
schema.ParseResourceArg only splits the string, so whatever is written becomes the resource segment of the URL verbatim. Running it over a sample of the current entries:
pods.v1. -> Resource="pods" Version="v1" Group=""
nodes.v1. -> Resource="nodes" Version="v1" Group=""
node.v1. -> Resource="node" Version="v1" Group=""
job.v1.batch -> Resource="job" Version="v1" Group="batch"
event.v1.events.k8s.io -> Resource="event" Version="v1" Group="events.k8s.io"
resourcequota.v1. -> Resource="resourcequota" Version="v1" Group=""
So the job.v1.batch informer lists and watches /apis/batch/v1/job instead of /apis/batch/v1/jobs. Since nothing validates the GVR against server discovery, this fails at list/watch time rather than at startup.
Expected Behavior
Every configured resource is actually watched, or an unusable entry is reported at startup instead of failing quietly.
Impact
Resources that users would reasonably expect MeshSync to discover are missing, including Jobs, Events, ServiceAccounts, Roles, RoleBindings, ClusterRoleBindings, NetworkPolicies, ResourceQuotas, LimitRanges, Leases, HorizontalPodAutoscalers, PodDisruptionBudgets, CustomResourceDefinitions, ControllerRevisions, the CSI resources, and the webhook configurations.
This also explains why Kubernetes Events are absent from MeshSync data today. Worth noting separately: even with the resource name corrected to events.v1.events.k8s.io, ParseList in pkg/model/model_converter.go keeps only the generic object fields, so reason, message / note, regarding and count would still be dropped. Events need a follow-up beyond the rename to be useful.
Suggested fix
The entries fall into four groups, and they want different treatment:
- Real listable resources written in the singular. Pluralize:
job.v1.batch -> jobs.v1.batch, event.v1.events.k8s.io -> events.v1.events.k8s.io, resourcequota.v1. -> resourcequotas.v1., serviceaccount.v1. -> serviceaccounts.v1., networkpolicy.v1.networking.k8s.io -> networkpolicies..., csistoragecapacity... -> csistoragecapacities..., and so on for the rest of the group.
- Non-listable, create-only endpoints that no informer can watch:
tokenreview, tokenrequest, subjectaccessreview, selfsubjectaccessreview, selfsubjectrulesreview, selfsubjectreview, localsubjectaccessreview, binding. These should be removed rather than renamed.
- Entries that are not Kubernetes API resources at all:
container.v1.core, service.apis, volume.v1..
- The duplicate
node.v1. at line 261, superseded by nodes.v1. at line 31.
A guard alongside the data fix would stop this class of problem recurring: resolve each configured entry through discovery or a RESTMapper at startup and log the ones the cluster does not recognise, instead of registering an informer that can never list.
I am happy to send a PR for the renames and removals, and separately for the startup validation, if that split works for you. Wanted to confirm the intended disposition of groups 2 and 3 first, since removing entries changes what a cluster is configured to watch.
Environment:
- Version:
internal/config/default_config.go on master (verified at commit 91420b0)
Description
Most of the resource entries in
internal/config/default_config.gouse the singular Kubernetes kind name where the API expects the plural resource name. Kubernetes API paths are keyed by the plural resource, so those informers watch a path that does not exist and never sync anything. The affected resources are silently absent from MeshSync data.43 of the 71 entries in
Pipelineshave a singular first segment. The first block (namespaces, configmaps, nodes, secrets, pods, services, deployments, replicasets, statefulsets, daemonsets, ingresses, endpoints, endpointslices, persistentvolumes, persistentvolumeclaims) is correctly plural, and so is every entry in the local whitelist ininternal/config/config_local.go(cronjobs.v1.batch,storageclasses.v1.storage.k8s.io,clusterroles.v1.rbac.authorization.k8s.io,volumeattachments.v1.storage.k8s.io,apiservices.v1.apiregistration.k8s.io). The later block indefault_config.gois the one that diverges.The clearest single piece of evidence is that
nodes.v1.andnode.v1.are both registered, atdefault_config.go:31anddefault_config.go:261. Only the first can work.Why the singular names cannot work
internal/pipeline/step.go:46parses the entry and hands the result straight to the dynamic informer, with no RESTMapper and no discovery lookup:schema.ParseResourceArgonly splits the string, so whatever is written becomes the resource segment of the URL verbatim. Running it over a sample of the current entries:So the
job.v1.batchinformer lists and watches/apis/batch/v1/jobinstead of/apis/batch/v1/jobs. Since nothing validates the GVR against server discovery, this fails at list/watch time rather than at startup.Expected Behavior
Every configured resource is actually watched, or an unusable entry is reported at startup instead of failing quietly.
Impact
Resources that users would reasonably expect MeshSync to discover are missing, including Jobs, Events, ServiceAccounts, Roles, RoleBindings, ClusterRoleBindings, NetworkPolicies, ResourceQuotas, LimitRanges, Leases, HorizontalPodAutoscalers, PodDisruptionBudgets, CustomResourceDefinitions, ControllerRevisions, the CSI resources, and the webhook configurations.
This also explains why Kubernetes Events are absent from MeshSync data today. Worth noting separately: even with the resource name corrected to
events.v1.events.k8s.io,ParseListinpkg/model/model_converter.gokeeps only the generic object fields, soreason,message/note,regardingandcountwould still be dropped. Events need a follow-up beyond the rename to be useful.Suggested fix
The entries fall into four groups, and they want different treatment:
job.v1.batch->jobs.v1.batch,event.v1.events.k8s.io->events.v1.events.k8s.io,resourcequota.v1.->resourcequotas.v1.,serviceaccount.v1.->serviceaccounts.v1.,networkpolicy.v1.networking.k8s.io->networkpolicies...,csistoragecapacity...->csistoragecapacities..., and so on for the rest of the group.tokenreview,tokenrequest,subjectaccessreview,selfsubjectaccessreview,selfsubjectrulesreview,selfsubjectreview,localsubjectaccessreview,binding. These should be removed rather than renamed.container.v1.core,service.apis,volume.v1..node.v1.at line 261, superseded bynodes.v1.at line 31.A guard alongside the data fix would stop this class of problem recurring: resolve each configured entry through discovery or a RESTMapper at startup and log the ones the cluster does not recognise, instead of registering an informer that can never list.
I am happy to send a PR for the renames and removals, and separately for the startup validation, if that split works for you. Wanted to confirm the intended disposition of groups 2 and 3 first, since removing entries changes what a cluster is configured to watch.
Environment:
internal/config/default_config.goon master (verified at commit 91420b0)