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 }