// WARNING: generated by kopium - manual changes will be overwritten
// kopium command: kopium -D Default -D PartialEq -A -d -f -
// kopium version: 0.21.1

#[allow(unused_imports)]
mod prelude {
    pub use k8s_openapi::api::core::v1::ObjectReference;
    pub use k8s_openapi::apimachinery::pkg::apis::meta::v1::Condition;
    pub use k8s_openapi::apimachinery::pkg::util::intstr::IntOrString;
    pub use kube::CustomResource;
    pub use schemars::JsonSchema;
    pub use serde::{Deserialize, Serialize};
    pub use std::collections::BTreeMap;
}
use self::prelude::*;

/// ClusterSpec defines the desired state of Cluster.
#[derive(CustomResource, Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
#[kube(
    group = "cluster.x-k8s.io",
    version = "v1beta1",
    kind = "Cluster",
    plural = "clusters"
)]
#[kube(namespaced)]
#[kube(status = "ClusterStatus")]
#[kube(derive = "Default")]
#[kube(derive = "PartialEq")]
pub struct ClusterSpec {
    /// availabilityGates specifies additional conditions to include when evaluating Cluster Available condition.
    ///
    /// NOTE: this field is considered only for computing v1beta2 conditions.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "availabilityGates"
    )]
    pub availability_gates: Option<Vec<ClusterAvailabilityGates>>,
    /// Cluster network configuration.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "clusterNetwork"
    )]
    pub cluster_network: Option<ClusterClusterNetwork>,
    /// controlPlaneEndpoint represents the endpoint used to communicate with the control plane.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "controlPlaneEndpoint"
    )]
    pub control_plane_endpoint: Option<ClusterControlPlaneEndpoint>,
    /// controlPlaneRef is an optional reference to a provider-specific resource that holds
    /// the details for provisioning the Control Plane for a Cluster.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "controlPlaneRef"
    )]
    pub control_plane_ref: Option<ObjectReference>,
    /// infrastructureRef is a reference to a provider-specific resource that holds the details
    /// for provisioning infrastructure for a cluster in said provider.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "infrastructureRef"
    )]
    pub infrastructure_ref: Option<ObjectReference>,
    /// paused can be used to prevent controllers from processing the Cluster and all its associated objects.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub paused: Option<bool>,
    /// This encapsulates the topology for the cluster.
    /// NOTE: It is required to enable the ClusterTopology
    /// feature gate flag to activate managed topologies support;
    /// this feature is highly experimental, and parts of it might still be not implemented.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub topology: Option<ClusterTopology>,
}

/// ClusterAvailabilityGate contains the type of a Cluster condition to be used as availability gate.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterAvailabilityGates {
    /// conditionType refers to a positive polarity condition (status true means good) with matching type in the Cluster's condition list.
    /// If the conditions doesn't exist, it will be treated as unknown.
    /// Note: Both Cluster API conditions or conditions added by 3rd party controllers can be used as availability gates.
    #[serde(rename = "conditionType")]
    pub condition_type: String,
}

/// Cluster network configuration.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterClusterNetwork {
    /// apiServerPort specifies the port the API Server should bind to.
    /// Defaults to 6443.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "apiServerPort"
    )]
    pub api_server_port: Option<i32>,
    /// The network ranges from which Pod networks are allocated.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub pods: Option<ClusterClusterNetworkPods>,
    /// Domain name for services.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "serviceDomain"
    )]
    pub service_domain: Option<String>,
    /// The network ranges from which service VIPs are allocated.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub services: Option<ClusterClusterNetworkServices>,
}

/// The network ranges from which Pod networks are allocated.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterClusterNetworkPods {
    #[serde(rename = "cidrBlocks")]
    pub cidr_blocks: Vec<String>,
}

/// The network ranges from which service VIPs are allocated.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterClusterNetworkServices {
    #[serde(rename = "cidrBlocks")]
    pub cidr_blocks: Vec<String>,
}

/// controlPlaneEndpoint represents the endpoint used to communicate with the control plane.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterControlPlaneEndpoint {
    /// The hostname on which the API server is serving.
    pub host: String,
    /// The port on which the API server is serving.
    pub port: i32,
}

/// controlPlaneRef is an optional reference to a provider-specific resource that holds
/// the details for provisioning the Control Plane for a Cluster.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterControlPlaneRef {
    /// API version of the referent.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "apiVersion"
    )]
    pub api_version: Option<String>,
    /// If referring to a piece of an object instead of an entire object, this string
    /// should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2].
    /// For example, if the object reference is to a container within a pod, this would take on a value like:
    /// "spec.containers{name}" (where "name" refers to the name of the container that triggered
    /// the event) or if no container name is specified "spec.containers[2]" (container with
    /// index 2 in this pod). This syntax is chosen only to have some well-defined way of
    /// referencing a part of an object.
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "fieldPath")]
    pub field_path: Option<String>,
    /// Kind of the referent.
    /// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub kind: Option<String>,
    /// Name of the referent.
    /// More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub name: Option<String>,
    /// Namespace of the referent.
    /// More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub namespace: Option<String>,
    /// Specific resourceVersion to which this reference is made, if any.
    /// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "resourceVersion"
    )]
    pub resource_version: Option<String>,
    /// UID of the referent.
    /// More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub uid: Option<String>,
}

