/// <summary> /// Get's a shared directory that will be used to store the ACME challenge responses /// </summary> /// <returns></returns> public string GetWellKnownSharedPathForApplication() { var result = Path.Combine(this.GetAcmeTemporarySiteRootForApplication(), ".well-known"); UtilsSystem.DirectoryCreateIfNotExists(result); return(result); }
/// <summary> /// Execute the opreation... /// </summary> public void execute(IniFileManager manager, Deployment deployment) { var val = deployment.ExpandPaths(this.value); switch (this.ensureDir) { case "dir": UtilsSystem.EnsureDirectoryExists(val, true); break; case "file": UtilsSystem.EnsureDirectoryExists(val, false); break; } // If this is a directory or file, make sure we properly quote when // writting the PHP.ini, because whitespaces in a path will break // most settings if (this.ensureDir == "dir" || this.ensureDir == "file") { if (!val.StartsWith("\"")) { val = "\"" + val + "\""; } } if (this.multivalue) { manager.UpdateOrCreateMultivalueDirective(this.key, val, this.section ?? "AUTODEPLOY", this.comment, this.host); } else { manager.UpdateOrCreateDirective(this.key, val, this.section ?? "AUTODEPLOY", this.comment, this.host); } }
/// <summary> /// Grab from a settings file. /// </summary> /// <param name="path"></param> /// <param name="logger"></param> public void PopulateFromSettingsFile(string path, ILoggerInterface logger) { string file = UtilsSystem.CombinePaths(path, "artifact-settings.yml"); if (!File.Exists(file)) { return; } var configfile = new Configuration.YamlConfigurationFile(); try { // This file might be malformed, do not crash and let other // environment information sources have their chance configfile.ParseFromFile(file); } catch (Exception e) { logger.LogException(new Exception("Error parsing file: " + file, e)); return; } // Parse the artifact settings... this.branch = configfile.GetStringValue("repo-branch", null); this.commit_sha = configfile.GetStringValue("repo-commit", null); this.version = configfile.GetStringValue("build-id", null); }
public void undeploy(bool isUninstall = false) { // Not that we want to accidentally delete contents and files // for an application... if (!isUninstall) { return; } var diskSettings = this.DeployerSettings.castTo <DiskServiceSettings>(); var mounts = this.Deployment.GetSettingCollection <DiskStore>($"service.{diskSettings.id}"); foreach (var m in mounts.Values) { // Most of the time this directory will not exist, as the base storage deployer will already have // deleted the application folder. But for "local" installed applications, this removes // the symlinks. if (!string.IsNullOrWhiteSpace(m.junctionRealPath) && Directory.Exists(m.junctionRealPath)) { UtilsJunction.RemoveJunction(m.junctionRealPath); } if (Directory.Exists(m.path)) { UtilsSystem.DeleteDirectory(m.path, this.Logger); } } var baseStoragePath = this.GetStoragePath(diskSettings); if (!string.IsNullOrWhiteSpace(baseStoragePath) && Directory.Exists(baseStoragePath)) { UtilsSystem.DeleteDirectory(baseStoragePath, this.Logger); } }
/// <summary> /// /// </summary> /// <param name="dir"></param> public void CleanUpDir(string dir) { if (!Directory.Exists(dir)) { return; } foreach (var difo in new DirectoryInfo(dir).EnumerateDirectories()) { foreach (var appDifo in difo.EnumerateDirectories()) { try { // Delete folders older than 1 month if ((DateTime.Now - appDifo.LastWriteTime).TotalDays > 30) { UtilsSystem.DeleteDirectory(appDifo.FullName, this.Logger); this.Logger.LogInfo(true, "Deleted temp dir: {0}", appDifo.FullName); } } catch (Exception e) { this.Logger.LogException(e); } } } }
/// <summary> /// Get a deployer for the installed application. /// </summary> /// <param name="globalSettings">The global settings.</param> /// <param name="installedApplicationSettings">The installed application settings.</param> /// <param name="logger">The logger.</param> public ApplicationDeployer( EnvironmentSettings globalSettings, InstalledApplication installedApplicationSettings, ILoggerInterface logger) { this.GlobalSettings = globalSettings; this.installedAppSettings = installedApplicationSettings; this.Logger = logger; if (this.GlobalSettings == null) { throw new InvalidDataException("settings argument cannot be null."); } if (this.installedAppSettings == null) { throw new Exception("installedApplicationSettings argument cannot be null."); } // Try to grab previous deployment... this.activeDeploymentPathStorage = UtilsSystem.CombinePaths(globalSettings.activeDeploymentDir, "active." + this.installedAppSettings.GetId() + ".json"); if (File.Exists(this.activeDeploymentPathStorage)) { this.DeploymentActive = Deployment.InstanceFromPath(this.activeDeploymentPathStorage, globalSettings); } }
/// <summary> /// Get an instance of SslCertificateProviderService /// </summary> public SslCertificateProviderService( ILoggerInterface logger, string appId, EnvironmentSettings globalSettings, Deployment deployment) { this.AppPoolUtils = new UtilsAppPool(logger); this.UtilsHosts = new UtilsHosts(logger); this.MockEnvironment = UtilsSystem.RunningInContinuousIntegration() || UnitTestDetector.IsRunningInTests || Debugger.IsAttached; // Everything performed against the staging API needs to be kept apart, including signer, etc... this.StoragePath = Path.Combine(globalSettings.GetDefaultContentStorage().path, "letsencrypt" + (this.MockEnvironment ? "_mock" : null)); UtilsSystem.EnsureDirectoryExists(this.StoragePath, true); // If CCS is available, use that, otherwise use the central content storage string sslRenewalStateStorePath = UtilsIis.CentralStoreEnabled() ? UtilsIis.CentralStorePath(logger) : globalSettings.GetDefaultContentStorage().path; this.SimpleStoreRenewalStatus = new SimpleStore(Path.Combine(sslRenewalStateStorePath, "_ssl_renewal_state_store"), true); this.Logger = logger; this.AppId = appId; this.Deployment = deployment; this.GlobalSettings = globalSettings; }
/// <summary> /// Waits for a task to stop running (must be in disabled state) /// </summary> /// <param name="t"></param> /// <param name="maxWaitMilliseconds"></param> protected void DisableAndStopTask(Task t, int maxWaitMilliseconds = 30000) { this.Logger.LogInfo(true, "Stopping scheduler task {0} with state {1}", t.Name, t.State); t.Enabled = false; bool hasStopped = UtilsSystem.WaitWhile( () => t.State == TaskState.Running, maxWaitMilliseconds, $"Waiting for task {t.Name} to stop running...", this.Logger); // The task did not stop by itself, so we need to forcefully close it. if (!hasStopped) { this.Logger.LogInfo(true, "Forcefully stopping task {0} ", t.Name); t.Stop(); } // Wait again hasStopped = UtilsSystem.WaitWhile( () => t.State == TaskState.Running, maxWaitMilliseconds, $"Waiting for task {t.Name} to stop...", this.Logger); if (!hasStopped) { this.Logger.LogWarning(false, "Could not stop scheduled task {0}", t.Name); } }
/// <summary> /// All disk storage for this application is pointed to this directory. /// </summary> /// <param name="settings"></param> /// <returns></returns> protected string GetStoragePath(DiskServiceSettings settings) { var storage = this.GlobalSettings.GetDefaultContentStorage(); // We can have an app_setting configuration // to route a whole application to a specific sql server string diskTarget; if (this.Deployment.installedApplicationSettings.configuration["disktarget"] != null) { diskTarget = Convert.ToString(this.Deployment.installedApplicationSettings.configuration["disktarget"]); this.Logger.LogInfo(true, "Custom disk target: " + diskTarget); if (!Directory.Exists(diskTarget)) { throw new Exception("Invalid custom disk target: " + diskTarget); } } else { // Generate a unique "virtual disk" (directory) for this application diskTarget = UtilsSystem.EnsureDirectoryExists(UtilsSystem.CombinePaths( storage.path, "store_" + this.Deployment.installedApplicationSettings.GetId())); } return(diskTarget); }
public override void _sync(object input) { DiskService other = (DiskService)input; var diskSettings = this.DeployerSettings.castTo <DiskServiceSettings>(); var storage = this.GlobalSettings.GetDefaultContentStorage(); // Generate a unique virtual disk for this application DiskServiceSettings otherSettings = other.DeployerSettings.castTo <DiskServiceSettings>(); foreach (var mount in diskSettings.mounts) { string pathOri = UtilsSystem.EnsureDirectoryExists(other.Deployment.GetRuntimeSettingsToDeploy()["services." + otherSettings.id + ".mount.files.path"]); string pathDest = UtilsSystem.EnsureDirectoryExists(this.Deployment.GetRuntimeSettingsToDeploy()["services." + diskSettings.id + ".mount.files.path"]); FileSyncProvider ori = new FileSyncProvider(pathOri); FileSyncProvider dest = new FileSyncProvider(pathDest); SyncOrchestrator agent = new SyncOrchestrator(); agent.LocalProvider = ori; agent.RemoteProvider = dest; agent.Direction = SyncDirectionOrder.Upload; SyncOperationStatistics syncStats = agent.Synchronize(); this.Logger.LogInfo( true, "Synchronization stats \n\n local provider {0} to remote {1}\n upload changes applied {2}\n {3} upload changes failed", pathOri, pathDest, syncStats.UploadChangesApplied, syncStats.UploadChangesFailed); ori.Dispose(); dest.Dispose(); } }
public void TestCdnReplacements() { var sampleHtml = File.ReadAllText(UtilsSystem.GetResourceFileAsPath("samples/samplecdn.html")); var replacer = new CdnHtmlRedirectHelper(); replacer.PrependCdnToUri(sampleHtml, "https://cdnprefix/directory/"); }
/// <summary> /// Delete the artifact's source if it is remote /// </summary> /// <param name="artifact"></param> /// <param name="logger"></param> public static void DeleteIfRemote(this Artifact artifact, ILoggerInterface logger) { if (!artifact.isRemote) { return; } UtilsSystem.DeleteDirectory(artifact.localPath, logger); }
public override void beforeDone() { // We also have a canonical access to the deployed app through a symlink string basePath = this.Deployment.GetSetting("appstorage.base", (string)null, this.Logger); string canonicalPath = UtilsSystem.CombinePaths(this.GlobalSettings.GetDefaultApplicationStorage().path, "_" + this.Deployment.installedApplicationSettings.GetId()); UtilsJunction.EnsureLink(canonicalPath, basePath, this.Logger, false, true); this.Deployment.SetSetting("appstorage.canonical", canonicalPath); }
/// <summary> /// Run an API call and output results directly to a file /// mostly used to download artifacts... /// </summary> /// <param name="uri"></param> /// <param name="localPath"></param> protected void ExecuteApiCallToFile(string uri, string localPath) { UtilsSystem.EnsureDirectoryExists(localPath); var url = this.BaseUri + uri; WebClient client = this.PrepareWebClient(null); client.DownloadFile(url, localPath); }
protected override void ProcessRecord() { ConsoleUtils.RunCode(() => { var logger = new logger.ConsoleLogger(); logger.SetVerbose(true); UtilsSystem.DeleteDirectory(this.Directory, logger, 30); }); }
/// <summary> /// /// </summary> /// <param name="settings"></param> protected void DeployFonts(AppBaseStorageDeployerSettings settings) { // Nada que desplegar if (settings.fonts?.Any() != true) { return; } // TODO: Newer windows versions allow for per-user font registration, we should implement that // because with this approach fonts are installed first come first-served, and cannot be updated // if necessary. Plus we don't know who owns a font, se we can't delete them on cleanup var utilsFont = new UtilsFont(); foreach (var font in settings.fonts.AsIterable()) { // Check that the provided path is a zip with the font var fontSourceZip = Path.Combine(this.Deployment.appPath, font.Path); if (Path.GetExtension(fontSourceZip) != ".zip") { throw new Exception($"Unable to install the font '{font.Path}' because fonts have to be in a .zip file."); } if (!File.Exists(fontSourceZip)) { throw new Exception($"Font file not found '{font.Path}'."); } // We use a know directory var fontTempPath = UtilsSystem.GetTempPath("font-" + Guid.NewGuid()); var fontPersitentTempPath = UtilsSystem.GetTempPath("font-chef"); try { ZipFile.ExtractToDirectory(fontSourceZip, fontTempPath); UtilsSystem.CopyFilesRecursively(new DirectoryInfo(fontTempPath), new DirectoryInfo(fontPersitentTempPath), true, true); utilsFont.InstallFont(fontPersitentTempPath); } finally { UtilsSystem.DeleteDirectory(fontTempPath, this.Logger, 8); // This will some fonts get locked by the native API without explanation try { UtilsSystem.DeleteDirectory(fontPersitentTempPath, this.Logger, 4); } catch { // ignored } } } }
/// <summary> /// Do not deploy applications if we are short on disk space. /// /// Throws an exception if size is below minSize /// </summary> /// <param name="minSize">Defaults to 500Mb</param> protected void CheckDiskSpace(long minSize = 524288000) { var applicationPath = this.GlobalSettings.GetDefaultApplicationStorage().path; long freeSpaceBytes = UtilsSystem.GetTotalFreeSpace(applicationPath); if (freeSpaceBytes < minSize) { throw new Exception($"Insuficient storage [{UtilsSystem.BytesToString(freeSpaceBytes)}] to run deployments in: {applicationPath}"); } }
public void TestSymlinksAreNotRemoved() { var logger = new TestLogsLogger(this, nameof(this.TestSymlinksAreNotRemoved)); string testPath = UtilsSystem.GetTempPath("symlink_test" + Guid.NewGuid()); var pathWebsite = Path.Combine(testPath, "website"); var pathContentsPersistent = Path.Combine(testPath, "content_store_persistent"); Directory.CreateDirectory(pathWebsite); Directory.CreateDirectory(pathContentsPersistent); Directory.CreateDirectory(Path.Combine(pathContentsPersistent, "empty_directory")); string linkedDir = Path.Combine(pathWebsite, "contents"); string linkedDir2 = Path.Combine(pathWebsite, "contents2", "contents"); UtilsSystem.EnsureDirectoryExists(linkedDir); UtilsSystem.EnsureDirectoryExists(linkedDir2); UtilsJunction.EnsureLink(linkedDir, pathContentsPersistent, logger, true, linkType: UtilsJunction.LinkTypeRequest.Junction); UtilsJunction.EnsureLink(linkedDir2, pathContentsPersistent, logger, true, linkType: UtilsJunction.LinkTypeRequest.Symlink); Assert.True(UtilsJunction.IsJunctionOrSymlink(linkedDir)); Assert.True(UtilsJunction.IsJunctionOrSymlink(linkedDir2)); string fileInContentsPeristent = Path.Combine(pathContentsPersistent, "test.txt"); string fileInSymlinkDir = Path.Combine(linkedDir, "test.txt"); Assert.Equal(fileInContentsPeristent, UtilsJunction.ResolvePath(fileInSymlinkDir)); string fileInContentsPeristent2 = Path.Combine(pathContentsPersistent, "test2.txt"); string fileInSymlinkDir2 = Path.Combine(linkedDir2, "test2.txt"); Assert.Equal(fileInContentsPeristent2, UtilsJunction.ResolvePath(fileInSymlinkDir2)); File.WriteAllText(fileInSymlinkDir, "testfile"); File.WriteAllText(fileInSymlinkDir2, "testfile"); Assert.True(File.Exists(fileInSymlinkDir), $"File exists {fileInSymlinkDir}"); Assert.True(File.Exists(fileInSymlinkDir2), $"File exists {fileInSymlinkDir2}"); Assert.True(File.Exists(fileInContentsPeristent), $"File exists {fileInContentsPeristent}"); Assert.True(File.Exists(fileInContentsPeristent2), $"File exists {fileInContentsPeristent2}"); // If we delete the directory containing the symlink, the file still exists UtilsSystem.DeleteDirectory(pathWebsite, logger); Assert.False(Directory.Exists(pathWebsite), "Directory exists " + pathWebsite); Assert.False(File.Exists(fileInSymlinkDir), $"File exists {fileInSymlinkDir}"); Assert.True(File.Exists(fileInContentsPeristent), $"File exists {fileInContentsPeristent}"); Assert.False(File.Exists(fileInSymlinkDir2), $"File exists {fileInSymlinkDir2}"); Assert.True(File.Exists(fileInContentsPeristent2), $"File exists {fileInContentsPeristent2}"); Directory.Delete(testPath, true); }
/// <summary> /// Cause initialization of Certes /// </summary> /// <param name="signerPath"></param> /// <param name="registrationPath"></param> /// <param name="email"></param> public void InitRegistration(string signerPath, string registrationPath, string email) { // Signer path y registrationpath son específicos de la librería vieja, pero usamos el directorio que indican // para guardar la configuración del registro de cuenta de certes. Como el registration depende del entorno, ponemos la AcmeUri en el hash del propio // nombre del fichero. string settingsFilePath = Path.Combine(Path.GetDirectoryName(signerPath), UtilsEncryption.GetMD5(email + "::" + this.AcmeUri), "certes.json"); UtilsSystem.EnsureDirectoryExists(settingsFilePath); // Initialization and renewal/revocation handling // We get the CertesWrapper object, that will do most of the job. // RS256 Let's generate a new key (RSA is good enough IMHO) var serviceUri = new Uri(this.AcmeUri); this.Logger.LogInfo(true, "Using Acme URI: " + serviceUri); CertesSettings settings; this.HttpClient = new HttpClient(); this.AcmeHttpClient = new AcmeHttpClient(serviceUri, this.HttpClient); if (File.Exists(settingsFilePath)) { // Si ya teníamos unos settings, siginifica que la cuenta ya está registrada settings = JsonConvert.DeserializeObject <CertesSettings>(File.ReadAllText(settingsFilePath)); this.AcmeContext = new AcmeContext(serviceUri, KeyFactory.FromDer(settings.Key), this.AcmeHttpClient); } else { // Hay que crear una nueva cuenta con su clave, y registrarla en ACME settings = new CertesSettings() { AccountEmail = email, ServiceUri = serviceUri, Key = KeyFactory.NewKey(KeyAlgorithm.RS256).ToDer() }; // Register the account this.AcmeContext = new AcmeContext(serviceUri, KeyFactory.FromDer(settings.Key), this.AcmeHttpClient); IAccountContext accountCtx = this.AcmeContext.NewAccount(settings.AccountEmail, true).Result; File.WriteAllText(settingsFilePath, JsonConvert.SerializeObject(settings)); Certes.Acme.Resource.Directory directory = this.AcmeContext.GetDirectory().Result; this.Logger.LogInfo(true, $"Successfully registered account {settings.AccountEmail} with certificate authority {serviceUri.AbsoluteUri}"); if ((directory.Meta != null) && (directory.Meta.TermsOfService != null)) { this.Logger.LogInfo(true, $"Please check the ACME Service ToS at: {directory.Meta.TermsOfService}"); } } this.CertesSettings = settings; }
/// <summary> /// /// </summary> /// <param name="filename"></param> /// <returns></returns> protected string GetGlobalStoragePath(string filename) { var environmentSettingsFile = UtilsSystem.EnsureDirectoryExists( UtilsSystem.CombinePaths( Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "iischef", "config", filename)); return(environmentSettingsFile); }
public void TestResolveJunctionPath() { var logger = new TestLogsLogger(this, nameof(this.TestResolveJunctionPath)); string testPath = UtilsSystem.GetTempPath("symlink_test" + Guid.NewGuid()); // Probar resolución de nivel 1 string test1OriginalPath = UtilsSystem.EnsureDirectoryExists(Path.Combine(testPath, "test1"), true); string test1LinkPath = Path.Combine(testPath, "test1_link"); string test1JunctionPath = Path.Combine(testPath, "test1_junction"); UtilsJunction.EnsureLink(test1LinkPath, test1OriginalPath, logger, true, linkType: UtilsJunction.LinkTypeRequest.Symlink); UtilsJunction.EnsureLink(test1JunctionPath, test1OriginalPath, logger, true, linkType: UtilsJunction.LinkTypeRequest.Junction); Assert.Equal(test1OriginalPath, UtilsJunction.ResolvePath(test1LinkPath)); Assert.Equal(test1OriginalPath, UtilsJunction.ResolvePath(test1JunctionPath)); // Probar resolución de subdirectorio existente y no existente string test2OriginalPath = UtilsSystem.EnsureDirectoryExists(Path.Combine(testPath, "test2"), true); string test2LinkPath = Path.Combine(testPath, "test2_link"); string test2JunctionPath = Path.Combine(testPath, "test2_junction"); UtilsJunction.EnsureLink(test2LinkPath, test2OriginalPath, logger, true, linkType: UtilsJunction.LinkTypeRequest.Symlink); UtilsJunction.EnsureLink(test2JunctionPath, test2OriginalPath, logger, true, linkType: UtilsJunction.LinkTypeRequest.Junction); string test2LinkSubDir = UtilsSystem.EnsureDirectoryExists(Path.Combine(test2LinkPath, "sub1", "sub2"), true); string test2JunctionSubDir = UtilsSystem.EnsureDirectoryExists(Path.Combine(test2JunctionPath, "sub3", "sub4"), true); Assert.Equal(Path.Combine(test2OriginalPath, "sub1", "sub2"), UtilsJunction.ResolvePath(test2LinkSubDir)); Assert.Equal(Path.Combine(test2OriginalPath, "sub3", "sub4"), UtilsJunction.ResolvePath(test2JunctionSubDir)); // Ahora subdirectorios que no existen Assert.Equal(Path.Combine(test2OriginalPath, "sub4", "sub5"), UtilsJunction.ResolvePath(Path.Combine(test2LinkPath, "sub4", "sub5"))); Assert.Equal(Path.Combine(test2OriginalPath, "sub6", "sub7"), UtilsJunction.ResolvePath(Path.Combine(test2JunctionPath, "sub6", "sub7"))); // Ahora una cadena de enlaces dentro de otro enlace... string test3LinkSubDir = Path.Combine(test2LinkPath, "sub8"); UtilsSystem.EnsureDirectoryExists(Path.Combine(test2LinkPath, "test3"), true); UtilsJunction.EnsureLink(test3LinkSubDir, Path.Combine(test2LinkPath, "test3"), logger, true, linkType: UtilsJunction.LinkTypeRequest.Symlink); Assert.Equal(Path.Combine(test2OriginalPath, "test3"), UtilsJunction.ResolvePath(test3LinkSubDir)); UtilsSystem.DeleteDirectory(testPath, logger, 2); // Non existent and malformed network uri get reconstructed as-is string testNetworkUri = "\\\\147.83.73.25\\a\\b\\c\\\\d"; Assert.Equal(testNetworkUri, UtilsJunction.ResolvePath(testNetworkUri)); }
/// <summary> /// Get an instance of AppVeyorClient /// </summary> /// <param name="token">API Token</param> /// <param name="baseUri">Base URI</param> /// <param name="logger"></param> /// <param name="tempDir"></param> public Client( string token, string baseUri, ILoggerInterface logger, string tempDir) { string apiTempDir = UtilsSystem.EnsureDirectoryExists(UtilsSystem.CombinePaths(tempDir, "_appveyor", "api"), true); this.TempDir = tempDir; this.Token = token; this.Logger = logger; this.BaseUri = baseUri; this.SimpleStore = new SimpleStore(apiTempDir); }
/// <summary> /// Get a shared site root for the application /// </summary> /// <returns></returns> public string GetAcmeTemporarySiteRootForApplication() { // Create a phantom website only to serve the file... var wellKnownSharedPath = Path.Combine(this.StoragePath, "webroot_" + this.AppId); UtilsSystem.DirectoryCreateIfNotExists(wellKnownSharedPath); // Grant specific user permissions UtilsWindowsAccounts.AddPermissionToDirectoryIfMissing( this.Deployment.WindowsUsernameFqdn(), wellKnownSharedPath, FileSystemRights.ReadAndExecute, this.GlobalSettings.directoryPrincipal); return(wellKnownSharedPath); }
/// <summary> /// /// </summary> /// <param name="fileName"></param> /// <param name="dir"></param> /// <returns></returns> protected static Assembly LoadAssemblyWithPrefix(string fileName, string dir) { string path; path = Path.Combine(UtilsSystem.GetCodeBaseDir(), dir, fileName); if (File.Exists(path)) { return(Assembly.LoadFrom(path)); } path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, dir, fileName); if (File.Exists(path)) { return(Assembly.LoadFrom(path)); } return(null); }
/// <inheritdoc cref="IDownloaderInterface"/> public Artifact PullFromId(string version, string preferredLocalArtifactPath) { if (string.IsNullOrWhiteSpace(version)) { version = this.Settings.path; } Artifact artifact = new Artifact { id = version, localPath = preferredLocalArtifactPath, isRemote = true }; // Use artifact temp path, or local system temporary directory. if (Directory.Exists(artifact.localPath)) { UtilsSystem.DeleteDirectory(artifact.localPath, this.Logger); } // The ID is the PATH to the local zip, so just unzip this.Logger.LogInfo(true, "Unzipping file...."); ZipFile.ExtractToDirectory(version, artifact.localPath); this.Logger.LogInfo(true, "Unzipping finished...."); artifact.obtainedAt = DateTime.UtcNow; artifact.artifactSettings = new ArtifactSettings(); // We will merge data from both git and settings file, local settigns file // will override anything from GIT (if available). artifact.artifactSettings.PopulateFromGit(artifact.localPath); artifact.artifactSettings.PopulateFromSettingsFile(artifact.localPath, this.Logger); artifact.artifactSettings.PopulateFromEnvironment(); // Branch name is critical to some deployment... populate with a no-branch-found.... if (string.IsNullOrEmpty(artifact.artifactSettings.branch)) { artifact.artifactSettings.branch = "no-branch-found"; this.Logger.LogInfo(true, "Could not identify git branch for artifact. Using default: 'no-branch-found'"); } return(artifact); }
/// <inheritdoc cref="IDownloaderInterface"/> public Artifact PullFromId(string version, string preferredLocalArtifactPath) { Artifact artifact = new Artifact { id = version, localPath = preferredLocalArtifactPath, isRemote = true }; // Use artifact temp path, or local system temporary directory. if (Directory.Exists(artifact.localPath)) { UtilsSystem.DeleteDirectory(artifact.localPath, this.Logger); } // Use the build version to pull the build information. Build build = this.Client.GetBuildFromVersion(version, this.Settings.username, this.Settings.project); // Make sure that the builds matches the current active branch, otherwise throw an exception if (!build.branch.Equals(this.Settings.branch, StringComparison.CurrentCultureIgnoreCase)) { throw new Exception($"Requested version '{version}' with branch '{build.branch}' does not belong to active settings branch '{this.Settings.branch}'"); } this.Client.DownloadSingleArtifactFromBuild(this.ApplicationId, build, this.Settings.artifact_regex, artifact.localPath, this.Logger); artifact.artifactSettings = new ArtifactSettings(); artifact.artifactSettings.PopulateFromSettingsFile(artifact.localPath, this.Logger); if (string.IsNullOrWhiteSpace(artifact.artifactSettings.branch)) { artifact.artifactSettings.branch = Convert.ToString(build.branch); } if (string.IsNullOrWhiteSpace(artifact.artifactSettings.commit_sha)) { artifact.artifactSettings.commit_sha = Convert.ToString(build.commitId); } return(artifact); }
/// <summary> /// Find the matching deployer of the parent application when /// inheritance is configured for this application. /// </summary> /// <typeparam name="TType"></typeparam> /// <returns></returns> public TType getDeployerFromParentApp <TType>() where TType : DeployerBase { // We need a parent application for this to work. if (this.ParentApp == null) { return(null); } // Try to grab parent deployment... Deployment parentDeployment; string activeDeploymentPathStorage = UtilsSystem.CombinePaths(this.GlobalSettings.activeDeploymentDir, "active." + this.ParentApp.GetId() + ".json"); if (File.Exists(activeDeploymentPathStorage)) { parentDeployment = Deployment.InstanceFromPath(activeDeploymentPathStorage, this.GlobalSettings); DeployerSettingsBase ourSettings = this.DeployerSettings.castTo <DeployerSettingsBase>(); List <IDeployerInterface> deployersAndServices = new List <IDeployerInterface>(); deployersAndServices.AddRange(parentDeployment.GrabServices(this.Logger)); deployersAndServices.AddRange(parentDeployment.GrabDeployers(this.Logger)); // Only keep those that match our type deployersAndServices = deployersAndServices.Where(s => s.GetType() == typeof(TType)).ToList(); // Filter by ID foreach (TType t in deployersAndServices) { if (t.DeployerSettings.castTo <DeployerSettingsBase>().id == ourSettings.id) { return(t); } } return(null); } else { return(null); } }
/// <summary> /// Grab from local GIT repo. /// </summary> /// <param name="path"></param> public void PopulateFromGit(string path) { // Crawl up to find the first directory covered by GIT. There might be a difference // between the artifact folder structure and the repository (local working copy) itself... DirectoryInfo difo = new DirectoryInfo(path); string gitpath = null; while (difo != null && difo.Exists) { if (Directory.Exists(UtilsSystem.CombinePaths(difo.FullName, ".git"))) { gitpath = difo.FullName; break; } difo = difo.Parent; } if (gitpath == null) { return; } try { // Try to get information directly from GIT?? var repo = new LibGit2Sharp.Repository(gitpath, new LibGit2Sharp.RepositoryOptions() { }); this.branch = repo.Head.FriendlyName; this.commit_sha = repo.Commits.First().Sha; this.version = this.commit_sha; } catch (Exception e) { // Trying to read settings from GIT can be delicate. Such as... // https://github.com/GitTools/GitVersion/issues/1043 } }
public void TestPfxFromPem() { BindingRedirectHandler.DoBindingRedirects(AppDomain.CurrentDomain); string pfxFilePath = Path.GetTempPath() + "ssl-pfx-test-" + Guid.NewGuid() + ".pfx"; string certificatePassword = null; string crtFilePath = UtilsSystem.GetResourceFileAsPath("certificate_files_example\\a0e8efb7cca4452ed304b1d9614ec89d-crt.pem"); string keyFilePath = UtilsSystem.GetResourceFileAsPath("certificate_files_example\\a0e8efb7cca4452ed304b1d9614ec89d-key.pem"); UtilsCertificate.CreatePfXfromPem(crtFilePath, keyFilePath, pfxFilePath, certificatePassword); // Make sure that the certificate file is valid and works X509Certificate2Collection collection = new X509Certificate2Collection(); collection.Import(pfxFilePath, certificatePassword, X509KeyStorageFlags.EphemeralKeySet); var originalCert = collection[0]; Assert.Equal("033679B39C0CDA50C745ABD173FB0DD381A1", originalCert.SerialNumber); File.Delete(pfxFilePath); }
public void TestLongPathSupport() { string uncPath = "\\\\serverxx\\directory"; string uncPathLong = UtilsSystem.AddLongPathSupport(uncPath); Assert.Equal("\\\\?\\UNC\\serverxx\\directory", uncPathLong); Assert.Equal(uncPath, UtilsSystem.RemoveLongPathSupport(uncPathLong)); Assert.Equal(uncPath, UtilsSystem.RemoveLongPathSupport(uncPath)); string regularPath = "c:\\windows\\temp"; string regularPathLong = UtilsSystem.AddLongPathSupport(regularPath); Assert.Equal("\\\\?\\c:\\windows\\temp", regularPathLong); Assert.Equal(regularPath, UtilsSystem.RemoveLongPathSupport(regularPathLong)); Assert.Equal(regularPath, UtilsSystem.RemoveLongPathSupport(regularPath)); // Create a very long filename, individual segments can't be over 255 characters string fileName = "c:\\"; for (int x = 0; x < 100; x++) { fileName += Guid.NewGuid() + "\\"; } Assert.ThrowsAny <Exception>(() => { Directory.CreateDirectory(fileName); }); var fileNameWithLongPathSupport = UtilsSystem.EnsureLongPathSupportIfAvailable(fileName); Directory.CreateDirectory(fileNameWithLongPathSupport); fileNameWithLongPathSupport += "info.txt"; File.WriteAllText(fileNameWithLongPathSupport, "empty contents"); File.Delete(fileNameWithLongPathSupport); }