func()

in agent/plugins/configurepackage/configurepackage.go [508:642]


func (p *Plugin) execute(config contracts.Configuration, cancelFlag task.CancelFlag, output iohandler.IOHandler) {
	log := p.context.Log()
	log.Info("RunCommand started with configuration ", config)
	tracer := trace.NewTracer(log)
	defer tracer.BeginSection("configurePackage").End()

	out := trace.PluginOutputTrace{Tracer: tracer}

	if cancelFlag.ShutDown() {
		out.MarkAsShutdown()
	} else if cancelFlag.Canceled() {
		out.MarkAsCancelled()
	} else if input, err := parseAndValidateInput(config.Properties); err != nil {
		tracer.CurrentTrace().WithError(err).End()
		out.MarkAsFailed(nil, nil)
	} else {
		appConfig := p.context.AppConfig()
		packageService, err := p.packageServiceSelector(p.context, tracer, input, p.localRepository, &appConfig, p.birdwatcherfacade, &p.isDocumentArchive)
		if err != nil {
			tracer.CurrentTrace().WithError(err).End()
			out.MarkAsFailed(nil, nil)
		}
		if out.GetStatus() != contracts.ResultStatusFailed {
			//Return failure if the manifest cannot be accessed
			//Return failure if the package version is installed, but the manifest is no longer available
			packageName, packageVersion := packageService.GetPackageArnAndVersion(input.Name, input.Version)

			//always download the manifest before acting upon the request
			trace := tracer.BeginSection("download manifest")
			packageArn, manifestVersion, isSameAsCache, err := packageService.DownloadManifest(tracer, packageName, packageVersion)
			trace.AppendDebugf("got manifest for package %v version %v isSameAsCache %v", packageArn, manifestVersion, isSameAsCache)

			trace.End()

			if err != nil {
				tracer.CurrentTrace().WithError(err).End()
				out.MarkAsFailed(nil, nil)
			} else if err := p.localRepository.LockPackage(tracer, packageArn, input.Action); err != nil {
				// do not allow multiple actions to be performed at the same time for the same package
				// this is possible with multiple concurrent runcommand documents
				tracer.CurrentTrace().WithError(err).End()
				out.MarkAsFailed(nil, nil)
			} else {
				defer p.localRepository.UnlockPackage(tracer, packageArn)

				log.Debugf("Prepare for %v %v %v", input.Action, input.Name, input.Version)
				inst, uninst, isUpdateInPlace, installState, installedVersion := prepareConfigurePackage(
					tracer,
					config,
					p.localRepository,
					packageService,
					input,
					packageArn,
					manifestVersion,
					isSameAsCache,
					&out)
				log.Debugf("HasInst %v, HasUninst %v, IsInplaceUpdate %v, InstallState %v, PackageName %v, InstalledVersion %v", inst != nil, uninst != nil, isUpdateInPlace, installState, packageArn, installedVersion)

				//if the status is already decided as failed or succeeded, do not execute anything
				if out.GetStatus() != contracts.ResultStatusFailed && out.GetStatus() != contracts.ResultStatusSuccess {
					alreadyInstalled := checkAlreadyInstalled(tracer, p.context, p.localRepository, installedVersion, installState, inst, uninst, &out)
					// if package is not installed, set isUpdateInPlace to false so as to execute install script to install
					if installedVersion == "" || installState == localpackages.None {
						isUpdateInPlace = false
					}
					// if already failed or already installed and valid, do not execute install
					// if it is already installed and the cache is the same, do not execute install
					if !alreadyInstalled || !isSameAsCache {
						log.Debugf("Calling execute, current status %v", out.GetStatus())
						executeConfigurePackage(
							tracer,
							p.context,
							p.localRepository,
							inst,
							uninst,
							isUpdateInPlace,
							installState,
							&out)
					}
				}
				if err := p.localRepository.LoadTraces(tracer, packageArn); err != nil {
					log.Errorf("Error loading prior traces: %v", err.Error())
				}
				if out.GetStatus().IsReboot() {
					err := p.localRepository.PersistTraces(tracer, packageArn)
					if err != nil {
						log.Errorf("Error persisting traces: %v", err.Error())
					}
				} else {
					version := manifestVersion
					if out.GetStatus() != contracts.ResultStatusFailed && out.GetStatus() != contracts.ResultStatusSuccess {
						if input.Action == InstallAction {
							version = inst.Version()
						} else if input.Action == UninstallAction {
							version = uninst.Version()
						}
					}
					startTime := tracer.Traces()[0].Start
					for _, trace := range tracer.Traces() {
						if trace.Start < startTime {
							startTime = trace.Start
						}
					}

					err := packageService.ReportResult(tracer, packageservice.PackageResult{
						Exitcode:               int64(out.GetExitCode()),
						Operation:              input.Action,
						PackageName:            input.Name,
						PreviousPackageVersion: installedVersion,
						Timing:                 startTime,
						Version:                version,
						Trace:                  packageservice.ConvertToPackageServiceTrace(tracer.Traces()),
					})
					if err != nil {
						if p.isDocumentArchive {
							log.Warnf("Error reporting results for Document archive: %v", err.Error())
						} else {
							out.AppendErrorf(log, "Error reporting results: %v", err.Error())
						}
					}
				}
			}
		}
	}

	output.SetExitCode(out.GetExitCode())
	output.SetStatus(out.GetStatus())

	// convert trace
	traceout := tracer.ToPluginOutput()
	output.AppendInfo(traceout.GetStdout())
	output.AppendError(traceout.GetStderr())

	return
}