Skip to content

Commit 0e6d0ff

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 ab3f3e0 commit 0e6d0ff

37 files changed

Lines changed: 2784 additions & 537 deletions

architecture/object-metadata.md

Lines changed: 417 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(trailing_var_arg = 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.
@@ -2293,6 +2301,7 @@ async fn main() -> Result<()> {
22932301
no_bootstrap,
22942302
auto_providers,
22952303
no_auto_providers,
2304+
labels,
22962305
command,
22972306
} => {
22982307
// Resolve --tty / --no-tty into an Option<bool> override.
@@ -2323,6 +2332,19 @@ async fn main() -> Result<()> {
23232332
None // prompt or auto-detect
23242333
};
23252334

2335+
// Parse --label flags into a HashMap<String, String>.
2336+
let mut labels_map = std::collections::HashMap::new();
2337+
for label_str in &labels {
2338+
let parts: Vec<&str> = label_str.splitn(2, '=').collect();
2339+
if parts.len() != 2 {
2340+
return Err(miette::miette!(
2341+
"invalid label format '{}', expected key=value",
2342+
label_str
2343+
));
2344+
}
2345+
labels_map.insert(parts[0].to_string(), parts[1].to_string());
2346+
}
2347+
23262348
// Parse --upload spec into (local_path, sandbox_path, git_ignore).
23272349
let upload_spec = upload.as_deref().map(|s| {
23282350
let (local, remote) = parse_upload_spec(s);
@@ -2373,6 +2395,7 @@ async fn main() -> Result<()> {
23732395
tty_override,
23742396
Some(false),
23752397
auto_providers_override,
2398+
&labels_map,
23762399
&tls,
23772400
))
23782401
.await?;
@@ -2474,8 +2497,18 @@ async fn main() -> Result<()> {
24742497
offset,
24752498
ids,
24762499
names,
2500+
selector,
24772501
} => {
2478-
run::sandbox_list(endpoint, limit, offset, ids, names, &tls).await?;
2502+
run::sandbox_list(
2503+
endpoint,
2504+
limit,
2505+
offset,
2506+
ids,
2507+
names,
2508+
selector.as_deref(),
2509+
&tls,
2510+
)
2511+
.await?;
24792512
}
24802513
SandboxCommands::Delete { names, all } => {
24812514
run::sandbox_delete(endpoint, &names, all, &tls, &ctx.name).await?;

0 commit comments

Comments
 (0)