public async Task CreateStartNode()

in src/ccf/caci-ccf-provider/CAciNodeProvider.cs [41:174]


    public async Task<NodeEndpoint> CreateStartNode(
        string nodeName,
        string networkName,
        List<InitialMember> initialMembers,
        string? nodeLogLevel,
        SecurityPolicyConfiguration policyOption,
        NodeData nodeData,
        List<string> san,
        JsonObject? providerConfig)
    {
        this.ValidateCreateInput(providerConfig);

        string containerGroupName = nodeName;
        ContainerGroupData? cgData =
            await AciUtils.TryGetContainerGroupData(containerGroupName, providerConfig!);
        if (cgData != null)
        {
            this.logger.LogWarning($"Found existing {containerGroupName} instance." +
                $" Not re-creating start node.");
            return AciUtils.ToNodeEndpoint(cgData);
        }

        // Pack the start_config, members info and constitution files in a tar gz, base64 encode it
        // and set that as an environment variable on the ACI instance. Then have a bootstrap
        // script that unpacks the tar gz file and then launches the cchost instance.
        string configDataDir = WorkspaceDirectories.GetConfigurationDirectory(
            nodeName,
            networkName,
            this.InfraType);
        Directory.CreateDirectory(configDataDir);

        CCHostConfig cchostConfig = await CCHostConfig.InitConfig(
            "templates/snp/start-config.json",
            outDir: configDataDir);

        // Set networking configuration.
        string location = providerConfig!["location"]!.ToString();
        string dnsNameLabel = this.GenerateDnsName(nodeName, networkName, providerConfig);
        var fqdn = $"{dnsNameLabel}.{location}.azurecontainer.io";

        string instanceId = Guid.NewGuid().ToString();
        this.AddInfraProviderData(nodeData, instanceId);

        cchostConfig.SetPublishedAddress(fqdn);
        cchostConfig.SetNodeLogLevel(nodeLogLevel);
        await cchostConfig.SetNodeData(nodeData);
        var altNames = fqdn.NodeSanFormat();
        altNames.AddRange(san);
        cchostConfig.SetSubjectAltNames(altNames);

        await cchostConfig.SetStartConfiguration(initialMembers, "constitution");

        // Prepare node storage.
        var nodeStorageProvider = NodeStorageProviderFactory.Create(
            networkName,
            providerConfig,
            this.InfraType,
            this.logger);
        if (await nodeStorageProvider.NodeStorageDirectoryExists(nodeName))
        {
            // If no start node container exists but the storage folder from a previous run for
            // this start node exists then delete that or else cchost startup will fail saying
            // that ledger directory already exists.
            this.logger.LogWarning($"Removing {nodeName} node storage folder from a previous " +
                $"run before creating the start node container.");
            await nodeStorageProvider.DeleteNodeStorageDirectory(nodeName);
        }

        await nodeStorageProvider.CreateNodeStorageDirectory(nodeName);
        (var rwLedgerDir, var rwSnapshotsDir, var logsDir) =
            await nodeStorageProvider.GetReadWriteLedgerSnapshotsDir(nodeName);
        cchostConfig.SetLedgerSnapshotsDirectory(rwLedgerDir.MountPath, rwSnapshotsDir.MountPath);

        // Write out the config file.
        await cchostConfig.SaveConfig();

        // Add any configuration files that the node storage provider needs during container start.
        await nodeStorageProvider.AddNodeStorageProviderConfiguration(
            configDataDir,
            rwLedgerDir,
            rwSnapshotsDir,
            roLedgerDirs: null,
            roSnapshotsDir: null);

        // Pack the contents of the directory into base64 encoded tar gzip string which then
        // gets uncompressed and expanded in the container.
        string tgzConfigData = await Utils.PackDirectory(configDataDir);

        var securityPolicy =
            await this.GetContainerGroupSecurityPolicy(policyOption);

        ContainerGroupData inputData = this.CreateContainerGroupData(
            location,
            networkName,
            nodeName,
            dnsNameLabel,
            tgzConfigData,
            instanceId,
            securityPolicy);

        await nodeStorageProvider.UpdateCreateContainerGroupParams(
            rwLedgerDir,
            rwSnapshotsDir,
            roLedgerDirs: null,
            roSnapshotsDir: null,
            inputData);

        if (providerConfig.StartNodeSleep())
        {
            inputData.Containers.Single(
                c => c.Name == AciConstants.ContainerName.CcHost).EnvironmentVariables.Add(
                new ContainerEnvironmentVariable("TAIL_DEV_NULL")
                {
                    Value = "true"
                });
        }

        if (logsDir != null)
        {
            inputData.Containers.Single(
                c => c.Name == AciConstants.ContainerName.CcHost).EnvironmentVariables.Add(
                new ContainerEnvironmentVariable("LOGS_DIR")
                {
                    Value = logsDir.MountPath
                });
        }

        ContainerGroupData resourceData = await this.CreateContainerGroup(
            containerGroupName,
            inputData,
            providerConfig);

        return AciUtils.ToNodeEndpoint(resourceData);
    }