/// infrastructureRef is a reference to a provider-specific resource that holds the details
/// for provisioning infrastructure for a cluster in said provider.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterInfrastructureRef {
    /// API version of the referent.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "apiVersion"
    )]
    pub api_version: Option<String>,
    /// If referring to a piece of an object instead of an entire object, this string
    /// should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2].
    /// For example, if the object reference is to a container within a pod, this would take on a value like:
    /// "spec.containers{name}" (where "name" refers to the name of the container that triggered
    /// the event) or if no container name is specified "spec.containers[2]" (container with
    /// index 2 in this pod). This syntax is chosen only to have some well-defined way of
    /// referencing a part of an object.
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "fieldPath")]
    pub field_path: Option<String>,
    /// Kind of the referent.
    /// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub kind: Option<String>,
    /// Name of the referent.
    /// More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub name: Option<String>,
    /// Namespace of the referent.
    /// More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub namespace: Option<String>,
    /// Specific resourceVersion to which this reference is made, if any.
    /// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "resourceVersion"
    )]
    pub resource_version: Option<String>,
    /// UID of the referent.
    /// More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub uid: Option<String>,
}

/// This encapsulates the topology for the cluster.
/// NOTE: It is required to enable the ClusterTopology
/// feature gate flag to activate managed topologies support;
/// this feature is highly experimental, and parts of it might still be not implemented.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterTopology {
    /// The name of the ClusterClass object to create the topology.
    pub class: String,
    /// controlPlane describes the cluster control plane.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "controlPlane"
    )]
    pub control_plane: Option<ClusterTopologyControlPlane>,
    /// rolloutAfter performs a rollout of the entire cluster one component at a time,
    /// control plane first and then machine deployments.
    ///
    /// Deprecated: This field has no function and is going to be removed in the next apiVersion.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "rolloutAfter"
    )]
    pub rollout_after: Option<String>,
    /// variables can be used to customize the Cluster through
    /// patches. They must comply to the corresponding
    /// VariableClasses defined in the ClusterClass.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub variables: Option<Vec<ClusterTopologyVariables>>,
    /// The Kubernetes version of the cluster.
    pub version: String,
    /// workers encapsulates the different constructs that form the worker nodes
    /// for the cluster.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub workers: Option<ClusterTopologyWorkers>,
}

/// controlPlane describes the cluster control plane.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterTopologyControlPlane {
    /// machineHealthCheck allows to enable, disable and override
    /// the MachineHealthCheck configuration in the ClusterClass for this control plane.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "machineHealthCheck"
    )]
    pub machine_health_check: Option<ClusterTopologyControlPlaneMachineHealthCheck>,
    /// metadata is the metadata applied to the ControlPlane and the Machines of the ControlPlane
    /// if the ControlPlaneTemplate referenced by the ClusterClass is machine based. If not, it
    /// is applied only to the ControlPlane.
    /// At runtime this metadata is merged with the corresponding metadata from the ClusterClass.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub metadata: Option<ClusterTopologyControlPlaneMetadata>,
    /// nodeDeletionTimeout defines how long the controller will attempt to delete the Node that the Machine
    /// hosts after the Machine is marked for deletion. A duration of 0 will retry deletion indefinitely.
    /// Defaults to 10 seconds.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "nodeDeletionTimeout"
    )]
    pub node_deletion_timeout: Option<String>,
    /// nodeDrainTimeout is the total amount of time that the controller will spend on draining a node.
    /// The default value is 0, meaning that the node can be drained without any time limitations.
    /// NOTE: NodeDrainTimeout is different from `kubectl drain --timeout`
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "nodeDrainTimeout"
    )]
    pub node_drain_timeout: Option<String>,
    /// nodeVolumeDetachTimeout is the total amount of time that the controller will spend on waiting for all volumes
    /// to be detached. The default value is 0, meaning that the volumes can be detached without any time limitations.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "nodeVolumeDetachTimeout"
    )]
    pub node_volume_detach_timeout: Option<String>,
    /// replicas is the number of control plane nodes.
    /// If the value is nil, the ControlPlane object is created without the number of Replicas
    /// and it's assumed that the control plane controller does not implement support for this field.
    /// When specified against a control plane provider that lacks support for this field, this value will be ignored.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub replicas: Option<i32>,
    /// variables can be used to customize the ControlPlane through patches.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub variables: Option<ClusterTopologyControlPlaneVariables>,
}

