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  }