Add Nginx Deployer
This commit is contained in:
parent
b06a84457d
commit
22eab75005
|
|
@ -61,9 +61,9 @@ namespace Microsoft.AspNetCore.Server.Testing
|
|||
|
||||
public string EnvironmentName { get; set; }
|
||||
|
||||
public string ApplicationHostConfigTemplateContent { get; set; }
|
||||
public string ServerConfigTemplateContent { get; set; }
|
||||
|
||||
public string ApplicationHostConfigLocation { get; set; }
|
||||
public string ServerConfigLocation { get; set; }
|
||||
|
||||
public string SiteName { get; set; }
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ namespace Microsoft.AspNetCore.Server.Testing
|
|||
IISExpress,
|
||||
IIS,
|
||||
WebListener,
|
||||
Kestrel
|
||||
Kestrel,
|
||||
Nginx
|
||||
}
|
||||
}
|
||||
|
|
@ -40,6 +40,8 @@ namespace Microsoft.AspNetCore.Server.Testing
|
|||
case ServerType.WebListener:
|
||||
case ServerType.Kestrel:
|
||||
return new SelfHostDeployer(deploymentParameters, logger);
|
||||
case ServerType.Nginx:
|
||||
return new NginxDeployer(deploymentParameters, logger);
|
||||
default:
|
||||
throw new NotSupportedException(
|
||||
string.Format("Found no deployers suitable for server type '{0}' with the current runtime.",
|
||||
|
|
|
|||
|
|
@ -50,19 +50,19 @@ namespace Microsoft.AspNetCore.Server.Testing
|
|||
|
||||
private CancellationToken StartIISExpress(Uri uri)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(DeploymentParameters.ApplicationHostConfigTemplateContent))
|
||||
if (!string.IsNullOrWhiteSpace(DeploymentParameters.ServerConfigTemplateContent))
|
||||
{
|
||||
// Pass on the applicationhost.config to iis express. With this don't need to pass in the /path /port switches as they are in the applicationHost.config
|
||||
// We take a copy of the original specified applicationHost.Config to prevent modifying the one in the repo.
|
||||
|
||||
DeploymentParameters.ApplicationHostConfigTemplateContent =
|
||||
DeploymentParameters.ApplicationHostConfigTemplateContent
|
||||
DeploymentParameters.ServerConfigTemplateContent =
|
||||
DeploymentParameters.ServerConfigTemplateContent
|
||||
.Replace("[ApplicationPhysicalPath]", DeploymentParameters.ApplicationPath)
|
||||
.Replace("[PORT]", uri.Port.ToString());
|
||||
|
||||
DeploymentParameters.ApplicationHostConfigLocation = Path.GetTempFileName();
|
||||
DeploymentParameters.ServerConfigLocation = Path.GetTempFileName();
|
||||
|
||||
File.WriteAllText(DeploymentParameters.ApplicationHostConfigLocation, DeploymentParameters.ApplicationHostConfigTemplateContent);
|
||||
File.WriteAllText(DeploymentParameters.ServerConfigLocation, DeploymentParameters.ServerConfigTemplateContent);
|
||||
}
|
||||
|
||||
var webroot = DeploymentParameters.ApplicationPath;
|
||||
|
|
@ -71,9 +71,9 @@ namespace Microsoft.AspNetCore.Server.Testing
|
|||
webroot = Path.Combine(webroot, "wwwroot");
|
||||
}
|
||||
|
||||
var parameters = string.IsNullOrWhiteSpace(DeploymentParameters.ApplicationHostConfigLocation) ?
|
||||
var parameters = string.IsNullOrWhiteSpace(DeploymentParameters.ServerConfigLocation) ?
|
||||
string.Format("/port:{0} /path:\"{1}\" /trace:error", uri.Port, webroot) :
|
||||
string.Format("/site:{0} /config:{1} /trace:error", DeploymentParameters.SiteName, DeploymentParameters.ApplicationHostConfigLocation);
|
||||
string.Format("/site:{0} /config:{1} /trace:error", DeploymentParameters.SiteName, DeploymentParameters.ServerConfigLocation);
|
||||
|
||||
var iisExpressPath = GetIISExpressPath();
|
||||
|
||||
|
|
@ -140,18 +140,18 @@ namespace Microsoft.AspNetCore.Server.Testing
|
|||
{
|
||||
ShutDownIfAnyHostProcess(_hostProcess);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(DeploymentParameters.ApplicationHostConfigLocation)
|
||||
&& File.Exists(DeploymentParameters.ApplicationHostConfigLocation))
|
||||
if (!string.IsNullOrWhiteSpace(DeploymentParameters.ServerConfigLocation)
|
||||
&& File.Exists(DeploymentParameters.ServerConfigLocation))
|
||||
{
|
||||
// Delete the temp applicationHostConfig that we created.
|
||||
try
|
||||
{
|
||||
File.Delete(DeploymentParameters.ApplicationHostConfigLocation);
|
||||
File.Delete(DeploymentParameters.ServerConfigLocation);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
// Ignore delete failures - just write a log.
|
||||
Logger.LogWarning("Failed to delete '{config}'. Exception : {exception}", DeploymentParameters.ApplicationHostConfigLocation, exception.Message);
|
||||
Logger.LogWarning("Failed to delete '{config}'. Exception : {exception}", DeploymentParameters.ServerConfigLocation, exception.Message);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,138 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Net.Http;
|
||||
using Microsoft.AspNetCore.Server.Testing.Common;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Microsoft.AspNetCore.Server.Testing
|
||||
{
|
||||
/// <summary>
|
||||
/// Deployer for Kestrel on Nginx.
|
||||
/// </summary>
|
||||
public class NginxDeployer : SelfHostDeployer
|
||||
{
|
||||
private string _configFile;
|
||||
private readonly int _waitTime = (int)TimeSpan.FromSeconds(30).TotalMilliseconds;
|
||||
|
||||
public NginxDeployer(DeploymentParameters deploymentParameters, ILogger logger)
|
||||
: base(deploymentParameters, logger)
|
||||
{
|
||||
}
|
||||
|
||||
public override DeploymentResult Deploy()
|
||||
{
|
||||
_configFile = Path.GetTempFileName();
|
||||
var uri = new Uri(DeploymentParameters.ApplicationBaseUriHint);
|
||||
|
||||
var redirectUri = $"http://localhost:{TestUriHelper.FindFreePort()}";
|
||||
|
||||
var exitToken = StartSelfHost(new Uri(redirectUri));
|
||||
|
||||
SetupNginx(redirectUri, uri);
|
||||
|
||||
// Wait for App to be loaded since Nginx returns 502 instead of 503 when App isn't loaded
|
||||
// Target actual address to avoid going through Nginx proxy
|
||||
using (var httpClient = new HttpClient())
|
||||
{
|
||||
var response = RetryHelper.RetryRequest(() =>
|
||||
{
|
||||
return httpClient.GetAsync(redirectUri);
|
||||
}, Logger).Result;
|
||||
|
||||
if (!response.IsSuccessStatusCode)
|
||||
{
|
||||
throw new InvalidOperationException("Deploy failed");
|
||||
}
|
||||
}
|
||||
|
||||
return new DeploymentResult
|
||||
{
|
||||
WebRootLocation = DeploymentParameters.ApplicationPath,
|
||||
DeploymentParameters = DeploymentParameters,
|
||||
ApplicationBaseUri = uri.ToString(),
|
||||
HostShutdownToken = exitToken
|
||||
};
|
||||
}
|
||||
|
||||
private void SetupNginx(string redirectUri, Uri originalUri)
|
||||
{
|
||||
// copy nginx.conf template and replace pertinent information
|
||||
DeploymentParameters.ServerConfigTemplateContent = DeploymentParameters.ServerConfigTemplateContent
|
||||
.Replace("[user]", Environment.GetEnvironmentVariable("LOGNAME"))
|
||||
.Replace("[listenPort]", originalUri.Port.ToString())
|
||||
.Replace("[redirectUri]", redirectUri)
|
||||
.Replace("[pidFile]", Path.Combine(DeploymentParameters.ApplicationPath, Guid.NewGuid().ToString()));
|
||||
File.WriteAllText(_configFile, DeploymentParameters.ServerConfigTemplateContent);
|
||||
|
||||
var startInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = "nginx",
|
||||
Arguments = $"-c {_configFile}",
|
||||
UseShellExecute = false,
|
||||
CreateNoWindow = true,
|
||||
RedirectStandardError = true,
|
||||
RedirectStandardOutput = true,
|
||||
// Trying a work around for https://github.com/aspnet/Hosting/issues/140.
|
||||
RedirectStandardInput = true
|
||||
};
|
||||
|
||||
using (var runNginx = new Process() { StartInfo = startInfo })
|
||||
{
|
||||
runNginx.ErrorDataReceived += (sender, dataArgs) =>
|
||||
{
|
||||
if (!string.IsNullOrEmpty(dataArgs.Data))
|
||||
{
|
||||
Logger.LogWarning("nginx: " + dataArgs.Data);
|
||||
}
|
||||
};
|
||||
runNginx.OutputDataReceived += (sender, dataArgs) =>
|
||||
{
|
||||
if (!string.IsNullOrEmpty(dataArgs.Data))
|
||||
{
|
||||
Logger.LogInformation("nginx: " + dataArgs.Data);
|
||||
}
|
||||
};
|
||||
runNginx.Start();
|
||||
runNginx.BeginErrorReadLine();
|
||||
runNginx.BeginOutputReadLine();
|
||||
runNginx.WaitForExit(_waitTime);
|
||||
if (runNginx.ExitCode != 0)
|
||||
{
|
||||
throw new Exception("Failed to start Nginx");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
if (!string.IsNullOrEmpty(_configFile))
|
||||
{
|
||||
var startInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = "nginx",
|
||||
Arguments = $"-s stop -c {_configFile}",
|
||||
UseShellExecute = false,
|
||||
CreateNoWindow = true,
|
||||
RedirectStandardError = true,
|
||||
RedirectStandardOutput = true,
|
||||
// Trying a work around for https://github.com/aspnet/Hosting/issues/140.
|
||||
RedirectStandardInput = true
|
||||
};
|
||||
|
||||
using (var runNginx = new Process() { StartInfo = startInfo })
|
||||
{
|
||||
runNginx.Start();
|
||||
runNginx.WaitForExit(_waitTime);
|
||||
}
|
||||
|
||||
File.Delete(_configFile);
|
||||
}
|
||||
|
||||
base.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -46,7 +46,7 @@ namespace Microsoft.AspNetCore.Server.Testing
|
|||
};
|
||||
}
|
||||
|
||||
private CancellationToken StartSelfHost(Uri uri)
|
||||
protected CancellationToken StartSelfHost(Uri uri)
|
||||
{
|
||||
string executableName;
|
||||
string executableArgs = string.Empty;
|
||||
|
|
|
|||
Loading…
Reference in New Issue