sigs.k8s.io/cluster-api@v1.6.3/api/v1alpha4/cluster_types.go (about)

     1  /*
     2  Copyright 2020 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 v1alpha4
    18  
    19  import (
    20  	"fmt"
    21  	"net"
    22  	"strings"
    23  
    24  	"github.com/pkg/errors"
    25  	corev1 "k8s.io/api/core/v1"
    26  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    27  	"k8s.io/utils/pointer"
    28  
    29  	capierrors "sigs.k8s.io/cluster-api/errors"
    30  )
    31  
    32  const (
    33  	// ClusterFinalizer is the finalizer used by the cluster controller to
    34  	// cleanup the cluster resources when a Cluster is being deleted.
    35  	ClusterFinalizer = "cluster.cluster.x-k8s.io"
    36  )
    37  
    38  // ANCHOR: ClusterSpec
    39  
    40  // ClusterSpec defines the desired state of Cluster.
    41  type ClusterSpec struct {
    42  	// Paused can be used to prevent controllers from processing the Cluster and all its associated objects.
    43  	// +optional
    44  	Paused bool `json:"paused,omitempty"`
    45  
    46  	// Cluster network configuration.
    47  	// +optional
    48  	ClusterNetwork *ClusterNetwork `json:"clusterNetwork,omitempty"`
    49  
    50  	// ControlPlaneEndpoint represents the endpoint used to communicate with the control plane.
    51  	// +optional
    52  	ControlPlaneEndpoint APIEndpoint `json:"controlPlaneEndpoint"`
    53  
    54  	// ControlPlaneRef is an optional reference to a provider-specific resource that holds
    55  	// the details for provisioning the Control Plane for a Cluster.
    56  	// +optional
    57  	ControlPlaneRef *corev1.ObjectReference `json:"controlPlaneRef,omitempty"`
    58  
    59  	// InfrastructureRef is a reference to a provider-specific resource that holds the details
    60  	// for provisioning infrastructure for a cluster in said provider.
    61  	// +optional
    62  	InfrastructureRef *corev1.ObjectReference `json:"infrastructureRef,omitempty"`
    63  
    64  	// This encapsulates the topology for the cluster.
    65  	// NOTE: It is required to enable the ClusterTopology
    66  	// feature gate flag to activate managed topologies support;
    67  	// this feature is highly experimental, and parts of it might still be not implemented.
    68  	// +optional
    69  	Topology *Topology `json:"topology,omitempty"`
    70  }
    71  
    72  // Topology encapsulates the information of the managed resources.
    73  type Topology struct {
    74  	// The name of the ClusterClass object to create the topology.
    75  	Class string `json:"class"`
    76  
    77  	// The Kubernetes version of the cluster.
    78  	Version string `json:"version"`
    79  
    80  	// RolloutAfter performs a rollout of the entire cluster one component at a time,
    81  	// control plane first and then machine deployments.
    82  	// +optional
    83  	RolloutAfter *metav1.Time `json:"rolloutAfter,omitempty"`
    84  
    85  	// ControlPlane describes the cluster control plane.
    86  	// +optional
    87  	ControlPlane ControlPlaneTopology `json:"controlPlane"`
    88  
    89  	// Workers encapsulates the different constructs that form the worker nodes
    90  	// for the cluster.
    91  	// +optional
    92  	Workers *WorkersTopology `json:"workers,omitempty"`
    93  }
    94  
    95  // ControlPlaneTopology specifies the parameters for the control plane nodes in the cluster.
    96  type ControlPlaneTopology struct {
    97  	// Metadata is the metadata applied to the machines of the ControlPlane.
    98  	// At runtime this metadata is merged with the corresponding metadata from the ClusterClass.
    99  	//
   100  	// This field is supported if and only if the control plane provider template
   101  	// referenced in the ClusterClass is Machine based.
   102  	Metadata ObjectMeta `json:"metadata,omitempty"`
   103  
   104  	// Replicas is the number of control plane nodes.
   105  	// If the value is nil, the ControlPlane object is created without the number of Replicas
   106  	// and it's assumed that the control plane controller does not implement support for this field.
   107  	// When specified against a control plane provider that lacks support for this field, this value will be ignored.
   108  	// +optional
   109  	Replicas *int32 `json:"replicas,omitempty"`
   110  }
   111  
   112  // WorkersTopology represents the different sets of worker nodes in the cluster.
   113  type WorkersTopology struct {
   114  	// MachineDeployments is a list of machine deployments in the cluster.
   115  	MachineDeployments []MachineDeploymentTopology `json:"machineDeployments,omitempty"`
   116  }
   117  
   118  // MachineDeploymentTopology specifies the different parameters for a set of worker nodes in the topology.
   119  // This set of nodes is managed by a MachineDeployment object whose lifecycle is managed by the Cluster controller.
   120  type MachineDeploymentTopology struct {
   121  	// Metadata is the metadata applied to the machines of the MachineDeployment.
   122  	// At runtime this metadata is merged with the corresponding metadata from the ClusterClass.
   123  	Metadata ObjectMeta `json:"metadata,omitempty"`
   124  
   125  	// Class is the name of the MachineDeploymentClass used to create the set of worker nodes.
   126  	// This should match one of the deployment classes defined in the ClusterClass object
   127  	// mentioned in the `Cluster.Spec.Class` field.
   128  	Class string `json:"class"`
   129  
   130  	// Name is the unique identifier for this MachineDeploymentTopology.
   131  	// The value is used with other unique identifiers to create a MachineDeployment's Name
   132  	// (e.g. cluster's name, etc). In case the name is greater than the allowed maximum length,
   133  	// the values are hashed together.
   134  	Name string `json:"name"`
   135  
   136  	// Replicas is the number of worker nodes belonging to this set.
   137  	// If the value is nil, the MachineDeployment is created without the number of Replicas (defaulting to zero)
   138  	// and it's assumed that an external entity (like cluster autoscaler) is responsible for the management
   139  	// of this value.
   140  	// +optional
   141  	Replicas *int32 `json:"replicas,omitempty"`
   142  }
   143  
   144  // ANCHOR_END: ClusterSpec
   145  
   146  // ANCHOR: ClusterNetwork
   147  
   148  // ClusterNetwork specifies the different networking
   149  // parameters for a cluster.
   150  type ClusterNetwork struct {
   151  	// APIServerPort specifies the port the API Server should bind to.
   152  	// Defaults to 6443.
   153  	// +optional
   154  	APIServerPort *int32 `json:"apiServerPort,omitempty"`
   155  
   156  	// The network ranges from which service VIPs are allocated.
   157  	// +optional
   158  	Services *NetworkRanges `json:"services,omitempty"`
   159  
   160  	// The network ranges from which Pod networks are allocated.
   161  	// +optional
   162  	Pods *NetworkRanges `json:"pods,omitempty"`
   163  
   164  	// Domain name for services.
   165  	// +optional
   166  	ServiceDomain string `json:"serviceDomain,omitempty"`
   167  }
   168  
   169  // ANCHOR_END: ClusterNetwork
   170  
   171  // ANCHOR: NetworkRanges
   172  
   173  // NetworkRanges represents ranges of network addresses.
   174  type NetworkRanges struct {
   175  	CIDRBlocks []string `json:"cidrBlocks"`
   176  }
   177  
   178  func (n *NetworkRanges) String() string {
   179  	if n == nil {
   180  		return ""
   181  	}
   182  	return strings.Join(n.CIDRBlocks, ",")
   183  }
   184  
   185  // ANCHOR_END: NetworkRanges
   186  
   187  // ANCHOR: ClusterStatus
   188  
   189  // ClusterStatus defines the observed state of Cluster.
   190  type ClusterStatus struct {
   191  	// FailureDomains is a slice of failure domain objects synced from the infrastructure provider.
   192  	FailureDomains FailureDomains `json:"failureDomains,omitempty"`
   193  
   194  	// FailureReason indicates that there is a fatal problem reconciling the
   195  	// state, and will be set to a token value suitable for
   196  	// programmatic interpretation.
   197  	// +optional
   198  	FailureReason *capierrors.ClusterStatusError `json:"failureReason,omitempty"`
   199  
   200  	// FailureMessage indicates that there is a fatal problem reconciling the
   201  	// state, and will be set to a descriptive error message.
   202  	// +optional
   203  	FailureMessage *string `json:"failureMessage,omitempty"`
   204  
   205  	// Phase represents the current phase of cluster actuation.
   206  	// E.g. Pending, Running, Terminating, Failed etc.
   207  	// +optional
   208  	Phase string `json:"phase,omitempty"`
   209  
   210  	// InfrastructureReady is the state of the infrastructure provider.
   211  	// +optional
   212  	InfrastructureReady bool `json:"infrastructureReady"`
   213  
   214  	// ControlPlaneReady defines if the control plane is ready.
   215  	// +optional
   216  	ControlPlaneReady bool `json:"controlPlaneReady,omitempty"`
   217  
   218  	// Conditions defines current service state of the cluster.
   219  	// +optional
   220  	Conditions Conditions `json:"conditions,omitempty"`
   221  
   222  	// ObservedGeneration is the latest generation observed by the controller.
   223  	// +optional
   224  	ObservedGeneration int64 `json:"observedGeneration,omitempty"`
   225  }
   226  
   227  // ANCHOR_END: ClusterStatus
   228  
   229  // SetTypedPhase sets the Phase field to the string representation of ClusterPhase.
   230  func (c *ClusterStatus) SetTypedPhase(p ClusterPhase) {
   231  	c.Phase = string(p)
   232  }
   233  
   234  // GetTypedPhase attempts to parse the Phase field and return
   235  // the typed ClusterPhase representation as described in `machine_phase_types.go`.
   236  func (c *ClusterStatus) GetTypedPhase() ClusterPhase {
   237  	switch phase := ClusterPhase(c.Phase); phase {
   238  	case
   239  		ClusterPhasePending,
   240  		ClusterPhaseProvisioning,
   241  		ClusterPhaseProvisioned,
   242  		ClusterPhaseDeleting,
   243  		ClusterPhaseFailed:
   244  		return phase
   245  	default:
   246  		return ClusterPhaseUnknown
   247  	}
   248  }
   249  
   250  // ANCHOR: APIEndpoint
   251  
   252  // APIEndpoint represents a reachable Kubernetes API endpoint.
   253  type APIEndpoint struct {
   254  	// The hostname on which the API server is serving.
   255  	Host string `json:"host"`
   256  
   257  	// The port on which the API server is serving.
   258  	Port int32 `json:"port"`
   259  }
   260  
   261  // IsZero returns true if both host and port are zero values.
   262  func (v APIEndpoint) IsZero() bool {
   263  	return v.Host == "" && v.Port == 0
   264  }
   265  
   266  // IsValid returns true if both host and port are non-zero values.
   267  func (v APIEndpoint) IsValid() bool {
   268  	return v.Host != "" && v.Port != 0
   269  }
   270  
   271  // String returns a formatted version HOST:PORT of this APIEndpoint.
   272  func (v APIEndpoint) String() string {
   273  	return net.JoinHostPort(v.Host, fmt.Sprintf("%d", v.Port))
   274  }
   275  
   276  // ANCHOR_END: APIEndpoint
   277  
   278  // +kubebuilder:object:root=true
   279  // +kubebuilder:unservedversion
   280  // +kubebuilder:deprecatedversion
   281  // +kubebuilder:resource:path=clusters,shortName=cl,scope=Namespaced,categories=cluster-api
   282  // +kubebuilder:subresource:status
   283  // +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="Time duration since creation of Cluster"
   284  // +kubebuilder:printcolumn:name="Phase",type="string",JSONPath=".status.phase",description="Cluster status such as Pending/Provisioning/Provisioned/Deleting/Failed"
   285  
   286  // Cluster is the Schema for the clusters API.
   287  //
   288  // Deprecated: This type will be removed in one of the next releases.
   289  type Cluster struct {
   290  	metav1.TypeMeta   `json:",inline"`
   291  	metav1.ObjectMeta `json:"metadata,omitempty"`
   292  
   293  	Spec   ClusterSpec   `json:"spec,omitempty"`
   294  	Status ClusterStatus `json:"status,omitempty"`
   295  }
   296  
   297  // GetConditions returns the set of conditions for this object.
   298  func (c *Cluster) GetConditions() Conditions {
   299  	return c.Status.Conditions
   300  }
   301  
   302  // SetConditions sets the conditions on this object.
   303  func (c *Cluster) SetConditions(conditions Conditions) {
   304  	c.Status.Conditions = conditions
   305  }
   306  
   307  // GetIPFamily returns a ClusterIPFamily from the configuration provided.
   308  func (c *Cluster) GetIPFamily() (ClusterIPFamily, error) {
   309  	var podCIDRs, serviceCIDRs []string
   310  	if c.Spec.ClusterNetwork != nil {
   311  		if c.Spec.ClusterNetwork.Pods != nil {
   312  			podCIDRs = c.Spec.ClusterNetwork.Pods.CIDRBlocks
   313  		}
   314  		if c.Spec.ClusterNetwork.Services != nil {
   315  			serviceCIDRs = c.Spec.ClusterNetwork.Services.CIDRBlocks
   316  		}
   317  	}
   318  	if len(podCIDRs) == 0 && len(serviceCIDRs) == 0 {
   319  		return IPv4IPFamily, nil
   320  	}
   321  
   322  	podsIPFamily, err := ipFamilyForCIDRStrings(podCIDRs)
   323  	if err != nil {
   324  		return InvalidIPFamily, fmt.Errorf("pods: %s", err)
   325  	}
   326  	if len(serviceCIDRs) == 0 {
   327  		return podsIPFamily, nil
   328  	}
   329  
   330  	servicesIPFamily, err := ipFamilyForCIDRStrings(serviceCIDRs)
   331  	if err != nil {
   332  		return InvalidIPFamily, fmt.Errorf("services: %s", err)
   333  	}
   334  	if len(podCIDRs) == 0 {
   335  		return servicesIPFamily, nil
   336  	}
   337  
   338  	if podsIPFamily == DualStackIPFamily {
   339  		return DualStackIPFamily, nil
   340  	} else if podsIPFamily != servicesIPFamily {
   341  		return InvalidIPFamily, errors.New("pods and services IP family mismatch")
   342  	}
   343  
   344  	return podsIPFamily, nil
   345  }
   346  
   347  func ipFamilyForCIDRStrings(cidrs []string) (ClusterIPFamily, error) {
   348  	if len(cidrs) > 2 {
   349  		return InvalidIPFamily, errors.New("too many CIDRs specified")
   350  	}
   351  	var foundIPv4 bool
   352  	var foundIPv6 bool
   353  	for _, cidr := range cidrs {
   354  		ip, _, err := net.ParseCIDR(cidr)
   355  		if err != nil {
   356  			return InvalidIPFamily, fmt.Errorf("could not parse CIDR: %s", err)
   357  		}
   358  		if ip.To4() != nil {
   359  			foundIPv4 = true
   360  		} else {
   361  			foundIPv6 = true
   362  		}
   363  	}
   364  	switch {
   365  	case foundIPv4 && foundIPv6:
   366  		return DualStackIPFamily, nil
   367  	case foundIPv4:
   368  		return IPv4IPFamily, nil
   369  	case foundIPv6:
   370  		return IPv6IPFamily, nil
   371  	default:
   372  		return InvalidIPFamily, nil
   373  	}
   374  }
   375  
   376  // ClusterIPFamily defines the types of supported IP families.
   377  type ClusterIPFamily int
   378  
   379  // Define the ClusterIPFamily constants.
   380  const (
   381  	InvalidIPFamily ClusterIPFamily = iota
   382  	IPv4IPFamily
   383  	IPv6IPFamily
   384  	DualStackIPFamily
   385  )
   386  
   387  func (f ClusterIPFamily) String() string {
   388  	return [...]string{"InvalidIPFamily", "IPv4IPFamily", "IPv6IPFamily", "DualStackIPFamily"}[f]
   389  }
   390  
   391  // +kubebuilder:object:root=true
   392  
   393  // ClusterList contains a list of Cluster.
   394  //
   395  // Deprecated: This type will be removed in one of the next releases.
   396  type ClusterList struct {
   397  	metav1.TypeMeta `json:",inline"`
   398  	metav1.ListMeta `json:"metadata,omitempty"`
   399  	Items           []Cluster `json:"items"`
   400  }
   401  
   402  func init() {
   403  	objectTypes = append(objectTypes, &Cluster{}, &ClusterList{})
   404  }
   405  
   406  // FailureDomains is a slice of FailureDomains.
   407  type FailureDomains map[string]FailureDomainSpec
   408  
   409  // FilterControlPlane returns a FailureDomain slice containing only the domains suitable to be used
   410  // for control plane nodes.
   411  func (in FailureDomains) FilterControlPlane() FailureDomains {
   412  	res := make(FailureDomains)
   413  	for id, spec := range in {
   414  		if spec.ControlPlane {
   415  			res[id] = spec
   416  		}
   417  	}
   418  	return res
   419  }
   420  
   421  // GetIDs returns a slice containing the ids for failure domains.
   422  func (in FailureDomains) GetIDs() []*string {
   423  	ids := make([]*string, 0, len(in))
   424  	for id := range in {
   425  		ids = append(ids, pointer.String(id))
   426  	}
   427  	return ids
   428  }
   429  
   430  // FailureDomainSpec is the Schema for Cluster API failure domains.
   431  // It allows controllers to understand how many failure domains a cluster can optionally span across.
   432  type FailureDomainSpec struct {
   433  	// ControlPlane determines if this failure domain is suitable for use by control plane machines.
   434  	// +optional
   435  	ControlPlane bool `json:"controlPlane"`
   436  
   437  	// Attributes is a free form map of attributes an infrastructure provider might use or require.
   438  	// +optional
   439  	Attributes map[string]string `json:"attributes,omitempty"`
   440  }