// WARNING: generated by kopium - manual changes will be overwritten
// kopium command: kopium -D Default -D PartialEq -A -d openstackclustertemplates.infrastructure.cluster.x-k8s.io
// kopium version: 0.21.1

#[allow(unused_imports)]
mod prelude {
    pub use kube::CustomResource;
    pub use schemars::JsonSchema;
    pub use serde::{Deserialize, Serialize};
}
use self::prelude::*;

/// OpenStackClusterTemplateSpec defines the desired state of OpenStackClusterTemplate.
#[derive(CustomResource, Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
#[kube(
    group = "infrastructure.cluster.x-k8s.io",
    version = "v1beta1",
    kind = "OpenStackClusterTemplate",
    plural = "openstackclustertemplates"
)]
#[kube(namespaced)]
#[kube(derive = "Default")]
#[kube(derive = "PartialEq")]
pub struct OpenStackClusterTemplateSpec {
    /// OpenStackClusterTemplateResource describes the data needed to create a OpenStackCluster from a template.
    pub template: OpenStackClusterTemplateTemplate,
}

/// OpenStackClusterTemplateResource describes the data needed to create a OpenStackCluster from a template.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct OpenStackClusterTemplateTemplate {
    /// OpenStackClusterSpec defines the desired state of OpenStackCluster.
    pub spec: OpenStackClusterTemplateTemplateSpec,
}

/// OpenStackClusterSpec defines the desired state of OpenStackCluster.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct OpenStackClusterTemplateTemplateSpec {
    /// APIServerFixedIP is the fixed IP which will be associated with the API server.
    /// In the case where the API server has a floating IP but not a managed load balancer,
    /// this field is not used.
    /// If a managed load balancer is used and this field is not specified, a fixed IP will
    /// be dynamically allocated for the load balancer.
    /// If a managed load balancer is not used AND the API server floating IP is disabled,
    /// this field MUST be specified and should correspond to a pre-allocated port that
    /// holds the fixed IP to be used as a VIP.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "apiServerFixedIP"
    )]
    pub api_server_fixed_ip: Option<String>,
    /// APIServerFloatingIP is the floatingIP which will be associated with the API server.
    /// The floatingIP will be created if it does not already exist.
    /// If not specified, a new floatingIP is allocated.
    /// This field is not used if DisableAPIServerFloatingIP is set to true.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "apiServerFloatingIP"
    )]
    pub api_server_floating_ip: Option<String>,
    /// APIServerLoadBalancer configures the optional LoadBalancer for the APIServer.
    /// If not specified, no load balancer will be created for the API server.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "apiServerLoadBalancer"
    )]
    pub api_server_load_balancer: Option<OpenStackClusterTemplateTemplateSpecApiServerLoadBalancer>,
    /// APIServerPort is the port on which the listener on the APIServer
    /// will be created. If specified, it must be an integer between 0 and 65535.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "apiServerPort"
    )]
    pub api_server_port: Option<i64>,
    /// Bastion is the OpenStack instance to login the nodes
    ///
    /// As a rolling update is not ideal during a bastion host session, we
    /// prevent changes to a running bastion configuration. To make changes, it's required
    /// to first set `enabled: false` which will remove the bastion and then changes can be made.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub bastion: Option<OpenStackClusterTemplateTemplateSpecBastion>,
    /// ControlPlaneAvailabilityZones is the set of availability zones which
    /// control plane machines may be deployed to.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "controlPlaneAvailabilityZones"
    )]
    pub control_plane_availability_zones: Option<Vec<String>>,
    /// ControlPlaneEndpoint represents the endpoint used to communicate with the control plane.
    /// It is normally populated automatically by the OpenStackCluster
    /// controller during cluster provisioning. If it is set on creation the
    /// control plane endpoint will use the values set here in preference to
    /// values set elsewhere.
    /// ControlPlaneEndpoint cannot be modified after ControlPlaneEndpoint.Host has been set.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "controlPlaneEndpoint"
    )]
    pub control_plane_endpoint: Option<OpenStackClusterTemplateTemplateSpecControlPlaneEndpoint>,
    /// ControlPlaneOmitAvailabilityZone causes availability zone to be
    /// omitted when creating control plane nodes, allowing the Nova
    /// scheduler to make a decision on which availability zone to use based
    /// on other scheduling constraints
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "controlPlaneOmitAvailabilityZone"
    )]
    pub control_plane_omit_availability_zone: Option<bool>,
    /// DisableAPIServerFloatingIP determines whether or not to attempt to attach a floating
    /// IP to the API server. This allows for the creation of clusters when attaching a floating
    /// IP to the API server (and hence, in many cases, exposing the API server to the internet)
    /// is not possible or desirable, e.g. if using a shared VLAN for communication between
    /// management and workload clusters or when the management cluster is inside the
    /// project network.
    /// This option requires that the API server use a VIP on the cluster network so that the
    /// underlying machines can change without changing ControlPlaneEndpoint.Host.
    /// When using a managed load balancer, this VIP will be managed automatically.
    /// If not using a managed load balancer, cluster configuration will fail without additional
    /// configuration to manage the VIP on the control plane machines, which falls outside of
    /// the scope of this controller.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "disableAPIServerFloatingIP"
    )]
    pub disable_api_server_floating_ip: Option<bool>,
    /// DisableExternalNetwork specifies whether or not to attempt to connect the cluster
    /// to an external network. This allows for the creation of clusters when connecting
    /// to an external network is not possible or desirable, e.g. if using a provider network.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "disableExternalNetwork"
    )]
    pub disable_external_network: Option<bool>,
    /// DisablePortSecurity disables the port security of the network created for the
    /// Kubernetes cluster, which also disables SecurityGroups
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "disablePortSecurity"
    )]
    pub disable_port_security: Option<bool>,
    /// ExternalNetwork is the OpenStack Network to be used to get public internet to the VMs.
    /// This option is ignored if DisableExternalNetwork is set to true.
    ///
    /// If ExternalNetwork is defined it must refer to exactly one external network.
    ///
    /// If ExternalNetwork is not defined or is empty the controller will use any
    /// existing external network as long as there is only one. It is an
    /// error if ExternalNetwork is not defined and there are multiple
    /// external networks unless DisableExternalNetwork is also set.
    ///
    /// If ExternalNetwork is not defined and there are no external networks
    /// the controller will proceed as though DisableExternalNetwork was set.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "externalNetwork"
    )]
    pub external_network: Option<OpenStackClusterTemplateTemplateSpecExternalNetwork>,
    /// ExternalRouterIPs is an array of externalIPs on the respective subnets.
    /// This is necessary if the router needs a fixed ip in a specific subnet.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "externalRouterIPs"
    )]
    pub external_router_i_ps: Option<Vec<OpenStackClusterTemplateTemplateSpecExternalRouterIPs>>,
    /// IdentityRef is a reference to a secret holding OpenStack credentials
    /// to be used when reconciling this cluster. It is also to reconcile
    /// machines unless overridden in the machine spec.
    #[serde(rename = "identityRef")]
    pub identity_ref: OpenStackClusterTemplateTemplateSpecIdentityRef,
    /// ManagedSecurityGroups determines whether OpenStack security groups for the cluster
    /// will be managed by the OpenStack provider or whether pre-existing security groups will
    /// be specified as part of the configuration.
    /// By default, the managed security groups have rules that allow the Kubelet, etcd, and the
    /// Kubernetes API server to function correctly.
    /// It's possible to add additional rules to the managed security groups.
    /// When defined to an empty struct, the managed security groups will be created with the default rules.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "managedSecurityGroups"
    )]
    pub managed_security_groups: Option<OpenStackClusterTemplateTemplateSpecManagedSecurityGroups>,
    /// ManagedSubnets describe OpenStack Subnets to be created. Cluster actuator will create a network,
    /// subnets with the defined CIDR, and a router connected to these subnets. Currently only one IPv4
    /// subnet is supported. If you leave this empty, no network will be created.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "managedSubnets"
    )]
    pub managed_subnets: Option<Vec<OpenStackClusterTemplateTemplateSpecManagedSubnets>>,
    /// Network specifies an existing network to use if no ManagedSubnets
    /// are specified.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub network: Option<OpenStackClusterTemplateTemplateSpecNetwork>,
    /// NetworkMTU sets the maximum transmission unit (MTU) value to address fragmentation for the private network ID.
    /// This value will be used only if the Cluster actuator creates the network.
    /// If left empty, the network will have the default MTU defined in Openstack network service.
    /// To use this field, the Openstack installation requires the net-mtu neutron API extension.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "networkMTU"
    )]
    pub network_mtu: Option<i64>,
    /// Router specifies an existing router to be used if ManagedSubnets are
    /// specified. If specified, no new router will be created.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub router: Option<OpenStackClusterTemplateTemplateSpecRouter>,
    /// Subnets specifies existing subnets to use if not ManagedSubnets are
    /// specified. All subnets must be in the network specified by Network.
    /// There can be zero, one, or two subnets. If no subnets are specified,
    /// all subnets in Network will be used. If 2 subnets are specified, one
    /// must be IPv4 and the other IPv6.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub subnets: Option<Vec<OpenStackClusterTemplateTemplateSpecSubnets>>,
    /// Tags to set on all resources in cluster which support tags
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub tags: Option<Vec<String>>,
}

