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  }