-
Notifications
You must be signed in to change notification settings - Fork 158
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
actions: refactor to move template and manifest rendering in a helper #1563
base: main
Are you sure you want to change the base?
Conversation
Skipping CI for Draft Pull Request. |
/cc @lburgazzoli |
This PR can't be merged just yet 😢Please run For more info: https://github.com/opendatahub-io/opendatahub-operator/actions/runs/12953054333 |
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #1563 +/- ##
==========================================
+ Coverage 19.94% 20.09% +0.14%
==========================================
Files 158 160 +2
Lines 10799 10800 +1
==========================================
+ Hits 2154 2170 +16
+ Misses 8415 8407 -8
+ Partials 230 223 -7 ☔ View full report in Codecov by Sentry. |
"github.com/opendatahub-io/opendatahub-operator/v2/pkg/controller/types" | ||
) | ||
|
||
type Renderer interface { |
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.
type Renderer interface { | |
// Renderer defines an interface for rendering resources. | |
type Renderer interface { |
Render(r Renderer, rr *types.ReconciliationRequest) (any, bool, error) | ||
} | ||
|
||
type CachingKeyFn func(rr *types.ReconciliationRequest) ([]byte, error) |
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.
type CachingKeyFn func(rr *types.ReconciliationRequest) ([]byte, error) | |
// CachingKeyFn is a function type used to generate a caching key based on the reconciliation request. | |
type CachingKeyFn func(rr *types.ReconciliationRequest) ([]byte, error) |
|
||
type CachingKeyFn func(rr *types.ReconciliationRequest) ([]byte, error) | ||
|
||
type Cacher struct { |
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.
type Cacher struct { | |
// Cacher provides caching capabilities for rendered resources. | |
type Cacher struct { |
s.cachingKeyFn = key | ||
} | ||
|
||
func (s *Cacher) InvalidateCache() { |
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.
func (s *Cacher) InvalidateCache() { | |
// InvalidateCache clears the cached key and resources, forcing a re-render on the next invocation. | |
func (s *Cacher) InvalidateCache() { |
|
||
type CacherOpts func(*Cacher) | ||
|
||
func (s *Cacher) SetKey(key CachingKeyFn) { |
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.
func (s *Cacher) SetKey(key CachingKeyFn) { | |
// SetKey sets the caching key function for the Cacher. | |
func (s *Cacher) SetKey(key CachingKeyFn) { |
resList := resources.UnstructuredList(resUnstructured) | ||
|
||
if acted { | ||
controllerName := strings.ToLower(rr.Instance.GetObjectKind().GroupVersionKind().Kind) |
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.
controllerName := strings.ToLower(rr.Instance.GetObjectKind().GroupVersionKind().Kind) | |
// Track the number of rendered resources for monitoring | |
controllerName := strings.ToLower(rr.Instance.GetObjectKind().GroupVersionKind().Kind) |
controllerName := strings.ToLower(rr.Instance.GetObjectKind().GroupVersionKind().Kind) | ||
render.RenderedResourcesTotal.WithLabelValues(controllerName, s.Name()).Add(float64(len(resList))) | ||
|
||
rr.Generated = true |
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.
rr.Generated = true | |
// Mark the reconciliation request as having generated resources | |
rr.Generated = true |
// deep copy object so changes done in the pipelines won't | ||
// alter them |
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.
// deep copy object so changes done in the pipelines won't | |
// alter them | |
// Append cloned resources to the reconciliation request, | |
// ensuring a deep copy so changes in the pipeline don't alter the original objects. |
rr.Resources = append(rr.Resources, result.Clone()...) | ||
|
||
return nil | ||
return res, true, nil | ||
} | ||
|
||
func (a *Action) render(rr *types.ReconciliationRequest) ([]unstructured.Unstructured, error) { |
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.
func (a *Action) render(rr *types.ReconciliationRequest) ([]unstructured.Unstructured, error) { | |
// render handles the rendering of resources using the Kustomize engine. | |
func (a *Action) render(rr *types.ReconciliationRequest) ([]unstructured.Unstructured, error) { |
|
||
rr.Generated = true | ||
func (a *Action) Render(_ cacher.Renderer, rr *types.ReconciliationRequest) (any, bool, error) { |
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.
func (a *Action) Render(_ cacher.Renderer, rr *types.ReconciliationRequest) (any, bool, error) { | |
// Render is a wrapper for rendering the reconciliation request using Kustomize. | |
// It returns the rendered resources and indicates if any resources were acted upon. | |
func (a *Action) Render(_ cacher.Renderer, rr *types.ReconciliationRequest) (any, bool, error) { |
@ykaliuta, I believe the same caching abstraction can be applied to the |
…flux/component-updates/odh-kueue-controller-v2-17 chore(deps): update odh-kueue-controller-v2-17 to 3f5e5f0
f316a77
to
c4f5a74
Compare
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: The full list of commands accepted by this bot can be found here.
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
b3b34ca
to
e9e2fed
Compare
2559e06
to
34bf0d9
Compare
/test all |
34bf0d9
to
b0b8909
Compare
/test opendatahub-operator-e2e |
The caching code for all caching Actions is pretty much the same 1) hash the key 2) if the hash is the same as the stored one, return stored resource 3) otherwise render the resource 4) store the key and the resource 5) return the resource Abstract this logic into Cacher type which is supposed to be included as a composition in on the higher levels. The core engine is implemented as Render method which accepts actual renderer and return boolean value in addition to the resources indicating if it performed rendering. It supposed to be used in resource rendering actions for accounting. Possible usage supposed to be ``` type Action struct { cacher.Cacher // action data } type ActionOpts func(*Action) func WithCache() ActionOpts { return func(a *Action) { a.Cacher.SetKeyFn(types.Hash) // or own } } func (s *Action) run(ctx context.Context, rr *types.ReconciliationRequest) error { //... res, acted, err := a.Cacher.Render(ctx, s.render, rr) if acted { /* may be do something */ } // use resources } func (s *Action) render(ctx context.Context, rr *types.ReconciliationRequest) (any, error) { result := make([]unstructured.Unstructured) // make some resources return result, nil } func NewAction(opts ...ActionOpts) actions.Fn { for _, opt := range opts { opt(&action) } return action.run } ``` with reconciler creation ``` func (s *componentHandler) NewComponentReconciler(ctx context.Context, mgr ctrl.Manager) error { _, err := reconciler.ReconcilerFor( mgr, &componentApi.Type{}, ). // ... WithAction(foobar.NewAction( foobar.WithCache(), )) } ``` Pay attention to signature of render() and call to Cacher.Render() from run(). The code is taken pretty much from the existing kustomize rendering Action. Copy CachingKeyFn type. In future it can be extented to accept context for possible debug logging. Signed-off-by: Yauheni Kaliuta <ykaliuta@redhat.com>
Make an abstract wrapper on the raw cacher.Cacher to work on actions whose Renderer produces resources ([]unstructured.Unstructured) to be recorded into ReconciliationRequest.Manifests and later deployed (deleted) to the cluster. Performs common tasks: - invalidate caching if devflags enabled; - account resources if they were generated (and skip cached ones); - add resources to the ReconciliationRequest. !!! The user should define Name() method for proper accounting. At this moment this is the only part which interested in the origin of resources (cached or not) and it's supposed to be used in actions whose final goal is to add resources to the request (which is done by this helper), so change signature of its Render() method (comparing to cacher.Cacher) to return only error. The code is basically copied from manifest/template rendering actions run() method. Usage (added Name() and changed run() comparing to cacher.Cacher): ``` type Action struct { resourcecacher.ResourceCacher // action data } type ActionOpts func(*Action) func WithCache() ActionOpts { return func(a *Action) { a.ResourceCacher.SetKeyFn(types.Hash) // or own } } func (*Action) Name() string { return "CoolActionName" } func (s *Action) run(ctx context.Context, rr *types.ReconciliationRequest) error { //... return a.ResourceCacher.Render(ctx, s.render, rr) } func (s *Action) render(ctx context.Context, rr *types.ReconciliationRequest) (any, error) { result := make([]unstructured.Unstructured) // make some resources return result, nil } func NewAction(opts ...ActionOpts) actions.Fn { for _, opt := range opts { opt(&action) } return action.run } ``` Signed-off-by: Yauheni Kaliuta <ykaliuta@redhat.com>
Implement Name() method as it is required by the ResourceCacher. All the run() functionality now implemented by the ResourceCacher, so just call its Render() in run(). Amend WithCache() as required by ResourceCacher to set its CachingKeyFn and remove CachingKeyFn initialization from NewAction. Change render() signature to return `any` Signed-off-by: Yauheni Kaliuta <ykaliuta@redhat.com>
The same changes as to manifests rendering. Just keep `data` field initialization in NewAction, used in render(). Signed-off-by: Yauheni Kaliuta <ykaliuta@redhat.com>
b0b8909
to
b26704a
Compare
@ugiordan I added some comments to the update, but I usually do not add obvious comments like |
Jira: https://issues.redhat.com/browse/RHOAIENG-15921
The caching code for all caching Actions is pretty much the same
Abstract this logic into Cacher type which is supposed to be
included as a composition in on the higher levels.
The core engine is implemented as Render method which accepts actual
renderer and return boolean value in addition to the resources
indicating if it performed rendering. It supposed to be used in
resource rendering actions for accounting.
Possible usage supposed to be
with reconciler creation
Pay attention to signature of render() and call to Cacher.Render()
from run().
The code is taken pretty much from the existing kustomize rendering
Action.
Copy CachingKeyFn type. In future it can be extented to accept
context for possible debug logging.
Signed-off-by: Yauheni Kaliuta ykaliuta@redhat.com
Make an abstract wrapper on the raw cacher.Cacher to work on actions
whose Renderer produces resources ([]unstructured.Unstructured) to
be recorded into ReconciliationRequest.Manifests and later
deployed (deleted) to the cluster.
Performs common tasks:
!!! The user should define Name() method for proper accounting.
At this moment this is the only part which interested in the origin
of resources (cached or not) and it's supposed to be used in actions
whose final goal is to add resources to the request (which is done
by this helper), so change signature of its Render()
method (comparing to cacher.Cacher) to return only error.
The code is basically copied from manifest/template rendering
actions run() method.
Usage (added Name() and changed run() comparing to cacher.Cacher):
Signed-off-by: Yauheni Kaliuta ykaliuta@redhat.com
Implement Name() method as it is required by the ResourceCacher.
All the run() functionality now implemented by the ResourceCacher,
so just call its Render() in run().
Amend WithCache() as required by ResourceCacher to set its
CachingKeyFn and remove CachingKeyFn initialization from NewAction.
Change render() signature to return
any
Signed-off-by: Yauheni Kaliuta ykaliuta@redhat.com
The same changes as to manifests rendering.
Signed-off-by: Yauheni Kaliuta ykaliuta@redhat.com
Description
How Has This Been Tested?
Screenshot or short clip
Merge criteria