{
  "description": "ClusterClass is a template which can be used to create managed topologies.",
  "properties": {
    "apiVersion": {
      "description": "APIVersion defines the versioned schema of this representation of an object.\nServers should convert recognized schemas to the latest internal value, and\nmay reject unrecognized values.\nMore info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources",
      "type": "string"
    },
    "kind": {
      "description": "Kind is a string value representing the REST resource this object represents.\nServers may infer this from the endpoint the client submits requests to.\nCannot be updated.\nIn CamelCase.\nMore info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
      "type": "string"
    },
    "metadata": {
      "type": "object"
    },
    "spec": {
      "description": "spec is the desired state of ClusterClass.",
      "properties": {
        "availabilityGates": {
          "description": "availabilityGates specifies additional conditions to include when evaluating Cluster Available condition.\n\nNOTE: this field is considered only for computing v1beta2 conditions.\nNOTE: If a Cluster is using this ClusterClass, and this Cluster defines a custom list of availabilityGates,\nsuch list overrides availabilityGates defined in this field.",
          "items": {
            "description": "ClusterAvailabilityGate contains the type of a Cluster condition to be used as availability gate.",
            "properties": {
              "conditionType": {
                "description": "conditionType refers to a condition with matching type in the Cluster's condition list.\nIf the conditions doesn't exist, it will be treated as unknown.\nNote: Both Cluster API conditions or conditions added by 3rd party controllers can be used as availability gates.",
                "maxLength": 316,
                "minLength": 1,
                "pattern": "^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$",
                "type": "string"
              },
              "polarity": {
                "description": "polarity of the conditionType specified in this availabilityGate.\nValid values are Positive, Negative and omitted.\nWhen omitted, the default behaviour will be Positive.\nA positive polarity means that the condition should report a true status under normal conditions.\nA negative polarity means that the condition should report a false status under normal conditions.",
                "enum": [
                  "Positive",
                  "Negative"
                ],
                "type": "string"
              }
            },
            "required": [
              "conditionType"
            ],
            "type": "object",
            "additionalProperties": false
          },
          "maxItems": 32,
          "type": "array",
          "x-kubernetes-list-map-keys": [
            "conditionType"
          ],
          "x-kubernetes-list-type": "map"
        },
        "controlPlane": {
          "description": "controlPlane is a reference to a local struct that holds the details\nfor provisioning the Control Plane for the Cluster.",
          "properties": {
            "machineHealthCheck": {
              "description": "machineHealthCheck defines a MachineHealthCheck for this ControlPlaneClass.\nThis field is supported if and only if the ControlPlane provider template\nreferenced above is Machine based and supports setting replicas.",
              "properties": {
                "maxUnhealthy": {
                  "anyOf": [
                    {
                      "type": "integer"
                    },
                    {
                      "type": "string"
                    }
                  ],
                  "description": "maxUnhealthy specifies the maximum number of unhealthy machines allowed.\nAny further remediation is only allowed if at most \"maxUnhealthy\" machines selected by\n\"selector\" are not healthy.",
                  "x-kubernetes-int-or-string": true
                },
                "nodeStartupTimeout": {
                  "description": "nodeStartupTimeout allows to set the maximum time for MachineHealthCheck\nto consider a Machine unhealthy if a corresponding Node isn't associated\nthrough a `Spec.ProviderID` field.\n\nThe duration set in this field is compared to the greatest of:\n- Cluster's infrastructure ready condition timestamp (if and when available)\n- Control Plane's initialized condition timestamp (if and when available)\n- Machine's infrastructure ready condition timestamp (if and when available)\n- Machine's metadata creation timestamp\n\nDefaults to 10 minutes.\nIf you wish to disable this feature, set the value explicitly to 0.",
                  "type": "string"
                },
                "remediationTemplate": {
                  "description": "remediationTemplate is a reference to a remediation template\nprovided by an infrastructure provider.\n\nThis field is completely optional, when filled, the MachineHealthCheck controller\ncreates a new object from the template referenced and hands off remediation of the machine to\na controller that lives outside of Cluster API.",
                  "properties": {
                    "apiVersion": {
                      "description": "API version of the referent.",
                      "type": "string"
                    },
                    "fieldPath": {
                      "description": "If referring to a piece of an object instead of an entire object, this string\nshould contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2].\nFor example, if the object reference is to a container within a pod, this would take on a value like:\n\"spec.containers{name}\" (where \"name\" refers to the name of the container that triggered\nthe event) or if no container name is specified \"spec.containers[2]\" (container with\nindex 2 in this pod). This syntax is chosen only to have some well-defined way of\nreferencing a part of an object.",
                      "type": "string"
                    },
                    "kind": {
                      "description": "Kind of the referent.\nMore info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
                      "type": "string"
                    },
                    "name": {
                      "description": "Name of the referent.\nMore info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names",
                      "type": "string"
                    },
                    "namespace": {
                      "description": "Namespace of the referent.\nMore info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/",
                      "type": "string"
                    },
                    "resourceVersion": {
                      "description": "Specific resourceVersion to which this reference is made, if any.\nMore info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency",
                      "type": "string"
                    },
                    "uid": {
                      "description": "UID of the referent.\nMore info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids",
                      "type": "string"
                    }
                  },
                  "type": "object",
                  "x-kubernetes-map-type": "atomic",
                  "additionalProperties": false
                },
                "unhealthyConditions": {
                  "description": "unhealthyConditions contains a list of the conditions that determine\nwhether a node is considered unhealthy. The conditions are combined in a\nlogical OR, i.e. if any of the conditions is met, the node is unhealthy.",
                  "items": {
                    "description": "UnhealthyCondition represents a Node condition type and value with a timeout\nspecified as a duration.  When the named condition has been in the given\nstatus for at least the timeout value, a node is considered unhealthy.",
                    "properties": {
                      "status": {
                        "description": "status of the condition, one of True, False, Unknown.",
                        "minLength": 1,
                        "type": "string"
                      },
                      "timeout": {
                        "description": "timeout is the duration that a node must be in a given status for,\nafter which the node is considered unhealthy.\nFor example, with a value of \"1h\", the node must match the status\nfor at least 1 hour before being considered unhealthy.",
                        "type": "string"
                      },
                      "type": {
                        "description": "type of Node condition",
                        "minLength": 1,
                        "type": "string"
                      }
                    },
                    "required": [
                      "status",
                      "timeout",
                      "type"
                    ],
                    "type": "object",
                    "additionalProperties": false
                  },
                  "maxItems": 100,
                  "type": "array"
                },
                "unhealthyRange": {
                  "description": "unhealthyRange specifies the range of unhealthy machines allowed.\nAny further remediation is only allowed if the number of machines selected by \"selector\" as not healthy\nis within the range of \"unhealthyRange\". Takes precedence over maxUnhealthy.\nEg. \"[3-5]\" - This means that remediation will be allowed only when:\n(a) there are at least 3 unhealthy machines (and)\n(b) there are at most 5 unhealthy machines",
                  "maxLength": 32,
                  "minLength": 1,
                  "pattern": "^\\[[0-9]+-[0-9]+\\]$",
                  "type": "string"
                }
              },
              "type": "object",
              "additionalProperties": false
            },
            "machineInfrastructure": {
              "description": "machineInfrastructure defines the metadata and infrastructure information\nfor control plane machines.\n\nThis field is supported if and only if the control plane provider template\nreferenced above is Machine based and supports setting replicas.",
              "properties": {
                "ref": {
                  "description": "ref is a required reference to a custom resource\noffered by a provider.",
                  "properties": {
                    "apiVersion": {
                      "description": "API version of the referent.",
                      "type": "string"
                    },
                    "fieldPath": {
                      "description": "If referring to a piece of an object instead of an entire object, this string\nshould contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2].\nFor example, if the object reference is to a container within a pod, this would take on a value like:\n\"spec.containers{name}\" (where \"name\" refers to the name of the container that triggered\nthe event) or if no container name is specified \"spec.containers[2]\" (container with\nindex 2 in this pod). This syntax is chosen only to have some well-defined way of\nreferencing a part of an object.",
                      "type": "string"
                    },
                    "kind": {
                      "description": "Kind of the referent.\nMore info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
                      "type": "string"
                    },
                    "name": {
                      "description": "Name of the referent.\nMore info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names",
                      "type": "string"
                    },
                    "namespace": {
                      "description": "Namespace of the referent.\nMore info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/",
                      "type": "string"
                    },
                    "resourceVersion": {
                      "description": "Specific resourceVersion to which this reference is made, if any.\nMore info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency",
                      "type": "string"
                    },
                    "uid": {
                      "description": "UID of the referent.\nMore info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids",
                      "type": "string"
                    }
                  },
                  "type": "object",
                  "x-kubernetes-map-type": "atomic",
                  "additionalProperties": false
                }
              },
              "required": [
                "ref"
              ],
              "type": "object",
              "additionalProperties": false
            },
            "metadata": {
              "description": "metadata is the metadata applied to the ControlPlane and the Machines of the ControlPlane\nif the ControlPlaneTemplate referenced is machine based. If not, it is applied only to the\nControlPlane.\nAt runtime this metadata is merged with the corresponding metadata from the topology.\n\nThis field is supported if and only if the control plane provider template\nreferenced is Machine based.",
              "properties": {
                "annotations": {
                  "additionalProperties": {
                    "type": "string"
                  },
                  "description": "annotations is an unstructured key value map stored with a resource that may be\nset by external tools to store and retrieve arbitrary metadata. They are not\nqueryable and should be preserved when modifying objects.\nMore info: http://kubernetes.io/docs/user-guide/annotations",
                  "type": "object"
                },
                "labels": {
                  "additionalProperties": {
                    "type": "string"
                  },
                  "description": "labels is a map of string keys and values that can be used to organize and categorize\n(scope and select) objects. May match selectors of replication controllers\nand services.\nMore info: http://kubernetes.io/docs/user-guide/labels",
                  "type": "object"
                }
              },
              "type": "object",
              "additionalProperties": false
            },
            "namingStrategy": {
              "description": "namingStrategy allows changing the naming pattern used when creating the control plane provider object.",
              "properties": {
                "template": {
                  "description": "template defines the template to use for generating the name of the ControlPlane object.\nIf not defined, it will fallback to `{{ .cluster.name }}-{{ .random }}`.\nIf the templated string exceeds 63 characters, it will be trimmed to 58 characters and will\nget concatenated with a random suffix of length 5.\nThe templating mechanism provides the following arguments:\n* `.cluster.name`: The name of the cluster object.\n* `.random`: A random alphanumeric string, without vowels, of length 5.",
                  "maxLength": 1024,
                  "minLength": 1,
                  "type": "string"
                }
              },
              "type": "object",
              "additionalProperties": false
            },
            "nodeDeletionTimeout": {
              "description": "nodeDeletionTimeout defines how long the controller will attempt to delete the Node that the Machine\nhosts after the Machine is marked for deletion. A duration of 0 will retry deletion indefinitely.\nDefaults to 10 seconds.\nNOTE: This value can be overridden while defining a Cluster.Topology.",
              "type": "string"
            },
            "nodeDrainTimeout": {
              "description": "nodeDrainTimeout is the total amount of time that the controller will spend on draining a node.\nThe default value is 0, meaning that the node can be drained without any time limitations.\nNOTE: NodeDrainTimeout is different from `kubectl drain --timeout`\nNOTE: This value can be overridden while defining a Cluster.Topology.",
              "type": "string"
            },
            "nodeVolumeDetachTimeout": {
              "description": "nodeVolumeDetachTimeout is the total amount of time that the controller will spend on waiting for all volumes\nto be detached. The default value is 0, meaning that the volumes can be detached without any time limitations.\nNOTE: This value can be overridden while defining a Cluster.Topology.",
              "type": "string"
            },
            "readinessGates": {
              "description": "readinessGates specifies additional conditions to include when evaluating Machine Ready condition.\n\nThis field can be used e.g. to instruct the machine controller to include in the computation for Machine's ready\ncomputation a condition, managed by an external controllers, reporting the status of special software/hardware installed on the Machine.\n\nNOTE: This field is considered only for computing v1beta2 conditions.\nNOTE: If a Cluster defines a custom list of readinessGates for the control plane,\nsuch list overrides readinessGates defined in this field.\nNOTE: Specific control plane provider implementations might automatically extend the list of readinessGates;\ne.g. the kubeadm control provider adds ReadinessGates for the APIServerPodHealthy, SchedulerPodHealthy conditions, etc.",
              "items": {
                "description": "MachineReadinessGate contains the type of a Machine condition to be used as a readiness gate.",
                "properties": {
                  "conditionType": {
                    "description": "conditionType refers to a condition with matching type in the Machine's condition list.\nIf the conditions doesn't exist, it will be treated as unknown.\nNote: Both Cluster API conditions or conditions added by 3rd party controllers can be used as readiness gates.",
                    "maxLength": 316,
                    "minLength": 1,
                    "pattern": "^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$",
                    "type": "string"
                  },
                  "polarity": {
                    "description": "polarity of the conditionType specified in this readinessGate.\nValid values are Positive, Negative and omitted.\nWhen omitted, the default behaviour will be Positive.\nA positive polarity means that the condition should report a true status under normal conditions.\nA negative polarity means that the condition should report a false status under normal conditions.",
                    "enum": [
                      "Positive",
                      "Negative"
                    ],
                    "type": "string"
                  }
                },
                "required": [
                  "conditionType"
                ],
                "type": "object",
                "additionalProperties": false
              },
              "maxItems": 32,
              "type": "array",
              "x-kubernetes-list-map-keys": [
                "conditionType"
              ],
              "x-kubernetes-list-type": "map"
            },
            "ref": {
              "description": "ref is a required reference to a custom resource\noffered by a provider.",
              "properties": {
                "apiVersion": {
                  "description": "API version of the referent.",
                  "type": "string"
                },
                "fieldPath": {
                  "description": "If referring to a piece of an object instead of an entire object, this string\nshould contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2].\nFor example, if the object reference is to a container within a pod, this would take on a value like:\n\"spec.containers{name}\" (where \"name\" refers to the name of the container that triggered\nthe event) or if no container name is specified \"spec.containers[2]\" (container with\nindex 2 in this pod). This syntax is chosen only to have some well-defined way of\nreferencing a part of an object.",
                  "type": "string"
                },
                "kind": {
                  "description": "Kind of the referent.\nMore info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
                  "type": "string"
                },
                "name": {
                  "description": "Name of the referent.\nMore info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names",
                  "type": "string"
                },
                "namespace": {
                  "description": "Namespace of the referent.\nMore info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/",
                  "type": "string"
                },
                "resourceVersion": {
                  "description": "Specific resourceVersion to which this reference is made, if any.\nMore info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency",
                  "type": "string"
                },
                "uid": {
                  "description": "UID of the referent.\nMore info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids",
                  "type": "string"
                }
              },
              "type": "object",
              "x-kubernetes-map-type": "atomic",
              "additionalProperties": false
            }
          },
          "required": [
            "ref"
          ],
          "type": "object",
          "additionalProperties": false
        },
        "infrastructure": {
          "description": "infrastructure is a reference to a provider-specific template that holds\nthe details for provisioning infrastructure specific cluster\nfor the underlying provider.\nThe underlying provider is responsible for the implementation\nof the template to an infrastructure cluster.",
          "properties": {
            "ref": {
              "description": "ref is a required reference to a custom resource\noffered by a provider.",
              "properties": {
                "apiVersion": {
                  "description": "API version of the referent.",
                  "type": "string"
                },
                "fieldPath": {
                  "description": "If referring to a piece of an object instead of an entire object, this string\nshould contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2].\nFor example, if the object reference is to a container within a pod, this would take on a value like:\n\"spec.containers{name}\" (where \"name\" refers to the name of the container that triggered\nthe event) or if no container name is specified \"spec.containers[2]\" (container with\nindex 2 in this pod). This syntax is chosen only to have some well-defined way of\nreferencing a part of an object.",
                  "type": "string"
                },
                "kind": {
                  "description": "Kind of the referent.\nMore info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
                  "type": "string"
                },
                "name": {
                  "description": "Name of the referent.\nMore info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names",
                  "type": "string"
                },
                "namespace": {
                  "description": "Namespace of the referent.\nMore info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/",
                  "type": "string"
                },
                "resourceVersion": {
                  "description": "Specific resourceVersion to which this reference is made, if any.\nMore info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency",
                  "type": "string"
                },
                "uid": {
                  "description": "UID of the referent.\nMore info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids",
                  "type": "string"
                }
              },
              "type": "object",
              "x-kubernetes-map-type": "atomic",
              "additionalProperties": false
            }
          },
          "required": [
            "ref"
          ],
          "type": "object",
          "additionalProperties": false
        },
        "infrastructureNamingStrategy": {
          "description": "infrastructureNamingStrategy allows changing the naming pattern used when creating the infrastructure object.",
          "properties": {
            "template": {
              "description": "template defines the template to use for generating the name of the Infrastructure object.\nIf not defined, it will fallback to `{{ .cluster.name }}-{{ .random }}`.\nIf the templated string exceeds 63 characters, it will be trimmed to 58 characters and will\nget concatenated with a random suffix of length 5.\nThe templating mechanism provides the following arguments:\n* `.cluster.name`: The name of the cluster object.\n* `.random`: A random alphanumeric string, without vowels, of length 5.",
              "maxLength": 1024,
              "minLength": 1,
              "type": "string"
            }
          },
          "type": "object",
          "additionalProperties": false
        },
        "patches": {
          "description": "patches defines the patches which are applied to customize\nreferenced templates of a ClusterClass.\nNote: Patches will be applied in the order of the array.",
          "items": {
            "description": "ClusterClassPatch defines a patch which is applied to customize the referenced templates.",
            "properties": {
              "definitions": {
                "description": "definitions define inline patches.\nNote: Patches will be applied in the order of the array.\nNote: Exactly one of Definitions or External must be set.",
                "items": {
                  "description": "PatchDefinition defines a patch which is applied to customize the referenced templates.",
                  "properties": {
                    "jsonPatches": {
                      "description": "jsonPatches defines the patches which should be applied on the templates\nmatching the selector.\nNote: Patches will be applied in the order of the array.",
                      "items": {
                        "description": "JSONPatch defines a JSON patch.",
                        "properties": {
                          "op": {
                            "description": "op defines the operation of the patch.\nNote: Only `add`, `replace` and `remove` are supported.",
                            "enum": [
                              "add",
                              "replace",
                              "remove"
                            ],
                            "type": "string"
                          },
                          "path": {
                            "description": "path defines the path of the patch.\nNote: Only the spec of a template can be patched, thus the path has to start with /spec/.\nNote: For now the only allowed array modifications are `append` and `prepend`, i.e.:\n* for op: `add`: only index 0 (prepend) and - (append) are allowed\n* for op: `replace` or `remove`: no indexes are allowed",
                            "maxLength": 512,
                            "minLength": 1,
                            "type": "string"
                          },
                          "value": {
                            "description": "value defines the value of the patch.\nNote: Either Value or ValueFrom is required for add and replace\noperations. Only one of them is allowed to be set at the same time.\nNote: We have to use apiextensionsv1.JSON instead of our JSON type,\nbecause controller-tools has a hard-coded schema for apiextensionsv1.JSON\nwhich cannot be produced by another type (unset type field).\nRef: https://github.com/kubernetes-sigs/controller-tools/blob/d0e03a142d0ecdd5491593e941ee1d6b5d91dba6/pkg/crd/known_types.go#L106-L111",
                            "x-kubernetes-preserve-unknown-fields": true
                          },
                          "valueFrom": {
                            "description": "valueFrom defines the value of the patch.\nNote: Either Value or ValueFrom is required for add and replace\noperations. Only one of them is allowed to be set at the same time.",
                            "properties": {
                              "template": {
                                "description": "template is the Go template to be used to calculate the value.\nA template can reference variables defined in .spec.variables and builtin variables.\nNote: The template must evaluate to a valid YAML or JSON value.",
                                "maxLength": 10240,
                                "minLength": 1,
                                "type": "string"
                              },
                              "variable": {
                                "description": "variable is the variable to be used as value.\nVariable can be one of the variables defined in .spec.variables or a builtin variable.",
                                "maxLength": 256,
                                "minLength": 1,
                                "type": "string"
                              }
                            },
                            "type": "object",
                            "additionalProperties": false
                          }
                        },
                        "required": [
                          "op",
                          "path"
                        ],
                        "type": "object",
                        "additionalProperties": false
                      },
                      "maxItems": 100,
                      "type": "array"
                    },
                    "selector": {
                      "description": "selector defines on which templates the patch should be applied.",
                      "properties": {
                        "apiVersion": {
                          "description": "apiVersion filters templates by apiVersion.",
                          "maxLength": 512,
                          "minLength": 1,
                          "type": "string"
                        },
                        "kind": {
                          "description": "kind filters templates by kind.",
                          "maxLength": 256,
                          "minLength": 1,
                          "type": "string"
                        },
                        "matchResources": {
                          "description": "matchResources selects templates based on where they are referenced.",
                          "properties": {
                            "controlPlane": {
                              "description": "controlPlane selects templates referenced in .spec.ControlPlane.\nNote: this will match the controlPlane and also the controlPlane\nmachineInfrastructure (depending on the kind and apiVersion).",
                              "type": "boolean"
                            },
                            "infrastructureCluster": {
                              "description": "infrastructureCluster selects templates referenced in .spec.infrastructure.",
                              "type": "boolean"
                            },
                            "machineDeploymentClass": {
                              "description": "machineDeploymentClass selects templates referenced in specific MachineDeploymentClasses in\n.spec.workers.machineDeployments.",
                              "properties": {
                                "names": {
                                  "description": "names selects templates by class names.",
                                  "items": {
                                    "maxLength": 256,
                                    "minLength": 1,
                                    "type": "string"
                                  },
                                  "maxItems": 100,
                                  "type": "array"
                                }
                              },
                              "type": "object",
                              "additionalProperties": false
                            },
                            "machinePoolClass": {
                              "description": "machinePoolClass selects templates referenced in specific MachinePoolClasses in\n.spec.workers.machinePools.",
                              "properties": {
                                "names": {
                                  "description": "names selects templates by class names.",
                                  "items": {
                                    "maxLength": 256,
                                    "minLength": 1,
                                    "type": "string"
                                  },
                                  "maxItems": 100,
                                  "type": "array"
                                }
                              },
                              "type": "object",
                              "additionalProperties": false
                            }
                          },
                          "type": "object",
                          "additionalProperties": false
                        }
                      },
                      "required": [
                        "apiVersion",
                        "kind",
                        "matchResources"
                      ],
                      "type": "object",
                      "additionalProperties": false
                    }
                  },
                  "required": [
                    "jsonPatches",
                    "selector"
                  ],
                  "type": "object",
                  "additionalProperties": false
                },
                "maxItems": 100,
                "type": "array"
              },
              "description": {
                "description": "description is a human-readable description of this patch.",
                "maxLength": 1024,
                "minLength": 1,
                "type": "string"
              },
              "enabledIf": {
                "description": "enabledIf is a Go template to be used to calculate if a patch should be enabled.\nIt can reference variables defined in .spec.variables and builtin variables.\nThe patch will be enabled if the template evaluates to `true`, otherwise it will\nbe disabled.\nIf EnabledIf is not set, the patch will be enabled per default.",
                "maxLength": 256,
                "minLength": 1,
                "type": "string"
              },
              "external": {
                "description": "external defines an external patch.\nNote: Exactly one of Definitions or External must be set.",
                "properties": {
                  "discoverVariablesExtension": {
                    "description": "discoverVariablesExtension references an extension which is called to discover variables.",
                    "maxLength": 512,
                    "minLength": 1,
                    "type": "string"
                  },
                  "generateExtension": {
                    "description": "generateExtension references an extension which is called to generate patches.",
                    "maxLength": 512,
                    "minLength": 1,
                    "type": "string"
                  },
                  "settings": {
                    "additionalProperties": {
                      "type": "string"
                    },
                    "description": "settings defines key value pairs to be passed to the extensions.\nValues defined here take precedence over the values defined in the\ncorresponding ExtensionConfig.",
                    "type": "object"
                  },
                  "validateExtension": {
                    "description": "validateExtension references an extension which is called to validate the topology.",
                    "maxLength": 512,
                    "minLength": 1,
                    "type": "string"
                  }
                },
                "type": "object",
                "additionalProperties": false
              },
              "name": {
                "description": "name of the patch.",
                "maxLength": 256,
                "minLength": 1,
                "type": "string"
              }
            },
            "required": [
              "name"
            ],
            "type": "object",
            "additionalProperties": false
          },
          "maxItems": 1000,
          "type": "array"
        },
        "variables": {
          "description": "variables defines the variables which can be configured\nin the Cluster topology and are then used in patches.",
          "items": {
            "description": "ClusterClassVariable defines a variable which can\nbe configured in the Cluster topology and used in patches.",
            "properties": {
              "metadata": {
                "description": "metadata is the metadata of a variable.\nIt can be used to add additional data for higher level tools to\na ClusterClassVariable.\n\nDeprecated: This field is deprecated and is going to be removed in the next apiVersion. Please use XMetadata in JSONSchemaProps instead.",
                "properties": {
                  "annotations": {
                    "additionalProperties": {
                      "type": "string"
                    },
                    "description": "annotations is an unstructured key value map that can be used to store and\nretrieve arbitrary metadata.\nThey are not queryable.",
                    "type": "object"
                  },
                  "labels": {
                    "additionalProperties": {
                      "type": "string"
                    },
                    "description": "labels is a map of string keys and values that can be used to organize and categorize\n(scope and select) variables.",
                    "type": "object"
                  }
                },
                "type": "object",
                "additionalProperties": false
              },
              "name": {
                "description": "name of the variable.",
                "maxLength": 256,
                "minLength": 1,
                "type": "string"
              },
              "required": {
                "description": "required specifies if the variable is required.\nNote: this applies to the variable as a whole and thus the\ntop-level object defined in the schema. If nested fields are\nrequired, this will be specified inside the schema.",
                "type": "boolean"
              },
              "schema": {
                "description": "schema defines the schema of the variable.",
                "properties": {
                  "openAPIV3Schema": {
                    "description": "openAPIV3Schema defines the schema of a variable via OpenAPI v3\nschema. The schema is a subset of the schema used in\nKubernetes CRDs.",
                    "properties": {
                      "additionalProperties": {
                        "description": "additionalProperties specifies the schema of values in a map (keys are always strings).\nNOTE: Can only be set if type is object.\nNOTE: AdditionalProperties is mutually exclusive with Properties.\nNOTE: This field uses PreserveUnknownFields and Schemaless,\nbecause recursive validation is not possible.",
                        "x-kubernetes-preserve-unknown-fields": true
                      },
                      "allOf": {
                        "description": "allOf specifies that the variable must validate against all of the subschemas in the array.\nNOTE: This field uses PreserveUnknownFields and Schemaless,\nbecause recursive validation is not possible.",
                        "x-kubernetes-preserve-unknown-fields": true
                      },
                      "anyOf": {
                        "description": "anyOf specifies that the variable must validate against one or more of the subschemas in the array.\nNOTE: This field uses PreserveUnknownFields and Schemaless,\nbecause recursive validation is not possible.",
                        "x-kubernetes-preserve-unknown-fields": true
                      },
                      "default": {
                        "description": "default is the default value of the variable.\nNOTE: Can be set for all types.",
                        "x-kubernetes-preserve-unknown-fields": true
                      },
                      "description": {
                        "description": "description is a human-readable description of this variable.",
                        "maxLength": 4096,
                        "minLength": 1,
                        "type": "string"
                      },
                      "enum": {
                        "description": "enum is the list of valid values of the variable.\nNOTE: Can be set for all types.",
                        "items": {
                          "x-kubernetes-preserve-unknown-fields": true
                        },
                        "maxItems": 100,
                        "type": "array"
                      },
                      "example": {
                        "description": "example is an example for this variable.",
                        "x-kubernetes-preserve-unknown-fields": true
                      },
                      "exclusiveMaximum": {
                        "description": "exclusiveMaximum specifies if the Maximum is exclusive.\nNOTE: Can only be set if type is integer or number.",
                        "type": "boolean"
                      },
                      "exclusiveMinimum": {
                        "description": "exclusiveMinimum specifies if the Minimum is exclusive.\nNOTE: Can only be set if type is integer or number.",
                        "type": "boolean"
                      },
                      "format": {
                        "description": "format is an OpenAPI v3 format string. Unknown formats are ignored.\nFor a list of supported formats please see: (of the k8s.io/apiextensions-apiserver version we're currently using)\nhttps://github.com/kubernetes/apiextensions-apiserver/blob/master/pkg/apiserver/validation/formats.go\nNOTE: Can only be set if type is string.",
                        "maxLength": 32,
                        "minLength": 1,
                        "type": "string"
                      },
                      "items": {
                        "description": "items specifies fields of an array.\nNOTE: Can only be set if type is array.\nNOTE: This field uses PreserveUnknownFields and Schemaless,\nbecause recursive validation is not possible.",
                        "x-kubernetes-preserve-unknown-fields": true
                      },
                      "maxItems": {
                        "description": "maxItems is the max length of an array variable.\nNOTE: Can only be set if type is array.",
                        "format": "int64",
                        "type": "integer"
                      },
                      "maxLength": {
                        "description": "maxLength is the max length of a string variable.\nNOTE: Can only be set if type is string.",
                        "format": "int64",
                        "type": "integer"
                      },
                      "maxProperties": {
                        "description": "maxProperties is the maximum amount of entries in a map or properties in an object.\nNOTE: Can only be set if type is object.",
                        "format": "int64",
                        "type": "integer"
                      },
                      "maximum": {
                        "description": "maximum is the maximum of an integer or number variable.\nIf ExclusiveMaximum is false, the variable is valid if it is lower than, or equal to, the value of Maximum.\nIf ExclusiveMaximum is true, the variable is valid if it is strictly lower than the value of Maximum.\nNOTE: Can only be set if type is integer or number.",
                        "format": "int64",
                        "type": "integer"
                      },
                      "minItems": {
                        "description": "minItems is the min length of an array variable.\nNOTE: Can only be set if type is array.",
                        "format": "int64",
                        "type": "integer"
                      },
                      "minLength": {
                        "description": "minLength is the min length of a string variable.\nNOTE: Can only be set if type is string.",
                        "format": "int64",
                        "type": "integer"
                      },
                      "minProperties": {
                        "description": "minProperties is the minimum amount of entries in a map or properties in an object.\nNOTE: Can only be set if type is object.",
                        "format": "int64",
                        "type": "integer"
                      },
                      "minimum": {
                        "description": "minimum is the minimum of an integer or number variable.\nIf ExclusiveMinimum is false, the variable is valid if it is greater than, or equal to, the value of Minimum.\nIf ExclusiveMinimum is true, the variable is valid if it is strictly greater than the value of Minimum.\nNOTE: Can only be set if type is integer or number.",
                        "format": "int64",
                        "type": "integer"
                      },
                      "not": {
                        "description": "not specifies that the variable must not validate against the subschema.\nNOTE: This field uses PreserveUnknownFields and Schemaless,\nbecause recursive validation is not possible.",
                        "x-kubernetes-preserve-unknown-fields": true
                      },
                      "oneOf": {
                        "description": "oneOf specifies that the variable must validate against exactly one of the subschemas in the array.\nNOTE: This field uses PreserveUnknownFields and Schemaless,\nbecause recursive validation is not possible.",
                        "x-kubernetes-preserve-unknown-fields": true
                      },
                      "pattern": {
                        "description": "pattern is the regex which a string variable must match.\nNOTE: Can only be set if type is string.",
                        "maxLength": 512,
                        "minLength": 1,
                        "type": "string"
                      },
                      "properties": {
                        "description": "properties specifies fields of an object.\nNOTE: Can only be set if type is object.\nNOTE: Properties is mutually exclusive with AdditionalProperties.\nNOTE: This field uses PreserveUnknownFields and Schemaless,\nbecause recursive validation is not possible.",
                        "x-kubernetes-preserve-unknown-fields": true
                      },
                      "required": {
                        "description": "required specifies which fields of an object are required.\nNOTE: Can only be set if type is object.",
                        "items": {
                          "maxLength": 256,
                          "minLength": 1,
                          "type": "string"
                        },
                        "maxItems": 1000,
                        "type": "array"
                      },
                      "type": {
                        "description": "type is the type of the variable.\nValid values are: object, array, string, integer, number or boolean.",
                        "enum": [
                          "object",
                          "array",
                          "string",
                          "integer",
                          "number",
                          "boolean"
                        ],
                        "type": "string"
                      },
                      "uniqueItems": {
                        "description": "uniqueItems specifies if items in an array must be unique.\nNOTE: Can only be set if type is array.",
                        "type": "boolean"
                      },
                      "x-kubernetes-int-or-string": {
                        "description": "x-kubernetes-int-or-string specifies that this value is\neither an integer or a string. If this is true, an empty\ntype is allowed and type as child of anyOf is permitted\nif following one of the following patterns:\n\n1) anyOf:\n   - type: integer\n   - type: string\n2) allOf:\n   - anyOf:\n     - type: integer\n     - type: string\n   - ... zero or more",
                        "type": "boolean"
                      },
                      "x-kubernetes-preserve-unknown-fields": {
                        "description": "x-kubernetes-preserve-unknown-fields allows setting fields in a variable object\nwhich are not defined in the variable schema. This affects fields recursively,\nexcept if nested properties or additionalProperties are specified in the schema.",
                        "type": "boolean"
                      },
                      "x-kubernetes-validations": {
                        "description": "x-kubernetes-validations describes a list of validation rules written in the CEL expression language.",
                        "items": {
                          "description": "ValidationRule describes a validation rule written in the CEL expression language.",
                          "properties": {
                            "fieldPath": {
                              "description": "fieldPath represents the field path returned when the validation fails.\nIt 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.\ne.g. when validation checks if a specific attribute `foo` under a map `testMap`, the fieldPath could be set to `.testMap.foo`\nIf the validation checks two lists must have unique attributes, the fieldPath could be set to either of the list: e.g. `.testList`\nIt does not support list numeric index.\nIt 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.\nNumeric index of array is not supported.\nFor field name which contains special characters, use `['specialName']` to refer the field name.\ne.g. for attribute `foo.34$` appears in a list `testList`, the fieldPath could be set to `.testList['foo.34$']`",
                              "maxLength": 512,
                              "minLength": 1,
                              "type": "string"
                            },
                            "message": {
                              "description": "message represents the message displayed when validation fails. The message is required if the Rule contains\nline breaks. The message must not contain line breaks.\nIf unset, the message is \"failed rule: {Rule}\".\ne.g. \"must be a URL with the host matching spec.host\"",
                              "maxLength": 512,
                              "minLength": 1,
                              "type": "string"
                            },
                            "messageExpression": {
                              "description": "messageExpression declares a CEL expression that evaluates to the validation failure message that is returned when this rule fails.\nSince messageExpression is used as a failure message, it must evaluate to a string.\nIf both message and messageExpression are present on a rule, then messageExpression will be used if validation\nfails. If messageExpression results in a runtime error, the validation failure message is produced\nas if the messageExpression field were unset. If messageExpression evaluates to an empty string, a string with only spaces, or a string\nthat contains line breaks, then the validation failure message will also be produced as if the messageExpression field were unset.\nmessageExpression has access to all the same variables as the rule; the only difference is the return type.\nExample:\n\"x must be less than max (\"+string(self.max)+\")\"",
                              "maxLength": 1024,
                              "minLength": 1,
                              "type": "string"
                            },
                            "reason": {
                              "default": "FieldValueInvalid",
                              "description": "reason provides a machine-readable validation failure reason that is returned to the caller when a request fails this validation rule.\nThe currently supported reasons are: \"FieldValueInvalid\", \"FieldValueForbidden\", \"FieldValueRequired\", \"FieldValueDuplicate\".\nIf not set, default to use \"FieldValueInvalid\".\nAll future added reasons must be accepted by clients when reading this value and unknown reasons should be treated as FieldValueInvalid.",
                              "enum": [
                                "FieldValueInvalid",
                                "FieldValueForbidden",
                                "FieldValueRequired",
                                "FieldValueDuplicate"
                              ],
                              "type": "string"
                            },
                            "rule": {
                              "description": "rule represents the expression which will be evaluated by CEL.\nref: https://github.com/google/cel-spec\nThe Rule is scoped to the location of the x-kubernetes-validations extension in the schema.\nThe `self` variable in the CEL expression is bound to the scoped value.\nIf the Rule is scoped to an object with properties, the accessible properties of the object are field selectable\nvia `self.field` and field presence can be checked via `has(self.field)`.\nIf the Rule is scoped to an object with additionalProperties (i.e. a map) the value of the map\nare accessible via `self[mapKey]`, map containment can be checked via `mapKey in self` and all entries of the map\nare accessible via CEL macros and functions such as `self.all(...)`.\nIf the Rule is scoped to an array, the elements of the array are accessible via `self[i]` and also by macros and\nfunctions.\nIf the Rule is scoped to a scalar, `self` is bound to the scalar value.\nExamples:\n- Rule scoped to a map of objects: {\"rule\": \"self.components['Widget'].priority < 10\"}\n- Rule scoped to a list of integers: {\"rule\": \"self.values.all(value, value >= 0 && value < 100)\"}\n- Rule scoped to a string value: {\"rule\": \"self.startsWith('kube')\"}\n\nUnknown data preserved in custom resources via x-kubernetes-preserve-unknown-fields is not accessible in CEL\nexpressions. This includes:\n- Unknown field values that are preserved by object schemas with x-kubernetes-preserve-unknown-fields.\n- Object properties where the property schema is of an \"unknown type\". An \"unknown type\" is recursively defined as:\n  - A schema with no type and x-kubernetes-preserve-unknown-fields set to true\n  - An array where the items schema is of an \"unknown type\"\n  - An object where the additionalProperties schema is of an \"unknown type\"\n\nOnly property names of the form `[a-zA-Z_.-/][a-zA-Z0-9_.-/]*` are accessible.\nAccessible property names are escaped according to the following rules when accessed in the expression:\n- '__' escapes to '__underscores__'\n- '.' escapes to '__dot__'\n- '-' escapes to '__dash__'\n- '/' escapes to '__slash__'\n- Property names that exactly match a CEL RESERVED keyword escape to '__{keyword}__'. The keywords are:\n\t  \"true\", \"false\", \"null\", \"in\", \"as\", \"break\", \"const\", \"continue\", \"else\", \"for\", \"function\", \"if\",\n\t  \"import\", \"let\", \"loop\", \"package\", \"namespace\", \"return\".\nExamples:\n  - Rule accessing a property named \"namespace\": {\"rule\": \"self.__namespace__ > 0\"}\n  - Rule accessing a property named \"x-prop\": {\"rule\": \"self.x__dash__prop > 0\"}\n  - Rule accessing a property named \"redact__d\": {\"rule\": \"self.redact__underscores__d > 0\"}\n\nIf `rule` makes use of the `oldSelf` variable it is implicitly a\n`transition rule`.\n\nBy default, the `oldSelf` variable is the same type as `self`.\n\nTransition rules by default are applied only on UPDATE requests and are\nskipped if an old value could not be found.",
                              "maxLength": 4096,
                              "minLength": 1,
                              "type": "string"
                            }
                          },
                          "required": [
                            "rule"
                          ],
                          "type": "object",
                          "additionalProperties": false
                        },
                        "maxItems": 100,
                        "type": "array",
                        "x-kubernetes-list-map-keys": [
                          "rule"
                        ],
                        "x-kubernetes-list-type": "map"
                      },
                      "x-metadata": {
                        "description": "x-metadata is the metadata of a variable or a nested field within a variable.\nIt can be used to add additional data for higher level tools.",
                        "properties": {
                          "annotations": {
                            "additionalProperties": {
                              "type": "string"
                            },
                            "description": "annotations is an unstructured key value map that can be used to store and\nretrieve arbitrary metadata.\nThey are not queryable.",
                            "type": "object"
                          },
                          "labels": {
                            "additionalProperties": {
                              "type": "string"
                            },
                            "description": "labels is a map of string keys and values that can be used to organize and categorize\n(scope and select) variables.",
                            "type": "object"
                          }
                        },
                        "type": "object",
                        "additionalProperties": false
                      }
                    },
                    "type": "object",
                    "additionalProperties": false
                  }
                },
                "required": [
                  "openAPIV3Schema"
                ],
                "type": "object",
                "additionalProperties": false
              }
            },
            "required": [
              "name",
              "required",
              "schema"
            ],
            "type": "object",
            "additionalProperties": false
          },
          "maxItems": 1000,
          "type": "array"
        },
        "workers": {
          "description": "workers describes the worker nodes for the cluster.\nIt is a collection of node types which can be used to create\nthe worker nodes of the cluster.",
          "properties": {
            "machineDeployments": {
              "description": "machineDeployments is a list of machine deployment classes that can be used to create\na set of worker nodes.",
              "items": {
                "description": "MachineDeploymentClass serves as a template to define a set of worker nodes of the cluster\nprovisioned using the `ClusterClass`.",
                "properties": {
                  "class": {
                    "description": "class denotes a type of worker node present in the cluster,\nthis name MUST be unique within a ClusterClass and can be referenced\nin the Cluster to create a managed MachineDeployment.",
                    "maxLength": 256,
                    "minLength": 1,
                    "type": "string"
                  },
                  "failureDomain": {
                    "description": "failureDomain is the failure domain the machines will be created in.\nMust match a key in the FailureDomains map stored on the cluster object.\nNOTE: This value can be overridden while defining a Cluster.Topology using this MachineDeploymentClass.",
                    "maxLength": 256,
                    "minLength": 1,
                    "type": "string"
                  },
                  "machineHealthCheck": {
                    "description": "machineHealthCheck defines a MachineHealthCheck for this MachineDeploymentClass.",
                    "properties": {
                      "maxUnhealthy": {
                        "anyOf": [
                          {
                            "type": "integer"
                          },
                          {
                            "type": "string"
                          }
                        ],
                        "description": "maxUnhealthy specifies the maximum number of unhealthy machines allowed.\nAny further remediation is only allowed if at most \"maxUnhealthy\" machines selected by\n\"selector\" are not healthy.",
                        "x-kubernetes-int-or-string": true
                      },
                      "nodeStartupTimeout": {
                        "description": "nodeStartupTimeout allows to set the maximum time for MachineHealthCheck\nto consider a Machine unhealthy if a corresponding Node isn't associated\nthrough a `Spec.ProviderID` field.\n\nThe duration set in this field is compared to the greatest of:\n- Cluster's infrastructure ready condition timestamp (if and when available)\n- Control Plane's initialized condition timestamp (if and when available)\n- Machine's infrastructure ready condition timestamp (if and when available)\n- Machine's metadata creation timestamp\n\nDefaults to 10 minutes.\nIf you wish to disable this feature, set the value explicitly to 0.",
                        "type": "string"
                      },
                      "remediationTemplate": {
                        "description": "remediationTemplate is a reference to a remediation template\nprovided by an infrastructure provider.\n\nThis field is completely optional, when filled, the MachineHealthCheck controller\ncreates a new object from the template referenced and hands off remediation of the machine to\na controller that lives outside of Cluster API.",
                        "properties": {
                          "apiVersion": {
                            "description": "API version of the referent.",
                            "type": "string"
                          },
                          "fieldPath": {
                            "description": "If referring to a piece of an object instead of an entire object, this string\nshould contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2].\nFor example, if the object reference is to a container within a pod, this would take on a value like:\n\"spec.containers{name}\" (where \"name\" refers to the name of the container that triggered\nthe event) or if no container name is specified \"spec.containers[2]\" (container with\nindex 2 in this pod). This syntax is chosen only to have some well-defined way of\nreferencing a part of an object.",
                            "type": "string"
                          },
                          "kind": {
                            "description": "Kind of the referent.\nMore info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
                            "type": "string"
                          },
                          "name": {
                            "description": "Name of the referent.\nMore info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names",
                            "type": "string"
                          },
                          "namespace": {
                            "description": "Namespace of the referent.\nMore info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/",
                            "type": "string"
                          },
                          "resourceVersion": {
                            "description": "Specific resourceVersion to which this reference is made, if any.\nMore info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency",
                            "type": "string"
                          },
                          "uid": {
                            "description": "UID of the referent.\nMore info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids",
                            "type": "string"
                          }
                        },
                        "type": "object",
                        "x-kubernetes-map-type": "atomic",
                        "additionalProperties": false
                      },
                      "unhealthyConditions": {
                        "description": "unhealthyConditions contains a list of the conditions that determine\nwhether a node is considered unhealthy. The conditions are combined in a\nlogical OR, i.e. if any of the conditions is met, the node is unhealthy.",
                        "items": {
                          "description": "UnhealthyCondition represents a Node condition type and value with a timeout\nspecified as a duration.  When the named condition has been in the given\nstatus for at least the timeout value, a node is considered unhealthy.",
                          "properties": {
                            "status": {
                              "description": "status of the condition, one of True, False, Unknown.",
                              "minLength": 1,
                              "type": "string"
                            },
                            "timeout": {
                              "description": "timeout is the duration that a node must be in a given status for,\nafter which the node is considered unhealthy.\nFor example, with a value of \"1h\", the node must match the status\nfor at least 1 hour before being considered unhealthy.",
                              "type": "string"
                            },
                            "type": {
                              "description": "type of Node condition",
                              "minLength": 1,
                              "type": "string"
                            }
                          },
                          "required": [
                            "status",
                            "timeout",
                            "type"
                          ],
                          "type": "object",
                          "additionalProperties": false
                        },
                        "maxItems": 100,
                        "type": "array"
                      },
                      "unhealthyRange": {
                        "description": "unhealthyRange specifies the range of unhealthy machines allowed.\nAny further remediation is only allowed if the number of machines selected by \"selector\" as not healthy\nis within the range of \"unhealthyRange\". Takes precedence over maxUnhealthy.\nEg. \"[3-5]\" - This means that remediation will be allowed only when:\n(a) there are at least 3 unhealthy machines (and)\n(b) there are at most 5 unhealthy machines",
                        "maxLength": 32,
                        "minLength": 1,
                        "pattern": "^\\[[0-9]+-[0-9]+\\]$",
                        "type": "string"
                      }
                    },
                    "type": "object",
                    "additionalProperties": false
                  },
                  "minReadySeconds": {
                    "description": "minReadySeconds is the minimum number of seconds for which a newly created machine should\nbe ready.\nDefaults to 0 (machine will be considered available as soon as it\nis ready)\nNOTE: This value can be overridden while defining a Cluster.Topology using this MachineDeploymentClass.",
                    "format": "int32",
                    "type": "integer"
                  },
                  "namingStrategy": {
                    "description": "namingStrategy allows changing the naming pattern used when creating the MachineDeployment.",
                    "properties": {
                      "template": {
                        "description": "template defines the template to use for generating the name of the MachineDeployment object.\nIf not defined, it will fallback to `{{ .cluster.name }}-{{ .machineDeployment.topologyName }}-{{ .random }}`.\nIf the templated string exceeds 63 characters, it will be trimmed to 58 characters and will\nget concatenated with a random suffix of length 5.\nThe templating mechanism provides the following arguments:\n* `.cluster.name`: The name of the cluster object.\n* `.random`: A random alphanumeric string, without vowels, of length 5.\n* `.machineDeployment.topologyName`: The name of the MachineDeployment topology (Cluster.spec.topology.workers.machineDeployments[].name).",
                        "maxLength": 1024,
                        "minLength": 1,
                        "type": "string"
                      }
                    },
                    "type": "object",
                    "additionalProperties": false
                  },
                  "nodeDeletionTimeout": {
                    "description": "nodeDeletionTimeout defines how long the controller will attempt to delete the Node that the Machine\nhosts after the Machine is marked for deletion. A duration of 0 will retry deletion indefinitely.\nDefaults to 10 seconds.\nNOTE: This value can be overridden while defining a Cluster.Topology using this MachineDeploymentClass.",
                    "type": "string"
                  },
                  "nodeDrainTimeout": {
                    "description": "nodeDrainTimeout is the total amount of time that the controller will spend on draining a node.\nThe default value is 0, meaning that the node can be drained without any time limitations.\nNOTE: NodeDrainTimeout is different from `kubectl drain --timeout`\nNOTE: This value can be overridden while defining a Cluster.Topology using this MachineDeploymentClass.",
                    "type": "string"
                  },
                  "nodeVolumeDetachTimeout": {
                    "description": "nodeVolumeDetachTimeout is the total amount of time that the controller will spend on waiting for all volumes\nto be detached. The default value is 0, meaning that the volumes can be detached without any time limitations.\nNOTE: This value can be overridden while defining a Cluster.Topology using this MachineDeploymentClass.",
                    "type": "string"
                  },
                  "readinessGates": {
                    "description": "readinessGates specifies additional conditions to include when evaluating Machine Ready condition.\n\nThis field can be used e.g. to instruct the machine controller to include in the computation for Machine's ready\ncomputation a condition, managed by an external controllers, reporting the status of special software/hardware installed on the Machine.\n\nNOTE: This field is considered only for computing v1beta2 conditions.\nNOTE: If a Cluster defines a custom list of readinessGates for a MachineDeployment using this MachineDeploymentClass,\nsuch list overrides readinessGates defined in this field.",
                    "items": {
                      "description": "MachineReadinessGate contains the type of a Machine condition to be used as a readiness gate.",
                      "properties": {
                        "conditionType": {
                          "description": "conditionType refers to a condition with matching type in the Machine's condition list.\nIf the conditions doesn't exist, it will be treated as unknown.\nNote: Both Cluster API conditions or conditions added by 3rd party controllers can be used as readiness gates.",
                          "maxLength": 316,
                          "minLength": 1,
                          "pattern": "^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$",
                          "type": "string"
                        },
                        "polarity": {
                          "description": "polarity of the conditionType specified in this readinessGate.\nValid values are Positive, Negative and omitted.\nWhen omitted, the default behaviour will be Positive.\nA positive polarity means that the condition should report a true status under normal conditions.\nA negative polarity means that the condition should report a false status under normal conditions.",
                          "enum": [
                            "Positive",
                            "Negative"
                          ],
                          "type": "string"
                        }
                      },
                      "required": [
                        "conditionType"
                      ],
                      "type": "object",
                      "additionalProperties": false
                    },
                    "maxItems": 32,
                    "type": "array",
                    "x-kubernetes-list-map-keys": [
                      "conditionType"
                    ],
                    "x-kubernetes-list-type": "map"
                  },
                  "strategy": {
                    "description": "strategy is the deployment strategy to use to replace existing machines with\nnew ones.\nNOTE: This value can be overridden while defining a Cluster.Topology using this MachineDeploymentClass.",
                    "properties": {
                      "remediation": {
                        "description": "remediation controls the strategy of remediating unhealthy machines\nand how remediating operations should occur during the lifecycle of the dependant MachineSets.",
                        "properties": {
                          "maxInFlight": {
                            "anyOf": [
                              {
                                "type": "integer"
                              },
                              {
                                "type": "string"
                              }
                            ],
                            "description": "maxInFlight determines how many in flight remediations should happen at the same time.\n\nRemediation only happens on the MachineSet with the most current revision, while\nolder MachineSets (usually present during rollout operations) aren't allowed to remediate.\n\nNote: In general (independent of remediations), unhealthy machines are always\nprioritized during scale down operations over healthy ones.\n\nMaxInFlight can be set to a fixed number or a percentage.\nExample: when this is set to 20%, the MachineSet controller deletes at most 20% of\nthe desired replicas.\n\nIf not set, remediation is limited to all machines (bounded by replicas)\nunder the active MachineSet's management.",
                            "x-kubernetes-int-or-string": true
                          }
                        },
                        "type": "object",
                        "additionalProperties": false
                      },
                      "rollingUpdate": {
                        "description": "rollingUpdate is the rolling update config params. Present only if\nMachineDeploymentStrategyType = RollingUpdate.",
                        "properties": {
                          "deletePolicy": {
                            "description": "deletePolicy defines the policy used by the MachineDeployment to identify nodes to delete when downscaling.\nValid values are \"Random, \"Newest\", \"Oldest\"\nWhen no value is supplied, the default DeletePolicy of MachineSet is used",
                            "enum": [
                              "Random",
                              "Newest",
                              "Oldest"
                            ],
                            "type": "string"
                          },
                          "maxSurge": {
                            "anyOf": [
                              {
                                "type": "integer"
                              },
                              {
                                "type": "string"
                              }
                            ],
                            "description": "maxSurge is the maximum number of machines that can be scheduled above the\ndesired number of machines.\nValue can be an absolute number (ex: 5) or a percentage of\ndesired machines (ex: 10%).\nThis can not be 0 if MaxUnavailable is 0.\nAbsolute number is calculated from percentage by rounding up.\nDefaults to 1.\nExample: when this is set to 30%, the new MachineSet can be scaled\nup immediately when the rolling update starts, such that the total\nnumber of old and new machines do not exceed 130% of desired\nmachines. Once old machines have been killed, new MachineSet can\nbe scaled up further, ensuring that total number of machines running\nat any time during the update is at most 130% of desired machines.",
                            "x-kubernetes-int-or-string": true
                          },
                          "maxUnavailable": {
                            "anyOf": [
                              {
                                "type": "integer"
                              },
                              {
                                "type": "string"
                              }
                            ],
                            "description": "maxUnavailable is the maximum number of machines that can be unavailable during the update.\nValue can be an absolute number (ex: 5) or a percentage of desired\nmachines (ex: 10%).\nAbsolute number is calculated from percentage by rounding down.\nThis can not be 0 if MaxSurge is 0.\nDefaults to 0.\nExample: when this is set to 30%, the old MachineSet can be scaled\ndown to 70% of desired machines immediately when the rolling update\nstarts. Once new machines are ready, old MachineSet can be scaled\ndown further, followed by scaling up the new MachineSet, ensuring\nthat the total number of machines available at all times\nduring the update is at least 70% of desired machines.",
                            "x-kubernetes-int-or-string": true
                          }
                        },
                        "type": "object",
                        "additionalProperties": false
                      },
                      "type": {
                        "description": "type of deployment. Allowed values are RollingUpdate and OnDelete.\nThe default is RollingUpdate.",
                        "enum": [
                          "RollingUpdate",
                          "OnDelete"
                        ],
                        "type": "string"
                      }
                    },
                    "type": "object",
                    "additionalProperties": false
                  },
                  "template": {
                    "description": "template is a local struct containing a collection of templates for creation of\nMachineDeployment objects representing a set of worker nodes.",
                    "properties": {
                      "bootstrap": {
                        "description": "bootstrap contains the bootstrap template reference to be used\nfor the creation of worker Machines.",
                        "properties": {
                          "ref": {
                            "description": "ref is a required reference to a custom resource\noffered by a provider.",
                            "properties": {
                              "apiVersion": {
                                "description": "API version of the referent.",
                                "type": "string"
                              },
                              "fieldPath": {
                                "description": "If referring to a piece of an object instead of an entire object, this string\nshould contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2].\nFor example, if the object reference is to a container within a pod, this would take on a value like:\n\"spec.containers{name}\" (where \"name\" refers to the name of the container that triggered\nthe event) or if no container name is specified \"spec.containers[2]\" (container with\nindex 2 in this pod). This syntax is chosen only to have some well-defined way of\nreferencing a part of an object.",
                                "type": "string"
                              },
                              "kind": {
                                "description": "Kind of the referent.\nMore info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
                                "type": "string"
                              },
                              "name": {
                                "description": "Name of the referent.\nMore info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names",
                                "type": "string"
                              },
                              "namespace": {
                                "description": "Namespace of the referent.\nMore info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/",
                                "type": "string"
                              },
                              "resourceVersion": {
                                "description": "Specific resourceVersion to which this reference is made, if any.\nMore info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency",
                                "type": "string"
                              },
                              "uid": {
                                "description": "UID of the referent.\nMore info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids",
                                "type": "string"
                              }
                            },
                            "type": "object",
                            "x-kubernetes-map-type": "atomic",
                            "additionalProperties": false
                          }
                        },
                        "required": [
                          "ref"
                        ],
                        "type": "object",
                        "additionalProperties": false
                      },
                      "infrastructure": {
                        "description": "infrastructure contains the infrastructure template reference to be used\nfor the creation of worker Machines.",
                        "properties": {
                          "ref": {
                            "description": "ref is a required reference to a custom resource\noffered by a provider.",
                            "properties": {
                              "apiVersion": {
                                "description": "API version of the referent.",
                                "type": "string"
                              },
                              "fieldPath": {
                                "description": "If referring to a piece of an object instead of an entire object, this string\nshould contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2].\nFor example, if the object reference is to a container within a pod, this would take on a value like:\n\"spec.containers{name}\" (where \"name\" refers to the name of the container that triggered\nthe event) or if no container name is specified \"spec.containers[2]\" (container with\nindex 2 in this pod). This syntax is chosen only to have some well-defined way of\nreferencing a part of an object.",
                                "type": "string"
                              },
                              "kind": {
                                "description": "Kind of the referent.\nMore info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
                                "type": "string"
                              },
                              "name": {
                                "description": "Name of the referent.\nMore info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names",
                                "type": "string"
                              },
                              "namespace": {
                                "description": "Namespace of the referent.\nMore info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/",
                                "type": "string"
                              },
                              "resourceVersion": {
                                "description": "Specific resourceVersion to which this reference is made, if any.\nMore info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency",
                                "type": "string"
                              },
                              "uid": {
                                "description": "UID of the referent.\nMore info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids",
                                "type": "string"
                              }
                            },
                            "type": "object",
                            "x-kubernetes-map-type": "atomic",
                            "additionalProperties": false
                          }
                        },
                        "required": [
                          "ref"
                        ],
                        "type": "object",
                        "additionalProperties": false
                      },
                      "metadata": {
                        "description": "metadata is the metadata applied to the MachineDeployment and the machines of the MachineDeployment.\nAt runtime this metadata is merged with the corresponding metadata from the topology.",
                        "properties": {
                          "annotations": {
                            "additionalProperties": {
                              "type": "string"
                            },
                            "description": "annotations is an unstructured key value map stored with a resource that may be\nset by external tools to store and retrieve arbitrary metadata. They are not\nqueryable and should be preserved when modifying objects.\nMore info: http://kubernetes.io/docs/user-guide/annotations",
                            "type": "object"
                          },
                          "labels": {
                            "additionalProperties": {
                              "type": "string"
                            },
                            "description": "labels is a map of string keys and values that can be used to organize and categorize\n(scope and select) objects. May match selectors of replication controllers\nand services.\nMore info: http://kubernetes.io/docs/user-guide/labels",
                            "type": "object"
                          }
                        },
                        "type": "object",
                        "additionalProperties": false
                      }
                    },
                    "required": [
                      "bootstrap",
                      "infrastructure"
                    ],
                    "type": "object",
                    "additionalProperties": false
                  }
                },
                "required": [
                  "class",
                  "template"
                ],
                "type": "object",
                "additionalProperties": false
              },
              "maxItems": 100,
              "type": "array",
              "x-kubernetes-list-map-keys": [
                "class"
              ],
              "x-kubernetes-list-type": "map"
            },
            "machinePools": {
              "description": "machinePools is a list of machine pool classes that can be used to create\na set of worker nodes.",
              "items": {
                "description": "MachinePoolClass serves as a template to define a pool of worker nodes of the cluster\nprovisioned using `ClusterClass`.",
                "properties": {
                  "class": {
                    "description": "class denotes a type of machine pool present in the cluster,\nthis name MUST be unique within a ClusterClass and can be referenced\nin the Cluster to create a managed MachinePool.",
                    "maxLength": 256,
                    "minLength": 1,
                    "type": "string"
                  },
                  "failureDomains": {
                    "description": "failureDomains is the list of failure domains the MachinePool should be attached to.\nMust match a key in the FailureDomains map stored on the cluster object.\nNOTE: This value can be overridden while defining a Cluster.Topology using this MachinePoolClass.",
                    "items": {
                      "maxLength": 256,
                      "minLength": 1,
                      "type": "string"
                    },
                    "maxItems": 100,
                    "type": "array"
                  },
                  "minReadySeconds": {
                    "description": "minReadySeconds is the minimum number of seconds for which a newly created machine pool should\nbe ready.\nDefaults to 0 (machine will be considered available as soon as it\nis ready)\nNOTE: This value can be overridden while defining a Cluster.Topology using this MachinePoolClass.",
                    "format": "int32",
                    "type": "integer"
                  },
                  "namingStrategy": {
                    "description": "namingStrategy allows changing the naming pattern used when creating the MachinePool.",
                    "properties": {
                      "template": {
                        "description": "template defines the template to use for generating the name of the MachinePool object.\nIf not defined, it will fallback to `{{ .cluster.name }}-{{ .machinePool.topologyName }}-{{ .random }}`.\nIf the templated string exceeds 63 characters, it will be trimmed to 58 characters and will\nget concatenated with a random suffix of length 5.\nThe templating mechanism provides the following arguments:\n* `.cluster.name`: The name of the cluster object.\n* `.random`: A random alphanumeric string, without vowels, of length 5.\n* `.machinePool.topologyName`: The name of the MachinePool topology (Cluster.spec.topology.workers.machinePools[].name).",
                        "maxLength": 1024,
                        "minLength": 1,
                        "type": "string"
                      }
                    },
                    "type": "object",
                    "additionalProperties": false
                  },
                  "nodeDeletionTimeout": {
                    "description": "nodeDeletionTimeout defines how long the controller will attempt to delete the Node that the Machine\nhosts after the Machine Pool is marked for deletion. A duration of 0 will retry deletion indefinitely.\nDefaults to 10 seconds.\nNOTE: This value can be overridden while defining a Cluster.Topology using this MachinePoolClass.",
                    "type": "string"
                  },
                  "nodeDrainTimeout": {
                    "description": "nodeDrainTimeout is the total amount of time that the controller will spend on draining a node.\nThe default value is 0, meaning that the node can be drained without any time limitations.\nNOTE: NodeDrainTimeout is different from `kubectl drain --timeout`\nNOTE: This value can be overridden while defining a Cluster.Topology using this MachinePoolClass.",
                    "type": "string"
                  },
                  "nodeVolumeDetachTimeout": {
                    "description": "nodeVolumeDetachTimeout is the total amount of time that the controller will spend on waiting for all volumes\nto be detached. The default value is 0, meaning that the volumes can be detached without any time limitations.\nNOTE: This value can be overridden while defining a Cluster.Topology using this MachinePoolClass.",
                    "type": "string"
                  },
                  "template": {
                    "description": "template is a local struct containing a collection of templates for creation of\nMachinePools objects representing a pool of worker nodes.",
                    "properties": {
                      "bootstrap": {
                        "description": "bootstrap contains the bootstrap template reference to be used\nfor the creation of the Machines in the MachinePool.",
                        "properties": {
                          "ref": {
                            "description": "ref is a required reference to a custom resource\noffered by a provider.",
                            "properties": {
                              "apiVersion": {
                                "description": "API version of the referent.",
                                "type": "string"
                              },
                              "fieldPath": {
                                "description": "If referring to a piece of an object instead of an entire object, this string\nshould contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2].\nFor example, if the object reference is to a container within a pod, this would take on a value like:\n\"spec.containers{name}\" (where \"name\" refers to the name of the container that triggered\nthe event) or if no container name is specified \"spec.containers[2]\" (container with\nindex 2 in this pod). This syntax is chosen only to have some well-defined way of\nreferencing a part of an object.",
                                "type": "string"
                              },
                              "kind": {
                                "description": "Kind of the referent.\nMore info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
                                "type": "string"
                              },
                              "name": {
                                "description": "Name of the referent.\nMore info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names",
                                "type": "string"
                              },
                              "namespace": {
                                "description": "Namespace of the referent.\nMore info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/",
                                "type": "string"
                              },
                              "resourceVersion": {
                                "description": "Specific resourceVersion to which this reference is made, if any.\nMore info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency",
                                "type": "string"
                              },
                              "uid": {
                                "description": "UID of the referent.\nMore info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids",
                                "type": "string"
                              }
                            },
                            "type": "object",
                            "x-kubernetes-map-type": "atomic",
                            "additionalProperties": false
                          }
                        },
                        "required": [
                          "ref"
                        ],
                        "type": "object",
                        "additionalProperties": false
                      },
                      "infrastructure": {
                        "description": "infrastructure contains the infrastructure template reference to be used\nfor the creation of the MachinePool.",
                        "properties": {
                          "ref": {
                            "description": "ref is a required reference to a custom resource\noffered by a provider.",
                            "properties": {
                              "apiVersion": {
                                "description": "API version of the referent.",
                                "type": "string"
                              },
                              "fieldPath": {
                                "description": "If referring to a piece of an object instead of an entire object, this string\nshould contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2].\nFor example, if the object reference is to a container within a pod, this would take on a value like:\n\"spec.containers{name}\" (where \"name\" refers to the name of the container that triggered\nthe event) or if no container name is specified \"spec.containers[2]\" (container with\nindex 2 in this pod). This syntax is chosen only to have some well-defined way of\nreferencing a part of an object.",
                                "type": "string"
                              },
                              "kind": {
                                "description": "Kind of the referent.\nMore info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
                                "type": "string"
                              },
                              "name": {
                                "description": "Name of the referent.\nMore info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names",
                                "type": "string"
                              },
                              "namespace": {
                                "description": "Namespace of the referent.\nMore info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/",
                                "type": "string"
                              },
                              "resourceVersion": {
                                "description": "Specific resourceVersion to which this reference is made, if any.\nMore info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency",
                                "type": "string"
                              },
                              "uid": {
                                "description": "UID of the referent.\nMore info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids",
                                "type": "string"
                              }
                            },
                            "type": "object",
                            "x-kubernetes-map-type": "atomic",
                            "additionalProperties": false
                          }
                        },
                        "required": [
                          "ref"
                        ],
                        "type": "object",
                        "additionalProperties": false
                      },
                      "metadata": {
                        "description": "metadata is the metadata applied to the MachinePool.\nAt runtime this metadata is merged with the corresponding metadata from the topology.",
                        "properties": {
                          "annotations": {
                            "additionalProperties": {
                              "type": "string"
                            },
                            "description": "annotations is an unstructured key value map stored with a resource that may be\nset by external tools to store and retrieve arbitrary metadata. They are not\nqueryable and should be preserved when modifying objects.\nMore info: http://kubernetes.io/docs/user-guide/annotations",
                            "type": "object"
                          },
                          "labels": {
                            "additionalProperties": {
                              "type": "string"
                            },
                            "description": "labels is a map of string keys and values that can be used to organize and categorize\n(scope and select) objects. May match selectors of replication controllers\nand services.\nMore info: http://kubernetes.io/docs/user-guide/labels",
                            "type": "object"
                          }
                        },
                        "type": "object",
                        "additionalProperties": false
                      }
                    },
                    "required": [
                      "bootstrap",
                      "infrastructure"
                    ],
                    "type": "object",
                    "additionalProperties": false
                  }
                },
                "required": [
                  "class",
                  "template"
                ],
                "type": "object",
                "additionalProperties": false
              },
              "maxItems": 100,
              "type": "array",
              "x-kubernetes-list-map-keys": [
                "class"
              ],
              "x-kubernetes-list-type": "map"
            }
          },
          "type": "object",
          "additionalProperties": false
        }
      },
      "type": "object",
      "additionalProperties": false
    },
    "status": {
      "description": "status is the observed state of ClusterClass.",
      "properties": {
        "conditions": {
          "description": "conditions defines current observed state of the ClusterClass.",
          "items": {
            "description": "Condition defines an observation of a Cluster API resource operational state.",
            "properties": {
              "lastTransitionTime": {
                "description": "lastTransitionTime is the last time the condition transitioned from one status to another.\nThis should be when the underlying condition changed. If that is not known, then using the time when\nthe API field changed is acceptable.",
                "format": "date-time",
                "type": "string"
              },
              "message": {
                "description": "message is a human readable message indicating details about the transition.\nThis field may be empty.",
                "maxLength": 10240,
                "minLength": 1,
                "type": "string"
              },
              "reason": {
                "description": "reason is the reason for the condition's last transition in CamelCase.\nThe specific API may choose whether or not this field is considered a guaranteed API.\nThis field may be empty.",
                "maxLength": 256,
                "minLength": 1,
                "type": "string"
              },
              "severity": {
                "description": "severity provides an explicit classification of Reason code, so the users or machines can immediately\nunderstand the current situation and act accordingly.\nThe Severity field MUST be set only when Status=False.",
                "maxLength": 32,
                "type": "string"
              },
              "status": {
                "description": "status of the condition, one of True, False, Unknown.",
                "type": "string"
              },
              "type": {
                "description": "type of condition in CamelCase or in foo.example.com/CamelCase.\nMany .condition.type values are consistent across resources like Available, but because arbitrary conditions\ncan be useful (see .node.status.conditions), the ability to deconflict is important.",
                "maxLength": 256,
                "minLength": 1,
                "type": "string"
              }
            },
            "required": [
              "lastTransitionTime",
              "status",
              "type"
            ],
            "type": "object",
            "additionalProperties": false
          },
          "type": "array"
        },
        "observedGeneration": {
          "description": "observedGeneration is the latest generation observed by the controller.",
          "format": "int64",
          "type": "integer"
        },
        "v1beta2": {
          "description": "v1beta2 groups all the fields that will be added or modified in ClusterClass's status with the V1Beta2 version.",
          "properties": {
            "conditions": {
              "description": "conditions represents the observations of a ClusterClass's current state.\nKnown condition types are VariablesReady, RefVersionsUpToDate, Paused.",
              "items": {
                "description": "Condition contains details for one aspect of the current state of this API Resource.",
                "properties": {
                  "lastTransitionTime": {
                    "description": "lastTransitionTime is the last time the condition transitioned from one status to another.\nThis should be when the underlying condition changed.  If that is not known, then using the time when the API field changed is acceptable.",
                    "format": "date-time",
                    "type": "string"
                  },
                  "message": {
                    "description": "message is a human readable message indicating details about the transition.\nThis may be an empty string.",
                    "maxLength": 32768,
                    "type": "string"
                  },
                  "observedGeneration": {
                    "description": "observedGeneration represents the .metadata.generation that the condition was set based upon.\nFor instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date\nwith respect to the current state of the instance.",
                    "format": "int64",
                    "minimum": 0,
                    "type": "integer"
                  },
                  "reason": {
                    "description": "reason contains a programmatic identifier indicating the reason for the condition's last transition.\nProducers of specific condition types may define expected values and meanings for this field,\nand whether the values are considered a guaranteed API.\nThe value should be a CamelCase string.\nThis field may not be empty.",
                    "maxLength": 1024,
                    "minLength": 1,
                    "pattern": "^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$",
                    "type": "string"
                  },
                  "status": {
                    "description": "status of the condition, one of True, False, Unknown.",
                    "enum": [
                      "True",
                      "False",
                      "Unknown"
                    ],
                    "type": "string"
                  },
                  "type": {
                    "description": "type of condition in CamelCase or in foo.example.com/CamelCase.",
                    "maxLength": 316,
                    "pattern": "^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$",
                    "type": "string"
                  }
                },
                "required": [
                  "lastTransitionTime",
                  "message",
                  "reason",
                  "status",
                  "type"
                ],
                "type": "object",
                "additionalProperties": false
              },
              "maxItems": 32,
              "type": "array",
              "x-kubernetes-list-map-keys": [
                "type"
              ],
              "x-kubernetes-list-type": "map"
            }
          },
          "type": "object",
          "additionalProperties": false
        },
        "variables": {
          "description": "variables is a list of ClusterClassStatusVariable that are defined for the ClusterClass.",
          "items": {
            "description": "ClusterClassStatusVariable defines a variable which appears in the status of a ClusterClass.",
            "properties": {
              "definitions": {
                "description": "definitions is a list of definitions for a variable.",
                "items": {
                  "description": "ClusterClassStatusVariableDefinition defines a variable which appears in the status of a ClusterClass.",
                  "properties": {
                    "from": {
                      "description": "from specifies the origin of the variable definition.\nThis will be `inline` for variables defined in the ClusterClass or the name of a patch defined in the ClusterClass\nfor variables discovered from a DiscoverVariables runtime extensions.",
                      "maxLength": 256,
                      "minLength": 1,
                      "type": "string"
                    },
                    "metadata": {
                      "description": "metadata is the metadata of a variable.\nIt can be used to add additional data for higher level tools to\na ClusterClassVariable.\n\nDeprecated: This field is deprecated and is going to be removed in the next apiVersion.",
                      "properties": {
                        "annotations": {
                          "additionalProperties": {
                            "type": "string"
                          },
                          "description": "annotations is an unstructured key value map that can be used to store and\nretrieve arbitrary metadata.\nThey are not queryable.",
                          "type": "object"
                        },
                        "labels": {
                          "additionalProperties": {
                            "type": "string"
                          },
                          "description": "labels is a map of string keys and values that can be used to organize and categorize\n(scope and select) variables.",
                          "type": "object"
                        }
                      },
                      "type": "object",
                      "additionalProperties": false
                    },
                    "required": {
                      "description": "required specifies if the variable is required.\nNote: this applies to the variable as a whole and thus the\ntop-level object defined in the schema. If nested fields are\nrequired, this will be specified inside the schema.",
                      "type": "boolean"
                    },
                    "schema": {
                      "description": "schema defines the schema of the variable.",
                      "properties": {
                        "openAPIV3Schema": {
                          "description": "openAPIV3Schema defines the schema of a variable via OpenAPI v3\nschema. The schema is a subset of the schema used in\nKubernetes CRDs.",
                          "properties": {
                            "additionalProperties": {
                              "description": "additionalProperties specifies the schema of values in a map (keys are always strings).\nNOTE: Can only be set if type is object.\nNOTE: AdditionalProperties is mutually exclusive with Properties.\nNOTE: This field uses PreserveUnknownFields and Schemaless,\nbecause recursive validation is not possible.",
                              "x-kubernetes-preserve-unknown-fields": true
                            },
                            "allOf": {
                              "description": "allOf specifies that the variable must validate against all of the subschemas in the array.\nNOTE: This field uses PreserveUnknownFields and Schemaless,\nbecause recursive validation is not possible.",
                              "x-kubernetes-preserve-unknown-fields": true
                            },
                            "anyOf": {
                              "description": "anyOf specifies that the variable must validate against one or more of the subschemas in the array.\nNOTE: This field uses PreserveUnknownFields and Schemaless,\nbecause recursive validation is not possible.",
                              "x-kubernetes-preserve-unknown-fields": true
                            },
                            "default": {
                              "description": "default is the default value of the variable.\nNOTE: Can be set for all types.",
                              "x-kubernetes-preserve-unknown-fields": true
                            },
                            "description": {
                              "description": "description is a human-readable description of this variable.",
                              "maxLength": 4096,
                              "minLength": 1,
                              "type": "string"
                            },
                            "enum": {
                              "description": "enum is the list of valid values of the variable.\nNOTE: Can be set for all types.",
                              "items": {
                                "x-kubernetes-preserve-unknown-fields": true
                              },
                              "maxItems": 100,
                              "type": "array"
                            },
                            "example": {
                              "description": "example is an example for this variable.",
                              "x-kubernetes-preserve-unknown-fields": true
                            },
                            "exclusiveMaximum": {
                              "description": "exclusiveMaximum specifies if the Maximum is exclusive.\nNOTE: Can only be set if type is integer or number.",
                              "type": "boolean"
                            },
                            "exclusiveMinimum": {
                              "description": "exclusiveMinimum specifies if the Minimum is exclusive.\nNOTE: Can only be set if type is integer or number.",
                              "type": "boolean"
                            },
                            "format": {
                              "description": "format is an OpenAPI v3 format string. Unknown formats are ignored.\nFor a list of supported formats please see: (of the k8s.io/apiextensions-apiserver version we're currently using)\nhttps://github.com/kubernetes/apiextensions-apiserver/blob/master/pkg/apiserver/validation/formats.go\nNOTE: Can only be set if type is string.",
                              "maxLength": 32,
                              "minLength": 1,
                              "type": "string"
                            },
                            "items": {
                              "description": "items specifies fields of an array.\nNOTE: Can only be set if type is array.\nNOTE: This field uses PreserveUnknownFields and Schemaless,\nbecause recursive validation is not possible.",
                              "x-kubernetes-preserve-unknown-fields": true
                            },
                            "maxItems": {
                              "description": "maxItems is the max length of an array variable.\nNOTE: Can only be set if type is array.",
                              "format": "int64",
                              "type": "integer"
                            },
                            "maxLength": {
                              "description": "maxLength is the max length of a string variable.\nNOTE: Can only be set if type is string.",
                              "format": "int64",
                              "type": "integer"
                            },
                            "maxProperties": {
                              "description": "maxProperties is the maximum amount of entries in a map or properties in an object.\nNOTE: Can only be set if type is object.",
                              "format": "int64",
                              "type": "integer"
                            },
                            "maximum": {
                              "description": "maximum is the maximum of an integer or number variable.\nIf ExclusiveMaximum is false, the variable is valid if it is lower than, or equal to, the value of Maximum.\nIf ExclusiveMaximum is true, the variable is valid if it is strictly lower than the value of Maximum.\nNOTE: Can only be set if type is integer or number.",
                              "format": "int64",
                              "type": "integer"
                            },
                            "minItems": {
                              "description": "minItems is the min length of an array variable.\nNOTE: Can only be set if type is array.",
                              "format": "int64",
                              "type": "integer"
                            },
                            "minLength": {
                              "description": "minLength is the min length of a string variable.\nNOTE: Can only be set if type is string.",
                              "format": "int64",
                              "type": "integer"
                            },
                            "minProperties": {
                              "description": "minProperties is the minimum amount of entries in a map or properties in an object.\nNOTE: Can only be set if type is object.",
                              "format": "int64",
                              "type": "integer"
                            },
                            "minimum": {
                              "description": "minimum is the minimum of an integer or number variable.\nIf ExclusiveMinimum is false, the variable is valid if it is greater than, or equal to, the value of Minimum.\nIf ExclusiveMinimum is true, the variable is valid if it is strictly greater than the value of Minimum.\nNOTE: Can only be set if type is integer or number.",
                              "format": "int64",
                              "type": "integer"
                            },
                            "not": {
                              "description": "not specifies that the variable must not validate against the subschema.\nNOTE: This field uses PreserveUnknownFields and Schemaless,\nbecause recursive validation is not possible.",
                              "x-kubernetes-preserve-unknown-fields": true
                            },
                            "oneOf": {
                              "description": "oneOf specifies that the variable must validate against exactly one of the subschemas in the array.\nNOTE: This field uses PreserveUnknownFields and Schemaless,\nbecause recursive validation is not possible.",
                              "x-kubernetes-preserve-unknown-fields": true
                            },
                            "pattern": {
                              "description": "pattern is the regex which a string variable must match.\nNOTE: Can only be set if type is string.",
                              "maxLength": 512,
                              "minLength": 1,
                              "type": "string"
                            },
                            "properties": {
                              "description": "properties specifies fields of an object.\nNOTE: Can only be set if type is object.\nNOTE: Properties is mutually exclusive with AdditionalProperties.\nNOTE: This field uses PreserveUnknownFields and Schemaless,\nbecause recursive validation is not possible.",
                              "x-kubernetes-preserve-unknown-fields": true
                            },
                            "required": {
                              "description": "required specifies which fields of an object are required.\nNOTE: Can only be set if type is object.",
                              "items": {
                                "maxLength": 256,
                                "minLength": 1,
                                "type": "string"
                              },
                              "maxItems": 1000,
                              "type": "array"
                            },
                            "type": {
                              "description": "type is the type of the variable.\nValid values are: object, array, string, integer, number or boolean.",
                              "enum": [
                                "object",
                                "array",
                                "string",
                                "integer",
                                "number",
                                "boolean"
                              ],
                              "type": "string"
                            },
                            "uniqueItems": {
                              "description": "uniqueItems specifies if items in an array must be unique.\nNOTE: Can only be set if type is array.",
                              "type": "boolean"
                            },
                            "x-kubernetes-int-or-string": {
                              "description": "x-kubernetes-int-or-string specifies that this value is\neither an integer or a string. If this is true, an empty\ntype is allowed and type as child of anyOf is permitted\nif following one of the following patterns:\n\n1) anyOf:\n   - type: integer\n   - type: string\n2) allOf:\n   - anyOf:\n     - type: integer\n     - type: string\n   - ... zero or more",
                              "type": "boolean"
                            },
                            "x-kubernetes-preserve-unknown-fields": {
                              "description": "x-kubernetes-preserve-unknown-fields allows setting fields in a variable object\nwhich are not defined in the variable schema. This affects fields recursively,\nexcept if nested properties or additionalProperties are specified in the schema.",
                              "type": "boolean"
                            },
                            "x-kubernetes-validations": {
                              "description": "x-kubernetes-validations describes a list of validation rules written in the CEL expression language.",
                              "items": {
                                "description": "ValidationRule describes a validation rule written in the CEL expression language.",
                                "properties": {
                                  "fieldPath": {
                                    "description": "fieldPath represents the field path returned when the validation fails.\nIt 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.\ne.g. when validation checks if a specific attribute `foo` under a map `testMap`, the fieldPath could be set to `.testMap.foo`\nIf the validation checks two lists must have unique attributes, the fieldPath could be set to either of the list: e.g. `.testList`\nIt does not support list numeric index.\nIt 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.\nNumeric index of array is not supported.\nFor field name which contains special characters, use `['specialName']` to refer the field name.\ne.g. for attribute `foo.34$` appears in a list `testList`, the fieldPath could be set to `.testList['foo.34$']`",
                                    "maxLength": 512,
                                    "minLength": 1,
                                    "type": "string"
                                  },
                                  "message": {
                                    "description": "message represents the message displayed when validation fails. The message is required if the Rule contains\nline breaks. The message must not contain line breaks.\nIf unset, the message is \"failed rule: {Rule}\".\ne.g. \"must be a URL with the host matching spec.host\"",
                                    "maxLength": 512,
                                    "minLength": 1,
                                    "type": "string"
                                  },
                                  "messageExpression": {
                                    "description": "messageExpression declares a CEL expression that evaluates to the validation failure message that is returned when this rule fails.\nSince messageExpression is used as a failure message, it must evaluate to a string.\nIf both message and messageExpression are present on a rule, then messageExpression will be used if validation\nfails. If messageExpression results in a runtime error, the validation failure message is produced\nas if the messageExpression field were unset. If messageExpression evaluates to an empty string, a string with only spaces, or a string\nthat contains line breaks, then the validation failure message will also be produced as if the messageExpression field were unset.\nmessageExpression has access to all the same variables as the rule; the only difference is the return type.\nExample:\n\"x must be less than max (\"+string(self.max)+\")\"",
                                    "maxLength": 1024,
                                    "minLength": 1,
                                    "type": "string"
                                  },
                                  "reason": {
                                    "default": "FieldValueInvalid",
                                    "description": "reason provides a machine-readable validation failure reason that is returned to the caller when a request fails this validation rule.\nThe currently supported reasons are: \"FieldValueInvalid\", \"FieldValueForbidden\", \"FieldValueRequired\", \"FieldValueDuplicate\".\nIf not set, default to use \"FieldValueInvalid\".\nAll future added reasons must be accepted by clients when reading this value and unknown reasons should be treated as FieldValueInvalid.",
                                    "enum": [
                                      "FieldValueInvalid",
                                      "FieldValueForbidden",
                                      "FieldValueRequired",
                                      "FieldValueDuplicate"
                                    ],
                                    "type": "string"
                                  },
                                  "rule": {
                                    "description": "rule represents the expression which will be evaluated by CEL.\nref: https://github.com/google/cel-spec\nThe Rule is scoped to the location of the x-kubernetes-validations extension in the schema.\nThe `self` variable in the CEL expression is bound to the scoped value.\nIf the Rule is scoped to an object with properties, the accessible properties of the object are field selectable\nvia `self.field` and field presence can be checked via `has(self.field)`.\nIf the Rule is scoped to an object with additionalProperties (i.e. a map) the value of the map\nare accessible via `self[mapKey]`, map containment can be checked via `mapKey in self` and all entries of the map\nare accessible via CEL macros and functions such as `self.all(...)`.\nIf the Rule is scoped to an array, the elements of the array are accessible via `self[i]` and also by macros and\nfunctions.\nIf the Rule is scoped to a scalar, `self` is bound to the scalar value.\nExamples:\n- Rule scoped to a map of objects: {\"rule\": \"self.components['Widget'].priority < 10\"}\n- Rule scoped to a list of integers: {\"rule\": \"self.values.all(value, value >= 0 && value < 100)\"}\n- Rule scoped to a string value: {\"rule\": \"self.startsWith('kube')\"}\n\nUnknown data preserved in custom resources via x-kubernetes-preserve-unknown-fields is not accessible in CEL\nexpressions. This includes:\n- Unknown field values that are preserved by object schemas with x-kubernetes-preserve-unknown-fields.\n- Object properties where the property schema is of an \"unknown type\". An \"unknown type\" is recursively defined as:\n  - A schema with no type and x-kubernetes-preserve-unknown-fields set to true\n  - An array where the items schema is of an \"unknown type\"\n  - An object where the additionalProperties schema is of an \"unknown type\"\n\nOnly property names of the form `[a-zA-Z_.-/][a-zA-Z0-9_.-/]*` are accessible.\nAccessible property names are escaped according to the following rules when accessed in the expression:\n- '__' escapes to '__underscores__'\n- '.' escapes to '__dot__'\n- '-' escapes to '__dash__'\n- '/' escapes to '__slash__'\n- Property names that exactly match a CEL RESERVED keyword escape to '__{keyword}__'. The keywords are:\n\t  \"true\", \"false\", \"null\", \"in\", \"as\", \"break\", \"const\", \"continue\", \"else\", \"for\", \"function\", \"if\",\n\t  \"import\", \"let\", \"loop\", \"package\", \"namespace\", \"return\".\nExamples:\n  - Rule accessing a property named \"namespace\": {\"rule\": \"self.__namespace__ > 0\"}\n  - Rule accessing a property named \"x-prop\": {\"rule\": \"self.x__dash__prop > 0\"}\n  - Rule accessing a property named \"redact__d\": {\"rule\": \"self.redact__underscores__d > 0\"}\n\nIf `rule` makes use of the `oldSelf` variable it is implicitly a\n`transition rule`.\n\nBy default, the `oldSelf` variable is the same type as `self`.\n\nTransition rules by default are applied only on UPDATE requests and are\nskipped if an old value could not be found.",
                                    "maxLength": 4096,
                                    "minLength": 1,
                                    "type": "string"
                                  }
                                },
                                "required": [
                                  "rule"
                                ],
                                "type": "object",
                                "additionalProperties": false
                              },
                              "maxItems": 100,
                              "type": "array",
                              "x-kubernetes-list-map-keys": [
                                "rule"
                              ],
                              "x-kubernetes-list-type": "map"
                            },
                            "x-metadata": {
                              "description": "x-metadata is the metadata of a variable or a nested field within a variable.\nIt can be used to add additional data for higher level tools.",
                              "properties": {
                                "annotations": {
                                  "additionalProperties": {
                                    "type": "string"
                                  },
                                  "description": "annotations is an unstructured key value map that can be used to store and\nretrieve arbitrary metadata.\nThey are not queryable.",
                                  "type": "object"
                                },
                                "labels": {
                                  "additionalProperties": {
                                    "type": "string"
                                  },
                                  "description": "labels is a map of string keys and values that can be used to organize and categorize\n(scope and select) variables.",
                                  "type": "object"
                                }
                              },
                              "type": "object",
                              "additionalProperties": false
                            }
                          },
                          "type": "object",
                          "additionalProperties": false
                        }
                      },
                      "required": [
                        "openAPIV3Schema"
                      ],
                      "type": "object",
                      "additionalProperties": false
                    }
                  },
                  "required": [
                    "from",
                    "required",
                    "schema"
                  ],
                  "type": "object",
                  "additionalProperties": false
                },
                "maxItems": 100,
                "type": "array"
              },
              "definitionsConflict": {
                "description": "definitionsConflict specifies whether or not there are conflicting definitions for a single variable name.",
                "type": "boolean"
              },
              "name": {
                "description": "name is the name of the variable.",
                "maxLength": 256,
                "minLength": 1,
                "type": "string"
              }
            },
            "required": [
              "definitions",
              "name"
            ],
            "type": "object",
            "additionalProperties": false
          },
          "maxItems": 1000,
          "type": "array"
        }
      },
      "type": "object",
      "additionalProperties": false
    }
  },
  "type": "object"
}
