Skip to main content

openstack_cli_image/v2/image/
create.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//! Create Image command
19//!
20//! Wraps invoking of the `v2/images` with `POST` 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 clap::ValueEnum;
31use openstack_cli_core::common::parse_key_val;
32use openstack_sdk::api::QueryAsync;
33use openstack_sdk::api::image::v2::image::create;
34use openstack_types::image::v2::image::response;
35use serde_json::Value;
36
37/// Creates a catalog record for an operating system disk image. *(Since Image
38/// API v2.0)*
39///
40/// The `Location` response header contains the URI for the image.
41///
42/// A multiple store backend support is introduced in the Rocky release as a
43/// part of the EXPERIMENTAL Image API v2.8. Since Image API v2.8 a new header
44/// `OpenStack-image-store-ids` which contains the list of available stores
45/// will be included in response. This header is only included if multiple
46/// backend stores are supported.
47///
48/// The response body contains the new image entity.
49///
50/// Synchronous Postconditions
51///
52/// Normal response codes: 201
53///
54/// Error response codes: 400, 401, 403, 409, 413, 415
55#[derive(Args)]
56#[command(about = "Create image")]
57pub struct ImageCommand {
58    /// Request Query parameters
59    #[command(flatten)]
60    query: QueryParameters,
61
62    /// Path parameters
63    #[command(flatten)]
64    path: PathParameters,
65
66    /// Format of the image container.
67    ///
68    /// Values may vary based on the configuration available in a particular
69    /// OpenStack cloud. See the [Image Schema](#image-schema) response from
70    /// the cloud itself for the valid values available. See
71    /// [Container Format](https://docs.openstack.org/glance/latest/user/formats.html#container-format)
72    /// in the Glance documentation for more information.
73    ///
74    /// Example formats are: `ami`, `ari`, `aki`, `bare`, `ovf`, `ova`,
75    /// `docker`, or `compressed`.
76    ///
77    /// The value might be `null` (JSON null data type).
78    ///
79    /// **Train changes**: The `compressed` container format is a supported
80    /// value.
81    #[arg(help_heading = "Body parameters", long)]
82    container_format: Option<ContainerFormat>,
83
84    /// The format of the disk.
85    ///
86    /// Values may vary based on the configuration available in a particular
87    /// OpenStack cloud. See the [Image Schema](#image-schema) response from
88    /// the cloud itself for the valid values available. See
89    /// [Disk Format](https://docs.openstack.org/glance/latest/user/formats.html#disk-format)
90    /// in the Glance documentation for more information.
91    ///
92    /// Example formats are: `ami`, `ari`, `aki`, `vhd`, `vhdx`, `vmdk`, `raw`,
93    /// `qcow2`, `vdi`, `ploop` or `iso`.
94    ///
95    /// The value might be `null` (JSON null data type).
96    ///
97    /// **Newton changes**: The `vhdx` disk format is a supported value.\
98    /// **Ocata changes**: The `ploop` disk format is a supported value.
99    #[arg(help_heading = "Body parameters", long)]
100    disk_format: Option<DiskFormat>,
101
102    /// A unique, user-defined image UUID, in the format:
103    ///
104    /// ```text
105    /// nnnnnnnn-nnnn-nnnn-nnnn-nnnnnnnnnnnn
106    /// ```
107    ///
108    /// Where **n** is a hexadecimal digit from 0 to f, or F.
109    ///
110    /// For example:
111    ///
112    /// ```text
113    /// b2173dd3-7ad6-4362-baa6-a68bce3565cb
114    /// ```
115    ///
116    /// If you omit this value, the API generates a UUID for the image. If you
117    /// specify a value that has already been assigned, the request fails with
118    /// a `409` response code.
119    #[arg(help_heading = "Body parameters", long)]
120    id: Option<String>,
121
122    /// A set of URLs to access the image file kept in external store
123    ///
124    /// Parameter is an array, may be provided multiple times.
125    #[arg(action=clap::ArgAction::Append, help_heading = "Body parameters", long, value_name="JSON", value_parser=openstack_cli_core::common::parse_json)]
126    locations: Option<Vec<Value>>,
127
128    /// Amount of disk space in GB that is required to boot the image.
129    #[arg(help_heading = "Body parameters", long)]
130    min_disk: Option<i32>,
131
132    /// Amount of RAM in MB that is required to boot the image.
133    #[arg(help_heading = "Body parameters", long)]
134    min_ram: Option<i32>,
135
136    /// The name of the image.
137    #[arg(help_heading = "Body parameters", long)]
138    name: Option<String>,
139
140    /// If true, image will not appear in default image list response.
141    #[arg(action=clap::ArgAction::Set, help_heading = "Body parameters", long)]
142    os_hidden: Option<bool>,
143
144    /// Owner of the image
145    #[arg(help_heading = "Body parameters", long)]
146    owner: Option<String>,
147
148    /// Image protection for deletion. Valid value is `true` or `false`.
149    /// Default is `false`.
150    #[arg(action=clap::ArgAction::Set, help_heading = "Body parameters", long)]
151    protected: Option<bool>,
152
153    /// List of tags for this image. Each tag is a string of at most 255 chars.
154    /// The maximum number of tags allowed on an image is set by the operator.
155    ///
156    /// Parameter is an array, may be provided multiple times.
157    #[arg(action=clap::ArgAction::Append, help_heading = "Body parameters", long)]
158    tags: Option<Vec<String>>,
159
160    /// Visibility for this image. Valid value is one of: `public`, `private`,
161    /// `shared`, or `community`. At most sites, only an administrator can make
162    /// an image `public`. Some sites may restrict what users can make an image
163    /// `community`. Some sites may restrict what users can perform member
164    /// operations on a `shared` image. *Since the Image API v2.5, the default
165    /// value is `shared`.*
166    #[arg(help_heading = "Body parameters", long)]
167    visibility: Option<Visibility>,
168    /// Additional properties to be sent with the request
169    #[arg(long="property", value_name="key=value", value_parser=parse_key_val::<String, String>)]
170    #[arg(help_heading = "Body parameters")]
171    properties: Option<Vec<(String, String)>>,
172}
173
174/// Query parameters
175#[derive(Args)]
176struct QueryParameters {}
177
178/// Path parameters
179#[derive(Args)]
180struct PathParameters {}
181
182#[derive(Clone, Eq, Ord, PartialEq, PartialOrd, ValueEnum)]
183enum ContainerFormat {
184    Aki,
185    Ami,
186    Ari,
187    Bare,
188    Compressed,
189    Docker,
190    Ova,
191    Ovf,
192}
193
194#[derive(Clone, Eq, Ord, PartialEq, PartialOrd, ValueEnum)]
195enum DiskFormat {
196    Aki,
197    Ami,
198    Ari,
199    Iso,
200    Ploop,
201    Qcow2,
202    Raw,
203    Vdi,
204    Vhd,
205    Vhdx,
206    Vmdk,
207}
208
209#[derive(Clone, Eq, Ord, PartialEq, PartialOrd, ValueEnum)]
210enum Visibility {
211    Community,
212    Private,
213    Public,
214    Shared,
215}
216
217impl ImageCommand {
218    /// Perform command action
219    pub async fn take_action<C: CliArgs>(
220        &self,
221        parsed_args: &C,
222        client: &mut AsyncOpenStack,
223    ) -> Result<(), OpenStackCliError> {
224        info!("Create Image");
225
226        let op = OutputProcessor::from_args(parsed_args, Some("image.image"), Some("create"));
227        op.validate_args(parsed_args)?;
228
229        let mut ep_builder = create::Request::builder();
230
231        // Set body parameters
232        // Set Request.container_format data
233        if let Some(arg) = &self.container_format {
234            let tmp = match arg {
235                ContainerFormat::Aki => create::ContainerFormat::Aki,
236                ContainerFormat::Ami => create::ContainerFormat::Ami,
237                ContainerFormat::Ari => create::ContainerFormat::Ari,
238                ContainerFormat::Bare => create::ContainerFormat::Bare,
239                ContainerFormat::Compressed => create::ContainerFormat::Compressed,
240                ContainerFormat::Docker => create::ContainerFormat::Docker,
241                ContainerFormat::Ova => create::ContainerFormat::Ova,
242                ContainerFormat::Ovf => create::ContainerFormat::Ovf,
243            };
244            ep_builder.container_format(tmp);
245        }
246
247        // Set Request.disk_format data
248        if let Some(arg) = &self.disk_format {
249            let tmp = match arg {
250                DiskFormat::Aki => create::DiskFormat::Aki,
251                DiskFormat::Ami => create::DiskFormat::Ami,
252                DiskFormat::Ari => create::DiskFormat::Ari,
253                DiskFormat::Iso => create::DiskFormat::Iso,
254                DiskFormat::Ploop => create::DiskFormat::Ploop,
255                DiskFormat::Qcow2 => create::DiskFormat::Qcow2,
256                DiskFormat::Raw => create::DiskFormat::Raw,
257                DiskFormat::Vdi => create::DiskFormat::Vdi,
258                DiskFormat::Vhd => create::DiskFormat::Vhd,
259                DiskFormat::Vhdx => create::DiskFormat::Vhdx,
260                DiskFormat::Vmdk => create::DiskFormat::Vmdk,
261            };
262            ep_builder.disk_format(tmp);
263        }
264
265        // Set Request.id data
266        if let Some(arg) = &self.id {
267            ep_builder.id(arg);
268        }
269
270        // Set Request.locations data
271        if let Some(arg) = &self.locations {
272            let locations_builder: Vec<create::Locations> = arg
273                .iter()
274                .flat_map(|v| serde_json::from_value::<create::Locations>(v.to_owned()))
275                .collect::<Vec<create::Locations>>();
276            ep_builder.locations(locations_builder);
277        }
278
279        // Set Request.min_disk data
280        if let Some(arg) = &self.min_disk {
281            ep_builder.min_disk(*arg);
282        }
283
284        // Set Request.min_ram data
285        if let Some(arg) = &self.min_ram {
286            ep_builder.min_ram(*arg);
287        }
288
289        // Set Request.name data
290        if let Some(arg) = &self.name {
291            ep_builder.name(Some(arg.into()));
292        }
293
294        // Set Request.os_hidden data
295        if let Some(arg) = &self.os_hidden {
296            ep_builder.os_hidden(*arg);
297        }
298
299        // Set Request.owner data
300        if let Some(arg) = &self.owner {
301            ep_builder.owner(Some(arg.into()));
302        }
303
304        // Set Request.protected data
305        if let Some(arg) = &self.protected {
306            ep_builder.protected(*arg);
307        }
308
309        // Set Request.tags data
310        if let Some(arg) = &self.tags {
311            ep_builder.tags(arg.iter().map(Into::into).collect::<Vec<_>>());
312        }
313
314        // Set Request.visibility data
315        if let Some(arg) = &self.visibility {
316            let tmp = match arg {
317                Visibility::Community => create::Visibility::Community,
318                Visibility::Private => create::Visibility::Private,
319                Visibility::Public => create::Visibility::Public,
320                Visibility::Shared => create::Visibility::Shared,
321            };
322            ep_builder.visibility(tmp);
323        }
324
325        if let Some(properties) = &self.properties {
326            ep_builder.properties(properties.iter().cloned());
327        }
328
329        let ep = ep_builder
330            .build()
331            .map_err(|x| OpenStackCliError::EndpointBuild(x.to_string()))?;
332
333        let data: serde_json::Value = ep.query_async(client).await?;
334
335        op.output_single::<response::create::ImageResponse>(data.clone())?;
336        // Show command specific hints
337        op.show_command_hint()?;
338        Ok(())
339    }
340}