github.com/tilt-dev/tilt@v0.33.15-0.20240515162809-0a22ed45d8a0/internal/hud/view/view.go (about)

     1  package view
     2  
     3  import (
     4  	"strings"
     5  	"time"
     6  
     7  	"github.com/tilt-dev/tilt/internal/container"
     8  	"github.com/tilt-dev/tilt/pkg/apis/core/v1alpha1"
     9  	"github.com/tilt-dev/tilt/pkg/model"
    10  	"github.com/tilt-dev/tilt/pkg/model/logstore"
    11  )
    12  
    13  const LogLineCount = 50
    14  
    15  const TiltfileResourceName = "(Tiltfile)"
    16  
    17  type ResourceInfoView interface {
    18  	resourceInfoView()
    19  	RuntimeSpanID() logstore.SpanID
    20  	RuntimeStatus() v1alpha1.RuntimeStatus
    21  	Status() string
    22  }
    23  
    24  type DCResourceInfo struct {
    25  	ContainerStatus string
    26  	ContainerID     container.ID
    27  	SpanID          logstore.SpanID
    28  	StartTime       time.Time
    29  	RunStatus       v1alpha1.RuntimeStatus
    30  }
    31  
    32  func NewDCResourceInfo(status string, cID container.ID, spanID logstore.SpanID, startTime time.Time, runtimeStatus v1alpha1.RuntimeStatus) DCResourceInfo {
    33  	return DCResourceInfo{
    34  		ContainerStatus: status,
    35  		ContainerID:     cID,
    36  		SpanID:          spanID,
    37  		StartTime:       startTime,
    38  		RunStatus:       runtimeStatus,
    39  	}
    40  }
    41  
    42  var _ ResourceInfoView = DCResourceInfo{}
    43  
    44  func (DCResourceInfo) resourceInfoView()                     {}
    45  func (dcInfo DCResourceInfo) RuntimeSpanID() logstore.SpanID { return dcInfo.SpanID }
    46  func (dcInfo DCResourceInfo) Status() string {
    47  	return strings.Title(dcInfo.ContainerStatus)
    48  }
    49  func (dcInfo DCResourceInfo) RuntimeStatus() v1alpha1.RuntimeStatus { return dcInfo.RunStatus }
    50  
    51  type K8sResourceInfo struct {
    52  	PodName            string
    53  	PodCreationTime    time.Time
    54  	PodUpdateStartTime time.Time
    55  	PodStatus          string
    56  	PodRestarts        int
    57  	SpanID             logstore.SpanID
    58  	RunStatus          v1alpha1.RuntimeStatus
    59  	DisplayNames       []string
    60  }
    61  
    62  var _ ResourceInfoView = K8sResourceInfo{}
    63  
    64  func (K8sResourceInfo) resourceInfoView()                             {}
    65  func (k8sInfo K8sResourceInfo) RuntimeSpanID() logstore.SpanID        { return k8sInfo.SpanID }
    66  func (k8sInfo K8sResourceInfo) Status() string                        { return k8sInfo.PodStatus }
    67  func (k8sInfo K8sResourceInfo) RuntimeStatus() v1alpha1.RuntimeStatus { return k8sInfo.RunStatus }
    68  
    69  // This TiltfileResourceInfo is consistent with how the web UI models the tiltfile.
    70  type TiltfileResourceInfo struct {
    71  }
    72  
    73  var _ ResourceInfoView = TiltfileResourceInfo{}
    74  
    75  func (TiltfileResourceInfo) resourceInfoView()              {}
    76  func (TiltfileResourceInfo) RuntimeSpanID() logstore.SpanID { return "unknown" }
    77  func (TiltfileResourceInfo) Status() string                 { return "" }
    78  func (TiltfileResourceInfo) RuntimeStatus() v1alpha1.RuntimeStatus {
    79  	return v1alpha1.RuntimeStatusNotApplicable
    80  }
    81  
    82  type YAMLResourceInfo struct {
    83  	K8sDisplayNames []string
    84  }
    85  
    86  var _ ResourceInfoView = YAMLResourceInfo{}
    87  
    88  func (YAMLResourceInfo) resourceInfoView()                       {}
    89  func (yamlInfo YAMLResourceInfo) RuntimeSpanID() logstore.SpanID { return "unknown" }
    90  func (yamlInfo YAMLResourceInfo) Status() string                 { return "" }
    91  func (yamlInfo YAMLResourceInfo) RuntimeStatus() v1alpha1.RuntimeStatus {
    92  	return v1alpha1.RuntimeStatusNotApplicable
    93  }
    94  
    95  type LocalResourceInfo struct {
    96  	status v1alpha1.RuntimeStatus
    97  	pid    int
    98  	spanID model.LogSpanID
    99  }
   100  
   101  func NewLocalResourceInfo(status v1alpha1.RuntimeStatus, pid int, spanID model.LogSpanID) LocalResourceInfo {
   102  	return LocalResourceInfo{status: status, pid: pid, spanID: spanID}
   103  }
   104  
   105  var _ ResourceInfoView = LocalResourceInfo{}
   106  
   107  func (lri LocalResourceInfo) resourceInfoView()                     {}
   108  func (lri LocalResourceInfo) RuntimeSpanID() logstore.SpanID        { return lri.spanID }
   109  func (lri LocalResourceInfo) Status() string                        { return string(lri.status) }
   110  func (lri LocalResourceInfo) RuntimeStatus() v1alpha1.RuntimeStatus { return lri.status }
   111  
   112  type Resource struct {
   113  	Name           model.ManifestName
   114  	LastDeployTime time.Time
   115  	TriggerMode    model.TriggerMode
   116  
   117  	BuildHistory []model.BuildRecord
   118  	CurrentBuild model.BuildRecord
   119  
   120  	PendingBuildReason model.BuildReason
   121  	PendingBuildEdits  []string
   122  	PendingBuildSince  time.Time
   123  
   124  	Endpoints []string
   125  
   126  	ResourceInfo ResourceInfoView
   127  
   128  	IsTiltfile bool
   129  }
   130  
   131  func (r Resource) DockerComposeTarget() DCResourceInfo {
   132  	switch info := r.ResourceInfo.(type) {
   133  	case DCResourceInfo:
   134  		return info
   135  	default:
   136  		return DCResourceInfo{}
   137  	}
   138  }
   139  
   140  func (r Resource) DCInfo() DCResourceInfo {
   141  	ret, _ := r.ResourceInfo.(DCResourceInfo)
   142  	return ret
   143  }
   144  
   145  func (r Resource) IsDC() bool {
   146  	_, ok := r.ResourceInfo.(DCResourceInfo)
   147  	return ok
   148  }
   149  
   150  func (r Resource) K8sInfo() K8sResourceInfo {
   151  	ret, _ := r.ResourceInfo.(K8sResourceInfo)
   152  	return ret
   153  }
   154  
   155  func (r Resource) IsK8s() bool {
   156  	_, ok := r.ResourceInfo.(K8sResourceInfo)
   157  	return ok
   158  }
   159  
   160  func (r Resource) YAMLInfo() YAMLResourceInfo {
   161  	ret, _ := r.ResourceInfo.(YAMLResourceInfo)
   162  	return ret
   163  }
   164  
   165  func (r Resource) IsYAML() bool {
   166  	_, ok := r.ResourceInfo.(YAMLResourceInfo)
   167  	return ok
   168  }
   169  
   170  func (r Resource) LastBuild() model.BuildRecord {
   171  	if len(r.BuildHistory) == 0 {
   172  		return model.BuildRecord{}
   173  	}
   174  	return r.BuildHistory[0]
   175  }
   176  
   177  func (r Resource) DefaultCollapse() bool {
   178  	autoExpand := false
   179  	if k8sInfo, ok := r.ResourceInfo.(K8sResourceInfo); ok {
   180  		autoExpand = k8sInfo.PodRestarts > 0 || k8sInfo.PodStatus == "CrashLoopBackOff" || k8sInfo.PodStatus == "Error"
   181  	}
   182  
   183  	if r.IsDC() && r.DockerComposeTarget().RuntimeStatus() == v1alpha1.RuntimeStatusError {
   184  		autoExpand = true
   185  	}
   186  
   187  	autoExpand = autoExpand ||
   188  		r.LastBuild().Error != nil ||
   189  		r.LastBuild().WarningCount > 0
   190  	return !autoExpand
   191  }
   192  
   193  func (r Resource) IsCollapsed(rv ResourceViewState) bool {
   194  	return rv.CollapseState.IsCollapsed(r.DefaultCollapse())
   195  }
   196  
   197  // Snapshot of the current view that's not expressed in the underlying model state.
   198  //
   199  // This includes things like the current selection, warning messages,
   200  // narration messages, etc.
   201  //
   202  // Client should always hold this as a value struct, and copy it
   203  // whenever they need to mutate something.
   204  type View struct {
   205  	LogReader  logstore.Reader
   206  	Resources  []Resource
   207  	FatalError error
   208  }
   209  
   210  func (v View) TiltfileErrorMessage() string {
   211  	for _, res := range v.Resources {
   212  		if res.Name == TiltfileResourceName {
   213  			err := res.LastBuild().Error
   214  			if err != nil {
   215  				return err.Error()
   216  			}
   217  			return ""
   218  		}
   219  	}
   220  	return ""
   221  }
   222  
   223  func (v View) Resource(n model.ManifestName) (Resource, bool) {
   224  	for _, res := range v.Resources {
   225  		if res.Name == n {
   226  			return res, true
   227  		}
   228  	}
   229  	return Resource{}, false
   230  }
   231  
   232  type ViewState struct {
   233  	ShowNarration    bool
   234  	NarrationMessage string
   235  	Resources        []ResourceViewState
   236  	ProcessedLogs    logstore.Checkpoint
   237  	AlertMessage     string
   238  	TabState         TabState
   239  	SelectedIndex    int
   240  	TiltLogState     TiltLogState
   241  }
   242  
   243  type TabState int
   244  
   245  const (
   246  	TabAllLog TabState = iota
   247  	TabBuildLog
   248  	TabRuntimeLog
   249  )
   250  
   251  type CollapseState int
   252  
   253  const (
   254  	CollapseAuto = iota
   255  	CollapseYes
   256  	CollapseNo
   257  )
   258  
   259  func (c CollapseState) IsCollapsed(defaultCollapse bool) bool {
   260  	switch c {
   261  	case CollapseYes:
   262  		return true
   263  	case CollapseNo:
   264  		return false
   265  	default: // CollapseAuto
   266  		return defaultCollapse
   267  	}
   268  }
   269  
   270  func (vs *ViewState) CycleViewLogState() {
   271  	states := []TiltLogState{TiltLogShort, TiltLogHalfScreen, TiltLogFullScreen}
   272  	for i := range states {
   273  		if states[i] == vs.TiltLogState {
   274  			vs.TiltLogState = states[(i+1)%len(states)]
   275  			return
   276  		}
   277  	}
   278  	vs.TiltLogState = TiltLogFullScreen
   279  }
   280  
   281  type TiltLogState int
   282  
   283  const (
   284  	TiltLogShort TiltLogState = iota
   285  	TiltLogHalfScreen
   286  	TiltLogFullScreen
   287  )
   288  
   289  type ResourceViewState struct {
   290  	CollapseState CollapseState
   291  }