/// APIServerLoadBalancer configures the optional LoadBalancer for the APIServer.
/// If not specified, no load balancer will be created for the API server.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct OpenStackClusterTemplateTemplateSpecApiServerLoadBalancer {
    /// AdditionalPorts adds additional tcp ports to the load balancer.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "additionalPorts"
    )]
    pub additional_ports: Option<Vec<i64>>,
    /// AllowedCIDRs restrict access to all API-Server listeners to the given address CIDRs.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "allowedCIDRs"
    )]
    pub allowed_cid_rs: Option<Vec<String>>,
    /// AvailabilityZone is the failure domain that will be used to create the APIServerLoadBalancer Spec.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "availabilityZone"
    )]
    pub availability_zone: Option<String>,
    /// Enabled defines whether a load balancer should be created. This value
    /// defaults to true if an APIServerLoadBalancer is given.
    ///
    /// There is no reason to set this to false. To disable creation of the
    /// API server loadbalancer, omit the APIServerLoadBalancer field in the
    /// cluster spec instead.
    pub enabled: bool,
    /// Flavor is the flavor name that will be used to create the APIServerLoadBalancer Spec.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub flavor: Option<String>,
    /// Network defines which network should the load balancer be allocated on.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub network: Option<OpenStackClusterTemplateTemplateSpecApiServerLoadBalancerNetwork>,
    /// Provider specifies name of a specific Octavia provider to use for the
    /// API load balancer. The Octavia default will be used if it is not
    /// specified.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub provider: Option<String>,
    /// Subnets define which subnets should the load balancer be allocated on.
    /// It is expected that subnets are located on the network specified in this resource.
    /// Only the first element is taken into account.
    /// kubebuilder:validation:MaxLength:=2
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub subnets: Option<Vec<OpenStackClusterTemplateTemplateSpecApiServerLoadBalancerSubnets>>,
}

/// Network defines which network should the load balancer be allocated on.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct OpenStackClusterTemplateTemplateSpecApiServerLoadBalancerNetwork {
    /// Filter specifies a filter to select an OpenStack network. If provided, cannot be empty.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub filter: Option<OpenStackClusterTemplateTemplateSpecApiServerLoadBalancerNetworkFilter>,
    /// ID is the ID of the network to use. If ID is provided, the other filters cannot be provided. Must be in UUID format.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub id: Option<String>,
}

/// Filter specifies a filter to select an OpenStack network. If provided, cannot be empty.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct OpenStackClusterTemplateTemplateSpecApiServerLoadBalancerNetworkFilter {
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub description: Option<String>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub name: Option<String>,
    /// NotTags is a list of tags to filter by. If specified, resources which
    /// contain all of the given tags will be excluded from the result.
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "notTags")]
    pub not_tags: Option<Vec<String>>,
    /// NotTagsAny is a list of tags to filter by. If specified, resources
    /// which contain any of the given tags will be excluded from the result.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "notTagsAny"
    )]
    pub not_tags_any: Option<Vec<String>>,
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "projectID")]
    pub project_id: Option<String>,
    /// Tags is a list of tags to filter by. If specified, the resource must
    /// have all of the tags specified to be included in the result.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub tags: Option<Vec<String>>,
    /// TagsAny is a list of tags to filter by. If specified, the resource
    /// must have at least one of the tags specified to be included in the
    /// result.
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "tagsAny")]
    pub tags_any: Option<Vec<String>>,
}

/// SubnetParam specifies an OpenStack subnet to use. It may be specified by either ID or filter, but not both.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct OpenStackClusterTemplateTemplateSpecApiServerLoadBalancerSubnets {
    /// Filter specifies a filter to select the subnet. It must match exactly one subnet.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub filter: Option<OpenStackClusterTemplateTemplateSpecApiServerLoadBalancerSubnetsFilter>,
    /// ID is the uuid of the subnet. It will not be validated.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub id: Option<String>,
}

/// Filter specifies a filter to select the subnet. It must match exactly one subnet.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct OpenStackClusterTemplateTemplateSpecApiServerLoadBalancerSubnetsFilter {
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub cidr: Option<String>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub description: Option<String>,
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "gatewayIP")]
    pub gateway_ip: Option<String>,
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "ipVersion")]
    pub ip_version: Option<i64>,
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "ipv6AddressMode"
    )]
    pub ipv6_address_mode: Option<String>,
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "ipv6RAMode"
    )]
    pub ipv6_ra_mode: Option<String>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub name: Option<String>,
    /// NotTags is a list of tags to filter by. If specified, resources which
    /// contain all of the given tags will be excluded from the result.
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "notTags")]
    pub not_tags: Option<Vec<String>>,
    /// NotTagsAny is a list of tags to filter by. If specified, resources
    /// which contain any of the given tags will be excluded from the result.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "notTagsAny"
    )]
    pub not_tags_any: Option<Vec<String>>,
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "projectID")]
    pub project_id: Option<String>,
    /// Tags is a list of tags to filter by. If specified, the resource must
    /// have all of the tags specified to be included in the result.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub tags: Option<Vec<String>>,
    /// TagsAny is a list of tags to filter by. If specified, the resource
    /// must have at least one of the tags specified to be included in the
    /// result.
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "tagsAny")]
    pub tags_any: Option<Vec<String>>,
}

