-
Notifications
You must be signed in to change notification settings - Fork 135
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[YUNIKORN-2625] Refactor Clients to avoid hard-code checks #844
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -27,13 +27,41 @@ | |
coreInformerV1 "k8s.io/client-go/informers/core/v1" | ||
schedulingInformerV1 "k8s.io/client-go/informers/scheduling/v1" | ||
storageInformerV1 "k8s.io/client-go/informers/storage/v1" | ||
"k8s.io/client-go/tools/cache" | ||
"k8s.io/klog/v2" | ||
"k8s.io/kubernetes/pkg/scheduler/framework/plugins/volumebinding" | ||
|
||
"github.com/apache/yunikorn-k8shim/pkg/conf" | ||
"github.com/apache/yunikorn-k8shim/pkg/log" | ||
"github.com/apache/yunikorn-scheduler-interface/lib/go/api" | ||
) | ||
|
||
var informerTypes = [...]string{"Pod", "Node", "ConfigMap", "Storage", "PV", "PVC", "PriorityClass", "Namespaces", "CSINode", "CSIDrivers", "CSIStorageCapacity"} | ||
|
||
type InformerType int | ||
|
||
func (t InformerType) String() string { | ||
return informerTypes[t] | ||
} | ||
|
||
const ( | ||
PodInformerHandlers InformerType = iota | ||
NodeInformerHandlers | ||
ConfigMapInformerHandlers | ||
StorageInformerHandlers | ||
PVInformerHandlers | ||
PVCInformerHandlers | ||
PriorityClassInformerHandlers | ||
NamespacesInformerHandlers | ||
CSINodeInformerHandlers | ||
CSIDriversInformerHandlers | ||
CSIStorageCapacityInformerHandlers | ||
) | ||
|
||
type hasInformer interface { | ||
Informer() cache.SharedIndexInformer | ||
} | ||
|
||
// clients encapsulates a set of useful client APIs | ||
// that can be shared by callers when talking to K8s api-server, | ||
// or the scheduler core. | ||
|
@@ -49,6 +77,7 @@ | |
InformerFactory informers.SharedInformerFactory | ||
|
||
// resource informers | ||
hasInformers []hasInformer | ||
PodInformer coreInformerV1.PodInformer | ||
NodeInformer coreInformerV1.NodeInformer | ||
ConfigMapInformer coreInformerV1.ConfigMapInformer | ||
|
@@ -63,42 +92,96 @@ | |
VolumeBinder volumebinding.SchedulerVolumeBinder | ||
} | ||
|
||
func NewClients(scheduler api.SchedulerAPI, informerFactory informers.SharedInformerFactory, configs *conf.SchedulerConf, kubeClient KubeClient) *Clients { | ||
// init informers | ||
// volume informers are also used to get the Listers for the predicates | ||
hasInformers := []hasInformer{} | ||
|
||
podInformer := save(informerFactory.Core().V1().Pods(), &hasInformers) | ||
nodeInformer := save(informerFactory.Core().V1().Nodes(), &hasInformers) | ||
configMapInformer := save(informerFactory.Core().V1().ConfigMaps(), &hasInformers) | ||
storageInformer := save(informerFactory.Storage().V1().StorageClasses(), &hasInformers) | ||
pvInformer := save(informerFactory.Core().V1().PersistentVolumes(), &hasInformers) | ||
pvcInformer := save(informerFactory.Core().V1().PersistentVolumeClaims(), &hasInformers) | ||
priorityClassInformer := save(informerFactory.Scheduling().V1().PriorityClasses(), &hasInformers) | ||
namespaceInformer := save(informerFactory.Core().V1().Namespaces(), &hasInformers) | ||
csiNodeInformer := save(informerFactory.Storage().V1().CSINodes(), &hasInformers) | ||
csiDriversInformer := save(informerFactory.Storage().V1().CSIDrivers(), &hasInformers) | ||
csiStorageCapacityInformer := save(informerFactory.Storage().V1().CSIStorageCapacities(), &hasInformers) | ||
Comment on lines
+98
to
+110
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Honestly, I don't know. We do save some lines by introducing this intermediate type, at the same, readability is not the best. In fact, I had to download and apply the patch locally to understand what's happening here. For example, even though this is more LOC, it's just much simpler:
Then There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
yep, that is a good idea. However, the previous discussion (#844 (comment)) seems to want a style of avoid ignoring the Let me summary the requests:
I agree to @wilfred-s said "Not sure how we do that without manual work" - Maybe we should let this PR go and focus on adding missed |
||
|
||
var capacityCheck = volumebinding.CapacityCheck{ | ||
CSIDriverInformer: csiDriversInformer, | ||
CSIStorageCapacityInformer: csiStorageCapacityInformer, | ||
} | ||
|
||
// create a volume binder (needs the informers) | ||
volumeBinder := volumebinding.NewVolumeBinder( | ||
klog.NewKlogr(), | ||
kubeClient.GetClientSet(), | ||
podInformer, | ||
nodeInformer, | ||
csiNodeInformer, | ||
pvcInformer, | ||
pvInformer, | ||
storageInformer, | ||
capacityCheck, | ||
configs.VolumeBindTimeout, | ||
) | ||
|
||
return &Clients{ | ||
conf: configs, | ||
KubeClient: kubeClient, | ||
SchedulerAPI: scheduler, | ||
InformerFactory: informerFactory, | ||
hasInformers: hasInformers, | ||
PodInformer: podInformer, | ||
NodeInformer: nodeInformer, | ||
ConfigMapInformer: configMapInformer, | ||
PVInformer: pvInformer, | ||
PVCInformer: pvcInformer, | ||
NamespaceInformer: namespaceInformer, | ||
StorageInformer: storageInformer, | ||
CSINodeInformer: csiNodeInformer, | ||
PriorityClassInformer: priorityClassInformer, | ||
VolumeBinder: volumeBinder, | ||
} | ||
} | ||
|
||
func save[T hasInformer](n T, collector *[]hasInformer) T { | ||
*collector = append(*collector, n) | ||
return n | ||
} | ||
|
||
func (c *Clients) GetConf() *conf.SchedulerConf { | ||
return c.conf | ||
} | ||
|
||
func (c *Clients) getInformers() []cache.SharedIndexInformer { | ||
informers := make([]cache.SharedIndexInformer, len(c.hasInformers)) | ||
for i, informer := range c.hasInformers { | ||
informers[i] = informer.Informer() | ||
} | ||
return informers | ||
} | ||
|
||
func (c *Clients) WaitForSync() { | ||
syncStartTime := time.Now() | ||
counter := 0 | ||
for { | ||
if c.NodeInformer.Informer().HasSynced() && | ||
c.PodInformer.Informer().HasSynced() && | ||
c.PVCInformer.Informer().HasSynced() && | ||
c.PVInformer.Informer().HasSynced() && | ||
c.StorageInformer.Informer().HasSynced() && | ||
c.CSINodeInformer.Informer().HasSynced() && | ||
c.ConfigMapInformer.Informer().HasSynced() && | ||
c.NamespaceInformer.Informer().HasSynced() && | ||
c.PriorityClassInformer.Informer().HasSynced() { | ||
return | ||
} | ||
time.Sleep(time.Second) | ||
counter++ | ||
if counter%10 == 0 { | ||
log.Log(log.ShimClient).Info("Waiting for informers to sync", | ||
zap.Duration("timeElapsed", time.Since(syncStartTime).Round(time.Second))) | ||
|
||
for _, informer := range c.getInformers() { | ||
for !informer.HasSynced() { | ||
time.Sleep(time.Second) | ||
counter++ | ||
if counter%10 == 0 { | ||
log.Log(log.ShimClient).Info("Waiting for informers to sync", | ||
zap.Duration("timeElapsed", time.Since(syncStartTime).Round(time.Second))) | ||
} | ||
} | ||
} | ||
} | ||
|
||
func (c *Clients) Run(stopCh <-chan struct{}) { | ||
go c.NodeInformer.Informer().Run(stopCh) | ||
go c.PodInformer.Informer().Run(stopCh) | ||
go c.PVInformer.Informer().Run(stopCh) | ||
go c.PVCInformer.Informer().Run(stopCh) | ||
go c.StorageInformer.Informer().Run(stopCh) | ||
go c.CSINodeInformer.Informer().Run(stopCh) | ||
go c.ConfigMapInformer.Informer().Run(stopCh) | ||
go c.NamespaceInformer.Informer().Run(stopCh) | ||
go c.PriorityClassInformer.Informer().Run(stopCh) | ||
for _, informer := range c.getInformers() { | ||
go informer.Run(stopCh) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was this changed to avoid confusion with
type
?