in agent/association/processor/refreshassociation.go [75:176]
func (p *Processor) refreshAssociation(log log.T, associationIds []string, orchestrationDirectory string, outputS3BucketName string, outputS3KeyPrefix string, out iohandler.IOHandler) {
var err error
var instanceID string
associations := []*model.InstanceAssociation{}
if instanceID, err = p.context.Identity().InstanceID(); err != nil {
out.MarkAsFailed(fmt.Errorf("failed to load instance ID, %v", err))
return
}
// Get associations
if associations, err = p.assocSvc.ListInstanceAssociations(log, instanceID); err != nil {
out.MarkAsFailed(fmt.Errorf("failed to list instance associations, %v", err))
return
}
// evict the invalid cache first
for _, assoc := range associations {
cache.ValidateCache(assoc)
}
// if user provided empty list or "" in the document, we will run all the associations now
applyAll := len(associationIds) == 0 || (len(associationIds) == 1 && associationIds[0] == "")
// Default is success
out.MarkAsSucceeded()
// read from cache or load association details from service
for _, assoc := range associations {
if err = p.assocSvc.LoadAssociationDetail(log, assoc); err != nil {
err = fmt.Errorf("Encountered error while loading association %v contents, %v",
*assoc.Association.AssociationId,
err)
assoc.Errors = append(assoc.Errors, err)
p.assocSvc.UpdateInstanceAssociationStatus(
log,
*assoc.Association.AssociationId,
*assoc.Association.Name,
*assoc.Association.InstanceId,
contracts.AssociationStatusFailed,
contracts.AssociationErrorCodeListAssociationError,
times.ToIso8601UTC(time.Now()),
err.Error(),
service.NoOutputUrl)
out.MarkAsFailed(err)
continue
}
// validate association expression, fail association if expression cannot be passed
// Note: we do not want to fail runcommand with out.MarkAsFailed
if !assoc.IsRunOnceAssociation() {
if err := assoc.ParseExpression(log); err != nil {
message := fmt.Sprintf("Encountered error while parsing expression for association %v", *assoc.Association.AssociationId)
log.Errorf("%v, %v", message, err)
assoc.Errors = append(assoc.Errors, err)
p.assocSvc.UpdateInstanceAssociationStatus(
log,
*assoc.Association.AssociationId,
*assoc.Association.Name,
*assoc.Association.InstanceId,
contracts.AssociationStatusFailed,
contracts.AssociationErrorCodeInvalidExpression,
times.ToIso8601UTC(time.Now()),
message,
service.NoOutputUrl)
out.MarkAsFailed(err)
continue
}
}
if applyAll || isAssociationQualifiedToRunNow(associationIds, assoc) {
// If association is already InProgress, we don't want to run it again
if assoc.Association.DetailedStatus == nil ||
(*assoc.Association.DetailedStatus != contracts.AssociationStatusInProgress && *assoc.Association.DetailedStatus != contracts.AssociationStatusPending) {
// Updates status to pending, which is the indicator for schedulemanager for immediate execution
p.assocSvc.UpdateInstanceAssociationStatus(
log,
*assoc.Association.AssociationId,
*assoc.Association.Name,
*assoc.Association.InstanceId,
contracts.AssociationStatusPending,
contracts.AssociationErrorCodeNoError,
times.ToIso8601UTC(time.Now()),
contracts.AssociationPendingMessage,
service.NoOutputUrl)
assoc.Association.DetailedStatus = aws.String(contracts.AssociationStatusPending)
}
}
}
schedulemanager.Refresh(log, associations)
if applyAll {
out.AppendInfo("All associations have been requested to execute immediately")
} else {
out.AppendInfof("Associations %v have been requested to execute immediately", associationIds)
}
signal.ExecuteAssociation(log)
return
}