tools/cubec: fix CLI so ./check stress works; separate client flags from command
cubec forwarded its OWN leading options (--socket/--tenant/...) verbatim into the command payload sent to the daemon, so 'cubec --socket SOCK "prog ..."' made the server reject '--socket' as an unknown command. stress.sh therefore produced 'error: unknown command: --socket' on every sample and measured nothing. Split cubec arg parsing into client-option vs command-payload so flags are consumed locally and only the command reaches the daemon. The canonical './check stress' stage now drives a real daemon and samples stats.
This commit is contained in:
+64
-19
@@ -13,29 +13,74 @@ use cubesys::net::{read_stream_frame, write_frame};
|
|||||||
use std::io::{BufRead, Write};
|
use std::io::{BufRead, Write};
|
||||||
use std::os::unix::net::UnixStream;
|
use std::os::unix::net::UnixStream;
|
||||||
|
|
||||||
/// Resolve `--key VALUE` from argv, or None.
|
/// `cubec` — a tiny Unix-domain-socket client for the `cube-server` daemon.
|
||||||
fn arg_value(args: &[String], key: &str) -> Option<String> {
|
///
|
||||||
args.iter()
|
/// Separates cubec's OWN options (`--socket`, `--tenant`, `--owner`,
|
||||||
.position(|a| a == key)
|
/// `--auth-key*`) from the command it forwards to the daemon. Conflating the
|
||||||
.and_then(|i| args.get(i + 1).cloned())
|
/// two made `cubec --socket SOCK "prog ..."` send `--socket SOCK prog ...` to
|
||||||
}
|
/// the server, which rejected it as an unknown command.
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let args: Vec<String> = std::env::args().skip(1).collect();
|
let raw: Vec<String> = std::env::args().skip(1).collect();
|
||||||
let socket = arg_value(&args, "--socket")
|
|
||||||
.or_else(|| std::env::var("CUBE_SOCKET").ok())
|
// Defaults from the environment (kept so legacy invocations still work).
|
||||||
.unwrap_or_else(|| "/run/cube/demo.sock".to_string());
|
let mut socket =
|
||||||
let tenant = arg_value(&args, "--tenant").unwrap_or_else(|| "default".to_string());
|
std::env::var("CUBE_SOCKET").unwrap_or_else(|_| "/run/cube/demo.sock".to_string());
|
||||||
let owner = arg_value(&args, "--owner")
|
let mut tenant = "default".to_string();
|
||||||
.or_else(|| std::env::var("USER").ok())
|
let mut owner = std::env::var("USER").unwrap_or_else(|_| "cubec".to_string());
|
||||||
.unwrap_or_else(|| "cubec".to_string());
|
let mut psk_path: Option<String> = None;
|
||||||
|
let mut psk_env: Option<String> = None;
|
||||||
|
|
||||||
|
// Everything that is not one of cubec's options becomes the command text
|
||||||
|
// forwarded to the daemon.
|
||||||
|
let mut cmd_args: Vec<String> = Vec::new();
|
||||||
|
let mut i = 0;
|
||||||
|
while i < raw.len() {
|
||||||
|
match raw[i].as_str() {
|
||||||
|
"--socket" => {
|
||||||
|
if let Some(v) = raw.get(i + 1) {
|
||||||
|
socket = v.clone();
|
||||||
|
}
|
||||||
|
i += 2;
|
||||||
|
}
|
||||||
|
"--tenant" => {
|
||||||
|
if let Some(v) = raw.get(i + 1) {
|
||||||
|
tenant = v.clone();
|
||||||
|
}
|
||||||
|
i += 2;
|
||||||
|
}
|
||||||
|
"--owner" => {
|
||||||
|
if let Some(v) = raw.get(i + 1) {
|
||||||
|
owner = v.clone();
|
||||||
|
}
|
||||||
|
i += 2;
|
||||||
|
}
|
||||||
|
"--auth-key" => {
|
||||||
|
if let Some(v) = raw.get(i + 1) {
|
||||||
|
psk_path = Some(v.clone());
|
||||||
|
}
|
||||||
|
i += 2;
|
||||||
|
}
|
||||||
|
"--auth-key-env" => {
|
||||||
|
if let Some(v) = raw.get(i + 1) {
|
||||||
|
psk_env = Some(v.clone());
|
||||||
|
}
|
||||||
|
i += 2;
|
||||||
|
}
|
||||||
|
// Not a cubec option: part of the command payload.
|
||||||
|
other => {
|
||||||
|
cmd_args.push(other.to_string());
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Pre-shared key for the signed-HELLO handshake (plan R4). `--auth-key PATH`
|
// Pre-shared key for the signed-HELLO handshake (plan R4). `--auth-key PATH`
|
||||||
// reads a file; `--auth-key-env VAR` reads an env var; otherwise `CUBE_AUTH_KEY`.
|
// reads a file; `--auth-key-env VAR` reads an env var; otherwise `CUBE_AUTH_KEY`.
|
||||||
let psk: Option<Vec<u8>> = if let Some(path) = arg_value(&args, "--auth-key") {
|
let psk: Option<Vec<u8>> = if let Some(path) = psk_path {
|
||||||
std::fs::read_to_string(&path)
|
std::fs::read_to_string(&path)
|
||||||
.map(|s| s.trim().as_bytes().to_vec())
|
.map(|s| s.trim().as_bytes().to_vec())
|
||||||
.ok()
|
.ok()
|
||||||
} else if let Some(var) = arg_value(&args, "--auth-key-env") {
|
} else if let Some(var) = psk_env {
|
||||||
std::env::var(&var)
|
std::env::var(&var)
|
||||||
.ok()
|
.ok()
|
||||||
.map(|s| s.trim().as_bytes().to_vec())
|
.map(|s| s.trim().as_bytes().to_vec())
|
||||||
@@ -79,7 +124,7 @@ fn main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if args.is_empty() {
|
if cmd_args.is_empty() {
|
||||||
// REPL mode (legacy behaviour, now after an optional handshake).
|
// REPL mode (legacy behaviour, now after an optional handshake).
|
||||||
let stdin = std::io::stdin();
|
let stdin = std::io::stdin();
|
||||||
for line in stdin.lock().lines().map_while(Result::ok) {
|
for line in stdin.lock().lines().map_while(Result::ok) {
|
||||||
@@ -101,7 +146,7 @@ fn main() {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// One-shot: join the remaining args as the command line, send, print.
|
// One-shot: join the remaining args as the command line, send, print.
|
||||||
let cmd = args.join(" ");
|
let cmd = cmd_args.join(" ");
|
||||||
if write_frame(&mut stream, &cmd).is_err() {
|
if write_frame(&mut stream, &cmd).is_err() {
|
||||||
eprintln!("cubec: write failed");
|
eprintln!("cubec: write failed");
|
||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
|
|||||||
@@ -47,6 +47,9 @@ PAIRS=0
|
|||||||
SAMPLE_EVERY=25 # sample stats every 25 pairs (~ once a second at load)
|
SAMPLE_EVERY=25 # sample stats every 25 pairs (~ once a second at load)
|
||||||
while [ "$(date +%s)" -lt "$END" ]; do
|
while [ "$(date +%s)" -lt "$END" ]; do
|
||||||
X=$((PAIRS % 256))
|
X=$((PAIRS % 256))
|
||||||
|
# Flags MUST precede the command: `cubec` parses --socket/--tenant as leading
|
||||||
|
# options, so `"$CLI" --socket SOCK "prog ..."` would turn the trailing
|
||||||
|
# --socket into an unknown subcommand. Pass flags first.
|
||||||
"$CLI" --socket "$SOCK" "prog /c077/z001/y001/x$X const $((PAIRS % 97)) halt" >/dev/null 2>&1
|
"$CLI" --socket "$SOCK" "prog /c077/z001/y001/x$X const $((PAIRS % 97)) halt" >/dev/null 2>&1
|
||||||
"$CLI" --socket "$SOCK" "run /c077/z001/y001/x$X" >/dev/null 2>&1
|
"$CLI" --socket "$SOCK" "run /c077/z001/y001/x$X" >/dev/null 2>&1
|
||||||
PAIRS=$((PAIRS + 1))
|
PAIRS=$((PAIRS + 1))
|
||||||
|
|||||||
Reference in New Issue
Block a user