/// machineHealthCheck allows to enable, disable and override
/// the MachineHealthCheck configuration in the ClusterClass for this control plane.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterTopologyControlPlaneMachineHealthCheck {
    /// enable controls if a MachineHealthCheck should be created for the target machines.
    ///
    /// If false: No MachineHealthCheck will be created.
    ///
    /// If not set(default): A MachineHealthCheck will be created if it is defined here or
    ///  in the associated ClusterClass. If no MachineHealthCheck is defined then none will be created.
    ///
    /// If true: A MachineHealthCheck is guaranteed to be created. Cluster validation will
    /// block if `enable` is true and no MachineHealthCheck definition is available.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub enable: Option<bool>,
    /// Any further remediation is only allowed if at most "MaxUnhealthy" machines selected by
    /// "selector" are not healthy.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "maxUnhealthy"
    )]
    pub max_unhealthy: Option<IntOrString>,
    /// nodeStartupTimeout allows to set the maximum time for MachineHealthCheck
    /// to consider a Machine unhealthy if a corresponding Node isn't associated
    /// through a `Spec.ProviderID` field.
    ///
    /// The duration set in this field is compared to the greatest of:
    /// - Cluster's infrastructure ready condition timestamp (if and when available)
    /// - Control Plane's initialized condition timestamp (if and when available)
    /// - Machine's infrastructure ready condition timestamp (if and when available)
    /// - Machine's metadata creation timestamp
    ///
    /// Defaults to 10 minutes.
    /// If you wish to disable this feature, set the value explicitly to 0.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "nodeStartupTimeout"
    )]
    pub node_startup_timeout: Option<String>,
    /// remediationTemplate is a reference to a remediation template
    /// provided by an infrastructure provider.
    ///
    /// This field is completely optional, when filled, the MachineHealthCheck controller
    /// creates a new object from the template referenced and hands off remediation of the machine to
    /// a controller that lives outside of Cluster API.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "remediationTemplate"
    )]
    pub remediation_template: Option<ObjectReference>,
    /// unhealthyConditions contains a list of the conditions that determine
    /// whether a node is considered unhealthy. The conditions are combined in a
    /// logical OR, i.e. if any of the conditions is met, the node is unhealthy.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "unhealthyConditions"
    )]
    pub unhealthy_conditions:
        Option<Vec<ClusterTopologyControlPlaneMachineHealthCheckUnhealthyConditions>>,
    /// Any further remediation is only allowed if the number of machines selected by "selector" as not healthy
    /// is within the range of "UnhealthyRange". Takes precedence over MaxUnhealthy.
    /// Eg. "[3-5]" - This means that remediation will be allowed only when:
    /// (a) there are at least 3 unhealthy machines (and)
    /// (b) there are at most 5 unhealthy machines
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "unhealthyRange"
    )]
    pub unhealthy_range: Option<String>,
}

/// remediationTemplate is a reference to a remediation template
/// provided by an infrastructure provider.
///
/// This field is completely optional, when filled, the MachineHealthCheck controller
/// creates a new object from the template referenced and hands off remediation of the machine to
/// a controller that lives outside of Cluster API.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterTopologyControlPlaneMachineHealthCheckRemediationTemplate {
    /// API version of the referent.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "apiVersion"
    )]
    pub api_version: Option<String>,
    /// If referring to a piece of an object instead of an entire object, this string
    /// should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2].
    /// For example, if the object reference is to a container within a pod, this would take on a value like:
    /// "spec.containers{name}" (where "name" refers to the name of the container that triggered
    /// the event) or if no container name is specified "spec.containers[2]" (container with
    /// index 2 in this pod). This syntax is chosen only to have some well-defined way of
    /// referencing a part of an object.
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "fieldPath")]
    pub field_path: Option<String>,
    /// Kind of the referent.
    /// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub kind: Option<String>,
    /// Name of the referent.
    /// More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub name: Option<String>,
    /// Namespace of the referent.
    /// More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub namespace: Option<String>,
    /// Specific resourceVersion to which this reference is made, if any.
    /// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "resourceVersion"
    )]
    pub resource_version: Option<String>,
    /// UID of the referent.
    /// More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub uid: Option<String>,
}

/// UnhealthyCondition represents a Node condition type and value with a timeout
/// specified as a duration.  When the named condition has been in the given
/// status for at least the timeout value, a node is considered unhealthy.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterTopologyControlPlaneMachineHealthCheckUnhealthyConditions {
    pub status: String,
    pub timeout: String,
    #[serde(rename = "type")]
    pub r#type: String,
}

/// metadata is the metadata applied to the ControlPlane and the Machines of the ControlPlane
/// if the ControlPlaneTemplate referenced by the ClusterClass is machine based. If not, it
/// is applied only to the ControlPlane.
/// At runtime this metadata is merged with the corresponding metadata from the ClusterClass.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterTopologyControlPlaneMetadata {
    /// annotations is an unstructured key value map stored with a resource that may be
    /// set by external tools to store and retrieve arbitrary metadata. They are not
    /// queryable and should be preserved when modifying objects.
    /// More info: http://kubernetes.io/docs/user-guide/annotations
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub annotations: Option<BTreeMap<String, String>>,
    /// Map of string keys and values that can be used to organize and categorize
    /// (scope and select) objects. May match selectors of replication controllers
    /// and services.
    /// More info: http://kubernetes.io/docs/user-guide/labels
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub labels: Option<BTreeMap<String, String>>,
}

/// variables can be used to customize the ControlPlane through patches.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterTopologyControlPlaneVariables {
    /// overrides can be used to override Cluster level variables.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub overrides: Option<Vec<ClusterTopologyControlPlaneVariablesOverrides>>,
}

/// ClusterVariable can be used to customize the Cluster through patches. Each ClusterVariable is associated with a
/// Variable definition in the ClusterClass `status` variables.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterTopologyControlPlaneVariablesOverrides {
    /// definitionFrom specifies where the definition of this Variable is from.
    ///
    /// Deprecated: This field is deprecated, must not be set anymore and is going to be removed in the next apiVersion.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "definitionFrom"
    )]
    pub definition_from: Option<String>,
    /// name of the variable.
    pub name: String,
    /// value of the variable.
    /// Note: the value will be validated against the schema of the corresponding ClusterClassVariable
    /// from the ClusterClass.
    /// Note: We have to use apiextensionsv1.JSON instead of a custom JSON type, because controller-tools has a
    /// hard-coded schema for apiextensionsv1.JSON which cannot be produced by another type via controller-tools,
    /// i.e. it is not possible to have no type field.
    /// Ref: https://github.com/kubernetes-sigs/controller-tools/blob/d0e03a142d0ecdd5491593e941ee1d6b5d91dba6/pkg/crd/known_types.go#L106-L111
    pub value: serde_json::Value,
}

