openstack_cli_compute/v2/keypair/
list.rs1use clap::Args;
23use eyre::OptionExt;
24use tracing::info;
25
26use openstack_cli_core::cli::CliArgs;
27use openstack_cli_core::error::OpenStackCliError;
28use openstack_cli_core::output::OutputProcessor;
29use openstack_sdk::AsyncOpenStack;
30
31use openstack_sdk::api::QueryAsync;
32use openstack_sdk::api::compute::v2::keypair::list;
33use openstack_sdk::api::find_by_name;
34use openstack_sdk::api::identity::v3::user::find as find_user;
35use openstack_sdk::api::{Pagination, paged};
36use openstack_types::compute::v2::keypair::response;
37use tracing::warn;
38
39#[derive(Args)]
45#[command(about = "List Keypairs")]
46pub struct KeypairsCommand {
47 #[command(flatten)]
49 query: QueryParameters,
50
51 #[command(flatten)]
53 path: PathParameters,
54
55 #[arg(long, default_value_t = 10000)]
57 max_items: usize,
58}
59
60#[derive(Args)]
62struct QueryParameters {
63 #[arg(
68 help_heading = "Query parameters",
69 long("page-size"),
70 visible_alias("limit")
71 )]
72 limit: Option<u32>,
73
74 #[arg(help_heading = "Query parameters", long)]
78 marker: Option<String>,
79
80 #[command(flatten)]
82 user: UserInput,
83}
84
85#[derive(Args)]
87#[group(required = false, multiple = false)]
88struct UserInput {
89 #[arg(long, help_heading = "Path parameters", value_name = "USER_NAME")]
91 user_name: Option<String>,
92 #[arg(long, help_heading = "Path parameters", value_name = "USER_ID")]
94 user_id: Option<String>,
95 #[arg(long, help_heading = "Path parameters", action = clap::ArgAction::SetTrue)]
97 current_user: bool,
98}
99
100#[derive(Args)]
102struct PathParameters {}
103
104impl KeypairsCommand {
105 pub async fn take_action<C: CliArgs>(
107 &self,
108 parsed_args: &C,
109 client: &mut AsyncOpenStack,
110 ) -> Result<(), OpenStackCliError> {
111 info!("List Keypairs");
112
113 let op = OutputProcessor::from_args(parsed_args, Some("compute.keypair"), Some("list"));
114 op.validate_args(parsed_args)?;
115
116 let mut ep_builder = list::Request::builder();
117
118 if let Some(val) = &self.query.limit {
120 ep_builder.limit(*val);
121 }
122 if let Some(val) = &self.query.marker {
123 ep_builder.marker(val);
124 }
125 if let Some(id) = &self.query.user.user_id {
126 ep_builder.user_id(id);
128 } else if let Some(name) = &self.query.user.user_name {
129 let mut sub_find_builder = find_user::Request::builder();
131 warn!(
132 "Querying user by name (because of `--user-name` parameter passed) may not be definite. This may fail in which case parameter `--user-id` should be used instead."
133 );
134
135 sub_find_builder.id(name);
136 let find_ep = sub_find_builder
137 .build()
138 .map_err(|x| OpenStackCliError::EndpointBuild(x.to_string()))?;
139 let find_data: serde_json::Value = find_by_name(find_ep).query_async(client).await?;
140 match find_data.get("id") {
142 Some(val) => match val.as_str() {
143 Some(id_str) => {
144 ep_builder.user_id(id_str.to_owned());
145 }
146 None => {
147 return Err(OpenStackCliError::ResourceAttributeNotString(
148 serde_json::to_string(&val)?,
149 ));
150 }
151 },
152 None => {
153 return Err(OpenStackCliError::ResourceAttributeMissing(
154 "id".to_string(),
155 ));
156 }
157 };
158 } else if self.query.user.current_user {
159 ep_builder.user_id(
160 client
161 .get_auth_info()
162 .ok_or_eyre("Cannot determine current authentication information")?
163 .token
164 .user
165 .id,
166 );
167 }
168
169 let ep = ep_builder
170 .build()
171 .map_err(|x| OpenStackCliError::EndpointBuild(x.to_string()))?;
172
173 let data: Vec<serde_json::Value> = paged(ep, Pagination::Limit(self.max_items))
174 .query_async(client)
175 .await?;
176
177 op.output_list::<response::list_20::KeypairResponse>(data.clone())
178 .or_else(|_| op.output_list::<response::list_22::KeypairResponse>(data.clone()))
179 .or_else(|_| op.output_list::<response::list_235::KeypairResponse>(data.clone()))?;
180 op.show_command_hint()?;
182 Ok(())
183 }
184}