@@ -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"
@@ -34,6 +36,7 @@ import (
3436 "github.com/jetstack/preflight/api"
3537 "github.com/jetstack/preflight/pkg/client"
3638 "github.com/jetstack/preflight/pkg/datagatherer"
39+ "github.com/jetstack/preflight/pkg/datagatherer/k8s"
3740 "github.com/jetstack/preflight/pkg/kubeconfig"
3841 "github.com/jetstack/preflight/pkg/logs"
3942 "github.com/jetstack/preflight/pkg/version"
@@ -160,11 +163,44 @@ func Run(cmd *cobra.Command, args []string) (returnErr error) {
160163 if err != nil {
161164 return fmt .Errorf ("failed to create event recorder: %v" , err )
162165 }
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+ }
163172
173+ _ , resources , err := discoveryClient .ServerGroupsAndResources ()
174+ if err != nil {
175+ return fmt .Errorf ("failed to get server resources: %v" , err )
176+ }
177+ supported := sets .NewString ()
178+ for _ , r := range resources {
179+ gv , err := schema .ParseGroupVersion (r .GroupVersion )
180+ if err != nil {
181+ log .Error (err , "Failed to parse group version" )
182+ }
183+ for _ , r2 := range r .APIResources {
184+ supported .Insert (gv .WithResource (r2 .Name ).String ())
185+ }
186+ }
187+ log .V (logs .Debug ).Info ("Supported" , "resources" , supported .List ())
164188 dataGatherers := map [string ]datagatherer.DataGatherer {}
165189
166190 // load datagatherer config and boot each one
167191 for _ , dgConfig := range config .DataGatherers {
192+ if c , ok := dgConfig .Config .(* k8s.ConfigDynamic ); ok {
193+ gvr := c .GroupVersionResource
194+ if ! supported .Has (gvr .String ()) {
195+ log .Info (
196+ "Skipping DataGatherer" ,
197+ "name" , dgConfig .Name ,
198+ "reason" , "GroupVersionResource not installed" ,
199+ "groupVersionResource" , gvr ,
200+ )
201+ continue
202+ }
203+ }
168204 kind := dgConfig .Kind
169205 if dgConfig .DataPath != "" {
170206 kind = "local"
@@ -206,17 +242,16 @@ func Run(cmd *cobra.Command, args []string) (returnErr error) {
206242 // too, it will backoff and retry of its own accord. Initial boot
207243 // will only be delayed by a max of 5 seconds.
208244 bootCtx , bootCancel := context .WithTimeout (gctx , 5 * time .Second )
209- defer bootCancel ()
210- for _ , dgConfig := range config .DataGatherers {
211- dg := dataGatherers [dgConfig .Name ]
245+ for dgName , dg := range dataGatherers {
212246 // wait for the informer to complete an initial sync, we do this to
213247 // attempt to have an initial set of data for the first upload of
214248 // the run.
215249 if err := dg .WaitForCacheSync (bootCtx .Done ()); err != nil {
216250 // log sync failure, this might recover in future
217- log .Error (err , "Failed to complete initial sync of DataGatherer" , "kind" , dgConfig . Kind , " name" , dgConfig . Name )
251+ log .Error (err , "Failed to complete initial sync of DataGatherer" , "name" , dgName )
218252 }
219253 }
254+ bootCancel ()
220255
221256 // begin the datagathering loop, periodically sending data to the
222257 // configured output using data in datagatherer caches or refreshing from
0 commit comments