-
Notifications
You must be signed in to change notification settings - Fork 289
/
runtime_state.go
195 lines (156 loc) · 4.1 KB
/
runtime_state.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
package store
import (
"net/url"
"time"
"github.com/docker/distribution/reference"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/types"
"github.com/windmilleng/tilt/internal/container"
"github.com/windmilleng/tilt/internal/k8s"
"github.com/windmilleng/tilt/pkg/model"
)
type RuntimeState interface {
RuntimeState()
}
// Currently just a placeholder, as a LocalResource has no runtime state, only "build"
// state. In future, we may use this to store runtime state for long-running processes
// kicked off via a LocalResource.
type LocalRuntimeState struct{}
func (LocalRuntimeState) RuntimeState() {}
var _ RuntimeState = LocalRuntimeState{}
type K8sRuntimeState struct {
// The ancestor that we match pods against to associate them with this manifest.
// If we deployed Pod YAML, this will be the Pod UID.
// In many cases, this will be a Deployment UID.
PodAncestorUID types.UID
Pods map[k8s.PodID]*Pod
LBs map[k8s.ServiceName]*url.URL
DeployedUIDSet UIDSet
}
func (K8sRuntimeState) RuntimeState() {}
var _ RuntimeState = K8sRuntimeState{}
func NewK8sRuntimeState(pods ...Pod) K8sRuntimeState {
podMap := make(map[k8s.PodID]*Pod, len(pods))
for _, pod := range pods {
p := pod
podMap[p.PodID] = &p
}
return K8sRuntimeState{
Pods: podMap,
LBs: make(map[k8s.ServiceName]*url.URL),
DeployedUIDSet: NewUIDSet(),
}
}
func (s K8sRuntimeState) PodLen() int {
return len(s.Pods)
}
func (s K8sRuntimeState) ContainsID(id k8s.PodID) bool {
_, ok := s.Pods[id]
return ok
}
func (s K8sRuntimeState) PodList() []Pod {
pods := make([]Pod, 0, len(s.Pods))
for _, pod := range s.Pods {
pods = append(pods, *pod)
}
return pods
}
// Get the "most recent pod" from the K8sRuntimeState.
// For most users, we believe there will be only one pod per manifest.
// So most of this time, this will return the only pod.
// And in other cases, it will return a reasonable, consistent default.
func (s K8sRuntimeState) MostRecentPod() Pod {
bestPod := Pod{}
found := false
for _, v := range s.Pods {
if !found || v.isAfter(bestPod) {
bestPod = *v
found = true
}
}
return bestPod
}
type Pod struct {
PodID k8s.PodID
Namespace k8s.Namespace
StartedAt time.Time
Status string
Phase v1.PodPhase
// Error messages from the pod state if it's in an error state.
StatusMessages []string
// Set when we get ready to replace a pod. We may do the update in-place.
UpdateStartTime time.Time
// If a pod is being deleted, Kubernetes marks it as Running
// until it actually gets removed.
Deleting bool
HasSynclet bool
// The log for the currently active pod, if any
CurrentLog model.Log `testdiff:"ignore"`
Containers []Container
// We want to show the user # of restarts since some baseline time
// i.e. Total Restarts - BaselineRestarts
BaselineRestarts int
}
type Container struct {
Name container.Name
ID container.ID
Ports []int32
Ready bool
ImageRef reference.Named
Restarts int
}
func (c Container) Empty() bool {
return c.Name == "" && c.ID == ""
}
func (p Pod) Empty() bool {
return p.PodID == ""
}
// A stable sort order for pods.
func (p Pod) isAfter(p2 Pod) bool {
if p.StartedAt.After(p2.StartedAt) {
return true
} else if p2.StartedAt.After(p.StartedAt) {
return false
}
return p.PodID > p2.PodID
}
func (p Pod) Log() model.Log {
return p.CurrentLog
}
func (p Pod) AllContainerPorts() []int32 {
result := make([]int32, 0)
for _, c := range p.Containers {
result = append(result, c.Ports...)
}
return result
}
func (p Pod) AllContainersReady() bool {
for _, c := range p.Containers {
if !c.Ready {
return false
}
}
return true
}
func (p Pod) VisibleContainerRestarts() int {
return p.AllContainerRestarts() - p.BaselineRestarts
}
func (p Pod) AllContainerRestarts() int {
result := 0
for _, c := range p.Containers {
result += c.Restarts
}
return result
}
type UIDSet map[types.UID]bool
func NewUIDSet() UIDSet {
return make(map[types.UID]bool)
}
func (s UIDSet) Add(uids ...types.UID) {
for _, uid := range uids {
s[uid] = true
}
}
func (s UIDSet) Contains(uid types.UID) bool {
return s[uid]
}