in updater/aws.go [421:468]
func (u *updater) sendCommand(instanceIDs []string, ssmDocument string) (string, error) {
log.Printf("Sending SSM document %q", ssmDocument)
resp, err := u.ssm.SendCommand(&ssm.SendCommandInput{
DocumentName: aws.String(ssmDocument),
DocumentVersion: aws.String("$DEFAULT"),
InstanceIds: aws.StringSlice(instanceIDs),
TimeoutSeconds: aws.Int64(deliveryTimeoutSeconds),
})
if err != nil {
return "", fmt.Errorf("send command failed: %w", err)
}
commandID := *resp.Command.CommandId
log.Printf("SSM document %q posted with command id %q", ssmDocument, commandID)
// Wait for the sent commands to complete.
wg := sync.WaitGroup{}
instanceCount := len(instanceIDs)
errChan := make(chan error, instanceCount)
for _, v := range instanceIDs {
log.Printf("Waiting for command %q to complete for instance %q", commandID, v)
wg.Add(1)
go func(instanceID string) {
defer wg.Done()
err = u.ssm.WaitUntilCommandExecutedWithContext(aws.BackgroundContext(), &ssm.GetCommandInvocationInput{
CommandId: aws.String(commandID),
InstanceId: aws.String(instanceID),
},
request.WithWaiterMaxAttempts(waiterMaxAttempts),
request.WithWaiterDelay(request.ConstantWaiterDelay(waiterDelay)))
if err != nil {
errChan <- err
log.Printf("Error encountered while awaiting document %q execution for instance: %q: %s", ssmDocument, instanceID, err)
u.logCommmandOutput(commandID, instanceID)
}
}(aws.StringValue(&v))
}
wg.Wait()
close(errChan)
errCount := 0
for err = range errChan {
errCount++
if errCount == instanceCount {
return "", fmt.Errorf("too many failures while awaiting document execution: %w", err)
}
}
return commandID, nil
}