github.com/tilt-dev/tilt@v0.33.15-0.20240515162809-0a22ed45d8a0/internal/controllers/core/filewatch/action.go (about)

     1  package filewatch
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"strings"
     7  
     8  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
     9  
    10  	"github.com/tilt-dev/tilt/internal/store"
    11  	"github.com/tilt-dev/tilt/pkg/apis/core/v1alpha1"
    12  	filewatches "github.com/tilt-dev/tilt/pkg/apis/core/v1alpha1"
    13  	"github.com/tilt-dev/tilt/pkg/logger"
    14  	"github.com/tilt-dev/tilt/pkg/model"
    15  )
    16  
    17  type FileWatchUpdateStatusAction struct {
    18  	ObjectMeta *metav1.ObjectMeta
    19  	Status     *filewatches.FileWatchStatus
    20  }
    21  
    22  func (a FileWatchUpdateStatusAction) Summarize(_ *store.ChangeSummary) {
    23  	// do nothing - we only care about _spec_ changes on the summary
    24  }
    25  
    26  func (FileWatchUpdateStatusAction) Action() {}
    27  
    28  func NewFileWatchUpdateStatusAction(fw *filewatches.FileWatch) FileWatchUpdateStatusAction {
    29  	return FileWatchUpdateStatusAction{ObjectMeta: fw.GetObjectMeta().DeepCopy(), Status: fw.Status.DeepCopy()}
    30  }
    31  
    32  func HandleFileWatchUpdateStatusEvent(ctx context.Context, state *store.EngineState, action FileWatchUpdateStatusAction) {
    33  	processFileWatchStatus(ctx, state, action.ObjectMeta, action.Status)
    34  }
    35  
    36  func processFileWatchStatus(ctx context.Context, state *store.EngineState, meta *metav1.ObjectMeta, status *v1alpha1.FileWatchStatus) {
    37  	if status.Error != "" || len(status.FileEvents) == 0 {
    38  		return
    39  	}
    40  
    41  	// since the store is called on EVERY update, can always just look at the last event
    42  	latestEvent := status.FileEvents[len(status.FileEvents)-1]
    43  
    44  	targetID, err := targetID(meta)
    45  	if err != nil {
    46  		logger.Get(ctx).Debugf("Failed to get targetID for FileWatch %q to process update: %v", meta.GetName(), err)
    47  		return
    48  	} else if targetID.Empty() {
    49  		return
    50  	}
    51  
    52  	mns := state.ManifestNamesForTargetID(targetID)
    53  	for _, mn := range mns {
    54  		ms, ok := state.ManifestState(mn)
    55  		if !ok {
    56  			return
    57  		}
    58  
    59  		for _, f := range latestEvent.SeenFiles {
    60  			ms.AddPendingFileChange(targetID, f, latestEvent.Time.Time)
    61  		}
    62  	}
    63  }
    64  
    65  func targetID(metaObj *metav1.ObjectMeta) (model.TargetID, error) {
    66  	labelVal := metaObj.GetAnnotations()[filewatches.AnnotationTargetID]
    67  	if labelVal == "" {
    68  		return model.TargetID{}, nil
    69  	}
    70  	targetParts := strings.SplitN(labelVal, ":", 2)
    71  	if len(targetParts) != 2 || targetParts[0] == "" || targetParts[1] == "" {
    72  		return model.TargetID{}, fmt.Errorf("invalid target ID: %q", labelVal)
    73  	}
    74  	return model.TargetID{Type: model.TargetType(targetParts[0]), Name: model.TargetName(targetParts[1])}, nil
    75  }