public IActionResult SetPrivateKey([FromBody] string content) { string key; if (IsContentType("application/json")) { JObject result = GetJsonContent(); key = result == null ? null : result.Value <string>(KeyParameterName); } else { // any other content-type assuming the content is key // curl http://server/sshkey -X PUT --upload-file /c/temp/id_rsa key = content; } if (String.IsNullOrEmpty(key)) { return(StatusCode(StatusCodes.Status400BadRequest, new ArgumentNullException(KeyParameterName))); //throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.BadRequest, new ArgumentNullException(KeyParameterName))); } using (_tracer.Step("SSHKeyController.SetPrivateKey")) { IActionResult result = Ok(); try { _sshKeyLock.LockOperation(() => { try { _sshKeyManager.SetPrivateKey(key); } catch (ArgumentException ex) { result = StatusCode(StatusCodes.Status400BadRequest, ex.Message); } catch (InvalidOperationException ex) { result = StatusCode(StatusCodes.Status409Conflict, ex.Message); } }, "Updating SSH key", TimeSpan.FromSeconds(LockTimeoutSecs)); } catch (LockOperationException ex) { result = StatusCode(StatusCodes.Status409Conflict, ex.Message); } return(result); } }
public static DeploymentStatusFile Open(string id, IEnvironment environment, IAnalytics analytics, IOperationLock statusLock) { return(statusLock.LockOperation(() => { string path = Path.Combine(environment.DeploymentsPath, id, StatusFile); if (!FileSystemHelpers.FileExists(path)) { return null; } try { XDocument document = null; using (var stream = FileSystemHelpers.OpenRead(path)) { document = XDocument.Load(stream); } return new DeploymentStatusFile(id, environment, statusLock, document); } catch (Exception ex) { // in the scenario where w3wp is abruptly terminated while xml is being written, // we may end up with corrupted xml. we will handle the error and remove the problematic directory. analytics.UnexpectedException(ex); FileSystemHelpers.DeleteDirectorySafe(Path.GetDirectoryName(path), ignoreErrors: true); // it is ok to return null as callers already handle null. return null; } }, "Getting deployment status", DeploymentStatusManager.LockTimeout)); }
public static DeploymentStatusFile Open(string id, IEnvironment environment, IAnalytics analytics, IOperationLock statusLock) { return statusLock.LockOperation(() => { string path = Path.Combine(environment.DeploymentsPath, id, StatusFile); if (!FileSystemHelpers.FileExists(path)) { return null; } try { XDocument document = null; using (var stream = FileSystemHelpers.OpenRead(path)) { document = XDocument.Load(stream); } return new DeploymentStatusFile(id, environment, statusLock, document); } catch (Exception ex) { // in the scenario where w3wp is abruptly terminated while xml is being written, // we may end up with corrupted xml. we will handle the error and remove the problematic directory. analytics.UnexpectedException(ex); FileSystemHelpers.DeleteDirectorySafe(Path.GetDirectoryName(path), ignoreErrors: true); // it is ok to return null as callers already handle null. return null; } }, DeploymentStatusManager.LockTimeout); }
public static DeploymentStatusFile Open(string id, IEnvironment environment, IAnalytics analytics, IOperationLock statusLock) { return(statusLock.LockOperation(() => { string path = Path.Combine(environment.DeploymentsPath, id, StatusFile); if (!FileSystemHelpers.FileExists(path)) { return null; } try { // In case we read status file in middle of a write, attempt to // read it again. Don't fail the status get request XDocument document = OperationManager.Attempt(() => LoadXmlStatusFile(path), 2, 250); return new DeploymentStatusFile(id, environment, statusLock, document); } catch (Exception ex) { // in the scenario where w3wp is abruptly terminated while xml is being written, // we may end up with corrupted xml. we will handle the error and remove the problematic directory. analytics.UnexpectedException(ex); FileSystemHelpers.DeleteDirectorySafe(Path.GetDirectoryName(path), ignoreErrors: true); // it is ok to return null as callers already handle null. return null; } }, "Getting deployment status", DeploymentStatusManager.LockTimeout)); }
public void ProcessRequest(HttpContext context) { using (_tracer.Step("RpcService.ReceivePack")) { _deploymentLock.LockOperation(() => { string username = null; if (AuthUtility.TryExtractBasicAuthUser(context.Request, out username)) { _gitServer.SetDeployer(username); } context.Response.Buffer = false; context.Response.BufferOutput = false; context.Response.ContentType = "application/x-git-receive-pack-result"; context.Response.AddHeader("Expires", "Fri, 01 Jan 1980 00:00:00 GMT"); context.Response.AddHeader("Pragma", "no-cache"); context.Response.AddHeader("Cache-Control", "no-cache, max-age=0, must-revalidate"); _gitServer.Receive(GetInputStream(context.Request), context.Response.OutputStream); }, () => { context.Response.StatusCode = 409; context.ApplicationInstance.CompleteRequest(); }); } }
public void Save() { if (String.IsNullOrEmpty(Id)) { throw new InvalidOperationException(); } var document = new XDocument(new XElement("deployment", new XElement("id", Id), new XElement("author", XmlUtility.Sanitize(Author)), new XElement("deployer", Deployer), new XElement("authorEmail", AuthorEmail), new XElement("message", XmlUtility.Sanitize(Message)), new XElement("progress", Progress), new XElement("status", Status), new XElement("statusText", StatusText), new XElement("lastSuccessEndTime", LastSuccessEndTime), new XElement("receivedTime", ReceivedTime), new XElement("startTime", StartTime), new XElement("endTime", EndTime), new XElement("complete", Complete.ToString()), new XElement("is_temp", IsTemporary.ToString()), new XElement("is_readonly", IsReadOnly.ToString()) )); _statusLock.LockOperation(() => { using (Stream stream = FileSystemHelpers.CreateFile(_statusFile)) { document.Save(stream); } OperationManager.Attempt(() => { // Used for ETAG if (FileSystemHelpers.FileExists(_activeFile)) { FileSystemHelpers.SetLastWriteTimeUtc(_activeFile, DateTime.UtcNow); } else { FileSystemHelpers.WriteAllText(_activeFile, String.Empty); } }); OperationManager.Attempt(() => { // enable the feature thru configuration if (ScmHostingConfigurations.DeploymentStatusCompleteFileEnabled && Complete) { FileSystemHelpers.CopyFile(_statusFile, _statusCompleteFile); } else if (FileSystemHelpers.FileExists(_statusCompleteFile)) { FileSystemHelpers.DeleteFile(_statusCompleteFile); } }); }, "Updating deployment status", DeploymentStatusManager.LockTimeout); }
public static void LockHttpOperation(this IOperationLock lockObj, Action action) { lockObj.LockOperation(action, () => { var response = new HttpResponseMessage(HttpStatusCode.Conflict); response.Content = new StringContent(Resources.Error_DeploymentInProgess); throw new HttpResponseException(response); }); }
/// <summary> /// Create or change some settings /// </summary> /// <param name="newSettings">The object containing the new settings</param> /// <returns></returns> public HttpResponseMessage Set(JObject newSettings) { if (newSettings == null) { return(Request.CreateResponse(HttpStatusCode.BadRequest)); } // We support two formats here: // 1. For backward compat, we support {key: 'someKey', value: 'someValue' } // 2. The preferred format is { someKey = 'someValue' } // Note that #2 allows multiple settings to be set, e.g. { someKey = 'someValue', someKey2 = 'someValue2' } try { return(_deploymentLock.LockOperation(() => { JToken keyToken, valueToken; if (newSettings.Count == 2 && newSettings.TryGetValue("key", out keyToken) && newSettings.TryGetValue("value", out valueToken)) { string key = keyToken.Value <string>(); if (String.IsNullOrEmpty(key)) { return Request.CreateResponse(HttpStatusCode.BadRequest); } _settingsManager.SetValue(key, valueToken.Value <string>()); } else { foreach (var keyValuePair in newSettings) { _settingsManager.SetValue(keyValuePair.Key, keyValuePair.Value.Value <string>()); } } return Request.CreateResponse(HttpStatusCode.NoContent); }, TimeSpan.Zero)); } catch (LockOperationException ex) { return(Request.CreateErrorResponse(HttpStatusCode.Conflict, ex.Message)); } }
/// <summary> /// Create or change some settings /// </summary> /// <param name="newSettings">The object containing the new settings</param> /// <returns></returns> public IActionResult Set([FromBody] JObject newSettings) { if (newSettings == null) { return(BadRequest()); } // We support two formats here: // 1. For backward compat, we support {key: 'someKey', value: 'someValue' } // 2. The preferred format is { someKey = 'someValue' } // Note that #2 allows multiple settings to be set, e.g. { someKey = 'someValue', someKey2 = 'someValue2' } try { return(_deploymentLock.LockOperation <IActionResult>(() => { JToken keyToken, valueToken; if (newSettings.Count == 2 && newSettings.TryGetValue("key", out keyToken) && newSettings.TryGetValue("value", out valueToken)) { string key = keyToken.Value <string>(); if (String.IsNullOrEmpty(key)) { return BadRequest(); } _settingsManager.SetValue(key, valueToken.Value <string>()); } else { foreach (var keyValuePair in newSettings) { _settingsManager.SetValue(keyValuePair.Key, keyValuePair.Value.Value <string>()); } } return NoContent(); }, "Updating deployment setting", TimeSpan.FromSeconds(5))); } catch (LockOperationException ex) { return(StatusCode(StatusCodes.Status409Conflict, ex.Message)); } }
public static T LockOperationIfNeccessary <T>(this IOperationLock lockObj, Func <T> operation, string operationName, TimeSpan timeout) { try { return(operation()); } catch (Exception) { return(lockObj.LockOperation(operation, operationName, timeout)); } }
public static DeploymentStatusFile Open(string id, IEnvironment environment, IAnalytics analytics, IOperationLock statusLock) { // status complete file is created infrequently at deployment completion time // once deployment is completed, it is highly unlikely its status will change // this helps optimize status read operation avoid taking status lock DeploymentStatusFile statusComplete = null; OperationManager.SafeExecute(() => { string path = Path.Combine(environment.DeploymentsPath, id, StatusCompleteFile); if (FileSystemHelpers.FileExists(path)) { if (ScmHostingConfigurations.DeploymentStatusCompleteFileEnabled) { statusComplete = new DeploymentStatusFile(id, environment, statusLock, FileSystemCache.ReadXml(path)); } else { FileSystemHelpers.DeleteFile(path); } } }); return(statusComplete ?? statusLock.LockOperation(() => { string path = Path.Combine(environment.DeploymentsPath, id, StatusFile); if (!FileSystemHelpers.FileExists(path)) { return null; } try { XDocument document = null; using (var stream = FileSystemHelpers.OpenRead(path)) { document = XDocument.Load(stream); } return new DeploymentStatusFile(id, environment, statusLock, document); } catch (Exception ex) { // in the scenario where w3wp is abruptly terminated while xml is being written, // we may end up with corrupted xml. we will handle the error and remove the problematic directory. analytics.UnexpectedException(ex); FileSystemHelpers.DeleteDirectorySafe(Path.GetDirectoryName(path), ignoreErrors: true); // it is ok to return null as callers already handle null. return null; } }, "Getting deployment status", DeploymentStatusManager.LockTimeout)); }
public WebHook AddWebHook(WebHook webHook) { using (_tracer.Step("WebHooksManager.AddWebHook")) { // must be valid absolute uri. if (!Uri.IsWellFormedUriString(webHook.HookAddress, UriKind.Absolute)) { throw new FormatException(Resources.Error_InvalidHookAddress.FormatCurrentCulture(webHook.HookAddress)); } WebHook createdWebHook = null; _hooksLock.LockOperation(() => { var webHooks = new List <WebHook>(ReadWebHooksFromFile()); WebHook existingWebHook = webHooks.FirstOrDefault(h => String.Equals(h.HookAddress, webHook.HookAddress, StringComparison.OrdinalIgnoreCase)); if (existingWebHook == null) { // if web hook doesn't exist (by address) then add it createdWebHook = new WebHook(webHook.HookEventType, webHook.HookAddress, id: DateTime.UtcNow.Ticks.ToString(), insecureSsl: webHook.InsecureSsl); webHooks.Add(createdWebHook); SaveHooksToFile(webHooks); _tracer.Trace("Added web hook: type - {0}, address - {1}", createdWebHook.HookEventType, createdWebHook.HookAddress); } else if (String.Equals(webHook.HookEventType, existingWebHook.HookEventType, StringComparison.OrdinalIgnoreCase)) { // if web hook exist with the same hook event type, return the existing one createdWebHook = existingWebHook; } else { // if web hook exists but with a different hook event type then throw a conflict exception throw new ConflictException(); } }, "Adding WebHook", LockTimeout); return(createdWebHook); } }
/// <summary> /// Delete a setting /// </summary> /// <param name="key">The key of the setting to delete</param> /// <returns></returns> public HttpResponseMessage Delete(string key) { if (String.IsNullOrEmpty(key)) { return Request.CreateResponse(HttpStatusCode.BadRequest); } try { return _deploymentLock.LockOperation(() => { _settingsManager.DeleteValue(key); return Request.CreateResponse(HttpStatusCode.NoContent); }, TimeSpan.Zero); } catch (LockOperationException ex) { return Request.CreateErrorResponse(HttpStatusCode.Conflict, ex.Message); } }
public static void LockHttpOperation(this IOperationLock lockObj, Action action, string operationName) { try { lockObj.LockOperation(action, operationName, TimeSpan.Zero); } catch (LockOperationException ex) { var response = new HttpResponseMessage(HttpStatusCode.Conflict); response.Content = new StringContent(ex.Message); throw new HttpResponseException(response); } }
internal void Initialize() { IRepository repository = _repositoryFactory.GetRepository(); if (repository == null) { _initLock.LockOperation(() => { repository = _repositoryFactory.GetRepository(); if (repository == null) { InitializeRepository(); } }, InitTimeout); } }
private void Save(XElement stepElement) { _traceLock.LockOperation(() => { XDocument document = GetDocument(); // Make sure the size of the log doesn't go over the limit EnsureSize(document); document.Root.Add(stepElement); using (var stream = FileSystemHelpers.OpenFile(_path, FileMode.Create, FileAccess.Write, FileShare.Read)) { document.Save(stream); } }, TimeSpan.FromMinutes(1)); }
public void Save() { if (String.IsNullOrEmpty(Id)) { throw new InvalidOperationException(); } var document = new XDocument(new XElement("deployment", new XElement("id", Id), new XElement("author", Author), new XElement("deployer", Deployer), new XElement("authorEmail", AuthorEmail), new XElement("message", Message), new XElement("progress", Progress), new XElement("status", Status), new XElement("statusText", StatusText), new XElement("lastSuccessEndTime", LastSuccessEndTime), new XElement("receivedTime", ReceivedTime), new XElement("startTime", StartTime), new XElement("endTime", EndTime), new XElement("complete", Complete.ToString()), new XElement("is_temp", IsTemporary.ToString()), new XElement("is_readonly", IsReadOnly.ToString()) )); _statusLock.LockOperation(() => { using (Stream stream = FileSystemHelpers.CreateFile(_statusFile)) { document.Save(stream); } // Used for ETAG if (FileSystemHelpers.FileExists(_activeFile)) { FileSystemHelpers.SetLastWriteTimeUtc(_activeFile, DateTime.UtcNow); } else { FileSystemHelpers.WriteAllText(_activeFile, String.Empty); } }, DeploymentStatusManager.LockTimeout); }
public void Delete(string id) { string path = Path.Combine(_environment.DeploymentsPath, id); _statusLock.LockOperation(() => { FileSystemHelpers.DeleteDirectorySafe(path, ignoreErrors: true); // Used for ETAG if (_fileSystem.File.Exists(_activeFile)) { _fileSystem.File.SetLastWriteTimeUtc(_activeFile, DateTime.UtcNow); } else { _fileSystem.File.WriteAllText(_activeFile, String.Empty); } }, LockTimeout); }
public static DeploymentStatusFile Open(string id, IFileSystem fileSystem, IEnvironment environment, IOperationLock statusLock) { return statusLock.LockOperation(() => { string path = Path.Combine(environment.DeploymentsPath, id, StatusFile); XDocument document = null; if (!fileSystem.File.Exists(path)) { return null; } using (var stream = fileSystem.File.OpenRead(path)) { document = XDocument.Load(stream); } return new DeploymentStatusFile(id, environment, fileSystem, statusLock, document); }, DeploymentStatusManager.LockTimeout); }
public static DeploymentStatusFile Open(string id, IEnvironment environment, IOperationLock statusLock) { return(statusLock.LockOperation(() => { string path = Path.Combine(environment.DeploymentsPath, id, StatusFile); XDocument document = null; if (!FileSystemHelpers.FileExists(path)) { return null; } using (var stream = FileSystemHelpers.OpenRead(path)) { document = XDocument.Load(stream); } return new DeploymentStatusFile(id, environment, statusLock, document); }, DeploymentStatusManager.LockTimeout)); }
public static void LockOperationWithRetry(this IOperationLock lockObj, Action operation, string operationName, TimeSpan timeout) { lockObj.LockOperation(() => { for (int i = 0; i < 3; ++i) { try { operation(); return; } catch (Exception) { } Thread.Sleep(250); } operation(); }, operationName, timeout); }
private static int Main(string[] args) { var logRepository = LogManager.GetRepository(Assembly.GetEntryAssembly()); XmlConfigurator.Configure(logRepository, new FileInfo("log4net.config")); // Turn flag on in app.config to wait for debugger on launch if (ConfigurationManager.AppSettings["WaitForDebuggerOnStart"] == "true") { while (!Debugger.IsAttached) { System.Threading.Thread.Sleep(100); } } if (System.Environment.GetEnvironmentVariable(SettingsKeys.DisableDeploymentOnPush) == "1") { return(0); } if (args.Length < 2) { System.Console.WriteLine("Usage: kudu.exe appRoot wapTargets [deployer]"); return(1); } // The post receive hook launches the exe from sh and intereprets newline differently. // This fixes very wacky issues with how the output shows up in the console on push System.Console.Error.NewLine = "\n"; System.Console.Out.NewLine = "\n"; string appRoot = args[0]; string wapTargets = args[1]; string deployer = args.Length == 2 ? null : args[2]; string requestId = System.Environment.GetEnvironmentVariable(Constants.RequestIdHeader); IEnvironment env = GetEnvironment(appRoot, requestId); ISettings settings = new XmlSettings.Settings(GetSettingsPath(env)); IDeploymentSettingsManager settingsManager = new DeploymentSettingsManager(settings); // Setup the trace TraceLevel level = settingsManager.GetTraceLevel(); ITracer tracer = GetTracer(env, level); ITraceFactory traceFactory = new TracerFactory(() => tracer); // Calculate the lock path string lockPath = Path.Combine(env.SiteRootPath, Constants.LockPath); string deploymentLockPath = Path.Combine(lockPath, Constants.DeploymentLockFile); IOperationLock deploymentLock = DeploymentLockFile.GetInstance(deploymentLockPath, traceFactory); if (deploymentLock.IsHeld) { return(PerformDeploy(appRoot, wapTargets, deployer, lockPath, env, settingsManager, level, tracer, traceFactory, deploymentLock)); } // Cross child process lock is not working on linux via mono. // When we reach here, deployment lock must be HELD! To solve above issue, we lock again before continue. try { return(deploymentLock.LockOperation(() => { return PerformDeploy(appRoot, wapTargets, deployer, lockPath, env, settingsManager, level, tracer, traceFactory, deploymentLock); }, "Performing deployment", TimeSpan.Zero)); } catch (LockOperationException) { return(-1); } }
public async Task <ScanRequestResult> StartScan(String timeout, String mainScanDirPath, String id, String host) { using (_tracer.Step("Start scan in the background")) { String folderPath = Path.Combine(mainScanDirPath, Constants.ScanFolderName + id); String filePath = Path.Combine(folderPath, Constants.ScanStatusFile); Boolean hasFileModifcations = true; if (_deploymentLock.IsHeld) { return(ScanRequestResult.ScanAlreadyInProgress); } //Create unique scan folder and scan status file _deploymentLock.LockOperation(() => { //Check if files are modified if (CheckModifications(mainScanDirPath)) { //Create unique scan directory for current scan FileSystemHelpers.CreateDirectory(folderPath); _tracer.Trace("Unique scan directory created for scan {0}", id); //Create scan status file inside folder FileSystemHelpers.CreateFile(filePath).Close(); //Create temp file to check if scan is still running string tempScanFilePath = GetTempScanFilePath(mainScanDirPath); tempScanFilePath = Path.Combine(mainScanDirPath, Constants.TempScanFile); FileSystemHelpers.CreateFile(tempScanFilePath).Close(); UpdateScanStatus(folderPath, ScanStatus.Starting); } else { hasFileModifcations = false; } }, "Creating unique scan folder", TimeSpan.Zero); if (!hasFileModifcations) { return(ScanRequestResult.NoFileModifications); } //Start Backgorund Scan using (var timeoutCancellationTokenSource = new CancellationTokenSource()) { var successfullyScanned = PerformBackgroundScan(_tracer, folderPath, timeoutCancellationTokenSource.Token, id, mainScanDirPath); //Wait till scan task completes or the timeout goes off if (await Task.WhenAny(successfullyScanned, Task.Delay(Int32.Parse(timeout), timeoutCancellationTokenSource.Token)) == successfullyScanned) { //If scan task completes before timeout //Delete excess scan folders, just keep the maximum number allowed await DeletePastScans(mainScanDirPath, _tracer); //Create new Manifest file containing the modified timestamps String manifestPath = Path.Combine(mainScanDirPath, Constants.ScanManifest); if (FileSystemHelpers.FileExists(manifestPath)) { FileSystemHelpers.DeleteFileSafe(manifestPath); } JObject manifestObj = new JObject(); //Write to the manifest with new timestamps of the modified file ModifyManifestFile(manifestObj, Constants.ScanDir); File.WriteAllText(manifestPath, JsonConvert.SerializeObject(manifestObj)); //Path to common log file for azure monitor String aggrLogPath = Path.Combine(mainScanDirPath, Constants.AggregrateScanResults); //This checks if result scan log is formed //If yes, it will append necessary logs to the aggregrate log file //Current appended logs will be "Scanned files","Infected files", and details of infected files String currLogPath = Path.Combine(folderPath, Constants.ScanLogFile); if (FileSystemHelpers.FileExists(currLogPath)) { StreamReader file = new StreamReader(currLogPath); string line; while ((line = file.ReadLine()) != null) { if (line.Contains("FOUND") || line.Contains("Infected files") || line.Contains("Scanned files")) { //logType "Infected" means this log line represents details of infected files String logType = "Infected"; if (line.Contains("Infected files") || line.Contains("Scanned files")) { //logType "Info" means this log line represents total number of scanned or infected files logType = "Info"; } FileSystemHelpers.AppendAllTextToFile(aggrLogPath, DateTime.UtcNow.ToString(@"M/d/yyyy hh:mm:ss tt") + "," + id + "," + logType + "," + host + "," + line + '\n'); } } } return(successfullyScanned.Result ? ScanRequestResult.RunningAynschronously : ScanRequestResult.AsyncScanFailed); } else { //Timeout went off before scan task completion //Cancel scan task timeoutCancellationTokenSource.Cancel(); //Scan process will be cancelled //wait till scan status file is appropriately updated await successfullyScanned; //Delete excess scan folders, just keep the maximum number allowed await DeletePastScans(mainScanDirPath, _tracer); return(ScanRequestResult.AsyncScanFailed); } } } }
public async Task <FetchDeploymentRequestResult> FetchDeploy( DeploymentInfoBase deployInfo, bool asyncRequested, Uri requestUri, string targetBranch) { // If Scm is not enabled, we will reject all but one payload for GenericHandler // This is to block the unintended CI with Scm providers like GitHub // Since Generic payload can only be done by user action, we loosely allow // that and assume users know what they are doing. Same applies to git // push/clone endpoint and zip deployment. if (!(_settings.IsScmEnabled() || deployInfo.AllowDeploymentWhileScmDisabled)) { return(FetchDeploymentRequestResult.ForbiddenScmDisabled); } // Else if this app is configured with a url in WEBSITE_USE_ZIP, then fail the deployment // since this is a RunFromZip site and the deployment has no chance of succeeding. else if (_settings.RunFromRemoteZip()) { return(FetchDeploymentRequestResult.ConflictRunFromRemoteZipConfigured); } // for CI payload, we will return Accepted and do the task in the BG // if isAsync is defined, we will return Accepted and do the task in the BG // since autoSwap relies on the response header, deployment has to be synchronously. bool isBackground = asyncRequested || deployInfo.IsContinuous; if (isBackground) { using (_tracer.Step("Start deployment in the background")) { var waitForTempDeploymentCreation = asyncRequested; var successfullyRequested = await PerformBackgroundDeployment( deployInfo, _environment, _settings, _tracer.TraceLevel, requestUri, waitForTempDeploymentCreation); return(successfullyRequested ? FetchDeploymentRequestResult.RunningAynschronously : FetchDeploymentRequestResult.ConflictDeploymentInProgress); } } _tracer.Trace("Attempting to fetch target branch {0}", targetBranch); try { return(await _deploymentLock.LockOperation(async() => { if (PostDeploymentHelper.IsAutoSwapOngoing()) { return FetchDeploymentRequestResult.ConflictAutoSwapOngoing; } await PerformDeployment(deployInfo); Console.WriteLine("\n\n\n\n Perform deployment Over\n\n\n"); return FetchDeploymentRequestResult.RanSynchronously; }, "Performing continuous deployment", TimeSpan.Zero)); } catch (LockOperationException) { if (deployInfo.AllowDeferredDeployment) { // Create a marker file that indicates if there's another deployment to pull // because there was a deployment in progress. using (_tracer.Step("Update pending deployment marker file")) { // REVIEW: This makes the assumption that the repository url is the same. // If it isn't the result would be buggy either way. FileSystemHelpers.SetLastWriteTimeUtc(_markerFilePath, DateTime.UtcNow); } return(FetchDeploymentRequestResult.Pending); } else { return(FetchDeploymentRequestResult.ConflictDeploymentInProgress); } } }
public void Delete(int deleteWebRoot = 0, int ignoreErrors = 0) { try { // Fail if a deployment is in progress _deploymentLock.LockOperation(() => { using (_tracer.Step("Deleting repository")) { string repositoryPath = Path.Combine(_environment.SiteRootPath, Constants.RepositoryPath); if (String.Equals(repositoryPath, _environment.RepositoryPath, StringComparison.OrdinalIgnoreCase)) { // Delete the repository FileSystemHelpers.DeleteDirectorySafe(_environment.RepositoryPath, ignoreErrors != 0); } else { // Just delete .git folder FileSystemHelpers.DeleteDirectorySafe(Path.Combine(_environment.RepositoryPath, ".git"), ignoreErrors != 0); FileSystemHelpers.DeleteDirectorySafe(Path.Combine(_environment.RepositoryPath, ".hg"), ignoreErrors != 0); } } using (_tracer.Step("Delete auto swap lock file")) { FileSystemHelpers.DeleteFileSafe(Path.Combine(_environment.LocksPath, AutoSwapHandler.AutoSwapLockFile)); } using (_tracer.Step("Deleting ssh key")) { // Delete the ssh key FileSystemHelpers.DeleteDirectorySafe(_environment.SSHKeyPath, ignoreErrors != 0); } if (deleteWebRoot != 0) { // This logic is primarily used to help with site reuse during test. // The flag is not documented for general use. using (_tracer.Step("Deleting web root")) { // Delete the wwwroot folder FileSystemHelpers.DeleteDirectoryContentsSafe(_environment.WebRootPath, ignoreErrors != 0); } using (_tracer.Step("Deleting diagnostics")) { // Delete the diagnostic log. This is a slight abuse of deleteWebRoot, but the // real semantic is more to reset the site to a fully clean state FileSystemHelpers.DeleteDirectorySafe(_environment.DiagnosticsPath, ignoreErrors != 0); } using (_tracer.Step("Deleting ASP.NET 5 approot")) { // Delete the approot folder used by ASP.NET 5 apps FileSystemHelpers.DeleteDirectorySafe(Path.Combine(_environment.SiteRootPath, "approot"), ignoreErrors != 0); } // Delete first deployment manifest since it is no longer needed FileSystemHelpers.DeleteFileSafe(Path.Combine(_environment.SiteRootPath, Constants.FirstDeploymentManifestFileName)); } else { using (_tracer.Step("Updating initial deployment manifest")) { // The active deployment manifest becomes the baseline initial deployment manifest // When SCM is reconnected, the new deployment will use this manifest to clean the wwwroot SaveInitialDeploymentManifest(); } } using (_tracer.Step("Deleting deployment cache")) { // Delete the deployment cache FileSystemHelpers.DeleteDirectorySafe(_environment.DeploymentsPath, ignoreErrors != 0); } }, "Deleting repository", TimeSpan.Zero); } catch (LockOperationException ex) { HttpResponseMessage response = Request.CreateErrorResponse(HttpStatusCode.Conflict, ex.Message); throw new HttpResponseException(response); } }