Skip to content

Commit

Permalink
Separate Kudu's site management logic into separate assembly (Kudu.Si…
Browse files Browse the repository at this point in the history
…teManagement).

- Inject SiteManager in the Kudu.Web
- Discover siteroot and application room from web.config settings.
  • Loading branch information
davidfowl committed Nov 17, 2011
1 parent a6fe3b2 commit 9cdccfb
Show file tree
Hide file tree
Showing 15 changed files with 206 additions and 72 deletions.
34 changes: 34 additions & 0 deletions Kudu.SiteManagement/DefaultPathResolver.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using System.IO;

namespace Kudu.SiteManagement
{
public class DefaultPathResolver : IPathResolver
{
private readonly string _rootPath;
private readonly string _serviceSitePath;

public DefaultPathResolver(string serviceSitePath, string rootPath)
{
_serviceSitePath = Path.GetFullPath(serviceSitePath);
_rootPath = Path.GetFullPath(rootPath);
}

public string ServiceSitePath
{
get
{
return _serviceSitePath;
}
}

public string GetApplicationPath(string applicationName)
{
return Path.Combine(_rootPath, applicationName, "live");
}

public string GetDeveloperApplicationPath(string applicationName)
{
return Path.Combine(_rootPath, applicationName, "dev");
}
}
}
9 changes: 9 additions & 0 deletions Kudu.SiteManagement/IPathResolver.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace Kudu.SiteManagement
{
public interface IPathResolver
{
string ServiceSitePath { get; }
string GetApplicationPath(string applicationName);
string GetDeveloperApplicationPath(string applicationName);
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
using Kudu.Web.Models;

namespace Kudu.Web.Infrastructure
namespace Kudu.SiteManagement
{
public interface ISiteManager
{
Site CreateSite(string applicationName);
void DeleteSite(string applicationName);
bool TryCreateDeveloperSite(string applicationName, out string siteUrl);
void SetDeveloperSiteWebRoot(string applicationName, string projectPath);
void SetDeveloperSiteWebRoot(string applicationName, string siteRoot);
}
}
79 changes: 79 additions & 0 deletions Kudu.SiteManagement/Kudu.SiteManagement.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{D5669C1D-3408-4CEE-8C1B-D86D03D27EE2}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Kudu.SiteManagement</RootNamespace>
<AssemblyName>Kudu.SiteManagement</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\kudu\</SolutionDir>
<RestorePackages>true</RestorePackages>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Web.Administration, Version=7.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\..\..\Windows\System32\inetsrv\Microsoft.Web.Administration.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.IO.Abstractions">
<HintPath>..\packages\System.IO.Abstractions.1.4.0.12\lib\net35\System.IO.Abstractions.dll</HintPath>
</Reference>
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\Common\CommonAssemblyInfo.cs">
<Link>Properties\CommonAssemblyInfo.cs</Link>
</Compile>
<Compile Include="..\Common\Constants.cs">
<Link>Constants.cs</Link>
</Compile>
<Compile Include="..\Kudu.Core\Infrastructure\FileSystemHelpers.cs">
<Link>FileSystemHelpers.cs</Link>
</Compile>
<Compile Include="DefaultPathResolver.cs" />
<Compile Include="IPathResolver.cs" />
<Compile Include="ISiteManager.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Site.cs" />
<Compile Include="SiteManager.cs" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(SolutionDir)\.nuget\nuget.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
4 changes: 4 additions & 0 deletions Kudu.SiteManagement/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
using System.Reflection;

[assembly: AssemblyTitle("Kudu.SiteManagement")]
[assembly: AssemblyDescription("Site management logic for kudu")]
4 changes: 1 addition & 3 deletions Kudu.Web/Models/Site.cs → Kudu.SiteManagement/Site.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
namespace Kudu.Web.Models
namespace Kudu.SiteManagement
{
public class Site
{
public string SiteName { get; set; }
public string ServiceAppName { get; set; }
public string ServiceUrl { get; set; }
public string SiteUrl { get; set; }
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
using System;
using System.IO;
using System.Threading;
using Kudu.Core.Infrastructure;
using Kudu.Web.Models;
using IIS = Microsoft.Web.Administration;

namespace Kudu.Web.Infrastructure
namespace Kudu.SiteManagement
{
public class SiteManager : ISiteManager
{
private const string KuduAppPoolName = "kudu";


private readonly IPathResolver _pathResolver;

public SiteManager(IPathResolver pathResolver)
{
_pathResolver = pathResolver;
}

public Site CreateSite(string applicationName)
{
var iis = new IIS.ServerManager();
Expand All @@ -18,11 +25,11 @@ public Site CreateSite(string applicationName)
{
// Create the service site for this site
string serviceSiteName = GetServiceSite(applicationName);
int serviceSitePort = CreateSite(iis, serviceSiteName, PathHelper.ServiceSitePath);
int serviceSitePort = CreateSite(iis, serviceSiteName, _pathResolver.ServiceSitePath);

// Create the main site
string siteName = GetLiveSite(applicationName);
string siteRoot = PathHelper.GetApplicationPath(applicationName);
string siteRoot = _pathResolver.GetApplicationPath(applicationName);
string webRoot = Path.Combine(siteRoot, Constants.WebRoot);
int sitePort = CreateSite(iis, siteName, webRoot);

Expand All @@ -32,9 +39,12 @@ public Site CreateSite(string applicationName)
// Commit the changes to iis
iis.CommitChanges();

// Give IIS some time to create the site and map the path
// REVIEW: Should we poll the site's state?
Thread.Sleep(1000);

return new Site
{
SiteName = siteName,
ServiceUrl = String.Format("http://localhost:{0}/", serviceSitePort),
SiteUrl = String.Format("http://localhost:{0}/", sitePort),
};
Expand All @@ -56,7 +66,7 @@ public bool TryCreateDeveloperSite(string applicationName, out string siteUrl)
if (site == null)
{
// Get the path to the dev site
string siteRoot = PathHelper.GetDeveloperApplicationPath(applicationName);
string siteRoot = _pathResolver.GetDeveloperApplicationPath(applicationName);
string webRoot = Path.Combine(siteRoot, Constants.WebRoot);
int sitePort = CreateSite(iis, devSiteName, webRoot);

Expand All @@ -69,6 +79,8 @@ public bool TryCreateDeveloperSite(string applicationName, out string siteUrl)

iis.CommitChanges();

Thread.Sleep(1000);

siteUrl = String.Format("http://localhost:{0}/", sitePort);
return true;
}
Expand All @@ -86,28 +98,32 @@ public void DeleteSite(string applicationName)
// Don't delete the physical files for the service site
DeleteSite(iis, GetServiceSite(applicationName), deletePhysicalFiles: false);

var appPath = PathHelper.GetApplicationPath(applicationName);
var devPath = PathHelper.GetDeveloperApplicationPath(applicationName);
var appPath = _pathResolver.GetApplicationPath(applicationName);
var devPath = _pathResolver.GetDeveloperApplicationPath(applicationName);

DeleteSafe(appPath);
DeleteSafe(devPath);

iis.CommitChanges();
}

public void SetDeveloperSiteWebRoot(string applicationName, string projectPath)
public void SetDeveloperSiteWebRoot(string applicationName, string siteRoot)
{
var iis = new IIS.ServerManager();
string siteName = GetDevSite(applicationName);

IIS.Site site = iis.Sites[siteName];
if (site != null)
{
string devSitePath = PathHelper.GetDeveloperApplicationPath(applicationName);
string webRoot = Path.Combine(devSitePath, Constants.WebRoot, Path.GetDirectoryName(projectPath));
string devSitePath = _pathResolver.GetDeveloperApplicationPath(applicationName);
string webRoot = Path.Combine(devSitePath, Constants.WebRoot, siteRoot);

// Change the web root
site.Applications[0].VirtualDirectories[0].PhysicalPath = webRoot;

iis.CommitChanges();

Thread.Sleep(1000);
}
}

Expand All @@ -122,7 +138,6 @@ private static void MapServiceSitePath(IIS.ServerManager iis, string application
throw new InvalidOperationException("Could not retrieve service site");
}


// Map the path to the live site in the service site
site.Applications.Add(path, siteRoot);
}
Expand Down
4 changes: 4 additions & 0 deletions Kudu.SiteManagement/packages.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="System.IO.Abstractions" version="1.4.0.12" />
</packages>
17 changes: 14 additions & 3 deletions Kudu.Web/App_Start/NinjectMvc3Services.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
using Kudu.Web.Infrastructure;
using System.Configuration;
using System.IO;
using System.Web;
using Kudu.Client.Infrastructure;
using Kudu.SiteManagement;
using Microsoft.Web.Infrastructure.DynamicModuleHelper;
using Ninject;
using Ninject.Web.Mvc;
using Kudu.Client.Infrastructure;

[assembly: WebActivator.PreApplicationStartMethod(typeof(Kudu.Web.App_Start.NinjectMvc3Services), "Start")]
[assembly: WebActivator.ApplicationShutdownMethodAttribute(typeof(Kudu.Web.App_Start.NinjectMvc3Services), "Stop")]
Expand Down Expand Up @@ -49,7 +52,15 @@ private static IKernel CreateKernel()
/// <param name="kernel">The kernel.</param>
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<ISiteManager>().ToConstant(new SiteManager());
string sitePath = HttpRuntime.AppDomainAppPath;
string serviceSitePath = ConfigurationManager.AppSettings["serviceSitePath"];
string sitesPath = ConfigurationManager.AppSettings["sitesPath"];

serviceSitePath = Path.Combine(sitePath, serviceSitePath);
sitesPath = Path.Combine(sitePath, sitesPath);

kernel.Bind<IPathResolver>().ToConstant(new DefaultPathResolver(serviceSitePath, sitesPath));
kernel.Bind<ISiteManager>().To<SiteManager>();
kernel.Bind<ICredentialProvider>().ToConstant(new BasicAuthCredentialProvider("admin", "kudu"));
}
}
Expand Down
25 changes: 11 additions & 14 deletions Kudu.Web/Controllers/ApplicationController.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
using System;
using System.IO;
using System.Linq;
using System.Threading;
using System.Web.Mvc;
using Kudu.Client.Infrastructure;
using Kudu.Client.SourceControl;
using Kudu.Core.SourceControl;
using Kudu.SiteManagement;
using Kudu.Web.Infrastructure;
using Kudu.Web.Models;

Expand All @@ -15,11 +16,15 @@ public class ApplicationController : Controller
private KuduContext db = new KuduContext();
private readonly ISiteManager _siteManager;
private readonly ICredentialProvider _credentialProvider;
private readonly IPathResolver _pathResolver;

public ApplicationController(ISiteManager siteManager, ICredentialProvider credentialProvider)
public ApplicationController(ISiteManager siteManager,
ICredentialProvider credentialProvider,
IPathResolver pathResolver)
{
_siteManager = siteManager;
_credentialProvider = credentialProvider;
_pathResolver = pathResolver;
}

//
Expand Down Expand Up @@ -82,16 +87,11 @@ public ActionResult Create(ApplicationViewModel appViewModel)
Slug = slug,
ServiceUrl = site.ServiceUrl,
SiteUrl = site.SiteUrl,
ServiceAppName = site.ServiceAppName,
SiteName = site.SiteName,
SiteName = slug,
Created = DateTime.Now,
UniqueId = Guid.NewGuid()
};

// Give iis a chance to start the app up
// if we send requests too quickly, we'll end up getting 404s
Thread.Sleep(500);

if (appViewModel.RepositoryType != RepositoryType.None)
{
IRepositoryManager repositoryManager = GetRepositoryManager(app);
Expand Down Expand Up @@ -192,7 +192,7 @@ public ActionResult SetWebRoot(string slug, string projectPath)
return HttpNotFound();
}

_siteManager.SetDeveloperSiteWebRoot(application.Name, projectPath);
_siteManager.SetDeveloperSiteWebRoot(application.Name, Path.GetDirectoryName(projectPath));

return new EmptyResult();
}
Expand All @@ -218,8 +218,8 @@ public ActionResult CreateDeveloperSite(string slug)
return new EmptyResult();
}

string sourceRepositoryPath = PathHelper.GetDeploymentRepositoryPath(application.Name);
string destRepositoryPath = PathHelper.GetDeveloperApplicationPath(application.Name);
string sourceRepositoryPath = Path.Combine(_pathResolver.GetApplicationPath(application.Name), Constants.RepositoryPath);
string destRepositoryPath = Path.Combine(_pathResolver.GetDeveloperApplicationPath(application.Name), Constants.WebRoot);

try
{
Expand All @@ -229,9 +229,6 @@ public ActionResult CreateDeveloperSite(string slug)
string developerSiteUrl;
if (_siteManager.TryCreateDeveloperSite(slug, out developerSiteUrl))
{
// Wait for the mapping to take effect in the service site
Thread.Sleep(1000);

// Clone the repository to the developer site
var devRepositoryManager = new RemoteRepositoryManager(application.ServiceUrl + "dev/scm");
devRepositoryManager.Credentials = _credentialProvider.GetCredentials();
Expand Down
Loading

0 comments on commit 9cdccfb

Please sign in to comment.