tools/unitctl: unitctl export
* new subcommand for "export" in CLI * new cmd submodule for exporting config tarballs * logic to also output to stdout * README additions * limitations documented Signed-off-by: Ava Hahn <a.hahn@f5.com>
This commit is contained in:
parent
e0c15ae457
commit
57a0f94efb
7 changed files with 130 additions and 22 deletions
66
tools/unitctl/Cargo.lock
generated
66
tools/unitctl/Cargo.lock
generated
|
@ -485,23 +485,12 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
|||
|
||||
[[package]]
|
||||
name = "errno"
|
||||
version = "0.3.1"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a"
|
||||
checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba"
|
||||
dependencies = [
|
||||
"errno-dragonfly",
|
||||
"libc",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "errno-dragonfly"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -510,6 +499,18 @@ version = "2.0.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5"
|
||||
|
||||
[[package]]
|
||||
name = "filetime"
|
||||
version = "0.2.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fnv"
|
||||
version = "1.0.7"
|
||||
|
@ -1009,9 +1010,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
|
|||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.150"
|
||||
version = "0.2.155"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c"
|
||||
checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
|
||||
|
||||
[[package]]
|
||||
name = "libloading"
|
||||
|
@ -1034,9 +1035,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.4.11"
|
||||
version = "0.4.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "969488b55f8ac402214f3f5fd243ebb7206cf82de60d3172994707a4bcc2b829"
|
||||
checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
|
@ -1488,15 +1489,15 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
|||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.38.25"
|
||||
version = "0.38.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc99bc2d4f1fed22595588a013687477aedf3cdcfb26558c559edb67b4d9b22e"
|
||||
checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f"
|
||||
dependencies = [
|
||||
"bitflags 2.4.1",
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
"windows-sys 0.48.0",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1788,6 +1789,17 @@ dependencies = [
|
|||
"windows",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tar"
|
||||
version = "0.4.41"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cb797dad5fb5b76fcf519e702f4a589483b5ef06567f160c392832c1f5e44909"
|
||||
dependencies = [
|
||||
"filetime",
|
||||
"libc",
|
||||
"xattr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tempfile"
|
||||
version = "3.8.1"
|
||||
|
@ -2061,6 +2073,7 @@ dependencies = [
|
|||
"serde",
|
||||
"serde_json",
|
||||
"serde_yaml",
|
||||
"tar",
|
||||
"tempfile",
|
||||
"tokio",
|
||||
"unit-client-rs",
|
||||
|
@ -2439,6 +2452,17 @@ version = "0.52.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
|
||||
|
||||
[[package]]
|
||||
name = "xattr"
|
||||
version = "1.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8da84f1a25939b27f6820d92aed108f83ff920fdf11a7b19366c27c4cda81d4f"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
"rustix",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "yansi"
|
||||
version = "0.5.1"
|
||||
|
|
|
@ -177,6 +177,20 @@ Imported /opt/unit/config/put.json -> /config
|
|||
Imported 3 files
|
||||
```
|
||||
|
||||
### Export configuration from a running Unit instance
|
||||
```
|
||||
$ unitctl export -f config.tar
|
||||
```
|
||||
|
||||
Addtionally, standard out can be used:
|
||||
```
|
||||
$ unitctl export -f -
|
||||
$ unitctl export -f - | tar xf - config.json
|
||||
$ unitctl export -f - > config.tar
|
||||
```
|
||||
|
||||
*Note:* The exported configuration omits certificates.
|
||||
|
||||
### Wait for socket to become available
|
||||
```
|
||||
$ unitctl --wait-timeout-seconds=3 --wait-max-tries=4 import /opt/unit/config`
|
||||
|
|
|
@ -32,6 +32,7 @@ hyperlocal = "0.8"
|
|||
hyper-tls = "0.5"
|
||||
tokio = { version = "1.35", features = ["macros"] }
|
||||
futures = "0.3"
|
||||
tar = "0.4.41"
|
||||
|
||||
[package.metadata.deb]
|
||||
copyright = "2022, F5"
|
||||
|
|
|
@ -5,3 +5,4 @@ pub(crate) mod import;
|
|||
pub(crate) mod instances;
|
||||
pub(crate) mod listeners;
|
||||
pub(crate) mod status;
|
||||
pub(crate) mod save;
|
||||
|
|
52
tools/unitctl/unitctl/src/cmd/save.rs
Normal file
52
tools/unitctl/unitctl/src/cmd/save.rs
Normal file
|
@ -0,0 +1,52 @@
|
|||
use crate::unitctl::UnitCtl;
|
||||
use crate::wait;
|
||||
use crate::UnitctlError;
|
||||
use crate::requests::send_empty_body_deserialize_response;
|
||||
use unit_client_rs::unit_client::UnitClient;
|
||||
use tar::{Builder, Header};
|
||||
use std::fs::File;
|
||||
use std::io::stdout;
|
||||
|
||||
|
||||
pub async fn cmd(
|
||||
cli: &UnitCtl,
|
||||
filename: &String
|
||||
) -> Result<(), UnitctlError> {
|
||||
if !filename.ends_with(".tar") {
|
||||
eprintln!("Warning: writing uncompressed tarball to {}", filename);
|
||||
}
|
||||
|
||||
let control_socket = wait::wait_for_socket(cli).await?;
|
||||
let client = UnitClient::new(control_socket);
|
||||
|
||||
let config_res = serde_json::to_string_pretty(
|
||||
&send_empty_body_deserialize_response(&client, "GET", "/config").await?
|
||||
);
|
||||
if let Err(e) = config_res {
|
||||
return Err(UnitctlError::DeserializationError{message: e.to_string()})
|
||||
}
|
||||
|
||||
let current_config = config_res
|
||||
.unwrap()
|
||||
.into_bytes();
|
||||
|
||||
//let current_js_modules = send_empty_body_deserialize_response(&client, "GET", "/js_modules")
|
||||
// .await?;
|
||||
|
||||
let mut conf_header = Header::new_gnu();
|
||||
conf_header.set_size(current_config.len() as u64);
|
||||
conf_header.set_mode(0o644);
|
||||
conf_header.set_cksum();
|
||||
|
||||
// builder has a different type depending on output
|
||||
if filename == "-" {
|
||||
let mut ar = Builder::new(stdout());
|
||||
ar.append_data(&mut conf_header, "config.json", current_config.as_slice()).unwrap();
|
||||
} else {
|
||||
let file = File::create(filename).unwrap();
|
||||
let mut ar = Builder::new(file);
|
||||
ar.append_data(&mut conf_header, "config.json", current_config.as_slice()).unwrap();
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
|
@ -8,7 +8,11 @@ extern crate unit_client_rs;
|
|||
|
||||
use clap::Parser;
|
||||
|
||||
use crate::cmd::{applications, edit, execute as execute_cmd, import, instances, listeners, status};
|
||||
use crate::cmd::{
|
||||
applications, edit, execute as execute_cmd,
|
||||
import, instances, listeners, status,
|
||||
save
|
||||
};
|
||||
use crate::output_format::OutputFormat;
|
||||
use crate::unitctl::{Commands, UnitCtl};
|
||||
use crate::unitctl_error::UnitctlError;
|
||||
|
@ -46,6 +50,8 @@ async fn main() -> Result<(), UnitctlError> {
|
|||
Commands::Status { output_format } => status::cmd(&cli, output_format).await,
|
||||
|
||||
Commands::Listeners { output_format } => listeners::cmd(&cli, output_format).await,
|
||||
|
||||
Commands::Export { ref filename } => save::cmd(&cli, filename).await,
|
||||
}
|
||||
.map_err(|error| {
|
||||
eprint_error(&error);
|
||||
|
|
|
@ -116,6 +116,16 @@ pub(crate) enum Commands {
|
|||
},
|
||||
#[command(about = "List all configured Unit applications")]
|
||||
App(ApplicationArgs),
|
||||
|
||||
#[command(about = "Export the current configuration of UNIT")]
|
||||
Export {
|
||||
#[arg(
|
||||
required = true,
|
||||
short = 'f',
|
||||
help = "tarball filename to save configuration to"
|
||||
)]
|
||||
filename: String
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, Args)]
|
||||
|
|
Loading…
Reference in a new issue