Skip to content

Commit 46a37df

Browse files
feat(server): add object meta convention to top-level objects
- adds filterable label selectors on resources Closes #864 Signed-off-by: Derek Carr <decarr@redhat.com>
1 parent bb5bdb4 commit 46a37df

39 files changed

Lines changed: 2806 additions & 549 deletions

architecture/object-metadata.md

Lines changed: 426 additions & 0 deletions
Large diffs are not rendered by default.

crates/openshell-cli/src/completers.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use std::time::Duration;
77

88
use clap_complete::engine::CompletionCandidate;
99
use openshell_bootstrap::{list_gateways, load_active_gateway, load_gateway_metadata};
10+
use openshell_core::ObjectName;
1011
use openshell_core::proto::open_shell_client::OpenShellClient;
1112
use openshell_core::proto::{ListProvidersRequest, ListSandboxesRequest};
1213
use tonic::transport::{Channel, Endpoint};
@@ -33,6 +34,7 @@ pub fn complete_sandbox_names(_prefix: &OsStr) -> Vec<CompletionCandidate> {
3334
.list_sandboxes(ListSandboxesRequest {
3435
limit: 200,
3536
offset: 0,
37+
label_selector: String::new(),
3638
})
3739
.await
3840
.ok()?;
@@ -41,7 +43,7 @@ pub fn complete_sandbox_names(_prefix: &OsStr) -> Vec<CompletionCandidate> {
4143
.into_inner()
4244
.sandboxes
4345
.into_iter()
44-
.map(|s| CompletionCandidate::new(s.name))
46+
.map(|s| CompletionCandidate::new(s.object_name()))
4547
.collect(),
4648
)
4749
})
@@ -64,7 +66,7 @@ pub fn complete_provider_names(_prefix: &OsStr) -> Vec<CompletionCandidate> {
6466
.into_inner()
6567
.providers
6668
.into_iter()
67-
.map(|p| CompletionCandidate::new(p.name))
69+
.map(|p| CompletionCandidate::new(p.object_name()))
6870
.collect(),
6971
)
7072
})

crates/openshell-cli/src/main.rs

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1197,6 +1197,10 @@ enum SandboxCommands {
11971197
#[arg(long, overrides_with = "auto_providers")]
11981198
no_auto_providers: bool,
11991199

1200+
/// Attach labels to the sandbox (key=value format, repeatable).
1201+
#[arg(long = "label")]
1202+
labels: Vec<String>,
1203+
12001204
/// Command to run after "--" (defaults to an interactive shell).
12011205
#[arg(last = true, allow_hyphen_values = true)]
12021206
command: Vec<String>,
@@ -1232,6 +1236,10 @@ enum SandboxCommands {
12321236
/// Print only sandbox names (one per line).
12331237
#[arg(long, conflicts_with = "ids")]
12341238
names: bool,
1239+
1240+
/// Filter sandboxes by label selector (key1=value1,key2=value2).
1241+
#[arg(long)]
1242+
selector: Option<String>,
12351243
},
12361244

12371245
/// Delete a sandbox by name.
@@ -2310,6 +2318,7 @@ async fn main() -> Result<()> {
23102318
no_bootstrap,
23112319
auto_providers,
23122320
no_auto_providers,
2321+
labels,
23132322
command,
23142323
} => {
23152324
// Resolve --tty / --no-tty into an Option<bool> override.
@@ -2340,6 +2349,19 @@ async fn main() -> Result<()> {
23402349
None // prompt or auto-detect
23412350
};
23422351

2352+
// Parse --label flags into a HashMap<String, String>.
2353+
let mut labels_map = std::collections::HashMap::new();
2354+
for label_str in &labels {
2355+
let parts: Vec<&str> = label_str.splitn(2, '=').collect();
2356+
if parts.len() != 2 {
2357+
return Err(miette::miette!(
2358+
"invalid label format '{}', expected key=value",
2359+
label_str
2360+
));
2361+
}
2362+
labels_map.insert(parts[0].to_string(), parts[1].to_string());
2363+
}
2364+
23432365
// Parse --upload spec into (local_path, sandbox_path, git_ignore).
23442366
let upload_spec = upload.as_deref().map(|s| {
23452367
let (local, remote) = parse_upload_spec(s);
@@ -2390,6 +2412,7 @@ async fn main() -> Result<()> {
23902412
tty_override,
23912413
Some(false),
23922414
auto_providers_override,
2415+
&labels_map,
23932416
&tls,
23942417
))
23952418
.await?;
@@ -2491,8 +2514,18 @@ async fn main() -> Result<()> {
24912514
offset,
24922515
ids,
24932516
names,
2517+
selector,
24942518
} => {
2495-
run::sandbox_list(endpoint, limit, offset, ids, names, &tls).await?;
2519+
run::sandbox_list(
2520+
endpoint,
2521+
limit,
2522+
offset,
2523+
ids,
2524+
names,
2525+
selector.as_deref(),
2526+
&tls,
2527+
)
2528+
.await?;
24962529
}
24972530
SandboxCommands::Delete { names, all } => {
24982531
run::sandbox_delete(endpoint, &names, all, &tls, &ctx.name).await?;

0 commit comments

Comments
 (0)