key: Make the key source better typed
This commit is contained in:
parent
62753ea138
commit
ce9f639a53
3 changed files with 46 additions and 22 deletions
|
@ -107,7 +107,7 @@ impl Local {
|
||||||
async fn upload_key(&mut self, name: &str, key: &Key) -> NixResult<()> {
|
async fn upload_key(&mut self, name: &str, key: &Key) -> NixResult<()> {
|
||||||
self.progress_bar.log(&format!("Deploying key {}", name));
|
self.progress_bar.log(&format!("Deploying key {}", name));
|
||||||
|
|
||||||
let dest_path = key.dest_dir.join(name);
|
let dest_path = key.dest_dir().join(name);
|
||||||
|
|
||||||
let temp = NamedTempFile::new()?;
|
let temp = NamedTempFile::new()?;
|
||||||
let (_, temp_path) = temp.keep().map_err(|pe| pe.error)?;
|
let (_, temp_path) = temp.keep().map_err(|pe| pe.error)?;
|
||||||
|
@ -120,7 +120,7 @@ impl Local {
|
||||||
{
|
{
|
||||||
let mut command = Command::new("chmod");
|
let mut command = Command::new("chmod");
|
||||||
command
|
command
|
||||||
.arg(&key.permissions)
|
.arg(&key.permissions())
|
||||||
.arg(&temp_path);
|
.arg(&temp_path);
|
||||||
|
|
||||||
let mut execution = CommandExecution::new(command);
|
let mut execution = CommandExecution::new(command);
|
||||||
|
@ -135,7 +135,7 @@ impl Local {
|
||||||
{
|
{
|
||||||
let mut command = Command::new("chown");
|
let mut command = Command::new("chown");
|
||||||
command
|
command
|
||||||
.arg(&format!("{}:{}", key.user, key.group))
|
.arg(&format!("{}:{}", key.user(), key.group()))
|
||||||
.arg(&temp_path);
|
.arg(&temp_path);
|
||||||
|
|
||||||
let mut execution = CommandExecution::new(command);
|
let mut execution = CommandExecution::new(command);
|
||||||
|
|
|
@ -197,13 +197,13 @@ impl Ssh {
|
||||||
async fn upload_key(&mut self, name: &str, key: &Key) -> NixResult<()> {
|
async fn upload_key(&mut self, name: &str, key: &Key) -> NixResult<()> {
|
||||||
self.progress_bar.log(&format!("Deploying key {}", name));
|
self.progress_bar.log(&format!("Deploying key {}", name));
|
||||||
|
|
||||||
let dest_path = key.dest_dir.join(name);
|
let dest_path = key.dest_dir().join(name);
|
||||||
|
|
||||||
let remote_command = DEPLOY_KEY_TEMPLATE.to_string()
|
let remote_command = DEPLOY_KEY_TEMPLATE.to_string()
|
||||||
.replace("%DESTINATION%", dest_path.to_str().unwrap())
|
.replace("%DESTINATION%", dest_path.to_str().unwrap())
|
||||||
.replace("%USER%", &key.user)
|
.replace("%USER%", &key.user())
|
||||||
.replace("%GROUP%", &key.group)
|
.replace("%GROUP%", &key.group())
|
||||||
.replace("%PERMISSIONS%", &key.permissions);
|
.replace("%PERMISSIONS%", &key.permissions());
|
||||||
|
|
||||||
let mut command = self.ssh(&["sh", "-c", &remote_command]);
|
let mut command = self.ssh(&["sh", "-c", &remote_command]);
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use std::{
|
use std::{
|
||||||
io::{self, Cursor},
|
io::{self, Cursor},
|
||||||
path::PathBuf,
|
path::{Path, PathBuf},
|
||||||
};
|
};
|
||||||
|
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
|
@ -8,31 +8,55 @@ use serde::{Deserialize, Serialize};
|
||||||
use tokio::{fs::File, io::AsyncRead};
|
use tokio::{fs::File, io::AsyncRead};
|
||||||
use validator::{Validate, ValidationError};
|
use validator::{Validate, ValidationError};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
enum KeySource {
|
||||||
|
#[serde(rename = "text")]
|
||||||
|
Text(String),
|
||||||
|
|
||||||
|
#[serde(rename = "keyCommand")]
|
||||||
|
Command(Vec<String>),
|
||||||
|
|
||||||
|
#[serde(rename = "keyFile")]
|
||||||
|
File(PathBuf),
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Validate, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Validate, Serialize, Deserialize)]
|
||||||
pub struct Key {
|
pub struct Key {
|
||||||
pub(crate) text: Option<String>,
|
#[serde(flatten)]
|
||||||
#[serde(rename = "keyFile")]
|
source: KeySource,
|
||||||
pub(crate) key_file: Option<String>,
|
|
||||||
#[validate(custom = "validate_dest_dir")]
|
#[validate(custom = "validate_dest_dir")]
|
||||||
#[serde(rename = "destDir")]
|
#[serde(rename = "destDir")]
|
||||||
pub(super) dest_dir: PathBuf,
|
dest_dir: PathBuf,
|
||||||
|
|
||||||
#[validate(custom = "validate_unix_name")]
|
#[validate(custom = "validate_unix_name")]
|
||||||
pub(super) user: String,
|
user: String,
|
||||||
|
|
||||||
#[validate(custom = "validate_unix_name")]
|
#[validate(custom = "validate_unix_name")]
|
||||||
pub(super) group: String,
|
group: String,
|
||||||
pub(super) permissions: String,
|
|
||||||
|
permissions: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Key {
|
impl Key {
|
||||||
pub(crate) async fn reader(&'_ self,) -> Result<Box<dyn AsyncRead + Send + Unpin + '_>, io::Error> {
|
pub async fn reader(&'_ self,) -> Result<Box<dyn AsyncRead + Send + Unpin + '_>, io::Error> {
|
||||||
if let Some(ref t) = self.text {
|
match &self.source {
|
||||||
Ok(Box::new(Cursor::new(t)))
|
KeySource::Text(content) => {
|
||||||
} else if let Some(ref p) = self.key_file {
|
Ok(Box::new(Cursor::new(content)))
|
||||||
Ok(Box::new(File::open(p).await?))
|
}
|
||||||
} else {
|
KeySource::Command(_command) => {
|
||||||
unreachable!("Neither `text` nor `keyFile` set. This should have been validated by Nix assertions.");
|
todo!("Implement keyCommand support")
|
||||||
|
}
|
||||||
|
KeySource::File(path) => {
|
||||||
|
Ok(Box::new(File::open(path).await?))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn dest_dir(&self) -> &Path { &self.dest_dir }
|
||||||
|
pub fn user(&self) -> &str { &self.user }
|
||||||
|
pub fn group(&self) -> &str { &self.user }
|
||||||
|
pub fn permissions(&self) -> &str { &self.permissions }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn validate_unix_name(name: &str) -> Result<(), ValidationError> {
|
fn validate_unix_name(name: &str) -> Result<(), ValidationError> {
|
||||||
|
|
Loading…
Add table
Reference in a new issue