1
0

Use generated docker-compose

This commit is contained in:
nicolas.dorier
2018-03-19 22:54:52 +09:00
parent fb543295d9
commit a3e2d5ea9c
13 changed files with 567 additions and 210 deletions

View 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;
}
}
}

View 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);
}
}
}
}

View 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>