Playlists: convert to use reconcilers instead (#98075)
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
Reference in New Issue
Block a user