/// Bastion is the OpenStack instance to login the nodes
///
/// As a rolling update is not ideal during a bastion host session, we
/// prevent changes to a running bastion configuration. To make changes, it's required
/// to first set `enabled: false` which will remove the bastion and then changes can be made.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct OpenStackClusterTemplateTemplateSpecBastion {
    /// AvailabilityZone is the failure domain that will be used to create the Bastion Spec.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "availabilityZone"
    )]
    pub availability_zone: Option<String>,
    /// Enabled means that bastion is enabled. The bastion is enabled by
    /// default if this field is not specified. Set this field to false to disable the
    /// bastion.
    ///
    /// It is not currently possible to remove the bastion from the cluster
    /// spec without first disabling it by setting this field to false and
    /// waiting until the bastion has been deleted.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub enabled: Option<bool>,
    /// FloatingIP which will be associated to the bastion machine. It's the IP address, not UUID.
    /// The floating IP should already exist and should not be associated with a port. If FIP of this address does not
    /// exist, CAPO will try to create it, but by default only OpenStack administrators have privileges to do so.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "floatingIP"
    )]
    pub floating_ip: Option<String>,
    /// Spec for the bastion itself
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub spec: Option<OpenStackClusterTemplateTemplateSpecBastionSpec>,
}

/// Spec for the bastion itself
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct OpenStackClusterTemplateTemplateSpecBastionSpec {
    /// AdditionalBlockDevices is a list of specifications for additional block devices to attach to the server instance
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "additionalBlockDevices"
    )]
    pub additional_block_devices:
        Option<Vec<OpenStackClusterTemplateTemplateSpecBastionSpecAdditionalBlockDevices>>,
    /// Config Drive support
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "configDrive"
    )]
    pub config_drive: Option<bool>,
    /// The flavor reference for the flavor for your server instance.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub flavor: Option<String>,
    /// FlavorID allows flavors to be specified by ID.  This field takes precedence
    /// over Flavor.
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "flavorID")]
    pub flavor_id: Option<String>,
    /// floatingIPPoolRef is a reference to a IPPool that will be assigned
    /// to an IPAddressClaim. Once the IPAddressClaim is fulfilled, the FloatingIP
    /// will be assigned to the OpenStackMachine.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "floatingIPPoolRef"
    )]
    pub floating_ip_pool_ref:
        Option<OpenStackClusterTemplateTemplateSpecBastionSpecFloatingIpPoolRef>,
    /// IdentityRef is a reference to a secret holding OpenStack credentials
    /// to be used when reconciling this machine. If not specified, the
    /// credentials specified in the cluster will be used.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "identityRef"
    )]
    pub identity_ref: Option<OpenStackClusterTemplateTemplateSpecBastionSpecIdentityRef>,
    /// The image to use for your server instance.
    /// If the rootVolume is specified, this will be used when creating the root volume.
    pub image: OpenStackClusterTemplateTemplateSpecBastionSpecImage,
    /// Ports to be attached to the server instance. They are created if a port with the given name does not already exist.
    /// If not specified a default port will be added for the default cluster network.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub ports: Option<Vec<OpenStackClusterTemplateTemplateSpecBastionSpecPorts>>,
    /// ProviderID is the unique identifier as specified by the cloud provider.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "providerID"
    )]
    pub provider_id: Option<String>,
    /// The volume metadata to boot from
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "rootVolume"
    )]
    pub root_volume: Option<OpenStackClusterTemplateTemplateSpecBastionSpecRootVolume>,
    /// SchedulerHintAdditionalProperties are arbitrary key/value pairs that provide additional hints
    /// to the OpenStack scheduler. These hints can influence how instances are placed on the infrastructure,
    /// such as specifying certain host aggregates or availability zones.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "schedulerHintAdditionalProperties"
    )]
    pub scheduler_hint_additional_properties: Option<
        Vec<OpenStackClusterTemplateTemplateSpecBastionSpecSchedulerHintAdditionalProperties>,
    >,
    /// The names of the security groups to assign to the instance
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "securityGroups"
    )]
    pub security_groups: Option<Vec<OpenStackClusterTemplateTemplateSpecBastionSpecSecurityGroups>>,
    /// The server group to assign the machine to.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "serverGroup"
    )]
    pub server_group: Option<OpenStackClusterTemplateTemplateSpecBastionSpecServerGroup>,
    /// Metadata mapping. Allows you to create a map of key value pairs to add to the server instance.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "serverMetadata"
    )]
    pub server_metadata: Option<Vec<OpenStackClusterTemplateTemplateSpecBastionSpecServerMetadata>>,
    /// The ssh key to inject in the instance
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "sshKeyName"
    )]
    pub ssh_key_name: Option<String>,
    /// Tags which will be added to the machine and all dependent resources
    /// which support them. These are in addition to Tags defined on the
    /// cluster.
    /// Requires Nova api 2.52 minimum!
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub tags: Option<Vec<String>>,
    /// Whether the server instance is created on a trunk port or not.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub trunk: Option<bool>,
}

/// AdditionalBlockDevice is a block device to attach to the server.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct OpenStackClusterTemplateTemplateSpecBastionSpecAdditionalBlockDevices {
    /// Name of the block device in the context of a machine.
    /// If the block device is a volume, the Cinder volume will be named
    /// as a combination of the machine name and this name.
    /// Also, this name will be used for tagging the block device.
    /// Information about the block device tag can be obtained from the OpenStack
    /// metadata API or the config drive.
    /// Name cannot be 'root', which is reserved for the root volume.
    pub name: String,
    /// SizeGiB is the size of the block device in gibibytes (GiB).
    #[serde(rename = "sizeGiB")]
    pub size_gi_b: i64,
    /// Storage specifies the storage type of the block device and
    /// additional storage options.
    pub storage: OpenStackClusterTemplateTemplateSpecBastionSpecAdditionalBlockDevicesStorage,
}

/// Storage specifies the storage type of the block device and
/// additional storage options.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct OpenStackClusterTemplateTemplateSpecBastionSpecAdditionalBlockDevicesStorage {
    /// Type is the type of block device to create.
    /// This can be either "Volume" or "Local".
    #[serde(rename = "type")]
    pub r#type: String,
    /// Volume contains additional storage options for a volume block device.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub volume:
        Option<OpenStackClusterTemplateTemplateSpecBastionSpecAdditionalBlockDevicesStorageVolume>,
}

/// Volume contains additional storage options for a volume block device.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct OpenStackClusterTemplateTemplateSpecBastionSpecAdditionalBlockDevicesStorageVolume {
    /// AvailabilityZone is the volume availability zone to create the volume
    /// in. If not specified, the volume will be created without an explicit
    /// availability zone.
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "availabilityZone")]
    pub availability_zone: Option<OpenStackClusterTemplateTemplateSpecBastionSpecAdditionalBlockDevicesStorageVolumeAvailabilityZone>,
    /// Type is the Cinder volume type of the volume.
    /// If omitted, the default Cinder volume type that is configured in the OpenStack cloud
    /// will be used.
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "type")]
    pub r#type: Option<String>,
}

/// AvailabilityZone is the volume availability zone to create the volume
/// in. If not specified, the volume will be created without an explicit
/// availability zone.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct OpenStackClusterTemplateTemplateSpecBastionSpecAdditionalBlockDevicesStorageVolumeAvailabilityZone {
    /// From specifies where we will obtain the availability zone for the
    /// volume. The options are "Name" and "Machine". If "Name" is specified
    /// then the Name field must also be specified. If "Machine" is specified
    /// the volume will use the value of FailureDomain, if any, from the
    /// associated Machine.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub from: Option<OpenStackClusterTemplateTemplateSpecBastionSpecAdditionalBlockDevicesStorageVolumeAvailabilityZoneFrom>,
    /// Name is the name of a volume availability zone to use. It is required
    /// if From is "Name". The volume availability zone name may not contain
    /// spaces.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub name: Option<String>,
}

