func()

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
}