Skip to content

Commit

Permalink
[#21] Remove implicit sudo call (#22)
Browse files Browse the repository at this point in the history
  • Loading branch information
MitchellBerend authored Oct 16, 2022
1 parent 2a46685 commit bc2c26b
Show file tree
Hide file tree
Showing 8 changed files with 204 additions and 75 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
## Added

[[#21](https://github.com/MitchellBerend/docker-manager/issues/21)] Remove implicit sudo call


## Added

v0.0.4
---

Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,9 @@ to support all docker commands on remote nodes.
| STOP | |
| LOGS | |
| EXEC | --tty is not implemented |


# Flags

`-s`/`--sudo` Enables sudo on the remote node. This might be needed depending on
how the remote node and it's user is set up.
4 changes: 4 additions & 0 deletions src/cli/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ use clap::{Parser, Subcommand};
#[derive(Parser)]
#[command(author, version, about)]
pub struct App {
/// Runs the command as sudo on the remote nodes
#[arg(short, long)]
pub sudo: bool,

/// This command will be ran on the remote nodes
#[command(subcommand)]
pub command: Command,
Expand Down
23 changes: 16 additions & 7 deletions src/client/connector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ impl Node {
Self { address }
}

pub async fn run_command(&self, command: Command) -> Result<String, NodeError> {
pub async fn run_command(&self, command: Command, sudo: bool) -> Result<String, NodeError> {
let session = match openssh::SessionBuilder::default()
.connect_timeout(std::time::Duration::new(1, 0))
.connect_mux(&self.address)
Expand Down Expand Up @@ -79,8 +79,15 @@ impl Node {
user,
workdir,
);
match command::run_exec(self.address.clone(), session, container_id, command, flags)
.await
match command::run_exec(
self.address.clone(),
session,
container_id,
sudo,
command,
flags,
)
.await
{
Ok(result) => Ok(result),
Err(e) => Err(NodeError::SessionError(self.address.clone(), e)),
Expand All @@ -96,7 +103,7 @@ impl Node {
} => {
let flags = ImagesFlags::new(all, digest, filter, format, no_trunc, quiet);

match command::run_images(self.address.clone(), session, flags).await {
match command::run_images(self.address.clone(), session, sudo, flags).await {
Ok(result) => Ok(result),
Err(e) => Err(NodeError::SessionError(self.address.clone(), e)),
}
Expand All @@ -112,7 +119,9 @@ impl Node {
} => {
let flags = LogsFlags::new(details, follow, since, tail, timestamps, until);

match command::run_logs(self.address.clone(), session, container_id, flags).await {
match command::run_logs(self.address.clone(), session, container_id, sudo, flags)
.await
{
//, follow).await {
Ok(result) => Ok(result),
Err(e) => Err(NodeError::SessionError(self.address.clone(), e)),
Expand All @@ -129,13 +138,13 @@ impl Node {
size,
} => {
let flags = PsFlags::new(all, filter, format, last, latests, no_trunc, quiet, size);
match command::run_ps(self.address.clone(), session, flags).await {
match command::run_ps(self.address.clone(), session, sudo, flags).await {
Ok(result) => Ok(result),
Err(e) => Err(NodeError::SessionError(self.address.clone(), e)),
}
}
Command::Stop { container_id } => {
match command::run_stop(self.address.clone(), session, container_id).await {
match command::run_stop(self.address.clone(), session, sudo, container_id).await {
Ok(result) => Ok(result),
Err(e) => Err(NodeError::SessionError(self.address.clone(), e)),
}
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ pub async fn run() {
}

_ => {
for word in utility::run_command(_cli.command).await {
for word in utility::run_command(_cli.command, _cli.sudo).await {
match word {
Ok(s) => println!("{}", s),
Err(e) => println!("{}", e),
Expand Down
110 changes: 98 additions & 12 deletions src/utility/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@ pub async fn run_exec(
hostname: String,
session: openssh::Session,
container_id: String,
sudo: bool,
command: Vec<String>,
//args: Option<Vec<String>>,
flags: ExecFlags,
) -> Result<String, openssh::Error> {
let mut _command: Vec<String> = vec!["docker".into(), "exec".into()];
let mut _command: Vec<String> = vec!["exec".into()];

for flag in &flags.flags() {
_command.push(flag.clone());
Expand All @@ -22,13 +23,35 @@ pub async fn run_exec(
if flags.interactive {
// This needs to be mutable so the stdout can be written to
#[allow(unused_mut)]
let mut _output = session.command("sudo").args(_command).spawn().await?;
let mut _output = match sudo {
true => {
session
.command("sudo")
.arg("docker")
.args(_command)
.spawn()
.await?
}
false => session.command("docker").args(_command).spawn().await?,
};

loop {
std::thread::sleep(std::time::Duration::new(1, 0));
}
} else {
let output = match session.command("sudo").args(_command).output().await {
let _output = match sudo {
true => {
session
.command("sudo")
.arg("docker")
.args(_command)
.output()
.await
}
false => session.command("docker").args(_command).output().await,
};

let output = match _output {
Ok(output) => output,
Err(e) => return Err(e),
};
Expand All @@ -45,18 +68,32 @@ pub async fn run_exec(
pub async fn run_images(
hostname: String,
session: openssh::Session,
sudo: bool,
flags: ImagesFlags,
) -> Result<String, openssh::Error> {
let mut command: Vec<String> = vec!["docker".into(), "images".into()];
let mut command: Vec<String> = vec!["images".into()];

for flag in flags.flags() {
command.push(flag)
}

let output = match session.command("sudo").args(command).output().await {
let _output = match sudo {
true => {
session
.command("sudo")
.arg("docker")
.args(command)
.output()
.await
}
false => session.command("docker").args(command).output().await,
};

let output = match _output {
Ok(output) => output,
Err(e) => return Err(e),
};

let mut rv: String = format!("{}\n", hostname);
match output.status.code().unwrap() {
0 => rv.push_str(std::str::from_utf8(&output.stdout).unwrap_or("")),
Expand All @@ -70,9 +107,10 @@ pub async fn run_logs(
hostname: String,
session: openssh::Session,
container_id: String,
sudo: bool,
flags: LogsFlags,
) -> Result<String, openssh::Error> {
let mut command: Vec<String> = vec!["docker".into(), "logs".into()];
let mut command: Vec<String> = vec!["logs".into()];

for item in flags.flags() {
command.push(item)
Expand All @@ -84,15 +122,36 @@ pub async fn run_logs(

// This needs to be mutable so the stdout can be written to
#[allow(unused_mut)]
let mut _output = session.command("sudo").args(command).spawn().await?;
let mut _output = match sudo {
true => {
session
.command("sudo")
.arg("docker")
.args(command)
.spawn()
.await?
}
false => session.command("docker").args(command).spawn().await?,
};

loop {
std::thread::sleep(std::time::Duration::new(1, 0));
}
} else {
command.push(container_id);
let _output = match sudo {
true => {
session
.command("sudo")
.arg("docker")
.args(command)
.output()
.await
}
false => session.command("docker").args(command).output().await,
};

let output = match session.command("sudo").args(command).output().await {
let output = match _output {
Ok(output) => output,
Err(e) => return Err(e),
};
Expand All @@ -111,18 +170,32 @@ pub async fn run_logs(
pub async fn run_ps(
hostname: String,
session: openssh::Session,
sudo: bool,
flags: PsFlags,
) -> Result<String, openssh::Error> {
let mut command: Vec<String> = vec!["docker".into(), "ps".into()];
let mut command: Vec<String> = vec!["ps".into()];

for flag in flags.flags() {
command.push(flag)
}

let output = match session.command("sudo").args(command).output().await {
let _output = match sudo {
true => {
session
.command("sudo")
.arg("docker")
.args(command)
.output()
.await
}
false => session.command("docker").args(command).output().await,
};

let output = match _output {
Ok(output) => output,
Err(e) => return Err(e),
};

let mut rv: String = format!("{}\n", hostname);
match output.status.code().unwrap() {
0 => rv.push_str(std::str::from_utf8(&output.stdout).unwrap_or("")),
Expand All @@ -135,11 +208,24 @@ pub async fn run_ps(
pub async fn run_stop(
hostname: String,
session: openssh::Session,
sudo: bool,
container_id: String,
) -> Result<String, openssh::Error> {
let command = vec!["docker", "stop", &container_id];
let command = vec!["stop", &container_id];

let _output = match sudo {
true => {
session
.command("sudo")
.arg("docker")
.args(command)
.output()
.await
}
false => session.command("docker").args(command).output().await,
};

let output = match session.command("sudo").args(command).output().await {
let output = match _output {
Ok(output) => output,
Err(e) => return Err(e),
};
Expand Down
29 changes: 18 additions & 11 deletions src/utility/other.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,27 @@ use futures::{stream, StreamExt};

/// This function takes a `Client` and returns a list of matched node names in the form of a tuple
/// with (hostname, container_id).
pub async fn find_container(client: Client, container_id: &str) -> Vec<(String, String)> {
pub async fn find_container(
client: Client,
container_id: &str,
sudo: bool,
) -> Vec<(String, String)> {
let bodies = stream::iter(client.nodes_info())
.map(|(hostname, node)| async move {
match node
.run_command(Command::Ps {
all: false,
filter: None,
format: None,
last: false,
latests: false,
no_trunc: false,
quiet: false,
size: false,
})
.run_command(
Command::Ps {
all: false,
filter: None,
format: None,
last: false,
latests: false,
no_trunc: false,
quiet: false,
size: false,
},
sudo,
)
.await
{
Ok(result) => (hostname.clone(), Ok(result)),
Expand Down
Loading

0 comments on commit bc2c26b

Please sign in to comment.