public void LockFileRepositoryClearLockTest() { // Mock var path = @"x:\temp"; var lockFileName = Path.Combine(path, "deployment.lock"); var fileSystem = new Mock<IFileSystem>(); var file = new Mock<FileBase>(); var directory = new Mock<DirectoryBase>(); var repository = new Mock<IRepository>(); var repositoryFactory = new Mock<IRepositoryFactory>(); var lockFile = new DeploymentLockFile(lockFileName, Mock.Of<ITraceFactory>(), fileSystem.Object); // Setup fileSystem.SetupGet(f => f.Directory) .Returns(directory.Object); directory.Setup(d => d.Exists(path)) .Returns(true); fileSystem.SetupGet(f => f.File) .Returns(file.Object); file.Setup(f => f.Open(lockFileName, FileMode.Create, FileAccess.Write, FileShare.None)) .Returns(Mock.Of<Stream>()); repositoryFactory.Setup(f => f.GetRepository()) .Returns(repository.Object); // Test lockFile.RepositoryFactory = repositoryFactory.Object; var locked = lockFile.Lock(); // Assert Assert.True(locked, "lock should be successfule!"); repository.Verify(r => r.ClearLock(), Times.Once); }
//private static AllSafeLinuxLock _linuxLock; public static DeploymentLockFile GetInstance(string path, ITraceFactory traceFactory) { if (_deploymentLockFile == null) { _deploymentLockFile = new DeploymentLockFile(path, traceFactory); } return(_deploymentLockFile); }
/// <summary> /// Stops the application. /// </summary> public static void Stop() { if (Shutdown != null) { Shutdown(); } if (_deploymentLock != null) { _deploymentLock.TerminateAsyncLocks(); _deploymentLock = null; } _bootstrapper.ShutDown(); }
// key goal is to create background tracer that is independent of request. public static void PerformBackgroundDeployment(DeploymentInfo deployInfo, IEnvironment environment, IDeploymentSettingsManager settings, TraceLevel traceLevel, Uri uri, IDisposable tempDeployment, IAutoSwapHandler autoSwapHandler, ChangeSet tempChangeSet) { var tracer = traceLevel <= TraceLevel.Off ? NullTracer.Instance : new XmlTracer(environment.TracePath, traceLevel); var traceFactory = new TracerFactory(() => tracer); var backgroundTrace = tracer.Step(XmlTracer.BackgroundTrace, new Dictionary<string, string> { {"url", uri.AbsolutePath}, {"method", "POST"} }); Task.Run(() => { try { // lock related string lockPath = Path.Combine(environment.SiteRootPath, Constants.LockPath); string deploymentLockPath = Path.Combine(lockPath, Constants.DeploymentLockFile); string statusLockPath = Path.Combine(lockPath, Constants.StatusLockFile); string hooksLockPath = Path.Combine(lockPath, Constants.HooksLockFile); var statusLock = new LockFile(statusLockPath, traceFactory); var hooksLock = new LockFile(hooksLockPath, traceFactory); var deploymentLock = new DeploymentLockFile(deploymentLockPath, traceFactory); var analytics = new Analytics(settings, new ServerConfiguration(), traceFactory); var deploymentStatusManager = new DeploymentStatusManager(environment, analytics, statusLock); var repositoryFactory = new RepositoryFactory(environment, settings, traceFactory); var siteBuilderFactory = new SiteBuilderFactory(new BuildPropertyProvider(), environment); var webHooksManager = new WebHooksManager(tracer, environment, hooksLock); var functionManager = new FunctionManager(environment, traceFactory); var deploymentManager = new DeploymentManager(siteBuilderFactory, environment, traceFactory, analytics, settings, deploymentStatusManager, deploymentLock, NullLogger.Instance, webHooksManager, autoSwapHandler, functionManager); var fetchHandler = new FetchHandler(tracer, deploymentManager, settings, deploymentStatusManager, deploymentLock, environment, null, repositoryFactory, null); // Perform deployment var acquired = deploymentLock.TryLockOperation(() => { fetchHandler.PerformDeployment(deployInfo, tempDeployment, tempChangeSet).Wait(); }, TimeSpan.Zero); if (!acquired) { if (tempDeployment != null) { tempDeployment.Dispose(); } 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(fetchHandler._markerFilePath, DateTime.UtcNow); } } } catch (Exception ex) { tracer.TraceError(ex); } finally { backgroundTrace.Dispose(); } }); }
private static void RegisterServices(IKernel kernel) { var serverConfiguration = new ServerConfiguration(); // Make sure %HOME% is correctly set EnsureHomeEnvironmentVariable(); EnsureSiteBitnessEnvironmentVariable(); IEnvironment environment = GetEnvironment(); // Add various folders that never change to the process path. All child processes will inherit PrependFoldersToPath(environment); // Per request environment kernel.Bind<IEnvironment>().ToMethod(context => GetEnvironment(context.Kernel.Get<IDeploymentSettingsManager>())) .InRequestScope(); // General kernel.Bind<HttpContextBase>().ToMethod(context => new HttpContextWrapper(HttpContext.Current)) .InRequestScope(); kernel.Bind<IServerConfiguration>().ToConstant(serverConfiguration); kernel.Bind<IBuildPropertyProvider>().ToConstant(new BuildPropertyProvider()); System.Func<ITracer> createTracerThunk = () => GetTracer(environment, kernel); System.Func<ILogger> createLoggerThunk = () => GetLogger(environment, kernel); // First try to use the current request profiler if any, otherwise create a new one var traceFactory = new TracerFactory(() => TraceServices.CurrentRequestTracer ?? createTracerThunk()); kernel.Bind<ITracer>().ToMethod(context => TraceServices.CurrentRequestTracer ?? NullTracer.Instance); kernel.Bind<ITraceFactory>().ToConstant(traceFactory); TraceServices.SetTraceFactory(createTracerThunk, createLoggerThunk); // Setup the deployment lock string lockPath = Path.Combine(environment.SiteRootPath, Constants.LockPath); string deploymentLockPath = Path.Combine(lockPath, Constants.DeploymentLockFile); string statusLockPath = Path.Combine(lockPath, Constants.StatusLockFile); string sshKeyLockPath = Path.Combine(lockPath, Constants.SSHKeyLockFile); string hooksLockPath = Path.Combine(lockPath, Constants.HooksLockFile); _deploymentLock = new DeploymentLockFile(deploymentLockPath, kernel.Get<ITraceFactory>()); _deploymentLock.InitializeAsyncLocks(); var statusLock = new LockFile(statusLockPath, kernel.Get<ITraceFactory>()); var sshKeyLock = new LockFile(sshKeyLockPath, kernel.Get<ITraceFactory>()); var hooksLock = new LockFile(hooksLockPath, kernel.Get<ITraceFactory>()); kernel.Bind<IOperationLock>().ToConstant(sshKeyLock).WhenInjectedInto<SSHKeyController>(); kernel.Bind<IOperationLock>().ToConstant(statusLock).WhenInjectedInto<DeploymentStatusManager>(); kernel.Bind<IOperationLock>().ToConstant(hooksLock).WhenInjectedInto<WebHooksManager>(); kernel.Bind<IOperationLock>().ToConstant(_deploymentLock); var shutdownDetector = new ShutdownDetector(); shutdownDetector.Initialize(); IDeploymentSettingsManager noContextDeploymentsSettingsManager = new DeploymentSettingsManager(new XmlSettings.Settings(GetSettingsPath(environment))); var noContextTraceFactory = new TracerFactory(() => GetTracerWithoutContext(environment, noContextDeploymentsSettingsManager)); kernel.Bind<IAnalytics>().ToMethod(context => new Analytics(context.Kernel.Get<IDeploymentSettingsManager>(), context.Kernel.Get<IServerConfiguration>(), noContextTraceFactory)); // Trace unhandled (crash) exceptions. AppDomain.CurrentDomain.UnhandledException += (sender, args) => { var ex = args.ExceptionObject as Exception; if (ex != null) { kernel.Get<IAnalytics>().UnexpectedException(ex); } }; // Trace shutdown event // Cannot use shutdownDetector.Token.Register because of race condition // with NinjectServices.Stop via WebActivator.ApplicationShutdownMethodAttribute Shutdown += () => TraceShutdown(environment, noContextDeploymentsSettingsManager); // LogStream service // The hooks and log stream start endpoint are low traffic end-points. Re-using it to avoid creating another lock var logStreamManagerLock = hooksLock; kernel.Bind<LogStreamManager>().ToMethod(context => new LogStreamManager(Path.Combine(environment.RootPath, Constants.LogFilesPath), context.Kernel.Get<IEnvironment>(), context.Kernel.Get<IDeploymentSettingsManager>(), context.Kernel.Get<ITracer>(), shutdownDetector, logStreamManagerLock)); kernel.Bind<InfoRefsController>().ToMethod(context => new InfoRefsController(t => context.Kernel.Get(t))) .InRequestScope(); kernel.Bind<CustomGitRepositoryHandler>().ToMethod(context => new CustomGitRepositoryHandler(t => context.Kernel.Get(t))) .InRequestScope(); // Deployment Service kernel.Bind<ISettings>().ToMethod(context => new XmlSettings.Settings(GetSettingsPath(environment))) .InRequestScope(); kernel.Bind<IDeploymentSettingsManager>().To<DeploymentSettingsManager>() .InRequestScope(); kernel.Bind<IDeploymentStatusManager>().To<DeploymentStatusManager>() .InRequestScope(); kernel.Bind<ISiteBuilderFactory>().To<SiteBuilderFactory>() .InRequestScope(); kernel.Bind<IWebHooksManager>().To<WebHooksManager>() .InRequestScope(); ITriggeredJobsManager triggeredJobsManager = new TriggeredJobsManager( noContextTraceFactory, kernel.Get<IEnvironment>(), kernel.Get<IDeploymentSettingsManager>(), kernel.Get<IAnalytics>(), kernel.Get<IWebHooksManager>()); kernel.Bind<ITriggeredJobsManager>().ToConstant(triggeredJobsManager) .InTransientScope(); IContinuousJobsManager continuousJobManager = new ContinuousJobsManager( noContextTraceFactory, kernel.Get<IEnvironment>(), kernel.Get<IDeploymentSettingsManager>(), kernel.Get<IAnalytics>()); triggeredJobsManager.CleanupDeletedJobs(); continuousJobManager.CleanupDeletedJobs(); kernel.Bind<IContinuousJobsManager>().ToConstant(continuousJobManager) .InTransientScope(); TriggeredJobsScheduler triggeredJobsScheduler = new TriggeredJobsScheduler( triggeredJobsManager, noContextTraceFactory, environment); kernel.Bind<TriggeredJobsScheduler>().ToConstant(triggeredJobsScheduler) .InTransientScope(); kernel.Bind<ILogger>().ToMethod(context => GetLogger(environment, context.Kernel)) .InRequestScope(); kernel.Bind<IDeploymentManager>().To<DeploymentManager>() .InRequestScope(); kernel.Bind<IAutoSwapHandler>().To<AutoSwapHandler>() .InRequestScope(); kernel.Bind<ISSHKeyManager>().To<SSHKeyManager>() .InRequestScope(); kernel.Bind<IRepositoryFactory>().ToMethod(context => _deploymentLock.RepositoryFactory = new RepositoryFactory(context.Kernel.Get<IEnvironment>(), context.Kernel.Get<IDeploymentSettingsManager>(), context.Kernel.Get<ITraceFactory>())) .InRequestScope(); kernel.Bind<IApplicationLogsReader>().To<ApplicationLogsReader>() .InSingletonScope(); // Git server kernel.Bind<IDeploymentEnvironment>().To<DeploymentEnvrionment>(); kernel.Bind<IGitServer>().ToMethod(context => new GitExeServer(context.Kernel.Get<IEnvironment>(), _deploymentLock, GetRequestTraceFile(context.Kernel), context.Kernel.Get<IRepositoryFactory>(), context.Kernel.Get<IDeploymentEnvironment>(), context.Kernel.Get<IDeploymentSettingsManager>(), context.Kernel.Get<ITraceFactory>())) .InRequestScope(); // Git Servicehook parsers kernel.Bind<IServiceHookHandler>().To<GenericHandler>().InRequestScope(); kernel.Bind<IServiceHookHandler>().To<GitHubHandler>().InRequestScope(); kernel.Bind<IServiceHookHandler>().To<BitbucketHandler>().InRequestScope(); kernel.Bind<IServiceHookHandler>().To<BitbucketHandlerV2>().InRequestScope(); kernel.Bind<IServiceHookHandler>().To<DropboxHandler>().InRequestScope(); kernel.Bind<IServiceHookHandler>().To<CodePlexHandler>().InRequestScope(); kernel.Bind<IServiceHookHandler>().To<CodebaseHqHandler>().InRequestScope(); kernel.Bind<IServiceHookHandler>().To<GitlabHqHandler>().InRequestScope(); kernel.Bind<IServiceHookHandler>().To<CodingHandler>().InRequestScope(); kernel.Bind<IServiceHookHandler>().To<GitHubCompatHandler>().InRequestScope(); kernel.Bind<IServiceHookHandler>().To<KilnHgHandler>().InRequestScope(); kernel.Bind<IServiceHookHandler>().To<VSOHandler>().InRequestScope(); kernel.Bind<IServiceHookHandler>().To<OneDriveHandler>().InRequestScope(); // SiteExtensions kernel.Bind<ISiteExtensionManager>().To<SiteExtensionManager>().InRequestScope(); // Functions kernel.Bind<IFunctionManager>().To<FunctionManager>().InRequestScope(); // Command executor kernel.Bind<ICommandExecutor>().To<CommandExecutor>().InRequestScope(); MigrateSite(environment, noContextDeploymentsSettingsManager); RemoveOldTracePath(environment); RemoveTempFileFromUserDrive(environment); // Temporary fix for https://github.com/npm/npm/issues/5905 EnsureNpmGlobalDirectory(); EnsureUserProfileDirectory(); // Skip SSL Certificate Validate OperationClient.SkipSslValidationIfNeeded(); // Make sure webpages:Enabled is true. Even though we set it in web.config, it could be overwritten by // an Azure AppSetting that's supposed to be for the site only but incidently affects Kudu as well. ConfigurationManager.AppSettings["webpages:Enabled"] = "true"; // Kudu does not rely owin:appStartup. This is to avoid Azure AppSetting if set. if (ConfigurationManager.AppSettings["owin:appStartup"] != null) { // Set the appSetting to null since we cannot use AppSettings.Remove(key) (ReadOnly exception!) ConfigurationManager.AppSettings["owin:appStartup"] = null; } RegisterRoutes(kernel, RouteTable.Routes); // Register the default hubs route: ~/signalr GlobalHost.DependencyResolver = new SignalRNinjectDependencyResolver(kernel); GlobalConfiguration.Configuration.Filters.Add( new TraceDeprecatedActionAttribute( kernel.Get<IAnalytics>(), kernel.Get<ITraceFactory>())); GlobalConfiguration.Configuration.Filters.Add(new EnsureRequestIdHandlerAttribute()); }
private static void RegisterServices(IKernel kernel) { var serverConfiguration = new ServerConfiguration(); // Make sure %HOME% is correctly set EnsureHomeEnvironmentVariable(); IEnvironment environment = GetEnvironment(); // Per request environment kernel.Bind<IEnvironment>().ToMethod(context => GetEnvironment(context.Kernel.Get<IDeploymentSettingsManager>())) .InRequestScope(); // General kernel.Bind<HttpContextBase>().ToMethod(context => new HttpContextWrapper(HttpContext.Current)) .InRequestScope(); kernel.Bind<IServerConfiguration>().ToConstant(serverConfiguration); kernel.Bind<IBuildPropertyProvider>().ToConstant(new BuildPropertyProvider()); System.Func<ITracer> createTracerThunk = () => GetTracer(environment, kernel); System.Func<ILogger> createLoggerThunk = () => GetLogger(environment, kernel); // First try to use the current request profiler if any, otherwise create a new one var traceFactory = new TracerFactory(() => TraceServices.CurrentRequestTracer ?? createTracerThunk()); kernel.Bind<ITracer>().ToMethod(context => TraceServices.CurrentRequestTracer ?? NullTracer.Instance); kernel.Bind<ITraceFactory>().ToConstant(traceFactory); TraceServices.SetTraceFactory(createTracerThunk, createLoggerThunk); // Setup the deployment lock string lockPath = Path.Combine(environment.SiteRootPath, Constants.LockPath); string deploymentLockPath = Path.Combine(lockPath, Constants.DeploymentLockFile); string statusLockPath = Path.Combine(lockPath, Constants.StatusLockFile); string sshKeyLockPath = Path.Combine(lockPath, Constants.SSHKeyLockFile); string hooksLockPath = Path.Combine(lockPath, Constants.HooksLockFile); _deploymentLock = new DeploymentLockFile(deploymentLockPath, kernel.Get<ITraceFactory>()); _deploymentLock.InitializeAsyncLocks(); var statusLock = new LockFile(statusLockPath, kernel.Get<ITraceFactory>()); var sshKeyLock = new LockFile(sshKeyLockPath, kernel.Get<ITraceFactory>()); var hooksLock = new LockFile(hooksLockPath, kernel.Get<ITraceFactory>()); kernel.Bind<IOperationLock>().ToConstant(sshKeyLock).WhenInjectedInto<SSHKeyController>(); kernel.Bind<IOperationLock>().ToConstant(statusLock).WhenInjectedInto<DeploymentStatusManager>(); kernel.Bind<IOperationLock>().ToConstant(hooksLock).WhenInjectedInto<WebHooksManager>(); kernel.Bind<IOperationLock>().ToConstant(_deploymentLock); kernel.Bind<IAnalytics>().ToMethod(context => new Analytics(context.Kernel.Get<IDeploymentSettingsManager>(), context.Kernel.Get<ITracer>(), environment.AnalyticsPath)); var shutdownDetector = new ShutdownDetector(); shutdownDetector.Initialize(); IDeploymentSettingsManager noContextDeploymentsSettingsManager = new DeploymentSettingsManager(new XmlSettings.Settings(GetSettingsPath(environment))); // Trace shutdown event // Cannot use shutdownDetector.Token.Register because of race condition // with NinjectServices.Stop via WebActivator.ApplicationShutdownMethodAttribute Shutdown += () => TraceShutdown(environment, noContextDeploymentsSettingsManager); // LogStream service // The hooks and log stream start endpoint are low traffic end-points. Re-using it to avoid creating another lock var logStreamManagerLock = hooksLock; kernel.Bind<LogStreamManager>().ToMethod(context => new LogStreamManager(Path.Combine(environment.RootPath, Constants.LogFilesPath), context.Kernel.Get<IEnvironment>(), context.Kernel.Get<IDeploymentSettingsManager>(), context.Kernel.Get<ITracer>(), shutdownDetector, logStreamManagerLock)); kernel.Bind<InfoRefsController>().ToMethod(context => new InfoRefsController(t => context.Kernel.Get(t))) .InRequestScope(); kernel.Bind<CustomGitRepositoryHandler>().ToMethod(context => new CustomGitRepositoryHandler(t => context.Kernel.Get(t))) .InRequestScope(); // Deployment Service kernel.Bind<ISettings>().ToMethod(context => new XmlSettings.Settings(GetSettingsPath(environment))) .InRequestScope(); kernel.Bind<IDeploymentSettingsManager>().To<DeploymentSettingsManager>() .InRequestScope(); kernel.Bind<IDeploymentStatusManager>().To<DeploymentStatusManager>() .InRequestScope(); kernel.Bind<ISiteBuilderFactory>().To<SiteBuilderFactory>() .InRequestScope(); kernel.Bind<IWebHooksManager>().To<WebHooksManager>() .InRequestScope(); var noContextTraceFactory = new TracerFactory(() => GetTracerWithoutContext(environment, noContextDeploymentsSettingsManager)); ITriggeredJobsManager triggeredJobsManager = new TriggeredJobsManager( noContextTraceFactory, kernel.Get<IEnvironment>(), kernel.Get<IDeploymentSettingsManager>(), kernel.Get<IAnalytics>(), kernel.Get<IWebHooksManager>()); kernel.Bind<ITriggeredJobsManager>().ToConstant(triggeredJobsManager) .InTransientScope(); IContinuousJobsManager continuousJobManager = new ContinuousJobsManager( noContextTraceFactory, kernel.Get<IEnvironment>(), kernel.Get<IDeploymentSettingsManager>(), kernel.Get<IAnalytics>()); kernel.Bind<IContinuousJobsManager>().ToConstant(continuousJobManager) .InTransientScope(); kernel.Bind<ILogger>().ToMethod(context => GetLogger(environment, context.Kernel)) .InRequestScope(); kernel.Bind<IRepository>().ToMethod(context => new GitExeRepository(context.Kernel.Get<IEnvironment>(), context.Kernel.Get<IDeploymentSettingsManager>(), context.Kernel.Get<ITraceFactory>())) .InRequestScope(); kernel.Bind<IDeploymentManager>().To<DeploymentManager>() .InRequestScope(); kernel.Bind<ISSHKeyManager>().To<SSHKeyManager>() .InRequestScope(); kernel.Bind<IRepositoryFactory>().ToMethod(context => _deploymentLock.RepositoryFactory = new RepositoryFactory(context.Kernel.Get<IEnvironment>(), context.Kernel.Get<IDeploymentSettingsManager>(), context.Kernel.Get<ITraceFactory>(), context.Kernel.Get<HttpContextBase>())) .InRequestScope(); kernel.Bind<IApplicationLogsReader>().To<ApplicationLogsReader>() .InSingletonScope(); // Git server kernel.Bind<IDeploymentEnvironment>().To<DeploymentEnvrionment>(); kernel.Bind<IGitServer>().ToMethod(context => new GitExeServer(context.Kernel.Get<IEnvironment>(), _deploymentLock, GetRequestTraceFile(context.Kernel), context.Kernel.Get<IRepositoryFactory>(), context.Kernel.Get<IDeploymentEnvironment>(), context.Kernel.Get<IDeploymentSettingsManager>(), context.Kernel.Get<ITraceFactory>())) .InRequestScope(); // Git Servicehook parsers kernel.Bind<IServiceHookHandler>().To<GenericHandler>().InRequestScope(); kernel.Bind<IServiceHookHandler>().To<GitHubHandler>().InRequestScope(); kernel.Bind<IServiceHookHandler>().To<BitbucketHandler>().InRequestScope(); kernel.Bind<IServiceHookHandler>().To<DropboxHandler>().InRequestScope(); kernel.Bind<IServiceHookHandler>().To<CodePlexHandler>().InRequestScope(); kernel.Bind<IServiceHookHandler>().To<CodebaseHqHandler>().InRequestScope(); kernel.Bind<IServiceHookHandler>().To<GitlabHqHandler>().InRequestScope(); kernel.Bind<IServiceHookHandler>().To<GitHubCompatHandler>().InRequestScope(); kernel.Bind<IServiceHookHandler>().To<KilnHgHandler>().InRequestScope(); // SiteExtensions kernel.Bind<ISiteExtensionManager>().To<SiteExtensionManager>().InRequestScope(); // Command executor kernel.Bind<ICommandExecutor>().ToMethod(context => GetCommandExecutor(environment, context)) .InRequestScope(); MigrateSite(environment, noContextDeploymentsSettingsManager); // Temporary fix for https://github.com/npm/npm/issues/5905 EnsureNpmGlobalDirectory(); RegisterRoutes(kernel, RouteTable.Routes); // Register the default hubs route: ~/signalr GlobalHost.DependencyResolver = new SignalRNinjectDependencyResolver(kernel); RouteTable.Routes.MapConnection<PersistentCommandController>("commandstream", "/api/commandstream"); RouteTable.Routes.MapHubs("/api/filesystemhub", new HubConfiguration()); }
public AsyncLockFileTests() { _lockFilePath = Path.Combine(PathHelper.TestLockPath, "file.lock"); _lockFile = new DeploymentLockFile(_lockFilePath, NullTracerFactory.Instance); _lockFile.InitializeAsyncLocks(); }