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);
            }
        }
Beispiel #2
0
        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));
        }
Beispiel #5
0
        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();
                });
            }
        }
Beispiel #6
0
        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);
        }
Beispiel #7
0
 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);
     });
 }
Beispiel #8
0
        /// <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));
            }
        }
Beispiel #10
0
 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));
     }
 }
Beispiel #11
0
        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);
            }
        }
Beispiel #13
0
        /// <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);
     }
 }
Beispiel #15
0
        internal void Initialize()
        {
            IRepository repository = _repositoryFactory.GetRepository();

            if (repository == null)
            {
                _initLock.LockOperation(() =>
                {
                    repository = _repositoryFactory.GetRepository();
                    if (repository == null)
                    {
                        InitializeRepository();
                    }
                }, InitTimeout);
            }
        }
Beispiel #16
0
        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));
        }
Beispiel #17
0
        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);
        }
Beispiel #19
0
        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);
        }
Beispiel #20
0
        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));
        }
Beispiel #21
0
        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);
        }
Beispiel #22
0
        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);
            }
        }
Beispiel #23
0
        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);
                }
            }
        }
Beispiel #25
0
        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);
            }
        }