-
Notifications
You must be signed in to change notification settings - Fork 14
[DLX] Integrate cache and watcher into dlx struct #76
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
Changes from 7 commits
842731f
4ffa9d6
e546acd
6755685
5aa4898
1ca9836
316dd12
abead1c
667935b
adc046b
659d388
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 |
|---|---|---|
|
|
@@ -24,21 +24,28 @@ import ( | |
| "context" | ||
| "net/http" | ||
|
|
||
| "github.com/v3io/scaler/pkg/ingresscache" | ||
| "github.com/v3io/scaler/pkg/kube" | ||
| "github.com/v3io/scaler/pkg/scalertypes" | ||
|
|
||
| "github.com/nuclio/errors" | ||
| "github.com/nuclio/logger" | ||
| "k8s.io/client-go/kubernetes" | ||
| ) | ||
|
|
||
| type DLX struct { | ||
| logger logger.Logger | ||
| handler Handler | ||
| server *http.Server | ||
| cache ingresscache.IngressHostCache | ||
| watcher *kube.IngressWatcher | ||
| } | ||
|
|
||
| func NewDLX(parentLogger logger.Logger, | ||
| resourceScaler scalertypes.ResourceScaler, | ||
| options scalertypes.DLXOptions) (*DLX, error) { | ||
| options scalertypes.DLXOptions, | ||
| kubeClientSet kubernetes.Interface, | ||
| ) (*DLX, error) { | ||
| childLogger := parentLogger.GetChild("dlx") | ||
| childLogger.InfoWith("Creating DLX", | ||
| "options", options) | ||
|
|
@@ -50,6 +57,7 @@ func NewDLX(parentLogger logger.Logger, | |
| return nil, errors.Wrap(err, "Failed to create function starter") | ||
| } | ||
|
|
||
| cache := ingresscache.NewIngressCache(childLogger) | ||
| handler, err := NewHandler(childLogger, | ||
| resourceStarter, | ||
| resourceScaler, | ||
|
|
@@ -61,23 +69,46 @@ func NewDLX(parentLogger logger.Logger, | |
| return nil, errors.Wrap(err, "Failed to create handler") | ||
| } | ||
|
|
||
| watcher, err := kube.NewIngressWatcher( | ||
| context.Background(), | ||
| childLogger, | ||
| kubeClientSet, | ||
| cache, | ||
| options.ResolveTargetsFromIngressCallback, | ||
| options.ResyncInterval, | ||
| options.Namespace, | ||
| options.LabelSelector, | ||
| ) | ||
| if err != nil { | ||
| return nil, errors.Wrap(err, "Failed to create ingress watcher") | ||
| } | ||
|
|
||
| return &DLX{ | ||
| logger: childLogger, | ||
| handler: handler, | ||
| server: &http.Server{ | ||
| Addr: options.ListenAddress, | ||
| }, | ||
| cache: cache, | ||
|
||
| watcher: watcher, | ||
| }, nil | ||
| } | ||
|
|
||
| func (d *DLX) Start() error { | ||
| d.logger.DebugWith("Starting", "server", d.server.Addr) | ||
| http.HandleFunc("/", d.handler.HandleFunc) | ||
|
|
||
| // Start the ingress watcher synchronously to ensure cache is fully synced before DLX begins handling traffic | ||
| if err := d.watcher.Start(); err != nil { | ||
| return errors.Wrap(err, "Failed to start ingress watcher") | ||
| } | ||
|
|
||
| go d.server.ListenAndServe() // nolint: errcheck | ||
| return nil | ||
| } | ||
|
|
||
| func (d *DLX) Stop(context context.Context) error { | ||
| d.logger.DebugWith("Stopping", "server", d.server.Addr) | ||
| d.watcher.Stop() | ||
| return d.server.Shutdown(context) | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -22,9 +22,9 @@ package kube | |||||
|
|
||||||
| import ( | ||||||
| "context" | ||||||
| "time" | ||||||
|
|
||||||
| "github.com/v3io/scaler/pkg/ingresscache" | ||||||
| "github.com/v3io/scaler/pkg/scalertypes" | ||||||
|
|
||||||
| "github.com/nuclio/errors" | ||||||
| "github.com/nuclio/logger" | ||||||
|
|
@@ -35,64 +35,44 @@ import ( | |||||
| "k8s.io/client-go/tools/cache" | ||||||
| ) | ||||||
|
|
||||||
| const ( | ||||||
| defaultResyncInterval = 30 * time.Second | ||||||
| ) | ||||||
|
|
||||||
| // ResolveTargetsFromIngressCallback defines a function that extracts a list of target identifiers | ||||||
| // (e.g., names of services the Ingress routes traffic to) from a Kubernetes Ingress resource. | ||||||
| // | ||||||
| // This function is expected to be implemented externally and passed into the IngressWatcher, | ||||||
| // allowing for custom logic such as parsing annotations, labels, or other ingress metadata. | ||||||
| // | ||||||
| // Parameters: | ||||||
| // - ingress: The Kubernetes Ingress resource to extract targets from | ||||||
| // | ||||||
| // Returns: | ||||||
| // - []string: A slice of target identifiers (e.g., service names, endpoint addresses) | ||||||
| // - error: An error if target resolution fails | ||||||
| // | ||||||
| // Implementation guidelines: | ||||||
| // - Return a non-nil slice when targets are successfully resolved | ||||||
| // - Return a non-nil error if resolution fails | ||||||
| // - Should handle nil or malformed Ingress objects gracefully and return an error in such cases | ||||||
| type ResolveTargetsFromIngressCallback func(ingress *networkingv1.Ingress) ([]string, error) | ||||||
|
|
||||||
| type ingressValue struct { | ||||||
| name string | ||||||
| host string | ||||||
| path string | ||||||
| version string | ||||||
|
||||||
| targets []string | ||||||
| } | ||||||
|
|
||||||
| // IngressWatcher watches for changes in Kubernetes Ingress resources and updates the ingress cache accordingly | ||||||
| type IngressWatcher struct { | ||||||
| ctx context.Context | ||||||
| cancel context.CancelFunc | ||||||
| logger logger.Logger | ||||||
| cache ingresscache.IngressHostCache | ||||||
| factory informers.SharedInformerFactory | ||||||
| informer cache.SharedIndexInformer | ||||||
| resolveTargetsCallback ResolveTargetsFromIngressCallback | ||||||
| resolveTargetsCallback scalertypes.ResolveTargetsFromIngressCallback | ||||||
| } | ||||||
|
|
||||||
| func NewIngressWatcher( | ||||||
| ctx context.Context, | ||||||
| dlxCtx context.Context, | ||||||
| dlxLogger logger.Logger, | ||||||
| kubeClient kubernetes.Interface, | ||||||
| ingressCache ingresscache.IngressCache, | ||||||
| resolveTargetsCallback ResolveTargetsFromIngressCallback, | ||||||
| resyncTimeout *time.Duration, | ||||||
| ingressCache ingresscache.IngressHostCache, | ||||||
| resolveTargetsCallback scalertypes.ResolveTargetsFromIngressCallback, | ||||||
| resyncInterval scalertypes.Duration, | ||||||
| namespace string, | ||||||
| labelSelector string, | ||||||
| ) (*IngressWatcher, error) { | ||||||
| if resyncTimeout == nil { | ||||||
| defaultTimeout := defaultResyncInterval | ||||||
| resyncTimeout = &defaultTimeout | ||||||
| if resyncInterval.Duration == 0 { | ||||||
| resyncInterval = scalertypes.Duration{Duration: scalertypes.DefaultResyncInterval} | ||||||
| } | ||||||
|
|
||||||
| ctx, cancel := context.WithCancel(dlxCtx) | ||||||
|
||||||
| ctx, cancel := context.WithCancel(dlxCtx) | |
| contextWithCancel, cancel := context.WithCancel(dlxCtx) |
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.
Outdated
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.
This will be super spammy - most of the time we won't have changes in the ingress, and with a small resync interval will get 1 log line for every nuclio ingress - could be a very large number.
No need for log here at all.
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.
That's why this log is DEBUG =]
But ok I will remove
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.
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.
why not adding kubeClientSet into options?
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.
I initially assumed that options was meant only for static variables or configuration values.
From your comment, I understand that including runtime dependencies like the Kubernetes client in options is acceptable here—and likely the better practice in this case.
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.
Fixed here - CR comments - move kubeClientSet to dlx.options, avoid tests addition…