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