/// AvailabilityZone is the volume availability zone to create the volume
/// in. If not specified, the volume will be created without an explicit
/// availability zone.
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub enum OpenStackClusterTemplateTemplateSpecBastionSpecAdditionalBlockDevicesStorageVolumeAvailabilityZoneFrom
{
    Name,
    Machine,
}

/// floatingIPPoolRef is a reference to a IPPool that will be assigned
/// to an IPAddressClaim. Once the IPAddressClaim is fulfilled, the FloatingIP
/// will be assigned to the OpenStackMachine.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct OpenStackClusterTemplateTemplateSpecBastionSpecFloatingIpPoolRef {
    /// APIGroup is the group for the resource being referenced.
    /// If APIGroup is not specified, the specified Kind must be in the core API group.
    /// For any other third-party types, APIGroup is required.
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "apiGroup")]
    pub api_group: Option<String>,
    /// Kind is the type of resource being referenced
    pub kind: String,
    /// Name is the name of resource being referenced
    pub name: String,
}

/// IdentityRef is a reference to a secret holding OpenStack credentials
/// to be used when reconciling this machine. If not specified, the
/// credentials specified in the cluster will be used.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct OpenStackClusterTemplateTemplateSpecBastionSpecIdentityRef {
    /// CloudName specifies the name of the entry in the clouds.yaml file to use.
    #[serde(rename = "cloudName")]
    pub cloud_name: String,
    /// Name is the name of a secret in the same namespace as the resource being provisioned.
    /// The secret must contain a key named `clouds.yaml` which contains an OpenStack clouds.yaml file.
    /// The secret may optionally contain a key named `cacert` containing a PEM-encoded CA certificate.
    pub name: String,
    /// Region specifies an OpenStack region to use. If specified, it overrides
    /// any value in clouds.yaml. If specified for an OpenStackMachine, its
    /// value will be included in providerID.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub region: Option<String>,
}

/// The image to use for your server instance.
/// If the rootVolume is specified, this will be used when creating the root volume.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct OpenStackClusterTemplateTemplateSpecBastionSpecImage {
    /// Filter describes a query for an image. If specified, the combination
    /// of name and tags must return a single matching image or an error will
    /// be raised.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub filter: Option<OpenStackClusterTemplateTemplateSpecBastionSpecImageFilter>,
    /// ID is the uuid of the image. ID will not be validated before use.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub id: Option<String>,
    /// ImageRef is a reference to an ORC Image in the same namespace as the
    /// referring object.
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "imageRef")]
    pub image_ref: Option<OpenStackClusterTemplateTemplateSpecBastionSpecImageImageRef>,
}

/// Filter describes a query for an image. If specified, the combination
/// of name and tags must return a single matching image or an error will
/// be raised.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct OpenStackClusterTemplateTemplateSpecBastionSpecImageFilter {
    /// The name of the desired image. If specified, the combination of name and tags must return a single matching image or an error will be raised.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub name: Option<String>,
    /// The tags associated with the desired image. If specified, the combination of name and tags must return a single matching image or an error will be raised.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub tags: Option<Vec<String>>,
}

/// ImageRef is a reference to an ORC Image in the same namespace as the
/// referring object.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct OpenStackClusterTemplateTemplateSpecBastionSpecImageImageRef {
    /// Name is the name of the referenced resource
    pub name: String,
}

#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct OpenStackClusterTemplateTemplateSpecBastionSpecPorts {
    /// AdminStateUp specifies whether the port should be created in the up (true) or down (false) state. The default is up.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "adminStateUp"
    )]
    pub admin_state_up: Option<bool>,
    /// AllowedAddressPairs is a list of address pairs which Neutron will
    /// allow the port to send traffic from in addition to the port's
    /// addresses. If not specified, the MAC Address will be the MAC Address
    /// of the port. Depending on the configuration of Neutron, it may be
    /// supported to specify a CIDR instead of a specific IP address.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "allowedAddressPairs"
    )]
    pub allowed_address_pairs:
        Option<Vec<OpenStackClusterTemplateTemplateSpecBastionSpecPortsAllowedAddressPairs>>,
    /// Description is a human-readable description for the port.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub description: Option<String>,
    /// DisablePortSecurity enables or disables the port security when set.
    /// When not set, it takes the value of the corresponding field at the network level.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "disablePortSecurity"
    )]
    pub disable_port_security: Option<bool>,
    /// FixedIPs is a list of pairs of subnet and/or IP address to assign to the port. If specified, these must be subnets of the port's network.
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "fixedIPs")]
    pub fixed_i_ps: Option<Vec<OpenStackClusterTemplateTemplateSpecBastionSpecPortsFixedIPs>>,
    /// HostID specifies the ID of the host where the port resides.
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "hostID")]
    pub host_id: Option<String>,
    /// MACAddress specifies the MAC address of the port. If not specified, the MAC address will be generated.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "macAddress"
    )]
    pub mac_address: Option<String>,
    /// NameSuffix will be appended to the name of the port if specified. If unspecified, instead the 0-based index of the port in the list is used.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "nameSuffix"
    )]
    pub name_suffix: Option<String>,
    /// Network is a query for an openstack network that the port will be created or discovered on.
    /// This will fail if the query returns more than one network.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub network: Option<OpenStackClusterTemplateTemplateSpecBastionSpecPortsNetwork>,
    /// Profile is a set of key-value pairs that are used for binding
    /// details. We intentionally don't expose this as a map[string]string
    /// because we only want to enable the users to set the values of the
    /// keys that are known to work in OpenStack Networking API.  See
    /// https://docs.openstack.org/api-ref/network/v2/index.html?expanded=create-port-detail#create-port
    /// To set profiles, your tenant needs permissions rule:create_port, and
    /// rule:create_port:binding:profile
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub profile: Option<OpenStackClusterTemplateTemplateSpecBastionSpecPortsProfile>,
    /// PropageteUplinkStatus enables or disables the propagate uplink status on the port.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "propagateUplinkStatus"
    )]
    pub propagate_uplink_status: Option<bool>,
    /// SecurityGroups is a list of the names, uuids, filters or any combination these of the security groups to assign to the instance.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "securityGroups"
    )]
    pub security_groups:
        Option<Vec<OpenStackClusterTemplateTemplateSpecBastionSpecPortsSecurityGroups>>,
    /// Tags applied to the port (and corresponding trunk, if a trunk is configured.)
    /// These tags are applied in addition to the instance's tags, which will also be applied to the port.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub tags: Option<Vec<String>>,
    /// Trunk specifies whether trunking is enabled at the port level. If not
    /// provided the value is inherited from the machine, or false for a
    /// bastion host.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub trunk: Option<bool>,
    /// Value specs are extra parameters to include in the API request with OpenStack.
    /// This is an extension point for the API, so what they do and if they are supported,
    /// depends on the specific OpenStack implementation.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "valueSpecs"
    )]
    pub value_specs: Option<Vec<OpenStackClusterTemplateTemplateSpecBastionSpecPortsValueSpecs>>,
    /// VNICType specifies the type of vNIC which this port should be
    /// attached to. This is used to determine which mechanism driver(s) to
    /// be used to bind the port. The valid values are normal, macvtap,
    /// direct, baremetal, direct-physical, virtio-forwarder, smart-nic and
    /// remote-managed, although these values will not be validated in this
    /// API to ensure compatibility with future neutron changes or custom
    /// implementations. What type of vNIC is actually available depends on
    /// deployments. If not specified, the Neutron default value is used.
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "vnicType")]
    pub vnic_type: Option<String>,
}

