diff --git a/cloud/services/container/clusters/reconcile.go b/cloud/services/container/clusters/reconcile.go index 5a3f8cb08..dfb8cfca3 100644 --- a/cloud/services/container/clusters/reconcile.go +++ b/cloud/services/container/clusters/reconcile.go @@ -251,9 +251,10 @@ func (s *Service) createCluster(ctx context.Context, log *logr.Logger) error { isRegional := shared.IsRegional(s.scope.Region()) cluster := &containerpb.Cluster{ - Name: s.scope.ClusterName(), - Network: *s.scope.GCPManagedCluster.Spec.Network.Name, - Subnetwork: s.getSubnetNameInClusterRegion(), + Name: s.scope.ClusterName(), + Description: s.scope.GCPManagedControlPlane.Spec.Description, + Network: *s.scope.GCPManagedCluster.Spec.Network.Name, + Subnetwork: s.getSubnetNameInClusterRegion(), Autopilot: &containerpb.Autopilot{ Enabled: s.scope.GCPManagedControlPlane.Spec.EnableAutopilot, }, @@ -265,6 +266,34 @@ func (s *Service) createCluster(ctx context.Context, log *logr.Logger) error { if s.scope.GCPManagedControlPlane.Spec.ControlPlaneVersion != nil { cluster.InitialClusterVersion = convertToSdkMasterVersion(*s.scope.GCPManagedControlPlane.Spec.ControlPlaneVersion) } + if s.scope.GCPManagedControlPlane.Spec.ClusterNetwork != nil { + cn := s.scope.GCPManagedControlPlane.Spec.ClusterNetwork + if cn.UseIPAliases { + cluster.IpAllocationPolicy = &containerpb.IPAllocationPolicy{} + cluster.IpAllocationPolicy.UseIpAliases = cn.UseIPAliases + } + if cn.PrivateCluster != nil { + cluster.PrivateClusterConfig = &containerpb.PrivateClusterConfig{} + cluster.PrivateClusterConfig.EnablePrivateEndpoint = cn.PrivateCluster.EnablePrivateEndpoint + if cn.PrivateCluster.EnablePrivateEndpoint { + cluster.MasterAuthorizedNetworksConfig = &containerpb.MasterAuthorizedNetworksConfig{ + Enabled: true, + } + } + cluster.PrivateClusterConfig.EnablePrivateNodes = cn.PrivateCluster.EnablePrivateNodes + + cluster.PrivateClusterConfig.MasterIpv4CidrBlock = cn.PrivateCluster.ControlPlaneCidrBlock + cluster.PrivateClusterConfig.MasterGlobalAccessConfig = &containerpb.PrivateClusterMasterGlobalAccessConfig{ + Enabled: cn.PrivateCluster.ControlPlaneGlobalAccess, + } + + cluster.NetworkConfig = &containerpb.NetworkConfig{ + DefaultSnatStatus: &containerpb.DefaultSnatStatus{ + Disabled: cn.PrivateCluster.DisableDefaultSNAT, + }, + } + } + } if !s.scope.IsAutopilotCluster() { cluster.NodePools = scope.ConvertToSdkNodePools(nodePools, machinePools, isRegional, cluster.GetName()) } diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_gcpmanagedcontrolplanes.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_gcpmanagedcontrolplanes.yaml index 9707e5284..39a580c90 100644 --- a/config/crd/bases/infrastructure.cluster.x-k8s.io_gcpmanagedcontrolplanes.yaml +++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_gcpmanagedcontrolplanes.yaml @@ -68,12 +68,75 @@ spec: If you don't specify a name then a default name will be created based on the namespace and name of the managed control plane. type: string + clusterNetwork: + description: ClusterNetwork define the cluster network. + properties: + pod: + description: Pod defines the range of CIDRBlock list from where + it gets the IP address. + properties: + cidrBlock: + description: |- + CidrBlock is where all pods in the cluster are assigned an IP address from this range. Enter a range + (in CIDR notation) within a network range, a mask, or leave this field blank to use a default range. + This setting is permanent. + type: string + type: object + privateCluster: + description: PrivateCluster defines the private cluster spec. + properties: + controlPlaneCidrBlock: + description: |- + ControlPlaneCidrBlock is the IP range in CIDR notation to use for the hosted master network. This range must not + overlap with any other ranges in use within the cluster's network. Honored when enabled is true. + type: string + controlPlaneGlobalAccess: + description: ControlPlaneGlobalAccess is whenever master is + accessible globally or not. Honored when enabled is true. + type: boolean + disableDefaultSNAT: + description: DisableDefaultSNAT disables cluster default sNAT + rules. Honored when enabled is true. + type: boolean + enablePrivateEndpoint: + description: |- + EnablePrivateEndpoint: Whether the master's internal IP + address is used as the cluster endpoint. + type: boolean + enablePrivateNodes: + description: |- + EnablePrivateNodes: Whether nodes have internal IP + addresses only. If enabled, all nodes are given only RFC + 1918 private addresses and communicate with the master via + private networking. + type: boolean + type: object + service: + description: Service defines the range of CIDRBlock list from + where it gets the IP address. + properties: + cidrBlock: + description: |- + CidrBlock is where cluster services will be assigned an IP address from this IP address range. Enter a range + (in CIDR notation) within a network range, a mask, or leave this field blank to use a default range. + This setting is permanent. + type: string + type: object + useIPAliases: + description: |- + UseIPAliases is whether alias IPs will be used for pod IPs in the cluster. If false, routes will be used for + pod IPs in the cluster. + type: boolean + type: object controlPlaneVersion: description: |- ControlPlaneVersion represents the control plane version of the GKE cluster. If not specified, the default version currently supported by GKE will be used. type: string + description: + description: Description describe the cluster. + type: string enableAutopilot: description: EnableAutopilot indicates whether to enable autopilot for this GKE cluster. diff --git a/exp/api/v1beta1/gcpmanagedcontrolplane_types.go b/exp/api/v1beta1/gcpmanagedcontrolplane_types.go index b0fb6540d..b7b1699cf 100644 --- a/exp/api/v1beta1/gcpmanagedcontrolplane_types.go +++ b/exp/api/v1beta1/gcpmanagedcontrolplane_types.go @@ -27,6 +27,88 @@ const ( ManagedControlPlaneFinalizer = "gcpmanagedcontrolplane.infrastructure.cluster.x-k8s.io" ) +// PrivateCluster defines a private Cluster. +type PrivateCluster struct { + // EnablePrivateEndpoint: Whether the master's internal IP + // address is used as the cluster endpoint. + // +optional + EnablePrivateEndpoint bool `json:"enablePrivateEndpoint,omitempty"` + + // EnablePrivateNodes: Whether nodes have internal IP + // addresses only. If enabled, all nodes are given only RFC + // 1918 private addresses and communicate with the master via + // private networking. + // +optional + EnablePrivateNodes bool `json:"enablePrivateNodes,omitempty"` + + // ControlPlaneCidrBlock is the IP range in CIDR notation to use for the hosted master network. This range must not + // overlap with any other ranges in use within the cluster's network. Honored when enabled is true. + // +optional + ControlPlaneCidrBlock string `json:"controlPlaneCidrBlock,omitempty"` + + // ControlPlaneGlobalAccess is whenever master is accessible globally or not. Honored when enabled is true. + // +optional + ControlPlaneGlobalAccess bool `json:"controlPlaneGlobalAccess,omitempty"` + + // DisableDefaultSNAT disables cluster default sNAT rules. Honored when enabled is true. + // +optional + DisableDefaultSNAT bool `json:"disableDefaultSNAT,omitempty"` +} + +// ClusterNetworkPod the range of CIDRBlock list from where it gets the IP address. +type ClusterNetworkPod struct { + // CidrBlock is where all pods in the cluster are assigned an IP address from this range. Enter a range + // (in CIDR notation) within a network range, a mask, or leave this field blank to use a default range. + // This setting is permanent. + // +optional + CidrBlock string `json:"cidrBlock,omitempty"` +} + +// ClusterNetworkService defines the range of CIDRBlock list from where it gets the IP address. +type ClusterNetworkService struct { + // CidrBlock is where cluster services will be assigned an IP address from this IP address range. Enter a range + // (in CIDR notation) within a network range, a mask, or leave this field blank to use a default range. + // This setting is permanent. + // +optional + CidrBlock string `json:"cidrBlock,omitempty"` +} + +// ClusterNetwork define the cluster network. +type ClusterNetwork struct { + // PrivateCluster defines the private cluster spec. + // +optional + PrivateCluster *PrivateCluster `json:"privateCluster,omitempty"` + + // UseIPAliases is whether alias IPs will be used for pod IPs in the cluster. If false, routes will be used for + // pod IPs in the cluster. + // +optional + UseIPAliases bool `json:"useIPAliases,omitempty"` + + // Pod defines the range of CIDRBlock list from where it gets the IP address. + // +optional + Pod *ClusterNetworkPod `json:"pod,omitempty"` + + // Service defines the range of CIDRBlock list from where it gets the IP address. + // +optional + Service *ClusterNetworkService `json:"service,omitempty"` +} + +// WorkloadIdentityConfig allows workloads in your GKE clusters to impersonate Identity and Access Management (IAM) +// service accounts to access Google Cloud services. +type WorkloadIdentityConfig struct { + // WorkloadPool is the workload pool to attach all Kubernetes service accounts to Google Cloud services. + // Only relevant when enabled is true + // +kubebuilder:validation:Required + WorkloadPool string `json:"workloadPool,omitempty"` +} + +// AuthenticatorGroupConfig is RBAC security group for use with Google security groups in Kubernetes RBAC. +type AuthenticatorGroupConfig struct { + // SecurityGroups is the name of the security group-of-groups to be used. + // +kubebuilder:validation:Required + SecurityGroups string `json:"securityGroups,omitempty"` +} + // GCPManagedControlPlaneSpec defines the desired state of GCPManagedControlPlane. type GCPManagedControlPlaneSpec struct { // ClusterName allows you to specify the name of the GKE cluster. @@ -34,6 +116,15 @@ type GCPManagedControlPlaneSpec struct { // based on the namespace and name of the managed control plane. // +optional ClusterName string `json:"clusterName,omitempty"` + + // Description describe the cluster. + // +optional + Description string `json:"description,omitempty"` + + // ClusterNetwork define the cluster network. + // +optional + ClusterNetwork *ClusterNetwork `json:"clusterNetwork,omitempty"` + // Project is the name of the project to deploy the cluster to. Project string `json:"project"` // Location represents the location (region or zone) in which the GKE cluster diff --git a/exp/api/v1beta1/zz_generated.deepcopy.go b/exp/api/v1beta1/zz_generated.deepcopy.go index 15e7d6543..f70cde996 100644 --- a/exp/api/v1beta1/zz_generated.deepcopy.go +++ b/exp/api/v1beta1/zz_generated.deepcopy.go @@ -26,6 +26,81 @@ import ( cluster_apiapiv1beta1 "sigs.k8s.io/cluster-api/api/v1beta1" ) +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AuthenticatorGroupConfig) DeepCopyInto(out *AuthenticatorGroupConfig) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuthenticatorGroupConfig. +func (in *AuthenticatorGroupConfig) DeepCopy() *AuthenticatorGroupConfig { + if in == nil { + return nil + } + out := new(AuthenticatorGroupConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClusterNetwork) DeepCopyInto(out *ClusterNetwork) { + *out = *in + if in.PrivateCluster != nil { + in, out := &in.PrivateCluster, &out.PrivateCluster + *out = new(PrivateCluster) + **out = **in + } + if in.Pod != nil { + in, out := &in.Pod, &out.Pod + *out = new(ClusterNetworkPod) + **out = **in + } + if in.Service != nil { + in, out := &in.Service, &out.Service + *out = new(ClusterNetworkService) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterNetwork. +func (in *ClusterNetwork) DeepCopy() *ClusterNetwork { + if in == nil { + return nil + } + out := new(ClusterNetwork) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClusterNetworkPod) DeepCopyInto(out *ClusterNetworkPod) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterNetworkPod. +func (in *ClusterNetworkPod) DeepCopy() *ClusterNetworkPod { + if in == nil { + return nil + } + out := new(ClusterNetworkPod) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClusterNetworkService) DeepCopyInto(out *ClusterNetworkService) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterNetworkService. +func (in *ClusterNetworkService) DeepCopy() *ClusterNetworkService { + if in == nil { + return nil + } + out := new(ClusterNetworkService) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *GCPManagedCluster) DeepCopyInto(out *GCPManagedCluster) { *out = *in @@ -212,6 +287,11 @@ func (in *GCPManagedControlPlaneList) DeepCopyObject() runtime.Object { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *GCPManagedControlPlaneSpec) DeepCopyInto(out *GCPManagedControlPlaneSpec) { *out = *in + if in.ClusterNetwork != nil { + in, out := &in.ClusterNetwork, &out.ClusterNetwork + *out = new(ClusterNetwork) + (*in).DeepCopyInto(*out) + } if in.ReleaseChannel != nil { in, out := &in.ReleaseChannel, &out.ReleaseChannel *out = new(ReleaseChannel) @@ -631,6 +711,21 @@ func (in *NodeSecurityConfig) DeepCopy() *NodeSecurityConfig { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PrivateCluster) DeepCopyInto(out *PrivateCluster) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PrivateCluster. +func (in *PrivateCluster) DeepCopy() *PrivateCluster { + if in == nil { + return nil + } + out := new(PrivateCluster) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServiceAccountConfig) DeepCopyInto(out *ServiceAccountConfig) { *out = *in @@ -704,3 +799,18 @@ func (in Taints) DeepCopy() Taints { in.DeepCopyInto(out) return *out } + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WorkloadIdentityConfig) DeepCopyInto(out *WorkloadIdentityConfig) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WorkloadIdentityConfig. +func (in *WorkloadIdentityConfig) DeepCopy() *WorkloadIdentityConfig { + if in == nil { + return nil + } + out := new(WorkloadIdentityConfig) + in.DeepCopyInto(out) + return out +} diff --git a/hack/tools/go.mod b/hack/tools/go.mod index fd145ce8d..6bd2c22d3 100644 --- a/hack/tools/go.mod +++ b/hack/tools/go.mod @@ -1,6 +1,6 @@ module sigs.k8s.io/cluster-api-provider-gcp/hack/tools -go 1.21.10 +go 1.21 replace sigs.k8s.io/cluster-api => sigs.k8s.io/cluster-api v1.7.3