/// ClusterVariable can be used to customize the Cluster through patches. Each ClusterVariable is associated with a
/// Variable definition in the ClusterClass `status` variables.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterTopologyVariables {
    /// definitionFrom specifies where the definition of this Variable is from.
    ///
    /// Deprecated: This field is deprecated, must not be set anymore and is going to be removed in the next apiVersion.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "definitionFrom"
    )]
    pub definition_from: Option<String>,
    /// name of the variable.
    pub name: String,
    /// value of the variable.
    /// Note: the value will be validated against the schema of the corresponding ClusterClassVariable
    /// from the ClusterClass.
    /// Note: We have to use apiextensionsv1.JSON instead of a custom JSON type, because controller-tools has a
    /// hard-coded schema for apiextensionsv1.JSON which cannot be produced by another type via controller-tools,
    /// i.e. it is not possible to have no type field.
    /// Ref: https://github.com/kubernetes-sigs/controller-tools/blob/d0e03a142d0ecdd5491593e941ee1d6b5d91dba6/pkg/crd/known_types.go#L106-L111
    pub value: serde_json::Value,
}

/// workers encapsulates the different constructs that form the worker nodes
/// for the cluster.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterTopologyWorkers {
    /// machineDeployments is a list of machine deployments in the cluster.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "machineDeployments"
    )]
    pub machine_deployments: Option<Vec<ClusterTopologyWorkersMachineDeployments>>,
    /// machinePools is a list of machine pools in the cluster.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "machinePools"
    )]
    pub machine_pools: Option<Vec<ClusterTopologyWorkersMachinePools>>,
}

/// MachineDeploymentTopology specifies the different parameters for a set of worker nodes in the topology.
/// This set of nodes is managed by a MachineDeployment object whose lifecycle is managed by the Cluster controller.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterTopologyWorkersMachineDeployments {
    /// class is the name of the MachineDeploymentClass used to create the set of worker nodes.
    /// This should match one of the deployment classes defined in the ClusterClass object
    /// mentioned in the `Cluster.Spec.Class` field.
    pub class: String,
    /// failureDomain is the failure domain the machines will be created in.
    /// Must match a key in the FailureDomains map stored on the cluster object.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "failureDomain"
    )]
    pub failure_domain: Option<String>,
    /// machineHealthCheck allows to enable, disable and override
    /// the MachineHealthCheck configuration in the ClusterClass for this MachineDeployment.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "machineHealthCheck"
    )]
    pub machine_health_check: Option<ClusterTopologyWorkersMachineDeploymentsMachineHealthCheck>,
    /// metadata is the metadata applied to the MachineDeployment and the machines of the MachineDeployment.
    /// At runtime this metadata is merged with the corresponding metadata from the ClusterClass.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub metadata: Option<ClusterTopologyWorkersMachineDeploymentsMetadata>,
    /// Minimum number of seconds for which a newly created machine should
    /// be ready.
    /// Defaults to 0 (machine will be considered available as soon as it
    /// is ready)
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "minReadySeconds"
    )]
    pub min_ready_seconds: Option<i32>,
    /// name is the unique identifier for this MachineDeploymentTopology.
    /// The value is used with other unique identifiers to create a MachineDeployment's Name
    /// (e.g. cluster's name, etc). In case the name is greater than the allowed maximum length,
    /// the values are hashed together.
    pub name: String,
    /// nodeDeletionTimeout defines how long the controller will attempt to delete the Node that the Machine
    /// hosts after the Machine is marked for deletion. A duration of 0 will retry deletion indefinitely.
    /// Defaults to 10 seconds.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "nodeDeletionTimeout"
    )]
    pub node_deletion_timeout: Option<String>,
    /// nodeDrainTimeout is the total amount of time that the controller will spend on draining a node.
    /// The default value is 0, meaning that the node can be drained without any time limitations.
    /// NOTE: NodeDrainTimeout is different from `kubectl drain --timeout`
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "nodeDrainTimeout"
    )]
    pub node_drain_timeout: Option<String>,
    /// nodeVolumeDetachTimeout is the total amount of time that the controller will spend on waiting for all volumes
    /// to be detached. The default value is 0, meaning that the volumes can be detached without any time limitations.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "nodeVolumeDetachTimeout"
    )]
    pub node_volume_detach_timeout: Option<String>,
    /// replicas is the number of worker nodes belonging to this set.
    /// If the value is nil, the MachineDeployment is created without the number of Replicas (defaulting to 1)
    /// and it's assumed that an external entity (like cluster autoscaler) is responsible for the management
    /// of this value.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub replicas: Option<i32>,
    /// The deployment strategy to use to replace existing machines with
    /// new ones.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub strategy: Option<ClusterTopologyWorkersMachineDeploymentsStrategy>,
    /// variables can be used to customize the MachineDeployment through patches.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub variables: Option<ClusterTopologyWorkersMachineDeploymentsVariables>,
}