#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct OpenStackClusterTemplateTemplateSpecBastionSpecPortsAllowedAddressPairs {
    /// IPAddress is the IP address of the allowed address pair. Depending on
    /// the configuration of Neutron, it may be supported to specify a CIDR
    /// instead of a specific IP address.
    #[serde(rename = "ipAddress")]
    pub ip_address: String,
    /// MACAddress is the MAC address of the allowed address pair. If not
    /// specified, the MAC address will be the MAC address of the port.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "macAddress"
    )]
    pub mac_address: Option<String>,
}

#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct OpenStackClusterTemplateTemplateSpecBastionSpecPortsFixedIPs {
    /// IPAddress is a specific IP address to assign to the port. If Subnet
    /// is also specified, IPAddress must be a valid IP address in the
    /// subnet. If Subnet is not specified, IPAddress must be a valid IP
    /// address in any subnet of the port's network.
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "ipAddress")]
    pub ip_address: Option<String>,
    /// Subnet is an openstack subnet query that will return the id of a subnet to create
    /// the fixed IP of a port in. This query must not return more than one subnet.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub subnet: Option<OpenStackClusterTemplateTemplateSpecBastionSpecPortsFixedIPsSubnet>,
}

/// Subnet is an openstack subnet query that will return the id of a subnet to create
/// the fixed IP of a port in. This query must not return more than one subnet.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct OpenStackClusterTemplateTemplateSpecBastionSpecPortsFixedIPsSubnet {
    /// Filter specifies a filter to select the subnet. It must match exactly one subnet.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub filter: Option<OpenStackClusterTemplateTemplateSpecBastionSpecPortsFixedIPsSubnetFilter>,
    /// ID is the uuid of the subnet. It will not be validated.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub id: Option<String>,
}

/// Filter specifies a filter to select the subnet. It must match exactly one subnet.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct OpenStackClusterTemplateTemplateSpecBastionSpecPortsFixedIPsSubnetFilter {
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub cidr: Option<String>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub description: Option<String>,
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "gatewayIP")]
    pub gateway_ip: Option<String>,
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "ipVersion")]
    pub ip_version: Option<i64>,
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "ipv6AddressMode"
    )]
    pub ipv6_address_mode: Option<String>,
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "ipv6RAMode"
    )]
    pub ipv6_ra_mode: Option<String>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub name: Option<String>,
    /// NotTags is a list of tags to filter by. If specified, resources which
    /// contain all of the given tags will be excluded from the result.
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "notTags")]
    pub not_tags: Option<Vec<String>>,
    /// NotTagsAny is a list of tags to filter by. If specified, resources
    /// which contain any of the given tags will be excluded from the result.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "notTagsAny"
    )]
    pub not_tags_any: Option<Vec<String>>,
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "projectID")]
    pub project_id: Option<String>,
    /// Tags is a list of tags to filter by. If specified, the resource must
    /// have all of the tags specified to be included in the result.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub tags: Option<Vec<String>>,
    /// TagsAny is a list of tags to filter by. If specified, the resource
    /// must have at least one of the tags specified to be included in the
    /// result.
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "tagsAny")]
    pub tags_any: Option<Vec<String>>,
}

/// Network is a query for an openstack network that the port will be created or discovered on.
/// This will fail if the query returns more than one network.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct OpenStackClusterTemplateTemplateSpecBastionSpecPortsNetwork {
    /// Filter specifies a filter to select an OpenStack network. If provided, cannot be empty.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub filter: Option<OpenStackClusterTemplateTemplateSpecBastionSpecPortsNetworkFilter>,
    /// ID is the ID of the network to use. If ID is provided, the other filters cannot be provided. Must be in UUID format.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub id: Option<String>,
}

/// Filter specifies a filter to select an OpenStack network. If provided, cannot be empty.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct OpenStackClusterTemplateTemplateSpecBastionSpecPortsNetworkFilter {
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub description: Option<String>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub name: Option<String>,
    /// NotTags is a list of tags to filter by. If specified, resources which
    /// contain all of the given tags will be excluded from the result.
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "notTags")]
    pub not_tags: Option<Vec<String>>,
    /// NotTagsAny is a list of tags to filter by. If specified, resources
    /// which contain any of the given tags will be excluded from the result.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "notTagsAny"
    )]
    pub not_tags_any: Option<Vec<String>>,
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "projectID")]
    pub project_id: Option<String>,
    /// Tags is a list of tags to filter by. If specified, the resource must
    /// have all of the tags specified to be included in the result.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub tags: Option<Vec<String>>,
    /// TagsAny is a list of tags to filter by. If specified, the resource
    /// must have at least one of the tags specified to be included in the
    /// result.
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "tagsAny")]
    pub tags_any: Option<Vec<String>>,
}

/// Profile is a set of key-value pairs that are used for binding
/// details. We intentionally don't expose this as a map[string]string
/// because we only want to enable the users to set the values of the
/// keys that are known to work in OpenStack Networking API.  See
/// https://docs.openstack.org/api-ref/network/v2/index.html?expanded=create-port-detail#create-port
/// To set profiles, your tenant needs permissions rule:create_port, and
/// rule:create_port:binding:profile
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct OpenStackClusterTemplateTemplateSpecBastionSpecPortsProfile {
    /// OVSHWOffload enables or disables the OVS hardware offload feature.
    /// This flag is not required on OpenStack clouds since Yoga as Nova will set it automatically when the port is attached.
    /// See: https://bugs.launchpad.net/nova/+bug/2020813
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "ovsHWOffload"
    )]
    pub ovs_hw_offload: Option<bool>,
    /// TrustedVF enables or disables the “trusted mode” for the VF.
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "trustedVF")]
    pub trusted_vf: Option<bool>,
}

/// SecurityGroupParam specifies an OpenStack security group. It may be specified by ID or filter, but not both.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct OpenStackClusterTemplateTemplateSpecBastionSpecPortsSecurityGroups {
    /// Filter specifies a query to select an OpenStack security group. If provided, cannot be empty.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub filter: Option<OpenStackClusterTemplateTemplateSpecBastionSpecPortsSecurityGroupsFilter>,
    /// ID is the ID of the security group to use. If ID is provided, the other filters cannot be provided. Must be in UUID format.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub id: Option<String>,
}

/// Filter specifies a query to select an OpenStack security group. If provided, cannot be empty.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct OpenStackClusterTemplateTemplateSpecBastionSpecPortsSecurityGroupsFilter {
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub description: Option<String>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub name: Option<String>,
    /// NotTags is a list of tags to filter by. If specified, resources which
    /// contain all of the given tags will be excluded from the result.
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "notTags")]
    pub not_tags: Option<Vec<String>>,
    /// NotTagsAny is a list of tags to filter by. If specified, resources
    /// which contain any of the given tags will be excluded from the result.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "notTagsAny"
    )]
    pub not_tags_any: Option<Vec<String>>,
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "projectID")]
    pub project_id: Option<String>,
    /// Tags is a list of tags to filter by. If specified, the resource must
    /// have all of the tags specified to be included in the result.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub tags: Option<Vec<String>>,
    /// TagsAny is a list of tags to filter by. If specified, the resource
    /// must have at least one of the tags specified to be included in the
    /// result.
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "tagsAny")]
    pub tags_any: Option<Vec<String>>,
}

