in agent/update/updater/updater.go [115:235]
func updateAgent() int {
defer log.Close()
defer log.Flush()
flag.Parse()
// Initialize agent config for agent identity
appConfig, err := appconfig.Config(true)
if err != nil {
log.Warnf("Failed to load agent config: %v", err)
}
// Create identity selector
agentIdentity, err := resolveAgentIdentity(appConfig)
if err != nil {
log.Errorf("Failed to assume agent identity: %v", err)
return errorExitCode
}
agentContext = context.Default(log, appConfig, agentIdentity)
updateUtilRef := updateutil.NewUpdaterUtilWithLoadedDocContent(agentContext, *messageID)
updateSSMUserShellProperties(log)
// Create update info
updateInfo, err := updateinfo.New(agentContext)
if err != nil {
log.Errorf("Failed to initialize update info object: %v", err)
return errorExitCode
}
// Sleep 3 seconds to allow agent to finishing up it's work
time.Sleep(defaultWaitTimeForAgentToFinish * time.Second)
updater = processor.NewUpdater(agentContext, updateInfo, updateUtilRef)
// If the updater already owns the lockfile, no harm done
// If there is no lockfile, the updater will own it
// If the updater is unable to lock the file, we retry and then fail
lock, _ := lockfile.New(appconfig.UpdaterPidLockfile)
err = lock.TryLockExpireWithRetry(updateconstants.UpdateLockFileMinutes)
if err != nil {
if err == lockfile.ErrBusy {
log.Warnf("Failed to lock update lockfile, another update is in progress: %s", err)
return nonErrorExitCode
} else {
log.Warnf("Proceeding update process with new lock. Failed to lock update lockfile: %s", err)
}
}
defer lock.Unlock()
// Return if update is not present in the command
if !*update {
log.Error("incorrect usage (use -update).")
flag.Usage()
return nonErrorExitCode
}
// Basic Validation
if len(*manifestURL) == 0 && len(*sourceLocation) == 0 {
log.Error("must pass either manifest url or source location")
flag.Usage()
}
if len(*sourceVersion) == 0 {
log.Error("no current version")
flag.Usage()
}
if !*selfUpdate && len(*targetVersion) == 0 {
log.Error("no target version")
flag.Usage()
}
// Create new UpdateDetail
updateDetail := &processor.UpdateDetail{
State: processor.NotStarted,
Result: contracts.ResultStatusInProgress,
SourceVersion: *sourceVersion,
SourceLocation: *sourceLocation,
TargetVersion: *targetVersion,
StdoutFileName: *stdout,
StderrFileName: *stderr,
OutputS3KeyPrefix: *outputKeyPrefix,
OutputS3BucketName: *outputBucket,
PackageName: *packageName,
MessageID: *messageID,
StartDateTime: time.Now().UTC(),
RequiresUninstall: false,
ManifestURL: *manifestURL,
Manifest: updatemanifest.New(agentContext, updateInfo, ""),
SelfUpdate: *selfUpdate,
AllowDowngrade: !*disableDowngrade,
UpstreamServiceName: *upstreamServiceName,
}
updateDetail.UpdateRoot, err = updateutil.ResolveUpdateRoot(updateDetail.SourceVersion)
if err != nil {
log.Errorf("Failed to resolve update root: %v", err)
return nonErrorExitCode
}
log.Infof("Update root is: %v", updateDetail.UpdateRoot)
// Initialize update detail with plugin info
err = updater.InitializeUpdate(log, updateDetail)
if err != nil {
log.Errorf(err.Error())
return nonErrorExitCode
}
// Recover updater if panic occurs and fail the updater
defer recoverUpdaterFromPanic(updateDetail)
// Start or resume update
if err = updater.StartOrResumeUpdate(log, updateDetail); err != nil { // We do not send any error above this to ICS/MGS except panic message
// Rolled back, but service cannot start, Update failed.
updater.Failed(updateDetail, log, updateconstants.ErrorUnexpected, err.Error(), false)
} else {
log.Infof(updateDetail.StandardOut)
}
return nonErrorExitCode
}