/
global_yaml_buildcontroller.go
107 lines (83 loc) · 2.62 KB
/
global_yaml_buildcontroller.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
package engine
import (
"context"
"sort"
"github.com/pkg/errors"
v1 "k8s.io/api/core/v1"
"github.com/windmilleng/tilt/internal/k8s"
"github.com/windmilleng/tilt/internal/logger"
"github.com/windmilleng/tilt/internal/model"
"github.com/windmilleng/tilt/internal/store"
)
type GlobalYAMLBuildController struct {
disabledForTesting bool
lastGlobalYAMLManifest model.Manifest
k8sClient k8s.Client
}
func NewGlobalYAMLBuildController(k8sClient k8s.Client) *GlobalYAMLBuildController {
return &GlobalYAMLBuildController{
k8sClient: k8sClient,
}
}
func (c *GlobalYAMLBuildController) OnChange(ctx context.Context, st store.RStore) {
if c.disabledForTesting {
return
}
state := st.RLockState()
m := state.GlobalYAML
st.RUnlockState()
if m.K8sTarget().YAML != c.lastGlobalYAMLManifest.K8sTarget().YAML {
c.lastGlobalYAMLManifest = m
st.Dispatch(GlobalYAMLApplyStartedAction{})
err := handleGlobalYamlChange(ctx, m, c.k8sClient)
if err != nil {
logger.Get(ctx).Infof(err.Error())
}
st.Dispatch(GlobalYAMLApplyCompleteAction{Error: err})
}
}
type namespacesFirst []k8s.K8sEntity
var _ sort.Interface = namespacesFirst{}
func (nf namespacesFirst) Len() int {
return len(nf)
}
func (nf namespacesFirst) Less(i, j int) bool {
if nf[i].Kind.Kind == "Namespace" {
return true
} else if nf[j].Kind.Kind == "Namespace" {
return false
} else {
return i < j
}
}
func (nf namespacesFirst) Swap(i, j int) {
nf[i], nf[j] = nf[j], nf[i]
}
func handleGlobalYamlChange(ctx context.Context, m model.Manifest, kCli k8s.Client) error {
entities, err := k8s.ParseYAMLFromString(m.K8sTarget().YAML)
if err != nil {
return errors.Wrap(err, "Error parsing k8s_yaml")
}
newK8sEntities := []k8s.K8sEntity{}
for _, e := range entities {
e, err = k8s.InjectLabels(e, []model.LabelPair{k8s.TiltRunLabel(), {Key: k8s.ManifestNameLabel, Value: m.ManifestName().String()}})
if err != nil {
return errors.Wrap(err, "Error injecting labels in to k8s_yaml")
}
// For development, image pull policy should never be set to "Always",
// even if it might make sense to use "Always" in prod. People who
// set "Always" for development are shooting their own feet.
e, err = k8s.InjectImagePullPolicy(e, v1.PullIfNotPresent)
if err != nil {
return errors.Wrap(err, "Error injecting image pull policy in to k8s_yaml")
}
newK8sEntities = append(newK8sEntities, e)
}
// namespaces need to be created before the entities that go in them
sort.Sort(namespacesFirst(newK8sEntities))
err = kCli.Upsert(ctx, newK8sEntities)
if err != nil {
return errors.Wrap(err, "Error upserting k8s_yaml")
}
return nil
}