-
Notifications
You must be signed in to change notification settings - Fork 8
/
callbacks.go
145 lines (118 loc) · 4 KB
/
callbacks.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
package main
import (
"time"
"github.com/Nitro/sidecar-executor/container"
mesos "github.com/mesos/mesos-go/api/v1/lib"
"github.com/relistan/go-director"
log "github.com/sirupsen/logrus"
)
// LaunchTask is a callback from Mesos driver to launch a new task in this
// executor.
func (exec *sidecarExecutor) LaunchTask(taskInfo *mesos.TaskInfo) {
var err error
taskID := taskInfo.GetTaskID()
log.Info("Task ID ", taskID.GetValue())
// We need to tell the scheduler that we started the task
exec.sendStatus(TaskRunning, &taskID)
// Pull our Docker container if required
err = exec.maybePullContainer(taskInfo)
if err != nil {
log.Errorf("Failed to pull image: %s", err)
exec.failTask(taskInfo)
return
}
// Additional environment variables we'll pass to the container
var addEnvVars []string
if exec.config.SeedSidecar {
// Fetch the Mesos slave list and append the SIDECAR_SEEDS env var
addEnvVars = exec.addSidecarSeeds(addEnvVars)
}
dockerLabels := container.LabelsForTask(taskInfo)
// Look up the AWS Role in Vault if we have one defined
if exec.config.AWSRole != "" {
addEnvVars, err = exec.AddAndMonitorVaultAWSKeys(addEnvVars, exec.config.AWSRole)
if err != nil {
log.Error(err.Error())
exec.failTask(taskInfo)
return
}
// We can also have a custom TTL up to the Vault-configured max
if exec.config.AWSRoleTTL != time.Duration(0) {
err = exec.SetVaultAWSTTL(exec.config.AWSRoleTTL)
if err != nil {
log.Error(err.Error())
exec.failTask(taskInfo)
return
}
}
// Monitor creds if we got them, and exit the process before expiry if needed
go exec.monitorAWSCredsLease()
}
// Configure the container and cache the container config
exec.containerConfig = container.ConfigForTask(
taskInfo,
exec.config.ForceCpuLimit,
exec.config.ForceMemoryLimit,
exec.config.UseCpuShares,
addEnvVars,
)
// Log out what we're starting up with
exec.logTaskEnv(taskInfo, dockerLabels, addEnvVars)
// Try to decrypt any existing Vault encoded env.
decryptedEnv, err := exec.vault.DecryptAllEnv(exec.containerConfig.Config.Env)
if err != nil {
log.Error(err.Error())
exec.failTask(taskInfo)
return
}
exec.containerConfig.Config.Env = decryptedEnv
// create the container
cntnr, err := exec.client.CreateContainer(*exec.containerConfig)
if err != nil {
log.Errorf("Failed to create Docker container: %s", err)
exec.failTask(taskInfo)
return
}
// Cache the container ID
exec.containerID = cntnr.ID
// Start the container
log.Info("Starting container with ID " + cntnr.ID[:12])
err = exec.client.StartContainer(cntnr.ID, nil)
if err != nil {
log.Errorf("Failed to start Docker container: %s", err)
exec.failTask(taskInfo)
return
}
// For debugging, set process title to contain container ID & image
SetProcessName("sidecar-executor " + cntnr.ID[:12] + " (" + taskInfo.Container.Docker.Image + ")")
exec.watchLooper = director.NewImmediateTimedLooper(
director.FOREVER,
exec.config.SidecarPollInterval,
make(chan error),
)
// We have to do this in a different goroutine or the scheduler
// can't send us any further updates.
go exec.monitorTask(
cntnr.ID, taskInfo, shouldCheckSidecar(exec.containerConfig),
)
// We may be responsible for log relaying. Handle, if we are.
exec.handleContainerLogs(cntnr.ID, dockerLabels)
log.Info("Launched Sidecar tasks... ready for Mesos instructions")
}
// KillTask is a Mesos callback that will try very hard to kill off a running
// task/container.
func (exec *sidecarExecutor) KillTask(taskID *mesos.TaskID) {
log.Infof("Killing task: %s", taskID.Value)
// Instruct Sidecar to set the status of the service to DRAINING
exec.notifyDrain()
containerName := container.GetContainerName(taskID)
// Stop the container ourselves
err := container.StopContainer(
exec.client, containerName, exec.config.KillTaskTimeout,
)
if err != nil {
log.Errorf("Error stopping container %s! %s", containerName, err.Error())
}
// Stop watching the container and report appropriate task status
exec.watchLooper.Quit()
}