/// ValueSpec represents a single value_spec key-value pair.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct OpenStackClusterTemplateTemplateSpecBastionSpecPortsValueSpecs {
    /// Key is the key in the key-value pair.
    pub key: String,
    /// Name is the name of the key-value pair.
    /// This is just for identifying the pair and will not be sent to the OpenStack API.
    pub name: String,
    /// Value is the value in the key-value pair.
    pub value: String,
}

/// The volume metadata to boot from
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct OpenStackClusterTemplateTemplateSpecBastionSpecRootVolume {
    /// AvailabilityZone is the volume availability zone to create the volume
    /// in. If not specified, the volume will be created without an explicit
    /// availability zone.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "availabilityZone"
    )]
    pub availability_zone:
        Option<OpenStackClusterTemplateTemplateSpecBastionSpecRootVolumeAvailabilityZone>,
    /// SizeGiB is the size of the block device in gibibytes (GiB).
    #[serde(rename = "sizeGiB")]
    pub size_gi_b: i64,
    /// Type is the Cinder volume type of the volume.
    /// If omitted, the default Cinder volume type that is configured in the OpenStack cloud
    /// will be used.
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "type")]
    pub r#type: Option<String>,
}

/// AvailabilityZone is the volume availability zone to create the volume
/// in. If not specified, the volume will be created without an explicit
/// availability zone.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct OpenStackClusterTemplateTemplateSpecBastionSpecRootVolumeAvailabilityZone {
    /// From specifies where we will obtain the availability zone for the
    /// volume. The options are "Name" and "Machine". If "Name" is specified
    /// then the Name field must also be specified. If "Machine" is specified
    /// the volume will use the value of FailureDomain, if any, from the
    /// associated Machine.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub from: Option<OpenStackClusterTemplateTemplateSpecBastionSpecRootVolumeAvailabilityZoneFrom>,
    /// Name is the name of a volume availability zone to use. It is required
    /// if From is "Name". The volume availability zone name may not contain
    /// spaces.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub name: Option<String>,
}

/// AvailabilityZone is the volume availability zone to create the volume
/// in. If not specified, the volume will be created without an explicit
/// availability zone.
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub enum OpenStackClusterTemplateTemplateSpecBastionSpecRootVolumeAvailabilityZoneFrom {
    Name,
    Machine,
}

/// SchedulerHintAdditionalProperty represents a single additional property for a scheduler hint.
/// It includes a Name to identify the property and a Value that can be of various types.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct OpenStackClusterTemplateTemplateSpecBastionSpecSchedulerHintAdditionalProperties {
    /// Name is the name of the scheduler hint property.
    /// It is a unique identifier for the property.
    pub name: String,
    /// Value is the value of the scheduler hint property, which can be of various types
    /// (e.g., bool, string, int). The type is indicated by the Value.Type field.
    pub value:
        OpenStackClusterTemplateTemplateSpecBastionSpecSchedulerHintAdditionalPropertiesValue,
}

/// Value is the value of the scheduler hint property, which can be of various types
/// (e.g., bool, string, int). The type is indicated by the Value.Type field.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct OpenStackClusterTemplateTemplateSpecBastionSpecSchedulerHintAdditionalPropertiesValue {
    /// Bool is the boolean value of the scheduler hint, used when Type is "Bool".
    /// This field is required if type is 'Bool', and must not be set otherwise.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub bool: Option<bool>,
    /// Number is the integer value of the scheduler hint, used when Type is "Number".
    /// This field is required if type is 'Number', and must not be set otherwise.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub number: Option<i64>,
    /// String is the string value of the scheduler hint, used when Type is "String".
    /// This field is required if type is 'String', and must not be set otherwise.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub string: Option<String>,
    /// Type represents the type of the value.
    /// Valid values are Bool, String, and Number.
    #[serde(rename = "type")]
    pub r#type:
        OpenStackClusterTemplateTemplateSpecBastionSpecSchedulerHintAdditionalPropertiesValueType,
}

/// Value is the value of the scheduler hint property, which can be of various types
/// (e.g., bool, string, int). The type is indicated by the Value.Type field.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub enum OpenStackClusterTemplateTemplateSpecBastionSpecSchedulerHintAdditionalPropertiesValueType {
    Bool,
    #[default]
    String,
    Number,
}

/// SecurityGroupParam specifies an OpenStack security group. It may be specified by ID or filter, but not both.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct OpenStackClusterTemplateTemplateSpecBastionSpecSecurityGroups {
    /// Filter specifies a query to select an OpenStack security group. If provided, cannot be empty.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub filter: Option<OpenStackClusterTemplateTemplateSpecBastionSpecSecurityGroupsFilter>,
    /// ID is the ID of the security group to use. If ID is provided, the other filters cannot be provided. Must be in UUID format.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub id: Option<String>,
}

/// Filter specifies a query to select an OpenStack security group. If provided, cannot be empty.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct OpenStackClusterTemplateTemplateSpecBastionSpecSecurityGroupsFilter {
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub description: Option<String>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub name: Option<String>,
    /// NotTags is a list of tags to filter by. If specified, resources which
    /// contain all of the given tags will be excluded from the result.
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "notTags")]
    pub not_tags: Option<Vec<String>>,
    /// NotTagsAny is a list of tags to filter by. If specified, resources
    /// which contain any of the given tags will be excluded from the result.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "notTagsAny"
    )]
    pub not_tags_any: Option<Vec<String>>,
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "projectID")]
    pub project_id: Option<String>,
    /// Tags is a list of tags to filter by. If specified, the resource must
    /// have all of the tags specified to be included in the result.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub tags: Option<Vec<String>>,
    /// TagsAny is a list of tags to filter by. If specified, the resource
    /// must have at least one of the tags specified to be included in the
    /// result.
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "tagsAny")]
    pub tags_any: Option<Vec<String>>,
}

/// The server group to assign the machine to.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct OpenStackClusterTemplateTemplateSpecBastionSpecServerGroup {
    /// Filter specifies a query to select an OpenStack server group. If provided, it cannot be empty.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub filter: Option<OpenStackClusterTemplateTemplateSpecBastionSpecServerGroupFilter>,
    /// ID is the ID of the server group to use.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub id: Option<String>,
}

/// Filter specifies a query to select an OpenStack server group. If provided, it cannot be empty.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct OpenStackClusterTemplateTemplateSpecBastionSpecServerGroupFilter {
    /// Name is the name of a server group to look for.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub name: Option<String>,
}

#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct OpenStackClusterTemplateTemplateSpecBastionSpecServerMetadata {
    /// Key is the server metadata key
    pub key: String,
    /// Value is the server metadata value
    pub value: String,
}

