// WARNING: generated by kopium - manual changes will be overwritten
// kopium command: kopium -D Default -D PartialEq -A -d clusterclasses.cluster.x-k8s.io
// 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::*;

/// ClusterClassSpec describes the desired state of the ClusterClass.
#[derive(CustomResource, Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
#[kube(
    group = "cluster.x-k8s.io",
    version = "v1beta1",
    kind = "ClusterClass",
    plural = "clusterclasses"
)]
#[kube(namespaced)]
#[kube(status = "ClusterClassStatus")]
#[kube(derive = "Default")]
#[kube(derive = "PartialEq")]
pub struct ClusterClassSpec {
    /// ControlPlane is a reference to a local struct that holds the details
    /// for provisioning the Control Plane for the Cluster.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "controlPlane"
    )]
    pub control_plane: Option<ClusterClassControlPlane>,
    /// Infrastructure is a reference to a provider-specific template that holds
    /// the details for provisioning infrastructure specific cluster
    /// for the underlying provider.
    /// The underlying provider is responsible for the implementation
    /// of the template to an infrastructure cluster.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub infrastructure: Option<ClusterClassInfrastructure>,
    /// Patches defines the patches which are applied to customize
    /// referenced templates of a ClusterClass.
    /// Note: Patches will be applied in the order of the array.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub patches: Option<Vec<ClusterClassPatches>>,
    /// Variables defines the variables which can be configured
    /// in the Cluster topology and are then used in patches.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub variables: Option<Vec<ClusterClassVariables>>,
    /// Workers describes the worker nodes for the cluster.
    /// It is a collection of node types which can be used to create
    /// the worker nodes of the cluster.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub workers: Option<ClusterClassWorkers>,
}

/// ControlPlane is a reference to a local struct that holds the details
/// for provisioning the Control Plane for the Cluster.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterClassControlPlane {
    /// MachineHealthCheck defines a MachineHealthCheck for this ControlPlaneClass.
    /// This field is supported if and only if the ControlPlane provider template
    /// referenced above is Machine based and supports setting replicas.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "machineHealthCheck"
    )]
    pub machine_health_check: Option<ClusterClassControlPlaneMachineHealthCheck>,
    /// MachineInfrastructure defines the metadata and infrastructure information
    /// for control plane machines.
    ///
    ///
    /// This field is supported if and only if the control plane provider template
    /// referenced above is Machine based and supports setting replicas.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "machineInfrastructure"
    )]
    pub machine_infrastructure: Option<ClusterClassControlPlaneMachineInfrastructure>,
    /// Metadata is the metadata applied to the ControlPlane and the Machines of the ControlPlane
    /// if the ControlPlaneTemplate referenced is machine based. If not, it is applied only to the
    /// ControlPlane.
    /// At runtime this metadata is merged with the corresponding metadata from the topology.
    ///
    ///
    /// This field is supported if and only if the control plane provider template
    /// referenced is Machine based.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub metadata: Option<ClusterClassControlPlaneMetadata>,
    /// NamingStrategy allows changing the naming pattern used when creating the control plane provider object.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "namingStrategy"
    )]
    pub naming_strategy: Option<ClusterClassControlPlaneNamingStrategy>,
    /// 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.
    /// NOTE: This value can be overridden while defining a Cluster.Topology.
    #[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`
    /// NOTE: This value can be overridden while defining a Cluster.Topology.
    #[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.
    /// NOTE: This value can be overridden while defining a Cluster.Topology.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "nodeVolumeDetachTimeout"
    )]
    pub node_volume_detach_timeout: Option<String>,
    /// Ref is a required reference to a custom resource
    /// offered by a provider.
    #[serde(rename = "ref")]
    pub r#ref: ObjectReference,
}

/// MachineHealthCheck defines a MachineHealthCheck for this ControlPlaneClass.
/// This field is supported if and only if the ControlPlane provider template
/// referenced above is Machine based and supports setting replicas.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterClassControlPlaneMachineHealthCheck {
    /// 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<ClusterClassControlPlaneMachineHealthCheckUnhealthyConditions>>,
    /// 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 ClusterClassControlPlaneMachineHealthCheckRemediationTemplate {
    /// 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.
    /// TODO: this design is not final and this field is subject to change in the future.
    #[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 ClusterClassControlPlaneMachineHealthCheckUnhealthyConditions {
    pub status: String,
    pub timeout: String,
    #[serde(rename = "type")]
    pub r#type: String,
}

/// MachineInfrastructure defines the metadata and infrastructure information
/// for control plane machines.
///
///
/// This field is supported if and only if the control plane provider template
/// referenced above is Machine based and supports setting replicas.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterClassControlPlaneMachineInfrastructure {
    /// Ref is a required reference to a custom resource
    /// offered by a provider.
    #[serde(rename = "ref")]
    pub r#ref: ObjectReference,
}

/// Ref is a required reference to a custom resource
/// offered by a provider.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterClassControlPlaneMachineInfrastructureRef {
    /// 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.
    /// TODO: this design is not final and this field is subject to change in the future.
    #[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>,
}

/// Metadata is the metadata applied to the ControlPlane and the Machines of the ControlPlane
/// if the ControlPlaneTemplate referenced is machine based. If not, it is applied only to the
/// ControlPlane.
/// At runtime this metadata is merged with the corresponding metadata from the topology.
///
///
/// This field is supported if and only if the control plane provider template
/// referenced is Machine based.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterClassControlPlaneMetadata {
    /// 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>>,
}

/// NamingStrategy allows changing the naming pattern used when creating the control plane provider object.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterClassControlPlaneNamingStrategy {
    /// Template defines the template to use for generating the name of the ControlPlane object.
    /// If not defined, it will fallback to `{{ .cluster.name }}-{{ .random }}`.
    /// If the templated string exceeds 63 characters, it will be trimmed to 58 characters and will
    /// get concatenated with a random suffix of length 5.
    /// The templating mechanism provides the following arguments:
    /// * `.cluster.name`: The name of the cluster object.
    /// * `.random`: A random alphanumeric string, without vowels, of length 5.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub template: Option<String>,
}

/// Ref is a required reference to a custom resource
/// offered by a provider.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterClassControlPlaneRef {
    /// 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.
    /// TODO: this design is not final and this field is subject to change in the future.
    #[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>,
}

/// Infrastructure is a reference to a provider-specific template that holds
/// the details for provisioning infrastructure specific cluster
/// for the underlying provider.
/// The underlying provider is responsible for the implementation
/// of the template to an infrastructure cluster.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterClassInfrastructure {
    /// Ref is a required reference to a custom resource
    /// offered by a provider.
    #[serde(rename = "ref")]
    pub r#ref: ObjectReference,
}

/// Ref is a required reference to a custom resource
/// offered by a provider.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterClassInfrastructureRef {
    /// 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.
    /// TODO: this design is not final and this field is subject to change in the future.
    #[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>,
}

