func updateAgent()

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
}