/// ControlPlaneEndpoint represents the endpoint used to communicate with the control plane.
/// It is normally populated automatically by the OpenStackCluster
/// controller during cluster provisioning. If it is set on creation the
/// control plane endpoint will use the values set here in preference to
/// values set elsewhere.
/// ControlPlaneEndpoint cannot be modified after ControlPlaneEndpoint.Host has been set.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct OpenStackClusterTemplateTemplateSpecControlPlaneEndpoint {
    /// The hostname on which the API server is serving.
    pub host: String,
    /// The port on which the API server is serving.
    pub port: i32,
}

/// ExternalNetwork is the OpenStack Network to be used to get public internet to the VMs.
/// This option is ignored if DisableExternalNetwork is set to true.
///
/// If ExternalNetwork is defined it must refer to exactly one external network.
///
/// If ExternalNetwork is not defined or is empty the controller will use any
/// existing external network as long as there is only one. It is an
/// error if ExternalNetwork is not defined and there are multiple
/// external networks unless DisableExternalNetwork is also set.
///
/// If ExternalNetwork is not defined and there are no external networks
/// the controller will proceed as though DisableExternalNetwork was set.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct OpenStackClusterTemplateTemplateSpecExternalNetwork {
    /// Filter specifies a filter to select an OpenStack network. If provided, cannot be empty.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub filter: Option<OpenStackClusterTemplateTemplateSpecExternalNetworkFilter>,
    /// ID is the ID of the network to use. If ID is provided, the other filters cannot be provided. Must be in UUID format.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub id: Option<String>,
}

/// Filter specifies a filter to select an OpenStack network. If provided, cannot be empty.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct OpenStackClusterTemplateTemplateSpecExternalNetworkFilter {
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub description: Option<String>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub name: Option<String>,
    /// NotTags is a list of tags to filter by. If specified, resources which
    /// contain all of the given tags will be excluded from the result.
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "notTags")]
    pub not_tags: Option<Vec<String>>,
    /// NotTagsAny is a list of tags to filter by. If specified, resources
    /// which contain any of the given tags will be excluded from the result.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "notTagsAny"
    )]
    pub not_tags_any: Option<Vec<String>>,
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "projectID")]
    pub project_id: Option<String>,
    /// Tags is a list of tags to filter by. If specified, the resource must
    /// have all of the tags specified to be included in the result.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub tags: Option<Vec<String>>,
    /// TagsAny is a list of tags to filter by. If specified, the resource
    /// must have at least one of the tags specified to be included in the
    /// result.
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "tagsAny")]
    pub tags_any: Option<Vec<String>>,
}

#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct OpenStackClusterTemplateTemplateSpecExternalRouterIPs {
    /// The FixedIP in the corresponding subnet
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "fixedIP")]
    pub fixed_ip: Option<String>,
    /// The subnet in which the FixedIP is used for the Gateway of this router
    pub subnet: OpenStackClusterTemplateTemplateSpecExternalRouterIPsSubnet,
}

/// The subnet in which the FixedIP is used for the Gateway of this router
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct OpenStackClusterTemplateTemplateSpecExternalRouterIPsSubnet {
    /// Filter specifies a filter to select the subnet. It must match exactly one subnet.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub filter: Option<OpenStackClusterTemplateTemplateSpecExternalRouterIPsSubnetFilter>,
    /// ID is the uuid of the subnet. It will not be validated.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub id: Option<String>,
}

/// Filter specifies a filter to select the subnet. It must match exactly one subnet.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct OpenStackClusterTemplateTemplateSpecExternalRouterIPsSubnetFilter {
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub cidr: Option<String>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub description: Option<String>,
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "gatewayIP")]
    pub gateway_ip: Option<String>,
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "ipVersion")]
    pub ip_version: Option<i64>,
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "ipv6AddressMode"
    )]
    pub ipv6_address_mode: Option<String>,
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "ipv6RAMode"
    )]
    pub ipv6_ra_mode: Option<String>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub name: Option<String>,
    /// NotTags is a list of tags to filter by. If specified, resources which
    /// contain all of the given tags will be excluded from the result.
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "notTags")]
    pub not_tags: Option<Vec<String>>,
    /// NotTagsAny is a list of tags to filter by. If specified, resources
    /// which contain any of the given tags will be excluded from the result.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "notTagsAny"
    )]
    pub not_tags_any: Option<Vec<String>>,
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "projectID")]
    pub project_id: Option<String>,
    /// Tags is a list of tags to filter by. If specified, the resource must
    /// have all of the tags specified to be included in the result.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub tags: Option<Vec<String>>,
    /// TagsAny is a list of tags to filter by. If specified, the resource
    /// must have at least one of the tags specified to be included in the
    /// result.
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "tagsAny")]
    pub tags_any: Option<Vec<String>>,
}

/// IdentityRef is a reference to a secret holding OpenStack credentials
/// to be used when reconciling this cluster. It is also to reconcile
/// machines unless overridden in the machine spec.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct OpenStackClusterTemplateTemplateSpecIdentityRef {
    /// CloudName specifies the name of the entry in the clouds.yaml file to use.
    #[serde(rename = "cloudName")]
    pub cloud_name: String,
    /// Name is the name of a secret in the same namespace as the resource being provisioned.
    /// The secret must contain a key named `clouds.yaml` which contains an OpenStack clouds.yaml file.
    /// The secret may optionally contain a key named `cacert` containing a PEM-encoded CA certificate.
    pub name: String,
    /// Region specifies an OpenStack region to use. If specified, it overrides
    /// any value in clouds.yaml. If specified for an OpenStackMachine, its
    /// value will be included in providerID.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub region: Option<String>,
}

/// ManagedSecurityGroups determines whether OpenStack security groups for the cluster
/// will be managed by the OpenStack provider or whether pre-existing security groups will
/// be specified as part of the configuration.
/// By default, the managed security groups have rules that allow the Kubelet, etcd, and the
/// Kubernetes API server to function correctly.
/// It's possible to add additional rules to the managed security groups.
/// When defined to an empty struct, the managed security groups will be created with the default rules.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct OpenStackClusterTemplateTemplateSpecManagedSecurityGroups {
    /// allNodesSecurityGroupRules defines the rules that should be applied to all nodes.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "allNodesSecurityGroupRules"
    )]
    pub all_nodes_security_group_rules: Option<
        Vec<OpenStackClusterTemplateTemplateSpecManagedSecurityGroupsAllNodesSecurityGroupRules>,
    >,
    /// AllowAllInClusterTraffic allows all ingress and egress traffic between cluster nodes when set to true.
    #[serde(rename = "allowAllInClusterTraffic")]
    pub allow_all_in_cluster_traffic: bool,
}

