Browse Source

Refactore kubernetes manifest generator (#810)

* removed one intend

* changed 0 <= into == 0 because it can not be less then zero see also #786 for more informations

* added newline looks nicer

* removed intend if

* use of initalizes

* check for not null

* removed if nesteding

* check for null

* check for null

* remove if nesting

* added initializer

* use of language feature destruction key value

* removed unused () brakes

* use of switch statment instend of if
finitereality/replica-status-colors
Marvin Huber 6 years ago
committed by GitHub
parent
commit
d11e807456
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 224
      src/Microsoft.Tye.Core/KubernetesManifestGenerator.cs

224
src/Microsoft.Tye.Core/KubernetesManifestGenerator.cs

@ -42,71 +42,73 @@ namespace Microsoft.Tye
var spec = new YamlMappingNode();
root.Add("spec", spec);
if (ingress.Rules.Count > 0)
if (ingress.Rules.Count == 0)
{
var rules = new YamlSequenceNode();
spec.Add("rules", rules);
return new KubernetesIngressOutput(ingress.Name, new YamlDocument(root));
}
// k8s ingress is grouped by host first, then grouped by path
foreach (var hostgroup in ingress.Rules.GroupBy(r => r.Host))
{
var rule = new YamlMappingNode();
rules.Add(rule);
var rules = new YamlSequenceNode();
spec.Add("rules", rules);
if (!string.IsNullOrEmpty(hostgroup.Key))
{
rule.Add("host", hostgroup.Key);
}
// k8s ingress is grouped by host first, then grouped by path
foreach (var hostgroup in ingress.Rules.GroupBy(r => r.Host))
{
var rule = new YamlMappingNode();
rules.Add(rule);
var http = new YamlMappingNode();
rule.Add("http", http);
if (!string.IsNullOrEmpty(hostgroup.Key))
{
rule.Add("host", hostgroup.Key);
}
var paths = new YamlSequenceNode();
http.Add("paths", paths);
var http = new YamlMappingNode();
rule.Add("http", http);
foreach (var ingressRule in hostgroup)
{
var path = new YamlMappingNode();
paths.Add(path);
var paths = new YamlSequenceNode();
http.Add("paths", paths);
var backend = new YamlMappingNode();
path.Add("backend", backend);
backend.Add("serviceName", ingressRule.Service);
foreach (var ingressRule in hostgroup)
{
var path = new YamlMappingNode();
paths.Add(path);
var service = application.Services.FirstOrDefault(s => s.Name == ingressRule.Service);
if (service is null)
{
throw new InvalidOperationException($"Could not resolve service '{ingressRule.Service}'.");
}
var backend = new YamlMappingNode();
path.Add("backend", backend);
backend.Add("serviceName", ingressRule.Service);
var binding = service.Bindings.FirstOrDefault(b => b.Name is null || b.Name == "http");
if (binding is null)
{
throw new InvalidOperationException($"Could not resolve an http binding for service '{service.Name}'.");
}
var service = application.Services.FirstOrDefault(s => s.Name == ingressRule.Service);
if (service is null)
{
throw new InvalidOperationException($"Could not resolve service '{ingressRule.Service}'.");
}
backend.Add("servicePort", (binding.Port ?? 80).ToString(CultureInfo.InvariantCulture));
var binding = service.Bindings.FirstOrDefault(b => b.Name is null || b.Name == "http");
if (binding is null)
{
throw new InvalidOperationException($"Could not resolve an http binding for service '{service.Name}'.");
}
// Tye implements path matching similar to this example:
// https://kubernetes.github.io/ingress-nginx/examples/rewrite/
//
// Therefore our rewrite-target is set to $2 - we want to make sure we have
// two capture groups.
if (string.IsNullOrEmpty(ingressRule.Path) || ingressRule.Path == "/")
backend.Add("servicePort", (binding.Port ?? 80).ToString(CultureInfo.InvariantCulture));
// Tye implements path matching similar to this example:
// https://kubernetes.github.io/ingress-nginx/examples/rewrite/
//
// Therefore our rewrite-target is set to $2 - we want to make sure we have
// two capture groups.
if (string.IsNullOrEmpty(ingressRule.Path) || ingressRule.Path == "/")
{
path.Add("path", "/()(.*)"); // () is an empty capture group.
}
else
{
if (ingressRule.PreservePath)
{
path.Add("path", "/()(.*)"); // () is an empty capture group.
path.Add("path", $"/()({ingressRule.Path.Trim('/')}.*)");
}
else
{
if (ingressRule.PreservePath)
{
path.Add("path", $"/()({ingressRule.Path.Trim('/')}.*)");
}
else
{
var regex = $"{ingressRule.Path.TrimEnd('/')}(/|$)(.*)";
path.Add("path", regex);
}
var regex = $"{ingressRule.Path.TrimEnd('/')}(/|$)(.*)";
path.Add("path", regex);
}
}
}
@ -182,16 +184,18 @@ namespace Microsoft.Tye
continue;
}
if (binding.Port != null)
if (binding.Port == null)
{
var port = new YamlMappingNode();
ports.Add(port);
port.Add("name", binding.Name ?? binding.Protocol ?? "http");
port.Add("protocol", "TCP"); // we use assume TCP. YOLO
port.Add("port", binding.Port.Value.ToString());
port.Add("targetPort", (binding.ContainerPort ?? binding.Port.Value).ToString());
continue;
}
var port = new YamlMappingNode();
ports.Add(port);
port.Add("name", binding.Name ?? binding.Protocol ?? "http");
port.Add("protocol", "TCP"); // we use assume TCP. YOLO
port.Add("port", binding.Port.Value.ToString());
port.Add("targetPort", (binding.ContainerPort ?? binding.Port.Value).ToString());
}
return new KubernetesServiceOutput(project.Name, new YamlDocument(root));
@ -205,10 +209,11 @@ namespace Microsoft.Tye
{
var bindings = project.Outputs.OfType<ComputedBindings>().FirstOrDefault();
var root = new YamlMappingNode();
root.Add("kind", "Deployment");
root.Add("apiVersion", "apps/v1");
var root = new YamlMappingNode
{
{"kind", "Deployment"},
{"apiVersion", "apps/v1"}
};
var metadata = new YamlMappingNode();
root.Add("metadata", metadata);
@ -343,7 +348,7 @@ namespace Microsoft.Tye
});
}
if (bindings is object)
if (bindings != null)
{
AddEnvironmentVariablesForComputedBindings(env, bindings);
}
@ -377,12 +382,14 @@ namespace Microsoft.Tye
continue;
}
if (binding.Port != null)
if (binding.Port == null)
{
var containerPort = new YamlMappingNode();
ports.Add(containerPort);
containerPort.Add("containerPort", (binding.ContainerPort ?? binding.Port.Value).ToString());
continue;
}
var containerPort = new YamlMappingNode();
ports.Add(containerPort);
containerPort.Add("containerPort", (binding.ContainerPort ?? binding.Port.Value).ToString());
}
}
@ -431,48 +438,51 @@ namespace Microsoft.Tye
});
}
if (sidecarBindings is object)
if (sidecarBindings != null)
{
AddEnvironmentVariablesForComputedBindings(env, sidecarBindings);
}
}
if (project.RelocateDiagnosticsDomainSockets)
if (!project.RelocateDiagnosticsDomainSockets)
{
// volumeMounts:
// - name: shared-data
// mountPath: /usr/share/nginx/html
var volumeMounts = new YamlSequenceNode();
container.Add("volumeMounts", volumeMounts);
var volumeMount = new YamlMappingNode();
volumeMounts.Add(volumeMount);
volumeMount.Add("name", "tye-diagnostics");
volumeMount.Add("mountPath", "/var/tye/diagnostics");
continue;
}
// volumeMounts:
// - name: shared-data
// mountPath: /usr/share/nginx/html
var volumeMounts = new YamlSequenceNode();
container.Add("volumeMounts", volumeMounts);
var volumeMount = new YamlMappingNode();
volumeMounts.Add(volumeMount);
volumeMount.Add("name", "tye-diagnostics");
volumeMount.Add("mountPath", "/var/tye/diagnostics");
}
if (project.RelocateDiagnosticsDomainSockets)
if (!project.RelocateDiagnosticsDomainSockets)
{
// volumes:
// - name: shared-data
// emptyDir: {}
var volumes = new YamlSequenceNode();
spec.Add("volumes", volumes);
var volume = new YamlMappingNode();
volumes.Add(volume);
volume.Add("name", "tye-diagnostics");
volume.Add("emptyDir", new YamlMappingNode());
return new KubernetesDeploymentOutput(project.Name, new YamlDocument(root));
}
// volumes:
// - name: shared-data
// emptyDir: {}
var volumes = new YamlSequenceNode();
spec.Add("volumes", volumes);
var volume = new YamlMappingNode();
volumes.Add(volume);
volume.Add("name", "tye-diagnostics");
volume.Add("emptyDir", new YamlMappingNode());
return new KubernetesDeploymentOutput(project.Name, new YamlDocument(root));
}
private static void AddProbe(ServiceBuilder service, YamlMappingNode container, ProbeBuilder builder, string name)
private static void AddProbe(ServiceBuilder service, YamlMappingNode container, ProbeBuilder builder, string probeName)
{
var probe = new YamlMappingNode();
container.Add(name, probe);
container.Add(probeName, probe);
if (builder.Http != null)
{
@ -511,11 +521,13 @@ namespace Microsoft.Tye
var headers = new YamlSequenceNode();
httpGet.Add("httpHeaders", headers);
foreach (var builderHeader in builderHttp.Headers)
foreach (var (name, value) in builderHttp.Headers)
{
var header = new YamlMappingNode();
header.Add("name", builderHeader.Key);
header.Add("value", builderHeader.Value.ToString()!);
var header = new YamlMappingNode
{
{"name", name},
{"value", value.ToString()!}
};
headers.Add(header);
}
}
@ -531,7 +543,7 @@ namespace Microsoft.Tye
{
foreach (var binding in bindings.Bindings.OfType<EnvironmentVariableInputBinding>())
{
env.Add(new YamlMappingNode()
env.Add(new YamlMappingNode
{
{ "name", binding.Name },
{ "value", new YamlScalarNode(binding.Value) { Style = ScalarStyle.SingleQuoted, } },
@ -546,16 +558,16 @@ namespace Microsoft.Tye
// name: mysecret
// key: username
if (binding is SecretConnectionStringInputBinding connectionStringBinding)
{
AddSecret(env, connectionStringBinding.KeyName, binding.Name, "connectionstring");
}
else if (binding is SecretUrlInputBinding urlBinding)
switch (binding)
{
AddSecret(env, $"{urlBinding.KeyNameBase}__PROTOCOL", binding.Name, "protocol");
AddSecret(env, $"{urlBinding.KeyNameBase}__HOST", binding.Name, "host");
AddSecret(env, $"{urlBinding.KeyNameBase}__PORT", binding.Name, "port");
case SecretConnectionStringInputBinding connectionStringBinding:
AddSecret(env, connectionStringBinding.KeyName, binding.Name, "connectionstring");
break;
case SecretUrlInputBinding urlBinding:
AddSecret(env, $"{urlBinding.KeyNameBase}__PROTOCOL", binding.Name, "protocol");
AddSecret(env, $"{urlBinding.KeyNameBase}__HOST", binding.Name, "host");
AddSecret(env, $"{urlBinding.KeyNameBase}__PORT", binding.Name, "port");
break;
}
}

Loading…
Cancel
Save