/// ClusterClassPatch defines a patch which is applied to customize the referenced templates.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterClassPatches {
    /// Definitions define inline patches.
    /// Note: Patches will be applied in the order of the array.
    /// Note: Exactly one of Definitions or External must be set.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub definitions: Option<Vec<ClusterClassPatchesDefinitions>>,
    /// Description is a human-readable description of this patch.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub description: Option<String>,
    /// EnabledIf is a Go template to be used to calculate if a patch should be enabled.
    /// It can reference variables defined in .spec.variables and builtin variables.
    /// The patch will be enabled if the template evaluates to `true`, otherwise it will
    /// be disabled.
    /// If EnabledIf is not set, the patch will be enabled per default.
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "enabledIf")]
    pub enabled_if: Option<String>,
    /// External defines an external patch.
    /// Note: Exactly one of Definitions or External must be set.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub external: Option<ClusterClassPatchesExternal>,
    /// Name of the patch.
    pub name: String,
}

/// PatchDefinition defines a patch which is applied to customize the referenced templates.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterClassPatchesDefinitions {
    /// JSONPatches defines the patches which should be applied on the templates
    /// matching the selector.
    /// Note: Patches will be applied in the order of the array.
    #[serde(rename = "jsonPatches")]
    pub json_patches: Vec<ClusterClassPatchesDefinitionsJsonPatches>,
    /// Selector defines on which templates the patch should be applied.
    pub selector: ClusterClassPatchesDefinitionsSelector,
}

/// JSONPatch defines a JSON patch.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterClassPatchesDefinitionsJsonPatches {
    /// Op defines the operation of the patch.
    /// Note: Only `add`, `replace` and `remove` are supported.
    pub op: String,
    /// Path defines the path of the patch.
    /// Note: Only the spec of a template can be patched, thus the path has to start with /spec/.
    /// Note: For now the only allowed array modifications are `append` and `prepend`, i.e.:
    /// * for op: `add`: only index 0 (prepend) and - (append) are allowed
    /// * for op: `replace` or `remove`: no indexes are allowed
    pub path: String,
    /// Value defines the value of the patch.
    /// Note: Either Value or ValueFrom is required for add and replace
    /// operations. Only one of them is allowed to be set at the same time.
    /// Note: We have to use apiextensionsv1.JSON instead of our JSON type,
    /// because controller-tools has a hard-coded schema for apiextensionsv1.JSON
    /// which cannot be produced by another type (unset type field).
    /// Ref: https://github.com/kubernetes-sigs/controller-tools/blob/d0e03a142d0ecdd5491593e941ee1d6b5d91dba6/pkg/crd/known_types.go#L106-L111
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub value: Option<serde_json::Value>,
    /// ValueFrom defines the value of the patch.
    /// Note: Either Value or ValueFrom is required for add and replace
    /// operations. Only one of them is allowed to be set at the same time.
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "valueFrom")]
    pub value_from: Option<ClusterClassPatchesDefinitionsJsonPatchesValueFrom>,
}

/// ValueFrom defines the value of the patch.
/// Note: Either Value or ValueFrom is required for add and replace
/// operations. Only one of them is allowed to be set at the same time.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterClassPatchesDefinitionsJsonPatchesValueFrom {
    /// Template is the Go template to be used to calculate the value.
    /// A template can reference variables defined in .spec.variables and builtin variables.
    /// Note: The template must evaluate to a valid YAML or JSON value.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub template: Option<String>,
    /// Variable is the variable to be used as value.
    /// Variable can be one of the variables defined in .spec.variables or a builtin variable.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub variable: Option<String>,
}

/// Selector defines on which templates the patch should be applied.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterClassPatchesDefinitionsSelector {
    /// APIVersion filters templates by apiVersion.
    #[serde(rename = "apiVersion")]
    pub api_version: String,
    /// Kind filters templates by kind.
    pub kind: String,
    /// MatchResources selects templates based on where they are referenced.
    #[serde(rename = "matchResources")]
    pub match_resources: ClusterClassPatchesDefinitionsSelectorMatchResources,
}

/// MatchResources selects templates based on where they are referenced.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterClassPatchesDefinitionsSelectorMatchResources {
    /// ControlPlane selects templates referenced in .spec.ControlPlane.
    /// Note: this will match the controlPlane and also the controlPlane
    /// machineInfrastructure (depending on the kind and apiVersion).
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "controlPlane"
    )]
    pub control_plane: Option<bool>,
    /// InfrastructureCluster selects templates referenced in .spec.infrastructure.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "infrastructureCluster"
    )]
    pub infrastructure_cluster: Option<bool>,
    /// MachineDeploymentClass selects templates referenced in specific MachineDeploymentClasses in
    /// .spec.workers.machineDeployments.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "machineDeploymentClass"
    )]
    pub machine_deployment_class:
        Option<ClusterClassPatchesDefinitionsSelectorMatchResourcesMachineDeploymentClass>,
    /// MachinePoolClass selects templates referenced in specific MachinePoolClasses in
    /// .spec.workers.machinePools.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "machinePoolClass"
    )]
    pub machine_pool_class:
        Option<ClusterClassPatchesDefinitionsSelectorMatchResourcesMachinePoolClass>,
}

/// MachineDeploymentClass selects templates referenced in specific MachineDeploymentClasses in
/// .spec.workers.machineDeployments.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterClassPatchesDefinitionsSelectorMatchResourcesMachineDeploymentClass {
    /// Names selects templates by class names.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub names: Option<Vec<String>>,
}

/// MachinePoolClass selects templates referenced in specific MachinePoolClasses in
/// .spec.workers.machinePools.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterClassPatchesDefinitionsSelectorMatchResourcesMachinePoolClass {
    /// Names selects templates by class names.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub names: Option<Vec<String>>,
}

/// External defines an external patch.
/// Note: Exactly one of Definitions or External must be set.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterClassPatchesExternal {
    /// DiscoverVariablesExtension references an extension which is called to discover variables.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "discoverVariablesExtension"
    )]
    pub discover_variables_extension: Option<String>,
    /// GenerateExtension references an extension which is called to generate patches.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "generateExtension"
    )]
    pub generate_extension: Option<String>,
    /// Settings defines key value pairs to be passed to the extensions.
    /// Values defined here take precedence over the values defined in the
    /// corresponding ExtensionConfig.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub settings: Option<BTreeMap<String, String>>,
    /// ValidateExtension references an extension which is called to validate the topology.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "validateExtension"
    )]
    pub validate_extension: Option<String>,
}

