add a new patch action to modify image config and redirect action for better port redirect insight

This commit is contained in:
Yan Ka, Chiu
2023-07-06 01:23:39 +08:00
parent c3c1845bb2
commit 1d4dbad7d0
4 changed files with 162 additions and 30 deletions

View File

@@ -21,9 +21,11 @@
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
// SUCH DAMAGE.
use clap::Subcommand;
use clap::{Parser, Subcommand};
use oci_util::image_reference::ImageReference;
use std::os::unix::net::UnixStream;
use varutil::string_interpolation::Var;
use xc::models::{jail_image::JailConfig, EnvSpec};
use xcd::ipc::*;
#[derive(Subcommand, Debug)]
@@ -37,13 +39,60 @@ pub(crate) enum ImageAction {
Show {
image_id: String,
},
GetMeta {
GetConfig {
image_id: String,
},
ReplaceMeta {
SetConfig {
image_id: String,
meta_path: String,
},
#[clap(subcommand)]
Patch(PatchActions),
}
#[derive(Parser, Debug)]
pub(crate) enum PatchActions {
AddEnv {
#[clap(long, action)]
required: bool,
#[clap(short = 'd', long = "description")]
description: Option<String>,
env: String,
image_reference: ImageReference,
},
}
fn patch_image<F>(
conn: &mut UnixStream,
image_reference: &ImageReference,
f: F,
) -> Result<(), crate::ActionError>
where
F: FnOnce(&mut JailConfig),
{
let image_name = &image_reference.name;
let tag = &image_reference.tag;
let reqt = DescribeImageRequest {
image_name: image_name.to_string(),
tag: tag.to_string(),
};
let res = do_describe_image(conn, reqt)?;
match res {
Err(e) => {
eprintln!("{e:#?}");
}
Ok(res) => {
let mut config = res.jail_image.jail_config();
f(&mut config);
let req = SetConfigRequest {
name: image_name.to_string(),
tag: tag.to_string(),
config,
};
_ = do_replace_meta(conn, req)?;
}
}
Ok(())
}
pub(crate) fn use_image_action(
@@ -51,6 +100,25 @@ pub(crate) fn use_image_action(
action: ImageAction,
) -> Result<(), crate::ActionError> {
match action {
ImageAction::Patch(patch) => match patch {
PatchActions::AddEnv {
required,
description,
env,
image_reference,
} => {
patch_image(conn, &image_reference, |config| {
let env_var = Var::new(env).expect("invalid environment variable name");
config.envs.insert(
env_var,
EnvSpec {
description,
required,
},
);
})?;
}
},
ImageAction::Import {
image_id,
path,
@@ -99,7 +167,7 @@ pub(crate) fn use_image_action(
}
}
}
ImageAction::GetMeta { image_id } => {
ImageAction::GetConfig { image_id } => {
let (image_name, tag) = image_id.rsplit_once(':').expect("invalid image id");
let reqt = DescribeImageRequest {
image_name: image_name.to_string(),
@@ -116,13 +184,13 @@ pub(crate) fn use_image_action(
}
}
}
ImageAction::ReplaceMeta {
ImageAction::SetConfig {
image_id,
meta_path,
} => {
let (name, tag) = image_id.rsplit_once(':').expect("invalid image id");
let meta: xc::models::jail_image::JailConfig = if meta_path == *"-" {
let config: xc::models::jail_image::JailConfig = if meta_path == *"-" {
//let input = std::io::read_to_string(std::io::stdin())?;
serde_json::from_reader(std::io::stdin()).unwrap()
} else {
@@ -133,10 +201,10 @@ pub(crate) fn use_image_action(
serde_json::from_reader(meta_file).unwrap()
};
let req = ReplaceMetaRequest {
let req = SetConfigRequest {
name: name.to_string(),
tag: tag.to_string(),
meta,
config,
};
let manifest = do_replace_meta(conn, req)?;
// let manifest = request(conn, "replace_meta", req)?;

View File

@@ -27,12 +27,14 @@ mod error;
mod format;
mod image;
mod network;
mod redirect;
use crate::channel::{use_channel_action, ChannelAction};
use crate::error::ActionError;
use crate::format::{BindMount, EnvPair, IpWant, PublishSpec};
use crate::image::{use_image_action, ImageAction};
use crate::network::{use_network_action, NetworkAction};
use crate::redirect::{use_rdr_action, RdrAction};
use clap::Parser;
use freebsd::event::{eventfd, EventFdNotify};
@@ -42,7 +44,6 @@ use oci_util::digest::OciDigest;
use oci_util::image_reference::ImageReference;
use serde::{Deserialize, Serialize};
use std::cmp::Ordering;
use std::io::{stdin, Read};
use std::os::fd::{AsRawFd, IntoRawFd};
use std::os::unix::net::UnixStream;
use term_table::homogeneous::{TableLayout, TableSource, Title};
@@ -134,11 +135,8 @@ enum Action {
image_reference: ImageReference,
new_image_reference: ImageReference,
},
Rdr {
#[clap(long = "publish", short = 'p', multiple_occurrences = true)]
publish: Vec<PublishSpec>,
name: String,
},
#[clap(subcommand)]
Rdr(RdrAction),
Run {
#[clap(long, default_value_t, action)]
no_clean: bool,
@@ -246,8 +244,8 @@ fn main() -> Result<(), ActionError> {
eprintln!("{res:#?}");
}
Action::Kill { name } => {
let req = DestroyContainerRequest { name };
let res = do_destroy_container(&mut conn, req)?.unwrap();
let req = KillContainerRequest { name };
let res = do_kill_container(&mut conn, req)?.unwrap();
eprintln!("{res:#?}");
}
Action::Link { name } => {
@@ -284,7 +282,6 @@ fn main() -> Result<(), ActionError> {
}
let password = password.unwrap_or_else(|| {
let mut password = String::new();
print!("Enter password: \n");
rpassword::read_password().unwrap()
});
@@ -435,18 +432,8 @@ fn main() -> Result<(), ActionError> {
}
}
}
Action::Rdr { name, publish } => {
for expose in publish.iter() {
let redirection = expose.to_host_spec();
let request = DoRdr {
name: name.clone(),
redirection,
};
if let Ok(response) = do_rdr_container(&mut conn, request)? {
eprintln!("{response:#?}");
}
}
Action::Rdr(rdr) => {
_ = use_rdr_action(&mut conn, rdr);
}
Action::Run {
image_reference,

78
xc-bin/src/redirect.rs Normal file
View File

@@ -0,0 +1,78 @@
// Copyright (c) 2023 Yan Ka, Chiu.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions, and the following disclaimer,
// without modification, immediately at the beginning of the file.
// 2. The name of the author may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
// SUCH DAMAGE.
use clap::Parser;
use std::os::unix::net::UnixStream;
use xcd::ipc::*;
use crate::format::PublishSpec;
#[derive(Parser, Debug)]
pub(crate) enum RdrAction {
Add {
#[clap(long = "publish", short = 'p', multiple_occurrences = true)]
publish: Vec<PublishSpec>,
name: String,
},
List {
name: String,
#[clap(short = 'H', action)]
without_header: bool,
},
}
pub(crate) fn use_rdr_action(
conn: &mut UnixStream,
action: RdrAction,
) -> Result<(), crate::ActionError> {
match action {
RdrAction::Add { name, publish } => {
for expose in publish.iter() {
let redirection = expose.to_host_spec();
let request = DoRdr {
name: name.clone(),
redirection,
};
if let Ok(response) = do_rdr_container(conn, request)? {
eprintln!("{response:#?}");
}
}
}
RdrAction::List {
name,
without_header,
} => {
let response = do_list_site_rdr(conn, ContainerRdrList { name })?;
if let Ok(response) = response {
if !without_header {
let count = response.len();
println!("{count} redirection(s)");
}
for rdr in response.iter() {
println!("{}", rdr.to_pf_rule());
}
}
}
}
Ok(())
}

View File

@@ -31,7 +31,6 @@ use freebsd::fs::zfs::ZfsHandle;
use oci_util::digest::OciDigest;
use oci_util::distribution::client::*;
use oci_util::image_reference::ImageReference;
use oci_util::image_reference::ImageTag;
use oci_util::layer::ChainId;
use oci_util::models::ImageManifest;
use serde::{Deserialize, Serialize};