openstack_cli_image/v2/image/file/upload.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//! Upload File command
19//!
20//! Wraps invoking of the `v2/images/{image_id}/file` with `PUT` 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::build_upload_asyncread;
31use openstack_sdk::api::RawQueryAsync;
32use openstack_sdk::api::image::v2::image::file::upload;
33
34/// Uploads binary image data. *(Since Image API v2.0)*
35///
36/// Set the `Content-Type` request header to `application/octet-stream`.
37///
38/// A multiple store backend support is introduced in the Rocky release as a
39/// part of the EXPERIMENTAL Image API v2.8.
40///
41/// Beginning with API version 2.8, an optional `X-Image-Meta-Store` header may
42/// be added to the request. When present, the image data will be placed into
43/// the backing store whose identifier is the value of this header. If the
44/// store identifier specified is not recognized, a 400 (Bad Request) response
45/// is returned. When the header is not present, the image data is placed into
46/// the default backing store.
47///
48/// An optional `x-openstack-image-size` header may be added to the request.
49/// When present, the server will validate that the uploaded data size matches
50/// this value. If the actual size does not match the expected size, a 400 (Bad
51/// Request) response is returned. When not present, the server will calculate
52/// the image size based on the actual request body size.
53///
54/// Example call:
55///
56/// **Preconditions**
57///
58/// Before you can store binary image data, you must meet the following
59/// preconditions:
60///
61/// **Synchronous Postconditions**
62///
63/// **Troubleshooting**
64///
65/// Normal response codes: 204
66///
67/// Error response codes: 400, 401, 403, 404, 409, 410, 413, 415, 503
68#[derive(Args)]
69#[command(about = "Upload binary image data")]
70pub struct FileCommand {
71 /// Request Query parameters
72 #[command(flatten)]
73 query: QueryParameters,
74
75 /// Request Headers parameters
76 #[command(flatten)]
77 headers: HeaderParameters,
78
79 /// Path parameters
80 #[command(flatten)]
81 path: PathParameters,
82
83 /// Source filename (using "-" will read object from stdout)
84 #[arg(long)]
85 file: Option<String>,
86}
87
88/// Query parameters
89#[derive(Args)]
90struct QueryParameters {}
91
92/// Header parameters
93#[derive(Args)]
94struct HeaderParameters {
95 /// The media type descriptor of the body, namely application/octet-stream
96 #[arg(long)]
97 content_type: Option<String>,
98
99 /// A store identifier to upload or import image data. Should only be
100 /// included when making a request to a cloud that supports multiple
101 /// backing stores. Use the Store Discovery call to determine an
102 /// appropriate store identifier. Simply omit this header to use the
103 /// default store.
104 #[arg(long)]
105 x_image_meta_store: Option<String>,
106}
107
108/// Path parameters
109#[derive(Args)]
110struct PathParameters {
111 /// image_id parameter for /v2/images/{image_id}/file API
112 #[arg(
113 help_heading = "Path parameters",
114 id = "path_param_image_id",
115 value_name = "IMAGE_ID"
116 )]
117 image_id: String,
118}
119
120impl FileCommand {
121 /// Perform command action
122 pub async fn take_action<C: CliArgs>(
123 &self,
124 parsed_args: &C,
125 client: &mut AsyncOpenStack,
126 ) -> Result<(), OpenStackCliError> {
127 info!("Upload File");
128
129 let op = OutputProcessor::from_args(parsed_args, Some("image.image/file"), Some("upload"));
130 op.validate_args(parsed_args)?;
131
132 let mut ep_builder = upload::Request::builder();
133 // Set path parameters
134 ep_builder.image_id(&self.path.image_id);
135
136 // Set header parameters
137 if let Some(val) = &self.headers.content_type {
138 ep_builder.header(
139 http::header::HeaderName::from_static("Content-Type"),
140 http::header::HeaderValue::from_str(val)?,
141 );
142 }
143 if let Some(val) = &self.headers.x_image_meta_store {
144 ep_builder.header(
145 http::header::HeaderName::from_static("X-Image-Meta-Store"),
146 http::header::HeaderValue::from_str(val)?,
147 );
148 }
149
150 // The only supported media type
151 ep_builder.header(
152 http::header::CONTENT_TYPE,
153 http::header::HeaderValue::from_static("application/octet-stream"),
154 );
155
156 let ep = ep_builder
157 .build()
158 .map_err(|x| OpenStackCliError::EndpointBuild(x.to_string()))?;
159 let dst = self.file.clone();
160 let data = build_upload_asyncread(dst).await?;
161
162 let _rsp = ep.raw_query_read_body_async(client, data).await?;
163 // TODO: what if there is an interesting response
164 // Show command specific hints
165 op.show_command_hint()?;
166 Ok(())
167 }
168}