Skip to content

Commit

Permalink
Merge pull request #25 from OSInside/robust_create
Browse files Browse the repository at this point in the history
Force cleanup of resume type flakes
  • Loading branch information
schaefi authored Nov 6, 2023
2 parents 49476b4 + 6901125 commit cf7746b
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 52 deletions.
63 changes: 27 additions & 36 deletions common/src/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,16 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
use std::{fmt::{Display, Write}, process::{Command, Output, CommandArgs}, ffi::OsStr};
use std::fmt::{Display, Write};
use std::process::{Command, Output, CommandArgs};
use std::ffi::OsStr;
use thiserror::Error;

pub trait CommandExtTrait {
/// Execute this command and return:
/// Execute command via output() and return:
///
/// 1. An IO Error if the command could not be run
/// 2. An Execution Error if the Command was not successfull
/// 2. An ExecutionError if the Command was not successfull
/// 3. The [Output] of the Command if the command was executed successfully
///
/// Attaches all args to the resulting error
Expand All @@ -44,7 +46,9 @@ impl CommandExtTrait for Command {
}
}

pub fn handle_output(maybe_output: Result<Output, std::io::Error>, args: CommandArgs) -> Result<std::process::Output, CommandError> {
pub fn handle_output(
maybe_output: Result<Output, std::io::Error>, args: CommandArgs
) -> Result<std::process::Output, CommandError> {
let out = maybe_output.map_err(ProcessError::IO);

let error: ProcessError = match out {
Expand All @@ -57,21 +61,25 @@ pub fn handle_output(maybe_output: Result<Output, std::io::Error>, args: Command
}
Err(error) => error,
};

Err(CommandError {
base: error,
args: args
.flat_map(OsStr::to_str)
.map(ToOwned::to_owned)
.collect(),
})
// Provide caller arguments in addition to the error
Err(
CommandError {
base: error,
args: args
.flat_map(OsStr::to_str)
.map(ToOwned::to_owned)
.collect(),
}
)
}

#[derive(Debug, Error)]
pub enum ProcessError {
// The command could not be called
#[error(transparent)]
IO(#[from] std::io::Error),
// The Command terminated correctly but with unwanted results (e.g. wrong return code)

// The Command could be called but has a non zero exit status
#[error("The process failed with status {}", .0.status)]
ExecutionError(std::process::Output),
}
Expand All @@ -95,37 +103,20 @@ impl CommandError {
base,
}
}

pub fn with(&mut self, arg: String) -> &mut Self {
self.args.push(arg);
self
}
}

impl Display for CommandError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_char('"')?;
for arg in self.args.iter() {
f.write_str(arg)?;
f.write_char(' ')?;
}
f.write_char('"')?;
f.write_char(':')?;
f.write_char(' ')?;
f.write_str(format!("{:?}", self.base).as_str())?;
f.write_char(' ')?;
std::fmt::Display::fmt(&self.base, f)
}
}

impl From<std::process::Output> for CommandError {
fn from(value: std::process::Output) -> Self {
Self {
base: value.into(),
args: Default::default(),
}
}
}

impl From<ProcessError> for CommandError {
fn from(value: ProcessError) -> Self {
Self {
base: value,
args: Default::default(),
}
}
}
1 change: 1 addition & 0 deletions podman-pilot/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@ spinoff = { version = "0.7" }
lazy_static = { version = "1.4" }
serde = { version = "1.0", features = ["derive"]}
serde_yaml = { version = "0.9" }
regex = { version = "1.9" }
flakes = { version = "3.0.1", path = "../common" }
58 changes: 42 additions & 16 deletions podman-pilot/src/podman.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,25 +21,28 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
use crate::defaults;
use crate::config::{RuntimeSection, config};

use flakes::user::{User, chmod, mkdir};
use flakes::lookup::Lookup;
use flakes::io::IO;
use spinoff::{Spinner, spinners, Color};
use flakes::error::FlakeError;
use flakes::command::{CommandError, CommandExtTrait};
use flakes::config::get_podman_ids_dir;

use std::path::Path;
use std::process::{Command, Stdio};
use std::process::{Command, Output, Stdio};
use std::env;
use std::fs;
use crate::config::{RuntimeSection, config};
use flakes::error::FlakeError;
use flakes::command::{CommandError, CommandExtTrait};
use tempfile::tempfile;
use std::io::{Write, Read};
use std::fs::File;
use std::io::Seek;
use std::io::SeekFrom;
use flakes::config::get_podman_ids_dir;

use crate::defaults;
use spinoff::{Spinner, spinners, Color};
use tempfile::tempfile;
use regex::Regex;

pub fn create(
program_name: &String
Expand Down Expand Up @@ -143,9 +146,7 @@ pub fn create(
if Path::new(&container_cid_file).exists() && gc_cid_file(&container_cid_file, runas)? && (resume || attach) {
// resume or attach mode is active and container exists
// report ID value and its ID file name

let cid = fs::read_to_string(&container_cid_file)?;

return Ok((cid, container_cid_file));
}

Expand All @@ -165,7 +166,7 @@ pub fn create(
if !resume {
app.arg("--rm");
}
app.arg("-ti");
app.arg("--tty").arg("--interactive");
}

// setup container name to use
Expand Down Expand Up @@ -223,11 +224,32 @@ fn run_podman_creation(mut app: Command) -> Result<String, FlakeError> {
/*!
Create and provision container prior start
!*/
let output = app.perform()?;
let RuntimeSection { runas, resume, .. } = config().runtime();

let cid = String::from_utf8_lossy(&output.stdout).trim_end_matches('\n').to_owned();
let output: Output = match app.perform() {
Ok(output) => {
output
}
Err(error) => {
if resume {
// Cleanup potentially left over container instance from an
// inconsistent state, e.g powerfail
if Lookup::is_debug() {
debug!("Force cleanup container instance...");
}
let error_pattern = Regex::new(r"in use by (.*)\.").unwrap();
if let Some(captures) = error_pattern.captures(&format!("{:?}", error.base)) {
let cid = captures.get(1).unwrap().as_str();
call_instance("rm_force", cid, "none", runas)?;
}
app.perform()?
} else {
return Err(FlakeError::CommandError(error))
}
}
};

let runas = config().runtime().runas;
let cid = String::from_utf8_lossy(&output.stdout).trim_end_matches('\n').to_owned();

let is_delta_container = config().container.base_container.is_some();
let has_includes = !config().tars().is_empty() || !config().paths().is_empty();
Expand Down Expand Up @@ -357,11 +379,15 @@ pub fn call_instance(
let RuntimeSection { resume, .. } = config().runtime();

let mut call = user.run("podman");
if action == "create" || action == "rm" {
if action == "rm" || action == "rm_force" {
call.stderr(Stdio::null());
call.stdout(Stdio::null());
}
call.arg(action);
if action == "rm_force" {
call.arg("rm").arg("--force");
} else {
call.arg(action);
}
if action == "exec" {
call.arg("--interactive");
call.arg("--tty");
Expand Down

0 comments on commit cf7746b

Please sign in to comment.