github.com/tilt-dev/tilt@v0.33.15-0.20240515162809-0a22ed45d8a0/internal/controllers/core/uibutton/reconciler.go (about) 1 package uibutton 2 3 import ( 4 "context" 5 "fmt" 6 7 apierrors "k8s.io/apimachinery/pkg/api/errors" 8 ctrl "sigs.k8s.io/controller-runtime" 9 "sigs.k8s.io/controller-runtime/pkg/builder" 10 ctrlclient "sigs.k8s.io/controller-runtime/pkg/client" 11 "sigs.k8s.io/controller-runtime/pkg/reconcile" 12 13 "github.com/tilt-dev/tilt/internal/hud/server" 14 "github.com/tilt-dev/tilt/internal/store" 15 "github.com/tilt-dev/tilt/internal/store/uibuttons" 16 "github.com/tilt-dev/tilt/pkg/apis/core/v1alpha1" 17 ) 18 19 type Reconciler struct { 20 client ctrlclient.Client 21 wsList *server.WebsocketList 22 dispatcher store.Dispatcher 23 } 24 25 var _ reconcile.Reconciler = &Reconciler{} 26 27 func NewReconciler(client ctrlclient.Client, wsList *server.WebsocketList, store store.RStore) *Reconciler { 28 return &Reconciler{ 29 client: client, 30 wsList: wsList, 31 dispatcher: store, 32 } 33 } 34 35 func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { 36 button := &v1alpha1.UIButton{} 37 err := r.client.Get(ctx, req.NamespacedName, button) 38 if err != nil && !apierrors.IsNotFound(err) { 39 return ctrl.Result{}, fmt.Errorf("uibutton reconcile: %v", err) 40 } 41 42 if apierrors.IsNotFound(err) || button.ObjectMeta.DeletionTimestamp != nil { 43 r.wsList.ForEach(func(ws *server.WebsocketSubscriber) { 44 ws.SendUIButtonUpdate(ctx, req.NamespacedName, nil) 45 }) 46 47 r.dispatcher.Dispatch(uibuttons.NewUIButtonDeleteAction(req.Name)) 48 49 return ctrl.Result{}, nil 50 } 51 52 // The apiserver is the source of truth, and will ensure the engine state is up to date. 53 r.dispatcher.Dispatch(uibuttons.NewUIButtonUpsertAction(button)) 54 55 // Add an annotation to each button that hashes the spec, 56 // so that we can determine that a button is unique. 57 hash, err := hashUIButtonSpec(button.Spec) 58 if err == nil && hash != button.Annotations[annotationSpecHash] { 59 update := button.DeepCopy() 60 if update.Annotations == nil { 61 update.Annotations = make(map[string]string) 62 } 63 update.Annotations[annotationSpecHash] = hash 64 err := r.client.Update(ctx, update) 65 if err != nil { 66 return ctrl.Result{}, nil 67 } 68 button = update 69 } 70 71 r.wsList.ForEach(func(ws *server.WebsocketSubscriber) { 72 ws.SendUIButtonUpdate(ctx, req.NamespacedName, button) 73 }) 74 75 return ctrl.Result{}, nil 76 } 77 78 func (r *Reconciler) CreateBuilder(mgr ctrl.Manager) (*builder.Builder, error) { 79 b := ctrl.NewControllerManagedBy(mgr). 80 For(&v1alpha1.UIButton{}) 81 82 return b, nil 83 }