pub fn add_peer(
    peers: &[Peer],
    cidr_tree: &CidrTree,
    args: &AddPeerOpts,
) -> Result<Option<(PeerContents, KeyPair, String, File)>, Error> {
    let leaves = cidr_tree.leaves();

    let cidr = if let Some(ref parent_name) = args.cidr {
        leaves
            .iter()
            .find(|cidr| &cidr.name == parent_name)
            .ok_or_else(|| anyhow!("No eligible CIDR with that name exists."))?
    } else {
        choose_cidr(&leaves[..], "Eligible CIDRs for peer")?
    };

    let mut available_ip = None;
    let candidate_ips = cidr.iter().filter(|ip| cidr.is_assignable(*ip));
    for ip in candidate_ips {
        if !peers.iter().any(|peer| peer.ip == ip) {
            available_ip = Some(ip);
            break;
        }
    }

    let available_ip = available_ip.expect("No IPs in this CIDR are avavilable");

    let ip = if let Some(ip) = args.ip {
        ip
    } else if args.auto_ip {
        available_ip
    } else {
        input("IP", Prefill::Default(available_ip))?
    };

    let name = if let Some(ref name) = args.name {
        name.clone()
    } else {
        input("Name", Prefill::None)?
    };

    let is_admin = if let Some(is_admin) = args.admin {
        is_admin
    } else {
        confirm(&format!("Make {} an admin?", name))?
    };

    let invite_expires = if let Some(ref invite_expires) = args.invite_expires {
        invite_expires.clone()
    } else {
        input(
            "Invite expires after",
            Prefill::Default("14d".parse().map_err(|s: &str| anyhow!(s))?),
        )?
    };

    let invite_save_path = if let Some(ref location) = args.save_config {
        location.clone()
    } else {
        input(
            "Save peer invitation file to",
            Prefill::Default(format!("{}.toml", name)),
        )?
    };

    let default_keypair = KeyPair::generate();
    let peer_request = PeerContents {
        name,
        ip,
        cidr_id: cidr.id,
        public_key: default_keypair.public.to_base64(),
        endpoint: None,
        is_admin,
        is_disabled: false,
        is_redeemed: false,
        persistent_keepalive_interval: Some(PERSISTENT_KEEPALIVE_INTERVAL_SECS),
        invite_expires: Some(SystemTime::now() + invite_expires.into()),
        candidates: vec![],
    };

    Ok(
        if args.yes || confirm(&format!("Create peer {}?", peer_request.name.yellow()))? {
            let invite_file = OpenOptions::new()
                .read(true)
                .write(true)
                .create_new(true)
                .open(&invite_save_path)?;
            Some((peer_request, default_keypair, invite_save_path, invite_file))
        } else {
            None
        },
    )
}
/// Bring up a prompt to create a new peer. Returns the peer request.
Bring up a prompt to create a new peer. Returns the peer request.
Bring up a prompt to create a new peer . Returns the peer request .
pub fn add_peer(
    peers: &[Peer],
    cidr_tree: &CidrTree,
    args: &AddPeerOpts,
) -> Result<Option<(PeerContents, KeyPair, String, File)>, Error> {
    let leaves = cidr_tree.leaves();
    let cidr = if let Some(ref parent_name) = args.cidr {
        leaves
            .iter()
            .find(|cidr| &cidr.name == parent_name)
            .ok_or_else(|| anyhow!("No eligible CIDR with that name exists."))?
    } else {
        choose_cidr(&leaves[..], "Eligible CIDRs for peer")?
    };
    let mut available_ip = None;
    let candidate_ips = cidr.iter().filter(|ip| cidr.is_assignable(*ip));
    for ip in candidate_ips {
        if !peers.iter().any(|peer| peer.ip == ip) {
            available_ip = Some(ip);
            break;
        }
    }
    let available_ip = available_ip.expect("No IPs in this CIDR are avavilable");
    let ip = if let Some(ip) = args.ip {
        ip
    } else if args.auto_ip {
        available_ip
    } else {
        input("IP", Prefill::Default(available_ip))?
    };
    let name = if let Some(ref name) = args.name {
        name.clone()
    } else {
        input("Name", Prefill::None)?
    };
    let is_admin = if let Some(is_admin) = args.admin {
        is_admin
    } else {
        confirm(&format!("Make {} an admin?", name))?
    };
    let invite_expires = if let Some(ref invite_expires) = args.invite_expires {
        invite_expires.clone()
    } else {
        input(
            "Invite expires after",
            Prefill::Default("14d".parse().map_err(|s: &str| anyhow!(s))?),
        )?
    };
    let invite_save_path = if let Some(ref location) = args.save_config {
        location.clone()
    } else {
        input(
            "Save peer invitation file to",
            Prefill::Default(format!("{}.toml", name)),
        )?
    };
    let default_keypair = KeyPair::generate();
    let peer_request = PeerContents {
        name,
        ip,
        cidr_id: cidr.id,
        public_key: default_keypair.public.to_base64(),
        endpoint: None,
        is_admin,
        is_disabled: false,
        is_redeemed: false,
        persistent_keepalive_interval: Some(PERSISTENT_KEEPALIVE_INTERVAL_SECS),
        invite_expires: Some(SystemTime::now() + invite_expires.into()),
        candidates: vec![],
    };
    Ok(
        if args.yes || confirm(&format!("Create peer {}?", peer_request.name.yellow()))? {
            let invite_file = OpenOptions::new()
                .read(true)
                .write(true)
                .create_new(true)
                .open(&invite_save_path)?;
            Some((peer_request, default_keypair, invite_save_path, invite_file))
        } else {
            None
        },
    )
}
pub fn add_peer ( peers : & [ Peer ] , cidr_tree : & CidrTree , args : & AddPeerOpts , ) -> Result < Option < ( PeerContents , KeyPair , String , File ) > , Error > { let leaves = cidr_tree . leaves ( ) ; let cidr = if let Some ( ref parent_name ) = args . cidr { leaves . iter ( ) . find ( | cidr | & cidr . name == parent_name ) . ok_or_else ( | | anyhow ! ( " " ) ) ? } else { choose_cidr ( & leaves [ .. ] , " " ) ? } ; let mut available_ip = None ; let candidate_ips = cidr . iter ( ) . filter ( | ip | cidr . is_assignable ( * ip ) ) ; for ip in candidate_ips { if ! peers . iter ( ) . any ( | peer | peer . ip == ip ) { available_ip = Some ( ip ) ; break ; } } let available_ip = available_ip . expect ( " " ) ; let ip = if let Some ( ip ) = args . ip { ip } else if args . auto_ip { available_ip } else { input ( " " , Prefill :: Default ( available_ip ) ) ? } ; let name = if let Some ( ref name ) = args . name { name . clone ( ) } else { input ( " " , Prefill :: None ) ? } ; let is_admin = if let Some ( is_admin ) = args . admin { is_admin } else { confirm ( & format ! ( " " name ) ) ? } ; let invite_expires = if let Some ( ref invite_expires ) = args . invite_expires { invite_expires . clone ( ) } else { input ( " " , Prefill :: Default ( " " . parse ( ) . map_err ( | s : & str | anyhow ! ( s ) ) ? ) , ) ? } ; let invite_save_path = if let Some ( ref location ) = args . save_config { location . clone ( ) } else { input ( " " , Prefill :: Default ( format ! ( " " name ) ) , ) ? } ; let default_keypair = KeyPair :: generate ( ) ; let peer_request = PeerContents { name , ip , cidr_id : cidr . id , public_key : default_keypair . public . to_base64 ( ) , endpoint : None , is_admin , is_disabled : false , is_redeemed : false , persistent_keepalive_interval : Some ( PERSISTENT_KEEPALIVE_INTERVAL_SECS ) , invite_expires : Some ( SystemTime :: now ( ) + invite_expires . into ( ) ) , candidates : vec ! [ ] , } ; Ok ( if args . yes || confirm ( & format ! ( " " peer_request name yellow ( ) ) ) ? { let invite_file = OpenOptions :: new ( ) . read ( true ) . write ( true ) . create_new ( true ) . open ( & invite_save_path ) ? ; Some ( ( peer_request , default_keypair , invite_save_path , invite_file ) ) } else { None } , ) }
Bring up a prompt to create a new peer.
Bring up a prompt to create a new peer .
peers
&[Peer]
cidr_tree
&CidrTree
args
&AddPeerOpts