/// machineHealthCheck allows to enable, disable and override
/// the MachineHealthCheck configuration in the ClusterClass for this MachineDeployment.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterTopologyWorkersMachineDeploymentsMachineHealthCheck {
    /// enable controls if a MachineHealthCheck should be created for the target machines.
    ///
    /// If false: No MachineHealthCheck will be created.
    ///
    /// If not set(default): A MachineHealthCheck will be created if it is defined here or
    ///  in the associated ClusterClass. If no MachineHealthCheck is defined then none will be created.
    ///
    /// If true: A MachineHealthCheck is guaranteed to be created. Cluster validation will
    /// block if `enable` is true and no MachineHealthCheck definition is available.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub enable: Option<bool>,
    /// Any further remediation is only allowed if at most "MaxUnhealthy" machines selected by
    /// "selector" are not healthy.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "maxUnhealthy"
    )]
    pub max_unhealthy: Option<IntOrString>,
    /// nodeStartupTimeout allows to set the maximum time for MachineHealthCheck
    /// to consider a Machine unhealthy if a corresponding Node isn't associated
    /// through a `Spec.ProviderID` field.
    ///
    /// The duration set in this field is compared to the greatest of:
    /// - Cluster's infrastructure ready condition timestamp (if and when available)
    /// - Control Plane's initialized condition timestamp (if and when available)
    /// - Machine's infrastructure ready condition timestamp (if and when available)
    /// - Machine's metadata creation timestamp
    ///
    /// Defaults to 10 minutes.
    /// If you wish to disable this feature, set the value explicitly to 0.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "nodeStartupTimeout"
    )]
    pub node_startup_timeout: Option<String>,
    /// remediationTemplate is a reference to a remediation template
    /// provided by an infrastructure provider.
    ///
    /// This field is completely optional, when filled, the MachineHealthCheck controller
    /// creates a new object from the template referenced and hands off remediation of the machine to
    /// a controller that lives outside of Cluster API.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "remediationTemplate"
    )]
    pub remediation_template: Option<ObjectReference>,
    /// unhealthyConditions contains a list of the conditions that determine
    /// whether a node is considered unhealthy. The conditions are combined in a
    /// logical OR, i.e. if any of the conditions is met, the node is unhealthy.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "unhealthyConditions"
    )]
    pub unhealthy_conditions:
        Option<Vec<ClusterTopologyWorkersMachineDeploymentsMachineHealthCheckUnhealthyConditions>>,
    /// Any further remediation is only allowed if the number of machines selected by "selector" as not healthy
    /// is within the range of "UnhealthyRange". Takes precedence over MaxUnhealthy.
    /// Eg. "[3-5]" - This means that remediation will be allowed only when:
    /// (a) there are at least 3 unhealthy machines (and)
    /// (b) there are at most 5 unhealthy machines
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "unhealthyRange"
    )]
    pub unhealthy_range: Option<String>,
}

/// remediationTemplate is a reference to a remediation template
/// provided by an infrastructure provider.
///
/// This field is completely optional, when filled, the MachineHealthCheck controller
/// creates a new object from the template referenced and hands off remediation of the machine to
/// a controller that lives outside of Cluster API.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterTopologyWorkersMachineDeploymentsMachineHealthCheckRemediationTemplate {
    /// API version of the referent.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "apiVersion"
    )]
    pub api_version: Option<String>,
    /// If referring to a piece of an object instead of an entire object, this string
    /// should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2].
    /// For example, if the object reference is to a container within a pod, this would take on a value like:
    /// "spec.containers{name}" (where "name" refers to the name of the container that triggered
    /// the event) or if no container name is specified "spec.containers[2]" (container with
    /// index 2 in this pod). This syntax is chosen only to have some well-defined way of
    /// referencing a part of an object.
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "fieldPath")]
    pub field_path: Option<String>,
    /// Kind of the referent.
    /// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub kind: Option<String>,
    /// Name of the referent.
    /// More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub name: Option<String>,
    /// Namespace of the referent.
    /// More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub namespace: Option<String>,
    /// Specific resourceVersion to which this reference is made, if any.
    /// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "resourceVersion"
    )]
    pub resource_version: Option<String>,
    /// UID of the referent.
    /// More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub uid: Option<String>,
}

/// UnhealthyCondition represents a Node condition type and value with a timeout
/// specified as a duration.  When the named condition has been in the given
/// status for at least the timeout value, a node is considered unhealthy.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterTopologyWorkersMachineDeploymentsMachineHealthCheckUnhealthyConditions {
    pub status: String,
    pub timeout: String,
    #[serde(rename = "type")]
    pub r#type: String,
}

/// metadata is the metadata applied to the MachineDeployment and the machines of the MachineDeployment.
/// At runtime this metadata is merged with the corresponding metadata from the ClusterClass.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterTopologyWorkersMachineDeploymentsMetadata {
    /// annotations is an unstructured key value map stored with a resource that may be
    /// set by external tools to store and retrieve arbitrary metadata. They are not
    /// queryable and should be preserved when modifying objects.
    /// More info: http://kubernetes.io/docs/user-guide/annotations
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub annotations: Option<BTreeMap<String, String>>,
    /// Map of string keys and values that can be used to organize and categorize
    /// (scope and select) objects. May match selectors of replication controllers
    /// and services.
    /// More info: http://kubernetes.io/docs/user-guide/labels
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub labels: Option<BTreeMap<String, String>>,
}

