merge upstream changes
This commit is contained in:
@@ -8,146 +8,160 @@ using System.IO;
|
||||
|
||||
namespace DockerGenerator
|
||||
{
|
||||
public class DockerComposeDefinition
|
||||
{
|
||||
public List<string> Fragments
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
private string _Name;
|
||||
public class DockerComposeDefinition
|
||||
{
|
||||
public List<string> Fragments
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
private string _Name;
|
||||
|
||||
public DockerComposeDefinition(string name, List<string> fragments)
|
||||
{
|
||||
Fragments = fragments;
|
||||
_Name = name;
|
||||
}
|
||||
public DockerComposeDefinition(string name, List<string> fragments)
|
||||
{
|
||||
Fragments = fragments;
|
||||
_Name = name;
|
||||
}
|
||||
|
||||
public string FragmentLocation
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
public string BuildOutputDirectory
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
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();
|
||||
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>>();
|
||||
Console.WriteLine($"With fragments:");
|
||||
foreach (var fragment in Fragments.ToList())
|
||||
{
|
||||
var fragmentPath = GetFragmentLocation(fragment);
|
||||
if (!File.Exists(fragmentPath))
|
||||
{
|
||||
Console.WriteLine($"\t{fragment} not found in {fragmentPath}, ignoring...");
|
||||
Fragments.Remove(fragment);
|
||||
}
|
||||
else
|
||||
{
|
||||
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.ContainsKey("services") && doc.Children["services"] is YamlMappingNode fragmentServicesRoot)
|
||||
{
|
||||
services.AddRange(fragmentServicesRoot.Children);
|
||||
}
|
||||
foreach (var doc in Fragments.Select(f => ParseDocument(f)))
|
||||
{
|
||||
if (doc.Children.ContainsKey("services") && doc.Children["services"] is YamlMappingNode fragmentServicesRoot)
|
||||
{
|
||||
services.AddRange(fragmentServicesRoot.Children);
|
||||
}
|
||||
|
||||
if(doc.Children.ContainsKey("volumes") && doc.Children["volumes"] is YamlMappingNode fragmentVolumesRoot)
|
||||
{
|
||||
volumes.AddRange(fragmentVolumesRoot.Children);
|
||||
}
|
||||
}
|
||||
if (doc.Children.ContainsKey("volumes") && doc.Children["volumes"] is YamlMappingNode fragmentVolumesRoot)
|
||||
{
|
||||
volumes.AddRange(fragmentVolumesRoot.Children);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
YamlMappingNode output = new YamlMappingNode();
|
||||
output.Add("version", new YamlScalarNode("3") { Style = YamlDotNet.Core.ScalarStyle.DoubleQuoted });
|
||||
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();
|
||||
}
|
||||
YamlMappingNode output = new YamlMappingNode();
|
||||
output.Add("version", new YamlScalarNode("3") { Style = YamlDotNet.Core.ScalarStyle.DoubleQuoted });
|
||||
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>().SingleOrDefault(n => n.Children.ContainsKey("image")),
|
||||
MergedNodes: group.OfType<YamlMappingNode>().Where(n => !n.Children.ContainsKey("image"))))
|
||||
.Where(_ => _.MainNode != null)
|
||||
.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)
|
||||
{
|
||||
var eof = EOF(leafMainScalar.Value) ?? EOF(leaf.Value.ToString());
|
||||
if(eof != null)
|
||||
{
|
||||
leafMainScalar.Value = leafMainScalar.Value + eof + leaf.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
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 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>().SingleOrDefault(n => n.Children.ContainsKey("image")),
|
||||
MergedNodes: group.OfType<YamlMappingNode>().Where(n => !n.Children.ContainsKey("image"))))
|
||||
.Where(_ => _.MainNode != null)
|
||||
.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)
|
||||
{
|
||||
var eof = EOF(leafMainScalar.Value) ?? EOF(leaf.Value.ToString());
|
||||
if (eof != null)
|
||||
{
|
||||
leafMainScalar.Value = leafMainScalar.Value + eof + leaf.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
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 string EOF(string value)
|
||||
{
|
||||
if(value.Contains("\r\n", StringComparison.OrdinalIgnoreCase))
|
||||
return "\r\n";
|
||||
if(value.Contains("\n", StringComparison.OrdinalIgnoreCase))
|
||||
return "\n";
|
||||
return null;
|
||||
}
|
||||
private string EOF(string value)
|
||||
{
|
||||
if (value.Contains("\r\n", StringComparison.OrdinalIgnoreCase))
|
||||
return "\r\n";
|
||||
if (value.Contains("\n", StringComparison.OrdinalIgnoreCase))
|
||||
return "\n";
|
||||
return null;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
private YamlMappingNode ParseDocument(string fragment)
|
||||
{
|
||||
var input = new StringReader(File.ReadAllText(GetFragmentLocation(fragment)));
|
||||
YamlStream stream = new YamlStream();
|
||||
stream.Load(input);
|
||||
return (YamlMappingNode)stream.Documents[0].RootNode;
|
||||
}
|
||||
|
||||
private string GetFragmentLocation(string fragment)
|
||||
{
|
||||
return Path.Combine(FragmentLocation, $"{fragment}.yml");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,50 +14,15 @@ namespace DockerGenerator
|
||||
var root = Environment.GetEnvironmentVariable("INSIDE_CONTAINER") == "1" ? FindRoot("app")
|
||||
: Path.GetFullPath(Path.Combine(FindRoot("docker-compose-generator"), ".."));
|
||||
|
||||
if(args.Any(a => a == "pregen"))
|
||||
{
|
||||
var productionLocation = Path.GetFullPath(Path.Combine(root, "Production"));
|
||||
var testLocation = Path.GetFullPath(Path.Combine(root, "Production-NoReverseProxy"));
|
||||
var composition = DockerComposition.FromEnvironmentVariables();
|
||||
Console.WriteLine("Crypto: " + string.Join(", ", composition.SelectedCryptos.ToArray()));
|
||||
Console.WriteLine("Lightning: " + composition.SelectedLN);
|
||||
Console.WriteLine("ReverseProxy: " + composition.SelectedProxy);
|
||||
var generatedLocation = Path.GetFullPath(Path.Combine(root, "Generated"));
|
||||
|
||||
foreach(var proxy in new[] { "nginx", "no-reverseproxy" })
|
||||
{
|
||||
foreach(var lightning in new[] { "clightning", "" })
|
||||
{
|
||||
foreach(var btc in new[] { "btc", "" })
|
||||
{
|
||||
foreach(var ltc in new[] { "ltc", "" })
|
||||
{
|
||||
if(btc == "" && ltc == "")
|
||||
continue;
|
||||
string name = $"{btc}-{ltc}-{lightning}".Replace("--", "-");
|
||||
if(name.EndsWith("-"))
|
||||
name = name.Substring(0, name.Length - 1);
|
||||
if(name.StartsWith("-"))
|
||||
name = name.Substring(1, name.Length - 1);
|
||||
var composition = new DockerComposition();
|
||||
composition.SelectedCryptos = new HashSet<string>();
|
||||
composition.SelectedCryptos.Add(btc);
|
||||
composition.SelectedCryptos.Add(ltc);
|
||||
composition.SelectedLN = lightning;
|
||||
composition.SelectedProxy = proxy;
|
||||
new Program().Run(composition, name, proxy == "nginx" ? productionLocation : testLocation);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var composition = DockerComposition.FromEnvironmentVariables();
|
||||
Console.WriteLine("Crypto: " + string.Join(", ", composition.SelectedCryptos.ToArray()));
|
||||
Console.WriteLine("Lightning: " + composition.SelectedLN);
|
||||
Console.WriteLine("ReverseProxy: " + composition.SelectedProxy);
|
||||
var generatedLocation = Path.GetFullPath(Path.Combine(root, "Generated"));
|
||||
|
||||
var name = Environment.GetEnvironmentVariable("BTCPAYGEN_SUBNAME");
|
||||
name = string.IsNullOrEmpty(name) ? "generated" : name;
|
||||
new Program().Run(composition, name, generatedLocation);
|
||||
}
|
||||
var name = Environment.GetEnvironmentVariable("BTCPAYGEN_SUBNAME");
|
||||
name = string.IsNullOrEmpty(name) ? "generated" : name;
|
||||
new Program().Run(composition, name, generatedLocation);
|
||||
}
|
||||
|
||||
private void Run(DockerComposition composition, string name, string output)
|
||||
@@ -67,35 +32,44 @@ namespace DockerGenerator
|
||||
fragmentLocation = Path.GetFullPath(Path.Combine(fragmentLocation, "docker-fragments"));
|
||||
|
||||
var fragments = new List<string>();
|
||||
if(composition.SelectedProxy == "nginx")
|
||||
switch (composition.SelectedProxy)
|
||||
{
|
||||
fragments.Add("nginx");
|
||||
}
|
||||
else
|
||||
{
|
||||
fragments.Add("btcpayserver-noreverseproxy");
|
||||
case "nginx":
|
||||
|
||||
fragments.Add("nginx");
|
||||
fragments.Add("btcpayserver-nginx");
|
||||
break;
|
||||
case "traefik":
|
||||
fragments.Add("traefik");
|
||||
fragments.Add("traefik-labels");
|
||||
break;
|
||||
case "no-reverseproxy":
|
||||
fragments.Add("btcpayserver-noreverseproxy");
|
||||
break;
|
||||
}
|
||||
fragments.Add("btcpayserver");
|
||||
foreach(var crypto in CryptoDefinition.GetDefinitions())
|
||||
fragments.Add("nbxplorer");
|
||||
fragments.Add("postgres");
|
||||
foreach (var crypto in CryptoDefinition.GetDefinitions())
|
||||
{
|
||||
if(!composition.SelectedCryptos.Contains(crypto.Crypto))
|
||||
if (!composition.SelectedCryptos.Contains(crypto.Crypto))
|
||||
continue;
|
||||
|
||||
fragments.Add(crypto.CryptoFragment);
|
||||
if(composition.SelectedLN == "clightning" && crypto.CLightningFragment != null)
|
||||
if (composition.SelectedLN == "clightning" && crypto.CLightningFragment != null)
|
||||
{
|
||||
fragments.Add(crypto.CLightningFragment);
|
||||
}
|
||||
if(composition.SelectedLN == "lnd" && crypto.LNDFragment != null)
|
||||
{
|
||||
fragments.Add(crypto.LNDFragment);
|
||||
}
|
||||
}
|
||||
if (composition.SelectedLN == "lnd" && crypto.LNDFragment != null)
|
||||
{
|
||||
fragments.Add(crypto.LNDFragment);
|
||||
}
|
||||
}
|
||||
|
||||
foreach(var fragment in composition.AdditionalFragments)
|
||||
{
|
||||
fragments.Add(fragment.Trim());
|
||||
}
|
||||
foreach (var fragment in composition.AdditionalFragments)
|
||||
{
|
||||
fragments.Add(fragment.Trim());
|
||||
}
|
||||
|
||||
var def = new DockerComposeDefinition(name, fragments);
|
||||
def.FragmentLocation = fragmentLocation;
|
||||
@@ -107,11 +81,11 @@ namespace DockerGenerator
|
||||
{
|
||||
string directory = Directory.GetCurrentDirectory();
|
||||
int i = 0;
|
||||
while(true)
|
||||
while (true)
|
||||
{
|
||||
if(i > 10)
|
||||
if (i > 10)
|
||||
throw new DirectoryNotFoundException(rootDirectory);
|
||||
if(directory.EndsWith(rootDirectory))
|
||||
if (directory.EndsWith(rootDirectory))
|
||||
return directory;
|
||||
directory = Path.GetFullPath(Path.Combine(directory, ".."));
|
||||
i++;
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="YamlDotNet" Version="4.3.1" />
|
||||
<PackageReference Include="YamlDotNet" Version="5.2.1" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
Reference in New Issue
Block a user