in agent/acs/update_handler/updater.go [88:164]
func (u *updater) stageUpdateHandler() func(req *ecsacs.StageUpdateMessage) {
return func(req *ecsacs.StageUpdateMessage) {
u.Lock()
defer u.Unlock()
if req == nil || req.MessageId == nil {
seelog.Error("Nil request to stage update or missing MessageID")
return
}
nack := func(reason string) {
seelog.Errorf("Nacking StageUpdate; reason: %s", reason)
u.acs.MakeRequest(&ecsacs.NackRequest{
Cluster: req.ClusterArn,
ContainerInstance: req.ContainerInstanceArn,
MessageId: req.MessageId,
Reason: aws.String(reason),
})
u.reset()
}
if !u.config.UpdatesEnabled.Enabled() {
nack("Updates are disabled")
return
}
if err := validateUpdateInfo(req.UpdateInfo); err != nil {
nack("Invalid update: " + err.Error())
return
}
seelog.Debug("Staging update", "update", req)
if u.stage != updateNone {
if u.updateID != "" && u.updateID == *req.UpdateInfo.Signature {
seelog.Debug("Update already in progress, acking duplicate message", "id", u.updateID)
// Acking here is safe as any currently-downloading update will already be holding
// the update lock. A failed download will nack and clear state (while holding the
// update lock) before this code is reached, meaning that the above conditional will
// not evaluate true (no matching, in-progress update).
u.acs.MakeRequest(&ecsacs.AckRequest{
Cluster: req.ClusterArn,
ContainerInstance: req.ContainerInstanceArn,
MessageId: req.MessageId,
})
return
} else {
// Nack previous update
reason := "New update arrived: " + *req.MessageId
u.acs.MakeRequest(&ecsacs.NackRequest{
Cluster: req.ClusterArn,
ContainerInstance: req.ContainerInstanceArn,
MessageId: &u.downloadMessageID,
Reason: &reason,
})
}
}
u.updateID = *req.UpdateInfo.Signature
u.stage = updateDownloading
u.stageTime = ttime.Now()
u.downloadMessageID = *req.MessageId
err := u.download(req.UpdateInfo)
if err != nil {
nack("Unable to download: " + err.Error())
return
}
u.stage = updateDownloaded
u.acs.MakeRequest(&ecsacs.AckRequest{
Cluster: req.ClusterArn,
ContainerInstance: req.ContainerInstanceArn,
MessageId: req.MessageId,
})
}
}