/// The deployment strategy to use to replace existing machines with
/// new ones.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterTopologyWorkersMachineDeploymentsStrategy {
    /// remediation controls the strategy of remediating unhealthy machines
    /// and how remediating operations should occur during the lifecycle of the dependant MachineSets.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub remediation: Option<ClusterTopologyWorkersMachineDeploymentsStrategyRemediation>,
    /// Rolling update config params. Present only if
    /// MachineDeploymentStrategyType = RollingUpdate.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "rollingUpdate"
    )]
    pub rolling_update: Option<ClusterTopologyWorkersMachineDeploymentsStrategyRollingUpdate>,
    /// type of deployment. Allowed values are RollingUpdate and OnDelete.
    /// The default is RollingUpdate.
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "type")]
    pub r#type: Option<ClusterTopologyWorkersMachineDeploymentsStrategyType>,
}

/// remediation controls the strategy of remediating unhealthy machines
/// and how remediating operations should occur during the lifecycle of the dependant MachineSets.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterTopologyWorkersMachineDeploymentsStrategyRemediation {
    /// maxInFlight determines how many in flight remediations should happen at the same time.
    ///
    /// Remediation only happens on the MachineSet with the most current revision, while
    /// older MachineSets (usually present during rollout operations) aren't allowed to remediate.
    ///
    /// Note: In general (independent of remediations), unhealthy machines are always
    /// prioritized during scale down operations over healthy ones.
    ///
    /// MaxInFlight can be set to a fixed number or a percentage.
    /// Example: when this is set to 20%, the MachineSet controller deletes at most 20% of
    /// the desired replicas.
    ///
    /// If not set, remediation is limited to all machines (bounded by replicas)
    /// under the active MachineSet's management.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "maxInFlight"
    )]
    pub max_in_flight: Option<IntOrString>,
}

/// Rolling update config params. Present only if
/// MachineDeploymentStrategyType = RollingUpdate.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterTopologyWorkersMachineDeploymentsStrategyRollingUpdate {
    /// deletePolicy defines the policy used by the MachineDeployment to identify nodes to delete when downscaling.
    /// Valid values are "Random, "Newest", "Oldest"
    /// When no value is supplied, the default DeletePolicy of MachineSet is used
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "deletePolicy"
    )]
    pub delete_policy:
        Option<ClusterTopologyWorkersMachineDeploymentsStrategyRollingUpdateDeletePolicy>,
    /// The maximum number of machines that can be scheduled above the
    /// desired number of machines.
    /// Value can be an absolute number (ex: 5) or a percentage of
    /// desired machines (ex: 10%).
    /// This can not be 0 if MaxUnavailable is 0.
    /// Absolute number is calculated from percentage by rounding up.
    /// Defaults to 1.
    /// Example: when this is set to 30%, the new MachineSet can be scaled
    /// up immediately when the rolling update starts, such that the total
    /// number of old and new machines do not exceed 130% of desired
    /// machines. Once old machines have been killed, new MachineSet can
    /// be scaled up further, ensuring that total number of machines running
    /// at any time during the update is at most 130% of desired machines.
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "maxSurge")]
    pub max_surge: Option<IntOrString>,
    /// The maximum number of machines that can be unavailable during the update.
    /// Value can be an absolute number (ex: 5) or a percentage of desired
    /// machines (ex: 10%).
    /// Absolute number is calculated from percentage by rounding down.
    /// This can not be 0 if MaxSurge is 0.
    /// Defaults to 0.
    /// Example: when this is set to 30%, the old MachineSet can be scaled
    /// down to 70% of desired machines immediately when the rolling update
    /// starts. Once new machines are ready, old MachineSet can be scaled
    /// down further, followed by scaling up the new MachineSet, ensuring
    /// that the total number of machines available at all times
    /// during the update is at least 70% of desired machines.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "maxUnavailable"
    )]
    pub max_unavailable: Option<IntOrString>,
}

/// Rolling update config params. Present only if
/// MachineDeploymentStrategyType = RollingUpdate.
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub enum ClusterTopologyWorkersMachineDeploymentsStrategyRollingUpdateDeletePolicy {
    Random,
    Newest,
    Oldest,
}

/// The deployment strategy to use to replace existing machines with
/// new ones.
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub enum ClusterTopologyWorkersMachineDeploymentsStrategyType {
    RollingUpdate,
    OnDelete,
}

/// variables can be used to customize the MachineDeployment through patches.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterTopologyWorkersMachineDeploymentsVariables {
    /// overrides can be used to override Cluster level variables.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub overrides: Option<Vec<ClusterTopologyWorkersMachineDeploymentsVariablesOverrides>>,
}

/// ClusterVariable can be used to customize the Cluster through patches. Each ClusterVariable is associated with a
/// Variable definition in the ClusterClass `status` variables.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterTopologyWorkersMachineDeploymentsVariablesOverrides {
    /// definitionFrom specifies where the definition of this Variable is from.
    ///
    /// Deprecated: This field is deprecated, must not be set anymore and is going to be removed in the next apiVersion.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "definitionFrom"
    )]
    pub definition_from: Option<String>,
    /// name of the variable.
    pub name: String,
    /// value of the variable.
    /// Note: the value will be validated against the schema of the corresponding ClusterClassVariable
    /// from the ClusterClass.
    /// Note: We have to use apiextensionsv1.JSON instead of a custom JSON type, because controller-tools has a
    /// hard-coded schema for apiextensionsv1.JSON which cannot be produced by another type via controller-tools,
    /// i.e. it is not possible to have no type field.
    /// Ref: https://github.com/kubernetes-sigs/controller-tools/blob/d0e03a142d0ecdd5491593e941ee1d6b5d91dba6/pkg/crd/known_types.go#L106-L111
    pub value: serde_json::Value,
}

