// <summary> // This method initializes status,ssh,hooks & deployment locks used by Kudu to ensure // synchronized operations. This method creates a dictionary of locks which is injected // into various controllers to resolve the locks they need. // <list type="bullet"> // <listheader> // <term>Locks used by Kudu:</term> // </listheader> // <item> // <term>Status Lock</term> // <description>Used by DeploymentStatusManager</description> // </item> // <item> // <term>SSH Lock</term> // <description>Used by SSHKeyController</description> // </item> // <item> // <term>Hooks Lock</term> // <description>Used by WebHooksManager</description> // </item> // <item> // <term>Deployment Lock</term> // <description> // Used by DeploymentController, DeploymentManager, SettingsController, // FetchDeploymentManager, LiveScmController, ReceivePackHandlerMiddleware // </description> // </item> // </list> // </summary> // <remarks> // Uses File watcher. // This originally used Ninject's "WhenInjectedInto" in .Net project for specific instances. IServiceCollection // doesn't support this concept, or anything similar like named instances. There are a few possibilities, // but the hack solution for now is just injecting a dictionary of locks and letting each dependent resolve // the one it needs. // </remarks> private static void SetupLocks(ITraceFactory traceFactory, IEnvironment environment) { var lockPath = Path.Combine(environment.SiteRootPath, Constants.LockPath); var deploymentLockPath = Path.Combine(lockPath, Constants.DeploymentLockFile); var statusLockPath = Path.Combine(lockPath, Constants.StatusLockFile); var sshKeyLockPath = Path.Combine(lockPath, Constants.SSHKeyLockFile); var hooksLockPath = Path.Combine(lockPath, Constants.HooksLockFile); _deploymentLock = DeploymentLockFile.GetInstance(deploymentLockPath, traceFactory); _deploymentLock.InitializeAsyncLocks(); var statusLock = new LockFile(statusLockPath, traceFactory); statusLock.InitializeAsyncLocks(); var sshKeyLock = new LockFile(sshKeyLockPath, traceFactory); sshKeyLock.InitializeAsyncLocks(); var hooksLock = new LockFile(hooksLockPath, traceFactory); hooksLock.InitializeAsyncLocks(); _namedLocks = new Dictionary <string, IOperationLock> { { "status", statusLock }, { "ssh", sshKeyLock }, { "hooks", hooksLock }, { "deployment", _deploymentLock } }; }
private static void RegisterServices(IKernel kernel) { var serverConfiguration = new ServerConfiguration(); 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 <IFileSystem>().To <FileSystem>().InSingletonScope(); 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); var fileSystem = new FileSystem(); _deploymentLock = new LockFile(deploymentLockPath, kernel.Get <ITraceFactory>(), fileSystem); _deploymentLock.InitializeAsyncLocks(); var statusLock = new LockFile(statusLockPath, kernel.Get <ITraceFactory>(), fileSystem); var sshKeyLock = new LockFile(sshKeyLockPath, kernel.Get <ITraceFactory>(), fileSystem); var hooksLock = new LockFile(hooksLockPath, kernel.Get <ITraceFactory>(), fileSystem); 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>(), fileSystem, context.Kernel.Get <ITracer>(), environment.AnalyticsPath)); var shutdownDetector = new ShutdownDetector(); shutdownDetector.Initialize(); // Trace shutdown event // Cannot use shutdownDetector.Token.Register because of race condition // with NinjectServices.Stop via WebActivator.ApplicationShutdownMethodAttribute Shutdown += () => TraceShutdown(environment, kernel); // 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(); 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>().To <RepositoryFactory>() .InRequestScope(); // 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(); // Command executor kernel.Bind <ICommandExecutor>().ToMethod(context => GetCommandExecutor(environment, context)) .InRequestScope(); MigrateSite(environment, kernel); RegisterRoutes(kernel, RouteTable.Routes); }
public AsyncLockFileTests() { _lockFilePath = Path.Combine(PathHelper.TestLockPath, "file.lock"); _lockFile = new LockFile(_lockFilePath, NullTracerFactory.Instance, new FileSystem()); _lockFile.InitializeAsyncLocks(); }