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 }