private V1Deployment GenerateEnvoyDeployment()

in src/routingmanager/RoutingStateEstablisher.cs [400:529]


        private V1Deployment GenerateEnvoyDeployment(KeyValuePair<V1Service, RoutingStateEstablisherInput> input)
        {
            _log.Verbose("Generating envoy deployment for service '{0}'", input.Key.Metadata.Name);
            var containerPorts = new List<V1ContainerPort>();
            // TODO: This is nasty and needs a better fix
            // As of today we already now that at this point the targetPorts are already all integers because Pragya did so in ReplaceNamedTargetPortsInTriggerServicesAsync
            // This should also be taken care of when we'll migrate to non BETA types:https://devdiv.visualstudio.com/DevDiv/_boards/board/t/Mindaro/Stories/?workitem=1269558
            // With the new non BETA types we don't need intOrString anymore.
            input.Key.Spec.Ports.ExecuteForEach(svcPort => containerPorts.Add(new V1ContainerPort(Int32.Parse(svcPort.TargetPort.Value))));
            var envoyDeploymentName = GetEnvoyDeploymentName(input.Key.Metadata.Name);
            var envoyDeployment = new V1Deployment
            {
                Metadata = new V1ObjectMeta
                {
                    Name = envoyDeploymentName,
                    NamespaceProperty = input.Key.Metadata.NamespaceProperty,
                    Labels = new Dictionary<string, string>
                    {
                        { Routing.GeneratedLabel, "true" },
                        { Constants.EntityLabel, envoyDeploymentName },
                        { Constants.TriggerEntityLabel, GetEntityLabelValue(input.Value) }
                    }
                },
                Spec = new V1DeploymentSpec
                {
                    Strategy = new V1DeploymentStrategy
                    {
                        RollingUpdate = new V1RollingUpdateDeployment
                        {
                            MaxSurge = 2,
                            MaxUnavailable = 1
                        }
                    },
                    Replicas = 2,
                    Selector = new V1LabelSelector
                    {
                        MatchLabels = new Dictionary<string, string>
                        {
                            { Routing.GeneratedLabel, "true" },
                            { Constants.EntityLabel, envoyDeploymentName }
                        }
                    },
                    Template = new V1PodTemplateSpec
                    {
                        Metadata = new V1ObjectMeta
                        {
                            Name = GetEnvoyPodName(input.Key.Metadata.Name),
                            NamespaceProperty = input.Key.Metadata.NamespaceProperty,
                            Labels = new Dictionary<string, string>
                            {
                                { Routing.GeneratedLabel, "true" },
                                { Constants.EntityLabel, envoyDeploymentName }
                            },
                            Annotations = new Dictionary<string, string>
                            {
                                { Annotations.IstioInjection, "false"}
                            }
                        },
                        Spec = new V1PodSpec
                        {
                            TerminationGracePeriodSeconds = 0,
                            Volumes = new List<V1Volume>
                            {
                                {
                                    new V1Volume
                                    {
                                        Name = GetEnvoyConfigMapVolumeName(),
                                        ConfigMap = new V1ConfigMapVolumeSource
                                        {
                                            Name = GetEnvoyConfigMapName(input.Key.Metadata.Name),
                                            Items = new List<V1KeyToPath>
                                            {
                                                {
                                                    new V1KeyToPath
                                                    {
                                                        Key = "config",
                                                        Path = "envoy.yaml"
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            },
                            Containers = new List<V1Container>
                            {
                                new V1Container
                                {
                                    Name = "envoy",
                                    Image = Constants.EnvoyImageName,
                                    Command = new List<string> { "/bin/bash" },
                                    Args = new List<string>
                                    {
                                        "-c",
                                        "touch envoy-logs.txt && /usr/local/bin/envoy --log-path envoy-logs.txt --log-level trace --config-path /etc/envoy/envoy.yaml"
                                    },
                                    Ports = containerPorts,
                                    VolumeMounts = new List<V1VolumeMount>
                                    {
                                        {
                                            new V1VolumeMount()
                                            {
                                                Name = "config",
                                                MountPath = "/etc/envoy",
                                                ReadOnlyProperty = true
                                            }
                                        }
                                    }
                                }
                            },
                            NodeSelector = new Dictionary<string, string>() { { KubernetesConstants.Labels.OS, KubernetesConstants.Labels.Values.Linux } }
                        }
                    }
                }
            };

            // If both pod trigger and ingress trigger are not null, then they should mostly contain the same value,
            // but just in case they don't, give more priority to ingress trigger's probes for AGIC case
            if (input.Value.IngressTriggers != null && input.Value.IngressTriggers.Any(i => i.IsAgicIngress))
            {
                // There will only be one container - running the envoy image
                // But there could potentially be multiple pods getting debugged at the same time under this envoy pod
                // i.e. if multiple people are debugging the same service at the same time.
                // Since kubernetes only supports a single liveness or readiness probe to be added to a pod, we will default to the first one
                envoyDeployment.Spec.Template.Spec.Containers.First().ReadinessProbe = input.Value.IngressTriggers.First().HttpReadinessProbe;
                envoyDeployment.Spec.Template.Spec.Containers.First().LivenessProbe = input.Value.IngressTriggers.First().HttpLivenessProbe;
            }

            return envoyDeployment;
        }