/// ClusterClassVariable defines a variable which can
/// be configured in the Cluster topology and used in patches.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterClassVariables {
    /// Metadata is the metadata of a variable.
    /// It can be used to add additional data for higher level tools to
    /// a ClusterClassVariable.
    ///
    ///
    /// Deprecated: This field is deprecated and is going to be removed in the next apiVersion. Please use XMetadata in JSONSchemaProps instead.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub metadata: Option<ClusterClassVariablesMetadata>,
    /// Name of the variable.
    pub name: String,
    /// Required specifies if the variable is required.
    /// Note: this applies to the variable as a whole and thus the
    /// top-level object defined in the schema. If nested fields are
    /// required, this will be specified inside the schema.
    pub required: bool,
    /// Schema defines the schema of the variable.
    pub schema: ClusterClassVariablesSchema,
}

/// Metadata is the metadata of a variable.
/// It can be used to add additional data for higher level tools to
/// a ClusterClassVariable.
///
///
/// Deprecated: This field is deprecated and is going to be removed in the next apiVersion. Please use XMetadata in JSONSchemaProps instead.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterClassVariablesMetadata {
    /// Annotations is an unstructured key value map that can be used to store and
    /// retrieve arbitrary metadata.
    /// They are not queryable.
    #[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) variables.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub labels: Option<BTreeMap<String, String>>,
}

/// Schema defines the schema of the variable.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterClassVariablesSchema {
    /// OpenAPIV3Schema defines the schema of a variable via OpenAPI v3
    /// schema. The schema is a subset of the schema used in
    /// Kubernetes CRDs.
    #[serde(rename = "openAPIV3Schema")]
    pub open_apiv3_schema: ClusterClassVariablesSchemaOpenApiv3Schema,
}

/// OpenAPIV3Schema defines the schema of a variable via OpenAPI v3
/// schema. The schema is a subset of the schema used in
/// Kubernetes CRDs.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterClassVariablesSchemaOpenApiv3Schema {
    /// AdditionalProperties specifies the schema of values in a map (keys are always strings).
    /// NOTE: Can only be set if type is object.
    /// NOTE: AdditionalProperties is mutually exclusive with Properties.
    /// NOTE: This field uses PreserveUnknownFields and Schemaless,
    /// because recursive validation is not possible.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "additionalProperties"
    )]
    pub additional_properties: Option<serde_json::Value>,
    /// Default is the default value of the variable.
    /// NOTE: Can be set for all types.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub default: Option<serde_json::Value>,
    /// Description is a human-readable description of this variable.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub description: Option<String>,
    /// Enum is the list of valid values of the variable.
    /// NOTE: Can be set for all types.
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "enum")]
    pub r#enum: Option<Vec<serde_json::Value>>,
    /// Example is an example for this variable.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub example: Option<serde_json::Value>,
    /// ExclusiveMaximum specifies if the Maximum is exclusive.
    /// NOTE: Can only be set if type is integer or number.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "exclusiveMaximum"
    )]
    pub exclusive_maximum: Option<bool>,
    /// ExclusiveMinimum specifies if the Minimum is exclusive.
    /// NOTE: Can only be set if type is integer or number.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "exclusiveMinimum"
    )]
    pub exclusive_minimum: Option<bool>,
    /// Format is an OpenAPI v3 format string. Unknown formats are ignored.
    /// For a list of supported formats please see: (of the k8s.io/apiextensions-apiserver version we're currently using)
    /// https://github.com/kubernetes/apiextensions-apiserver/blob/master/pkg/apiserver/validation/formats.go
    /// NOTE: Can only be set if type is string.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub format: Option<String>,
    /// Items specifies fields of an array.
    /// NOTE: Can only be set if type is array.
    /// NOTE: This field uses PreserveUnknownFields and Schemaless,
    /// because recursive validation is not possible.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub items: Option<serde_json::Value>,
    /// MaxItems is the max length of an array variable.
    /// NOTE: Can only be set if type is array.
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "maxItems")]
    pub max_items: Option<i64>,
    /// MaxLength is the max length of a string variable.
    /// NOTE: Can only be set if type is string.
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "maxLength")]
    pub max_length: Option<i64>,
    /// MaxProperties is the maximum amount of entries in a map or properties in an object.
    /// NOTE: Can only be set if type is object.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "maxProperties"
    )]
    pub max_properties: Option<i64>,
    /// Maximum is the maximum of an integer or number variable.
    /// If ExclusiveMaximum is false, the variable is valid if it is lower than, or equal to, the value of Maximum.
    /// If ExclusiveMaximum is true, the variable is valid if it is strictly lower than the value of Maximum.
    /// NOTE: Can only be set if type is integer or number.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub maximum: Option<i64>,
    /// MinItems is the min length of an array variable.
    /// NOTE: Can only be set if type is array.
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "minItems")]
    pub min_items: Option<i64>,
    /// MinLength is the min length of a string variable.
    /// NOTE: Can only be set if type is string.
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "minLength")]
    pub min_length: Option<i64>,
    /// MinProperties is the minimum amount of entries in a map or properties in an object.
    /// NOTE: Can only be set if type is object.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "minProperties"
    )]
    pub min_properties: Option<i64>,
    /// Minimum is the minimum of an integer or number variable.
    /// If ExclusiveMinimum is false, the variable is valid if it is greater than, or equal to, the value of Minimum.
    /// If ExclusiveMinimum is true, the variable is valid if it is strictly greater than the value of Minimum.
    /// NOTE: Can only be set if type is integer or number.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub minimum: Option<i64>,
    /// Pattern is the regex which a string variable must match.
    /// NOTE: Can only be set if type is string.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub pattern: Option<String>,
    /// Properties specifies fields of an object.
    /// NOTE: Can only be set if type is object.
    /// NOTE: Properties is mutually exclusive with AdditionalProperties.
    /// NOTE: This field uses PreserveUnknownFields and Schemaless,
    /// because recursive validation is not possible.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub properties: Option<serde_json::Value>,
    /// Required specifies which fields of an object are required.
    /// NOTE: Can only be set if type is object.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub required: Option<Vec<String>>,
    /// Type is the type of the variable.
    /// Valid values are: object, array, string, integer, number or boolean.
    #[serde(rename = "type")]
    pub r#type: String,
    /// UniqueItems specifies if items in an array must be unique.
    /// NOTE: Can only be set if type is array.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "uniqueItems"
    )]
    pub unique_items: Option<bool>,
    /// XPreserveUnknownFields allows setting fields in a variable object
    /// which are not defined in the variable schema. This affects fields recursively,
    /// except if nested properties or additionalProperties are specified in the schema.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "x-kubernetes-preserve-unknown-fields"
    )]
    pub x_kubernetes_preserve_unknown_fields: Option<bool>,
    /// XValidations describes a list of validation rules written in the CEL expression language.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "x-kubernetes-validations"
    )]
    pub x_kubernetes_validations:
        Option<Vec<ClusterClassVariablesSchemaOpenApiv3SchemaXKubernetesValidations>>,
    /// XMetadata is the metadata of a variable or a nested field within a variable.
    /// It can be used to add additional data for higher level tools.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "x-metadata"
    )]
    pub x_metadata: Option<ClusterClassVariablesSchemaOpenApiv3SchemaXMetadata>,
}

