private async Task _DeployAgentOnlyPodAsync()

in src/library/Connect/KubernetesRemoteEnvironmentManager.cs [322:419]


        private async Task<V1Pod> _DeployAgentOnlyPodAsync(string agentImage, string namespaceName, string podName, string containerName, IDictionary<int, string> tcpPorts, IDictionary<string, string> labels, CancellationToken cancellationToken)
        {
            using (var perfLogger = _log.StartPerformanceLogger(Events.KubernetesRemoteEnvironmentManager.AreaName, Events.KubernetesRemoteEnvironmentManager.Operations.DeployAgentOnlyPod))
            {
                // Generate pod spec
                V1Pod podSpec = new V1Pod()
                {
                    ApiVersion = "v1",
                    Kind = "Pod",
                    Metadata = new V1ObjectMeta
                    {
                        Name = podName
                    },
                    Spec = new V1PodSpec
                    {
                        TerminationGracePeriodSeconds = 0,
                        Containers = new List<V1Container>(),
                        NodeSelector = new Dictionary<string, string>() { { KubernetesConstants.Labels.OS, KubernetesConstants.Labels.Values.Linux } }
                    }
                };

                // Add devhostagent container to the pod
                V1Container containerSpec = new V1Container
                {
                    Image = agentImage,
                    ImagePullPolicy = "IfNotPresent",
                    Name = containerName
                };

                if (tcpPorts != null && tcpPorts.Count > 0)
                {
                    containerSpec.Ports = new List<V1ContainerPort>();
                    foreach (var p in tcpPorts)
                    {
                        containerSpec.Ports.Add(new V1ContainerPort()
                        {
                            ContainerPort = p.Key,
                            Name = p.Value,
                            Protocol = "TCP"
                        });
                    }
                }
                podSpec.Spec.Containers.Add(containerSpec);

                // Add a label to identify that the pod has been created for connect clone scenario
                if (labels != null && labels.Count > 0)
                {
                    podSpec.Metadata.Labels = labels;
                }
                if (podSpec.Metadata.Labels == null)
                {
                    podSpec.Metadata.Labels = new Dictionary<string, string>();
                }
                podSpec.Metadata.Labels[Common.Constants.Labels.ConnectCloneLabel] = "true";

                // Deploy the pod in the namespace and wait for it to get created
                var deployedPod = await _kubernetesClient.CreateV1PodAsync(namespaceName, podSpec, cancellationToken);
                if (deployedPod == null)
                {
                    throw new UserVisibleException(_operationContext, Resources.FailedToDeployPodMessage);
                }
                var podDeployment = new PodDeployment(deployedPod);
                try
                {
                    // Deploy remote restore job
                    await _remoteRestoreJobDeployer.CreateRemoteRestoreJobAsync(deployedPod.Name(), namespaceName, podDeployment, cancellationToken);
                    // Save the pod to deployed pods context
                    _patchState.AddPodDeployment(podDeployment);
                }
                catch (Exception ex)
                {
                    // Try to clean up deployed pod
                    this._ReportProgress(EventLevel.Warning, Resources.RestoringPodDeploymentMessage);
                    await _workloadRestorationService.Value.RemovePodDeploymentAsync(
                        podDeployment,
                        cancellationToken,
                        progressCallback: p => this._ReportProgress(p.Message, p.Level),
                        noThrow: true);
                    var errorMessage = $"Failed to deploy remote restore job for pod deployment {deployedPod.Namespace()}/{deployedPod.Name()}. {ex.Message}";

                    // In this case we cannot really do anything so logging it as warning
                    if (this.IsForbiddenHttpOperationException(ex))
                    {
                        _log.Warning(errorMessage);
                    }
                    else
                    {
                        _log.Error(errorMessage);
                    }
                    throw new UserVisibleException(_operationContext, ex, Resources.FailedToDeployRemoteRestoreJobFormat, deployedPod.Namespace(), deployedPod.Name(), ex.Message);
                }
                deployedPod = await _WaitForPodToRunAsync(deployedPod, TimeSpan.FromMinutes(5), cancellationToken);

                this._ReportProgress(Resources.PodCreatedFormat, deployedPod.Metadata.NamespaceProperty, deployedPod.Metadata.Name);
                perfLogger.SetSucceeded();
                return deployedPod;
            }
        }