ContainerRecipeFactory.cs
1 using System.Globalization; 2 using Utils; 3 4 namespace KubernetesWorkflow.Recipe 5 { 6 public abstract class ContainerRecipeFactory 7 { 8 private readonly List<Port> exposedPorts = new List<Port>(); 9 private readonly List<Port> internalPorts = new List<Port>(); 10 private readonly List<EnvVar> envVars = new List<EnvVar>(); 11 private readonly PodLabels podLabels = new PodLabels(); 12 private readonly PodAnnotations podAnnotations = new PodAnnotations(); 13 private readonly List<VolumeMount> volumeMounts = new List<VolumeMount>(); 14 private readonly List<object> additionals = new List<object>(); 15 private RecipeComponentFactory factory = null!; 16 private ContainerResources resources = new ContainerResources(); 17 private SchedulingAffinity schedulingAffinity = new SchedulingAffinity(); 18 private CommandOverride commandOverride = new CommandOverride(); 19 private bool setCriticalPriority; 20 21 public ContainerRecipe CreateRecipe(int index, int containerNumber, RecipeComponentFactory factory, StartupConfig config) 22 { 23 this.factory = factory; 24 ContainerNumber = containerNumber; 25 Index = index; 26 27 Initialize(config); 28 29 var recipe = new ContainerRecipe(DateTime.UtcNow, containerNumber, config.NameOverride, Image, resources, schedulingAffinity, commandOverride, setCriticalPriority, 30 exposedPorts.ToArray(), 31 internalPorts.ToArray(), 32 envVars.ToArray(), 33 podLabels.Clone(), 34 podAnnotations.Clone(), 35 volumeMounts.ToArray(), 36 ContainerAdditionals.CreateFromUserData(additionals)); 37 38 exposedPorts.Clear(); 39 internalPorts.Clear(); 40 envVars.Clear(); 41 podLabels.Clear(); 42 podAnnotations.Clear(); 43 volumeMounts.Clear(); 44 additionals.Clear(); 45 this.factory = null!; 46 resources = new ContainerResources(); 47 schedulingAffinity = new SchedulingAffinity(); 48 commandOverride = new CommandOverride(); 49 setCriticalPriority = false; 50 51 return recipe; 52 } 53 54 public abstract string AppName { get; } 55 public abstract string Image { get; } 56 protected int ContainerNumber { get; private set; } = 0; 57 protected int Index { get; private set; } = 0; 58 protected abstract void Initialize(StartupConfig config); 59 60 protected Port AddExposedPort(string tag, PortProtocol protocol = PortProtocol.TCP) 61 { 62 return AddExposedPort(factory.CreateExternalPort(tag, protocol)); 63 } 64 65 protected Port AddExposedPort(int number, string tag, PortProtocol protocol = PortProtocol.TCP) 66 { 67 return AddExposedPort(factory.CreateExternalPort(number, tag, protocol)); 68 } 69 70 protected Port AddInternalPort(string tag = "", PortProtocol protocol = PortProtocol.TCP) 71 { 72 var p = factory.CreateInternalPort(tag, protocol); 73 internalPorts.Add(p); 74 return p; 75 } 76 77 protected void AddExposedPortAndVar(string name, string tag, PortProtocol protocol = PortProtocol.TCP) 78 { 79 AddEnvVar(name, AddExposedPort(tag, protocol)); 80 } 81 82 protected void AddInternalPortAndVar(string name, string tag = "", PortProtocol protocol = PortProtocol.TCP) 83 { 84 AddEnvVar(name, AddInternalPort(tag, protocol)); 85 } 86 87 protected void AddEnvVar(string name, string value) 88 { 89 envVars.Add(factory.CreateEnvVar(name, value)); 90 } 91 92 protected void AddEnvVar(string name, int value) 93 { 94 envVars.Add(factory.CreateEnvVar(name, value.ToString(CultureInfo.InvariantCulture))); 95 } 96 97 protected void AddEnvVar(string name, Port value) 98 { 99 envVars.Add(factory.CreateEnvVar(name, value.Number)); 100 } 101 102 protected void AddPodLabel(string name, string value) 103 { 104 podLabels.Add(name, value); 105 } 106 107 protected void AddPodAnnotation(string name, string value) 108 { 109 podAnnotations.Add(name, value); 110 } 111 112 protected void AddVolume(string name, string mountPath, string? subPath = null, string? secret = null, string? hostPath = null) 113 { 114 var size = 10.MB().SizeInBytes.ToString(); 115 volumeMounts.Add(new VolumeMount(name, mountPath, subPath, size, secret, hostPath)); 116 } 117 118 protected void AddVolume(string mountPath, ByteSize volumeSize) 119 { 120 volumeMounts.Add(new VolumeMount( 121 $"autovolume-{Guid.NewGuid().ToString().ToLowerInvariant()}", 122 mountPath, 123 resourceQuantity: volumeSize.SizeInBytes.ToString())); 124 } 125 126 protected void Additional(object userData) 127 { 128 additionals.Add(userData); 129 } 130 131 protected void SetResourcesRequest(int milliCPUs, ByteSize memory) 132 { 133 SetResourcesRequest(new ContainerResourceSet(milliCPUs, memory)); 134 } 135 136 protected void SetSchedulingAffinity(string notIn) 137 { 138 schedulingAffinity = new SchedulingAffinity(notIn); 139 } 140 141 protected void OverrideCommand(params string[] command) 142 { 143 commandOverride = new CommandOverride(command); 144 } 145 146 protected void SetSystemCriticalPriority() 147 { 148 setCriticalPriority = true; 149 } 150 151 // Disabled following a possible bug in the k8s cluster that will throttle containers much more than is 152 // called for if they have resource limits defined. 153 //protected void SetResourceLimits(int milliCPUs, ByteSize memory) 154 //{ 155 // SetResourceLimits(new ContainerResourceSet(milliCPUs, memory)); 156 //} 157 158 protected void SetResourcesRequest(ContainerResourceSet requests) 159 { 160 resources.Requests = requests; 161 } 162 163 protected void SetResourceLimits(ContainerResourceSet limits) 164 { 165 resources.Limits = limits; 166 } 167 168 private Port AddExposedPort(Port port) 169 { 170 exposedPorts.Add(port); 171 return port; 172 } 173 } 174 }