-
Notifications
You must be signed in to change notification settings - Fork 298
/
k8s_target.go
153 lines (122 loc) · 4.03 KB
/
k8s_target.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
package model
import (
"fmt"
"reflect"
"strings"
v1 "k8s.io/api/core/v1"
"github.com/tilt-dev/tilt/pkg/apis/core/v1alpha1"
)
// Whether or not to wait for pods to become ready before
// marking the k8s resource healthy.
//
// TODO(nick): I strongly suspect we will at least want a separate mode
// for jobs that waits until they become complete, as we do in `tilt ci`
type PodReadinessMode string
// Pod readiness isn't applicable to this resource
const PodReadinessNone PodReadinessMode = ""
// Always wait for pods to become ready.
const PodReadinessWait PodReadinessMode = "wait"
// Don't even wait for pods to appear.
const PodReadinessIgnore PodReadinessMode = "ignore"
type K8sTarget struct {
// An apiserver-driven data model for applying Kubernetes YAML.
//
// This will eventually replace K8sTarget. We represent this as an embedded
// struct while we're migrating fields.
v1alpha1.KubernetesApplySpec
Name TargetName
PortForwards []PortForward
// Each K8s entity should have a display name for user interfaces
// that balances brevity and uniqueness
DisplayNames []string
// Store the name, namespace, and type in a structured form
// for easy access. This should duplicate what's specified in the YAML.
ObjectRefs []v1.ObjectReference
PodReadinessMode PodReadinessMode
// Map configRef -> number of times we (expect to) inject it.
// NOTE(maia): currently this map is only for use in metrics, though someday
// we want a better way of mapping configRefs -> their injection point(s)
// (right now, Tiltfile and Engine have two different ways of finding a
// given image in a k8s entity.
refInjectCounts map[string]int
// zero+ links assoc'd with this resource (to be displayed in UIs,
// in addition to any port forwards/LB endpoints)
Links []Link
depIDs []TargetID
}
func NewK8sTargetForTesting(yaml string) K8sTarget {
apply := v1alpha1.KubernetesApplySpec{
YAML: yaml,
}
return K8sTarget{KubernetesApplySpec: apply}
}
func (k8s K8sTarget) Empty() bool { return reflect.DeepEqual(k8s, K8sTarget{}) }
func (k8s K8sTarget) HasJob() bool {
for _, ref := range k8s.ObjectRefs {
if strings.Contains(ref.Kind, "Job") {
return true
}
}
return false
}
func (k8s K8sTarget) DependencyIDs() []TargetID {
return append([]TargetID{}, k8s.depIDs...)
}
func (k8s K8sTarget) RefInjectCounts() map[string]int {
return k8s.refInjectCounts
}
func (k8s K8sTarget) Validate() error {
if k8s.ID().Empty() {
return fmt.Errorf("[Validate] K8s resources missing name:\n%s", k8s.YAML)
}
if k8s.YAML == "" {
return fmt.Errorf("[Validate] K8s resources %q missing YAML", k8s.Name)
}
return nil
}
func (k8s K8sTarget) ID() TargetID {
return TargetID{
Type: TargetTypeK8s,
Name: k8s.Name,
}
}
// Track which objects this target depends on inside the manifest.
//
// We're disentangling ImageTarget and live updates -
// image builds may or may not have live updates attached, but
// also live updates may or may not have image builds attached.
//
// KubernetesApplySpec only depends on ImageTargets with an Image build.
//
// The depIDs field depends on ImageTargets that have image builds OR have live
// updates.
//
// ids: a list of the images we directly depend on.
// isLiveUpdateOnly: a map of images that are live-update-only
func (k8s K8sTarget) WithDependencyIDs(ids []TargetID, isLiveUpdateOnly map[TargetID]bool) K8sTarget {
ids = DedupeTargetIDs(ids)
k8s.depIDs = ids
k8s.ImageMaps = make([]string, 0, len(ids))
for _, id := range ids {
if id.Type != TargetTypeImage {
panic(fmt.Sprintf("Invalid k8s dependency: %+v", id))
}
if isLiveUpdateOnly[id] {
continue
}
k8s.ImageMaps = append(k8s.ImageMaps, string(id.Name))
}
return k8s
}
func (k8s K8sTarget) WithRefInjectCounts(ric map[string]int) K8sTarget {
k8s.refInjectCounts = ric
return k8s
}
var _ TargetSpec = K8sTarget{}
func ToLiveUpdateOnlyMap(imageTargets []ImageTarget) map[TargetID]bool {
result := make(map[TargetID]bool, len(imageTargets))
for _, image := range imageTargets {
result[image.ID()] = image.IsLiveUpdateOnly
}
return result
}