sigs.k8s.io/cluster-api@v1.7.1/api/v1beta1/clusterclass_types.go (about)

     1  /*
     2  Copyright 2021 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package v1beta1
    18  
    19  import (
    20  	"reflect"
    21  
    22  	corev1 "k8s.io/api/core/v1"
    23  	apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
    24  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    25  	"k8s.io/apimachinery/pkg/util/intstr"
    26  )
    27  
    28  // ClusterClassKind represents the Kind of ClusterClass.
    29  const ClusterClassKind = "ClusterClass"
    30  
    31  // +kubebuilder:object:root=true
    32  // +kubebuilder:resource:path=clusterclasses,shortName=cc,scope=Namespaced,categories=cluster-api
    33  // +kubebuilder:storageversion
    34  // +kubebuilder:subresource:status
    35  // +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="Time duration since creation of ClusterClass"
    36  
    37  // ClusterClass is a template which can be used to create managed topologies.
    38  type ClusterClass struct {
    39  	metav1.TypeMeta   `json:",inline"`
    40  	metav1.ObjectMeta `json:"metadata,omitempty"`
    41  
    42  	Spec   ClusterClassSpec   `json:"spec,omitempty"`
    43  	Status ClusterClassStatus `json:"status,omitempty"`
    44  }
    45  
    46  // ClusterClassSpec describes the desired state of the ClusterClass.
    47  type ClusterClassSpec struct {
    48  	// Infrastructure is a reference to a provider-specific template that holds
    49  	// the details for provisioning infrastructure specific cluster
    50  	// for the underlying provider.
    51  	// The underlying provider is responsible for the implementation
    52  	// of the template to an infrastructure cluster.
    53  	// +optional
    54  	Infrastructure LocalObjectTemplate `json:"infrastructure,omitempty"`
    55  
    56  	// ControlPlane is a reference to a local struct that holds the details
    57  	// for provisioning the Control Plane for the Cluster.
    58  	// +optional
    59  	ControlPlane ControlPlaneClass `json:"controlPlane,omitempty"`
    60  
    61  	// Workers describes the worker nodes for the cluster.
    62  	// It is a collection of node types which can be used to create
    63  	// the worker nodes of the cluster.
    64  	// +optional
    65  	Workers WorkersClass `json:"workers,omitempty"`
    66  
    67  	// Variables defines the variables which can be configured
    68  	// in the Cluster topology and are then used in patches.
    69  	// +optional
    70  	Variables []ClusterClassVariable `json:"variables,omitempty"`
    71  
    72  	// Patches defines the patches which are applied to customize
    73  	// referenced templates of a ClusterClass.
    74  	// Note: Patches will be applied in the order of the array.
    75  	// +optional
    76  	Patches []ClusterClassPatch `json:"patches,omitempty"`
    77  }
    78  
    79  // ControlPlaneClass defines the class for the control plane.
    80  type ControlPlaneClass struct {
    81  	// Metadata is the metadata applied to the ControlPlane and the Machines of the ControlPlane
    82  	// if the ControlPlaneTemplate referenced is machine based. If not, it is applied only to the
    83  	// ControlPlane.
    84  	// At runtime this metadata is merged with the corresponding metadata from the topology.
    85  	//
    86  	// This field is supported if and only if the control plane provider template
    87  	// referenced is Machine based.
    88  	// +optional
    89  	Metadata ObjectMeta `json:"metadata,omitempty"`
    90  
    91  	// LocalObjectTemplate contains the reference to the control plane provider.
    92  	LocalObjectTemplate `json:",inline"`
    93  
    94  	// MachineInfrastructure defines the metadata and infrastructure information
    95  	// for control plane machines.
    96  	//
    97  	// This field is supported if and only if the control plane provider template
    98  	// referenced above is Machine based and supports setting replicas.
    99  	//
   100  	// +optional
   101  	MachineInfrastructure *LocalObjectTemplate `json:"machineInfrastructure,omitempty"`
   102  
   103  	// MachineHealthCheck defines a MachineHealthCheck for this ControlPlaneClass.
   104  	// This field is supported if and only if the ControlPlane provider template
   105  	// referenced above is Machine based and supports setting replicas.
   106  	// +optional
   107  	MachineHealthCheck *MachineHealthCheckClass `json:"machineHealthCheck,omitempty"`
   108  
   109  	// NamingStrategy allows changing the naming pattern used when creating the control plane provider object.
   110  	// +optional
   111  	NamingStrategy *ControlPlaneClassNamingStrategy `json:"namingStrategy,omitempty"`
   112  
   113  	// NodeDrainTimeout is the total amount of time that the controller will spend on draining a node.
   114  	// The default value is 0, meaning that the node can be drained without any time limitations.
   115  	// NOTE: NodeDrainTimeout is different from `kubectl drain --timeout`
   116  	// NOTE: This value can be overridden while defining a Cluster.Topology.
   117  	// +optional
   118  	NodeDrainTimeout *metav1.Duration `json:"nodeDrainTimeout,omitempty"`
   119  
   120  	// NodeVolumeDetachTimeout is the total amount of time that the controller will spend on waiting for all volumes
   121  	// to be detached. The default value is 0, meaning that the volumes can be detached without any time limitations.
   122  	// NOTE: This value can be overridden while defining a Cluster.Topology.
   123  	// +optional
   124  	NodeVolumeDetachTimeout *metav1.Duration `json:"nodeVolumeDetachTimeout,omitempty"`
   125  
   126  	// NodeDeletionTimeout defines how long the controller will attempt to delete the Node that the Machine
   127  	// hosts after the Machine is marked for deletion. A duration of 0 will retry deletion indefinitely.
   128  	// Defaults to 10 seconds.
   129  	// NOTE: This value can be overridden while defining a Cluster.Topology.
   130  	// +optional
   131  	NodeDeletionTimeout *metav1.Duration `json:"nodeDeletionTimeout,omitempty"`
   132  }
   133  
   134  // ControlPlaneClassNamingStrategy defines the naming strategy for control plane objects.
   135  type ControlPlaneClassNamingStrategy struct {
   136  	// Template defines the template to use for generating the name of the ControlPlane object.
   137  	// If not defined, it will fallback to `{{ .cluster.name }}-{{ .random }}`.
   138  	// If the templated string exceeds 63 characters, it will be trimmed to 58 characters and will
   139  	// get concatenated with a random suffix of length 5.
   140  	// The templating mechanism provides the following arguments:
   141  	// * `.cluster.name`: The name of the cluster object.
   142  	// * `.random`: A random alphanumeric string, without vowels, of length 5.
   143  	// +optional
   144  	Template *string `json:"template,omitempty"`
   145  }
   146  
   147  // WorkersClass is a collection of deployment classes.
   148  type WorkersClass struct {
   149  	// MachineDeployments is a list of machine deployment classes that can be used to create
   150  	// a set of worker nodes.
   151  	// +optional
   152  	MachineDeployments []MachineDeploymentClass `json:"machineDeployments,omitempty"`
   153  
   154  	// MachinePools is a list of machine pool classes that can be used to create
   155  	// a set of worker nodes.
   156  	// +optional
   157  	MachinePools []MachinePoolClass `json:"machinePools,omitempty"`
   158  }
   159  
   160  // MachineDeploymentClass serves as a template to define a set of worker nodes of the cluster
   161  // provisioned using the `ClusterClass`.
   162  type MachineDeploymentClass struct {
   163  	// Class denotes a type of worker node present in the cluster,
   164  	// this name MUST be unique within a ClusterClass and can be referenced
   165  	// in the Cluster to create a managed MachineDeployment.
   166  	Class string `json:"class"`
   167  
   168  	// Template is a local struct containing a collection of templates for creation of
   169  	// MachineDeployment objects representing a set of worker nodes.
   170  	Template MachineDeploymentClassTemplate `json:"template"`
   171  
   172  	// MachineHealthCheck defines a MachineHealthCheck for this MachineDeploymentClass.
   173  	// +optional
   174  	MachineHealthCheck *MachineHealthCheckClass `json:"machineHealthCheck,omitempty"`
   175  
   176  	// FailureDomain is the failure domain the machines will be created in.
   177  	// Must match a key in the FailureDomains map stored on the cluster object.
   178  	// NOTE: This value can be overridden while defining a Cluster.Topology using this MachineDeploymentClass.
   179  	// +optional
   180  	FailureDomain *string `json:"failureDomain,omitempty"`
   181  
   182  	// NamingStrategy allows changing the naming pattern used when creating the MachineDeployment.
   183  	// +optional
   184  	NamingStrategy *MachineDeploymentClassNamingStrategy `json:"namingStrategy,omitempty"`
   185  
   186  	// NodeDrainTimeout is the total amount of time that the controller will spend on draining a node.
   187  	// The default value is 0, meaning that the node can be drained without any time limitations.
   188  	// NOTE: NodeDrainTimeout is different from `kubectl drain --timeout`
   189  	// NOTE: This value can be overridden while defining a Cluster.Topology using this MachineDeploymentClass.
   190  	// +optional
   191  	NodeDrainTimeout *metav1.Duration `json:"nodeDrainTimeout,omitempty"`
   192  
   193  	// NodeVolumeDetachTimeout is the total amount of time that the controller will spend on waiting for all volumes
   194  	// to be detached. The default value is 0, meaning that the volumes can be detached without any time limitations.
   195  	// NOTE: This value can be overridden while defining a Cluster.Topology using this MachineDeploymentClass.
   196  	// +optional
   197  	NodeVolumeDetachTimeout *metav1.Duration `json:"nodeVolumeDetachTimeout,omitempty"`
   198  
   199  	// NodeDeletionTimeout defines how long the controller will attempt to delete the Node that the Machine
   200  	// hosts after the Machine is marked for deletion. A duration of 0 will retry deletion indefinitely.
   201  	// Defaults to 10 seconds.
   202  	// NOTE: This value can be overridden while defining a Cluster.Topology using this MachineDeploymentClass.
   203  	// +optional
   204  	NodeDeletionTimeout *metav1.Duration `json:"nodeDeletionTimeout,omitempty"`
   205  
   206  	// Minimum number of seconds for which a newly created machine should
   207  	// be ready.
   208  	// Defaults to 0 (machine will be considered available as soon as it
   209  	// is ready)
   210  	// NOTE: This value can be overridden while defining a Cluster.Topology using this MachineDeploymentClass.
   211  	MinReadySeconds *int32 `json:"minReadySeconds,omitempty"`
   212  
   213  	// The deployment strategy to use to replace existing machines with
   214  	// new ones.
   215  	// NOTE: This value can be overridden while defining a Cluster.Topology using this MachineDeploymentClass.
   216  	Strategy *MachineDeploymentStrategy `json:"strategy,omitempty"`
   217  }
   218  
   219  // MachineDeploymentClassTemplate defines how a MachineDeployment generated from a MachineDeploymentClass
   220  // should look like.
   221  type MachineDeploymentClassTemplate struct {
   222  	// Metadata is the metadata applied to the MachineDeployment and the machines of the MachineDeployment.
   223  	// At runtime this metadata is merged with the corresponding metadata from the topology.
   224  	// +optional
   225  	Metadata ObjectMeta `json:"metadata,omitempty"`
   226  
   227  	// Bootstrap contains the bootstrap template reference to be used
   228  	// for the creation of worker Machines.
   229  	Bootstrap LocalObjectTemplate `json:"bootstrap"`
   230  
   231  	// Infrastructure contains the infrastructure template reference to be used
   232  	// for the creation of worker Machines.
   233  	Infrastructure LocalObjectTemplate `json:"infrastructure"`
   234  }
   235  
   236  // MachineDeploymentClassNamingStrategy defines the naming strategy for machine deployment objects.
   237  type MachineDeploymentClassNamingStrategy struct {
   238  	// Template defines the template to use for generating the name of the MachineDeployment object.
   239  	// If not defined, it will fallback to `{{ .cluster.name }}-{{ .machineDeployment.topologyName }}-{{ .random }}`.
   240  	// If the templated string exceeds 63 characters, it will be trimmed to 58 characters and will
   241  	// get concatenated with a random suffix of length 5.
   242  	// The templating mechanism provides the following arguments:
   243  	// * `.cluster.name`: The name of the cluster object.
   244  	// * `.random`: A random alphanumeric string, without vowels, of length 5.
   245  	// * `.machineDeployment.topologyName`: The name of the MachineDeployment topology (Cluster.spec.topology.workers.machineDeployments[].name).
   246  	// +optional
   247  	Template *string `json:"template,omitempty"`
   248  }
   249  
   250  // MachineHealthCheckClass defines a MachineHealthCheck for a group of Machines.
   251  type MachineHealthCheckClass struct {
   252  	// UnhealthyConditions contains a list of the conditions that determine
   253  	// whether a node is considered unhealthy. The conditions are combined in a
   254  	// logical OR, i.e. if any of the conditions is met, the node is unhealthy.
   255  	UnhealthyConditions []UnhealthyCondition `json:"unhealthyConditions,omitempty"`
   256  
   257  	// Any further remediation is only allowed if at most "MaxUnhealthy" machines selected by
   258  	// "selector" are not healthy.
   259  	// +optional
   260  	MaxUnhealthy *intstr.IntOrString `json:"maxUnhealthy,omitempty"`
   261  
   262  	// Any further remediation is only allowed if the number of machines selected by "selector" as not healthy
   263  	// is within the range of "UnhealthyRange". Takes precedence over MaxUnhealthy.
   264  	// Eg. "[3-5]" - This means that remediation will be allowed only when:
   265  	// (a) there are at least 3 unhealthy machines (and)
   266  	// (b) there are at most 5 unhealthy machines
   267  	// +optional
   268  	// +kubebuilder:validation:Pattern=^\[[0-9]+-[0-9]+\]$
   269  	UnhealthyRange *string `json:"unhealthyRange,omitempty"`
   270  
   271  	// Machines older than this duration without a node will be considered to have
   272  	// failed and will be remediated.
   273  	// If you wish to disable this feature, set the value explicitly to 0.
   274  	// +optional
   275  	NodeStartupTimeout *metav1.Duration `json:"nodeStartupTimeout,omitempty"`
   276  
   277  	// RemediationTemplate is a reference to a remediation template
   278  	// provided by an infrastructure provider.
   279  	//
   280  	// This field is completely optional, when filled, the MachineHealthCheck controller
   281  	// creates a new object from the template referenced and hands off remediation of the machine to
   282  	// a controller that lives outside of Cluster API.
   283  	// +optional
   284  	RemediationTemplate *corev1.ObjectReference `json:"remediationTemplate,omitempty"`
   285  }
   286  
   287  // MachinePoolClass serves as a template to define a pool of worker nodes of the cluster
   288  // provisioned using `ClusterClass`.
   289  type MachinePoolClass struct {
   290  	// Class denotes a type of machine pool present in the cluster,
   291  	// this name MUST be unique within a ClusterClass and can be referenced
   292  	// in the Cluster to create a managed MachinePool.
   293  	Class string `json:"class"`
   294  
   295  	// Template is a local struct containing a collection of templates for creation of
   296  	// MachinePools objects representing a pool of worker nodes.
   297  	Template MachinePoolClassTemplate `json:"template"`
   298  
   299  	// FailureDomains is the list of failure domains the MachinePool should be attached to.
   300  	// Must match a key in the FailureDomains map stored on the cluster object.
   301  	// NOTE: This value can be overridden while defining a Cluster.Topology using this MachinePoolClass.
   302  	// +optional
   303  	FailureDomains []string `json:"failureDomains,omitempty"`
   304  
   305  	// NamingStrategy allows changing the naming pattern used when creating the MachinePool.
   306  	// +optional
   307  	NamingStrategy *MachinePoolClassNamingStrategy `json:"namingStrategy,omitempty"`
   308  
   309  	// NodeDrainTimeout is the total amount of time that the controller will spend on draining a node.
   310  	// The default value is 0, meaning that the node can be drained without any time limitations.
   311  	// NOTE: NodeDrainTimeout is different from `kubectl drain --timeout`
   312  	// NOTE: This value can be overridden while defining a Cluster.Topology using this MachinePoolClass.
   313  	// +optional
   314  	NodeDrainTimeout *metav1.Duration `json:"nodeDrainTimeout,omitempty"`
   315  
   316  	// NodeVolumeDetachTimeout is the total amount of time that the controller will spend on waiting for all volumes
   317  	// to be detached. The default value is 0, meaning that the volumes can be detached without any time limitations.
   318  	// NOTE: This value can be overridden while defining a Cluster.Topology using this MachinePoolClass.
   319  	// +optional
   320  	NodeVolumeDetachTimeout *metav1.Duration `json:"nodeVolumeDetachTimeout,omitempty"`
   321  
   322  	// NodeDeletionTimeout defines how long the controller will attempt to delete the Node that the Machine
   323  	// hosts after the Machine Pool is marked for deletion. A duration of 0 will retry deletion indefinitely.
   324  	// Defaults to 10 seconds.
   325  	// NOTE: This value can be overridden while defining a Cluster.Topology using this MachinePoolClass.
   326  	// +optional
   327  	NodeDeletionTimeout *metav1.Duration `json:"nodeDeletionTimeout,omitempty"`
   328  
   329  	// Minimum number of seconds for which a newly created machine pool should
   330  	// be ready.
   331  	// Defaults to 0 (machine will be considered available as soon as it
   332  	// is ready)
   333  	// NOTE: This value can be overridden while defining a Cluster.Topology using this MachinePoolClass.
   334  	MinReadySeconds *int32 `json:"minReadySeconds,omitempty"`
   335  }
   336  
   337  // MachinePoolClassTemplate defines how a MachinePool generated from a MachinePoolClass
   338  // should look like.
   339  type MachinePoolClassTemplate struct {
   340  	// Metadata is the metadata applied to the MachinePool.
   341  	// At runtime this metadata is merged with the corresponding metadata from the topology.
   342  	// +optional
   343  	Metadata ObjectMeta `json:"metadata,omitempty"`
   344  
   345  	// Bootstrap contains the bootstrap template reference to be used
   346  	// for the creation of the Machines in the MachinePool.
   347  	Bootstrap LocalObjectTemplate `json:"bootstrap"`
   348  
   349  	// Infrastructure contains the infrastructure template reference to be used
   350  	// for the creation of the MachinePool.
   351  	Infrastructure LocalObjectTemplate `json:"infrastructure"`
   352  }
   353  
   354  // MachinePoolClassNamingStrategy defines the naming strategy for machine pool objects.
   355  type MachinePoolClassNamingStrategy struct {
   356  	// Template defines the template to use for generating the name of the MachinePool object.
   357  	// If not defined, it will fallback to `{{ .cluster.name }}-{{ .machinePool.topologyName }}-{{ .random }}`.
   358  	// If the templated string exceeds 63 characters, it will be trimmed to 58 characters and will
   359  	// get concatenated with a random suffix of length 5.
   360  	// The templating mechanism provides the following arguments:
   361  	// * `.cluster.name`: The name of the cluster object.
   362  	// * `.random`: A random alphanumeric string, without vowels, of length 5.
   363  	// * `.machinePool.topologyName`: The name of the MachinePool topology (Cluster.spec.topology.workers.machinePools[].name).
   364  	// +optional
   365  	Template *string `json:"template,omitempty"`
   366  }
   367  
   368  // IsZero returns true if none of the values of MachineHealthCheckClass are defined.
   369  func (m MachineHealthCheckClass) IsZero() bool {
   370  	return reflect.ValueOf(m).IsZero()
   371  }
   372  
   373  // ClusterClassVariable defines a variable which can
   374  // be configured in the Cluster topology and used in patches.
   375  type ClusterClassVariable struct {
   376  	// Name of the variable.
   377  	Name string `json:"name"`
   378  
   379  	// Required specifies if the variable is required.
   380  	// Note: this applies to the variable as a whole and thus the
   381  	// top-level object defined in the schema. If nested fields are
   382  	// required, this will be specified inside the schema.
   383  	Required bool `json:"required"`
   384  
   385  	// Metadata is the metadata of a variable.
   386  	// It can be used to add additional data for higher level tools to
   387  	// a ClusterClassVariable.
   388  	// +optional
   389  	Metadata ClusterClassVariableMetadata `json:"metadata,omitempty"`
   390  
   391  	// Schema defines the schema of the variable.
   392  	Schema VariableSchema `json:"schema"`
   393  }
   394  
   395  // ClusterClassVariableMetadata is the metadata of a variable.
   396  // It can be used to add additional data for higher level tools to
   397  // a ClusterClassVariable.
   398  type ClusterClassVariableMetadata struct {
   399  	// Map of string keys and values that can be used to organize and categorize
   400  	// (scope and select) variables.
   401  	// +optional
   402  	Labels map[string]string `json:"labels,omitempty"`
   403  
   404  	// Annotations is an unstructured key value map that can be used to store and
   405  	// retrieve arbitrary metadata.
   406  	// They are not queryable.
   407  	// +optional
   408  	Annotations map[string]string `json:"annotations,omitempty"`
   409  }
   410  
   411  // VariableSchema defines the schema of a variable.
   412  type VariableSchema struct {
   413  	// OpenAPIV3Schema defines the schema of a variable via OpenAPI v3
   414  	// schema. The schema is a subset of the schema used in
   415  	// Kubernetes CRDs.
   416  	OpenAPIV3Schema JSONSchemaProps `json:"openAPIV3Schema"`
   417  }
   418  
   419  // JSONSchemaProps is a JSON-Schema following Specification Draft 4 (http://json-schema.org/).
   420  // This struct has been initially copied from apiextensionsv1.JSONSchemaProps, but all fields
   421  // which are not supported in CAPI have been removed.
   422  type JSONSchemaProps struct {
   423  	// Description is a human-readable description of this variable.
   424  	Description string `json:"description,omitempty"`
   425  
   426  	// Example is an example for this variable.
   427  	Example *apiextensionsv1.JSON `json:"example,omitempty"`
   428  
   429  	// Type is the type of the variable.
   430  	// Valid values are: object, array, string, integer, number or boolean.
   431  	Type string `json:"type"`
   432  
   433  	// Properties specifies fields of an object.
   434  	// NOTE: Can only be set if type is object.
   435  	// NOTE: Properties is mutually exclusive with AdditionalProperties.
   436  	// NOTE: This field uses PreserveUnknownFields and Schemaless,
   437  	// because recursive validation is not possible.
   438  	// +optional
   439  	// +kubebuilder:pruning:PreserveUnknownFields
   440  	// +kubebuilder:validation:Schemaless
   441  	Properties map[string]JSONSchemaProps `json:"properties,omitempty"`
   442  
   443  	// AdditionalProperties specifies the schema of values in a map (keys are always strings).
   444  	// NOTE: Can only be set if type is object.
   445  	// NOTE: AdditionalProperties is mutually exclusive with Properties.
   446  	// NOTE: This field uses PreserveUnknownFields and Schemaless,
   447  	// because recursive validation is not possible.
   448  	// +optional
   449  	// +kubebuilder:pruning:PreserveUnknownFields
   450  	// +kubebuilder:validation:Schemaless
   451  	AdditionalProperties *JSONSchemaProps `json:"additionalProperties,omitempty"`
   452  
   453  	// Required specifies which fields of an object are required.
   454  	// NOTE: Can only be set if type is object.
   455  	// +optional
   456  	Required []string `json:"required,omitempty"`
   457  
   458  	// Items specifies fields of an array.
   459  	// NOTE: Can only be set if type is array.
   460  	// NOTE: This field uses PreserveUnknownFields and Schemaless,
   461  	// because recursive validation is not possible.
   462  	// +optional
   463  	// +kubebuilder:pruning:PreserveUnknownFields
   464  	// +kubebuilder:validation:Schemaless
   465  	Items *JSONSchemaProps `json:"items,omitempty"`
   466  
   467  	// MaxItems is the max length of an array variable.
   468  	// NOTE: Can only be set if type is array.
   469  	// +optional
   470  	MaxItems *int64 `json:"maxItems,omitempty"`
   471  
   472  	// MinItems is the min length of an array variable.
   473  	// NOTE: Can only be set if type is array.
   474  	// +optional
   475  	MinItems *int64 `json:"minItems,omitempty"`
   476  
   477  	// UniqueItems specifies if items in an array must be unique.
   478  	// NOTE: Can only be set if type is array.
   479  	// +optional
   480  	UniqueItems bool `json:"uniqueItems,omitempty"`
   481  
   482  	// Format is an OpenAPI v3 format string. Unknown formats are ignored.
   483  	// For a list of supported formats please see: (of the k8s.io/apiextensions-apiserver version we're currently using)
   484  	// https://github.com/kubernetes/apiextensions-apiserver/blob/master/pkg/apiserver/validation/formats.go
   485  	// NOTE: Can only be set if type is string.
   486  	// +optional
   487  	Format string `json:"format,omitempty"`
   488  
   489  	// MaxLength is the max length of a string variable.
   490  	// NOTE: Can only be set if type is string.
   491  	// +optional
   492  	MaxLength *int64 `json:"maxLength,omitempty"`
   493  
   494  	// MinLength is the min length of a string variable.
   495  	// NOTE: Can only be set if type is string.
   496  	// +optional
   497  	MinLength *int64 `json:"minLength,omitempty"`
   498  
   499  	// Pattern is the regex which a string variable must match.
   500  	// NOTE: Can only be set if type is string.
   501  	// +optional
   502  	Pattern string `json:"pattern,omitempty"`
   503  
   504  	// Maximum is the maximum of an integer or number variable.
   505  	// If ExclusiveMaximum is false, the variable is valid if it is lower than, or equal to, the value of Maximum.
   506  	// If ExclusiveMaximum is true, the variable is valid if it is strictly lower than the value of Maximum.
   507  	// NOTE: Can only be set if type is integer or number.
   508  	// +optional
   509  	Maximum *int64 `json:"maximum,omitempty"`
   510  
   511  	// ExclusiveMaximum specifies if the Maximum is exclusive.
   512  	// NOTE: Can only be set if type is integer or number.
   513  	// +optional
   514  	ExclusiveMaximum bool `json:"exclusiveMaximum,omitempty"`
   515  
   516  	// Minimum is the minimum of an integer or number variable.
   517  	// If ExclusiveMinimum is false, the variable is valid if it is greater than, or equal to, the value of Minimum.
   518  	// If ExclusiveMinimum is true, the variable is valid if it is strictly greater than the value of Minimum.
   519  	// NOTE: Can only be set if type is integer or number.
   520  	// +optional
   521  	Minimum *int64 `json:"minimum,omitempty"`
   522  
   523  	// ExclusiveMinimum specifies if the Minimum is exclusive.
   524  	// NOTE: Can only be set if type is integer or number.
   525  	// +optional
   526  	ExclusiveMinimum bool `json:"exclusiveMinimum,omitempty"`
   527  
   528  	// XPreserveUnknownFields allows setting fields in a variable object
   529  	// which are not defined in the variable schema. This affects fields recursively,
   530  	// except if nested properties or additionalProperties are specified in the schema.
   531  	// +optional
   532  	XPreserveUnknownFields bool `json:"x-kubernetes-preserve-unknown-fields,omitempty"`
   533  
   534  	// Enum is the list of valid values of the variable.
   535  	// NOTE: Can be set for all types.
   536  	// +optional
   537  	Enum []apiextensionsv1.JSON `json:"enum,omitempty"`
   538  
   539  	// Default is the default value of the variable.
   540  	// NOTE: Can be set for all types.
   541  	// +optional
   542  	Default *apiextensionsv1.JSON `json:"default,omitempty"`
   543  }
   544  
   545  // ClusterClassPatch defines a patch which is applied to customize the referenced templates.
   546  type ClusterClassPatch struct {
   547  	// Name of the patch.
   548  	Name string `json:"name"`
   549  
   550  	// Description is a human-readable description of this patch.
   551  	Description string `json:"description,omitempty"`
   552  
   553  	// EnabledIf is a Go template to be used to calculate if a patch should be enabled.
   554  	// It can reference variables defined in .spec.variables and builtin variables.
   555  	// The patch will be enabled if the template evaluates to `true`, otherwise it will
   556  	// be disabled.
   557  	// If EnabledIf is not set, the patch will be enabled per default.
   558  	// +optional
   559  	EnabledIf *string `json:"enabledIf,omitempty"`
   560  
   561  	// Definitions define inline patches.
   562  	// Note: Patches will be applied in the order of the array.
   563  	// Note: Exactly one of Definitions or External must be set.
   564  	// +optional
   565  	Definitions []PatchDefinition `json:"definitions,omitempty"`
   566  
   567  	// External defines an external patch.
   568  	// Note: Exactly one of Definitions or External must be set.
   569  	// +optional
   570  	External *ExternalPatchDefinition `json:"external,omitempty"`
   571  }
   572  
   573  // PatchDefinition defines a patch which is applied to customize the referenced templates.
   574  type PatchDefinition struct {
   575  	// Selector defines on which templates the patch should be applied.
   576  	Selector PatchSelector `json:"selector"`
   577  
   578  	// JSONPatches defines the patches which should be applied on the templates
   579  	// matching the selector.
   580  	// Note: Patches will be applied in the order of the array.
   581  	JSONPatches []JSONPatch `json:"jsonPatches"`
   582  }
   583  
   584  // PatchSelector defines on which templates the patch should be applied.
   585  // Note: Matching on APIVersion and Kind is mandatory, to enforce that the patches are
   586  // written for the correct version. The version of the references in the ClusterClass may
   587  // be automatically updated during reconciliation if there is a newer version for the same contract.
   588  // Note: The results of selection based on the individual fields are ANDed.
   589  type PatchSelector struct {
   590  	// APIVersion filters templates by apiVersion.
   591  	APIVersion string `json:"apiVersion"`
   592  
   593  	// Kind filters templates by kind.
   594  	Kind string `json:"kind"`
   595  
   596  	// MatchResources selects templates based on where they are referenced.
   597  	MatchResources PatchSelectorMatch `json:"matchResources"`
   598  }
   599  
   600  // PatchSelectorMatch selects templates based on where they are referenced.
   601  // Note: The selector must match at least one template.
   602  // Note: The results of selection based on the individual fields are ORed.
   603  type PatchSelectorMatch struct {
   604  	// ControlPlane selects templates referenced in .spec.ControlPlane.
   605  	// Note: this will match the controlPlane and also the controlPlane
   606  	// machineInfrastructure (depending on the kind and apiVersion).
   607  	// +optional
   608  	ControlPlane bool `json:"controlPlane,omitempty"`
   609  
   610  	// InfrastructureCluster selects templates referenced in .spec.infrastructure.
   611  	// +optional
   612  	InfrastructureCluster bool `json:"infrastructureCluster,omitempty"`
   613  
   614  	// MachineDeploymentClass selects templates referenced in specific MachineDeploymentClasses in
   615  	// .spec.workers.machineDeployments.
   616  	// +optional
   617  	MachineDeploymentClass *PatchSelectorMatchMachineDeploymentClass `json:"machineDeploymentClass,omitempty"`
   618  
   619  	// MachinePoolClass selects templates referenced in specific MachinePoolClasses in
   620  	// .spec.workers.machinePools.
   621  	// +optional
   622  	MachinePoolClass *PatchSelectorMatchMachinePoolClass `json:"machinePoolClass,omitempty"`
   623  }
   624  
   625  // PatchSelectorMatchMachineDeploymentClass selects templates referenced
   626  // in specific MachineDeploymentClasses in .spec.workers.machineDeployments.
   627  type PatchSelectorMatchMachineDeploymentClass struct {
   628  	// Names selects templates by class names.
   629  	// +optional
   630  	Names []string `json:"names,omitempty"`
   631  }
   632  
   633  // PatchSelectorMatchMachinePoolClass selects templates referenced
   634  // in specific MachinePoolClasses in .spec.workers.machinePools.
   635  type PatchSelectorMatchMachinePoolClass struct {
   636  	// Names selects templates by class names.
   637  	// +optional
   638  	Names []string `json:"names,omitempty"`
   639  }
   640  
   641  // JSONPatch defines a JSON patch.
   642  type JSONPatch struct {
   643  	// Op defines the operation of the patch.
   644  	// Note: Only `add`, `replace` and `remove` are supported.
   645  	Op string `json:"op"`
   646  
   647  	// Path defines the path of the patch.
   648  	// Note: Only the spec of a template can be patched, thus the path has to start with /spec/.
   649  	// Note: For now the only allowed array modifications are `append` and `prepend`, i.e.:
   650  	// * for op: `add`: only index 0 (prepend) and - (append) are allowed
   651  	// * for op: `replace` or `remove`: no indexes are allowed
   652  	Path string `json:"path"`
   653  
   654  	// Value defines the value of the patch.
   655  	// Note: Either Value or ValueFrom is required for add and replace
   656  	// operations. Only one of them is allowed to be set at the same time.
   657  	// Note: We have to use apiextensionsv1.JSON instead of our JSON type,
   658  	// because controller-tools has a hard-coded schema for apiextensionsv1.JSON
   659  	// which cannot be produced by another type (unset type field).
   660  	// Ref: https://github.com/kubernetes-sigs/controller-tools/blob/d0e03a142d0ecdd5491593e941ee1d6b5d91dba6/pkg/crd/known_types.go#L106-L111
   661  	// +optional
   662  	Value *apiextensionsv1.JSON `json:"value,omitempty"`
   663  
   664  	// ValueFrom defines the value of the patch.
   665  	// Note: Either Value or ValueFrom is required for add and replace
   666  	// operations. Only one of them is allowed to be set at the same time.
   667  	// +optional
   668  	ValueFrom *JSONPatchValue `json:"valueFrom,omitempty"`
   669  }
   670  
   671  // JSONPatchValue defines the value of a patch.
   672  // Note: Only one of the fields is allowed to be set at the same time.
   673  type JSONPatchValue struct {
   674  	// Variable is the variable to be used as value.
   675  	// Variable can be one of the variables defined in .spec.variables or a builtin variable.
   676  	// +optional
   677  	Variable *string `json:"variable,omitempty"`
   678  
   679  	// Template is the Go template to be used to calculate the value.
   680  	// A template can reference variables defined in .spec.variables and builtin variables.
   681  	// Note: The template must evaluate to a valid YAML or JSON value.
   682  	// +optional
   683  	Template *string `json:"template,omitempty"`
   684  }
   685  
   686  // ExternalPatchDefinition defines an external patch.
   687  // Note: At least one of GenerateExtension or ValidateExtension must be set.
   688  type ExternalPatchDefinition struct {
   689  	// GenerateExtension references an extension which is called to generate patches.
   690  	// +optional
   691  	GenerateExtension *string `json:"generateExtension,omitempty"`
   692  
   693  	// ValidateExtension references an extension which is called to validate the topology.
   694  	// +optional
   695  	ValidateExtension *string `json:"validateExtension,omitempty"`
   696  
   697  	// DiscoverVariablesExtension references an extension which is called to discover variables.
   698  	// +optional
   699  	DiscoverVariablesExtension *string `json:"discoverVariablesExtension,omitempty"`
   700  
   701  	// Settings defines key value pairs to be passed to the extensions.
   702  	// Values defined here take precedence over the values defined in the
   703  	// corresponding ExtensionConfig.
   704  	// +optional
   705  	Settings map[string]string `json:"settings,omitempty"`
   706  }
   707  
   708  // LocalObjectTemplate defines a template for a topology Class.
   709  type LocalObjectTemplate struct {
   710  	// Ref is a required reference to a custom resource
   711  	// offered by a provider.
   712  	Ref *corev1.ObjectReference `json:"ref"`
   713  }
   714  
   715  // ANCHOR: ClusterClassStatus
   716  
   717  // ClusterClassStatus defines the observed state of the ClusterClass.
   718  type ClusterClassStatus struct {
   719  	// Variables is a list of ClusterClassStatusVariable that are defined for the ClusterClass.
   720  	// +optional
   721  	Variables []ClusterClassStatusVariable `json:"variables,omitempty"`
   722  
   723  	// Conditions defines current observed state of the ClusterClass.
   724  	// +optional
   725  	Conditions Conditions `json:"conditions,omitempty"`
   726  
   727  	// ObservedGeneration is the latest generation observed by the controller.
   728  	// +optional
   729  	ObservedGeneration int64 `json:"observedGeneration,omitempty"`
   730  }
   731  
   732  // ClusterClassStatusVariable defines a variable which appears in the status of a ClusterClass.
   733  type ClusterClassStatusVariable struct {
   734  	// Name is the name of the variable.
   735  	Name string `json:"name"`
   736  
   737  	// DefinitionsConflict specifies whether or not there are conflicting definitions for a single variable name.
   738  	// +optional
   739  	DefinitionsConflict bool `json:"definitionsConflict"`
   740  
   741  	// Definitions is a list of definitions for a variable.
   742  	Definitions []ClusterClassStatusVariableDefinition `json:"definitions"`
   743  }
   744  
   745  // ClusterClassStatusVariableDefinition defines a variable which appears in the status of a ClusterClass.
   746  type ClusterClassStatusVariableDefinition struct {
   747  	// From specifies the origin of the variable definition.
   748  	// This will be `inline` for variables defined in the ClusterClass or the name of a patch defined in the ClusterClass
   749  	// for variables discovered from a DiscoverVariables runtime extensions.
   750  	From string `json:"from"`
   751  
   752  	// Required specifies if the variable is required.
   753  	// Note: this applies to the variable as a whole and thus the
   754  	// top-level object defined in the schema. If nested fields are
   755  	// required, this will be specified inside the schema.
   756  	Required bool `json:"required"`
   757  
   758  	// Metadata is the metadata of a variable.
   759  	// It can be used to add additional data for higher level tools to
   760  	// a ClusterClassVariable.
   761  	// +optional
   762  	Metadata ClusterClassVariableMetadata `json:"metadata,omitempty"`
   763  
   764  	// Schema defines the schema of the variable.
   765  	Schema VariableSchema `json:"schema"`
   766  }
   767  
   768  // GetConditions returns the set of conditions for this object.
   769  func (c *ClusterClass) GetConditions() Conditions {
   770  	return c.Status.Conditions
   771  }
   772  
   773  // SetConditions sets the conditions on this object.
   774  func (c *ClusterClass) SetConditions(conditions Conditions) {
   775  	c.Status.Conditions = conditions
   776  }
   777  
   778  // ANCHOR_END: ClusterClassStatus
   779  
   780  // +kubebuilder:object:root=true
   781  
   782  // ClusterClassList contains a list of Cluster.
   783  type ClusterClassList struct {
   784  	metav1.TypeMeta `json:",inline"`
   785  	metav1.ListMeta `json:"metadata,omitempty"`
   786  	Items           []ClusterClass `json:"items"`
   787  }
   788  
   789  func init() {
   790  	objectTypes = append(objectTypes, &ClusterClass{}, &ClusterClassList{})
   791  }