Skip to main content

openstack_cli_image/v2/image/file/
download.rs

1// Licensed under the Apache License, Version 2.0 (the "License");
2// you may not use this file except in compliance with the License.
3// You may obtain a copy of the License at
4//
5//     http://www.apache.org/licenses/LICENSE-2.0
6//
7// Unless required by applicable law or agreed to in writing, software
8// distributed under the License is distributed on an "AS IS" BASIS,
9// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10// See the License for the specific language governing permissions and
11// limitations under the License.
12//
13// SPDX-License-Identifier: Apache-2.0
14//
15// WARNING: This file is automatically generated from OpenAPI schema using
16// `openstack-codegenerator`.
17
18//! Download File command
19//!
20//! Wraps invoking of the `v2/images/{image_id}/file` with `GET` method
21
22use clap::Args;
23use tracing::info;
24
25use openstack_cli_core::cli::CliArgs;
26use openstack_cli_core::error::OpenStackCliError;
27use openstack_cli_core::output::OutputProcessor;
28use openstack_sdk::AsyncOpenStack;
29
30use openstack_cli_core::common::download_file;
31use openstack_sdk::api::QueryAsync;
32use openstack_sdk::api::RawQueryAsync;
33use openstack_sdk::api::find;
34use openstack_sdk::api::image::v2::image::file::download;
35use openstack_sdk::api::image::v2::image::find;
36
37/// Downloads binary image data. *(Since Image API v2.0)*
38///
39/// Example call:
40/// `curl -i -X GET -H "X-Auth-Token: $token" $image_url/v2/images/{image_id}/file`
41///
42/// The response body contains the raw binary data that represents the actual
43/// virtual disk. The `Content-Type` header contains the
44/// `application/octet-stream` value. The `Content-MD5` header contains an MD5
45/// checksum of the image data. Use this checksum to verify the integrity of
46/// the image data.
47///
48/// **Preconditions**
49///
50/// **Synchronous Postconditions**
51///
52/// Normal response codes: 200, 204, 206
53///
54/// Error response codes: 400, 403, 404, 416
55#[derive(Args)]
56#[command(about = "Download binary image data")]
57pub struct FileCommand {
58    /// Request Query parameters
59    #[command(flatten)]
60    query: QueryParameters,
61
62    /// Request Headers parameters
63    #[command(flatten)]
64    headers: HeaderParameters,
65
66    /// Path parameters
67    #[command(flatten)]
68    path: PathParameters,
69
70    /// Destination filename (using "-" will print object to stdout)
71    #[arg(long)]
72    file: Option<String>,
73}
74
75/// Query parameters
76#[derive(Args)]
77struct QueryParameters {}
78
79/// Header parameters
80#[derive(Args)]
81struct HeaderParameters {
82    /// The range of image data requested. Note that multi range requests are
83    /// not supported.
84    #[arg(long)]
85    range: Option<String>,
86}
87
88/// Path parameters
89#[derive(Args)]
90struct PathParameters {
91    /// image_id parameter for /v2/images/{image_id}/file API
92    #[arg(
93        help_heading = "Path parameters",
94        id = "path_param_image_id",
95        value_name = "IMAGE_ID"
96    )]
97    image_id: String,
98}
99
100impl FileCommand {
101    /// Perform command action
102    pub async fn take_action<C: CliArgs>(
103        &self,
104        parsed_args: &C,
105        client: &mut AsyncOpenStack,
106    ) -> Result<(), OpenStackCliError> {
107        info!("Download File");
108
109        let op =
110            OutputProcessor::from_args(parsed_args, Some("image.image/file"), Some("download"));
111        op.validate_args(parsed_args)?;
112        let find_ep = find::Request::builder()
113            .id(&self.path.image_id)
114            .build()
115            .map_err(|x| OpenStackCliError::EndpointBuild(x.to_string()))?;
116        let image_data: serde_json::Value = find(find_ep).query_async(client).await?;
117
118        let image_id = image_data["id"]
119            .as_str()
120            .ok_or_else(|| eyre::eyre!("image ID must be a string"))?
121            .to_string();
122        let image_name = image_data["name"]
123            .as_str()
124            .ok_or_else(|| eyre::eyre!("image name must be a string"))?
125            .to_string();
126
127        let ep = download::Request::builder()
128            .image_id(image_id)
129            .build()
130            .map_err(|x| OpenStackCliError::EndpointBuild(x.to_string()))?;
131        let (headers, data) = ep.download_async(client).await?;
132
133        let size: u64 = headers
134            .get("content-length")
135            .and_then(|x| {
136                x.to_str()
137                    .inspect_err(|e| {
138                        tracing::warn!("content-length header cannot be treated as string: {}", e)
139                    })
140                    .ok()
141            })
142            .unwrap_or("0")
143            .parse()
144            .inspect_err(|e| {
145                tracing::warn!("content-length header mut represent u64 number: {}", e)
146            })
147            .unwrap_or_default();
148        download_file(self.file.clone().unwrap_or(image_name), size, data).await?;
149        // Show command specific hints
150        op.show_command_hint()?;
151        Ok(())
152    }
153}