publish-iis command

This commit is contained in:
moozzyk 2016-01-07 16:12:26 -08:00
parent 460b0c993a
commit ae61490092
6 changed files with 301 additions and 1 deletions

3
.gitignore vendored
View File

@ -24,4 +24,5 @@ project.lock.json
*DS_Store
*.ncrunchsolution
*.*sdf
*.ipch
*.ipch
*.vs/

View File

@ -0,0 +1,73 @@
using System;
using System.IO;
using System.Xml;
using System.Xml.Linq;
using Microsoft.Extensions.CommandLineUtils;
namespace Microsoft.AspNet.Tools.PublishIIS
{
public class Program
{
public static int Main(string[] args)
{
var app = new CommandLineApplication
{
// TODO: This needs to be updated once we know how this is going to be called
Name = "dotnet(????) publish-iis",
FullName = "Asp.Net IIS Publisher",
Description = "IIS Publisher for the Asp.Net web applications",
};
app.HelpOption("-h|--help");
var publishFolderOption = app.Option("--publish-folder", "The path to the publish output folder", CommandOptionType.SingleValue);
var appNameOption = app.Option("--application-name", "The name of the application", CommandOptionType.SingleValue);
app.OnExecute(() =>
{
var publishFolder = publishFolderOption.Value();
var appName = appNameOption.Value();
if (publishFolder == null || appName == null)
{
app.ShowHelp();
return 2;
}
XDocument webConfigXml = null;
var webConfigPath = Path.Combine(publishFolder, "wwwroot", "web.config");
if (File.Exists(webConfigPath))
{
try
{
webConfigXml = XDocument.Load(webConfigPath);
}
catch (XmlException) { }
}
var transformedConfig = WebConfigTransform.Transform(webConfigXml, appName);
using (var f = new FileStream(webConfigPath, FileMode.Create))
{
transformedConfig.Save(f);
}
return 0;
});
try
{
return app.Execute(args);
}
catch (Exception e)
{
#if DEBUG
Console.Error.WriteLine(e);
#else
Console.Error.WriteLine(ex.Message);
#endif
}
return 1;
}
}
}

View File

@ -0,0 +1,77 @@
using System;
using System.Linq;
using System.Xml.Linq;
namespace Microsoft.AspNet.Tools.PublishIIS
{
public static class WebConfigTransform
{
public static XDocument Transform(XDocument webConfig, string appName)
{
const string HandlersElementName = "handlers";
const string httpPlatformElementName = "httpPlatform";
webConfig = webConfig == null || webConfig.Root.Name.LocalName != "configuration"
? XDocument.Parse("<configuration />")
: webConfig;
var webServerSection = GetOrCreateChild(webConfig.Root, "system.webServer");
TransformHandlers(GetOrCreateChild(webServerSection, HandlersElementName));
TransformHttpPlatform(GetOrCreateChild(webServerSection, httpPlatformElementName), appName);
// make sure that the httpPlatform element is after handlers element
var httpPlatformElement = webServerSection.Element(HandlersElementName)
.ElementsBeforeSelf(httpPlatformElementName).SingleOrDefault();
if (httpPlatformElement != null)
{
httpPlatformElement.Remove();
webServerSection.Element(HandlersElementName).AddAfterSelf(httpPlatformElement);
}
return webConfig;
}
private static void TransformHandlers(XElement handlersElement)
{
var platformHandlerElement =
handlersElement.Elements("add")
.FirstOrDefault(e => string.Equals((string)e.Attribute("name"), "httpplatformhandler", StringComparison.OrdinalIgnoreCase));
if (platformHandlerElement == null)
{
platformHandlerElement = new XElement("add");
handlersElement.Add(platformHandlerElement);
}
platformHandlerElement.SetAttributeValue("name", "httpPlatformHandler");
SetAttributeValueIfEmpty(platformHandlerElement, "path", "*");
SetAttributeValueIfEmpty(platformHandlerElement, "verb", "*");
SetAttributeValueIfEmpty(platformHandlerElement, "modules", "httpPlatformHandler");
SetAttributeValueIfEmpty(platformHandlerElement, "resourceType", "Unspecified");
}
private static void TransformHttpPlatform(XElement httpPlatformElement, string appName)
{
httpPlatformElement.SetAttributeValue("processPath", $@"..\wwwroot\{appName}");
SetAttributeValueIfEmpty(httpPlatformElement, "stdoutLogEnabled", "false");
SetAttributeValueIfEmpty(httpPlatformElement, "startupTimeLimit", "3600");
}
private static XElement GetOrCreateChild(XElement parent, string childName)
{
var childElement = parent.Element(childName);
if (childElement == null)
{
childElement = new XElement(childName);
parent.Add(childElement);
}
return childElement;
}
private static void SetAttributeValueIfEmpty(XElement element, string attributeName, string value)
{
element.SetAttributeValue(attributeName, (string)element.Attribute(attributeName) ?? value);
}
}
}

View File

