in src/dsc/Commands/Connect/ConnectCommand.cs [488:570]
private async Task<(ExitCode, string)> ExecuteInnerContainerizedAsync(IConnectManagementClient connectManagementClient, KubeConfigDetails kubeConfigDetails, CancellationToken cancellationToken, IRoutingManagementClient routingManagementClient = null)
{
string localAgentContainerName = string.Empty;
try
{
// TODO (lolodi): To speed things up we should deploy routing manager and remote agent at the same time, instead of awaiting on the deployment of one before deploying the other.
// This should also be done in the normal ExecuteInnerAsync
if (!string.IsNullOrEmpty(_routingHeaderValue))
{
await routingManagementClient.DeployRoutingManagerAsync(cancellationToken);
}
var remoteAgentInfo = await connectManagementClient.StartRemoteAgentAsync(cancellationToken);
if (!string.IsNullOrEmpty(_routingHeaderValue))
{
// If routing is enabled, wait until the routing manager is connected to say the connection has been established successfully.
var routingStatus = await routingManagementClient.GetStatusAsync(remoteAgentInfo.PodName, cancellationToken);
if (routingStatus.Value.IsConnected == null)
{
_log.Error(routingStatus.Value.ErrorMessage);
throw new UserVisibleException(_operationContext, Resources.FailedToGetRoutingManagerDeploymentStatusFormat, string.Format(CommonResources.CorrelationIdErrorMessageFormat, _operationContext.CorrelationId));
}
else if (routingStatus.Value.IsConnected == false)
{
throw new UserVisibleException(_operationContext, Resources.FailedToGetRoutingManagerDeploymentStatusRanOutOfTimeFormat, routingStatus.Value.ErrorMessage + string.Format(CommonResources.CorrelationIdErrorMessageFormat, _operationContext.CorrelationId));
}
}
// this.ReportProgress(EventLevel.Informational, Resources.Progress_ConnectionEstablished); this should be "remote agent deployed"
localAgentContainerName = await connectManagementClient.StartLocalAgentAsync(_localPorts, kubeConfigDetails, remoteAgentInfo, cancellationToken);
// TODO: report progress local agent started
var envVars = await connectManagementClient.GetLocalEnvironment(_localPorts, cancellationToken);
// This is the env file that should be used
if (!string.IsNullOrEmpty(_envJsonPath))
{
_fileSystem.Value.WriteAllTextToFile(_envJsonPath, JsonHelpers.SerializeObjectIndented(envVars));
}
while (!cancellationToken.IsCancellationRequested)
{
if (_waitProcesses.Any() && !_waitProcesses.Where(p => !p.HasExited).Any())
{
// all waitProcesses are terminated.
break;
}
cancellationToken.WaitHandle.WaitOne(1000);
}
return (ExitCode.Success, string.Empty);
}
catch (OperationCanceledException)
{
// Expected for StopConnect scenario. Message has been logged. Continue.
return (ExitCode.Success, string.Empty);
}
catch (Exception e) when (base._sdkErrorHandling.TryHandleKnownException(e, CliConstants.Dependency.ServiceRunPortForward, out string failureReason))
{
// Message has been logged. Continue.
return (ExitCode.Fail, failureReason);
}
catch (Exception ex)
{
if (!(ex is TaskCanceledException) && !(ex is OperationCanceledException))
{
_log.Error($"ServiceConnectCommand.ExecuteInnerContainerizedAsync caught exception {ex.ToString()}");
_out.Error(Resources.Error_ConnectOperationFailed);
}
throw;
}
finally
{
// We attempt to restore remote workload and stop all port forward connections regardless of success/failure of the operation.
// In case of a failure we attempt to restore as much as possible and some of the restore/stop workflows might be essentially no-op,
// example if remote agent connection fails, there is no local workload connection to close because the port forwarding connections
// have not been made and no local IPs have been allocated for remote services.
this.ReportProgress(EventLevel.LogAlways, Resources.Progress_StoppingWorkload);
await Task.WhenAll(connectManagementClient.RestoreOriginalRemoteContainerAsync(CancellationToken.None),
connectManagementClient.StopLocalAgentAsync(localAgentContainerName, CancellationToken.None));
_cleanupPerformed = true;
}
}