k8c.io/api/v3@v3.0.0-20230904060738-b0a93889c0b6/pkg/apis/kubermatic/v1/ee.external_cluster.go (about) 1 /* 2 Copyright 2023 The Kubermatic Kubernetes Platform contributors. 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 v1 18 19 import ( 20 "fmt" 21 22 "k8c.io/api/v3/pkg/semver" 23 24 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 25 ) 26 27 // +genclient 28 // +kubebuilder:resource:scope=Cluster 29 // +kubebuilder:resource:categories=kkpee 30 // +kubebuilder:object:generate=true 31 // +kubebuilder:object:root=true 32 // +kubebuilder:subresource:status 33 // +kubebuilder:printcolumn:JSONPath=".spec.humanReadableName",name="HumanReadableName",type="string" 34 // +kubebuilder:printcolumn:JSONPath=".spec.cloudSpec.providerName",name="Provider",type="string" 35 // +kubebuilder:printcolumn:JSONPath=".spec.pause",name="Paused",type="boolean" 36 // +kubebuilder:printcolumn:JSONPath=".status.condition.phase",name="Phase",type="string" 37 // +kubebuilder:printcolumn:JSONPath=".metadata.creationTimestamp",name="Age",type="date" 38 39 // ExternalCluster is the object representing an external Kubernetes cluster. 40 // 41 // Note that this resource is part of a KKP Enterprise feature and is not used in the Community Edition. 42 type ExternalCluster struct { 43 metav1.TypeMeta `json:",inline"` 44 metav1.ObjectMeta `json:"metadata,omitempty"` 45 46 // Spec describes the desired cluster state. 47 Spec ExternalClusterSpec `json:"spec"` 48 49 // Status contains reconciliation information for the cluster. 50 Status ExternalClusterStatus `json:"status,omitempty"` 51 } 52 53 // ExternalClusterStatus denotes status information about an ExternalCluster. 54 type ExternalClusterStatus struct { 55 // Conditions contains conditions an externalcluster is in, its primary use case is status signaling for controller 56 Condition ExternalClusterCondition `json:"condition,omitempty"` 57 } 58 59 type ExternalClusterCondition struct { 60 Phase ExternalClusterPhase `json:"phase"` 61 // Human readable message indicating details about last transition. 62 Message string `json:"message,omitempty"` 63 } 64 65 type ExternalClusterKubeOneCloudSpec struct { 66 // ProviderName is the name of the cloud provider used, one of 67 // "aws", "azure", "digitalocean", "gcp", 68 // "hetzner", "nutanix", "openstack", "packet", "vsphere" KubeOne natively-supported providers 69 ProviderName string `json:"providerName"` 70 71 // Region is the cloud provider region in which the cluster resides. 72 // This field is used only to display information. 73 Region string `json:"region,omitempty"` 74 75 CredentialsReference *GlobalSecretKeySelector `json:"credentialsReference,omitempty"` 76 SSHReference *GlobalSecretKeySelector `json:"sshReference,omitempty"` 77 ManifestReference *GlobalSecretKeySelector `json:"manifestReference,omitempty"` 78 } 79 80 // +kubebuilder:object:generate=true 81 // +kubebuilder:object:root=true 82 83 // ExternalClusterList specifies a list of external kubernetes clusters. 84 type ExternalClusterList struct { 85 metav1.TypeMeta `json:",inline"` 86 metav1.ListMeta `json:"metadata,omitempty"` 87 88 Items []ExternalCluster `json:"items"` 89 } 90 91 // ExternalClusterSpec specifies the data for a new external kubernetes cluster. 92 type ExternalClusterSpec struct { 93 // HumanReadableName is the cluster name provided by the user 94 HumanReadableName string `json:"humanReadableName"` 95 96 // KubeconfigReference is reference to cluster Kubeconfig 97 KubeconfigReference *GlobalSecretKeySelector `json:"kubeconfigReference,omitempty"` 98 99 // Version defines the desired version of the control plane. 100 Version semver.Semver `json:"version"` 101 102 // CloudSpec contains provider specific fields 103 CloudSpec ExternalClusterCloudSpec `json:"cloudSpec"` 104 105 ClusterNetwork *ExternalClusterNetworkingConfig `json:"clusterNetwork,omitempty"` 106 107 // ContainerRuntime to use, i.e. `docker` or `containerd`. 108 ContainerRuntime string `json:"containerRuntime,omitempty"` 109 110 // If this is set to true, the cluster will not be reconciled by KKP. 111 // This indicates that the user needs to do some action to resolve the pause. 112 Pause bool `json:"pause"` 113 114 // PauseReason is the reason why the cluster is not being managed. This field is for informational 115 // purpose only and can be set by a user or a controller to communicate the reason for pausing the cluster. 116 PauseReason string `json:"pauseReason,omitempty"` 117 } 118 119 // ExternalClusterNetworkingConfig specifies the different networking 120 // parameters for a external cluster. 121 type ExternalClusterNetworkingConfig struct { 122 // The network ranges from which service VIPs are allocated. 123 // It can contain one IPv4 and/or one IPv6 CIDR. 124 // If both address families are specified, the first one defines the primary address family. 125 Services *ExternalClusterNetworkRanges `json:"services,omitempty"` 126 127 // The network ranges from which POD networks are allocated. 128 // It can contain one IPv4 and/or one IPv6 CIDR. 129 // If both address families are specified, the first one defines the primary address family. 130 Pods *ExternalClusterNetworkRanges `json:"pods,omitempty"` 131 } 132 133 // ExternalClusterNetworkRanges represents ranges of network addresses. 134 type ExternalClusterNetworkRanges struct { 135 CIDRBlocks []string `json:"cidrBlocks,omitempty"` 136 } 137 138 // ExternalClusterCloudSpec mutually stores access data to a cloud provider. 139 type ExternalClusterCloudSpec struct { 140 ProviderName ExternalClusterProvider `json:"providerName"` 141 GKE *ExternalClusterGKECloudSpec `json:"gke,omitempty"` 142 EKS *ExternalClusterEKSCloudSpec `json:"eks,omitempty"` 143 AKS *ExternalClusterAKSCloudSpec `json:"aks,omitempty"` 144 KubeOne *ExternalClusterKubeOneCloudSpec `json:"kubeone,omitempty"` 145 BringYourOwn *ExternalClusterBringYourOwnCloudSpec `json:"bringyourown,omitempty"` 146 } 147 148 type ExternalClusterPhase string 149 150 const ( 151 // ExternalClusterPhaseProvisioning status indicates the cluster is being imported. 152 ExternalClusterPhaseProvisioning ExternalClusterPhase = "Provisioning" 153 154 // ExternalClusterPhaseRunning status indicates the cluster is fully usable. 155 ExternalClusterPhaseRunning ExternalClusterPhase = "Running" 156 157 ExternalClusterPhaseStarting ExternalClusterPhase = "Starting" 158 159 ExternalClusterPhaseStopping ExternalClusterPhase = "Stopping" 160 161 ExternalClusterPhaseStopped ExternalClusterPhase = "Stopped" 162 163 ExternalClusterPhaseWarning ExternalClusterPhase = "Warning" 164 165 // ExternalClusterPhaseReconciling status indicates that some work is actively being done on the cluster, such as upgrading the master or 166 // node software. Details can be found in the `StatusMessage` field. 167 ExternalClusterPhaseReconciling ExternalClusterPhase = "Reconciling" 168 169 KubeOneClusterPhaseReconcilingUpgrade ExternalClusterPhase = "ReconcilingUpgrade" 170 171 KubeOneClusterPhaseReconcilingMigrate ExternalClusterPhase = "ReconcilingMigrate" 172 173 // ExternalClusterPhaseDeleting status indicates the cluster is being deleted. 174 ExternalClusterPhaseDeleting ExternalClusterPhase = "Deleting" 175 176 // ExternalClusterPhaseUnknown Not set. 177 ExternalClusterPhaseUnknown ExternalClusterPhase = "Unknown" 178 179 // ExternalClusterPhaseError status indicates the cluster is unusable. Details can be found in the 180 // `statusMessage` field. 181 ExternalClusterPhaseError ExternalClusterPhase = "Error" 182 183 // ExternalClusterPhaseRuntimeError status indicates cluster runtime error. Details can be found in the 184 // `statusMessage` field. 185 ExternalClusterPhaseRuntimeError ExternalClusterPhase = "RuntimeError" 186 187 // ExternalClusterPhaseEtcdError status indicates cluster etcd error. Details can be found in the 188 // `statusMessage` field. 189 ExternalClusterPhaseEtcdError ExternalClusterPhase = "EtcdError" 190 191 // ExternalClusterPhaseKubeClientError status indicates cluster kubeclient. Details can be found in the 192 // `statusMessage` field. 193 ExternalClusterPhaseKubeClientError ExternalClusterPhase = "KubeClientError" 194 195 // KubeOneExternalClusterPhaseSSHError status indicates cluster ssh error. Details can be found in the 196 // `statusMessage` field. 197 ExternalClusterPhaseSSHError ExternalClusterPhase = "SSHError" 198 199 // ExternalClusterPhaseConnectionError status indicates cluster connection error. Details can be found in the 200 // `statusMessage` field. 201 ExternalClusterPhaseConnectionError ExternalClusterPhase = "ConnectionError" 202 203 // ExternalClusterPhaseConfigError status indicates cluster config error. Details can be found in the 204 // `statusMessage` field. 205 ExternalClusterPhaseConfigError ExternalClusterPhase = "ConfigError" 206 ) 207 208 type ExternalClusterBringYourOwnCloudSpec struct{} 209 210 type ExternalClusterGKECloudSpec struct { 211 CredentialsReference *GlobalSecretKeySelector `json:"credentialsReference"` 212 213 Name string `json:"name"` 214 // ServiceAccount: The Google Cloud Platform Service Account. 215 // Can be read from `credentialsReference` instead. 216 ServiceAccount string `json:"serviceAccount,omitempty"` 217 // Zone: The name of the Google Compute Engine zone 218 // (https://cloud.google.com/compute/docs/zones#available) in which the 219 // cluster resides. 220 Zone string `json:"zone"` 221 } 222 223 type ExternalClusterEKSCloudSpec struct { 224 CredentialsReference *GlobalSecretKeySelector `json:"credentialsReference"` 225 226 Name string `json:"name"` 227 // AccessKeyID: AWS Access key ID 228 // Can be read from `credentialsReference` instead. 229 AccessKeyID string `json:"accessKeyID,omitempty"` 230 // SecretAccessKey: AWS Secret Access Key 231 // Can be read from `credentialsReference` instead. 232 SecretAccessKey string `json:"secretAccessKey,omitempty"` 233 Region string `json:"region"` 234 // ControlPlaneRoleARN: The Amazon Resource Name (ARN) of the IAM role that provides permissions 235 // for the Kubernetes control plane to make calls to Amazon Web Services API 236 // operations on your behalf. 237 ControlPlaneRoleARN string `json:"roleArn,omitempty"` 238 // VPCID: The VPC associated with your cluster. 239 VPCID string `json:"vpcID,omitempty"` 240 // SubnetIDs: The subnets associated with your cluster. 241 SubnetIDs []string `json:"subnetIDs,omitempty"` 242 // SecurityGroupIDs: The security groups associated with the cross-account elastic network interfaces 243 // that are used to allow communication between your nodes and the Kubernetes 244 // control plane. 245 SecurityGroupIDs []string `json:"securityGroupIDs,omitempty"` 246 247 // AssumeRoleARN defines the ARN for an IAM role that should be assumed when handling resources on AWS. It will be used 248 // to acquire temporary security credentials using an STS AssumeRole API operation whenever creating an AWS session. 249 // required: false 250 AssumeRoleARN string `json:"assumeRoleARN,omitempty"` //nolint:tagliatelle 251 // AssumeRoleExternalID is an arbitrary string that may be needed when calling the STS AssumeRole API operation. 252 // Using an external ID can help to prevent the "confused deputy problem". 253 // required: false 254 AssumeRoleExternalID string `json:"assumeRoleExternalID,omitempty"` 255 } 256 257 type ExternalClusterAKSCloudSpec struct { 258 // CredentialsReference allows referencing a `Secret` resource instead of passing secret data in this spec. 259 CredentialsReference *GlobalSecretKeySelector `json:"credentialsReference"` 260 261 Name string `json:"name"` 262 // TenantID: The Azure Active Directory Tenant used for this cluster. 263 // Can be read from `credentialsReference` instead. 264 TenantID string `json:"tenantID,omitempty"` 265 // SubscriptionID: The Azure Subscription used for this cluster. 266 // Can be read from `credentialsReference` instead. 267 SubscriptionID string `json:"subscriptionID,omitempty"` 268 // ClientID: The service principal used to access Azure. 269 // Can be read from `credentialsReference` instead. 270 ClientID string `json:"clientID,omitempty"` 271 // ClientSecret: The client secret corresponding to the given service principal. 272 // Can be read from `credentialsReference` instead. 273 ClientSecret string `json:"clientSecret,omitempty"` 274 // Location: The geo-location where the resource lives 275 Location string `json:"location"` 276 // ResourceGroup: The resource group that will be used to look up and create resources for the cluster in. 277 // If set to empty string at cluster creation, a new resource group will be created and this field will be updated to 278 // the generated resource group's name. 279 ResourceGroup string `json:"resourceGroup"` 280 } 281 282 const ( 283 // ExternalCluster Kubeconfig secret prefix. 284 externalClusterKubeconfigPrefix = "kubeconfig-external-cluster" 285 286 // kubeOneNamespacePrefix is the kubeone namespace prefix. 287 kubeOneNamespacePrefix = "kubeone" 288 289 // don't change this as these prefixes are used for rbac generation. 290 // KubeOne ssh secret prefixes. 291 kubeOneSSHSecretPrefix = "ssh-kubeone-external-cluster" 292 293 // KubeOne manifest secret prefixes. 294 kubeOneManifestSecretPrefix = "manifest-kubeone-external-cluster" 295 ) 296 297 // TODO: Replace this with a field in the ExternalClusterStatus in KKP 3.x. 298 func (c *ExternalCluster) GetKubeconfigSecretName() string { 299 return fmt.Sprintf("%s-%s", externalClusterKubeconfigPrefix, c.Name) 300 } 301 302 // TODO: Replace this with a field in the ExternalClusterStatus in KKP 3.x. 303 func (c *ExternalCluster) GetCredentialsSecretName() string { 304 // The kubermatic cluster `GetSecretName` method is used to get credential secret name for external cluster 305 // The same is used for the external cluster creation when secret is created 306 cluster := &Cluster{ 307 ObjectMeta: metav1.ObjectMeta{ 308 Name: c.Name, 309 }, 310 Spec: ClusterSpec{ 311 Cloud: CloudSpec{}, 312 }, 313 } 314 cloud := c.Spec.CloudSpec 315 if cloud.ProviderName == ExternalClusterProviderBringYourOwn { 316 return "" 317 } 318 if cloud.GKE != nil { 319 cluster.Spec.Cloud.GCP = &GCPCloudSpec{} 320 } 321 if cloud.EKS != nil { 322 cluster.Spec.Cloud.AWS = &AWSCloudSpec{} 323 } 324 if cloud.AKS != nil { 325 cluster.Spec.Cloud.Azure = &AzureCloudSpec{} 326 } 327 return cluster.GetSecretName() 328 } 329 330 // TODO: Replace this with a field in the ExternalClusterStatus in KKP 3.x. 331 func (c *ExternalCluster) GetKubeOneCredentialsSecretName() string { 332 providerName := c.Spec.CloudSpec.KubeOne.ProviderName 333 return fmt.Sprintf("%s-%s-%s", credentialPrefix, providerName, c.Name) 334 } 335 336 // TODO: Replace this with a field in the ExternalClusterStatus in KKP 3.x. 337 func (c *ExternalCluster) GetKubeOneSSHSecretName() string { 338 return fmt.Sprintf("%s-%s", kubeOneSSHSecretPrefix, c.Name) 339 } 340 341 // TODO: Replace this with a field in the ExternalClusterStatus in KKP 3.x. 342 func (c *ExternalCluster) GetKubeOneManifestSecretName() string { 343 return fmt.Sprintf("%s-%s", kubeOneManifestSecretPrefix, c.Name) 344 } 345 346 // TODO: Replace this with a field in the ExternalClusterStatus in KKP 3.x. 347 func (c *ExternalCluster) GetKubeOneNamespaceName() string { 348 return fmt.Sprintf("%s-%s", kubeOneNamespacePrefix, c.Name) 349 }