/// MachinePoolTopology specifies the different parameters for a pool of worker nodes in the topology.
/// This pool of nodes is managed by a MachinePool object whose lifecycle is managed by the Cluster controller.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterTopologyWorkersMachinePools {
    /// class is the name of the MachinePoolClass used to create the pool of worker nodes.
    /// This should match one of the deployment classes defined in the ClusterClass object
    /// mentioned in the `Cluster.Spec.Class` field.
    pub class: String,
    /// failureDomains is the list of failure domains the machine pool will be created in.
    /// Must match a key in the FailureDomains map stored on the cluster object.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "failureDomains"
    )]
    pub failure_domains: Option<Vec<String>>,
    /// metadata is the metadata applied to the MachinePool.
    /// At runtime this metadata is merged with the corresponding metadata from the ClusterClass.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub metadata: Option<ClusterTopologyWorkersMachinePoolsMetadata>,
    /// Minimum number of seconds for which a newly created machine pool should
    /// be ready.
    /// Defaults to 0 (machine will be considered available as soon as it
    /// is ready)
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "minReadySeconds"
    )]
    pub min_ready_seconds: Option<i32>,
    /// name is the unique identifier for this MachinePoolTopology.
    /// The value is used with other unique identifiers to create a MachinePool's Name
    /// (e.g. cluster's name, etc). In case the name is greater than the allowed maximum length,
    /// the values are hashed together.
    pub name: String,
    /// nodeDeletionTimeout defines how long the controller will attempt to delete the Node that the MachinePool
    /// hosts after the MachinePool is marked for deletion. A duration of 0 will retry deletion indefinitely.
    /// Defaults to 10 seconds.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "nodeDeletionTimeout"
    )]
    pub node_deletion_timeout: Option<String>,
    /// nodeDrainTimeout is the total amount of time that the controller will spend on draining a node.
    /// The default value is 0, meaning that the node can be drained without any time limitations.
    /// NOTE: NodeDrainTimeout is different from `kubectl drain --timeout`
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "nodeDrainTimeout"
    )]
    pub node_drain_timeout: Option<String>,
    /// nodeVolumeDetachTimeout is the total amount of time that the controller will spend on waiting for all volumes
    /// to be detached. The default value is 0, meaning that the volumes can be detached without any time limitations.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "nodeVolumeDetachTimeout"
    )]
    pub node_volume_detach_timeout: Option<String>,
    /// replicas is the number of nodes belonging to this pool.
    /// If the value is nil, the MachinePool is created without the number of Replicas (defaulting to 1)
    /// and it's assumed that an external entity (like cluster autoscaler) is responsible for the management
    /// of this value.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub replicas: Option<i32>,
    /// variables can be used to customize the MachinePool through patches.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub variables: Option<ClusterTopologyWorkersMachinePoolsVariables>,
}

/// metadata is the metadata applied to the MachinePool.
/// At runtime this metadata is merged with the corresponding metadata from the ClusterClass.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterTopologyWorkersMachinePoolsMetadata {
    /// annotations is an unstructured key value map stored with a resource that may be
    /// set by external tools to store and retrieve arbitrary metadata. They are not
    /// queryable and should be preserved when modifying objects.
    /// More info: http://kubernetes.io/docs/user-guide/annotations
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub annotations: Option<BTreeMap<String, String>>,
    /// Map of string keys and values that can be used to organize and categorize
    /// (scope and select) objects. May match selectors of replication controllers
    /// and services.
    /// More info: http://kubernetes.io/docs/user-guide/labels
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub labels: Option<BTreeMap<String, String>>,
}

/// variables can be used to customize the MachinePool through patches.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterTopologyWorkersMachinePoolsVariables {
    /// overrides can be used to override Cluster level variables.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub overrides: Option<Vec<ClusterTopologyWorkersMachinePoolsVariablesOverrides>>,
}

/// ClusterVariable can be used to customize the Cluster through patches. Each ClusterVariable is associated with a
/// Variable definition in the ClusterClass `status` variables.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterTopologyWorkersMachinePoolsVariablesOverrides {
    /// definitionFrom specifies where the definition of this Variable is from.
    ///
    /// Deprecated: This field is deprecated, must not be set anymore and is going to be removed in the next apiVersion.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "definitionFrom"
    )]
    pub definition_from: Option<String>,
    /// name of the variable.
    pub name: String,
    /// value of the variable.
    /// Note: the value will be validated against the schema of the corresponding ClusterClassVariable
    /// from the ClusterClass.
    /// Note: We have to use apiextensionsv1.JSON instead of a custom JSON type, because controller-tools has a
    /// hard-coded schema for apiextensionsv1.JSON which cannot be produced by another type via controller-tools,
    /// i.e. it is not possible to have no type field.
    /// Ref: https://github.com/kubernetes-sigs/controller-tools/blob/d0e03a142d0ecdd5491593e941ee1d6b5d91dba6/pkg/crd/known_types.go#L106-L111
    pub value: serde_json::Value,
}

