@@ -24,7 +24,9 @@ import (
2424 corev1 "k8s.io/api/core/v1"
2525 v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2626 "k8s.io/apimachinery/pkg/runtime"
27+ "k8s.io/apimachinery/pkg/runtime/schema"
2728 "k8s.io/apimachinery/pkg/types"
29+ "k8s.io/apimachinery/pkg/util/sets"
2830 "k8s.io/client-go/kubernetes"
2931 clientgocorev1 "k8s.io/client-go/kubernetes/typed/core/v1"
3032 "k8s.io/client-go/tools/record"
@@ -161,11 +163,45 @@ func Run(cmd *cobra.Command, args []string) (returnErr error) {
161163 if err != nil {
162164 return fmt .Errorf ("failed to create event recorder: %v" , err )
163165 }
166+ // Data gatherers are loaded depending on what the Kubernetes API supports.
167+ // First, let's do a /api discovery to see what the API supports.
168+ discoveryClient , err := k8s .NewDiscoveryClient ("" )
169+ if err != nil {
170+ return fmt .Errorf ("failed to create a discovery client: %v" , err )
171+ }
164172
173+ _ , apiResourceLists , err := discoveryClient .ServerGroupsAndResources ()
174+ if err != nil {
175+ return fmt .Errorf ("failed to get server resources: %v" , err )
176+ }
177+ availableGVRs := sets .NewString ()
178+ for _ , arl := range apiResourceLists {
179+ gv , err := schema .ParseGroupVersion (arl .GroupVersion )
180+ if err != nil {
181+ log .Error (err , "Failed to parse group version" )
182+ continue
183+ }
184+ for _ , ar := range arl .APIResources {
185+ availableGVRs .Insert (gv .WithResource (ar .Name ).String ())
186+ }
187+ }
188+ log .V (logs .Debug ).Info ("API discovery complete" , "found" , availableGVRs .List ())
165189 dataGatherers := map [string ]datagatherer.DataGatherer {}
166190
167191 // load datagatherer config and boot each one
168192 for _ , dgConfig := range config .DataGatherers {
193+ if c , ok := dgConfig .Config .(* k8s.ConfigDynamic ); ok {
194+ gvr := c .GroupVersionResource
195+ if ! availableGVRs .Has (gvr .String ()) {
196+ log .Info (
197+ "Skipping DataGatherer" ,
198+ "name" , dgConfig .Name ,
199+ "reason" , "GroupVersionResource not available" ,
200+ "groupVersionResource" , gvr ,
201+ )
202+ continue
203+ }
204+ }
169205 kind := dgConfig .Kind
170206 if dgConfig .DataPath != "" {
171207 kind = "local"
@@ -213,17 +249,16 @@ func Run(cmd *cobra.Command, args []string) (returnErr error) {
213249 // too, it will backoff and retry of its own accord. Initial boot
214250 // will only be delayed by a max of 5 seconds.
215251 bootCtx , bootCancel := context .WithTimeout (gctx , 5 * time .Second )
216- defer bootCancel ()
217- for _ , dgConfig := range config .DataGatherers {
218- dg := dataGatherers [dgConfig .Name ]
252+ for dgName , dg := range dataGatherers {
219253 // wait for the informer to complete an initial sync, we do this to
220254 // attempt to have an initial set of data for the first upload of
221255 // the run.
222256 if err := dg .WaitForCacheSync (bootCtx .Done ()); err != nil {
223257 // log sync failure, this might recover in future
224- log .Error (err , "Failed to complete initial sync of DataGatherer" , "kind" , dgConfig . Kind , " name" , dgConfig . Name )
258+ log .Error (err , "Failed to complete initial sync of DataGatherer" , "name" , dgName )
225259 }
226260 }
261+ bootCancel ()
227262
228263 // begin the datagathering loop, periodically sending data to the
229264 // configured output using data in datagatherer caches or refreshing from
0 commit comments