/// ValidationRule describes a validation rule written in the CEL expression language.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterClassVariablesSchemaOpenApiv3SchemaXKubernetesValidations {
    /// FieldPath represents the field path returned when the validation fails.
    /// It must be a relative JSON path (i.e. with array notation) scoped to the location of this x-kubernetes-validations extension in the schema and refer to an existing field.
    /// e.g. when validation checks if a specific attribute `foo` under a map `testMap`, the fieldPath could be set to `.testMap.foo`
    /// If the validation checks two lists must have unique attributes, the fieldPath could be set to either of the list: e.g. `.testList`
    /// It does not support list numeric index.
    /// It supports child operation to refer to an existing field currently. Refer to [JSONPath support in Kubernetes](https://kubernetes.io/docs/reference/kubectl/jsonpath/) for more info.
    /// Numeric index of array is not supported.
    /// For field name which contains special characters, use `['specialName']` to refer the field name.
    /// e.g. for attribute `foo.34$` appears in a list `testList`, the fieldPath could be set to `.testList['foo.34$']`
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "fieldPath")]
    pub field_path: Option<String>,
    /// Message represents the message displayed when validation fails. The message is required if the Rule contains
    /// line breaks. The message must not contain line breaks.
    /// If unset, the message is "failed rule: {Rule}".
    /// e.g. "must be a URL with the host matching spec.host"
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub message: Option<String>,
    /// MessageExpression declares a CEL expression that evaluates to the validation failure message that is returned when this rule fails.
    /// Since messageExpression is used as a failure message, it must evaluate to a string.
    /// If both message and messageExpression are present on a rule, then messageExpression will be used if validation
    /// fails. If messageExpression results in a runtime error, the validation failure message is produced
    /// as if the messageExpression field were unset. If messageExpression evaluates to an empty string, a string with only spaces, or a string
    /// that contains line breaks, then the validation failure message will also be produced as if the messageExpression field were unset.
    /// messageExpression has access to all the same variables as the rule; the only difference is the return type.
    /// Example:
    /// "x must be less than max ("+string(self.max)+")"
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "messageExpression"
    )]
    pub message_expression: Option<String>,
    /// Reason provides a machine-readable validation failure reason that is returned to the caller when a request fails this validation rule.
    /// The currently supported reasons are: "FieldValueInvalid", "FieldValueForbidden", "FieldValueRequired", "FieldValueDuplicate".
    /// If not set, default to use "FieldValueInvalid".
    /// All future added reasons must be accepted by clients when reading this value and unknown reasons should be treated as FieldValueInvalid.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub reason: Option<ClusterClassVariablesSchemaOpenApiv3SchemaXKubernetesValidationsReason>,
    /// Rule represents the expression which will be evaluated by CEL.
    /// ref: https://github.com/google/cel-spec
    /// The Rule is scoped to the location of the x-kubernetes-validations extension in the schema.
    /// The `self` variable in the CEL expression is bound to the scoped value.
    /// If the Rule is scoped to an object with properties, the accessible properties of the object are field selectable
    /// via `self.field` and field presence can be checked via `has(self.field)`.
    /// If the Rule is scoped to an object with additionalProperties (i.e. a map) the value of the map
    /// are accessible via `self[mapKey]`, map containment can be checked via `mapKey in self` and all entries of the map
    /// are accessible via CEL macros and functions such as `self.all(...)`.
    /// If the Rule is scoped to an array, the elements of the array are accessible via `self[i]` and also by macros and
    /// functions.
    /// If the Rule is scoped to a scalar, `self` is bound to the scalar value.
    /// Examples:
    /// - Rule scoped to a map of objects: {"rule": "self.components['Widget'].priority < 10"}
    /// - Rule scoped to a list of integers: {"rule": "self.values.all(value, value >= 0 && value < 100)"}
    /// - Rule scoped to a string value: {"rule": "self.startsWith('kube')"}
    ///
    ///
    /// Unknown data preserved in custom resources via x-kubernetes-preserve-unknown-fields is not accessible in CEL
    /// expressions. This includes:
    /// - Unknown field values that are preserved by object schemas with x-kubernetes-preserve-unknown-fields.
    /// - Object properties where the property schema is of an "unknown type". An "unknown type" is recursively defined as:
    ///   - A schema with no type and x-kubernetes-preserve-unknown-fields set to true
    ///   - An array where the items schema is of an "unknown type"
    ///   - An object where the additionalProperties schema is of an "unknown type"
    ///
    ///
    /// Only property names of the form `[a-zA-Z_.-/][a-zA-Z0-9_.-/]*` are accessible.
    /// Accessible property names are escaped according to the following rules when accessed in the expression:
    /// - '__' escapes to '__underscores__'
    /// - '.' escapes to '__dot__'
    /// - '-' escapes to '__dash__'
    /// - '/' escapes to '__slash__'
    /// - Property names that exactly match a CEL RESERVED keyword escape to '__{keyword}__'. The keywords are:
    /// 	  "true", "false", "null", "in", "as", "break", "const", "continue", "else", "for", "function", "if",
    /// 	  "import", "let", "loop", "package", "namespace", "return".
    /// Examples:
    ///   - Rule accessing a property named "namespace": {"rule": "self.__namespace__ > 0"}
    ///   - Rule accessing a property named "x-prop": {"rule": "self.x__dash__prop > 0"}
    ///   - Rule accessing a property named "redact__d": {"rule": "self.redact__underscores__d > 0"}
    ///
    ///
    /// If `rule` makes use of the `oldSelf` variable it is implicitly a
    /// `transition rule`.
    ///
    ///
    /// By default, the `oldSelf` variable is the same type as `self`.
    ///
    ///
    /// Transition rules by default are applied only on UPDATE requests and are
    /// skipped if an old value could not be found.
    pub rule: String,
}

/// ValidationRule describes a validation rule written in the CEL expression language.
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub enum ClusterClassVariablesSchemaOpenApiv3SchemaXKubernetesValidationsReason {
    FieldValueInvalid,
    FieldValueForbidden,
    FieldValueRequired,
    FieldValueDuplicate,
}

/// XMetadata is the metadata of a variable or a nested field within a variable.
/// It can be used to add additional data for higher level tools.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterClassVariablesSchemaOpenApiv3SchemaXMetadata {
    /// Annotations is an unstructured key value map that can be used to store and
    /// retrieve arbitrary metadata.
    /// They are not queryable.
    #[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) variables.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub labels: Option<BTreeMap<String, String>>,
}

