diff --git a/crates/cli/src/sdk/generated/iam.rs b/crates/cli/src/sdk/generated/iam.rs index f240d50..33e5c25 100644 --- a/crates/cli/src/sdk/generated/iam.rs +++ b/crates/cli/src/sdk/generated/iam.rs @@ -827,7 +827,14 @@ async fn list_service_accounts( Listing { field: "serviceAccounts", item: Some("origincloud.iam.v1beta1.ServiceAccount"), - columns: &["name", "displayName", "member", "createTime", "deleteTime"], + columns: &[ + "name", + "displayName", + "state", + "member", + "clientId", + "createTime", + ], parents: listed, create: Some("origin iam create-service-account"), }, @@ -853,7 +860,14 @@ async fn list_service_accounts( Listing { field: "serviceAccounts", item: Some("origincloud.iam.v1beta1.ServiceAccount"), - columns: &["name", "displayName", "member", "createTime", "deleteTime"], + columns: &[ + "name", + "displayName", + "state", + "member", + "clientId", + "createTime", + ], parents: listed, create: Some("origin iam create-service-account"), }, diff --git a/crates/cli/tests/output.rs b/crates/cli/tests/output.rs index 2fe9d91..3eb8834 100644 --- a/crates/cli/tests/output.rs +++ b/crates/cli/tests/output.rs @@ -265,6 +265,39 @@ rb-2 serviceAccount:sa-1 viewer projects/p1 ); } +/// Service accounts are listed with the member a role binding names them +/// by, their state and the client id they log in with; a deleted one +/// (`--show-deleted`) says so in its state. +#[tokio::test(flavor = "multi_thread")] +async fn service_accounts_are_listed_by_member_state_and_client_id() { + const ACCOUNTS: &str = r#"{"serviceAccounts":[ + {"name":"organizations/o/serviceAccounts/sa-1","displayName":"CI deploy", + "member":"serviceAccount:sa-1","clientId":"c-7f3a","state":"ACTIVE", + "creator":"user:ada@example.com"}, + {"name":"organizations/o/serviceAccounts/sa-2","displayName":"Old backup", + "member":"serviceAccount:sa-2","clientId":"c-91be","state":"DELETED", + "creator":"user:ada@example.com","deleteTime":"2026-01-02T00:00:00Z"}]}"#; + let server = recording(|_| Response::json(ACCOUNTS)).await; + let args = ["list-service-accounts", "--organization", "o"]; + let table = server + .run("iam", &[&args[..], &["-o", "table"]].concat()) + .await; + assert_eq!( + text(&table.stdout), + "\ +NAME DISPLAY NAME STATE MEMBER CLIENT ID CREATE TIME +sa-1 CI deploy ACTIVE serviceAccount:sa-1 c-7f3a +sa-2 Old backup DELETED serviceAccount:sa-2 c-91be +" + ); + + let wide = server + .run("iam", &[&args[..], &["-o", "wide"]].concat()) + .await; + let header = text(&wide.stdout).lines().next().unwrap().to_owned(); + assert!(header.contains("DELETE TIME"), "{header}"); +} + #[tokio::test(flavor = "multi_thread")] async fn an_empty_list_says_where_it_looked_and_how_to_make_one() { let server = recording(|_| Response::json("{}")).await; diff --git a/generator/commands.toml b/generator/commands.toml index 8c45cdf..feff104 100644 --- a/generator/commands.toml +++ b/generator/commands.toml @@ -504,7 +504,7 @@ columns = ["name", "member", "role", "project", "create_time"] [[view]] service = "iam" message = "ServiceAccount" -columns = ["name", "display_name", "member", "create_time", "delete_time"] +columns = ["name", "display_name", "state", "member", "client_id", "create_time"] [[view]] service = "iam"