Skip to content

Commit

Permalink
linkd: Accept profile id and rad home from args
Browse files Browse the repository at this point in the history
Signed-off-by: Alexander Simmerl <[email protected]>
  • Loading branch information
xla committed Sep 7, 2021
1 parent eb93de3 commit 765aa89
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 14 deletions.
33 changes: 24 additions & 9 deletions linkd/src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,22 @@
// This file is part of radicle-link, distributed under the GPLv3 with Radicle
// Linking Exception. For full terms see the included LICENSE file.

use std::{fmt::Display, path::PathBuf, str::FromStr};
use std::{fmt, path::PathBuf, str::FromStr};

use structopt::StructOpt;

use librad::profile::{ProfileId, RadHome};

#[derive(Debug, Default, Eq, PartialEq, StructOpt)]
pub struct Args {
#[structopt(long)]
pub profile_id: Option<ProfileId>,

/// Home of the profile data, if not provided is read from the environment
/// and falls back to project dirs.
#[structopt(long, default_value, parse(from_str = parse_rad_home))]
pub rad_home: RadHome,

/// Configures the type of signer used to get access to the storage.
#[structopt(long, default_value)]
pub signer: Signer,
Expand All @@ -21,16 +31,21 @@ pub struct Args {
required_if("key-source", "file")
)]
pub key_file_path: PathBuf,

/// Format of the key input data.
#[structopt(long, default_value, required_if("signer", "key"))]
pub key_format: KeyFormat,

/// Specifies from which source the secret should be read.
#[structopt(long, default_value, required_if("signer", "key"))]
pub key_source: KeySource,
}

fn parse_rad_home(src: &str) -> RadHome {
match src {
dirs if dirs == RadHome::ProjectDirs.to_string() => RadHome::ProjectDirs,
_ => RadHome::Root(PathBuf::from(src)),
}
}

#[derive(Debug, Eq, PartialEq, StructOpt)]
pub enum Signer {
/// Construct signer from a secret key.
Expand All @@ -45,8 +60,8 @@ impl Default for Signer {
}
}

impl Display for Signer {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
impl fmt::Display for Signer {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let ty = match self {
Self::Key => "key",
Self::SshAgent => "ssh-agent",
Expand Down Expand Up @@ -80,8 +95,8 @@ impl Default for KeyFormat {
}
}

impl Display for KeyFormat {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
impl fmt::Display for KeyFormat {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let source = match self {
Self::Base64 => "base64",
Self::Binary => "binary",
Expand Down Expand Up @@ -114,8 +129,8 @@ impl Default for KeySource {
}
}

impl Display for KeySource {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
impl fmt::Display for KeySource {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::fmt::Result {
let source = match self {
Self::File => "file",
Self::Stdin => "stdin",
Expand Down
22 changes: 19 additions & 3 deletions linkd/src/cfg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
// Linking Exception. For full terms see the included LICENSE file.

use std::{
io::{self},
convert::TryFrom,
io,
net::{Ipv4Addr, SocketAddr, SocketAddrV4},
time::Duration,
};
Expand All @@ -19,6 +20,7 @@ use tokio::{

use librad::{
crypto::{BoxedSigner, IntoSecretKeyError},
git::storage,
keystore::SecretKeyExt as _,
net,
net::peer::Config as PeerConfig,
Expand All @@ -28,7 +30,7 @@ use librad::{
};
use link_clib::keys;

use crate::args::{self};
use crate::args;

lazy_static::lazy_static! {
/// Localhost binding to any available port, i.e. `127.0.0.1:0`.
Expand All @@ -44,6 +46,9 @@ pub enum Error {
#[error(transparent)]
IO(#[from] io::Error),

#[error(transparent)]
Init(#[from] storage::error::Init),

#[error(transparent)]
Keys(#[from] keys::Error),

Expand All @@ -67,9 +72,12 @@ impl Cfg<BoxedSigner> {
where
S: ClientStream + Unpin + 'static,
{
let profile = Profile::from_root(std::path::Path::new("/tmp/linkd"), None)?;
let profile = Profile::try_from(&args)?;
let signer = construct_signer::<S>(args, &profile).await?;

// Ensure the storage is accessible for the created profile and signer.
storage::Storage::init(profile.paths(), signer.clone())?;

Ok(Self {
bootstrap: vec![],
peer: PeerConfig {
Expand All @@ -90,6 +98,14 @@ impl Cfg<BoxedSigner> {
}
}

impl TryFrom<&args::Args> for Profile {
type Error = Error;

fn try_from(args: &args::Args) -> Result<Self, Self::Error> {
Profile::from_home(&args.rad_home, args.profile_id.clone()).map_err(Error::from)
}
}

async fn construct_signer<S>(args: args::Args, profile: &Profile) -> Result<BoxedSigner, Error>
where
S: ClientStream + Unpin + 'static,
Expand Down
2 changes: 1 addition & 1 deletion test/examples/socket_activation_wrapper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use nix::{sys::socket, unistd::Pid};
use std::{fs::remove_file, os::unix::process::CommandExt as _, process::Command};

fn main() -> Result<()> {
remove_file("/tmp/test-linkd-socket-activation.sock")?;
remove_file("/tmp/test-linkd-socket-activation.sock").ok();

let sock = socket::socket(
socket::AddressFamily::Unix,
Expand Down
1 change: 0 additions & 1 deletion test/src/test/integration/linkd/socket_activation/unix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
use std::process::Command;

use anyhow::Result;
use assert_cmd;

#[test]
fn construct_listener_from_env() -> Result<()> {
Expand Down
51 changes: 51 additions & 0 deletions test/src/test/unit/linkd/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,67 @@ use std::path::PathBuf;
use anyhow::Result;
use structopt::StructOpt as _;

use librad::profile::{ProfileId, RadHome};

use linkd::args::{self, Args};

#[test]
fn defaults() -> Result<()> {
let iter = vec!["linkd"];
let parsed = Args::from_iter_safe(iter)?;

assert_matches!(
parsed,
Args {
rad_home: RadHome::ProjectDirs,
..
}
);
assert_eq!(
parsed,
Args {
..Default::default()
}
);

Ok(())
}

#[test]
fn profile_id() -> Result<()> {
let id = ProfileId::new();

#[rustfmt::skip]
let iter = vec![
"linkd",
"--profile-id", id.as_str()
];
let parsed = Args::from_iter_safe(iter)?;

assert_eq!(
parsed,
Args {
profile_id: Some(id),
..Default::default()
}
);

Ok(())
}

#[test]
fn rad_home() -> Result<()> {
#[rustfmt::skip]
let iter = vec![
"linkd",
"--rad-home", "/tmp/linkd",
];
let parsed = Args::from_iter_safe(iter)?;

assert_eq!(
parsed,
Args {
rad_home: RadHome::Root(PathBuf::from("/tmp/linkd")),
..Default::default()
}
);
Expand Down

0 comments on commit 765aa89

Please sign in to comment.