/// Workers describes the worker nodes for the cluster.
/// It is a collection of node types which can be used to create
/// the worker nodes of the cluster.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterClassWorkers {
    /// MachineDeployments is a list of machine deployment classes that can be used to create
    /// a set of worker nodes.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "machineDeployments"
    )]
    pub machine_deployments: Option<Vec<ClusterClassWorkersMachineDeployments>>,
    /// MachinePools is a list of machine pool classes that can be used to create
    /// a set of worker nodes.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "machinePools"
    )]
    pub machine_pools: Option<Vec<ClusterClassWorkersMachinePools>>,
}

/// MachineDeploymentClass serves as a template to define a set of worker nodes of the cluster
/// provisioned using the `ClusterClass`.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterClassWorkersMachineDeployments {
    /// Class denotes a type of worker node present in the cluster,
    /// this name MUST be unique within a ClusterClass and can be referenced
    /// in the Cluster to create a managed MachineDeployment.
    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.
    /// NOTE: This value can be overridden while defining a Cluster.Topology using this MachineDeploymentClass.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "failureDomain"
    )]
    pub failure_domain: Option<String>,
    /// MachineHealthCheck defines a MachineHealthCheck for this MachineDeploymentClass.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "machineHealthCheck"
    )]
    pub machine_health_check: Option<ClusterClassWorkersMachineDeploymentsMachineHealthCheck>,
    /// 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)
    /// NOTE: This value can be overridden while defining a Cluster.Topology using this MachineDeploymentClass.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "minReadySeconds"
    )]
    pub min_ready_seconds: Option<i32>,
    /// NamingStrategy allows changing the naming pattern used when creating the MachineDeployment.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "namingStrategy"
    )]
    pub naming_strategy: Option<ClusterClassWorkersMachineDeploymentsNamingStrategy>,
    /// 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.
    /// NOTE: This value can be overridden while defining a Cluster.Topology using this MachineDeploymentClass.
    #[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`
    /// NOTE: This value can be overridden while defining a Cluster.Topology using this MachineDeploymentClass.
    #[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.
    /// NOTE: This value can be overridden while defining a Cluster.Topology using this MachineDeploymentClass.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "nodeVolumeDetachTimeout"
    )]
    pub node_volume_detach_timeout: Option<String>,
    /// The deployment strategy to use to replace existing machines with
    /// new ones.
    /// NOTE: This value can be overridden while defining a Cluster.Topology using this MachineDeploymentClass.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub strategy: Option<ClusterClassWorkersMachineDeploymentsStrategy>,
    /// Template is a local struct containing a collection of templates for creation of
    /// MachineDeployment objects representing a set of worker nodes.
    pub template: ClusterClassWorkersMachineDeploymentsTemplate,
}

/// MachineHealthCheck defines a MachineHealthCheck for this MachineDeploymentClass.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterClassWorkersMachineDeploymentsMachineHealthCheck {
    /// 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<ClusterClassWorkersMachineDeploymentsMachineHealthCheckUnhealthyConditions>>,
    /// 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 ClusterClassWorkersMachineDeploymentsMachineHealthCheckRemediationTemplate {
    /// 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.
    /// TODO: this design is not final and this field is subject to change in the future.
    #[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 ClusterClassWorkersMachineDeploymentsMachineHealthCheckUnhealthyConditions {
    pub status: String,
    pub timeout: String,
    #[serde(rename = "type")]
    pub r#type: String,
}

/// NamingStrategy allows changing the naming pattern used when creating the MachineDeployment.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterClassWorkersMachineDeploymentsNamingStrategy {
    /// Template defines the template to use for generating the name of the MachineDeployment object.
    /// If not defined, it will fallback to `{{ .cluster.name }}-{{ .machineDeployment.topologyName }}-{{ .random }}`.
    /// If the templated string exceeds 63 characters, it will be trimmed to 58 characters and will
    /// get concatenated with a random suffix of length 5.
    /// The templating mechanism provides the following arguments:
    /// * `.cluster.name`: The name of the cluster object.
    /// * `.random`: A random alphanumeric string, without vowels, of length 5.
    /// * `.machineDeployment.topologyName`: The name of the MachineDeployment topology (Cluster.spec.topology.workers.machineDeployments[].name).
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub template: Option<String>,
}

/// The deployment strategy to use to replace existing machines with
/// new ones.
/// NOTE: This value can be overridden while defining a Cluster.Topology using this MachineDeploymentClass.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterClassWorkersMachineDeploymentsStrategy {
    /// 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<ClusterClassWorkersMachineDeploymentsStrategyRemediation>,
    /// Rolling update config params. Present only if
    /// MachineDeploymentStrategyType = RollingUpdate.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "rollingUpdate"
    )]
    pub rolling_update: Option<ClusterClassWorkersMachineDeploymentsStrategyRollingUpdate>,
    /// 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<ClusterClassWorkersMachineDeploymentsStrategyType>,
}

/// 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 ClusterClassWorkersMachineDeploymentsStrategyRemediation {
    /// 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 ClusterClassWorkersMachineDeploymentsStrategyRollingUpdate {
    /// 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<ClusterClassWorkersMachineDeploymentsStrategyRollingUpdateDeletePolicy>,
    /// 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 ClusterClassWorkersMachineDeploymentsStrategyRollingUpdateDeletePolicy {
    Random,
    Newest,
    Oldest,
}

/// The deployment strategy to use to replace existing machines with
/// new ones.
/// NOTE: This value can be overridden while defining a Cluster.Topology using this MachineDeploymentClass.
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub enum ClusterClassWorkersMachineDeploymentsStrategyType {
    RollingUpdate,
    OnDelete,
}

/// Template is a local struct containing a collection of templates for creation of
/// MachineDeployment objects representing a set of worker nodes.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterClassWorkersMachineDeploymentsTemplate {
    /// Bootstrap contains the bootstrap template reference to be used
    /// for the creation of worker Machines.
    pub bootstrap: ClusterClassWorkersMachineDeploymentsTemplateBootstrap,
    /// Infrastructure contains the infrastructure template reference to be used
    /// for the creation of worker Machines.
    pub infrastructure: ClusterClassWorkersMachineDeploymentsTemplateInfrastructure,
    /// 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 topology.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub metadata: Option<ClusterClassWorkersMachineDeploymentsTemplateMetadata>,
}

/// Bootstrap contains the bootstrap template reference to be used
/// for the creation of worker Machines.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterClassWorkersMachineDeploymentsTemplateBootstrap {
    /// Ref is a required reference to a custom resource
    /// offered by a provider.
    #[serde(rename = "ref")]
    pub r#ref: ObjectReference,
}

/// Ref is a required reference to a custom resource
/// offered by a provider.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterClassWorkersMachineDeploymentsTemplateBootstrapRef {
    /// 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.
    /// TODO: this design is not final and this field is subject to change in the future.
    #[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>,
}

/// Infrastructure contains the infrastructure template reference to be used
/// for the creation of worker Machines.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterClassWorkersMachineDeploymentsTemplateInfrastructure {
    /// Ref is a required reference to a custom resource
    /// offered by a provider.
    #[serde(rename = "ref")]
    pub r#ref: ObjectReference,
}