@ -0,0 +1,19 @@
{
"name": "publish-iis",
"version": "1.0.0-*",
"compilationOptions": {
"emitEntryPoint": true
},
"dependencies": {
"NETStandard.Library": "1.0.0-*",
"System.Xml.XDocument": "4.0.11-beta-*",
"Microsoft.Extensions.CommandLineUtils": "1.0.0-*"
},
"frameworks": {
"dnxcore50": {
"Microsoft.NETCore.Platforms": "1.0.0-*"
}
}
}

View File

@ -0,0 +1,111 @@
using Xunit;
using System.Linq;
using System.Xml.Linq;
using Microsoft.AspNet.Tools.PublishIIS;
namespace Microsoft.AspNet.Tools.PublishIIS.Tests
{
public class WebConfigTransformFacts
{
private XDocument WebConfigTemplate => XDocument.Parse(
@"<configuration>
<system.webServer>
<handlers>
<add name=""httpPlatformHandler"" path=""*"" verb=""*"" modules=""httpPlatformHandler"" resourceType=""Unspecified""/>
</handlers>
<httpPlatform processPath=""..\wwwroot\test.exe"" stdoutLogEnabled=""false"" startupTimeLimit=""3600""/>
</system.webServer>
</configuration>");
[Fact]
public void WebConfigTransform_creates_new_config_if_one_does_not_exist()
{
Assert.True(XNode.DeepEquals(WebConfigTemplate, WebConfigTransform.Transform(null, "test.exe")));
}
[Fact]
public void WebConfigTransform_creates_new_config_if_one_has_unexpected_format()
{
Assert.True(XNode.DeepEquals(WebConfigTemplate, WebConfigTransform.Transform(XDocument.Parse("<unexpected />"), "test.exe")));
}
[Theory]
[InlineData(new object[] { new[] {"system.webServer"}})]
[InlineData(new object[] { new[] {"add"}})]
[InlineData(new object[] { new[] {"handlers"}})]
[InlineData(new object[] { new[] {"httpPlatform"}})]
[InlineData(new object[] { new[] {"handlers", "httpPlatform"}})]
public void WebConfigTransform_adds_missing_elements(string[] elementNames)
{
var input = new XDocument(WebConfigTemplate);
foreach (var elementName in elementNames)
{
input.Descendants(elementName).Remove();
}
Assert.True(XNode.DeepEquals(WebConfigTemplate, WebConfigTransform.Transform(input, "test.exe")));
}
[Theory]
[InlineData("add", "path", "test")]
[InlineData("add", "verb","test")]
[InlineData("add", "modules", "mods")]
[InlineData("add", "resourceType", "Either")]
[InlineData("httpPlatform", "stdoutLogEnabled", "true")]
[InlineData("httpPlatform", "startupTimeLimit", "1200")]
[InlineData("httpPlatform", "arguments", "arg1")]
[InlineData("httpPlatform", "stdoutLogFile", "logfile.log")]
public void WebConfigTransform_wont_override_custom_values(string elementName, string attributeName, string attributeValue)
{
var input = new XDocument(WebConfigTemplate);
input.Descendants(elementName).Single().SetAttributeValue(attributeName, attributeValue);
var output = WebConfigTransform.Transform(input, "test.exe");
Assert.Equal(attributeValue, (string)output.Descendants(elementName).Single().Attribute(attributeName));
}
[Fact]
public void WebConfigTransform_overwrites_processPath()
{
var newProcessPath =
(string)WebConfigTransform.Transform(WebConfigTemplate, "app.exe")
.Descendants("httpPlatform").Single().Attribute("processPath");
Assert.Equal(@"..\wwwroot\app.exe", newProcessPath);
}
[Fact]
public void WebConfigTransform_fixes_httpPlatformHandler_casing()
{
var input = new XDocument(WebConfigTemplate);
input.Descendants("add").Single().SetAttributeValue("name", "httpplatformhandler");
Assert.True(XNode.DeepEquals(WebConfigTemplate, WebConfigTransform.Transform(input, "test.exe")));
}
[Fact]
public void WebConfigTransform_does_not_remove_children_of_httpPlatform_element()
{
var envVarsElement =
new XElement("environmentVariables",
new XElement("environmentVariable", new XAttribute("name", "ENVVAR"), new XAttribute("value", "123")));
var input = new XDocument(WebConfigTemplate);
input.Descendants("httpPlatform").Single().Add(envVarsElement);
Assert.True(XNode.DeepEquals(envVarsElement,
WebConfigTransform.Transform(input, "app.exe").Descendants("httpPlatform").Single().Elements().Single()));
}
private bool VerifyMissingElementCreated(params string[] elementNames)
{
var input = new XDocument(WebConfigTemplate);
foreach (var elementName in elementNames)
{
input.Descendants(elementName).Remove();
}
return XNode.DeepEquals(WebConfigTemplate, WebConfigTransform.Transform(input, "test.exe"));
}
}
}

View File

@ -0,0 +1,19 @@
{
"dependencies": {
"xunit": "2.1.0",
"Microsoft.AspNet.Tools.PublishIIS" : ""
},
"frameworks": {
"dnxcore50": {
"dependencies": {
"Microsoft.NETCore.Platforms": "1.0.0-*",
"xunit.runner.aspnet": "2.0.0-aspnet-*"
}
}
},
"commands": {
"test": "xunit.runner.aspnet"
}
}