/// ClusterStatus defines the observed state of Cluster.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterStatus {
    /// conditions defines current service state of the cluster.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub conditions: Option<Vec<Condition>>,
    /// controlPlaneReady denotes if the control plane became ready during initial provisioning
    /// to receive requests.
    /// NOTE: this field is part of the Cluster API contract and it is used to orchestrate provisioning.
    /// The value of this field is never updated after provisioning is completed. Please use conditions
    /// to check the operational state of the control plane.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "controlPlaneReady"
    )]
    pub control_plane_ready: Option<bool>,
    /// failureDomains is a slice of failure domain objects synced from the infrastructure provider.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "failureDomains"
    )]
    pub failure_domains: Option<BTreeMap<String, ClusterStatusFailureDomains>>,
    /// failureMessage indicates that there is a fatal problem reconciling the
    /// state, and will be set to a descriptive error message.
    ///
    /// Deprecated: This field is deprecated and is going to be removed in the next apiVersion. Please see https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more details.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "failureMessage"
    )]
    pub failure_message: Option<String>,
    /// failureReason indicates that there is a fatal problem reconciling the
    /// state, and will be set to a token value suitable for
    /// programmatic interpretation.
    ///
    /// Deprecated: This field is deprecated and is going to be removed in the next apiVersion. Please see https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more details.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "failureReason"
    )]
    pub failure_reason: Option<String>,
    /// infrastructureReady is the state of the infrastructure provider.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "infrastructureReady"
    )]
    pub infrastructure_ready: Option<bool>,
    /// observedGeneration is the latest generation observed by the controller.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "observedGeneration"
    )]
    pub observed_generation: Option<i64>,
    /// phase represents the current phase of cluster actuation.
    /// E.g. Pending, Running, Terminating, Failed etc.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub phase: Option<String>,
    /// v1beta2 groups all the fields that will be added or modified in Cluster's status with the V1Beta2 version.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub v1beta2: Option<ClusterStatusV1beta2>,
}

/// failureDomains is a slice of failure domain objects synced from the infrastructure provider.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterStatusFailureDomains {
    /// attributes is a free form map of attributes an infrastructure provider might use or require.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub attributes: Option<BTreeMap<String, String>>,
    /// controlPlane determines if this failure domain is suitable for use by control plane machines.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "controlPlane"
    )]
    pub control_plane: Option<bool>,
}

/// v1beta2 groups all the fields that will be added or modified in Cluster's status with the V1Beta2 version.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterStatusV1beta2 {
    /// conditions represents the observations of a Cluster's current state.
    /// Known condition types are Available, InfrastructureReady, ControlPlaneInitialized, ControlPlaneAvailable, WorkersAvailable, MachinesReady
    /// MachinesUpToDate, RemoteConnectionProbe, ScalingUp, ScalingDown, Remediating, Deleting, Paused.
    /// Additionally, a TopologyReconciled condition will be added in case the Cluster is referencing a ClusterClass / defining a managed Topology.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub conditions: Option<Vec<Condition>>,
    /// controlPlane groups all the observations about Cluster's ControlPlane current state.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "controlPlane"
    )]
    pub control_plane: Option<ClusterStatusV1beta2ControlPlane>,
    /// workers groups all the observations about Cluster's Workers current state.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub workers: Option<ClusterStatusV1beta2Workers>,
}

/// controlPlane groups all the observations about Cluster's ControlPlane current state.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterStatusV1beta2ControlPlane {
    /// availableReplicas is the total number of available control plane machines in this cluster. A machine is considered available when Machine's Available condition is true.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "availableReplicas"
    )]
    pub available_replicas: Option<i32>,
    /// desiredReplicas is the total number of desired control plane machines in this cluster.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "desiredReplicas"
    )]
    pub desired_replicas: Option<i32>,
    /// readyReplicas is the total number of ready control plane machines in this cluster. A machine is considered ready when Machine's Ready condition is true.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "readyReplicas"
    )]
    pub ready_replicas: Option<i32>,
    /// replicas is the total number of control plane machines in this cluster.
    /// NOTE: replicas also includes machines still being provisioned or being deleted.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub replicas: Option<i32>,
    /// upToDateReplicas is the number of up-to-date control plane machines in this cluster. A machine is considered up-to-date when Machine's UpToDate condition is true.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "upToDateReplicas"
    )]
    pub up_to_date_replicas: Option<i32>,
}

/// workers groups all the observations about Cluster's Workers current state.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterStatusV1beta2Workers {
    /// availableReplicas is the total number of available worker machines in this cluster. A machine is considered available when Machine's Available condition is true.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "availableReplicas"
    )]
    pub available_replicas: Option<i32>,
    /// desiredReplicas is the total number of desired worker machines in this cluster.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "desiredReplicas"
    )]
    pub desired_replicas: Option<i32>,
    /// readyReplicas is the total number of ready worker machines in this cluster. A machine is considered ready when Machine's Ready condition is true.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "readyReplicas"
    )]
    pub ready_replicas: Option<i32>,
    /// replicas is the total number of worker machines in this cluster.
    /// NOTE: replicas also includes machines still being provisioned or being deleted.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub replicas: Option<i32>,
    /// upToDateReplicas is the number of up-to-date worker machines in this cluster. A machine is considered up-to-date when Machine's UpToDate condition is true.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "upToDateReplicas"
    )]
    pub up_to_date_replicas: Option<i32>,
}