/// Ref is a required reference to a custom resource
/// offered by a provider.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterClassWorkersMachineDeploymentsTemplateInfrastructureRef {
    /// 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.
    /// TODO: this design is not final and this field is subject to change in the future.
    #[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>,
}

/// 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 topology.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterClassWorkersMachineDeploymentsTemplateMetadata {
    /// 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>>,
}

/// MachinePoolClass serves as a template to define a pool of worker nodes of the cluster
/// provisioned using `ClusterClass`.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterClassWorkersMachinePools {
    /// Class denotes a type of machine pool present in the cluster,
    /// this name MUST be unique within a ClusterClass and can be referenced
    /// in the Cluster to create a managed MachinePool.
    pub class: String,
    /// FailureDomains is the list of failure domains the MachinePool should be attached to.
    /// Must match a key in the FailureDomains map stored on the cluster object.
    /// NOTE: This value can be overridden while defining a Cluster.Topology using this MachinePoolClass.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "failureDomains"
    )]
    pub failure_domains: Option<Vec<String>>,
    /// 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)
    /// NOTE: This value can be overridden while defining a Cluster.Topology using this MachinePoolClass.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "minReadySeconds"
    )]
    pub min_ready_seconds: Option<i32>,
    /// NamingStrategy allows changing the naming pattern used when creating the MachinePool.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "namingStrategy"
    )]
    pub naming_strategy: Option<ClusterClassWorkersMachinePoolsNamingStrategy>,
    /// NodeDeletionTimeout defines how long the controller will attempt to delete the Node that the Machine
    /// hosts after the Machine Pool is marked for deletion. A duration of 0 will retry deletion indefinitely.
    /// Defaults to 10 seconds.
    /// NOTE: This value can be overridden while defining a Cluster.Topology using this MachinePoolClass.
    #[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`
    /// NOTE: This value can be overridden while defining a Cluster.Topology using this MachinePoolClass.
    #[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.
    /// NOTE: This value can be overridden while defining a Cluster.Topology using this MachinePoolClass.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "nodeVolumeDetachTimeout"
    )]
    pub node_volume_detach_timeout: Option<String>,
    /// Template is a local struct containing a collection of templates for creation of
    /// MachinePools objects representing a pool of worker nodes.
    pub template: ClusterClassWorkersMachinePoolsTemplate,
}

/// NamingStrategy allows changing the naming pattern used when creating the MachinePool.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterClassWorkersMachinePoolsNamingStrategy {
    /// Template defines the template to use for generating the name of the MachinePool object.
    /// If not defined, it will fallback to `{{ .cluster.name }}-{{ .machinePool.topologyName }}-{{ .random }}`.
    /// If the templated string exceeds 63 characters, it will be trimmed to 58 characters and will
    /// get concatenated with a random suffix of length 5.
    /// The templating mechanism provides the following arguments:
    /// * `.cluster.name`: The name of the cluster object.
    /// * `.random`: A random alphanumeric string, without vowels, of length 5.
    /// * `.machinePool.topologyName`: The name of the MachinePool topology (Cluster.spec.topology.workers.machinePools[].name).
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub template: Option<String>,
}

/// Template is a local struct containing a collection of templates for creation of
/// MachinePools objects representing a pool of worker nodes.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterClassWorkersMachinePoolsTemplate {
    /// Bootstrap contains the bootstrap template reference to be used
    /// for the creation of the Machines in the MachinePool.
    pub bootstrap: ClusterClassWorkersMachinePoolsTemplateBootstrap,
    /// Infrastructure contains the infrastructure template reference to be used
    /// for the creation of the MachinePool.
    pub infrastructure: ClusterClassWorkersMachinePoolsTemplateInfrastructure,
    /// Metadata is the metadata applied to the MachinePool.
    /// At runtime this metadata is merged with the corresponding metadata from the topology.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub metadata: Option<ClusterClassWorkersMachinePoolsTemplateMetadata>,
}

/// Bootstrap contains the bootstrap template reference to be used
/// for the creation of the Machines in the MachinePool.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterClassWorkersMachinePoolsTemplateBootstrap {
    /// Ref is a required reference to a custom resource
    /// offered by a provider.
    #[serde(rename = "ref")]
    pub r#ref: ObjectReference,
}

/// Ref is a required reference to a custom resource
/// offered by a provider.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterClassWorkersMachinePoolsTemplateBootstrapRef {
    /// 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.
    /// TODO: this design is not final and this field is subject to change in the future.
    #[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>,
}

/// Infrastructure contains the infrastructure template reference to be used
/// for the creation of the MachinePool.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterClassWorkersMachinePoolsTemplateInfrastructure {
    /// Ref is a required reference to a custom resource
    /// offered by a provider.
    #[serde(rename = "ref")]
    pub r#ref: ObjectReference,
}

/// Ref is a required reference to a custom resource
/// offered by a provider.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterClassWorkersMachinePoolsTemplateInfrastructureRef {
    /// 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.
    /// TODO: this design is not final and this field is subject to change in the future.
    #[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>,
}

/// Metadata is the metadata applied to the MachinePool.
/// At runtime this metadata is merged with the corresponding metadata from the topology.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterClassWorkersMachinePoolsTemplateMetadata {
    /// 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>>,
}

/// ClusterClassStatus defines the observed state of the ClusterClass.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterClassStatus {
    /// Conditions defines current observed state of the ClusterClass.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub conditions: Option<Vec<Condition>>,
    /// ObservedGeneration is the latest generation observed by the controller.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "observedGeneration"
    )]
    pub observed_generation: Option<i64>,
    /// Variables is a list of ClusterClassStatusVariable that are defined for the ClusterClass.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub variables: Option<Vec<ClusterClassStatusVariables>>,
}

/// ClusterClassStatusVariable defines a variable which appears in the status of a ClusterClass.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterClassStatusVariables {
    /// Definitions is a list of definitions for a variable.
    pub definitions: Vec<ClusterClassStatusVariablesDefinitions>,
    /// DefinitionsConflict specifies whether or not there are conflicting definitions for a single variable name.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "definitionsConflict"
    )]
    pub definitions_conflict: Option<bool>,
    /// Name is the name of the variable.
    pub name: String,
}

