mirror of
https://github.com/ModernRelay/omnigraph.git
synced 2026-06-12 01:45:14 +02:00
feat(cli): --server <name> targeting (RFC-007 PR 3, part 1)
Global flags --server (operator-defined server name) and --graph (graph id on a multi-graph server, requires --server) resolve to the effective remote URI through one helper and feed the ordinary uri slot — graph resolution and the PR-2 keyed-token URL match work unchanged; the flag is sugar for a URI the operator already owns. Exclusive with a positional URI and --target (loud error, never silent precedence). Unknown names fail listing the servers that ARE defined. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
65160cc060
commit
2b33ab64f2
4 changed files with 109 additions and 0 deletions
|
|
@ -21,6 +21,17 @@ pub(crate) struct Cli {
|
|||
#[arg(long = "as", global = true, value_name = "ACTOR")]
|
||||
pub(crate) as_actor: Option<String>,
|
||||
|
||||
/// Target an operator-defined server by name (RFC-007): resolves to
|
||||
/// its `url` from `servers:` in ~/.omnigraph/config.yaml. Exclusive
|
||||
/// with a positional URI or `--target`.
|
||||
#[arg(long, global = true, value_name = "NAME")]
|
||||
pub(crate) server: Option<String>,
|
||||
|
||||
/// Graph id on a multi-graph `--server` (appends `/graphs/<id>` to
|
||||
/// the server url). Requires --server.
|
||||
#[arg(long, global = true, value_name = "GRAPH_ID", requires = "server")]
|
||||
pub(crate) graph: Option<String>,
|
||||
|
||||
#[command(subcommand)]
|
||||
pub(crate) command: Command,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -264,6 +264,57 @@ pub(crate) fn resolve_remote_bearer_token(
|
|||
Ok(None)
|
||||
}
|
||||
|
||||
/// `--server <name>` (RFC-007 PR 3): resolve an operator-defined server
|
||||
/// name (+ optional `--graph` for multi-graph servers) to the effective
|
||||
/// remote URI. The result feeds the ordinary `uri` slot, so graph
|
||||
/// resolution and the keyed-token URL match work unchanged — the flag is
|
||||
/// sugar for a URI the operator already owns. Unknown names fail loudly,
|
||||
/// listing what IS defined.
|
||||
pub(crate) fn resolve_server_flag(
|
||||
server: Option<&str>,
|
||||
graph: Option<&str>,
|
||||
) -> Result<Option<String>> {
|
||||
let Some(server) = server else {
|
||||
return Ok(None);
|
||||
};
|
||||
let operator_config = operator::load_operator_config()?;
|
||||
let Some(entry) = operator_config.servers.get(server) else {
|
||||
let known = operator_config
|
||||
.servers
|
||||
.keys()
|
||||
.map(String::as_str)
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ");
|
||||
color_eyre::eyre::bail!(
|
||||
"unknown server '{server}' — servers defined in the operator config: [{known}] (add it under servers: in ~/.omnigraph/config.yaml)"
|
||||
);
|
||||
};
|
||||
let base = entry.url.trim_end_matches('/');
|
||||
Ok(Some(match graph {
|
||||
Some(graph) => format!("{base}/graphs/{graph}"),
|
||||
None => base.to_string(),
|
||||
}))
|
||||
}
|
||||
|
||||
/// Apply `--server`/`--graph` to a command's uri/target slots: exclusive
|
||||
/// with both (loud error, not silent precedence), no-op when absent.
|
||||
pub(crate) fn apply_server_flag(
|
||||
server: Option<&str>,
|
||||
graph: Option<&str>,
|
||||
uri: Option<String>,
|
||||
target: Option<&str>,
|
||||
) -> Result<Option<String>> {
|
||||
if server.is_none() {
|
||||
return Ok(uri);
|
||||
}
|
||||
if uri.is_some() || target.is_some() {
|
||||
color_eyre::eyre::bail!(
|
||||
"--server is exclusive with a positional URI and --target — pick one way to address the graph"
|
||||
);
|
||||
}
|
||||
resolve_server_flag(server, graph)
|
||||
}
|
||||
|
||||
/// The remote base URL a token resolution is FOR — the same scoping
|
||||
/// `graph_bearer_token_env` uses: an explicit http(s) `--uri` wins, else
|
||||
/// the config-resolved target's uri (when remote). Local URIs → None.
|
||||
|
|
|
|||
|
|
@ -130,6 +130,8 @@ async fn main() -> Result<()> {
|
|||
json,
|
||||
} => {
|
||||
let config = load_cli_config(config.as_ref())?;
|
||||
let uri =
|
||||
apply_server_flag(cli.server.as_deref(), cli.graph.as_deref(), uri, target.as_deref())?;
|
||||
let bearer_token =
|
||||
resolve_remote_bearer_token(&config, uri.as_deref(), target.as_deref())?;
|
||||
let graph = resolve_cli_graph(&config, uri, target.as_deref())?;
|
||||
|
|
@ -198,6 +200,8 @@ async fn main() -> Result<()> {
|
|||
use `omnigraph load --from <base> --mode <mode>` (ingest defaults: --from main --mode merge)"
|
||||
);
|
||||
let config = load_cli_config(config.as_ref())?;
|
||||
let uri =
|
||||
apply_server_flag(cli.server.as_deref(), cli.graph.as_deref(), uri, target.as_deref())?;
|
||||
let bearer_token =
|
||||
resolve_remote_bearer_token(&config, uri.as_deref(), target.as_deref())?;
|
||||
let graph = resolve_cli_graph(&config, uri, target.as_deref())?;
|
||||
|
|
@ -250,6 +254,8 @@ async fn main() -> Result<()> {
|
|||
json,
|
||||
} => {
|
||||
let config = load_cli_config(config.as_ref())?;
|
||||
let uri =
|
||||
apply_server_flag(cli.server.as_deref(), cli.graph.as_deref(), uri, target.as_deref())?;
|
||||
let bearer_token =
|
||||
resolve_remote_bearer_token(&config, uri.as_deref(), target.as_deref())?;
|
||||
let graph = resolve_cli_graph(&config, uri, target.as_deref())?;
|
||||
|
|
@ -293,6 +299,8 @@ async fn main() -> Result<()> {
|
|||
json,
|
||||
} => {
|
||||
let config = load_cli_config(config.as_ref())?;
|
||||
let uri =
|
||||
apply_server_flag(cli.server.as_deref(), cli.graph.as_deref(), uri, target.as_deref())?;
|
||||
let bearer_token =
|
||||
resolve_remote_bearer_token(&config, uri.as_deref(), target.as_deref())?;
|
||||
let graph = resolve_cli_graph(&config, uri, target.as_deref())?;
|
||||
|
|
@ -328,6 +336,8 @@ async fn main() -> Result<()> {
|
|||
json,
|
||||
} => {
|
||||
let config = load_cli_config(config.as_ref())?;
|
||||
let uri =
|
||||
apply_server_flag(cli.server.as_deref(), cli.graph.as_deref(), uri, target.as_deref())?;
|
||||
let bearer_token =
|
||||
resolve_remote_bearer_token(&config, uri.as_deref(), target.as_deref())?;
|
||||
let graph = resolve_cli_graph(&config, uri, target.as_deref())?;
|
||||
|
|
@ -367,6 +377,8 @@ async fn main() -> Result<()> {
|
|||
json,
|
||||
} => {
|
||||
let config = load_cli_config(config.as_ref())?;
|
||||
let uri =
|
||||
apply_server_flag(cli.server.as_deref(), cli.graph.as_deref(), uri, target.as_deref())?;
|
||||
let bearer_token =
|
||||
resolve_remote_bearer_token(&config, uri.as_deref(), target.as_deref())?;
|
||||
let graph = resolve_cli_graph(&config, uri, target.as_deref())?;
|
||||
|
|
@ -417,6 +429,8 @@ async fn main() -> Result<()> {
|
|||
json,
|
||||
} => {
|
||||
let config = load_cli_config(config.as_ref())?;
|
||||
let uri =
|
||||
apply_server_flag(cli.server.as_deref(), cli.graph.as_deref(), uri, target.as_deref())?;
|
||||
let bearer_token =
|
||||
resolve_remote_bearer_token(&config, uri.as_deref(), target.as_deref())?;
|
||||
let uri = resolve_uri(&config, uri, target.as_deref())?;
|
||||
|
|
@ -456,6 +470,8 @@ async fn main() -> Result<()> {
|
|||
json,
|
||||
} => {
|
||||
let config = load_cli_config(config.as_ref())?;
|
||||
let uri =
|
||||
apply_server_flag(cli.server.as_deref(), cli.graph.as_deref(), uri, target.as_deref())?;
|
||||
let bearer_token =
|
||||
resolve_remote_bearer_token(&config, uri.as_deref(), target.as_deref())?;
|
||||
let uri = resolve_uri(&config, uri, target.as_deref())?;
|
||||
|
|
@ -519,6 +535,8 @@ async fn main() -> Result<()> {
|
|||
allow_data_loss,
|
||||
} => {
|
||||
let config = load_cli_config(config.as_ref())?;
|
||||
let uri =
|
||||
apply_server_flag(cli.server.as_deref(), cli.graph.as_deref(), uri, target.as_deref())?;
|
||||
let bearer_token =
|
||||
resolve_remote_bearer_token(&config, uri.as_deref(), target.as_deref())?;
|
||||
let graph = resolve_cli_graph(&config, uri, target.as_deref())?;
|
||||
|
|
@ -576,6 +594,8 @@ async fn main() -> Result<()> {
|
|||
json,
|
||||
} => {
|
||||
let config = load_cli_config(config.as_ref())?;
|
||||
let uri =
|
||||
apply_server_flag(cli.server.as_deref(), cli.graph.as_deref(), uri, target.as_deref())?;
|
||||
let bearer_token =
|
||||
resolve_remote_bearer_token(&config, uri.as_deref(), target.as_deref())?;
|
||||
let uri = resolve_uri(&config, uri, target.as_deref())?;
|
||||
|
|
@ -640,6 +660,8 @@ async fn main() -> Result<()> {
|
|||
json,
|
||||
} => {
|
||||
let config = load_cli_config(config.as_ref())?;
|
||||
let uri =
|
||||
apply_server_flag(cli.server.as_deref(), cli.graph.as_deref(), uri, target.as_deref())?;
|
||||
let bearer_token =
|
||||
resolve_remote_bearer_token(&config, uri.as_deref(), target.as_deref())?;
|
||||
let uri = resolve_uri(&config, uri, target.as_deref())?;
|
||||
|
|
@ -675,6 +697,8 @@ async fn main() -> Result<()> {
|
|||
table_keys,
|
||||
} => {
|
||||
let config = load_cli_config(config.as_ref())?;
|
||||
let uri =
|
||||
apply_server_flag(cli.server.as_deref(), cli.graph.as_deref(), uri, target.as_deref())?;
|
||||
let bearer_token =
|
||||
resolve_remote_bearer_token(&config, uri.as_deref(), target.as_deref())?;
|
||||
let uri = resolve_uri(&config, uri, target.as_deref())?;
|
||||
|
|
@ -736,6 +760,7 @@ async fn main() -> Result<()> {
|
|||
let target_name = target
|
||||
.as_deref()
|
||||
.or_else(|| alias_config.and_then(|alias| alias.graph.as_deref()));
|
||||
let uri = apply_server_flag(cli.server.as_deref(), cli.graph.as_deref(), uri, target_name)?;
|
||||
let bearer_token = resolve_remote_bearer_token(&config, uri.as_deref(), target_name)?;
|
||||
let graph = resolve_cli_graph(&config, uri, target_name)?;
|
||||
let uri = graph.uri.clone();
|
||||
|
|
@ -822,6 +847,7 @@ async fn main() -> Result<()> {
|
|||
let target_name = target
|
||||
.as_deref()
|
||||
.or_else(|| alias_config.and_then(|alias| alias.graph.as_deref()));
|
||||
let uri = apply_server_flag(cli.server.as_deref(), cli.graph.as_deref(), uri, target_name)?;
|
||||
let bearer_token = resolve_remote_bearer_token(&config, uri.as_deref(), target_name)?;
|
||||
let graph = resolve_cli_graph(&config, uri, target_name)?;
|
||||
let uri = graph.uri.clone();
|
||||
|
|
@ -1177,6 +1203,8 @@ async fn main() -> Result<()> {
|
|||
json,
|
||||
} => {
|
||||
let config = load_cli_config(config.as_ref())?;
|
||||
let uri =
|
||||
apply_server_flag(cli.server.as_deref(), cli.graph.as_deref(), uri, target.as_deref())?;
|
||||
let bearer_token =
|
||||
resolve_remote_bearer_token(&config, uri.as_deref(), target.as_deref())?;
|
||||
let uri = resolve_uri(&config, uri, target.as_deref())?;
|
||||
|
|
|
|||
|
|
@ -467,6 +467,25 @@ mod tests {
|
|||
assert_eq!(config.find_server_for_url("http://other:9999"), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn server_lookup_supports_targeting() {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let path = dir.path().join("config.yaml");
|
||||
fs::write(
|
||||
&path,
|
||||
"servers:\n intel-dev:\n url: http://127.0.0.1:8080/\n",
|
||||
)
|
||||
.unwrap();
|
||||
let config = load_operator_config_at(&path).unwrap();
|
||||
// the --server resolution shape: bare url and graph-scoped url
|
||||
let base = config.servers["intel-dev"].url.trim_end_matches('/');
|
||||
assert_eq!(base, "http://127.0.0.1:8080");
|
||||
assert_eq!(
|
||||
format!("{base}/graphs/spike"),
|
||||
"http://127.0.0.1:8080/graphs/spike"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn token_env_name_uppercases_and_underscores() {
|
||||
assert_eq!(token_env_name("intel-dev"), "OMNIGRAPH_TOKEN_INTEL_DEV");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue