clippy bits

This commit is contained in:
Yan Ka, Chiu
2023-07-09 13:23:32 -04:00
parent 39a856b24b
commit 369ad8c87d
13 changed files with 213 additions and 87 deletions

View File

@@ -486,7 +486,7 @@ mod tests {
chdir: Some(dir.to_string()),
file: "test-materials/base.tar.zst".to_string(),
compression: CompressionType::Auto,
print_input_digest: false
print_input_digest: false,
};
do_extract(extract_arg).unwrap();
});
@@ -500,7 +500,7 @@ mod tests {
chdir: Some(dir.to_string()),
file: "test-materials/base.tar".to_string(),
compression: CompressionType::Auto,
print_input_digest: false
print_input_digest: false,
};
do_extract(extract_arg).unwrap();
});

View File

@@ -22,8 +22,8 @@
// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
// SUCH DAMAGE.
use crate::jailfile::JailContext;
use crate::jailfile::parse::Action;
use crate::jailfile::JailContext;
use anyhow::{bail, Result};
use oci_util::image_reference::ImageReference;
@@ -31,7 +31,7 @@ use xc::util::gen_id;
pub(crate) struct FromDirective {
image_reference: ImageReference,
alias: Option<String>
alias: Option<String>,
}
impl FromDirective {
@@ -44,9 +44,15 @@ impl FromDirective {
if action.args.len() > 1 {
let Some("as") = action.args.get(1).map(|s| s.as_str()) else { bail!("unexpected ariable") };
let alias = action.args.get(2).expect("expected alias");
Ok(FromDirective { image_reference, alias: Some(alias.to_string()) })
Ok(FromDirective {
image_reference,
alias: Some(alias.to_string()),
})
} else {
Ok(FromDirective { image_reference, alias: None })
Ok(FromDirective {
image_reference,
alias: None,
})
}
}
@@ -60,14 +66,11 @@ impl FromDirective {
let name = format!("build-{}", gen_id());
/* create container */
if let Some(alias) = &self.alias {
context.containers.insert(alias.to_string(), name.to_string());
context
.containers
.insert(alias.to_string(), name.to_string());
}
context.container_id = Some(name);
Ok(())
}
}

View File

@@ -0,0 +1 @@

View File

@@ -33,5 +33,5 @@ pub(crate) struct JailContext {
/// Mapping to different containers for multi-stage build
pub(crate) containers: HashMap<String, String>,
conn: UnixStream
conn: UnixStream,
}

View File