/// SecurityGroupRuleSpec represent the basic information of the associated OpenStack
/// Security Group Role.
/// For now this is only used for the allNodesSecurityGroupRules but when we add
/// other security groups, we'll need to add a validation because
/// Remote* fields are mutually exclusive.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct OpenStackClusterTemplateTemplateSpecManagedSecurityGroupsAllNodesSecurityGroupRules {
    /// description of the security group rule.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub description: Option<String>,
    /// direction in which the security group rule is applied. The only values
    /// allowed are "ingress" or "egress". For a compute instance, an ingress
    /// security group rule is applied to incoming (ingress) traffic for that
    /// instance. An egress rule is applied to traffic leaving the instance.
    pub direction: String,
    /// etherType must be IPv4 or IPv6, and addresses represented in CIDR must match the
    /// ingress or egress rules.
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "etherType")]
    pub ether_type: Option<String>,
    /// name of the security group rule.
    /// It's used to identify the rule so it can be patched and will not be sent to the OpenStack API.
    pub name: String,
    /// portRangeMax is a number in the range that is matched by the security group
    /// rule. The portRangeMin attribute constrains the portRangeMax attribute.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "portRangeMax"
    )]
    pub port_range_max: Option<i64>,
    /// portRangeMin is a number in the range that is matched by the security group
    /// rule. If the protocol is TCP or UDP, this value must be less than or equal
    /// to the value of the portRangeMax attribute.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "portRangeMin"
    )]
    pub port_range_min: Option<i64>,
    /// protocol is the protocol that is matched by the security group rule.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub protocol: Option<String>,
    /// remoteGroupID is the remote group ID to be associated with this security group rule.
    /// You can specify either remoteGroupID or remoteIPPrefix or remoteManagedGroups.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "remoteGroupID"
    )]
    pub remote_group_id: Option<String>,
    /// remoteIPPrefix is the remote IP prefix to be associated with this security group rule.
    /// You can specify either remoteGroupID or remoteIPPrefix or remoteManagedGroups.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "remoteIPPrefix"
    )]
    pub remote_ip_prefix: Option<String>,
    /// remoteManagedGroups is the remote managed groups to be associated with this security group rule.
    /// You can specify either remoteGroupID or remoteIPPrefix or remoteManagedGroups.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "remoteManagedGroups"
    )]
    pub remote_managed_groups: Option<Vec<String>>,
}

#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct OpenStackClusterTemplateTemplateSpecManagedSubnets {
    /// AllocationPools is an array of AllocationPool objects that will be applied to OpenStack Subnet being created.
    /// If set, OpenStack will only allocate these IPs for Machines. It will still be possible to create ports from
    /// outside of these ranges manually.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "allocationPools"
    )]
    pub allocation_pools:
        Option<Vec<OpenStackClusterTemplateTemplateSpecManagedSubnetsAllocationPools>>,
    /// CIDR is representing the IP address range used to create the subnet, e.g. 10.0.0.0/24.
    /// This field is required when defining a subnet.
    pub cidr: String,
    /// DNSNameservers holds a list of DNS server addresses that will be provided when creating
    /// the subnet. These addresses need to have the same IP version as CIDR.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "dnsNameservers"
    )]
    pub dns_nameservers: Option<Vec<String>>,
}

#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct OpenStackClusterTemplateTemplateSpecManagedSubnetsAllocationPools {
    /// End represents the end of the AlloctionPool, that is the highest IP of the pool.
    pub end: String,
    /// Start represents the start of the AllocationPool, that is the lowest IP of the pool.
    pub start: String,
}

/// Network specifies an existing network to use if no ManagedSubnets
/// are specified.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct OpenStackClusterTemplateTemplateSpecNetwork {
    /// Filter specifies a filter to select an OpenStack network. If provided, cannot be empty.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub filter: Option<OpenStackClusterTemplateTemplateSpecNetworkFilter>,
    /// ID is the ID of the network to use. If ID is provided, the other filters cannot be provided. Must be in UUID format.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub id: Option<String>,
}

/// Filter specifies a filter to select an OpenStack network. If provided, cannot be empty.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct OpenStackClusterTemplateTemplateSpecNetworkFilter {
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub description: Option<String>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub name: Option<String>,
    /// NotTags is a list of tags to filter by. If specified, resources which
    /// contain all of the given tags will be excluded from the result.
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "notTags")]
    pub not_tags: Option<Vec<String>>,
    /// NotTagsAny is a list of tags to filter by. If specified, resources
    /// which contain any of the given tags will be excluded from the result.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "notTagsAny"
    )]
    pub not_tags_any: Option<Vec<String>>,
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "projectID")]
    pub project_id: Option<String>,
    /// Tags is a list of tags to filter by. If specified, the resource must
    /// have all of the tags specified to be included in the result.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub tags: Option<Vec<String>>,
    /// TagsAny is a list of tags to filter by. If specified, the resource
    /// must have at least one of the tags specified to be included in the
    /// result.
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "tagsAny")]
    pub tags_any: Option<Vec<String>>,
}

/// Router specifies an existing router to be used if ManagedSubnets are
/// specified. If specified, no new router will be created.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct OpenStackClusterTemplateTemplateSpecRouter {
    /// Filter specifies a filter to select an OpenStack router. If provided, cannot be empty.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub filter: Option<OpenStackClusterTemplateTemplateSpecRouterFilter>,
    /// ID is the ID of the router to use. If ID is provided, the other filters cannot be provided. Must be in UUID format.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub id: Option<String>,
}

/// Filter specifies a filter to select an OpenStack router. If provided, cannot be empty.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct OpenStackClusterTemplateTemplateSpecRouterFilter {
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub description: Option<String>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub name: Option<String>,
    /// NotTags is a list of tags to filter by. If specified, resources which
    /// contain all of the given tags will be excluded from the result.
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "notTags")]
    pub not_tags: Option<Vec<String>>,
    /// NotTagsAny is a list of tags to filter by. If specified, resources
    /// which contain any of the given tags will be excluded from the result.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "notTagsAny"
    )]
    pub not_tags_any: Option<Vec<String>>,
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "projectID")]
    pub project_id: Option<String>,
    /// Tags is a list of tags to filter by. If specified, the resource must
    /// have all of the tags specified to be included in the result.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub tags: Option<Vec<String>>,
    /// TagsAny is a list of tags to filter by. If specified, the resource
    /// must have at least one of the tags specified to be included in the
    /// result.
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "tagsAny")]
    pub tags_any: Option<Vec<String>>,
}

/// SubnetParam specifies an OpenStack subnet to use. It may be specified by either ID or filter, but not both.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct OpenStackClusterTemplateTemplateSpecSubnets {
    /// Filter specifies a filter to select the subnet. It must match exactly one subnet.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub filter: Option<OpenStackClusterTemplateTemplateSpecSubnetsFilter>,
    /// ID is the uuid of the subnet. It will not be validated.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub id: Option<String>,
}

/// Filter specifies a filter to select the subnet. It must match exactly one subnet.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct OpenStackClusterTemplateTemplateSpecSubnetsFilter {
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub cidr: Option<String>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub description: Option<String>,
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "gatewayIP")]
    pub gateway_ip: Option<String>,
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "ipVersion")]
    pub ip_version: Option<i64>,
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "ipv6AddressMode"
    )]
    pub ipv6_address_mode: Option<String>,
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "ipv6RAMode"
    )]
    pub ipv6_ra_mode: Option<String>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub name: Option<String>,
    /// NotTags is a list of tags to filter by. If specified, resources which
    /// contain all of the given tags will be excluded from the result.
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "notTags")]
    pub not_tags: Option<Vec<String>>,
    /// NotTagsAny is a list of tags to filter by. If specified, resources
    /// which contain any of the given tags will be excluded from the result.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "notTagsAny"
    )]
    pub not_tags_any: Option<Vec<String>>,
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "projectID")]
    pub project_id: Option<String>,
    /// Tags is a list of tags to filter by. If specified, the resource must
    /// have all of the tags specified to be included in the result.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub tags: Option<Vec<String>>,
    /// TagsAny is a list of tags to filter by. If specified, the resource
    /// must have at least one of the tags specified to be included in the
    /// result.
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "tagsAny")]
    pub tags_any: Option<Vec<String>>,
}