/// ClusterClassStatusVariableDefinition defines a variable which appears in the status of a ClusterClass.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterClassStatusVariablesDefinitions {
    /// From specifies the origin of the variable definition.
    /// This will be `inline` for variables defined in the ClusterClass or the name of a patch defined in the ClusterClass
    /// for variables discovered from a DiscoverVariables runtime extensions.
    pub from: String,
    /// Metadata is the metadata of a variable.
    /// It can be used to add additional data for higher level tools to
    /// a ClusterClassVariable.
    ///
    ///
    /// Deprecated: This field is deprecated and is going to be removed in the next apiVersion.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub metadata: Option<ClusterClassStatusVariablesDefinitionsMetadata>,
    /// Required specifies if the variable is required.
    /// Note: this applies to the variable as a whole and thus the
    /// top-level object defined in the schema. If nested fields are
    /// required, this will be specified inside the schema.
    pub required: bool,
    /// Schema defines the schema of the variable.
    pub schema: ClusterClassStatusVariablesDefinitionsSchema,
}

/// Metadata is the metadata of a variable.
/// It can be used to add additional data for higher level tools to
/// a ClusterClassVariable.
///
///
/// Deprecated: This field is deprecated and is going to be removed in the next apiVersion.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterClassStatusVariablesDefinitionsMetadata {
    /// Annotations is an unstructured key value map that can be used to store and
    /// retrieve arbitrary metadata.
    /// They are not queryable.
    #[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) variables.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub labels: Option<BTreeMap<String, String>>,
}

/// Schema defines the schema of the variable.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterClassStatusVariablesDefinitionsSchema {
    /// OpenAPIV3Schema defines the schema of a variable via OpenAPI v3
    /// schema. The schema is a subset of the schema used in
    /// Kubernetes CRDs.
    #[serde(rename = "openAPIV3Schema")]
    pub open_apiv3_schema: ClusterClassStatusVariablesDefinitionsSchemaOpenApiv3Schema,
}

/// OpenAPIV3Schema defines the schema of a variable via OpenAPI v3
/// schema. The schema is a subset of the schema used in
/// Kubernetes CRDs.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterClassStatusVariablesDefinitionsSchemaOpenApiv3Schema {
    /// AdditionalProperties specifies the schema of values in a map (keys are always strings).
    /// NOTE: Can only be set if type is object.
    /// NOTE: AdditionalProperties is mutually exclusive with Properties.
    /// NOTE: This field uses PreserveUnknownFields and Schemaless,
    /// because recursive validation is not possible.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "additionalProperties"
    )]
    pub additional_properties: Option<serde_json::Value>,
    /// Default is the default value of the variable.
    /// NOTE: Can be set for all types.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub default: Option<serde_json::Value>,
    /// Description is a human-readable description of this variable.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub description: Option<String>,
    /// Enum is the list of valid values of the variable.
    /// NOTE: Can be set for all types.
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "enum")]
    pub r#enum: Option<Vec<serde_json::Value>>,
    /// Example is an example for this variable.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub example: Option<serde_json::Value>,
    /// ExclusiveMaximum specifies if the Maximum is exclusive.
    /// NOTE: Can only be set if type is integer or number.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "exclusiveMaximum"
    )]
    pub exclusive_maximum: Option<bool>,
    /// ExclusiveMinimum specifies if the Minimum is exclusive.
    /// NOTE: Can only be set if type is integer or number.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "exclusiveMinimum"
    )]
    pub exclusive_minimum: Option<bool>,
    /// Format is an OpenAPI v3 format string. Unknown formats are ignored.
    /// For a list of supported formats please see: (of the k8s.io/apiextensions-apiserver version we're currently using)
    /// https://github.com/kubernetes/apiextensions-apiserver/blob/master/pkg/apiserver/validation/formats.go
    /// NOTE: Can only be set if type is string.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub format: Option<String>,
    /// Items specifies fields of an array.
    /// NOTE: Can only be set if type is array.
    /// NOTE: This field uses PreserveUnknownFields and Schemaless,
    /// because recursive validation is not possible.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub items: Option<serde_json::Value>,
    /// MaxItems is the max length of an array variable.
    /// NOTE: Can only be set if type is array.
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "maxItems")]
    pub max_items: Option<i64>,
    /// MaxLength is the max length of a string variable.
    /// NOTE: Can only be set if type is string.
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "maxLength")]
    pub max_length: Option<i64>,
    /// MaxProperties is the maximum amount of entries in a map or properties in an object.
    /// NOTE: Can only be set if type is object.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "maxProperties"
    )]
    pub max_properties: Option<i64>,
    /// Maximum is the maximum of an integer or number variable.
    /// If ExclusiveMaximum is false, the variable is valid if it is lower than, or equal to, the value of Maximum.
    /// If ExclusiveMaximum is true, the variable is valid if it is strictly lower than the value of Maximum.
    /// NOTE: Can only be set if type is integer or number.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub maximum: Option<i64>,
    /// MinItems is the min length of an array variable.
    /// NOTE: Can only be set if type is array.
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "minItems")]
    pub min_items: Option<i64>,
    /// MinLength is the min length of a string variable.
    /// NOTE: Can only be set if type is string.
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "minLength")]
    pub min_length: Option<i64>,
    /// MinProperties is the minimum amount of entries in a map or properties in an object.
    /// NOTE: Can only be set if type is object.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "minProperties"
    )]
    pub min_properties: Option<i64>,
    /// Minimum is the minimum of an integer or number variable.
    /// If ExclusiveMinimum is false, the variable is valid if it is greater than, or equal to, the value of Minimum.
    /// If ExclusiveMinimum is true, the variable is valid if it is strictly greater than the value of Minimum.
    /// NOTE: Can only be set if type is integer or number.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub minimum: Option<i64>,
    /// Pattern is the regex which a string variable must match.
    /// NOTE: Can only be set if type is string.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub pattern: Option<String>,
    /// Properties specifies fields of an object.
    /// NOTE: Can only be set if type is object.
    /// NOTE: Properties is mutually exclusive with AdditionalProperties.
    /// NOTE: This field uses PreserveUnknownFields and Schemaless,
    /// because recursive validation is not possible.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub properties: Option<serde_json::Value>,
    /// Required specifies which fields of an object are required.
    /// NOTE: Can only be set if type is object.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub required: Option<Vec<String>>,
    /// Type is the type of the variable.
    /// Valid values are: object, array, string, integer, number or boolean.
    #[serde(rename = "type")]
    pub r#type: String,
    /// UniqueItems specifies if items in an array must be unique.
    /// NOTE: Can only be set if type is array.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "uniqueItems"
    )]
    pub unique_items: Option<bool>,
    /// XPreserveUnknownFields allows setting fields in a variable object
    /// which are not defined in the variable schema. This affects fields recursively,
    /// except if nested properties or additionalProperties are specified in the schema.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "x-kubernetes-preserve-unknown-fields"
    )]
    pub x_kubernetes_preserve_unknown_fields: Option<bool>,
    /// XValidations describes a list of validation rules written in the CEL expression language.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "x-kubernetes-validations"
    )]
    pub x_kubernetes_validations: Option<
        Vec<ClusterClassStatusVariablesDefinitionsSchemaOpenApiv3SchemaXKubernetesValidations>,
    >,
    /// XMetadata is the metadata of a variable or a nested field within a variable.
    /// It can be used to add additional data for higher level tools.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "x-metadata"
    )]
    pub x_metadata: Option<ClusterClassStatusVariablesDefinitionsSchemaOpenApiv3SchemaXMetadata>,
}