@@ -103,38 +103,57 @@ mod tests {
"#;
let parsed = super::parse_jailfile(input).expect("cannot parse input");
assert_eq!(parsed[0], Action {
directive_name: "FROM".to_string(),
directive_args: HashMap::new(),
args: vec!["node:18-alpine".to_string()],
heredoc: None
});
assert_eq!(parsed[1], Action {
directive_name: "WORKDIR".to_string(),
directive_args: HashMap::new(),
args: vec!["/app".to_string()],
heredoc: None
});
assert_eq!(parsed[2], Action {
directive_name: "COPY".to_string(),
directive_args: HashMap::new(),
args: vec![".".to_string(), ".".to_string()],
heredoc: None
});
assert_eq!(parsed[3], Action {
directive_name: "RUN".to_string(),
directive_args: HashMap::new(),
args: vec!["yarn".to_string(), "install".to_string(), "--production".to_string()],
heredoc: None
});
assert_eq!(parsed[4], Action {
directive_name: "RUN".to_string(),
directive_args: HashMap::new(),
args: Vec::new(),
heredoc: Some("\n This is some\n funny string\n ".to_string())
});
assert_eq!(
parsed[0],
Action {
directive_name: "FROM".to_string(),
directive_args: HashMap::new(),
args: vec!["node:18-alpine".to_string()],
heredoc: None
}
);
assert_eq!(
parsed[1],
Action {
directive_name: "WORKDIR".to_string(),
directive_args: HashMap::new(),
args: vec!["/app".to_string()],
heredoc: None
}
);
assert_eq!(
parsed[2],
Action {
directive_name: "COPY".to_string(),
directive_args: HashMap::new(),
args: vec![".".to_string(), ".".to_string()],
heredoc: None
}
);
assert_eq!(
parsed[3],
Action {
directive_name: "RUN".to_string(),
directive_args: HashMap::new(),
args: vec![
"yarn".to_string(),
"install".to_string(),
"--production".to_string()
],
heredoc: None
}
);
assert_eq!(
parsed[4],
Action {
directive_name: "RUN".to_string(),
directive_args: HashMap::new(),
args: Vec::new(),
heredoc: Some("\n This is some\n funny string\n ".to_string())
}
);
/*
/*
eprintln!("{parsed:?}");
assert!(false);
*/

View File

@@ -143,6 +143,8 @@ enum Action {
no_clean: bool,
#[clap(long, default_value_t, action)]
persist: bool,
#[clap(long="create-only", action)]
create_only: bool,
image_reference: ImageReference,
entry_point: Option<String>,
entry_point_args: Vec<String>,
@@ -192,8 +194,8 @@ enum Action {
Exec {
name: String,
arg0: String,
args: Vec<String>
}
args: Vec<String>,
},
}
fn main() -> Result<(), ActionError> {
@@ -289,7 +291,7 @@ fn main() -> Result<(), ActionError> {
}
let password = password.unwrap_or_else(|| {
print!("Enter password: \n");
println!("Enter password: ");
rpassword::read_password().unwrap()
});
@@ -444,6 +446,7 @@ fn main() -> Result<(), ActionError> {
}
Action::Run {
image_reference,
create_only,
detach,
entry_point,
entry_point_args,
@@ -528,7 +531,7 @@ fn main() -> Result<(), ActionError> {
Maybe::Some(Fd(fd))
};
let reqt = InstantiateRequest {
let mut reqt = InstantiateRequest {
alt_root: None,
name,
hostname,
@@ -550,6 +553,12 @@ fn main() -> Result<(), ActionError> {
main_started_notify: main_started_notify.clone(),
};
if create_only {
reqt.main_norun = true;
reqt.init_norun = true;
reqt.deinit_norun = true;
}
let res = do_instantiate(&mut conn, reqt)?;
(res, main_started_notify)
};
@@ -615,7 +624,7 @@ fn main() -> Result<(), ActionError> {
} else {
eprintln!("no such container");
}
},
}
Action::Exec { name, arg0, args } => {
let n = EventFdNotify::new();
let request = ExecCommandRequest {
@@ -627,7 +636,7 @@ fn main() -> Result<(), ActionError> {
stdout: Maybe::Some(ipc::packet::codec::Fd(1)),
stderr: Maybe::Some(ipc::packet::codec::Fd(2)),
uid: 0,
notify: Maybe::Some(ipc::packet::codec::Fd(n.as_raw_fd()))
notify: Maybe::Some(ipc::packet::codec::Fd(n.as_raw_fd())),
};
if let Ok(response) = do_exec(&mut conn, request)? {
n.notified_sync();

View File

@@ -104,9 +104,8 @@ pub(super) fn spawn_process_forward(
cmd: &mut std::process::Command,
stdin: Option<RawFd>,
stdout: Option<RawFd>,
stderr: Option<RawFd>
) -> Result<u32, ExecError>
{
stderr: Option<RawFd>,
) -> Result<u32, ExecError> {
unsafe {
cmd.pre_exec(move || {
if let Some(fd) = stdin {

View File

@@ -32,7 +32,9 @@ use crate::util::exists_exec;
use anyhow::Context;
use freebsd::event::{EventFdNotify, KEventExt};
use ipc::packet::codec::json::JsonPacket;
use ipc::packet::Packet;
use ipc::proto::Request;
use jail::process::Jailed;
use nix::libc::intptr_t;
use nix::sys::event::{kevent_ts, EventFilter, EventFlag, FilterFlag, KEvent};
@@ -88,6 +90,26 @@ impl ReadingPacket {
}
}
enum Readiness<T> {
Pending,
Ready(T),
}
impl<T> Readiness<T> {
fn map_can_fail<F, A, E>(self, transform: F) -> Result<Readiness<A>, E>
where
F: FnOnce(T) -> Result<A, E>,
{
match self {
Readiness::Pending => Ok(Readiness::Pending),
Readiness::Ready(value) => {
let x = transform(value)?;
Ok(Readiness::Ready(x))
}
}
}
}
// XXX: naively pretend writes always successful
#[derive(Debug)]
pub struct ControlStream {
@@ -103,7 +125,26 @@ impl ControlStream {
}
}
fn pour_in_bytes(&mut self, known_avail: usize) -> Result<Option<Packet>, anyhow::Error> {
fn try_get_request(
&mut self,
known_avail: usize,
) -> Result<Readiness<(String, JsonPacket)>, anyhow::Error> {
self.pour_in_bytes(known_avail)
.and_then(|readiness| match readiness {
Readiness::Pending => Ok(Readiness::Pending),
Readiness::Ready(packet) => {
let request: ipc::packet::TypedPacket<Request> =
packet.map_failable(|vec| serde_json::from_slice(vec))?;
let method = request.data.method.to_string();
let packet = request.map(|req| req.value.clone());
Ok(Readiness::Ready((method, packet)))
}
})
}
fn pour_in_bytes(&mut self, known_avail: usize) -> Result<Readiness<Packet>, anyhow::Error> {
if let Some(reading_packet) = &mut self.processing {
if reading_packet.ready() {
panic!("the client is sending more bytes than expected");
@@ -115,13 +156,13 @@ impl ControlStream {
}
let Some(processing) = self.processing.take() else { panic!() };
if processing.ready() {
Ok(Some(Packet {
Ok(Readiness::Ready(Packet {
data: processing.buffer,
fds: processing.fds,
}))
} else {
self.processing = Some(processing);
Ok(None)
Ok(Readiness::Pending)
}
}
}
@@ -351,10 +392,11 @@ impl ProcessRunner {
let err_path = format!("/var/log/xc.{}.{}.err.log", self.container.id, id);
spawn_process_files(&mut cmd, &Some(out_path), &Some(err_path))?
}
StdioMode::Forward { stdin, stdout, stderr } => {
spawn_process_forward(
&mut cmd, *stdin, *stdout, *stderr)?
}
StdioMode::Forward {
stdin,
stdout,
stderr,
} => spawn_process_forward(&mut cmd, *stdin, *stdout, *stderr)?,
};
tx.send_if_modified(|status| {
@@ -421,6 +463,16 @@ impl ProcessRunner {
}
}
fn handle_control_stream_cmd(&mut self, method: String, request: JsonPacket) {
if method == "exec" {
let jexec: Jexec = serde_json::from_value(request.data).unwrap();
let notify = Arc::new(EventFdNotify::from_fd(jexec.notify.unwrap()));
let _result = self.spawn_process(&crate::util::gen_id(), &jexec, Some(notify));
} else if method == "run_main" {
self.should_run_main = true;
}
}
fn handle_pid_event(
&mut self,
event: KEvent,
@@ -474,7 +526,9 @@ impl ProcessRunner {
if descentdant_gone {
stat.set_tree_exited();
if stat.id() == "main" {
if self.container.deinit_norun || deinits.is_empty() {
if (self.container.deinit_norun || deinits.is_empty())
&& !self.container.persist
{
return true;
} else {
debug!("activating deinit queue");
@@ -566,16 +620,13 @@ impl ProcessRunner {
} else if let Some(control_stream) =
self.control_streams.get_mut(&(event.ident() as i32))
{
match control_stream.pour_in_bytes(event.data() as usize) {
match control_stream.try_get_request(event.data() as usize) {
Err(_) => {
self.control_streams.remove(&(event.ident() as i32));
}
Ok(None) => {
}
Ok(Some(packet)) => {
let jexec: Jexec = serde_json::from_slice(&packet.data).unwrap();
let notify = Arc::new(EventFdNotify::from_fd(jexec.notify.unwrap()));
let _result = self.spawn_process(&crate::util::gen_id(), &jexec, Some(notify));
Ok(Readiness::Pending) => {}
Ok(Readiness::Ready((method, request))) => {
self.handle_control_stream_cmd(method, request);
}
}
}
@@ -630,7 +681,7 @@ impl ProcessRunner {
}
pub fn run(
container: RunningContainer,
container: RunningContainer,
control_stream: UnixStream,
) -> (i32, Receiver<ContainerManifest>) {
let kq = nix::sys::event::kqueue().unwrap();

View File

@@ -42,8 +42,8 @@ pub enum StdioMode {
Forward {
stdin: Option<RawFd>,
stdout: Option<RawFd>,
stderr: Option<RawFd>
}
stderr: Option<RawFd>,
},
}
/// Executable parameters to be executed in container
@@ -54,7 +54,7 @@ pub struct Jexec {
pub envs: std::collections::HashMap<String, String>,
pub uid: u32,
pub output_mode: StdioMode,
pub notify: Option<RawFd>
pub notify: Option<RawFd>,
}
pub struct ResolvedExec {
@@ -75,7 +75,7 @@ impl ResolvedExec {
stdout: None,
stderr: None,
},
notify: None
notify: None,
}
}
}

View File

@@ -146,7 +146,7 @@ impl InstantiateBlueprint {
envs,
uid: 0,
output_mode: StdioMode::Terminal,
notify: None
notify: None,
}
};
for assign in request.ips.iter() {

View File

@@ -469,8 +469,9 @@ impl ServerContext {
rename_reference: Option<ImageReference>,
) -> anyhow::Result<()> {
// XXX: handle pull image error
let result = crate::image::pull::pull_image(self.image_manager.clone(), reference, rename_reference)
.await;
let result =
crate::image::pull::pull_image(self.image_manager.clone(), reference, rename_reference)
.await;
if result.is_err() {
error!("result: {result:#?}");
}

View File

@@ -34,7 +34,6 @@ use oci_util::digest::OciDigest;
use oci_util::distribution::client::{BasicAuth, Registry};
use oci_util::image_reference::ImageReference;
use serde::{Deserialize, Serialize};
use xc::models::exec::{Jexec, StdioMode};
use std::collections::HashMap;
use std::io::Seek;
use std::net::IpAddr;
@@ -45,6 +44,7 @@ use tokio::sync::RwLock;
use tracing::*;
use varutil::string_interpolation::InterpolatedString;
use xc::container::request::{MountReq, NetworkAllocRequest};
use xc::models::exec::{Jexec, StdioMode};
use xc::models::jail_image::JailConfig;
use xc::models::network::{DnsSetting, IpAssign, PortRedirection};
use xc::res::network::Network;
@@ -820,21 +820,20 @@ pub struct ExecCommandRequest {
pub stdout: Maybe<Fd>,
pub stderr: Maybe<Fd>,
pub uid: u32,
pub notify: Maybe<Fd>
pub notify: Maybe<Fd>,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct ExecCommandResponse {
pub cid: String
pub cid: String,
}
#[ipc_method(method = "exec")]
async fn exec(
context: Arc<RwLock<ServerContext>>,
local_context: &mut ConnectionContext<Variables>,
request: ExecCommandRequest
) -> GenericResult<ExecCommandResponse>
{
request: ExecCommandRequest,
) -> GenericResult<ExecCommandResponse> {
info!("exec!!!");
let cid = gen_id();
let jexec = Jexec {
@@ -845,9 +844,9 @@ async fn exec(
output_mode: StdioMode::Forward {
stdin: request.stdin.to_option().map(|fd| fd.0),
stdout: request.stdout.to_option().map(|fd| fd.0),
stderr: request.stderr.to_option().map(|fd| fd.0)
stderr: request.stderr.to_option().map(|fd| fd.0),
},
notify: request.notify.to_option().map(|fd| fd.0)
notify: request.notify.to_option().map(|fd| fd.0),
};
if let Some(arc_site) = context.write().await.get_site(&request.name) {
let mut site = arc_site.write().await;
@@ -858,6 +857,28 @@ async fn exec(
}
}
#[derive(Serialize, Deserialize, Debug)]
pub struct RunMainRequest {
pub name: String
}
/// XXX: Temporary
#[ipc_method(method = "run_main")]
async fn run_main(
context: Arc<RwLock<ServerContext>>,
local_context: &mut ConnectionContext<Variables>,
request: RunMainRequest,
) -> GenericResult<()>
{
if let Some(arc_site) = context.write().await.get_site(&request.name) {
let mut site = arc_site.write().await;
site.run_main();
Ok(())
}else {
enoent("container not found")
}
}
#[derive(Serialize, Deserialize, Debug)]
pub struct PushImageRequest {
pub image_reference: ImageReference,

View File

@@ -26,8 +26,8 @@ use anyhow::{anyhow, bail, Context};
use freebsd::event::{EventFdNotify, Notify};
use freebsd::fs::zfs::ZfsHandle;
use ipc::packet::Packet;
use ipc::proto::Request;
use ipc::transport::PacketTransport;
use xc::models::exec::Jexec;
use std::ffi::OsString;
use std::os::fd::RawFd;
use std::os::unix::net::UnixStream;
@@ -37,6 +37,7 @@ use tracing::info;
use xc::config::XcConfig;
use xc::container::effect::UndoStack;
use xc::container::{Container, ContainerManifest};
use xc::models::exec::Jexec;
use xc::models::jail_image::JailImage;
pub enum SiteState {
@@ -113,8 +114,29 @@ impl Site {
}
pub fn exec(&mut self, jexec: Jexec) {
let encoded = serde_json::to_vec(&jexec).unwrap();
let packet = Packet { data: encoded, fds: Vec::new() };
let value = serde_json::to_value(jexec).unwrap();
let request = Request { method: "exec".to_string(), value };
let encoded = serde_json::to_vec(&request).unwrap();
let packet = Packet {
data: encoded,
fds: Vec::new(),
};
if let Some(stream) = self.control_stream.as_mut() {
let _result = stream.send_packet(&packet);
}
}
/// XXX: CHANGE ME
pub fn run_main(&mut self) {
let request = Request {
method: "run_main".to_string(),
value: serde_json::json!({})
};
let encoded = serde_json::to_vec(&request).unwrap();
let packet = Packet {
data: encoded,
fds: Vec::new(),
};
if let Some(stream) = self.control_stream.as_mut() {
let _result = stream.send_packet(&packet);
}