Use generated docker-compose
This commit is contained in:
132
docker-compose-generator/src/DockerComposeDefinition.cs
Normal file
132
docker-compose-generator/src/DockerComposeDefinition.cs
Normal file
@@ -0,0 +1,132 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using YamlDotNet.RepresentationModel;
|
||||
using YamlDotNet.Serialization;
|
||||
using System.IO;
|
||||
|
||||
namespace DockerGenerator
|
||||
{
|
||||
public class DockerComposeDefinition
|
||||
{
|
||||
string[] _Fragments;
|
||||
private string _Name;
|
||||
|
||||
public DockerComposeDefinition(string name, string[] fragments)
|
||||
{
|
||||
_Fragments = fragments;
|
||||
_Name = name;
|
||||
}
|
||||
|
||||
public string FragmentLocation
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
public string BuildOutputDirectory
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
public string GetFilePath()
|
||||
{
|
||||
return Path.Combine(BuildOutputDirectory, $"docker-compose.{_Name}.yml");
|
||||
}
|
||||
public void Build()
|
||||
{
|
||||
Console.WriteLine($"Generating {GetFilePath()}");
|
||||
var deserializer = new DeserializerBuilder().Build();
|
||||
var serializer = new SerializerBuilder().Build();
|
||||
|
||||
Console.WriteLine($"With fragments:");
|
||||
foreach(var fragment in _Fragments)
|
||||
{
|
||||
Console.WriteLine($"\t{fragment}");
|
||||
}
|
||||
var services = new List<KeyValuePair<YamlNode, YamlNode>>();
|
||||
var volumes = new List<KeyValuePair<YamlNode, YamlNode>>();
|
||||
|
||||
foreach(var doc in _Fragments.Select(f => ParseDocument(f)))
|
||||
{
|
||||
if(doc.Children["services"] is YamlMappingNode fragmentServicesRoot)
|
||||
{
|
||||
services.AddRange(fragmentServicesRoot.Children);
|
||||
}
|
||||
|
||||
if(doc.Children["volumes"] is YamlMappingNode fragmentVolumesRoot)
|
||||
{
|
||||
volumes.AddRange(fragmentVolumesRoot.Children);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
YamlMappingNode output = new YamlMappingNode();
|
||||
output.Add("version", new YamlScalarNode("3"));
|
||||
output.Add("services", new YamlMappingNode(Merge(services)));
|
||||
output.Add("volumes", new YamlMappingNode(volumes));
|
||||
var result = serializer.Serialize(output);
|
||||
var outputFile = GetFilePath();
|
||||
File.WriteAllText(outputFile, result.Replace("''", ""));
|
||||
Console.WriteLine($"Generated {outputFile}");
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
private KeyValuePair<YamlNode, YamlNode>[] Merge(List<KeyValuePair<YamlNode, YamlNode>> services)
|
||||
{
|
||||
return services
|
||||
.GroupBy(s => s.Key.ToString(), s=> s.Value)
|
||||
.Select(group =>
|
||||
(GroupName: group.Key,
|
||||
MainNode: group.OfType<YamlMappingNode>().Single(n=> n.Children.ContainsKey("image")),
|
||||
MergedNodes: group.OfType<YamlMappingNode>().Where(n => !n.Children.ContainsKey("image"))))
|
||||
.Select(_ =>
|
||||
{
|
||||
foreach(var node in _.MergedNodes)
|
||||
{
|
||||
foreach(var child in node)
|
||||
{
|
||||
var childValue = child.Value;
|
||||
if(!_.MainNode.Children.TryGetValue(child.Key, out var mainChildValue))
|
||||
{
|
||||
mainChildValue = child.Value;
|
||||
_.MainNode.Add(child.Key, child.Value);
|
||||
}
|
||||
else if(childValue is YamlMappingNode childMapping && mainChildValue is YamlMappingNode mainChildMapping)
|
||||
{
|
||||
foreach(var leaf in childMapping)
|
||||
{
|
||||
if(mainChildMapping.Children.TryGetValue(leaf.Key, out var mainLeaf))
|
||||
{
|
||||
if(leaf.Value is YamlScalarNode leafScalar && mainLeaf is YamlScalarNode leafMainScalar)
|
||||
{
|
||||
leafMainScalar.Value = leafMainScalar.Value + "," + leaf.Value;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mainChildMapping.Add(leaf.Key, leaf.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(childValue is YamlSequenceNode childSequence && mainChildValue is YamlSequenceNode mainSequence)
|
||||
{
|
||||
foreach(var c in childSequence.Children)
|
||||
{
|
||||
mainSequence.Add(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return new KeyValuePair<YamlNode, YamlNode>(_.GroupName, _.MainNode);
|
||||
}).ToArray();
|
||||
}
|
||||
|
||||
private YamlMappingNode ParseDocument(string fragment)
|
||||
{
|
||||
var input = new StringReader(File.ReadAllText(Path.Combine(FragmentLocation, $"{fragment}.yml")));
|
||||
YamlStream stream = new YamlStream();
|
||||
stream.Load(input);
|
||||
return (YamlMappingNode)stream.Documents[0].RootNode;
|
||||
}
|
||||
}
|
||||
}
|
||||
45
docker-compose-generator/src/Program.cs
Normal file
45
docker-compose-generator/src/Program.cs
Normal file
@@ -0,0 +1,45 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using YamlDotNet.Serialization;
|
||||
|
||||
namespace DockerGenerator
|
||||
{
|
||||
class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
new Program().Run();
|
||||
}
|
||||
|
||||
private void Run()
|
||||
{
|
||||
List<DockerComposeDefinition> defs = new List<DockerComposeDefinition>();
|
||||
var btc = new DockerComposeDefinition("btc",
|
||||
new string[] { "nginx", "btcpayserver", "bitcoin" });
|
||||
defs.Add(btc);
|
||||
defs.Add(new DockerComposeDefinition("btc-ltc",
|
||||
new string[] { "nginx", "btcpayserver", "bitcoin", "litecoin" }));
|
||||
|
||||
var fragmentLocation = FindLocation("docker-fragments");
|
||||
var productionLocation = FindLocation("Production");
|
||||
foreach(var def in defs)
|
||||
{
|
||||
def.FragmentLocation = fragmentLocation;
|
||||
def.BuildOutputDirectory = productionLocation;
|
||||
def.Build();
|
||||
}
|
||||
File.Copy(btc.GetFilePath(), Path.Combine(new FileInfo(btc.GetFilePath()).Directory.FullName, "docker-compose.yml"), true);
|
||||
}
|
||||
|
||||
private string FindLocation(string path)
|
||||
{
|
||||
while(true)
|
||||
{
|
||||
if(Directory.Exists(path))
|
||||
return path;
|
||||
path = Path.Combine("..", path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
16
docker-compose-generator/src/docker-compose-generator.csproj
Normal file
16
docker-compose-generator/src/docker-compose-generator.csproj
Normal file
@@ -0,0 +1,16 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp2.0</TargetFramework>
|
||||
<RootNamespace>DockerGenerator</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="NicolasDorier.CommandLine" Version="1.0.0.1" />
|
||||
<PackageReference Include="NicolasDorier.CommandLine.Configuration" Version="1.0.0.2" />
|
||||
<PackageReference Include="NicolasDorier.StandardConfiguration" Version="1.0.0.13" />
|
||||
<PackageReference Include="YamlDotNet" Version="4.3.1" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
Reference in New Issue
Block a user