Playlists: convert to use reconcilers instead (#98075)

This commit is contained in:
Charandas
2024-12-19 19:09:31 -08:00
committed by GitHub
parent c172bbba50
commit 24bf337c56
12 changed files with 89 additions and 99 deletions
+1 -1
View File
@@ -5,6 +5,7 @@ go 1.23.1
require (
github.com/grafana/grafana-app-sdk v0.23.1
k8s.io/apimachinery v0.31.3
k8s.io/client-go v0.31.3
k8s.io/klog/v2 v2.130.1
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340
)
@@ -75,7 +76,6 @@ require (
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/api v0.31.3 // indirect
k8s.io/apiextensions-apiserver v0.31.3 // indirect
k8s.io/client-go v0.31.3 // indirect
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 // indirect
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
+24 -10
View File
@@ -2,34 +2,48 @@ package app
import (
"context"
"fmt"
"github.com/grafana/grafana-app-sdk/app"
"github.com/grafana/grafana-app-sdk/k8s"
"github.com/grafana/grafana-app-sdk/operator"
"github.com/grafana/grafana-app-sdk/resource"
"github.com/grafana/grafana-app-sdk/simple"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/client-go/rest"
"k8s.io/klog/v2"
"github.com/grafana/grafana/apps/playlist/pkg/reconcilers"
playlistv0alpha1 "github.com/grafana/grafana/apps/playlist/pkg/apis/playlist/v0alpha1"
"github.com/grafana/grafana/apps/playlist/pkg/watchers"
)
type PlaylistConfig struct {
EnableWatchers bool
EnableReconcilers bool
}
func getPatchClient(restConfig rest.Config, playlistKind resource.Kind) (operator.PatchClient, error) {
clientGenerator := k8s.NewClientRegistry(restConfig, k8s.ClientConfig{})
return clientGenerator.ClientFor(playlistKind)
}
func New(cfg app.Config) (app.App, error) {
var (
playlistWatcher operator.ResourceWatcher
err error
playlistReconciler operator.Reconciler
err error
)
playlistConfig, ok := cfg.SpecificConfig.(*PlaylistConfig)
if ok && playlistConfig.EnableWatchers {
playlistWatcher, err = watchers.NewPlaylistWatcher()
if ok && playlistConfig.EnableReconcilers {
patchClient, err := getPatchClient(cfg.KubeConfig, playlistv0alpha1.PlaylistKind())
if err != nil {
return nil, fmt.Errorf("unable to create PlaylistWatcher: %w", err)
klog.ErrorS(err, "Error getting patch client for use with opinionated reconciler")
return nil, err
}
playlistReconciler, err = reconcilers.NewPlaylistReconciler(patchClient)
if err != nil {
klog.ErrorS(err, "Error creating playlist reconciler")
return nil, err
}
}
@@ -43,8 +57,8 @@ func New(cfg app.Config) (app.App, error) {
},
ManagedKinds: []simple.AppManagedKind{
{
Kind: playlistv0alpha1.PlaylistKind(),
Watcher: playlistWatcher,
Kind: playlistv0alpha1.PlaylistKind(),
Reconciler: playlistReconciler,
Mutator: &simple.Mutator{
MutateFunc: func(ctx context.Context, req *app.AdmissionRequest) (*app.MutatingResponse, error) {
// modify req.Object if needed
@@ -0,0 +1,46 @@
package reconcilers
import (
"context"
"k8s.io/klog/v2"
"github.com/grafana/grafana-app-sdk/operator"
playlist "github.com/grafana/grafana/apps/playlist/pkg/apis/playlist/v0alpha1"
)
func NewPlaylistReconciler(patchClient operator.PatchClient) (operator.Reconciler, error) {
inner := operator.TypedReconciler[*playlist.Playlist]{}
inner.ReconcileFunc = func(ctx context.Context, request operator.TypedReconcileRequest[*playlist.Playlist]) (operator.ReconcileResult, error) {
switch request.Action {
case operator.ReconcileActionCreated:
klog.InfoS("Added resource", "name", request.Object.GetStaticMetadata().Identifier().Name)
return operator.ReconcileResult{}, nil
case operator.ReconcileActionUpdated:
klog.InfoS("Updated resource", "name", request.Object.GetStaticMetadata().Identifier().Name)
return operator.ReconcileResult{}, nil
case operator.ReconcileActionDeleted:
klog.InfoS("Deleted resource", "name", request.Object.GetStaticMetadata().Identifier().Name)
return operator.ReconcileResult{}, nil
case operator.ReconcileActionResynced:
klog.InfoS("Possibly updated resource", "name", request.Object.GetStaticMetadata().Identifier().Name)
return operator.ReconcileResult{}, nil
case operator.ReconcileActionUnknown:
klog.InfoS("error reconciling unknown action for Playlist", "action", request.Action, "object", request.Object)
return operator.ReconcileResult{}, nil
}
klog.InfoS("error reconciling invalid action for Playlist", "action", request.Action, "object", request.Object)
return operator.ReconcileResult{}, nil
}
// prefixing the finalizer with <group>-<kind> similar to how OpinionatedWatcher does
reconciler, err := operator.NewOpinionatedReconciler(patchClient, "playlist-playlists-finalizer")
if err != nil {
klog.ErrorS(err, "Error creating opinionated reconciler for playlists")
return nil, err
}
reconciler.Reconciler = &inner
return reconciler, nil
}
@@ -1,75 +0,0 @@
package watchers
import (
"context"
"fmt"
"github.com/grafana/grafana-app-sdk/operator"
"github.com/grafana/grafana-app-sdk/resource"
"k8s.io/klog/v2"
playlist "github.com/grafana/grafana/apps/playlist/pkg/apis/playlist/v0alpha1"
)
var _ operator.ResourceWatcher = &PlaylistWatcher{}
type PlaylistWatcher struct{}
func NewPlaylistWatcher() (*PlaylistWatcher, error) {
return &PlaylistWatcher{}, nil
}
// Add handles add events for playlist.Playlist resources.
func (s *PlaylistWatcher) Add(ctx context.Context, rObj resource.Object) error {
object, ok := rObj.(*playlist.Playlist)
if !ok {
return fmt.Errorf("provided object is not of type *playlist.Playlist (name=%s, namespace=%s, kind=%s)",
rObj.GetStaticMetadata().Name, rObj.GetStaticMetadata().Namespace, rObj.GetStaticMetadata().Kind)
}
klog.InfoS("Added resource", "name", object.GetStaticMetadata().Identifier().Name)
return nil
}
// Update handles update events for playlist.Playlist resources.
func (s *PlaylistWatcher) Update(ctx context.Context, rOld resource.Object, rNew resource.Object) error {
oldObject, ok := rOld.(*playlist.Playlist)
if !ok {
return fmt.Errorf("provided object is not of type *playlist.Playlist (name=%s, namespace=%s, kind=%s)",
rOld.GetStaticMetadata().Name, rOld.GetStaticMetadata().Namespace, rOld.GetStaticMetadata().Kind)
}
_, ok = rNew.(*playlist.Playlist)
if !ok {
return fmt.Errorf("provided object is not of type *playlist.Playlist (name=%s, namespace=%s, kind=%s)",
rNew.GetStaticMetadata().Name, rNew.GetStaticMetadata().Namespace, rNew.GetStaticMetadata().Kind)
}
klog.InfoS("Updated resource", "name", oldObject.GetStaticMetadata().Identifier().Name)
return nil
}
// Delete handles delete events for playlist.Playlist resources.
func (s *PlaylistWatcher) Delete(ctx context.Context, rObj resource.Object) error {
object, ok := rObj.(*playlist.Playlist)
if !ok {
return fmt.Errorf("provided object is not of type *playlist.Playlist (name=%s, namespace=%s, kind=%s)",
rObj.GetStaticMetadata().Name, rObj.GetStaticMetadata().Namespace, rObj.GetStaticMetadata().Kind)
}
klog.InfoS("Deleted resource", "name", object.GetStaticMetadata().Identifier().Name)
return nil
}
// Sync is not a standard resource.Watcher function, but is used when wrapping this watcher in an operator.OpinionatedWatcher.
// It handles resources which MAY have been updated during an outage period where the watcher was not able to consume events.
func (s *PlaylistWatcher) Sync(ctx context.Context, rObj resource.Object) error {
object, ok := rObj.(*playlist.Playlist)
if !ok {
return fmt.Errorf("provided object is not of type *playlist.Playlist (name=%s, namespace=%s, kind=%s)",
rObj.GetStaticMetadata().Name, rObj.GetStaticMetadata().Namespace, rObj.GetStaticMetadata().Kind)
}
klog.InfoS("Possible resource update", "name", object.GetStaticMetadata().Identifier().Name)
return nil
}