private async Task CreateAndStartRecoveryAgentContainer()

in src/ccf/virtual-ccf-provider/docker/DockerNodeProvider.cs [882:987]


    private async Task<RecoveryAgentEndpoint> CreateAndStartRecoveryAgentContainer(
        string networkName,
        NodeEndpoint nodeEndpoint)
    {
        var containerName = "recovery-agent-nw-" + nodeEndpoint.NodeName;
        var envoyEndpoint = await this.CreateAndStartEnvoyProxyContainer(
            networkName,
            containerName,
            nodeEndpoint);

        var imageParams = new ImagesCreateParameters
        {
            FromImage = ImageUtils.CcfRecoveryAgentImage(),
            Tag = ImageUtils.CcfRecoveryAgentTag(),
        };
        await this.client.Images.CreateImageAsync(
            imageParams,
            authConfig: null,
            new Progress<JSONMessage>(m => this.logger.LogInformation(m.ToProgressMessage())));

        string hostServiceCertDir =
            DockerClientEx.GetHostServiceCertDirectory("ra", nodeEndpoint.NodeName);

        string hostInsecureVirtualDir =
            DockerClientEx.GetHostInsecureVirtualDirectory("ra", nodeEndpoint.NodeName);
        string insecureVirtualDir =
            DockerClientEx.GetInsecureVirtualDirectory("ra", nodeEndpoint.NodeName);
        Directory.CreateDirectory(insecureVirtualDir);

        // Copy out the test keys/report into the host directory so that it can be mounted into
        // the container.
        WorkspaceDirectories.CopyDirectory(
            Directory.GetCurrentDirectory() + "/insecure-virtual/recovery-agent",
            insecureVirtualDir,
            recursive: true);

        var createContainerParams = new CreateContainerParameters
        {
            Labels = new Dictionary<string, string>
            {
                {
                    DockerConstants.CcfNetworkNameTag,
                    networkName
                },
                {
                    DockerConstants.CcfNetworkTypeTag,
                    "recovery-agent"
                },
                {
                    DockerConstants.CcfNetworkResourceNameTag,
                    nodeEndpoint.NodeName
                }
            },
            Name = containerName,
            Image = $"{imageParams.FromImage}:{imageParams.Tag}",
            Env =
            [
                $"CCF_ENDPOINT={nodeEndpoint.ClientRpcAddress}",
                $"CCF_ENDPOINT_SKIP_TLS_VERIFY=true",
                $"ASPNETCORE_URLS=http://+:{Ports.RecoveryAgentPort}",
                $"SERVICE_CERT_LOCATION={DockerConstants.ServiceCertPemFilePath}",
                $"INSECURE_VIRTUAL_ENVIRONMENT=true"
            ],
            ExposedPorts = new Dictionary<string, EmptyStruct>
            {
                {
                    $"{Ports.RecoveryAgentPort}/tcp", new EmptyStruct()
                }
            },
            HostConfig = new HostConfig
            {
                NetworkMode = networkName,
                Devices = new List<DeviceMapping>(), // Allocate these as might be modified later.
                CapAdd = new List<string>(),
                Binds = new List<string>
                {
                    $"{hostServiceCertDir}:{DockerConstants.ServiceFolderMountPath}:ro",
                    $"{hostInsecureVirtualDir}:/app/insecure-virtual:ro"
                },

                // Although traffic will be routed via envoy exposing the HTTP port for easier
                // debugging.
                PortBindings = new Dictionary<string, IList<PortBinding>>
                {
                    {
                        $"{Ports.RecoveryAgentPort}/tcp", new List<PortBinding>
                        {
                            new()
                            {
                                    // Dynamic assignment.
                                HostPort = null
                            }
                        }
                    }
                }
            }
        };

        this.logger.LogInformation($"Creating container: {createContainerParams.Name}");
        var container = await this.client.CreateOrGetContainer(createContainerParams);
        await this.client.Containers.StartContainerAsync(
            container.ID,
            new ContainerStartParameters());

        return envoyEndpoint.ToRecoveryAgentEndpoint();
    }