in updater/aws.go [165:211]
func (u *updater) filterAvailableUpdates(bottlerocketInstances []instance) ([]instance, error) {
log.Printf("Filtering instances with available updates")
// make slice of Bottlerocket instances to use with SendCommand and checkCommandOutput
instances := make([]string, 0)
for _, inst := range bottlerocketInstances {
instances = append(instances, inst.instanceID)
}
var lastErr error
errCount := 0
candidates := make([]instance, 0)
pageCount, err := eachPage(len(instances), ssmPageSize, func(start, stop int) error {
commandID, err := u.sendCommand(instances[start:stop], u.checkDocument)
if err != nil {
// errors here are considered non-fatal.
log.Printf("Failed to send document %s: %v", u.checkDocument, err)
errCount++
lastErr = err
return nil
}
for _, inst := range bottlerocketInstances[start:stop] {
commandOutput, err := u.getCommandResult(commandID, inst.instanceID)
if err != nil {
// errors here are considered non-fatal
log.Printf("Failed to get output for command %s, document %s and instance %q: %v", commandID, u.checkDocument, inst, err)
continue
}
output, err := parseCommandOutput(commandOutput)
if err != nil {
log.Printf("Failed to parse command output %q for instance %q: %v", string(commandOutput), inst, err)
continue
}
if output.UpdateState == updateStateAvailable || output.UpdateState == updateStateReady {
inst.bottlerocketVersion = output.ActivePartition.Image.Version
candidates = append(candidates, inst)
}
}
return nil
})
if err != nil {
return nil, err
}
if errCount == pageCount {
return nil, fmt.Errorf("all attempts to send SSM document %s failed: %w", u.checkDocument, lastErr)
}
return candidates, nil
}