add service dependency detection
This commit is contained in:
Родитель
01e6ab7326
Коммит
90278e0dd6
|
@ -49,7 +49,7 @@ namespace Steeltoe.Tooling.Controllers
|
|||
/// <returns>The project.</returns>
|
||||
protected Deployment GetDeployment()
|
||||
{
|
||||
return new DeploymentBuilder().BuildDeployment(Context.WorkingDirectory);
|
||||
return new DeploymentBuilder(Context).BuildDeployment();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,17 +21,27 @@ namespace Steeltoe.Tooling.Models
|
|||
/// </summary>
|
||||
public class DeploymentBuilder
|
||||
{
|
||||
private readonly Context _context;
|
||||
|
||||
/// <summary>
|
||||
/// Create a DocumentBuilder for the specified directory.
|
||||
/// </summary>
|
||||
public DeploymentBuilder(Context context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a deployment for the specified directory.
|
||||
/// </summary>
|
||||
/// <returns>deployment model</returns>
|
||||
public Deployment BuildDeployment(string directory)
|
||||
public Deployment BuildDeployment()
|
||||
{
|
||||
var name = Path.GetFileName(directory);
|
||||
var name = Path.GetFileName(_context.WorkingDirectory);
|
||||
var deployment = new Deployment
|
||||
{
|
||||
Name = name,
|
||||
Project = new ProjectBuilder().BuildProject(Path.Join(directory, $"{name}.csproj"))
|
||||
Project = new ProjectBuilder(_context, Path.Join(_context.WorkingDirectory, $"{name}.csproj")).BuildProject()
|
||||
};
|
||||
return deployment;
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ namespace Steeltoe.Tooling.Models
|
|||
}
|
||||
|
||||
private string _name;
|
||||
|
||||
/// <summary>
|
||||
/// Project file path.
|
||||
/// </summary>
|
||||
|
@ -45,6 +46,12 @@ namespace Steeltoe.Tooling.Models
|
|||
[YamlMember(Alias = "framework")]
|
||||
public string Framework { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Docker image.
|
||||
/// </summary>
|
||||
[YamlMember(Alias = "image")]
|
||||
public string Image { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Network ports.
|
||||
/// </summary>
|
||||
|
@ -55,6 +62,6 @@ namespace Steeltoe.Tooling.Models
|
|||
/// Project service dependencies to be deployed.
|
||||
/// </summary>
|
||||
[YamlMember(Alias = "services")]
|
||||
public List<Service> Services { get; }
|
||||
public List<Service> Services { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,9 +28,13 @@ namespace Steeltoe.Tooling.Models
|
|||
public class ProjectBuilder
|
||||
{
|
||||
private static readonly ILogger Logger = Logging.LoggerFactory.CreateLogger<ProjectBuilder>();
|
||||
|
||||
private static readonly List<Protocol> DefaultProtocols = new List<Protocol>();
|
||||
|
||||
private Context _context;
|
||||
private readonly string _projectFile;
|
||||
private readonly string _launchSettingsFile;
|
||||
private XmlDocument _projectDoc;
|
||||
|
||||
static ProjectBuilder()
|
||||
{
|
||||
DefaultProtocols.Add(new Protocol("http", 8080));
|
||||
|
@ -41,39 +45,59 @@ namespace Steeltoe.Tooling.Models
|
|||
/// </summary>
|
||||
public string ProjectFile { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Create a ProjectBuilder for the specified project file.
|
||||
/// </summary>
|
||||
public ProjectBuilder(Context context, string projectFile)
|
||||
{
|
||||
_context = context;
|
||||
_projectFile = projectFile;
|
||||
_launchSettingsFile = Path.Join(Path.GetDirectoryName(projectFile), "Properties", "launchSettings.json");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a Project representation of the ProjectFile.
|
||||
/// </summary>
|
||||
/// <returns>project model</returns>
|
||||
public Project BuildProject(string projectFile)
|
||||
public Project BuildProject()
|
||||
{
|
||||
Logger.LogDebug($"loading project file: {projectFile}");
|
||||
if (!File.Exists(projectFile))
|
||||
Logger.LogDebug($"loading project file: {_projectFile}");
|
||||
if (!File.Exists(_projectFile))
|
||||
{
|
||||
throw new ToolingException($"project file not found: {projectFile}");
|
||||
throw new ToolingException($"project file not found: {_projectFile}");
|
||||
}
|
||||
|
||||
_projectDoc = new XmlDocument();
|
||||
_projectDoc.Load(_projectFile);
|
||||
var project = new Project
|
||||
{
|
||||
Name = Path.GetFileNameWithoutExtension(projectFile),
|
||||
File = Path.GetFileName(projectFile),
|
||||
Framework = GetFramework(projectFile),
|
||||
Protocols = GetProtocols(projectFile)
|
||||
Name = Path.GetFileNameWithoutExtension(_projectFile),
|
||||
File = Path.GetFileName(_projectFile)
|
||||
};
|
||||
project.Framework = GetFramework();
|
||||
if (_context.Registry.Images.TryGetValue(project.Framework, out var image))
|
||||
{
|
||||
project.Image = image;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ToolingException($"no image for framework: {project.Framework}");
|
||||
}
|
||||
|
||||
project.Protocols = GetProtocols();
|
||||
project.Services = GetServices();
|
||||
return project;
|
||||
}
|
||||
|
||||
private string GetFramework(string projectFile)
|
||||
private string GetFramework()
|
||||
{
|
||||
XmlDocument projectDoc = new XmlDocument();
|
||||
projectDoc.Load(projectFile);
|
||||
XmlNodeList nodes = projectDoc.SelectNodes("/Project/PropertyGroup/TargetFramework");
|
||||
XmlNodeList nodes = _projectDoc.SelectNodes("/Project/PropertyGroup/TargetFramework");
|
||||
if (nodes.Count > 0)
|
||||
{
|
||||
return nodes[0].InnerText;
|
||||
}
|
||||
|
||||
nodes = projectDoc.SelectNodes("/Project/PropertyGroup/TargetFrameworks");
|
||||
nodes = _projectDoc.SelectNodes("/Project/PropertyGroup/TargetFrameworks");
|
||||
if (nodes.Count > 0)
|
||||
{
|
||||
return nodes[0].InnerText.Split(';')[0];
|
||||
|
@ -82,18 +106,16 @@ namespace Steeltoe.Tooling.Models
|
|||
throw new ToolingException("could not determine framework");
|
||||
}
|
||||
|
||||
private List<Protocol> GetProtocols(string projectFile)
|
||||
private List<Protocol> GetProtocols()
|
||||
{
|
||||
var launchSettingsPath =
|
||||
Path.Join(Path.GetDirectoryName(projectFile), "Properties", "launchSettings.json");
|
||||
if (!File.Exists(launchSettingsPath))
|
||||
if (!File.Exists(_launchSettingsFile))
|
||||
{
|
||||
return DefaultProtocols;
|
||||
}
|
||||
|
||||
Logger.LogDebug($"loading launch settings: {launchSettingsPath}");
|
||||
Logger.LogDebug($"loading launch settings: {_launchSettingsFile}");
|
||||
var yaml = new YamlStream();
|
||||
using (var reader = new StreamReader(launchSettingsPath))
|
||||
using (var reader = new StreamReader(_launchSettingsFile))
|
||||
{
|
||||
yaml.Load(reader);
|
||||
}
|
||||
|
@ -101,7 +123,7 @@ namespace Steeltoe.Tooling.Models
|
|||
var root = (YamlMappingNode) yaml.Documents[0].RootNode;
|
||||
var profiles = (YamlMappingNode) root.Children[new YamlScalarNode("profiles")];
|
||||
var profile =
|
||||
(YamlMappingNode) profiles.Children[new YamlScalarNode(Path.GetFileNameWithoutExtension(projectFile))];
|
||||
(YamlMappingNode) profiles.Children[new YamlScalarNode(Path.GetFileNameWithoutExtension(_projectFile))];
|
||||
if (!profile.Children.ContainsKey(new YamlScalarNode("applicationUrl")))
|
||||
{
|
||||
return DefaultProtocols;
|
||||
|
@ -118,5 +140,64 @@ namespace Steeltoe.Tooling.Models
|
|||
protocols.Sort();
|
||||
return protocols;
|
||||
}
|
||||
|
||||
private List<Service> GetServices()
|
||||
{
|
||||
List<Service> services = new List<Service>();
|
||||
Dictionary<string, string> serviceNugets = new Dictionary<string, string>();
|
||||
serviceNugets["Pivotal.GemFire"] = "gemfire";
|
||||
serviceNugets["Microsoft.EntityFrameworkCore.SqlServer"] = "mssql";
|
||||
serviceNugets["MySql.Data"] = "mysql";
|
||||
serviceNugets["Pomelo.EntityFrameworkCore.MySql"] = "mysql";
|
||||
serviceNugets["Npgsql"] = "pgsql";
|
||||
serviceNugets["Npgsql.EntityFrameworkCore.PostgreSQL"] = "pgsql";
|
||||
serviceNugets["RabbitMQ.Client"] = "rabbitmq";
|
||||
serviceNugets["Microsoft.Extensions.Caching.StackExchangeRedis"] = "redis";
|
||||
foreach (var serviceNuget in serviceNugets.Keys)
|
||||
{
|
||||
var xpath = $"/Project/ItemGroup/PackageReference[@Include='{serviceNuget}']";
|
||||
if (_projectDoc.SelectNodes(xpath).Count == 0)
|
||||
{
|
||||
xpath = $"/Project/ItemGroup/Reference[@Include='{serviceNuget}']";
|
||||
if (_projectDoc.SelectNodes(xpath).Count == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
var serviceName = serviceNugets[serviceNuget];
|
||||
var service = new Service()
|
||||
{
|
||||
Name = serviceName,
|
||||
Type = serviceName
|
||||
};
|
||||
if (_context.Registry.Images.TryGetValue(service.Name, out var image))
|
||||
{
|
||||
service.Image = image;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ToolingException($"no image for service: {service.Name}");
|
||||
}
|
||||
|
||||
if (_context.Registry.Ports.TryGetValue(service.Name, out var port))
|
||||
{
|
||||
service.Port = port;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ToolingException($"no port for service: {service.Name}");
|
||||
}
|
||||
|
||||
services.Add(service);
|
||||
}
|
||||
|
||||
if (services.Count == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,39 @@ using YamlDotNet.Serialization;
|
|||
|
||||
namespace Steeltoe.Tooling.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// A model of a project service dependency.
|
||||
/// </summary>
|
||||
public class Service
|
||||
{
|
||||
/// <summary>
|
||||
/// Service name.
|
||||
/// </summary>
|
||||
[YamlMember(Alias = "name")]
|
||||
public string Name
|
||||
{
|
||||
get => _name;
|
||||
set => _name = value.ToLower();
|
||||
}
|
||||
|
||||
private string _name;
|
||||
|
||||
/// <summary>
|
||||
/// Service type.
|
||||
/// </summary>
|
||||
[YamlMember(Alias = "type")]
|
||||
public string Type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Service port.
|
||||
/// </summary>
|
||||
[YamlMember(Alias = "port")]
|
||||
public int Port { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Docker image.
|
||||
/// </summary>
|
||||
[YamlMember(Alias = "image")]
|
||||
public string Image { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,11 @@ namespace Steeltoe.Tooling
|
|||
/// </summary>
|
||||
public Dictionary<string, string> Images { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Service ports.
|
||||
/// </summary>
|
||||
public Dictionary<string, int> Ports { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Load the registry from the specified directory.
|
||||
/// </summary>
|
||||
|
@ -32,6 +37,10 @@ namespace Steeltoe.Tooling
|
|||
{
|
||||
Images = deserializer.Deserialize<Dictionary<string, string>>(reader);
|
||||
}
|
||||
using (var reader = new StreamReader(Path.Join(directory, "ports.yml")))
|
||||
{
|
||||
Ports = deserializer.Deserialize<Dictionary<string, int>>(reader);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,2 +1,7 @@
|
|||
mssql: steeltoeoss/mssql-amd64-linux
|
||||
mysql: steeltoeoss/mysql:5.7
|
||||
pgsql: steeltoeoss/postgresql:10.8
|
||||
rabbitmq: steeltoeoss/rabbitmq:3.7
|
||||
redis: steeltoeoss/redis-amd64-linux:4.0.11
|
||||
netcoreapp2.1: mcr.microsoft.com/dotnet/core/sdk:2.1
|
||||
netcoreapp3.1: mcr.microsoft.com/dotnet/core/sdk:3.1
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
mssql: 1433
|
||||
mysql: 3306
|
||||
pgsql: 5432
|
||||
rabbitmq: 5672
|
||||
redis: 5672
|
Загрузка…
Ссылка в новой задаче