openstack_cli_placement/v1/usage/
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::find_by_name;
33use openstack_sdk::api::identity::v3::project::find as find_project;
34use openstack_sdk::api::identity::v3::user::find as find_user;
35use openstack_sdk::api::placement::v1::usage::list;
36use openstack_types::placement::v1::usage::response;
37use tracing::warn;
38
39#[derive(Args)]
48#[command(about = "List usages")]
49pub struct UsagesCommand {
50 #[command(flatten)]
52 query: QueryParameters,
53
54 #[command(flatten)]
56 path: PathParameters,
57}
58
59#[derive(Args)]
61struct QueryParameters {
62 #[arg(help_heading = "Query parameters", long)]
69 consumer_type: Option<String>,
70
71 #[command(flatten)]
73 project: ProjectInput,
74
75 #[command(flatten)]
77 user: UserInput,
78}
79
80#[derive(Args)]
82#[group(required = true, multiple = false)]
83struct ProjectInput {
84 #[arg(long, help_heading = "Path parameters", value_name = "PROJECT_NAME")]
86 project_name: Option<String>,
87 #[arg(long, help_heading = "Path parameters", value_name = "PROJECT_ID")]
89 project_id: Option<String>,
90 #[arg(long, help_heading = "Path parameters", action = clap::ArgAction::SetTrue)]
92 current_project: bool,
93}
94
95#[derive(Args)]
97#[group(required = false, multiple = false)]
98struct UserInput {
99 #[arg(long, help_heading = "Path parameters", value_name = "USER_NAME")]
101 user_name: Option<String>,
102 #[arg(long, help_heading = "Path parameters", value_name = "USER_ID")]
104 user_id: Option<String>,
105 #[arg(long, help_heading = "Path parameters", action = clap::ArgAction::SetTrue)]
107 current_user: bool,
108}
109
110#[derive(Args)]
112struct PathParameters {}
113
114impl UsagesCommand {
115 pub async fn take_action<C: CliArgs>(
117 &self,
118 parsed_args: &C,
119 client: &mut AsyncOpenStack,
120 ) -> Result<(), OpenStackCliError> {
121 info!("List Usages");
122
123 let op = OutputProcessor::from_args(parsed_args, Some("placement.usage"), Some("list"));
124 op.validate_args(parsed_args)?;
125
126 let mut ep_builder = list::Request::builder();
127
128 if let Some(val) = &self.query.consumer_type {
130 ep_builder.consumer_type(val);
131 }
132 if let Some(id) = &self.query.project.project_id {
133 ep_builder.project_id(id);
135 } else if let Some(name) = &self.query.project.project_name {
136 let mut sub_find_builder = find_project::Request::builder();
138 warn!(
139 "Querying project by name (because of `--project-name` parameter passed) may not be definite. This may fail in which case parameter `--project-id` should be used instead."
140 );
141
142 sub_find_builder.id(name);
143 let find_ep = sub_find_builder
144 .build()
145 .map_err(|x| OpenStackCliError::EndpointBuild(x.to_string()))?;
146 let find_data: serde_json::Value = find_by_name(find_ep).query_async(client).await?;
147 match find_data.get("id") {
149 Some(val) => match val.as_str() {
150 Some(id_str) => {
151 ep_builder.project_id(id_str.to_owned());
152 }
153 None => {
154 return Err(OpenStackCliError::ResourceAttributeNotString(
155 serde_json::to_string(&val)?,
156 ));
157 }
158 },
159 None => {
160 return Err(OpenStackCliError::ResourceAttributeMissing(
161 "id".to_string(),
162 ));
163 }
164 };
165 } else if self.query.project.current_project {
166 ep_builder.project_id(
167 client
168 .get_auth_info()
169 .ok_or_eyre("Cannot determine current authentication information")?
170 .token
171 .user
172 .id,
173 );
174 }
175 if let Some(id) = &self.query.user.user_id {
176 ep_builder.user_id(id);
178 } else if let Some(name) = &self.query.user.user_name {
179 let mut sub_find_builder = find_user::Request::builder();
181 warn!(
182 "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."
183 );
184
185 sub_find_builder.id(name);
186 let find_ep = sub_find_builder
187 .build()
188 .map_err(|x| OpenStackCliError::EndpointBuild(x.to_string()))?;
189 let find_data: serde_json::Value = find_by_name(find_ep).query_async(client).await?;
190 match find_data.get("id") {
192 Some(val) => match val.as_str() {
193 Some(id_str) => {
194 ep_builder.user_id(id_str.to_owned());
195 }
196 None => {
197 return Err(OpenStackCliError::ResourceAttributeNotString(
198 serde_json::to_string(&val)?,
199 ));
200 }
201 },
202 None => {
203 return Err(OpenStackCliError::ResourceAttributeMissing(
204 "id".to_string(),
205 ));
206 }
207 };
208 } else if self.query.user.current_user {
209 ep_builder.user_id(
210 client
211 .get_auth_info()
212 .ok_or_eyre("Cannot determine current authentication information")?
213 .token
214 .user
215 .id,
216 );
217 }
218
219 let ep = ep_builder
220 .build()
221 .map_err(|x| OpenStackCliError::EndpointBuild(x.to_string()))?;
222
223 let data: Vec<serde_json::Value> = ep.query_async(client).await?;
224
225 op.output_list::<response::list::UsageResponse>(data.clone())?;
226 op.show_command_hint()?;
228 Ok(())
229 }
230}