diff --git a/cmd/app/options/options.go b/cmd/app/options/options.go index a35153f..e5bfcb8 100644 --- a/cmd/app/options/options.go +++ b/cmd/app/options/options.go @@ -1,7 +1,10 @@ package options import ( + "strings" + "github.com/spf13/pflag" + "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/component-base/cli/globalflag" "k8s.io/klog/v2" "sigs.k8s.io/controller-runtime/pkg/metrics" @@ -38,6 +41,8 @@ type Options struct { KubeAPIQPS float32 // KubeAPIBurst is the burst to allow while talking with kube-apiserver. KubeAPIBurst int + // PreCacheResources is a list of resources name to pre-cache when start up. + PreCacheResources string } // NewOptions builds an empty options. @@ -58,6 +63,8 @@ func (o *Options) AddFlags(flags *pflag.FlagSet) { flags.StringVar(&o.TLSMinVersion, "tls-min-version", defaultTLSMinVersion, "Minimum TLS version supported. Possible values: 1.0, 1.1, 1.2, 1.3.") flags.Float32Var(&o.KubeAPIQPS, "kube-api-qps", 40.0, "QPS to use while talking with kube-apiserver. Doesn't cover events and node heartbeat apis which rate limiting is controlled by a different set of flags.") flags.IntVar(&o.KubeAPIBurst, "kube-api-burst", 60, "Burst to use while talking with kube-apiserver. Doesn't cover events and node heartbeat apis which rate limiting is controlled by a different set of flags.") + flags.StringVar(&o.PreCacheResources, "pre-cache-resources", "Deployment/apps/v1,Replicas/apps/v1", "Resources list separate by comma, for example: Pod/v1,Deployment/apps/v1"+ + ". Will pre cache those resources to get it quicker when policies refer resources from cluster.") globalflag.AddGlobalFlags(flags, "global") } @@ -68,3 +75,32 @@ func PrintFlags(flags *pflag.FlagSet) { klog.Infof("FLAG: --%s=%q", flag.Name, flag.Value) }) } + +func (o *Options) PreCacheResourcesToGVKList() []schema.GroupVersionKind { + var ( + resourceList = strings.Split(o.PreCacheResources, ",") + gvkList = make([]schema.GroupVersionKind, 0, len(resourceList)) + ) + + for _, resource := range resourceList { + items := strings.Split(resource, "/") + if len(items) <= 1 { + // ignore it + continue + } + + gvk := schema.GroupVersionKind{ + Kind: items[0], + Version: items[1], + } + + if len(items) == 3 { + gvk.Group = items[1] + gvk.Version = items[2] + } + + gvkList = append(gvkList, gvk) + } + + return gvkList +} diff --git a/cmd/app/options/options_test.go b/cmd/app/options/options_test.go new file mode 100644 index 0000000..8d9e149 --- /dev/null +++ b/cmd/app/options/options_test.go @@ -0,0 +1,60 @@ +package options + +import ( + "reflect" + "testing" + + "k8s.io/apimachinery/pkg/runtime/schema" +) + +func TestOptions_PreCacheResourcesToGVKList(t *testing.T) { + type fields struct { + PreCacheResources string + } + tests := []struct { + name string + fields fields + want []schema.GroupVersionKind + }{ + { + name: "empty", + fields: fields{}, + want: make([]schema.GroupVersionKind, 0), + }, + { + name: "pod", + fields: fields{ + PreCacheResources: "Pod/v1", + }, + want: []schema.GroupVersionKind{ + { + Version: "v1", + Kind: "Pod", + }, + }, + }, + { + name: "Deployment", + fields: fields{ + PreCacheResources: "Pod/apps/v1", + }, + want: []schema.GroupVersionKind{ + { + Group: "apps", + Version: "v1", + Kind: "Pod", + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + o := &Options{ + PreCacheResources: tt.fields.PreCacheResources, + } + if got := o.PreCacheResourcesToGVKList(); !reflect.DeepEqual(got, tt.want) { + t.Errorf("PreCacheResourcesToGVKList() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/cmd/app/webhook.go b/cmd/app/webhook.go index 9066c3b..75a256a 100644 --- a/cmd/app/webhook.go +++ b/cmd/app/webhook.go @@ -107,7 +107,9 @@ func Run(ctx context.Context, opts *options.Options) error { return err } - sm := &setupManager{} + sm := &setupManager{ + opts: opts, + } if err := sm.init(hookManager, ctx.Done()); err != nil { klog.ErrorS(err, "init setup manager failed") return err @@ -167,6 +169,7 @@ func Run(ctx context.Context, opts *options.Options) error { } type setupManager struct { + opts *options.Options hookManager manager.Manager done <-chan struct{} client client.Client @@ -201,20 +204,8 @@ func (s *setupManager) init(hm manager.Manager, done <-chan struct{}) (err error func (s *setupManager) waitForCacheSync(ctx context.Context) error { eg, _ := errgroup.WithContext(ctx) eg.Go(func() error { - err := s.drLister.RegisterNewResource(true, - // pre cached resources - schema.GroupVersionKind{ - Group: "apps", - Version: "v1", - Kind: "Deployment", - }, schema.GroupVersionKind{ - Version: "v1", - Kind: "Pod", - }, schema.GroupVersionKind{ - Group: "apps", - Version: "v1", - Kind: "ReplicaSet", - }) + // pre cached resources + err := s.drLister.RegisterNewResource(true, s.opts.PreCacheResourcesToGVKList()...) if err != nil { klog.ErrorS(err, "failed to register resource to lister") }