// <inheritdoc /> public async Task <SiteExtensionInfo> GetLocalExtension(string id, bool checkLatest = true) { ITracer tracer = _traceFactory.GetTracer(); UIPackageMetadata package = null; using (tracer.Step("Now querying from local repo for package '{0}'.", id)) { package = await _localRepository.GetLatestPackageByIdFromSrcRepo(id); } if (package == null) { tracer.Trace("No package found from local repo with id: {0}.", id); return(null); } SiteExtensionInfo info; using (tracer.Step("Converting NuGet object to SiteExtensionInfo")) { info = await ConvertLocalPackageToSiteExtensionInfo(package, checkLatest, tracer : tracer); } SiteExtensionStatus armSettings = new SiteExtensionStatus(_environment.SiteExtensionSettingsPath, id, tracer); armSettings.FillSiteExtensionInfo(info); return(info); }
// can be called concurrently if metaDataResource is provided internal static async Task <UIPackageMetadata> GetLatestPackageByIdFromMetaRes(this UIMetadataResource metadataResource, string packageId, bool includePrerelease = true, bool includeUnlisted = false, bool explicitTag = false) { UIPackageMetadata latestPackage = null; IEnumerable <UIPackageMetadata> packages = await metadataResource.GetMetadata(packageId, includePrerelease, includeUnlisted, token : CancellationToken.None); // When using nuget.org, we only look at packages that have our tag. if (explicitTag) { packages = packages.Where(item => item.Tags.IndexOf("azuresiteextension", StringComparison.OrdinalIgnoreCase) >= 0); } foreach (var p in packages) { if (latestPackage == null || latestPackage.Identity.Version < p.Identity.Version) { latestPackage = p; } } // If we couldn't find any listed version, fall back to looking for unlisted versions, to avoid failing completely. // Reasoning is that if all the versions have been unlisted, it should still be possible to install it by // explicit id, even without specifying a version if (latestPackage == null && !includeUnlisted) { latestPackage = await GetLatestPackageByIdFromMetaRes(metadataResource, packageId, includePrerelease, includeUnlisted : true, explicitTag : explicitTag); } return(latestPackage); }
private async Task TryCheckLocalPackageLatestVersionFromRemote(SiteExtensionInfo info, bool checkLatest, ITracer tracer = null) { if (checkLatest) { try { // FindPackage gets back the latest version. IEnumerable <SourceRepository> remoteRepos = GetRemoteRepositories(info.FeedUrl); foreach (SourceRepository remoteRepo in remoteRepos) { UIPackageMetadata latestPackage = await remoteRepo.GetLatestPackageByIdFromSrcRepo(info.Id); if (latestPackage != null) { NuGetVersion currentVersion = NuGetVersion.Parse(info.Version); info.LocalIsLatestVersion = NuGetVersion.Parse(info.Version).Equals(latestPackage.Identity.Version); info.DownloadCount = latestPackage.DownloadCount; info.PublishedDateTime = latestPackage.Published; break; } } } catch (Exception ex) { if (tracer != null) { tracer.TraceError(ex); } } } }
/// <summary> /// <para> Return true if any of below cases is satisfied:</para> /// <para> 1) Package with same version and from same feed already exist in local repo</para> /// <para> 2) If given feedUrl is null</para> /// <para> Try to use feed from local package, if feed from local package also null, fallback to default feed</para> /// <para> Check if version from query is same as local package</para> /// <para> 3) If given version and feedUrl are null</para> /// <para> Try to use feed from local package, if feed from local package also null, fallback to default feed</para> /// <para> Check if version from query is same as local package</para> /// </summary> private async Task <bool> IsSiteExtensionInstalled(string id, string version, string feedUrl) { JsonSettings siteExtensionSettings = GetSettingManager(id); string localPackageVersion = siteExtensionSettings.GetValue(_versionSetting); string localPackageFeedUrl = siteExtensionSettings.GetValue(_feedUrlSetting); bool isInstalled = false; // Try to use given feed // If given feed is null, try with feed that from local package // And GetRemoteRepository will fallback to use default feed if pass in feed param is null SourceRepository remoteRepo = GetRemoteRepository(feedUrl ?? localPackageFeedUrl); // case 1 and 2 if (!string.IsNullOrWhiteSpace(version) && version.Equals(localPackageVersion, StringComparison.OrdinalIgnoreCase) && remoteRepo.PackageSource.Source.Equals(localPackageFeedUrl, StringComparison.OrdinalIgnoreCase)) { isInstalled = true; } else if (string.IsNullOrWhiteSpace(version) && string.IsNullOrWhiteSpace(feedUrl)) { // case 3 UIPackageMetadata remotePackage = await remoteRepo.GetLatestPackageByIdFromSrcRepo(id); if (remotePackage != null) { isInstalled = remotePackage.Identity.Version.ToNormalizedString().Equals(localPackageVersion, StringComparison.OrdinalIgnoreCase); } } return(isInstalled); }
// <inheritdoc /> public async Task <SiteExtensionInfo> GetLocalExtension(string id, bool checkLatest = true) { ITracer tracer = _traceFactory.GetTracer(); SiteExtensionInfo info = GetPreInstalledExtension(id); if (info != null && info.ExtensionUrl != null) { tracer.Trace("Pre-installed site extension found: {0}", id); } else { UIPackageMetadata package = null; using (tracer.Step("{0} is not a pre-installed package. Now querying from local repo.", id)) { package = await _localRepository.GetLatestPackageById(id); } if (package == null) { tracer.Trace("No package found from local repo with id: {0}.", id); return(null); } using (tracer.Step("Converting NuGet object to SiteExtensionInfo")) { info = await ConvertLocalPackageToSiteExtensionInfo(package, checkLatest, tracer : tracer); } } SiteExtensionStatus armSettings = new SiteExtensionStatus(_environment.SiteExtensionSettingsPath, id, tracer); armSettings.FillSiteExtensionInfo(info); return(info); }
public async Task <SiteExtensionInfo> GetRemoteExtension(string id, string version, string feedUrl) { ITracer tracer = _traceFactory.GetTracer(); SourceRepository remoteRepo = GetRemoteRepository(feedUrl); UIPackageMetadata package = null; if (string.IsNullOrWhiteSpace(version)) { using (tracer.Step("Version is null, search latest package by id: {0}", id)) { package = await remoteRepo.GetLatestPackageByIdFromSrcRepo(id); } } else { using (tracer.Step("Search package by id: {0} and version: {1}", id, version)) { package = await remoteRepo.GetPackageByIdentity(id, version); } } if (package == null) { tracer.Trace("No package found with id: {0} and version: {1}", id, version); return(null); } var metadataResource = await _localRepository.GetResourceAndValidateAsync <UIMetadataResource>(); return(await ConvertRemotePackageToSiteExtensionInfo(package, feedUrl, metadataResource)); }
/// <summary> /// <para>1. Download package</para> /// <para>2. Generate xdt file if not exist</para> /// <para>3. Deploy site extension job</para> /// <para>4. Execute install.cmd if exist</para> /// </summary> private async Task <UIPackageMetadata> InstallExtension(UIPackageMetadata package, string installationDirectory, string feedUrl) { ITracer tracer = _traceFactory.GetTracer(); try { if (FileSystemHelpers.DirectoryExists(installationDirectory)) { FileSystemHelpers.DeleteDirectorySafe(installationDirectory); } SourceRepository remoteRepo = GetRemoteRepository(feedUrl); // Copy content folder // Copy nupkg file for package list/lookup FileSystemHelpers.CreateDirectory(installationDirectory); // package path from local repo string packageLocalFilePath = GetNuGetPackageFile(package.Identity.Id, package.Identity.Version.ToString()); using (tracer.Step("Download site extension: {0}", package.Identity)) { await remoteRepo.DownloadPackageToFolder(package.Identity, installationDirectory, pathToLocalCopyOfNudpk : packageLocalFilePath); } // If there is no xdt file, generate default. using (tracer.Step("Check if applicationhost.xdt file existed.")) { GenerateApplicationHostXdt(installationDirectory, '/' + package.Identity.Id, isPreInstalled: false, tracer: tracer); } using (tracer.Step("Trigger site extension job")) { OperationManager.Attempt(() => DeploySiteExtensionJobs(package.Identity.Id)); } var externalCommandFactory = new ExternalCommandFactory(_environment, _settings, installationDirectory); string installScript = Path.Combine(installationDirectory, _installScriptName); if (FileSystemHelpers.FileExists(installScript)) { using (tracer.Step("Execute install.cmd")) { OperationManager.Attempt(() => { Executable exe = externalCommandFactory.BuildCommandExecutable(installScript, installationDirectory, _settings.GetCommandIdleTimeout(), NullLogger.Instance); exe.ExecuteWithProgressWriter(NullLogger.Instance, _traceFactory.GetTracer(), String.Empty); }); } } } catch (Exception ex) { tracer.TraceError(ex); FileSystemHelpers.DeleteDirectorySafe(installationDirectory); throw; } return(await _localRepository.GetLatestPackageById(package.Identity.Id)); }
private async Task <SiteExtensionInfo> CheckRemotePackageLatestVersion(SiteExtensionInfo info, UIMetadataResource metadataResource) { UIPackageMetadata localPackage = await metadataResource.GetLatestPackageByIdFromMetaRes(info.Id); if (localPackage != null) { SetLocalInfo(info); // Assume input package (from remote) is always the latest version. info.LocalIsLatestVersion = NuGetVersion.Parse(info.Version).Equals(localPackage.Identity.Version); } return(info); }
private async Task <SiteExtensionInfo> CheckRemotePackageLatestVersion(SiteExtensionInfo info, string feedUrl) { info.FeedUrl = feedUrl; UIPackageMetadata localPackage = await _localRepository.GetLatestPackageById(info.Id); if (localPackage != null) { SetLocalInfo(info); // Assume input package (from remote) is always the latest version. info.LocalIsLatestVersion = NuGetVersion.Parse(info.Version).Equals(localPackage.Identity.Version); } return(info); }
// can be called concurrently if metaDataResource is provided internal static async Task<UIPackageMetadata> GetLatestPackageByIdFromMetaRes(this UIMetadataResource metadataResource, string packageId, bool includePrerelease = true, bool includeUnlisted = false) { UIPackageMetadata latestPackage = null; IEnumerable<UIPackageMetadata> packages = await metadataResource.GetMetadata(packageId, includePrerelease, includeUnlisted, token: CancellationToken.None); foreach (var p in packages) { if (latestPackage == null || latestPackage.Identity.Version < p.Identity.Version) { latestPackage = p; } } return latestPackage; }
public SiteExtensionInfo(UIPackageMetadata data) { Id = data.Identity.Id; Title = data.Identity.Id; Type = SiteExtensionType.Gallery; Summary = data.Summary; Description = data.Description; Version = data.Identity.Version.ToNormalizedString(); ProjectUrl = data.ProjectUrl == null ? null : data.ProjectUrl.ToString(); IconUrl = data.IconUrl == null ? "https://www.siteextensions.net/Content/Images/packageDefaultIcon-50x50.png" : data.IconUrl.ToString(); LicenseUrl = data.LicenseUrl == null ? null : data.LicenseUrl.ToString(); Authors = data.Authors.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries); PublishedDateTime = data.Published; IsLatestVersion = true; DownloadCount = data.DownloadCount; }
public SiteExtensionInfo(UIPackageMetadata data) { Id = data.Identity.Id; Title = data.Title; Type = SiteExtensionType.Gallery; Summary = data.Summary; Description = data.Description; Version = data.Identity.Version.ToNormalizedString(); ProjectUrl = data.ProjectUrl == null ? null : data.ProjectUrl.ToString(); IconUrl = data.IconUrl == null ? "https://www.siteextensions.net/Content/Images/packageDefaultIcon-50x50.png" : data.IconUrl.ToString(); LicenseUrl = data.LicenseUrl == null ? null : data.LicenseUrl.ToString(); Authors = data.Authors.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries); PublishedDateTime = data.Published; IsLatestVersion = true; DownloadCount = data.DownloadCount; }
/// <summary> /// <para>Query source repository for a package base on given package id and version</para> /// <para>Will also query pre-release and unlisted packages</para> /// </summary> /// <param name="packageId">Package id, must not be null</param> /// <param name="version">Package version, must not be null</param> /// <returns>Package metadata</returns> public static async Task <UIPackageMetadata> GetPackageByIdentity(this SourceRepository srcRepo, string packageId, string version) { var metadataResource = await srcRepo.GetResourceAndValidateAsync <UIMetadataResource>(); NuGetVersion expectedVersion = NuGetVersion.Parse(version); var identity = new PackageIdentity(packageId, expectedVersion); UIPackageMetadata ret = await metadataResource.GetMetadata(identity, CancellationToken.None); // When using nuget.org, we only look at packages that have our tag. if (ret != null && IsNuGetRepo(srcRepo.PackageSource.Source) && (ret.Tags.IndexOf("azuresiteextension", StringComparison.OrdinalIgnoreCase) < 0)) { ret = null; } return(ret); }
private async Task TryCheckLocalPackageLatestVersionFromRemote(SiteExtensionInfo info, bool checkLatest) { if (checkLatest) { // FindPackage gets back the latest version. SourceRepository remoteRepo = GetRemoteRepository(info.FeedUrl); UIPackageMetadata latestPackage = await remoteRepo.GetLatestPackageById(info.Id); if (latestPackage != null) { NuGetVersion currentVersion = NuGetVersion.Parse(info.Version); info.LocalIsLatestVersion = NuGetVersion.Parse(info.Version).Equals(latestPackage.Identity.Version); info.DownloadCount = latestPackage.DownloadCount; info.PublishedDateTime = latestPackage.Published; } } }
/// <summary> /// Query source repository for latest package base given package id /// </summary> public static async Task <UIPackageMetadata> GetLatestPackageById(this SourceRepository srcRepo, string packageId) { UIPackageMetadata latestPackage = null; var metadataResource = await srcRepo.GetResourceAsync <UIMetadataResource>(); IEnumerable <UIPackageMetadata> packages = await metadataResource.GetMetadata(packageId, true, true, CancellationToken.None); foreach (var p in packages) { if (latestPackage == null || latestPackage.Identity.Version < p.Identity.Version) { latestPackage = p; } } return(latestPackage); }
/// <summary> /// Query source repository for latest package base given package id /// </summary> public static async Task <UIPackageMetadata> GetLatestPackageById(this SourceRepository srcRepo, string packageId, bool includePrerelease = true, bool includeUnlisted = false) { UIPackageMetadata latestPackage = null; var metadataResource = await srcRepo.GetResourceAndValidateAsync <UIMetadataResource>(); IEnumerable <UIPackageMetadata> packages = await metadataResource.GetMetadata(packageId, includePrerelease, includeUnlisted, token : CancellationToken.None); foreach (var p in packages) { if (latestPackage == null || latestPackage.Identity.Version < p.Identity.Version) { latestPackage = p; } } return(latestPackage); }
public DetailedPackageMetadata(UIPackageMetadata serverData, int downloadCount) { Version = serverData.Identity.Version; Summary = serverData.Summary; Description = serverData.Description; Authors = serverData.Authors; Owners = serverData.Owners; IconUrl = serverData.IconUrl; LicenseUrl = serverData.LicenseUrl; ProjectUrl = serverData.ProjectUrl; ReportAbuseUrl = serverData.ReportAbuseUrl; Tags = serverData.Tags; DownloadCount = downloadCount; Published = serverData.Published; DependencySets = serverData.DependencySets.Select(e => new PackageDependencySetMetadata(e)); HasDependencies = DependencySets.Any( dependencySet => dependencySet.Dependencies != null && dependencySet.Dependencies.Count > 0); }
public async Task TestVisualStudioUIMetadataResource(string SourceUrl) { SourceRepository repo = GetSourceRepository(SourceUrl); UIMetadataResource resource = repo.GetResource <UIMetadataResource>(); Assert.True(resource != null); var result = await resource.GetMetadata("Microsoft.AspNet.Razor", true, true, CancellationToken.None); UIPackageMetadata packageMetadata = result.FirstOrDefault( p => p.Identity.Version == new NuGetVersion("4.0.0-beta1")); Assert.True(packageMetadata.DependencySets.Count() == 1); Assert.True(packageMetadata.DependencySets.First().Packages.Count().Equals(12)); IEnumerable <UIPackageMetadata> packageMetadataList = resource.GetMetadata("Nuget.core", true, true, CancellationToken.None).Result; Assert.True(packageMetadataList != null); Assert.Equal(47, packageMetadataList.Count()); }
public async Task <SiteExtensionInfo> GetLocalExtension(string id, bool checkLatest = true) { ITracer tracer = _traceFactory.GetTracer(); SiteExtensionInfo info = GetPreInstalledExtension(id); if (info != null && info.ExtensionUrl != null) { tracer.Trace("Pre-installed site extension found: {0}", id); return(info); } UIPackageMetadata package = await _localRepository.GetLatestPackageById(id); if (package == null) { tracer.Trace("No package found from local repo with id: {0}.", id); return(null); } return(await ConvertLocalPackageToSiteExtensionInfo(package, checkLatest)); }
private async Task <SiteExtensionInfo> CheckRemotePackageLatestVersion(SiteExtensionInfo info, UIMetadataResource metadataResource) { bool isNuGetPackage = false; if (!string.IsNullOrEmpty(info.FeedUrl)) { isNuGetPackage = FeedExtensions.IsNuGetRepo(info.FeedUrl); } UIPackageMetadata localPackage = await metadataResource.GetLatestPackageByIdFromMetaRes(info.Id, explicitTag : isNuGetPackage); if (localPackage != null) { SetLocalInfo(info); // Assume input package (from remote) is always the latest version. info.LocalIsLatestVersion = NuGetVersion.Parse(info.Version).Equals(localPackage.Identity.Version); } return(info); }
/// <summary> /// <para> Return false if the installation arguments are different. Otherwise,</para> /// <para> Return true if any of below cases is satisfied:</para> /// <para> 1) Package with same version and from same feed already exist in local repo</para> /// <para> 2) If given feedUrl is null</para> /// <para> Try to use feed from local package, if feed from local package also null, fallback to default feed</para> /// <para> Check if version from query is same as local package</para> /// <para> 3) If given version and feedUrl are null</para> /// <para> Try to use feed from local package, if feed from local package also null, fallback to default feed</para> /// <para> Check if version from query is same as local package</para> /// </summary> private async Task <bool> IsSiteExtensionInstalled(string id, string version, string feedUrl, string installationArgs) { JsonSettings siteExtensionSettings = GetSettingManager(id); string localPackageVersion = siteExtensionSettings.GetValue(_versionSetting); string localPackageFeedUrl = siteExtensionSettings.GetValue(_feedUrlSetting); string localPackageInstallationArgs = siteExtensionSettings.GetValue(_installationArgs); bool isInstalled = false; // Shortcircuit check: if the installation arguments do not match, then we should return false here to avoid other checks which are now unnecessary. if (!string.Equals(localPackageInstallationArgs, installationArgs)) { return(false); } // Try to use given feed // If given feed is null, try with feed that from local package // And GetRemoteRepository will fallback to use default feed if pass in feed param is null SourceRepository remoteRepo = GetRemoteRepository(feedUrl ?? localPackageFeedUrl); // case 1 and 2 if (!string.IsNullOrWhiteSpace(version) && version.Equals(localPackageVersion, StringComparison.OrdinalIgnoreCase) && remoteRepo.PackageSource.Source.Equals(localPackageFeedUrl, StringComparison.OrdinalIgnoreCase)) { isInstalled = true; } else if (string.IsNullOrWhiteSpace(version) && string.IsNullOrWhiteSpace(feedUrl)) { // case 3 UIPackageMetadata remotePackage = await remoteRepo.GetLatestPackageByIdFromSrcRepo(id); if (remotePackage != null) { isInstalled = remotePackage.Identity.Version.ToNormalizedString().Equals(localPackageVersion, StringComparison.OrdinalIgnoreCase) && string.Equals(localPackageInstallationArgs, installationArgs); } } return(isInstalled); }
public async Task <SiteExtensionInfo> GetRemoteExtension(string id, string version, string feedUrl) { ITracer tracer = _traceFactory.GetTracer(); SiteExtensionInfo info = GetPreInstalledExtension(id); if (info != null) { return(info); } SourceRepository remoteRepo = GetRemoteRepository(feedUrl); UIPackageMetadata package = null; if (string.IsNullOrWhiteSpace(version)) { using (tracer.Step("Version is null, search latest package by id: {0}", id)) { package = await remoteRepo.GetLatestPackageById(id); } } else { using (tracer.Step("Search package by id: {0} and version: {1}", id, version)) { package = await remoteRepo.GetPackageByIdentity(id, version); } } if (package == null) { tracer.Trace("No package found with id: {0} and version: {1}", id, version); return(null); } return(await ConvertRemotePackageToSiteExtensionInfo(package, feedUrl)); }
// can be called concurrently if metaDataResource is provided internal static async Task <UIPackageMetadata> GetLatestPackageByIdFromMetaRes(this UIMetadataResource metadataResource, string packageId, bool includePrerelease = true, bool includeUnlisted = false) { UIPackageMetadata latestPackage = null; IEnumerable <UIPackageMetadata> packages = await metadataResource.GetMetadata(packageId, includePrerelease, includeUnlisted, token : CancellationToken.None); foreach (var p in packages) { if (latestPackage == null || latestPackage.Identity.Version < p.Identity.Version) { latestPackage = p; } } // If we couldn't find any listed version, fall back to looking for unlisted versions, to avoid failing completely. // Reasoning is that if all the versions have been unlisted, it should still be possible to install it by // explicit id, even without specifying a version if (latestPackage == null && !includeUnlisted) { latestPackage = await GetLatestPackageByIdFromMetaRes(metadataResource, packageId, includePrerelease, includeUnlisted : true); } return(latestPackage); }
private async Task<SiteExtensionInfo> ConvertRemotePackageToSiteExtensionInfo(UIPackageMetadata package, string feedUrl) { return await CheckRemotePackageLatestVersion(new SiteExtensionInfo(package), feedUrl); }
private async Task<SiteExtensionInfo> ConvertLocalPackageToSiteExtensionInfo(UIPackageMetadata package, bool checkLatest, ITracer tracer = null) { if (package == null) { return null; } var info = new SiteExtensionInfo(package); if (IsInstalledToWebRoot(info.Id)) { info.Type = SiteExtensionInfo.SiteExtensionType.WebRoot; } SetLocalInfo(info); await TryCheckLocalPackageLatestVersionFromRemote(info, checkLatest, tracer); return info; }
/// <summary> /// <para>1. Download package</para> /// <para>2. Generate xdt file if not exist</para> /// <para>3. Deploy site extension job</para> /// <para>4. Execute install.cmd if exist</para> /// </summary> private async Task<UIPackageMetadata> InstallExtension(UIPackageMetadata package, string installationDirectory, string feedUrl) { ITracer tracer = _traceFactory.GetTracer(); try { if (FileSystemHelpers.DirectoryExists(installationDirectory)) { FileSystemHelpers.DeleteDirectorySafe(installationDirectory); } SourceRepository remoteRepo = GetRemoteRepository(feedUrl); // Copy content folder // Copy nupkg file for package list/lookup FileSystemHelpers.CreateDirectory(installationDirectory); // package path from local repo string packageLocalFilePath = GetNuGetPackageFile(package.Identity.Id, package.Identity.Version.ToString()); using (tracer.Step("Download site extension: {0}", package.Identity)) { await remoteRepo.DownloadPackageToFolder(package.Identity, installationDirectory, pathToLocalCopyOfNudpk: packageLocalFilePath); } // If there is no xdt file, generate default. using (tracer.Step("Check if applicationhost.xdt file existed.")) { GenerateApplicationHostXdt(installationDirectory, '/' + package.Identity.Id, isPreInstalled: false, tracer: tracer); } using (tracer.Step("Trigger site extension job")) { OperationManager.Attempt(() => DeploySiteExtensionJobs(package.Identity.Id)); } var externalCommandFactory = new ExternalCommandFactory(_environment, _settings, installationDirectory); string installScript = Path.Combine(installationDirectory, _installScriptName); if (FileSystemHelpers.FileExists(installScript)) { using (tracer.Step("Execute install.cmd")) { OperationManager.Attempt(() => { Executable exe = externalCommandFactory.BuildCommandExecutable(installScript, installationDirectory, _settings.GetCommandIdleTimeout(), NullLogger.Instance); exe.ExecuteWithProgressWriter(NullLogger.Instance, _traceFactory.GetTracer(), String.Empty); }); } } } catch (Exception ex) { tracer.TraceError(ex); FileSystemHelpers.DeleteDirectorySafe(installationDirectory); throw; } return await _localRepository.GetLatestPackageById(package.Identity.Id); }
/// <summary> /// <para>1. Download package</para> /// <para>2. Generate xdt file if not exist</para> /// <para>3. Deploy site extension job</para> /// <para>4. Execute install.cmd if exist</para> /// </summary> private async Task<UIPackageMetadata> InstallExtension(UIPackageMetadata package, string installationDirectory, string feedUrl, SiteExtensionInfo.SiteExtensionType type, ITracer tracer) { try { EnsureInstallationEnviroment(installationDirectory, tracer); string packageLocalFilePath = GetNuGetPackageFile(package.Identity.Id, package.Identity.Version.ToNormalizedString()); bool packageExisted = FileSystemHelpers.DirectoryExists(installationDirectory); SourceRepository remoteRepo = GetRemoteRepository(feedUrl); using (tracer.Step("Download site extension: {0}", package.Identity)) { string extractPath = installationDirectory; if (SiteExtensionInfo.SiteExtensionType.WebRoot == type) { extractPath = _environment.WebRootPath; FileSystemHelpers.EnsureDirectory(extractPath); } // Copy/update content folder // Copy/update nupkg file for package list/lookup if (packageExisted) { await remoteRepo.UpdateLocalPackage(_localRepository, package.Identity, extractPath, packageLocalFilePath, tracer); } else { FileSystemHelpers.EnsureDirectory(installationDirectory); await remoteRepo.DownloadPackageToFolder(package.Identity, extractPath, packageLocalFilePath); } if (SiteExtensionInfo.SiteExtensionType.WebRoot == type) { // if install to WebRoot, check if there is any xdt file come with package // if there is one, move it to site extension folder string xdtFile = Path.Combine(extractPath, Constants.ApplicationHostXdtFileName); if (File.Exists(xdtFile)) { tracer.Trace("Use xdt file from package."); string newXdtFile = Path.Combine(installationDirectory, Constants.ApplicationHostXdtFileName); tracer.Trace("Moving {0} to {1}", xdtFile, newXdtFile); FileSystemHelpers.MoveFile(xdtFile, newXdtFile); } else { tracer.Trace("No xdt file come with package."); } } } // ignore below action if we install packge to wwwroot if (SiteExtensionInfo.SiteExtensionType.WebRoot != type) { // If there is no xdt file, generate default. using (tracer.Step("Check if applicationhost.xdt file existed.")) { GenerateApplicationHostXdt(installationDirectory, '/' + package.Identity.Id, isPreInstalled: false, tracer: tracer); } using (tracer.Step("Trigger site extension job")) { OperationManager.Attempt(() => DeploySiteExtensionJobs(package.Identity.Id)); } var externalCommandFactory = new ExternalCommandFactory(_environment, _settings, installationDirectory); string installScript = Path.Combine(installationDirectory, _installScriptName); if (FileSystemHelpers.FileExists(installScript)) { using (tracer.Step("Execute install.cmd")) { OperationManager.Attempt(() => { Executable exe = externalCommandFactory.BuildCommandExecutable(installScript, installationDirectory, _settings.GetCommandIdleTimeout(), NullLogger.Instance); exe.ExecuteWithProgressWriter(NullLogger.Instance, _traceFactory.GetTracer(), String.Empty); }); } } } } catch (Exception ex) { tracer.TraceError(ex); FileSystemHelpers.DeleteDirectorySafe(installationDirectory); throw; } return await _localRepository.GetLatestPackageById(package.Identity.Id); }
private async Task <SiteExtensionInfo> ConvertLocalPackageToSiteExtensionInfo(UIPackageMetadata package, bool checkLatest, ITracer tracer = null) { if (package == null) { return(null); } var info = new SiteExtensionInfo(package); if (IsInstalledToWebRoot(info.Id)) { info.Type = SiteExtensionInfo.SiteExtensionType.WebRoot; } SetLocalInfo(info); await TryCheckLocalPackageLatestVersionFromRemote(info, checkLatest, tracer); return(info); }
private async Task<SiteExtensionInfo> ConvertLocalPackageToSiteExtensionInfo(UIPackageMetadata package, bool checkLatest) { if (package == null) { return null; } var info = new SiteExtensionInfo(package); SetLocalInfo(info); await TryCheckLocalPackageLatestVersionFromRemote(info, checkLatest); return info; }
private async Task <SiteExtensionInfo> ConvertRemotePackageToSiteExtensionInfo(UIPackageMetadata package, string feedUrl, UIMetadataResource metadataResource) { // convert uipackagemetadata structure to siteextensioninfo structure var siteExtensionInfo = new SiteExtensionInfo(package); siteExtensionInfo.FeedUrl = feedUrl; // check existing local site extension version and update the field "LocalIsLatestVersion" in siteextensioninfo return(await CheckRemotePackageLatestVersion(siteExtensionInfo, metadataResource)); }
private async Task <SiteExtensionInfo> ConvertLocalPackageToSiteExtensionInfo(UIPackageMetadata package, bool checkLatest) { if (package == null) { return(null); } var info = new SiteExtensionInfo(package); SetLocalInfo(info); await TryCheckLocalPackageLatestVersionFromRemote(info, checkLatest); return(info); }
/// <summary> /// <para> Return false if the installation arguments are different. Otherwise,</para> /// <para> Return true if any of below cases is satisfied:</para> /// <para> 1) Package with same version and from same feed already exist in local repo</para> /// <para> 2) If given feedUrl is null</para> /// <para> Try to use feed from local package, if feed from local package also null, fallback to default feed</para> /// <para> Check if version from query is same as local package</para> /// <para> 3) If given version and feedUrl are null</para> /// <para> Try to use feed from local package, if feed from local package also null, fallback to default feed</para> /// <para> Check if version from query is same as local package</para> /// </summary> private async Task <bool> IsSiteExtensionInstalled(string id, string version, string feedUrl, string installationArgs) { ITracer tracer = _traceFactory.GetTracer(); JsonSettings siteExtensionSettings = GetSettingManager(id); string localPackageVersion = siteExtensionSettings.GetValue(_versionSetting); string localPackageFeedUrl = siteExtensionSettings.GetValue(_feedUrlSetting); string localPackageInstallationArgs = siteExtensionSettings.GetValue(_installationArgs); NuGetVersion localPkgVer = null; NuGetVersion lastFoundVer = null; bool isInstalled = false; // Shortcircuit check: if the installation arguments do not match, then we should return false here to avoid other checks which are now unnecessary. if (!string.Equals(localPackageInstallationArgs, installationArgs)) { return(false); } if (!string.IsNullOrEmpty(localPackageVersion)) { localPkgVer = NuGetVersion.Parse(localPackageVersion); } // Try to use given feed // If given feed is null, try with feed that from local package // And GetRemoteRepositories will fallback to use default feed if pass in feed param is null IEnumerable <SourceRepository> remoteRepos = GetRemoteRepositories(feedUrl ?? localPackageFeedUrl); foreach (SourceRepository rr in remoteRepos) { // case 1 and 2 if (!string.IsNullOrWhiteSpace(version) && version.Equals(localPackageVersion, StringComparison.OrdinalIgnoreCase) && rr.PackageSource.Source.Equals(localPackageFeedUrl, StringComparison.OrdinalIgnoreCase)) { isInstalled = true; } else if (string.IsNullOrWhiteSpace(version) && string.IsNullOrWhiteSpace(feedUrl) && string.Equals(localPackageInstallationArgs, installationArgs)) { // case 3 UIPackageMetadata remotePackage = await rr.GetLatestPackageByIdFromSrcRepo(id); if (remotePackage != null) { tracer.Trace("Found version: {0} on feed: {1}", remotePackage.Identity.Version.ToNormalizedString(), rr.PackageSource.Source); if (lastFoundVer == null || lastFoundVer < remotePackage.Identity.Version) { lastFoundVer = remotePackage.Identity.Version; } } } } if (lastFoundVer != null && localPkgVer != null && lastFoundVer <= localPkgVer) { isInstalled = true; } return(isInstalled); }
/// <summary> /// <para>1. Download package</para> /// <para>2. Generate xdt file if not exist</para> /// <para>3. Deploy site extension job</para> /// <para>4. Execute install.cmd if exist</para> /// </summary> private async Task <UIPackageMetadata> InstallExtension(UIPackageMetadata package, string installationDirectory, SourceRepository remoteRepo, SiteExtensionInfo.SiteExtensionType type, ITracer tracer, string installationArgs) { try { EnsureInstallationEnviroment(installationDirectory, tracer); string packageLocalFilePath = GetNuGetPackageFile(package.Identity.Id, package.Identity.Version.ToNormalizedString()); bool packageExisted = FileSystemHelpers.DirectoryExists(installationDirectory); using (tracer.Step("Download site extension: {0}", package.Identity)) { string extractPath = installationDirectory; if (SiteExtensionInfo.SiteExtensionType.WebRoot == type) { extractPath = _environment.WebRootPath; FileSystemHelpers.EnsureDirectory(extractPath); } // Copy/update content folder // Copy/update nupkg file for package list/lookup if (packageExisted) { await remoteRepo.UpdateLocalPackage(_localRepository, package.Identity, extractPath, packageLocalFilePath, tracer); } else { FileSystemHelpers.EnsureDirectory(installationDirectory); await remoteRepo.DownloadPackageToFolder(package.Identity, extractPath, packageLocalFilePath); } if (SiteExtensionInfo.SiteExtensionType.WebRoot == type) { // if install to WebRoot, check if there is any xdt or scmXdt file come with package // if there is, move it to site extension folder string xdtFile = Path.Combine(extractPath, Constants.ApplicationHostXdtFileName); string scmXdtFile = Path.Combine(extractPath, Constants.ScmApplicationHostXdtFileName); bool findXdts = false; if (FileSystemHelpers.FileExists(xdtFile)) { tracer.Trace("Use xdt file from package."); string newXdtFile = Path.Combine(installationDirectory, Constants.ApplicationHostXdtFileName); tracer.Trace("Moving {0} to {1}", xdtFile, newXdtFile); FileSystemHelpers.MoveFile(xdtFile, newXdtFile); findXdts = true; } // if the siteextension applies to both main site and the scm site if (FileSystemHelpers.FileExists(scmXdtFile)) { tracer.Trace("Use scmXdt file from package."); string newScmXdtFile = Path.Combine(installationDirectory, Constants.ScmApplicationHostXdtFileName); tracer.Trace("Moving {0} to {1}", scmXdtFile, newScmXdtFile); FileSystemHelpers.MoveFile(scmXdtFile, newScmXdtFile); findXdts = true; } if (!findXdts) { tracer.Trace("No xdt file come with package."); } } } // ignore below action if we install packge to wwwroot if (SiteExtensionInfo.SiteExtensionType.WebRoot != type) { using (tracer.Step("Check if applicationHost.xdt or scmApplicationHost.xdt file existed.")) { GenerateDefaultScmApplicationHostXdt(installationDirectory, '/' + package.Identity.Id, tracer: tracer); } using (tracer.Step("Trigger site extension job")) { OperationManager.Attempt(() => DeploySiteExtensionJobs(package.Identity.Id)); } var externalCommandFactory = new ExternalCommandFactory(_environment, _settings, installationDirectory); string installScript = Path.Combine(installationDirectory, _installScriptName); if (FileSystemHelpers.FileExists(installScript)) { using (tracer.Step("Execute install.cmd")) { OperationManager.Attempt(() => { Executable exe = externalCommandFactory.BuildCommandExecutable(installScript, installationDirectory, _settings.GetCommandIdleTimeout(), NullLogger.Instance); exe.ExecuteWithProgressWriter(NullLogger.Instance, _traceFactory.GetTracer(), installationArgs ?? String.Empty); }); } } } } catch (Exception ex) { tracer.TraceError(ex); FileSystemHelpers.DeleteDirectorySafe(installationDirectory); throw; } return(await _localRepository.GetLatestPackageByIdFromSrcRepo(package.Identity.Id)); }
private async Task <SiteExtensionInfo> TryInstallExtension(string id, string version, string feedUrl, SiteExtensionInfo.SiteExtensionType type, ITracer tracer, string installationArgs) { SiteExtensionInfo info = null; HttpStatusCode status = HttpStatusCode.OK; // final status when success bool alreadyInstalled = false; try { // Check if site extension already installed (id, version, feedUrl), if already install with correct installation arguments then return right away if (await this.IsSiteExtensionInstalled(id, version, feedUrl, installationArgs)) { // package already installed, return package from local repo. tracer.Trace("Package {0} with version {1} from {2} with installation arguments '{3}' already installed.", id, version, feedUrl, installationArgs); info = await GetLocalExtension(id); alreadyInstalled = true; } else { JsonSettings siteExtensionSettings = GetSettingManager(id); feedUrl = (string.IsNullOrEmpty(feedUrl) ? siteExtensionSettings.GetValue(_feedUrlSetting) : feedUrl); IEnumerable <SourceRepository> remoteRepos = GetRemoteRepositories(feedUrl); UIPackageMetadata localPackage = null; UIPackageMetadata repoPackage = null; SourceRepository remoteRepo = null; if (this.IsInstalledToWebRoot(id)) { // override WebRoot type from setting // WebRoot is a special type that install package to wwwroot, when perform update we need to update new content to wwwroot even if type is not specified type = SiteExtensionInfo.SiteExtensionType.WebRoot; } if (string.IsNullOrWhiteSpace(version)) { using (tracer.Step("Version is null, search latest package by id: {0}, will not search for unlisted package.", id)) { foreach (SourceRepository rr in remoteRepos) { repoPackage = await rr.GetLatestPackageByIdFromSrcRepo(id); if (repoPackage != null) { remoteRepo = rr; break; } } } } else { using (tracer.Step("Search package by id: {0} and version: {1}, will also search for unlisted package.", id, version)) { foreach (SourceRepository rr in remoteRepos) { repoPackage = await rr.GetPackageByIdentity(id, version); if (repoPackage != null) { remoteRepo = rr; break; } } } } if (repoPackage != null) { Debug.Assert(remoteRepo != null, "remote SourceRepository should not be null!"); using (tracer.Step("Install package: {0}.", id)) { string installationDirectory = GetInstallationDirectory(id); localPackage = await InstallExtension(repoPackage, installationDirectory, remoteRepo, type, tracer, installationArgs); siteExtensionSettings.SetValues(new KeyValuePair <string, JToken>[] { new KeyValuePair <string, JToken>(_versionSetting, localPackage.Identity.Version.ToNormalizedString()), new KeyValuePair <string, JToken>(_feedUrlSetting, feedUrl), new KeyValuePair <string, JToken>(_installUtcTimestampSetting, DateTime.UtcNow.ToString("u")), new KeyValuePair <string, JToken>(_packageType, Enum.GetName(typeof(SiteExtensionInfo.SiteExtensionType), type)), new KeyValuePair <string, JToken>(_installationArgs, installationArgs) }); } } info = await ConvertLocalPackageToSiteExtensionInfo(localPackage, checkLatest : true, tracer : tracer); } } catch (FileNotFoundException ex) { _analytics.UnexpectedException( ex, method: "PUT", path: string.Format(CultureInfo.InvariantCulture, "/api/siteextensions/{0}", id), result: Constants.SiteExtensionProvisioningStateFailed, message: string.Format(CultureInfo.InvariantCulture, "{{\"version\": {0}, \"feed_url\": {1}}}", version, feedUrl), trace: false); tracer.TraceError(ex); info = new SiteExtensionInfo(); info.Id = id; info.ProvisioningState = Constants.SiteExtensionProvisioningStateFailed; info.Comment = ex.ToString(); status = HttpStatusCode.NotFound; } catch (WebException ex) { _analytics.UnexpectedException( ex, method: "PUT", path: string.Format(CultureInfo.InvariantCulture, "/api/siteextensions/{0}", id), result: Constants.SiteExtensionProvisioningStateFailed, message: string.Format(CultureInfo.InvariantCulture, "{{\"version\": {0}, \"feed_url\": {1}}}", version, feedUrl), trace: false); tracer.TraceError(ex); info = new SiteExtensionInfo(); info.Id = id; info.ProvisioningState = Constants.SiteExtensionProvisioningStateFailed; info.Comment = ex.ToString(); status = HttpStatusCode.BadRequest; } catch (InvalidEndpointException ex) { _analytics.UnexpectedException(ex, trace: false); tracer.TraceError(ex); info = new SiteExtensionInfo(); info.Id = id; info.ProvisioningState = Constants.SiteExtensionProvisioningStateFailed; info.Comment = ex.ToString(); status = HttpStatusCode.BadRequest; } catch (Exception ex) { _analytics.UnexpectedException( ex, method: "PUT", path: string.Format(CultureInfo.InvariantCulture, "/api/siteextensions/{0}", id), result: Constants.SiteExtensionProvisioningStateFailed, message: string.Format(CultureInfo.InvariantCulture, "{{\"version\": {0}, \"feed_url\": {1}}}", version, feedUrl), trace: false); tracer.TraceError(ex); info = new SiteExtensionInfo(); info.Id = id; info.ProvisioningState = Constants.SiteExtensionProvisioningStateFailed; info.Comment = ex.ToString(); status = HttpStatusCode.BadRequest; } if (info == null) { // treat this as an error case since no result return from repo _analytics.UnexpectedException( new FileNotFoundException(id), method: "PUT", path: string.Format(CultureInfo.InvariantCulture, "/api/siteextensions/{0}", id), result: Constants.SiteExtensionProvisioningStateFailed, message: string.Format(CultureInfo.InvariantCulture, "{{\"version\": {0}, \"feed_url\": {1}}}", version, feedUrl), trace: false); info = new SiteExtensionInfo(); info.ProvisioningState = Constants.SiteExtensionProvisioningStateFailed; info.Comment = string.Format(Constants.SiteExtensionProvisioningStateNotFoundMessageFormat, id); status = HttpStatusCode.NotFound; } else if (!string.Equals(Constants.SiteExtensionProvisioningStateFailed, info.ProvisioningState, StringComparison.OrdinalIgnoreCase)) { info.ProvisioningState = Constants.SiteExtensionProvisioningStateSucceeded; info.Comment = null; } using (tracer.Step("Update arm settings for {0} installation. Status: {1}", id, status)) { SiteExtensionStatus armSettings = new SiteExtensionStatus(_environment.SiteExtensionSettingsPath, id, tracer); armSettings.ReadSiteExtensionInfo(info); armSettings.Status = status; armSettings.Operation = alreadyInstalled ? null : Constants.SiteExtensionOperationInstall; } return(info); }
private async Task <SiteExtensionInfo> TryInstallExtension(string id, string version, string feedUrl, SiteExtensionInfo.SiteExtensionType type, ITracer tracer) { SiteExtensionInfo info = null; HttpStatusCode status = HttpStatusCode.OK; // final status when success bool alreadyInstalled = false; if (_preInstalledExtensionDictionary.ContainsKey(id)) { tracer.Trace("Pre-installed site extension found: {0}, not going to perform new installation.", id); info = EnablePreInstalledExtension(_preInstalledExtensionDictionary[id], tracer); alreadyInstalled = true; } else { try { // Check if site extension already installed (id, version, feedUrl), if already install return right away if (await this.IsSiteExtensionInstalled(id, version, feedUrl)) { // package already installed, return package from local repo. tracer.Trace("Package {0} with version {1} from {2} already installed.", id, version, feedUrl); info = await GetLocalExtension(id); alreadyInstalled = true; } else { JsonSettings siteExtensionSettings = GetSettingManager(id); feedUrl = (string.IsNullOrEmpty(feedUrl) ? siteExtensionSettings.GetValue(_feedUrlSetting) : feedUrl); SourceRepository remoteRepo = GetRemoteRepository(feedUrl); UIPackageMetadata localPackage = null; UIPackageMetadata repoPackage = null; if (string.IsNullOrWhiteSpace(version)) { using (tracer.Step("Version is null, search latest package by id: {0}, will not search for unlisted package.", id)) { repoPackage = await remoteRepo.GetLatestPackageById(id); } } else { using (tracer.Step("Search package by id: {0} and version: {1}, will also search for unlisted package.", id, version)) { repoPackage = await remoteRepo.GetPackageByIdentity(id, version); } } if (repoPackage != null) { using (tracer.Step("Install package: {0}.", id)) { string installationDirectory = GetInstallationDirectory(id); localPackage = await InstallExtension(repoPackage, installationDirectory, feedUrl, type, tracer); siteExtensionSettings.SetValues(new KeyValuePair <string, JToken>[] { new KeyValuePair <string, JToken>(_versionSetting, localPackage.Identity.Version.ToNormalizedString()), new KeyValuePair <string, JToken>(_feedUrlSetting, feedUrl), new KeyValuePair <string, JToken>(_installUtcTimestampSetting, DateTime.UtcNow.ToString("u")), new KeyValuePair <string, JToken>(_packageType, Enum.GetName(typeof(SiteExtensionInfo.SiteExtensionType), type)) }); } } info = await ConvertLocalPackageToSiteExtensionInfo(localPackage, checkLatest : true, tracer : tracer); } } catch (FileNotFoundException ex) { _analytics.UnexpectedException( ex, method: "PUT", path: string.Format(CultureInfo.InvariantCulture, "/api/siteextensions/{0}", id), result: Constants.SiteExtensionProvisioningStateFailed, message: string.Format(CultureInfo.InvariantCulture, "{{\"version\": {0}, \"feed_url\": {1}}}", version, feedUrl), trace: false); tracer.TraceError(ex); info = new SiteExtensionInfo(); info.Id = id; info.ProvisioningState = Constants.SiteExtensionProvisioningStateFailed; info.Comment = string.Format(Constants.SiteExtensionProvisioningStateNotFoundMessageFormat, id); status = HttpStatusCode.NotFound; } catch (WebException ex) { _analytics.UnexpectedException( ex, method: "PUT", path: string.Format(CultureInfo.InvariantCulture, "/api/siteextensions/{0}", id), result: Constants.SiteExtensionProvisioningStateFailed, message: string.Format(CultureInfo.InvariantCulture, "{{\"version\": {0}, \"feed_url\": {1}}}", version, feedUrl), trace: false); tracer.TraceError(ex); info = new SiteExtensionInfo(); info.Id = id; info.ProvisioningState = Constants.SiteExtensionProvisioningStateFailed; info.Comment = string.Format(Constants.SiteExtensionProvisioningStateDownloadFailureMessageFormat, id); status = HttpStatusCode.BadRequest; } catch (InvalidEndpointException ex) { _analytics.UnexpectedException(ex, trace: false); tracer.TraceError(ex); info = new SiteExtensionInfo(); info.Id = id; info.ProvisioningState = Constants.SiteExtensionProvisioningStateFailed; info.Comment = ex.Message; status = HttpStatusCode.BadRequest; } catch (Exception ex) { _analytics.UnexpectedException( ex, method: "PUT", path: string.Format(CultureInfo.InvariantCulture, "/api/siteextensions/{0}", id), result: Constants.SiteExtensionProvisioningStateFailed, message: string.Format(CultureInfo.InvariantCulture, "{{\"version\": {0}, \"feed_url\": {1}}}", version, feedUrl), trace: false); tracer.TraceError(ex); info = new SiteExtensionInfo(); info.Id = id; info.ProvisioningState = Constants.SiteExtensionProvisioningStateFailed; info.Comment = string.Format(Constants.SiteExtensionProvisioningStateInvalidPackageMessageFormat, id); status = HttpStatusCode.BadRequest; } } if (info == null) { // treat this as an error case since no result return from repo _analytics.UnexpectedException( new FileNotFoundException(id), method: "PUT", path: string.Format(CultureInfo.InvariantCulture, "/api/siteextensions/{0}", id), result: Constants.SiteExtensionProvisioningStateFailed, message: string.Format(CultureInfo.InvariantCulture, "{{\"version\": {0}, \"feed_url\": {1}}}", version, feedUrl), trace: false); info = new SiteExtensionInfo(); info.ProvisioningState = Constants.SiteExtensionProvisioningStateFailed; info.Comment = string.Format(Constants.SiteExtensionProvisioningStateNotFoundMessageFormat, id); status = HttpStatusCode.NotFound; } else if (!string.Equals(Constants.SiteExtensionProvisioningStateFailed, info.ProvisioningState, StringComparison.OrdinalIgnoreCase)) { info.ProvisioningState = Constants.SiteExtensionProvisioningStateSucceeded; info.Comment = null; } using (tracer.Step("Update arm settings for {0} installation. Status: {1}", id, status)) { SiteExtensionStatus armSettings = new SiteExtensionStatus(_environment.SiteExtensionSettingsPath, id, tracer); armSettings.ReadSiteExtensionInfo(info); armSettings.Status = status; armSettings.Operation = alreadyInstalled ? null : Constants.SiteExtensionOperationInstall; } return(info); }
private async Task <SiteExtensionInfo> ConvertRemotePackageToSiteExtensionInfo(UIPackageMetadata package, string feedUrl) { return(await CheckRemotePackageLatestVersion(new SiteExtensionInfo(package), feedUrl)); }