/// ValidationRule describes a validation rule written in the CEL expression language.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterClassStatusVariablesDefinitionsSchemaOpenApiv3SchemaXKubernetesValidations {
    /// FieldPath represents the field path returned when the validation fails.
    /// It must be a relative JSON path (i.e. with array notation) scoped to the location of this x-kubernetes-validations extension in the schema and refer to an existing field.
    /// e.g. when validation checks if a specific attribute `foo` under a map `testMap`, the fieldPath could be set to `.testMap.foo`
    /// If the validation checks two lists must have unique attributes, the fieldPath could be set to either of the list: e.g. `.testList`
    /// It does not support list numeric index.
    /// It supports child operation to refer to an existing field currently. Refer to [JSONPath support in Kubernetes](https://kubernetes.io/docs/reference/kubectl/jsonpath/) for more info.
    /// Numeric index of array is not supported.
    /// For field name which contains special characters, use `['specialName']` to refer the field name.
    /// e.g. for attribute `foo.34$` appears in a list `testList`, the fieldPath could be set to `.testList['foo.34$']`
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "fieldPath")]
    pub field_path: Option<String>,
    /// Message represents the message displayed when validation fails. The message is required if the Rule contains
    /// line breaks. The message must not contain line breaks.
    /// If unset, the message is "failed rule: {Rule}".
    /// e.g. "must be a URL with the host matching spec.host"
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub message: Option<String>,
    /// MessageExpression declares a CEL expression that evaluates to the validation failure message that is returned when this rule fails.
    /// Since messageExpression is used as a failure message, it must evaluate to a string.
    /// If both message and messageExpression are present on a rule, then messageExpression will be used if validation
    /// fails. If messageExpression results in a runtime error, the validation failure message is produced
    /// as if the messageExpression field were unset. If messageExpression evaluates to an empty string, a string with only spaces, or a string
    /// that contains line breaks, then the validation failure message will also be produced as if the messageExpression field were unset.
    /// messageExpression has access to all the same variables as the rule; the only difference is the return type.
    /// Example:
    /// "x must be less than max ("+string(self.max)+")"
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "messageExpression"
    )]
    pub message_expression: Option<String>,
    /// Reason provides a machine-readable validation failure reason that is returned to the caller when a request fails this validation rule.
    /// The currently supported reasons are: "FieldValueInvalid", "FieldValueForbidden", "FieldValueRequired", "FieldValueDuplicate".
    /// If not set, default to use "FieldValueInvalid".
    /// All future added reasons must be accepted by clients when reading this value and unknown reasons should be treated as FieldValueInvalid.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub reason: Option<
        ClusterClassStatusVariablesDefinitionsSchemaOpenApiv3SchemaXKubernetesValidationsReason,
    >,
    /// Rule represents the expression which will be evaluated by CEL.
    /// ref: https://github.com/google/cel-spec
    /// The Rule is scoped to the location of the x-kubernetes-validations extension in the schema.
    /// The `self` variable in the CEL expression is bound to the scoped value.
    /// If the Rule is scoped to an object with properties, the accessible properties of the object are field selectable
    /// via `self.field` and field presence can be checked via `has(self.field)`.
    /// If the Rule is scoped to an object with additionalProperties (i.e. a map) the value of the map
    /// are accessible via `self[mapKey]`, map containment can be checked via `mapKey in self` and all entries of the map
    /// are accessible via CEL macros and functions such as `self.all(...)`.
    /// If the Rule is scoped to an array, the elements of the array are accessible via `self[i]` and also by macros and
    /// functions.
    /// If the Rule is scoped to a scalar, `self` is bound to the scalar value.
    /// Examples:
    /// - Rule scoped to a map of objects: {"rule": "self.components['Widget'].priority < 10"}
    /// - Rule scoped to a list of integers: {"rule": "self.values.all(value, value >= 0 && value < 100)"}
    /// - Rule scoped to a string value: {"rule": "self.startsWith('kube')"}
    ///
    ///
    /// Unknown data preserved in custom resources via x-kubernetes-preserve-unknown-fields is not accessible in CEL
    /// expressions. This includes:
    /// - Unknown field values that are preserved by object schemas with x-kubernetes-preserve-unknown-fields.
    /// - Object properties where the property schema is of an "unknown type". An "unknown type" is recursively defined as:
    ///   - A schema with no type and x-kubernetes-preserve-unknown-fields set to true
    ///   - An array where the items schema is of an "unknown type"
    ///   - An object where the additionalProperties schema is of an "unknown type"
    ///
    ///
    /// Only property names of the form `[a-zA-Z_.-/][a-zA-Z0-9_.-/]*` are accessible.
    /// Accessible property names are escaped according to the following rules when accessed in the expression:
    /// - '__' escapes to '__underscores__'
    /// - '.' escapes to '__dot__'
    /// - '-' escapes to '__dash__'
    /// - '/' escapes to '__slash__'
    /// - Property names that exactly match a CEL RESERVED keyword escape to '__{keyword}__'. The keywords are:
    /// 	  "true", "false", "null", "in", "as", "break", "const", "continue", "else", "for", "function", "if",
    /// 	  "import", "let", "loop", "package", "namespace", "return".
    /// Examples:
    ///   - Rule accessing a property named "namespace": {"rule": "self.__namespace__ > 0"}
    ///   - Rule accessing a property named "x-prop": {"rule": "self.x__dash__prop > 0"}
    ///   - Rule accessing a property named "redact__d": {"rule": "self.redact__underscores__d > 0"}
    ///
    ///
    /// If `rule` makes use of the `oldSelf` variable it is implicitly a
    /// `transition rule`.
    ///
    ///
    /// By default, the `oldSelf` variable is the same type as `self`.
    ///
    ///
    /// Transition rules by default are applied only on UPDATE requests and are
    /// skipped if an old value could not be found.
    pub rule: String,
}

/// ValidationRule describes a validation rule written in the CEL expression language.
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub enum ClusterClassStatusVariablesDefinitionsSchemaOpenApiv3SchemaXKubernetesValidationsReason {
    FieldValueInvalid,
    FieldValueForbidden,
    FieldValueRequired,
    FieldValueDuplicate,
}

/// XMetadata is the metadata of a variable or a nested field within a variable.
/// It can be used to add additional data for higher level tools.
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)]
pub struct ClusterClassStatusVariablesDefinitionsSchemaOpenApiv3SchemaXMetadata {
    /// Annotations is an unstructured key value map that can be used to store and
    /// retrieve arbitrary metadata.
    /// They are not queryable.
    #[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) variables.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub labels: Option<BTreeMap<String, String>>,
}
