use clap::Args;
use eyre::WrapErr;
use tracing::info;
use openstack_sdk::AsyncOpenStack;
use crate::Cli;
use crate::OpenStackCliError;
use crate::output::OutputProcessor;
use openstack_sdk::api::QueryAsync;
use openstack_sdk::api::load_balancer::v2::loadbalancer::create;
use openstack_types::load_balancer::v2::loadbalancer::response::create::LoadbalancerResponse;
use serde_json::Value;
#[derive(Args)]
#[command(about = "Create a Load Balancer")]
pub struct LoadbalancerCommand {
#[command(flatten)]
query: QueryParameters,
#[command(flatten)]
path: PathParameters,
#[command(flatten)]
loadbalancer: Loadbalancer,
}
#[derive(Args)]
struct QueryParameters {}
#[derive(Args)]
struct PathParameters {}
#[derive(Args, Clone)]
struct Loadbalancer {
#[arg(action=clap::ArgAction::Append, help_heading = "Body parameters", long, value_name="JSON", value_parser=crate::common::parse_json)]
additional_vips: Option<Vec<Value>>,
#[arg(action=clap::ArgAction::Set, help_heading = "Body parameters", long)]
admin_state_up: Option<bool>,
#[arg(help_heading = "Body parameters", long)]
availability_zone: Option<String>,
#[arg(help_heading = "Body parameters", long)]
description: Option<String>,
#[arg(help_heading = "Body parameters", long)]
flavor_id: Option<String>,
#[arg(action=clap::ArgAction::Append, help_heading = "Body parameters", long, value_name="JSON", value_parser=crate::common::parse_json)]
listeners: Option<Vec<Value>>,
#[arg(help_heading = "Body parameters", long)]
name: Option<String>,
#[arg(action=clap::ArgAction::Append, help_heading = "Body parameters", long, value_name="JSON", value_parser=crate::common::parse_json)]
pools: Option<Vec<Value>>,
#[arg(help_heading = "Body parameters", long)]
project_id: Option<String>,
#[arg(help_heading = "Body parameters", long)]
provider: Option<String>,
#[arg(action=clap::ArgAction::Append, help_heading = "Body parameters", long)]
tags: Option<Vec<String>>,
#[arg(help_heading = "Body parameters", long)]
tenant_id: Option<String>,
#[arg(help_heading = "Body parameters", long)]
vip_address: Option<String>,
#[arg(help_heading = "Body parameters", long)]
vip_network_id: Option<String>,
#[arg(help_heading = "Body parameters", long)]
vip_port_id: Option<String>,
#[arg(help_heading = "Body parameters", long)]
vip_qos_policy_id: Option<String>,
#[arg(action=clap::ArgAction::Append, help_heading = "Body parameters", long)]
vip_sg_ids: Option<Vec<String>>,
#[arg(help_heading = "Body parameters", long)]
vip_subnet_id: Option<String>,
}
impl LoadbalancerCommand {
pub async fn take_action(
&self,
parsed_args: &Cli,
client: &mut AsyncOpenStack,
) -> Result<(), OpenStackCliError> {
info!("Create Loadbalancer");
let op = OutputProcessor::from_args(
parsed_args,
Some("load-balancer.loadbalancer"),
Some("create"),
);
op.validate_args(parsed_args)?;
let mut ep_builder = create::Request::builder();
let args = &self.loadbalancer;
let mut loadbalancer_builder = create::LoadbalancerBuilder::default();
if let Some(val) = &args.additional_vips {
let additional_vips_builder: Vec<create::AdditionalVips> = val
.iter()
.flat_map(|v| serde_json::from_value::<create::AdditionalVips>(v.to_owned()))
.collect::<Vec<create::AdditionalVips>>();
loadbalancer_builder.additional_vips(additional_vips_builder);
}
if let Some(val) = &args.admin_state_up {
loadbalancer_builder.admin_state_up(*val);
}
if let Some(val) = &args.availability_zone {
loadbalancer_builder.availability_zone(val);
}
if let Some(val) = &args.description {
loadbalancer_builder.description(val);
}
if let Some(val) = &args.flavor_id {
loadbalancer_builder.flavor_id(val);
}
if let Some(val) = &args.listeners {
let listeners_builder: Vec<create::Listeners> = val
.iter()
.flat_map(|v| serde_json::from_value::<create::Listeners>(v.to_owned()))
.collect::<Vec<create::Listeners>>();
loadbalancer_builder.listeners(listeners_builder);
}
if let Some(val) = &args.name {
loadbalancer_builder.name(val);
}
if let Some(val) = &args.pools {
let pools_builder: Vec<create::Pools> = val
.iter()
.flat_map(|v| serde_json::from_value::<create::Pools>(v.to_owned()))
.collect::<Vec<create::Pools>>();
loadbalancer_builder.pools(pools_builder);
}
if let Some(val) = &args.project_id {
loadbalancer_builder.project_id(val);
}
if let Some(val) = &args.provider {
loadbalancer_builder.provider(val);
}
if let Some(val) = &args.tags {
loadbalancer_builder.tags(val.iter().map(Into::into).collect::<Vec<_>>());
}
if let Some(val) = &args.tenant_id {
loadbalancer_builder.tenant_id(val);
}
if let Some(val) = &args.vip_address {
loadbalancer_builder.vip_address(val);
}
if let Some(val) = &args.vip_network_id {
loadbalancer_builder.vip_network_id(val);
}
if let Some(val) = &args.vip_port_id {
loadbalancer_builder.vip_port_id(val);
}
if let Some(val) = &args.vip_qos_policy_id {
loadbalancer_builder.vip_qos_policy_id(val);
}
if let Some(val) = &args.vip_sg_ids {
loadbalancer_builder.vip_sg_ids(val.iter().map(Into::into).collect::<Vec<_>>());
}
if let Some(val) = &args.vip_subnet_id {
loadbalancer_builder.vip_subnet_id(val);
}
ep_builder.loadbalancer(
loadbalancer_builder
.build()
.wrap_err("error preparing the request data")?,
);
let ep = ep_builder
.build()
.map_err(|x| OpenStackCliError::EndpointBuild(x.to_string()))?;
let data = ep.query_async(client).await?;
op.output_single::<LoadbalancerResponse>(data)?;
op.show_command_hint()?;
Ok(())
}
}