sn-testnet-deploy 0.7.0

Tool for creating Autonomi networks
Documentation
// Copyright (c) 2023, MaidSafe.
// All rights reserved.
//
// This SAFE Network Software is licensed under the BSD-3-Clause license.
// Please see the LICENSE file for more details.

use super::{get_custom_inventory, split_nat_aware_custom_inventory};
use crate::{DeploymentInventoryService, TestnetDeployBuilder};
use color_eyre::{eyre::eyre, Result};
use sn_testnet_deploy::{CloudProvider, NodeType, UpgradeOptions};
use std::time::Duration;

#[allow(clippy::too_many_arguments)]
pub async fn handle_upgrade_command(
    ansible_verbose: bool,
    branch: Option<String>,
    custom_inventory: Option<Vec<String>>,
    env_variables: Option<Vec<(String, String)>>,
    force: bool,
    forks: usize,
    interval: Duration,
    name: String,
    node_type: Option<NodeType>,
    provider: CloudProvider,
    pre_upgrade_delay: Option<u64>,
    repo_owner: Option<String>,
    version: Option<String>,
) -> Result<()> {
    // The upgrade intentionally uses a small value for `forks`, but this is far too slow
    // for retrieving the inventory from a large deployment. Therefore, we will use 50
    // forks for the initial run to retrieve the inventory, then recreate the deployer
    // using the smaller fork value.
    let testnet_deployer = TestnetDeployBuilder::default()
        .ansible_forks(50)
        .environment_name(&name)
        .provider(provider)
        .build()?;
    let inventory_service = DeploymentInventoryService::from(&testnet_deployer);
    let inventory = inventory_service
        .generate_or_retrieve_inventory(&name, true, None)
        .await?;
    if inventory.is_empty() {
        return Err(eyre!("The {name} environment does not exist"));
    }

    let testnet_deployer = TestnetDeployBuilder::default()
        .ansible_forks(forks)
        .ansible_verbose_mode(ansible_verbose)
        .environment_name(&name)
        .provider(provider)
        .build()?;

    if let Some(custom_inventory) = custom_inventory {
        let custom_vms = get_custom_inventory(&inventory, &custom_inventory)?;
        let inv_dir = testnet_deployer
            .working_directory_path
            .join("ansible")
            .join("inventory");
        let ssh_sk_path = &testnet_deployer.ssh_client.private_key_path;
        let split = split_nat_aware_custom_inventory(
            &inventory,
            &custom_vms,
            &name,
            &inv_dir,
            ssh_sk_path,
        )?;

        if !split.regular_vms.is_empty() {
            testnet_deployer.upgrade(UpgradeOptions {
                ansible_verbose,
                branch: branch.clone(),
                custom_inventory: Some(split.regular_vms),
                env_variables: env_variables.clone(),
                force,
                forks,
                interval,
                name: name.clone(),
                node_type: None,
                provider,
                pre_upgrade_delay,
                repo_owner: repo_owner.clone(),
                version: version.clone(),
            })?;
        }
        for nat_type in &split.nat_node_types {
            testnet_deployer.upgrade(UpgradeOptions {
                ansible_verbose,
                branch: branch.clone(),
                custom_inventory: None,
                env_variables: env_variables.clone(),
                force,
                forks,
                interval,
                name: name.clone(),
                node_type: Some(*nat_type),
                provider,
                pre_upgrade_delay,
                repo_owner: repo_owner.clone(),
                version: version.clone(),
            })?;
        }
    } else {
        testnet_deployer.upgrade(UpgradeOptions {
            ansible_verbose,
            branch,
            custom_inventory: None,
            env_variables,
            force,
            forks,
            interval,
            name: name.clone(),
            node_type,
            provider,
            pre_upgrade_delay,
            repo_owner,
            version,
        })?;
    }

    // Recreate the deployer with an increased number of forks for retrieving the status.
    let testnet_deployer = TestnetDeployBuilder::default()
        .ansible_forks(50)
        .environment_name(&name)
        .provider(provider)
        .build()?;
    testnet_deployer.status().await?;

    Ok(())
}

pub async fn handle_upgrade_antctl_command(
    custom_inventory: Option<Vec<String>>,
    name: String,
    node_type: Option<NodeType>,
    provider: CloudProvider,
    version: String,
) -> Result<()> {
    let testnet_deployer = TestnetDeployBuilder::default()
        .ansible_forks(50)
        .environment_name(&name)
        .provider(provider)
        .build()?;
    let inventory_service = DeploymentInventoryService::from(&testnet_deployer);
    let inventory = inventory_service
        .generate_or_retrieve_inventory(&name, true, None)
        .await?;
    if inventory.is_empty() {
        return Err(eyre!("The {name} environment does not exist"));
    }

    if let Some(custom_inventory) = custom_inventory {
        let custom_vms = get_custom_inventory(&inventory, &custom_inventory)?;
        let inv_dir = testnet_deployer
            .working_directory_path
            .join("ansible")
            .join("inventory");
        let ssh_sk_path = &testnet_deployer.ssh_client.private_key_path;
        let split = split_nat_aware_custom_inventory(
            &inventory,
            &custom_vms,
            &name,
            &inv_dir,
            ssh_sk_path,
        )?;

        let parsed_version: semver::Version = version.parse()?;
        if !split.regular_vms.is_empty() {
            testnet_deployer.upgrade_antctl(
                parsed_version.clone(),
                None,
                Some(split.regular_vms),
            )?;
        }
        for nat_type in &split.nat_node_types {
            testnet_deployer.upgrade_antctl(parsed_version.clone(), Some(*nat_type), None)?;
        }
    } else {
        testnet_deployer.upgrade_antctl(version.parse()?, node_type, None)?;
    }
    Ok(())
}