From 45bb559a2f7fa85ef713be934656b7792761e6a1 Mon Sep 17 00:00:00 2001 From: cjschaef Date: Tue, 23 Jul 2024 15:33:19 -0500 Subject: [PATCH 1/2] VPC: API updates for extended VPC support Extending VPC related Cluster API's in order to provide additional VPC Infrastructure reconciliation support. --- api/v1beta1/zz_generated.conversion.go | 5 + api/v1beta2/ibmvpccluster_types.go | 182 +++- api/v1beta2/types.go | 109 ++- api/v1beta2/zz_generated.deepcopy.go | 274 +++++- ...e.cluster.x-k8s.io_ibmpowervsclusters.yaml | 145 +++ ...r.x-k8s.io_ibmpowervsclustertemplates.yaml | 147 +++ ...cture.cluster.x-k8s.io_ibmvpcclusters.yaml | 882 +++++++++++++++++- ...uster.x-k8s.io_ibmvpcclustertemplates.yaml | 777 ++++++++++++++- 8 files changed, 2493 insertions(+), 28 deletions(-) diff --git a/api/v1beta1/zz_generated.conversion.go b/api/v1beta1/zz_generated.conversion.go index 928ade768..9f5ffb4cc 100644 --- a/api/v1beta1/zz_generated.conversion.go +++ b/api/v1beta1/zz_generated.conversion.go @@ -1269,6 +1269,7 @@ func autoConvert_v1beta2_IBMVPCClusterSpec_To_v1beta1_IBMVPCClusterSpec(in *v1be } else { out.ControlPlaneLoadBalancer = nil } + // WARNING: in.Image requires manual conversion: does not exist in peer-type // WARNING: in.Network requires manual conversion: does not exist in peer-type return nil } @@ -1298,6 +1299,7 @@ func autoConvert_v1beta2_IBMVPCClusterStatus_To_v1beta1_IBMVPCClusterStatus(in * if err := Convert_v1beta2_VPC_To_v1beta1_VPC(&in.VPC, &out.VPC, s); err != nil { return err } + // WARNING: in.Image requires manual conversion: does not exist in peer-type // WARNING: in.Network requires manual conversion: does not exist in peer-type out.Ready = in.Ready // WARNING: in.ResourceGroup requires manual conversion: does not exist in peer-type @@ -1689,6 +1691,9 @@ func autoConvert_v1beta2_VPCLoadBalancerSpec_To_v1beta1_VPCLoadBalancerSpec(in * // WARNING: in.ID requires manual conversion: does not exist in peer-type // WARNING: in.Public requires manual conversion: does not exist in peer-type // WARNING: in.AdditionalListeners requires manual conversion: does not exist in peer-type + // WARNING: in.BackendPools requires manual conversion: does not exist in peer-type + // WARNING: in.SecurityGroups requires manual conversion: does not exist in peer-type + // WARNING: in.Subnets requires manual conversion: does not exist in peer-type return nil } diff --git a/api/v1beta2/ibmvpccluster_types.go b/api/v1beta2/ibmvpccluster_types.go index 4cad55e20..3740f4350 100644 --- a/api/v1beta2/ibmvpccluster_types.go +++ b/api/v1beta2/ibmvpccluster_types.go @@ -52,9 +52,14 @@ type IBMVPCClusterSpec struct { ControlPlaneEndpoint capiv1beta1.APIEndpoint `json:"controlPlaneEndpoint"` // ControlPlaneLoadBalancer is optional configuration for customizing control plane behavior. + // Use this for legacy support, use Network.LoadBalancers for the extended VPC support. // +optional ControlPlaneLoadBalancer *VPCLoadBalancerSpec `json:"controlPlaneLoadBalancer,omitempty"` + // image represents the Image details used for the cluster. + // +optional + Image *ImageSpec `json:"image,omitempty"` + // network represents the VPC network to use for the cluster. // +optional Network *VPCNetworkSpec `json:"network,omitempty"` @@ -87,37 +92,168 @@ type VPCLoadBalancerSpec struct { // +optional // ++kubebuilder:validation:UniqueItems=true AdditionalListeners []AdditionalListenerSpec `json:"additionalListeners,omitempty"` + + // backendPools defines the load balancer's backend pools. + // +optional + BackendPools []VPCLoadBalancerBackendPoolSpec `json:"backendPools,omitempty"` + + // securityGroups defines the Security Groups to attach to the load balancer. + // Security Groups defined here are expected to already exist when the load balancer is reconciled (these do not get created when reconciling the load balancer). + // +optional + SecurityGroups []VPCResource `json:"securityGroups,omitempty"` + + // subnets defines the VPC Subnets to attach to the load balancer. + // Subnets defiens here are expected to already exist when the load balancer is reconciled (these do not get created when reconciling the load balancer). + // +optional + Subnets []VPCResource `json:"subnets,omitempty"` } // AdditionalListenerSpec defines the desired state of an // additional listener on an VPC load balancer. type AdditionalListenerSpec struct { + // defaultPoolName defines the name of a VPC Load Balancer Backend Pool to use for the VPC Load Balancer Listener. + // +kubebuilder:validation:MinLength:=1 + // +kubebuilder:validation:MaxLength:=63 + // +kubebuilder:validation:Pattern=`^([a-z]|[a-z][-a-z0-9]*[a-z0-9])$` + // +optional + DefaultPoolName *string `json:"defaultPoolName,omitempty"` + // Port sets the port for the additional listener. // +kubebuilder:validation:Minimum=1 // +kubebuilder:validation:Maximum=65535 Port int64 `json:"port"` + + // protocol defines the protocol to use for the VPC Load Balancer Listener. + // Will default to TCP protocol if not specified. + // +optional + Protocol *VPCLoadBalancerListenerProtocol `json:"protocol,omitempty"` } -// VPCNetworkSpec defines the desired state of the network resources for the cluster for extended VPC Infrastructure support. -type VPCNetworkSpec struct { - // workerSubnets is a set of Subnet's which define the Worker subnets. +// VPCLoadBalancerBackendPoolSpec defines the desired configuration of a VPC Load Balancer Backend Pool. +type VPCLoadBalancerBackendPoolSpec struct { + // name defines the name of the Backend Pool. + // +kubebuilder:validation:MinLength:=1 + // +kubebuilder:validation:MaxLength:=63 + // +kubebuilder:validation:Pattern=`^([a-z]|[a-z][-a-z0-9]*[a-z0-9])$` // +optional - WorkerSubnets []Subnet `json:"workerSubnets,omitempty"` + Name *string `json:"name,omitempty"` + + // algorithm defines the load balancing algorithm to use. + // +required + Algorithm VPCLoadBalancerBackendPoolAlgorithm `json:"algorithm"` + + // healthMonitor defines the backend pool's health monitor. + // +required + HealthMonitor VPCLoadBalancerHealthMonitorSpec `json:"healthMonitor"` + + // protocol defines the protocol to use for the Backend Pool. + // +required + Protocol VPCLoadBalancerBackendPoolProtocol `json:"protocol"` +} + +// VPCLoadBalancerHealthMonitorSpec defines the desired state of a Health Monitor resource for a VPC Load Balancer Backend Pool. +// kubebuilder:validation:XValidation:rule="self.dely > self.timeout",message="health monitor's delay must be greater than the timeout" +type VPCLoadBalancerHealthMonitorSpec struct { + // delay defines the seconds to wait between health checks. + // +kubebuilder:validation:Minimum=2 + // +kubebuilder:validation:Maximum=60 + // +required + Delay int64 `json:"delay"` + + // retries defines the max retries for health check. + // +kubebuilder:validation:Minimum=1 + // +kubebuilder:validation:Maximum=10 + // +required + Retries int64 `json:"retries"` + + // port defines the port to perform health monitoring on. + // +kubebuilder:validation:Minimum=1 + // +kubebuilder:validation:Maximum=65535 + // +optional + Port *int64 `json:"port,omitempty"` + + // timeout defines the seconds to wait for a health check response. + // +kubebuilder:validation:Minimum=1 + // +kubebuilder:validation:Maximum=59 + // +required + Timeout int64 `json:"timeout"` + + // type defines the protocol used for health checks. + // +required + Type VPCLoadBalancerBackendPoolHealthMonitorType `json:"type"` + // urlPath defines the URL to use for health monitoring. + // +kubebuilder:validation:Pattern=`^\/(([a-zA-Z0-9-._~!$&'()*+,;=:@]|%[a-fA-F0-9]{2})+(\/([a-zA-Z0-9-._~!$&'()*+,;=:@]|%[a-fA-F0-9]{2})*)*)?(\\?([a-zA-Z0-9-._~!$&'()*+,;=:@\/?]|%[a-fA-F0-9]{2})*)?$` + // +optional + URLPath *string `json:"urlPath,omitempty"` +} + +// ImageSpec defines the desired state of the VPC Custom Image resources for the cluster. +// +kubebuilder:validation:XValidation:rule="(!has(self.cosInstance) && !has(self.cosBucket) && !has(self.cosObject)) || (has(self.cosInstance) && has(self.cosBucket) && has(self.cosObject))",message="if any of cosInstance, cosBucket, or cosObject are specified, all must be specified" +// +kubebuilder:validation:XValidation:rule="has(self.name) || has(self.crn) || (has(self.cosInstance) && has(self.cosBucket) && has(self.cosObject))",message="an existing image name or crn must be provided, or to create a new image the cos resources must be provided, with or without a name" +type ImageSpec struct { + // name is the name of the desired VPC Custom Image. + // +kubebuilder:validation:MinLength:=1 + // +kubebuilder:validation:MaxLength:=63 + // +kubebuilder:validation:Pattern='/^([a-z]|[a-z][-a-z0-9]*[a-z0-9])$/' + // +optional + Name *string `json:"name,omitempty"` + + // crn is the IBM Cloud CRN of the existing VPC Custom Image. + // +optional + CRN *string `json:"crn,omitempty"` + + // cosInstance is the name of the IBM Cloud COS Instance containing the source of the image, if necessary. + // +optional + COSInstance *string `json:"cosInstance,omitempty"` + + // cosBucket is the name of the IBM Cloud COS Bucket containing the source of the image, if necessary. + // +optional + COSBucket *string `json:"cosBucket,omitempty"` + + // cosBucketRegion is the COS region the bucket is in. + // +optional + COSBucketRegion *string `json:"cosBucketRegion,omitempty"` + + // cosObject is the name of a IBM Cloud COS Object used as the source of the image, if necessary. + // +optional + COSObject *string `json:"cosObject,omitempty"` + + // operatingSystem is the Custom Image's Operating System name. + // +optional + OperatingSystem *string `json:"operatingSystem,omitempty"` + + // resourceGroup is the Resource Group to create the Custom Image in. + // +optional + ResourceGroup *IBMCloudResourceReference `json:"resourceGroup,omitempty"` +} + +// VPCNetworkSpec defines the desired state of the network resources for the cluster for extended VPC Infrastructure support. +type VPCNetworkSpec struct { // controlPlaneSubnets is a set of Subnet's which define the Control Plane subnets. // +optional ControlPlaneSubnets []Subnet `json:"controlPlaneSubnets,omitempty"` - // resourceGroup is the name of the Resource Group containing all of the newtork resources. + // loadBalancers is a set of VPC Load Balancer definitions to use for the cluster. + // +optional + LoadBalancers []VPCLoadBalancerSpec `json:"loadBalancers,omitempty"` + + // resourceGroup is the Resource Group containing all of the newtork resources. // This can be different than the Resource Group containing the remaining cluster resources. // +optional - ResourceGroup *string `json:"resourceGroup,omitempty"` + ResourceGroup *IBMCloudResourceReference `json:"resourceGroup,omitempty"` + + // securityGroups is a set of VPCSecurityGroup's which define the VPC Security Groups that manage traffic within and out of the VPC. + // +optional + SecurityGroups []VPCSecurityGroup `json:"securityGroups,omitempty"` + + // workerSubnets is a set of Subnet's which define the Worker subnets. + // +optional + WorkerSubnets []Subnet `json:"workerSubnets,omitempty"` // vpc defines the IBM Cloud VPC for extended VPC Infrastructure support. // +optional VPC *VPCResource `json:"vpc,omitempty"` - - // TODO(cjschaef): Complete spec definition (SecurityGroups, etc.) } // VPCSecurityGroupStatus defines a vpc security group resource status with its id and respective rule's ids. @@ -148,11 +284,14 @@ type VPCLoadBalancerStatus struct { // IBMVPCClusterStatus defines the observed state of IBMVPCCluster. type IBMVPCClusterStatus struct { - // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster // Important: Run "make" to regenerate code after modifying this file // dep: rely on Network instead. VPC VPC `json:"vpc,omitempty"` + // image is the status of the VPC Custom Image. + // +optional + Image *ResourceStatus `json:"image,omitempty"` + // network is the status of the VPC network resources for extended VPC Infrastructure support. // +optional Network *VPCNetworkStatus `json:"network,omitempty"` @@ -180,11 +319,36 @@ type IBMVPCClusterStatus struct { // VPCNetworkStatus provides details on the status of VPC network resources for extended VPC Infrastructure support. type VPCNetworkStatus struct { + // controlPlaneSubnets references the VPC Subnets for the cluster's Control Plane. + // The map simplifies lookups. + // +optional + ControlPlaneSubnets map[string]*ResourceStatus `json:"controlPlaneSubnets,omitempty"` + + // loadBalancers references the VPC Load Balancer's for the cluster. + // The map simplifies lookups. + // +optional + LoadBalancers map[string]*VPCLoadBalancerStatus `json:"loadBalancers,omitempty"` + + // publicGateways references the VPC Public Gateways for the cluster. + // The map simplifies lookups. + // +optional + PublicGateways map[string]*ResourceStatus `json:"publicGateways,omitempty"` + // resourceGroup references the Resource Group for Network resources for the cluster. // This can be the same or unique from the cluster's Resource Group. // +optional ResourceGroup *ResourceStatus `json:"resourceGroup,omitempty"` + // securityGroups references the VPC Security Groups for the cluster. + // The map simplifies lookups. + // +optional + SecurityGroups map[string]*ResourceStatus `json:"securityGroups,omitempty"` + + // workerSubnets references the VPC Subnets for the cluster's Data Plane. + // The map simplifies lookups. + // +optional + WorkerSubnets map[string]*ResourceStatus `json:"workerSubnets,omitempty"` + // vpc references the status of the IBM Cloud VPC as part of the extended VPC Infrastructure support. // +optional VPC *ResourceStatus `json:"vpc,omitempty"` diff --git a/api/v1beta2/types.go b/api/v1beta2/types.go index 0507cf27d..c82ec61e7 100644 --- a/api/v1beta2/types.go +++ b/api/v1beta2/types.go @@ -18,8 +18,13 @@ package v1beta2 import "github.com/IBM/vpc-go-sdk/vpcv1" -// DefaultAPIServerPort is defuault API server port number. -const DefaultAPIServerPort int32 = 6443 +const ( + // CIDRBlockAny is the CIDRBlock representing any allowable destination/source IP. + CIDRBlockAny string = "0.0.0.0/0" + + // DefaultAPIServerPort is defuault API server port number. + DefaultAPIServerPort int32 = 6443 +) // PowerVSInstanceState describes the state of an IBM Power VS instance. type PowerVSInstanceState string @@ -109,6 +114,74 @@ var ( TransitGatewayConnectionStateDeleting = TransitGatewayConnectionState("deleting") ) +// VPCLoadBalancerBackendPoolAlgorithm describes the backend pool's load balancing algorithm. +// +kubebuilder:validation:Enum=least_connections;round_robin;weighted_round_robin +type VPCLoadBalancerBackendPoolAlgorithm string + +var ( + // VPCLoadBalancerBackendPoolAlgorithmLeastConnections is the string representing the least_connections load balancing algorithm. + VPCLoadBalancerBackendPoolAlgorithmLeastConnections VPCLoadBalancerBackendPoolAlgorithm = vpcv1.CreateLoadBalancerPoolOptionsAlgorithmLeastConnectionsConst + + // VPCLoadBalancerBackendPoolAlgorithmRoundRobin is the string representing the round_robin load balancing algorithm. + VPCLoadBalancerBackendPoolAlgorithmRoundRobin VPCLoadBalancerBackendPoolAlgorithm = vpcv1.CreateLoadBalancerPoolOptionsAlgorithmRoundRobinConst + + // VPCLoadBalancerBackendPoolAlgorithmWeightedRoundRobin is the string representing the weighted_round_robin load balancing algorithm. + VPCLoadBalancerBackendPoolAlgorithmWeightedRoundRobin VPCLoadBalancerBackendPoolAlgorithm = vpcv1.CreateLoadBalancerPoolOptionsAlgorithmWeightedRoundRobinConst +) + +// VPCLoadBalancerBackendPoolProtocol describes the protocol for load balancer backend pools. +// We have unique types in case IBM Cloud Load Balancer Listener and Backend Pool supported algorithms ever diverage. +// +kubebuilder:validation:Enum=http;https;tcp;udp +type VPCLoadBalancerBackendPoolProtocol string + +var ( + // VPCLoadBalancerBackendPoolProtocolHTTP is the string representing the http protocol for load balancer backend pools. + VPCLoadBalancerBackendPoolProtocolHTTP VPCLoadBalancerBackendPoolProtocol = vpcv1.LoadBalancerPoolPrototypeProtocolHTTPConst + + // VPCLoadBalancerBackendPoolProtocolHTTPS is the string representing the https protocol for load balancer backend pools. + VPCLoadBalancerBackendPoolProtocolHTTPS VPCLoadBalancerBackendPoolProtocol = vpcv1.LoadBalancerPoolPrototypeProtocolHTTPSConst + + // VPCLoadBalancerBackendPoolProtocolTCP is the string representing the tcp protocol for load balancer backend pools. + VPCLoadBalancerBackendPoolProtocolTCP VPCLoadBalancerBackendPoolProtocol = vpcv1.LoadBalancerPoolPrototypeProtocolTCPConst + + // VPCLoadBalancerBackendPoolProtocolUDP is the string representing the tudp protocol for load balancer backend pools. + VPCLoadBalancerBackendPoolProtocolUDP VPCLoadBalancerBackendPoolProtocol = vpcv1.LoadBalancerPoolPrototypeProtocolUDPConst +) + +// VPCLoadBalancerListenerProtocol describes the protocol for load balancer listeners. +// We have unique types in case IBM Cloud Load Balancer Listener and Backend Pool supported algorithms ever diverage. +// +kubebuilder:validation:Enum=http;https;tcp;udp +type VPCLoadBalancerListenerProtocol string + +var ( + // VPCLoadBalancerListenerProtocolHTTP is the string representing the http protocol for load balancer listeners. + VPCLoadBalancerListenerProtocolHTTP VPCLoadBalancerListenerProtocol = vpcv1.LoadBalancerListenerProtocolHTTPConst + + // VPCLoadBalancerListenerProtocolHTTPS is the string representing the https protocol for load balancer listeners. + VPCLoadBalancerListenerProtocolHTTPS VPCLoadBalancerListenerProtocol = vpcv1.LoadBalancerListenerProtocolHTTPSConst + + // VPCLoadBalancerListenerProtocolTCP is the string representing the tcp protocol for load balancer listeners. + VPCLoadBalancerListenerProtocolTCP VPCLoadBalancerListenerProtocol = vpcv1.LoadBalancerListenerProtocolTCPConst + + // VPCLoadBalancerListenerProtocolUDP is the string representing the tudp protocol for load balancer listeners. + VPCLoadBalancerListenerProtocolUDP VPCLoadBalancerListenerProtocol = vpcv1.LoadBalancerListenerProtocolUDPConst +) + +// VPCLoadBalancerBackendPoolHealthMonitorType describes the backend pool's health check protocol type. +// +kubebuilder:validation:Enum=http;https;tcp +type VPCLoadBalancerBackendPoolHealthMonitorType string + +var ( + // VPCLoadBalancerBackendPoolHealthMonitorTypeHTTP is the string representing the http health pool protocol type. + VPCLoadBalancerBackendPoolHealthMonitorTypeHTTP VPCLoadBalancerBackendPoolHealthMonitorType = vpcv1.LoadBalancerPoolHealthMonitorTypeHTTPConst + + // VPCLoadBalancerBackendPoolHealthMonitorTypeHTTPS is the string representing the https health pool protocol type. + VPCLoadBalancerBackendPoolHealthMonitorTypeHTTPS VPCLoadBalancerBackendPoolHealthMonitorType = vpcv1.LoadBalancerPoolHealthMonitorTypeHTTPSConst + + // VPCLoadBalancerBackendPoolHealthMonitorTypeTCP is the string representing the tcp health pool protocol type. + VPCLoadBalancerBackendPoolHealthMonitorTypeTCP VPCLoadBalancerBackendPoolHealthMonitorType = vpcv1.LoadBalancerPoolHealthMonitorTypeTCPConst +) + // VPCLoadBalancerState describes the state of the load balancer. type VPCLoadBalancerState string @@ -185,12 +258,33 @@ var ( ResourceTypeVPC = ResourceType("vpc") // ResourceTypeSubnet is VPC subnet resource. ResourceTypeSubnet = ResourceType("subnet") + // ResourceTypeComputeSubnet is a VPC subnet resource designated for the Compute (Data) Plane. + ResourceTypeComputeSubnet = ResourceType("computeSubnet") + // ResourceTypeControlPlaneSubnet is a VPC subnet resource designated for the Control Plane. + ResourceTypeControlPlaneSubnet = ResourceType("controlPlaneSubnet") + // ResourceTypeSecurityGroup is a VPC Security Group resource. + ResourceTypeSecurityGroup = ResourceType("securityGroup") // ResourceTypeCOSInstance is IBM COS instance resource. ResourceTypeCOSInstance = ResourceType("cosInstance") // ResourceTypeCOSBucket is IBM COS bucket resource. ResourceTypeCOSBucket = ResourceType("cosBucket") // ResourceTypeResourceGroup is IBM Resource Group. ResourceTypeResourceGroup = ResourceType("resourceGroup") + // ResourceTypePublicGateway is a VPC Public Gatway. + ResourceTypePublicGateway = ResourceType("publicGateway") + // ResourceTypeCustomImage is a VPC Custom Image. + ResourceTypeCustomImage = ResourceType("customImage") +) + +const ( + // VPCSecurityGroupRuleProtocolAllType is a string representation of the 'SecurityGroupRuleSecurityGroupRuleProtocolAll' type. + VPCSecurityGroupRuleProtocolAllType = "*vpcv1.SecurityGroupRuleSecurityGroupRuleProtocolAll" + + // VPCSecurityGroupRuleProtocolIcmpType is a string representation of the 'SecurityGroupRuleSecurityGroupRuleProtocolIcmp' type. + VPCSecurityGroupRuleProtocolIcmpType = "*vpcv1.SecurityGroupRuleSecurityGroupRuleProtocolIcmp" + + // VPCSecurityGroupRuleProtocolTcpudpType is a string representation of the 'SecurityGroupRuleSecurityGroupRuleProtocolTcpudp' type. + VPCSecurityGroupRuleProtocolTcpudpType = "*vpcv1.SecurityGroupRuleSecurityGroupRuleProtocolTcpudp" ) // VPCSecurityGroupRuleAction represents the actions for a Security Group Rule. @@ -251,6 +345,17 @@ const ( VPCSecurityGroupRuleRemoteTypeSG VPCSecurityGroupRuleRemoteType = VPCSecurityGroupRuleRemoteType("sg") ) +// IBMCloudResourceReference represents an IBM Cloud resource. +type IBMCloudResourceReference struct { + // id defines the IBM Cloud Resource ID. + // +required + ID string `json:"id"` + + // name defines the IBM Cloud Resource Name. + // +optional + Name *string `json:"name,omitempty"` +} + // NetworkInterface holds the network interface information like subnet id. type NetworkInterface struct { // Subnet ID of the network interface. diff --git a/api/v1beta2/zz_generated.deepcopy.go b/api/v1beta2/zz_generated.deepcopy.go index c6a2b3589..43fab533b 100644 --- a/api/v1beta2/zz_generated.deepcopy.go +++ b/api/v1beta2/zz_generated.deepcopy.go @@ -30,6 +30,16 @@ import ( // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *AdditionalListenerSpec) DeepCopyInto(out *AdditionalListenerSpec) { *out = *in + if in.DefaultPoolName != nil { + in, out := &in.DefaultPoolName, &out.DefaultPoolName + *out = new(string) + **out = **in + } + if in.Protocol != nil { + in, out := &in.Protocol, &out.Protocol + *out = new(VPCLoadBalancerListenerProtocol) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AdditionalListenerSpec. @@ -97,6 +107,26 @@ func (in *DHCPServer) DeepCopy() *DHCPServer { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *IBMCloudResourceReference) DeepCopyInto(out *IBMCloudResourceReference) { + *out = *in + if in.Name != nil { + in, out := &in.Name, &out.Name + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IBMCloudResourceReference. +func (in *IBMCloudResourceReference) DeepCopy() *IBMCloudResourceReference { + if in == nil { + return nil + } + out := new(IBMCloudResourceReference) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *IBMPowerVSCluster) DeepCopyInto(out *IBMPowerVSCluster) { *out = *in @@ -873,6 +903,11 @@ func (in *IBMVPCClusterSpec) DeepCopyInto(out *IBMVPCClusterSpec) { *out = new(VPCLoadBalancerSpec) (*in).DeepCopyInto(*out) } + if in.Image != nil { + in, out := &in.Image, &out.Image + *out = new(ImageSpec) + (*in).DeepCopyInto(*out) + } if in.Network != nil { in, out := &in.Network, &out.Network *out = new(VPCNetworkSpec) @@ -894,6 +929,11 @@ func (in *IBMVPCClusterSpec) DeepCopy() *IBMVPCClusterSpec { func (in *IBMVPCClusterStatus) DeepCopyInto(out *IBMVPCClusterStatus) { *out = *in out.VPC = in.VPC + if in.Image != nil { + in, out := &in.Image, &out.Image + *out = new(ResourceStatus) + (*in).DeepCopyInto(*out) + } if in.Network != nil { in, out := &in.Network, &out.Network *out = new(VPCNetworkStatus) @@ -1290,6 +1330,61 @@ func (in *Ignition) DeepCopy() *Ignition { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ImageSpec) DeepCopyInto(out *ImageSpec) { + *out = *in + if in.Name != nil { + in, out := &in.Name, &out.Name + *out = new(string) + **out = **in + } + if in.CRN != nil { + in, out := &in.CRN, &out.CRN + *out = new(string) + **out = **in + } + if in.COSInstance != nil { + in, out := &in.COSInstance, &out.COSInstance + *out = new(string) + **out = **in + } + if in.COSBucket != nil { + in, out := &in.COSBucket, &out.COSBucket + *out = new(string) + **out = **in + } + if in.COSBucketRegion != nil { + in, out := &in.COSBucketRegion, &out.COSBucketRegion + *out = new(string) + **out = **in + } + if in.COSObject != nil { + in, out := &in.COSObject, &out.COSObject + *out = new(string) + **out = **in + } + if in.OperatingSystem != nil { + in, out := &in.OperatingSystem, &out.OperatingSystem + *out = new(string) + **out = **in + } + if in.ResourceGroup != nil { + in, out := &in.ResourceGroup, &out.ResourceGroup + *out = new(IBMCloudResourceReference) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImageSpec. +func (in *ImageSpec) DeepCopy() *ImageSpec { + if in == nil { + return nil + } + out := new(ImageSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NetworkInterface) DeepCopyInto(out *NetworkInterface) { *out = *in @@ -1460,6 +1555,52 @@ func (in *VPCEndpoint) DeepCopy() *VPCEndpoint { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VPCLoadBalancerBackendPoolSpec) DeepCopyInto(out *VPCLoadBalancerBackendPoolSpec) { + *out = *in + if in.Name != nil { + in, out := &in.Name, &out.Name + *out = new(string) + **out = **in + } + in.HealthMonitor.DeepCopyInto(&out.HealthMonitor) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VPCLoadBalancerBackendPoolSpec. +func (in *VPCLoadBalancerBackendPoolSpec) DeepCopy() *VPCLoadBalancerBackendPoolSpec { + if in == nil { + return nil + } + out := new(VPCLoadBalancerBackendPoolSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VPCLoadBalancerHealthMonitorSpec) DeepCopyInto(out *VPCLoadBalancerHealthMonitorSpec) { + *out = *in + if in.Port != nil { + in, out := &in.Port, &out.Port + *out = new(int64) + **out = **in + } + if in.URLPath != nil { + in, out := &in.URLPath, &out.URLPath + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VPCLoadBalancerHealthMonitorSpec. +func (in *VPCLoadBalancerHealthMonitorSpec) DeepCopy() *VPCLoadBalancerHealthMonitorSpec { + if in == nil { + return nil + } + out := new(VPCLoadBalancerHealthMonitorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *VPCLoadBalancerSpec) DeepCopyInto(out *VPCLoadBalancerSpec) { *out = *in @@ -1476,7 +1617,30 @@ func (in *VPCLoadBalancerSpec) DeepCopyInto(out *VPCLoadBalancerSpec) { if in.AdditionalListeners != nil { in, out := &in.AdditionalListeners, &out.AdditionalListeners *out = make([]AdditionalListenerSpec, len(*in)) - copy(*out, *in) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.BackendPools != nil { + in, out := &in.BackendPools, &out.BackendPools + *out = make([]VPCLoadBalancerBackendPoolSpec, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.SecurityGroups != nil { + in, out := &in.SecurityGroups, &out.SecurityGroups + *out = make([]VPCResource, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Subnets != nil { + in, out := &in.Subnets, &out.Subnets + *out = make([]VPCResource, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } } } @@ -1523,24 +1687,38 @@ func (in *VPCLoadBalancerStatus) DeepCopy() *VPCLoadBalancerStatus { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *VPCNetworkSpec) DeepCopyInto(out *VPCNetworkSpec) { *out = *in - if in.WorkerSubnets != nil { - in, out := &in.WorkerSubnets, &out.WorkerSubnets + if in.ControlPlaneSubnets != nil { + in, out := &in.ControlPlaneSubnets, &out.ControlPlaneSubnets *out = make([]Subnet, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } } - if in.ControlPlaneSubnets != nil { - in, out := &in.ControlPlaneSubnets, &out.ControlPlaneSubnets - *out = make([]Subnet, len(*in)) + if in.LoadBalancers != nil { + in, out := &in.LoadBalancers, &out.LoadBalancers + *out = make([]VPCLoadBalancerSpec, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } } if in.ResourceGroup != nil { in, out := &in.ResourceGroup, &out.ResourceGroup - *out = new(string) - **out = **in + *out = new(IBMCloudResourceReference) + (*in).DeepCopyInto(*out) + } + if in.SecurityGroups != nil { + in, out := &in.SecurityGroups, &out.SecurityGroups + *out = make([]VPCSecurityGroup, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.WorkerSubnets != nil { + in, out := &in.WorkerSubnets, &out.WorkerSubnets + *out = make([]Subnet, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } } if in.VPC != nil { in, out := &in.VPC, &out.VPC @@ -1562,11 +1740,91 @@ func (in *VPCNetworkSpec) DeepCopy() *VPCNetworkSpec { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *VPCNetworkStatus) DeepCopyInto(out *VPCNetworkStatus) { *out = *in + if in.ControlPlaneSubnets != nil { + in, out := &in.ControlPlaneSubnets, &out.ControlPlaneSubnets + *out = make(map[string]*ResourceStatus, len(*in)) + for key, val := range *in { + var outVal *ResourceStatus + if val == nil { + (*out)[key] = nil + } else { + inVal := (*in)[key] + in, out := &inVal, &outVal + *out = new(ResourceStatus) + (*in).DeepCopyInto(*out) + } + (*out)[key] = outVal + } + } + if in.LoadBalancers != nil { + in, out := &in.LoadBalancers, &out.LoadBalancers + *out = make(map[string]*VPCLoadBalancerStatus, len(*in)) + for key, val := range *in { + var outVal *VPCLoadBalancerStatus + if val == nil { + (*out)[key] = nil + } else { + inVal := (*in)[key] + in, out := &inVal, &outVal + *out = new(VPCLoadBalancerStatus) + (*in).DeepCopyInto(*out) + } + (*out)[key] = outVal + } + } + if in.PublicGateways != nil { + in, out := &in.PublicGateways, &out.PublicGateways + *out = make(map[string]*ResourceStatus, len(*in)) + for key, val := range *in { + var outVal *ResourceStatus + if val == nil { + (*out)[key] = nil + } else { + inVal := (*in)[key] + in, out := &inVal, &outVal + *out = new(ResourceStatus) + (*in).DeepCopyInto(*out) + } + (*out)[key] = outVal + } + } if in.ResourceGroup != nil { in, out := &in.ResourceGroup, &out.ResourceGroup *out = new(ResourceStatus) (*in).DeepCopyInto(*out) } + if in.SecurityGroups != nil { + in, out := &in.SecurityGroups, &out.SecurityGroups + *out = make(map[string]*ResourceStatus, len(*in)) + for key, val := range *in { + var outVal *ResourceStatus + if val == nil { + (*out)[key] = nil + } else { + inVal := (*in)[key] + in, out := &inVal, &outVal + *out = new(ResourceStatus) + (*in).DeepCopyInto(*out) + } + (*out)[key] = outVal + } + } + if in.WorkerSubnets != nil { + in, out := &in.WorkerSubnets, &out.WorkerSubnets + *out = make(map[string]*ResourceStatus, len(*in)) + for key, val := range *in { + var outVal *ResourceStatus + if val == nil { + (*out)[key] = nil + } else { + inVal := (*in)[key] + in, out := &inVal, &outVal + *out = new(ResourceStatus) + (*in).DeepCopyInto(*out) + } + (*out)[key] = outVal + } + } if in.VPC != nil { in, out := &in.VPC, &out.VPC *out = new(ResourceStatus) diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_ibmpowervsclusters.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_ibmpowervsclusters.yaml index eddf3c70c..b922b3ae3 100644 --- a/config/crd/bases/infrastructure.cluster.x-k8s.io_ibmpowervsclusters.yaml +++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_ibmpowervsclusters.yaml @@ -275,12 +275,30 @@ spec: AdditionalListenerSpec defines the desired state of an additional listener on an VPC load balancer. properties: + defaultPoolName: + description: defaultPoolName defines the name of a VPC + Load Balancer Backend Pool to use for the VPC Load Balancer + Listener. + maxLength: 63 + minLength: 1 + pattern: ^([a-z]|[a-z][-a-z0-9]*[a-z0-9])$ + type: string port: description: Port sets the port for the additional listener. format: int64 maximum: 65535 minimum: 1 type: integer + protocol: + description: |- + protocol defines the protocol to use for the VPC Load Balancer Listener. + Will default to TCP protocol if not specified. + enum: + - http + - https + - tcp + - udp + type: string required: - port type: object @@ -288,6 +306,93 @@ spec: x-kubernetes-list-map-keys: - port x-kubernetes-list-type: map + backendPools: + description: backendPools defines the load balancer's backend + pools. + items: + description: VPCLoadBalancerBackendPoolSpec defines the desired + configuration of a VPC Load Balancer Backend Pool. + properties: + algorithm: + description: algorithm defines the load balancing algorithm + to use. + enum: + - least_connections + - round_robin + - weighted_round_robin + type: string + healthMonitor: + description: healthMonitor defines the backend pool's + health monitor. + properties: + delay: + description: delay defines the seconds to wait between + health checks. + format: int64 + maximum: 60 + minimum: 2 + type: integer + port: + description: port defines the port to perform health + monitoring on. + format: int64 + maximum: 65535 + minimum: 1 + type: integer + retries: + description: retries defines the max retries for health + check. + format: int64 + maximum: 10 + minimum: 1 + type: integer + timeout: + description: timeout defines the seconds to wait for + a health check response. + format: int64 + maximum: 59 + minimum: 1 + type: integer + type: + description: type defines the protocol used for health + checks. + enum: + - http + - https + - tcp + type: string + urlPath: + description: urlPath defines the URL to use for health + monitoring. + pattern: ^\/(([a-zA-Z0-9-._~!$&'()*+,;=:@]|%[a-fA-F0-9]{2})+(\/([a-zA-Z0-9-._~!$&'()*+,;=:@]|%[a-fA-F0-9]{2})*)*)?(\\?([a-zA-Z0-9-._~!$&'()*+,;=:@\/?]|%[a-fA-F0-9]{2})*)?$ + type: string + required: + - delay + - retries + - timeout + - type + type: object + name: + description: name defines the name of the Backend Pool. + maxLength: 63 + minLength: 1 + pattern: ^([a-z]|[a-z][-a-z0-9]*[a-z0-9])$ + type: string + protocol: + description: protocol defines the protocol to use for + the Backend Pool. + enum: + - http + - https + - tcp + - udp + type: string + required: + - algorithm + - healthMonitor + - protocol + type: object + type: array id: description: id of the loadbalancer maxLength: 64 @@ -305,6 +410,46 @@ spec: description: public indicates that load balancer is public or private type: boolean + securityGroups: + description: |- + securityGroups defines the Security Groups to attach to the load balancer. + Security Groups defined here are expected to already exist when the load balancer is reconciled (these do not get created when reconciling the load balancer). + items: + description: VPCResource represents a VPC resource. + properties: + id: + description: id of the resource. + minLength: 1 + type: string + name: + description: name of the resource. + minLength: 1 + type: string + type: object + x-kubernetes-validations: + - message: an id or name must be provided + rule: has(self.id) || has(self.name) + type: array + subnets: + description: |- + subnets defines the VPC Subnets to attach to the load balancer. + Subnets defiens here are expected to already exist when the load balancer is reconciled (these do not get created when reconciling the load balancer). + items: + description: VPCResource represents a VPC resource. + properties: + id: + description: id of the resource. + minLength: 1 + type: string + name: + description: name of the resource. + minLength: 1 + type: string + type: object + x-kubernetes-validations: + - message: an id or name must be provided + rule: has(self.id) || has(self.name) + type: array type: object type: array network: diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_ibmpowervsclustertemplates.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_ibmpowervsclustertemplates.yaml index 183db4202..b95b66781 100644 --- a/config/crd/bases/infrastructure.cluster.x-k8s.io_ibmpowervsclustertemplates.yaml +++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_ibmpowervsclustertemplates.yaml @@ -305,6 +305,14 @@ spec: AdditionalListenerSpec defines the desired state of an additional listener on an VPC load balancer. properties: + defaultPoolName: + description: defaultPoolName defines the name + of a VPC Load Balancer Backend Pool to use for + the VPC Load Balancer Listener. + maxLength: 63 + minLength: 1 + pattern: ^([a-z]|[a-z][-a-z0-9]*[a-z0-9])$ + type: string port: description: Port sets the port for the additional listener. @@ -312,6 +320,16 @@ spec: maximum: 65535 minimum: 1 type: integer + protocol: + description: |- + protocol defines the protocol to use for the VPC Load Balancer Listener. + Will default to TCP protocol if not specified. + enum: + - http + - https + - tcp + - udp + type: string required: - port type: object @@ -319,6 +337,95 @@ spec: x-kubernetes-list-map-keys: - port x-kubernetes-list-type: map + backendPools: + description: backendPools defines the load balancer's + backend pools. + items: + description: VPCLoadBalancerBackendPoolSpec defines + the desired configuration of a VPC Load Balancer + Backend Pool. + properties: + algorithm: + description: algorithm defines the load balancing + algorithm to use. + enum: + - least_connections + - round_robin + - weighted_round_robin + type: string + healthMonitor: + description: healthMonitor defines the backend + pool's health monitor. + properties: + delay: + description: delay defines the seconds to + wait between health checks. + format: int64 + maximum: 60 + minimum: 2 + type: integer + port: + description: port defines the port to perform + health monitoring on. + format: int64 + maximum: 65535 + minimum: 1 + type: integer + retries: + description: retries defines the max retries + for health check. + format: int64 + maximum: 10 + minimum: 1 + type: integer + timeout: + description: timeout defines the seconds to + wait for a health check response. + format: int64 + maximum: 59 + minimum: 1 + type: integer + type: + description: type defines the protocol used + for health checks. + enum: + - http + - https + - tcp + type: string + urlPath: + description: urlPath defines the URL to use + for health monitoring. + pattern: ^\/(([a-zA-Z0-9-._~!$&'()*+,;=:@]|%[a-fA-F0-9]{2})+(\/([a-zA-Z0-9-._~!$&'()*+,;=:@]|%[a-fA-F0-9]{2})*)*)?(\\?([a-zA-Z0-9-._~!$&'()*+,;=:@\/?]|%[a-fA-F0-9]{2})*)?$ + type: string + required: + - delay + - retries + - timeout + - type + type: object + name: + description: name defines the name of the Backend + Pool. + maxLength: 63 + minLength: 1 + pattern: ^([a-z]|[a-z][-a-z0-9]*[a-z0-9])$ + type: string + protocol: + description: protocol defines the protocol to + use for the Backend Pool. + enum: + - http + - https + - tcp + - udp + type: string + required: + - algorithm + - healthMonitor + - protocol + type: object + type: array id: description: id of the loadbalancer maxLength: 64 @@ -336,6 +443,46 @@ spec: description: public indicates that load balancer is public or private type: boolean + securityGroups: + description: |- + securityGroups defines the Security Groups to attach to the load balancer. + Security Groups defined here are expected to already exist when the load balancer is reconciled (these do not get created when reconciling the load balancer). + items: + description: VPCResource represents a VPC resource. + properties: + id: + description: id of the resource. + minLength: 1 + type: string + name: + description: name of the resource. + minLength: 1 + type: string + type: object + x-kubernetes-validations: + - message: an id or name must be provided + rule: has(self.id) || has(self.name) + type: array + subnets: + description: |- + subnets defines the VPC Subnets to attach to the load balancer. + Subnets defiens here are expected to already exist when the load balancer is reconciled (these do not get created when reconciling the load balancer). + items: + description: VPCResource represents a VPC resource. + properties: + id: + description: id of the resource. + minLength: 1 + type: string + name: + description: name of the resource. + minLength: 1 + type: string + type: object + x-kubernetes-validations: + - message: an id or name must be provided + rule: has(self.id) || has(self.name) + type: array type: object type: array network: diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_ibmvpcclusters.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_ibmvpcclusters.yaml index d487dc7ff..b2d46580e 100644 --- a/config/crd/bases/infrastructure.cluster.x-k8s.io_ibmvpcclusters.yaml +++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_ibmvpcclusters.yaml @@ -248,8 +248,9 @@ spec: - port type: object controlPlaneLoadBalancer: - description: ControlPlaneLoadBalancer is optional configuration for - customizing control plane behavior. + description: |- + ControlPlaneLoadBalancer is optional configuration for customizing control plane behavior. + Use this for legacy support, use Network.LoadBalancers for the extended VPC support. properties: additionalListeners: description: AdditionalListeners sets the additional listeners @@ -259,12 +260,30 @@ spec: AdditionalListenerSpec defines the desired state of an additional listener on an VPC load balancer. properties: + defaultPoolName: + description: defaultPoolName defines the name of a VPC Load + Balancer Backend Pool to use for the VPC Load Balancer + Listener. + maxLength: 63 + minLength: 1 + pattern: ^([a-z]|[a-z][-a-z0-9]*[a-z0-9])$ + type: string port: description: Port sets the port for the additional listener. format: int64 maximum: 65535 minimum: 1 type: integer + protocol: + description: |- + protocol defines the protocol to use for the VPC Load Balancer Listener. + Will default to TCP protocol if not specified. + enum: + - http + - https + - tcp + - udp + type: string required: - port type: object @@ -272,6 +291,93 @@ spec: x-kubernetes-list-map-keys: - port x-kubernetes-list-type: map + backendPools: + description: backendPools defines the load balancer's backend + pools. + items: + description: VPCLoadBalancerBackendPoolSpec defines the desired + configuration of a VPC Load Balancer Backend Pool. + properties: + algorithm: + description: algorithm defines the load balancing algorithm + to use. + enum: + - least_connections + - round_robin + - weighted_round_robin + type: string + healthMonitor: + description: healthMonitor defines the backend pool's health + monitor. + properties: + delay: + description: delay defines the seconds to wait between + health checks. + format: int64 + maximum: 60 + minimum: 2 + type: integer + port: + description: port defines the port to perform health + monitoring on. + format: int64 + maximum: 65535 + minimum: 1 + type: integer + retries: + description: retries defines the max retries for health + check. + format: int64 + maximum: 10 + minimum: 1 + type: integer + timeout: + description: timeout defines the seconds to wait for + a health check response. + format: int64 + maximum: 59 + minimum: 1 + type: integer + type: + description: type defines the protocol used for health + checks. + enum: + - http + - https + - tcp + type: string + urlPath: + description: urlPath defines the URL to use for health + monitoring. + pattern: ^\/(([a-zA-Z0-9-._~!$&'()*+,;=:@]|%[a-fA-F0-9]{2})+(\/([a-zA-Z0-9-._~!$&'()*+,;=:@]|%[a-fA-F0-9]{2})*)*)?(\\?([a-zA-Z0-9-._~!$&'()*+,;=:@\/?]|%[a-fA-F0-9]{2})*)?$ + type: string + required: + - delay + - retries + - timeout + - type + type: object + name: + description: name defines the name of the Backend Pool. + maxLength: 63 + minLength: 1 + pattern: ^([a-z]|[a-z][-a-z0-9]*[a-z0-9])$ + type: string + protocol: + description: protocol defines the protocol to use for the + Backend Pool. + enum: + - http + - https + - tcp + - udp + type: string + required: + - algorithm + - healthMonitor + - protocol + type: object + type: array id: description: id of the loadbalancer maxLength: 64 @@ -289,7 +395,103 @@ spec: description: public indicates that load balancer is public or private type: boolean + securityGroups: + description: |- + securityGroups defines the Security Groups to attach to the load balancer. + Security Groups defined here are expected to already exist when the load balancer is reconciled (these do not get created when reconciling the load balancer). + items: + description: VPCResource represents a VPC resource. + properties: + id: + description: id of the resource. + minLength: 1 + type: string + name: + description: name of the resource. + minLength: 1 + type: string + type: object + x-kubernetes-validations: + - message: an id or name must be provided + rule: has(self.id) || has(self.name) + type: array + subnets: + description: |- + subnets defines the VPC Subnets to attach to the load balancer. + Subnets defiens here are expected to already exist when the load balancer is reconciled (these do not get created when reconciling the load balancer). + items: + description: VPCResource represents a VPC resource. + properties: + id: + description: id of the resource. + minLength: 1 + type: string + name: + description: name of the resource. + minLength: 1 + type: string + type: object + x-kubernetes-validations: + - message: an id or name must be provided + rule: has(self.id) || has(self.name) + type: array type: object + image: + description: image represents the Image details used for the cluster. + properties: + cosBucket: + description: cosBucket is the name of the IBM Cloud COS Bucket + containing the source of the image, if necessary. + type: string + cosBucketRegion: + description: cosBucketRegion is the COS region the bucket is in. + type: string + cosInstance: + description: cosInstance is the name of the IBM Cloud COS Instance + containing the source of the image, if necessary. + type: string + cosObject: + description: cosObject is the name of a IBM Cloud COS Object used + as the source of the image, if necessary. + type: string + crn: + description: crn is the IBM Cloud CRN of the existing VPC Custom + Image. + type: string + name: + description: name is the name of the desired VPC Custom Image. + maxLength: 63 + minLength: 1 + pattern: '''/^([a-z]|[a-z][-a-z0-9]*[a-z0-9])$/''' + type: string + operatingSystem: + description: operatingSystem is the Custom Image's Operating System + name. + type: string + resourceGroup: + description: resourceGroup is the Resource Group to create the + Custom Image in. + properties: + id: + description: id defines the IBM Cloud Resource ID. + type: string + name: + description: name defines the IBM Cloud Resource Name. + type: string + required: + - id + type: object + type: object + x-kubernetes-validations: + - message: if any of cosInstance, cosBucket, or cosObject are specified, + all must be specified + rule: (!has(self.cosInstance) && !has(self.cosBucket) && !has(self.cosObject)) + || (has(self.cosInstance) && has(self.cosBucket) && has(self.cosObject)) + - message: an existing image name or crn must be provided, or to create + a new image the cos resources must be provided, with or without + a name + rule: has(self.name) || has(self.crn) || (has(self.cosInstance) + && has(self.cosBucket) && has(self.cosObject)) network: description: network represents the VPC network to use for the cluster. properties: @@ -315,11 +517,542 @@ spec: type: string type: object type: array + loadBalancers: + description: loadBalancers is a set of VPC Load Balancer definitions + to use for the cluster. + items: + description: VPCLoadBalancerSpec defines the desired state of + an VPC load balancer. + properties: + additionalListeners: + description: AdditionalListeners sets the additional listeners + for the control plane load balancer. + items: + description: |- + AdditionalListenerSpec defines the desired state of an + additional listener on an VPC load balancer. + properties: + defaultPoolName: + description: defaultPoolName defines the name of a + VPC Load Balancer Backend Pool to use for the VPC + Load Balancer Listener. + maxLength: 63 + minLength: 1 + pattern: ^([a-z]|[a-z][-a-z0-9]*[a-z0-9])$ + type: string + port: + description: Port sets the port for the additional + listener. + format: int64 + maximum: 65535 + minimum: 1 + type: integer + protocol: + description: |- + protocol defines the protocol to use for the VPC Load Balancer Listener. + Will default to TCP protocol if not specified. + enum: + - http + - https + - tcp + - udp + type: string + required: + - port + type: object + type: array + x-kubernetes-list-map-keys: + - port + x-kubernetes-list-type: map + backendPools: + description: backendPools defines the load balancer's backend + pools. + items: + description: VPCLoadBalancerBackendPoolSpec defines the + desired configuration of a VPC Load Balancer Backend + Pool. + properties: + algorithm: + description: algorithm defines the load balancing + algorithm to use. + enum: + - least_connections + - round_robin + - weighted_round_robin + type: string + healthMonitor: + description: healthMonitor defines the backend pool's + health monitor. + properties: + delay: + description: delay defines the seconds to wait + between health checks. + format: int64 + maximum: 60 + minimum: 2 + type: integer + port: + description: port defines the port to perform + health monitoring on. + format: int64 + maximum: 65535 + minimum: 1 + type: integer + retries: + description: retries defines the max retries for + health check. + format: int64 + maximum: 10 + minimum: 1 + type: integer + timeout: + description: timeout defines the seconds to wait + for a health check response. + format: int64 + maximum: 59 + minimum: 1 + type: integer + type: + description: type defines the protocol used for + health checks. + enum: + - http + - https + - tcp + type: string + urlPath: + description: urlPath defines the URL to use for + health monitoring. + pattern: ^\/(([a-zA-Z0-9-._~!$&'()*+,;=:@]|%[a-fA-F0-9]{2})+(\/([a-zA-Z0-9-._~!$&'()*+,;=:@]|%[a-fA-F0-9]{2})*)*)?(\\?([a-zA-Z0-9-._~!$&'()*+,;=:@\/?]|%[a-fA-F0-9]{2})*)?$ + type: string + required: + - delay + - retries + - timeout + - type + type: object + name: + description: name defines the name of the Backend + Pool. + maxLength: 63 + minLength: 1 + pattern: ^([a-z]|[a-z][-a-z0-9]*[a-z0-9])$ + type: string + protocol: + description: protocol defines the protocol to use + for the Backend Pool. + enum: + - http + - https + - tcp + - udp + type: string + required: + - algorithm + - healthMonitor + - protocol + type: object + type: array + id: + description: id of the loadbalancer + maxLength: 64 + minLength: 1 + pattern: ^[-0-9a-z_]+$ + type: string + name: + description: Name sets the name of the VPC load balancer. + maxLength: 63 + minLength: 1 + pattern: ^([a-z]|[a-z][-a-z0-9]*[a-z0-9])$ + type: string + public: + default: true + description: public indicates that load balancer is public + or private + type: boolean + securityGroups: + description: |- + securityGroups defines the Security Groups to attach to the load balancer. + Security Groups defined here are expected to already exist when the load balancer is reconciled (these do not get created when reconciling the load balancer). + items: + description: VPCResource represents a VPC resource. + properties: + id: + description: id of the resource. + minLength: 1 + type: string + name: + description: name of the resource. + minLength: 1 + type: string + type: object + x-kubernetes-validations: + - message: an id or name must be provided + rule: has(self.id) || has(self.name) + type: array + subnets: + description: |- + subnets defines the VPC Subnets to attach to the load balancer. + Subnets defiens here are expected to already exist when the load balancer is reconciled (these do not get created when reconciling the load balancer). + items: + description: VPCResource represents a VPC resource. + properties: + id: + description: id of the resource. + minLength: 1 + type: string + name: + description: name of the resource. + minLength: 1 + type: string + type: object + x-kubernetes-validations: + - message: an id or name must be provided + rule: has(self.id) || has(self.name) + type: array + type: object + type: array resourceGroup: description: |- - resourceGroup is the name of the Resource Group containing all of the newtork resources. + resourceGroup is the Resource Group containing all of the newtork resources. This can be different than the Resource Group containing the remaining cluster resources. - type: string + properties: + id: + description: id defines the IBM Cloud Resource ID. + type: string + name: + description: name defines the IBM Cloud Resource Name. + type: string + required: + - id + type: object + securityGroups: + description: securityGroups is a set of VPCSecurityGroup's which + define the VPC Security Groups that manage traffic within and + out of the VPC. + items: + description: VPCSecurityGroup defines a VPC Security Group that + should exist or be created within the specified VPC, with + the specified Security Group Rules. + properties: + id: + description: id of the Security Group. + type: string + name: + description: name of the Security Group. + type: string + rules: + description: rules are the Security Group Rules for the + Security Group. + items: + description: VPCSecurityGroupRule defines a VPC Security + Group Rule for a specified Security Group. + properties: + action: + description: action defines whether to allow or deny + traffic defined by the Security Group Rule. + enum: + - allow + - deny + type: string + destination: + description: |- + destination is a VPCSecurityGroupRulePrototype which defines the destination of outbound traffic for the Security Group Rule. + Only used when direction is VPCSecurityGroupRuleDirectionOutbound. + properties: + icmpCode: + description: |- + icmpCode is the ICMP code for the Rule. + Only used when Protocol is VPCSecurityGroupRuleProtocolIcmp. + format: int64 + type: integer + icmpType: + description: |- + icmpType is the ICMP type for the Rule. + Only used when Protocol is VPCSecurityGroupRuleProtocolIcmp. + format: int64 + type: integer + portRange: + description: portRange is a range of ports allowed + for the Rule's remote. + properties: + maximumPort: + description: maximumPort is the inclusive + upper range of ports. + format: int64 + maximum: 65535 + minimum: 1 + type: integer + minimumPort: + description: minimumPort is the inclusive + lower range of ports. + format: int64 + maximum: 65535 + minimum: 1 + type: integer + type: object + x-kubernetes-validations: + - message: maximum port must be greater than or + equal to minimum port + rule: self.maximumPort >= self.minimumPort + protocol: + description: protocol defines the traffic protocol + used for the Security Group Rule. + enum: + - all + - icmp + - tcp + - udp + type: string + remotes: + description: |- + remotes is a set of VPCSecurityGroupRuleRemote's that define the traffic allowed by the Rule's remote. + Specifying multiple VPCSecurityGroupRuleRemote's creates a unique Security Group Rule with the shared Protocol, PortRange, etc. + This allows for easier management of Security Group Rule's for sets of CIDR's, IP's, etc. + items: + description: |- + VPCSecurityGroupRuleRemote defines a VPC Security Group Rule's remote details. + The type of remote defines the additional remote details where are used for defining the remote. + properties: + address: + description: |2- + address is the address to use for the remote's destination/source. + Only used when remoteType is VPCSecurityGroupRuleRemoteTypeAddress. + type: string + cidrSubnetName: + description: |- + cidrSubnetName is the name of the VPC Subnet to retrieve the CIDR from, to use for the remote's destination/source. + Only used when remoteType is VPCSecurityGroupRuleRemoteTypeCIDR. + type: string + remoteType: + description: remoteType defines the type + of filter to define for the remote's destination/source. + enum: + - any + - cidr + - address + - sg + type: string + securityGroupName: + description: |- + securityGroupName is the name of the VPC Security Group to use for the remote's destination/source. + Only used when remoteType is VPCSecurityGroupRuleRemoteTypeSG + type: string + required: + - remoteType + type: object + x-kubernetes-validations: + - message: cidrSubnetName, addresss, and securityGroupName + are not valid for VPCSecurityGroupRuleRemoteTypeAny + remoteType + rule: 'self.remoteType == ''any'' ? (!has(self.cidrSubnetName) + && !has(self.address) && !has(self.securityGroupName)) + : true' + - message: only cidrSubnetName is valid for + VPCSecurityGroupRuleRemoteTypeCIDR remoteType + rule: 'self.remoteType == ''cidr'' ? (has(self.cidrSubnetName) + && !has(self.address) && !has(self.securityGroupName)) + : true' + - message: only address is valid for VPCSecurityGroupRuleRemoteTypeIP + remoteType + rule: 'self.remoteType == ''address'' ? (has(self.address) + && !has(self.cidrSubnetName) && !has(self.securityGroupName)) + : true' + - message: only securityGroupName is valid for + VPCSecurityGroupRuleRemoteTypeSG remoteType + rule: 'self.remoteType == ''sg'' ? (has(self.securityGroupName) + && !has(self.cidrSubnetName) && !has(self.address)) + : true' + type: array + required: + - protocol + - remotes + type: object + x-kubernetes-validations: + - message: icmpCode and icmpType are only supported + for VPCSecurityGroupRuleProtocolIcmp protocol + rule: 'self.protocol != ''icmp'' ? (!has(self.icmpCode) + && !has(self.icmpType)) : true' + - message: portRange is not valid for VPCSecurityGroupRuleProtocolAll + protocol + rule: 'self.protocol == ''all'' ? !has(self.portRange) + : true' + - message: portRange is not valid for VPCSecurityGroupRuleProtocolIcmp + protocol + rule: 'self.protocol == ''icmp'' ? !has(self.portRange) + : true' + direction: + description: direction defines whether the traffic + is inbound or outbound for the Security Group Rule. + enum: + - inbound + - outbound + type: string + securityGroupID: + description: securityGroupID is the ID of the Security + Group for the Security Group Rule. + type: string + source: + description: |- + source is a VPCSecurityGroupRulePrototype which defines the source of inbound traffic for the Security Group Rule. + Only used when direction is VPCSecurityGroupRuleDirectionInbound. + properties: + icmpCode: + description: |- + icmpCode is the ICMP code for the Rule. + Only used when Protocol is VPCSecurityGroupRuleProtocolIcmp. + format: int64 + type: integer + icmpType: + description: |- + icmpType is the ICMP type for the Rule. + Only used when Protocol is VPCSecurityGroupRuleProtocolIcmp. + format: int64 + type: integer + portRange: + description: portRange is a range of ports allowed + for the Rule's remote. + properties: + maximumPort: + description: maximumPort is the inclusive + upper range of ports. + format: int64 + maximum: 65535 + minimum: 1 + type: integer + minimumPort: + description: minimumPort is the inclusive + lower range of ports. + format: int64 + maximum: 65535 + minimum: 1 + type: integer + type: object + x-kubernetes-validations: + - message: maximum port must be greater than or + equal to minimum port + rule: self.maximumPort >= self.minimumPort + protocol: + description: protocol defines the traffic protocol + used for the Security Group Rule. + enum: + - all + - icmp + - tcp + - udp + type: string + remotes: + description: |- + remotes is a set of VPCSecurityGroupRuleRemote's that define the traffic allowed by the Rule's remote. + Specifying multiple VPCSecurityGroupRuleRemote's creates a unique Security Group Rule with the shared Protocol, PortRange, etc. + This allows for easier management of Security Group Rule's for sets of CIDR's, IP's, etc. + items: + description: |- + VPCSecurityGroupRuleRemote defines a VPC Security Group Rule's remote details. + The type of remote defines the additional remote details where are used for defining the remote. + properties: + address: + description: |2- + address is the address to use for the remote's destination/source. + Only used when remoteType is VPCSecurityGroupRuleRemoteTypeAddress. + type: string + cidrSubnetName: + description: |- + cidrSubnetName is the name of the VPC Subnet to retrieve the CIDR from, to use for the remote's destination/source. + Only used when remoteType is VPCSecurityGroupRuleRemoteTypeCIDR. + type: string + remoteType: + description: remoteType defines the type + of filter to define for the remote's destination/source. + enum: + - any + - cidr + - address + - sg + type: string + securityGroupName: + description: |- + securityGroupName is the name of the VPC Security Group to use for the remote's destination/source. + Only used when remoteType is VPCSecurityGroupRuleRemoteTypeSG + type: string + required: + - remoteType + type: object + x-kubernetes-validations: + - message: cidrSubnetName, addresss, and securityGroupName + are not valid for VPCSecurityGroupRuleRemoteTypeAny + remoteType + rule: 'self.remoteType == ''any'' ? (!has(self.cidrSubnetName) + && !has(self.address) && !has(self.securityGroupName)) + : true' + - message: only cidrSubnetName is valid for + VPCSecurityGroupRuleRemoteTypeCIDR remoteType + rule: 'self.remoteType == ''cidr'' ? (has(self.cidrSubnetName) + && !has(self.address) && !has(self.securityGroupName)) + : true' + - message: only address is valid for VPCSecurityGroupRuleRemoteTypeIP + remoteType + rule: 'self.remoteType == ''address'' ? (has(self.address) + && !has(self.cidrSubnetName) && !has(self.securityGroupName)) + : true' + - message: only securityGroupName is valid for + VPCSecurityGroupRuleRemoteTypeSG remoteType + rule: 'self.remoteType == ''sg'' ? (has(self.securityGroupName) + && !has(self.cidrSubnetName) && !has(self.address)) + : true' + type: array + required: + - protocol + - remotes + type: object + x-kubernetes-validations: + - message: icmpCode and icmpType are only supported + for VPCSecurityGroupRuleProtocolIcmp protocol + rule: 'self.protocol != ''icmp'' ? (!has(self.icmpCode) + && !has(self.icmpType)) : true' + - message: portRange is not valid for VPCSecurityGroupRuleProtocolAll + protocol + rule: 'self.protocol == ''all'' ? !has(self.portRange) + : true' + - message: portRange is not valid for VPCSecurityGroupRuleProtocolIcmp + protocol + rule: 'self.protocol == ''icmp'' ? !has(self.portRange) + : true' + required: + - action + - direction + type: object + x-kubernetes-validations: + - message: both destination and source cannot be provided + rule: (has(self.destination) && !has(self.source)) || + (!has(self.destination) && has(self.source)) + - message: source must be set for VPCSecurityGroupRuleDirectionInbound + direction + rule: 'self.direction == ''inbound'' ? has(self.source) + : true' + - message: destination is not valid for VPCSecurityGroupRuleDirectionInbound + direction + rule: 'self.direction == ''inbound'' ? !has(self.destination) + : true' + - message: destination must be set for VPCSecurityGroupRuleDirectionOutbound + direction + rule: 'self.direction == ''outbound'' ? has(self.destination) + : true' + - message: source is not valid for VPCSecurityGroupRuleDirectionOutbound + direction + rule: 'self.direction == ''outbound'' ? !has(self.source) + : true' + type: array + tags: + description: tags are tags to add to the Security Group. + items: + type: string + type: array + type: object + x-kubernetes-validations: + - message: either an id or name must be specified + rule: has(self.id) || has(self.name) + type: array vpc: description: vpc defines the IBM Cloud VPC for extended VPC Infrastructure support. @@ -429,10 +1162,100 @@ spec: description: ControlPlaneLoadBalancerState is the status of the load balancer. type: string + image: + description: image is the status of the VPC Custom Image. + properties: + id: + description: id defines the Id of the IBM Cloud resource status. + type: string + name: + description: name defines the name of the IBM Cloud resource status. + type: string + ready: + description: ready defines whether the IBM Cloud resource is ready. + type: boolean + required: + - id + - ready + type: object network: description: network is the status of the VPC network resources for extended VPC Infrastructure support. properties: + controlPlaneSubnets: + additionalProperties: + description: ResourceStatus identifies a resource by id (and + name) and whether it is ready. + properties: + id: + description: id defines the Id of the IBM Cloud resource + status. + type: string + name: + description: name defines the name of the IBM Cloud resource + status. + type: string + ready: + description: ready defines whether the IBM Cloud resource + is ready. + type: boolean + required: + - id + - ready + type: object + description: |- + controlPlaneSubnets references the VPC Subnets for the cluster's Control Plane. + The map simplifies lookups. + type: object + loadBalancers: + additionalProperties: + description: VPCLoadBalancerStatus defines the status VPC load + balancer. + properties: + controllerCreated: + default: false + description: controllerCreated indicates whether the resource + is created by the controller. + type: boolean + hostname: + description: hostname is the hostname of load balancer. + type: string + id: + description: id of VPC load balancer. + type: string + state: + description: State is the status of the load balancer. + type: string + type: object + description: |- + loadBalancers references the VPC Load Balancer's for the cluster. + The map simplifies lookups. + type: object + publicGateways: + additionalProperties: + description: ResourceStatus identifies a resource by id (and + name) and whether it is ready. + properties: + id: + description: id defines the Id of the IBM Cloud resource + status. + type: string + name: + description: name defines the name of the IBM Cloud resource + status. + type: string + ready: + description: ready defines whether the IBM Cloud resource + is ready. + type: boolean + required: + - id + - ready + type: object + description: |- + publicGateways references the VPC Public Gateways for the cluster. + The map simplifies lookups. + type: object resourceGroup: description: |- resourceGroup references the Resource Group for Network resources for the cluster. @@ -453,6 +1276,31 @@ spec: - id - ready type: object + securityGroups: + additionalProperties: + description: ResourceStatus identifies a resource by id (and + name) and whether it is ready. + properties: + id: + description: id defines the Id of the IBM Cloud resource + status. + type: string + name: + description: name defines the name of the IBM Cloud resource + status. + type: string + ready: + description: ready defines whether the IBM Cloud resource + is ready. + type: boolean + required: + - id + - ready + type: object + description: |- + securityGroups references the VPC Security Groups for the cluster. + The map simplifies lookups. + type: object vpc: description: vpc references the status of the IBM Cloud VPC as part of the extended VPC Infrastructure support. @@ -472,6 +1320,31 @@ spec: - id - ready type: object + workerSubnets: + additionalProperties: + description: ResourceStatus identifies a resource by id (and + name) and whether it is ready. + properties: + id: + description: id defines the Id of the IBM Cloud resource + status. + type: string + name: + description: name defines the name of the IBM Cloud resource + status. + type: string + ready: + description: ready defines whether the IBM Cloud resource + is ready. + type: boolean + required: + - id + - ready + type: object + description: |- + workerSubnets references the VPC Subnets for the cluster's Data Plane. + The map simplifies lookups. + type: object type: object ready: default: false @@ -514,7 +1387,6 @@ spec: type: object vpc: description: |- - INSERT ADDITIONAL STATUS FIELD - define observed state of cluster Important: Run "make" to regenerate code after modifying this file dep: rely on Network instead. properties: diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_ibmvpcclustertemplates.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_ibmvpcclustertemplates.yaml index f75f70bf3..c4dbff0b2 100644 --- a/config/crd/bases/infrastructure.cluster.x-k8s.io_ibmvpcclustertemplates.yaml +++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_ibmvpcclustertemplates.yaml @@ -96,8 +96,9 @@ spec: - port type: object controlPlaneLoadBalancer: - description: ControlPlaneLoadBalancer is optional configuration - for customizing control plane behavior. + description: |- + ControlPlaneLoadBalancer is optional configuration for customizing control plane behavior. + Use this for legacy support, use Network.LoadBalancers for the extended VPC support. properties: additionalListeners: description: AdditionalListeners sets the additional listeners @@ -107,6 +108,14 @@ spec: AdditionalListenerSpec defines the desired state of an additional listener on an VPC load balancer. properties: + defaultPoolName: + description: defaultPoolName defines the name of + a VPC Load Balancer Backend Pool to use for the + VPC Load Balancer Listener. + maxLength: 63 + minLength: 1 + pattern: ^([a-z]|[a-z][-a-z0-9]*[a-z0-9])$ + type: string port: description: Port sets the port for the additional listener. @@ -114,6 +123,16 @@ spec: maximum: 65535 minimum: 1 type: integer + protocol: + description: |- + protocol defines the protocol to use for the VPC Load Balancer Listener. + Will default to TCP protocol if not specified. + enum: + - http + - https + - tcp + - udp + type: string required: - port type: object @@ -121,6 +140,95 @@ spec: x-kubernetes-list-map-keys: - port x-kubernetes-list-type: map + backendPools: + description: backendPools defines the load balancer's + backend pools. + items: + description: VPCLoadBalancerBackendPoolSpec defines + the desired configuration of a VPC Load Balancer Backend + Pool. + properties: + algorithm: + description: algorithm defines the load balancing + algorithm to use. + enum: + - least_connections + - round_robin + - weighted_round_robin + type: string + healthMonitor: + description: healthMonitor defines the backend pool's + health monitor. + properties: + delay: + description: delay defines the seconds to wait + between health checks. + format: int64 + maximum: 60 + minimum: 2 + type: integer + port: + description: port defines the port to perform + health monitoring on. + format: int64 + maximum: 65535 + minimum: 1 + type: integer + retries: + description: retries defines the max retries + for health check. + format: int64 + maximum: 10 + minimum: 1 + type: integer + timeout: + description: timeout defines the seconds to + wait for a health check response. + format: int64 + maximum: 59 + minimum: 1 + type: integer + type: + description: type defines the protocol used + for health checks. + enum: + - http + - https + - tcp + type: string + urlPath: + description: urlPath defines the URL to use + for health monitoring. + pattern: ^\/(([a-zA-Z0-9-._~!$&'()*+,;=:@]|%[a-fA-F0-9]{2})+(\/([a-zA-Z0-9-._~!$&'()*+,;=:@]|%[a-fA-F0-9]{2})*)*)?(\\?([a-zA-Z0-9-._~!$&'()*+,;=:@\/?]|%[a-fA-F0-9]{2})*)?$ + type: string + required: + - delay + - retries + - timeout + - type + type: object + name: + description: name defines the name of the Backend + Pool. + maxLength: 63 + minLength: 1 + pattern: ^([a-z]|[a-z][-a-z0-9]*[a-z0-9])$ + type: string + protocol: + description: protocol defines the protocol to use + for the Backend Pool. + enum: + - http + - https + - tcp + - udp + type: string + required: + - algorithm + - healthMonitor + - protocol + type: object + type: array id: description: id of the loadbalancer maxLength: 64 @@ -138,7 +246,108 @@ spec: description: public indicates that load balancer is public or private type: boolean + securityGroups: + description: |- + securityGroups defines the Security Groups to attach to the load balancer. + Security Groups defined here are expected to already exist when the load balancer is reconciled (these do not get created when reconciling the load balancer). + items: + description: VPCResource represents a VPC resource. + properties: + id: + description: id of the resource. + minLength: 1 + type: string + name: + description: name of the resource. + minLength: 1 + type: string + type: object + x-kubernetes-validations: + - message: an id or name must be provided + rule: has(self.id) || has(self.name) + type: array + subnets: + description: |- + subnets defines the VPC Subnets to attach to the load balancer. + Subnets defiens here are expected to already exist when the load balancer is reconciled (these do not get created when reconciling the load balancer). + items: + description: VPCResource represents a VPC resource. + properties: + id: + description: id of the resource. + minLength: 1 + type: string + name: + description: name of the resource. + minLength: 1 + type: string + type: object + x-kubernetes-validations: + - message: an id or name must be provided + rule: has(self.id) || has(self.name) + type: array + type: object + image: + description: image represents the Image details used for the + cluster. + properties: + cosBucket: + description: cosBucket is the name of the IBM Cloud COS + Bucket containing the source of the image, if necessary. + type: string + cosBucketRegion: + description: cosBucketRegion is the COS region the bucket + is in. + type: string + cosInstance: + description: cosInstance is the name of the IBM Cloud + COS Instance containing the source of the image, if + necessary. + type: string + cosObject: + description: cosObject is the name of a IBM Cloud COS + Object used as the source of the image, if necessary. + type: string + crn: + description: crn is the IBM Cloud CRN of the existing + VPC Custom Image. + type: string + name: + description: name is the name of the desired VPC Custom + Image. + maxLength: 63 + minLength: 1 + pattern: '''/^([a-z]|[a-z][-a-z0-9]*[a-z0-9])$/''' + type: string + operatingSystem: + description: operatingSystem is the Custom Image's Operating + System name. + type: string + resourceGroup: + description: resourceGroup is the Resource Group to create + the Custom Image in. + properties: + id: + description: id defines the IBM Cloud Resource ID. + type: string + name: + description: name defines the IBM Cloud Resource Name. + type: string + required: + - id + type: object type: object + x-kubernetes-validations: + - message: if any of cosInstance, cosBucket, or cosObject + are specified, all must be specified + rule: (!has(self.cosInstance) && !has(self.cosBucket) && + !has(self.cosObject)) || (has(self.cosInstance) && has(self.cosBucket) + && has(self.cosObject)) + - message: an existing image name or crn must be provided, + or to create a new image the cos resources must be provided, + with or without a name + rule: has(self.name) || has(self.crn) || (has(self.cosInstance) + && has(self.cosBucket) && has(self.cosObject)) network: description: network represents the VPC network to use for the cluster. @@ -165,11 +374,571 @@ spec: type: string type: object type: array + loadBalancers: + description: loadBalancers is a set of VPC Load Balancer + definitions to use for the cluster. + items: + description: VPCLoadBalancerSpec defines the desired + state of an VPC load balancer. + properties: + additionalListeners: + description: AdditionalListeners sets the additional + listeners for the control plane load balancer. + items: + description: |- + AdditionalListenerSpec defines the desired state of an + additional listener on an VPC load balancer. + properties: + defaultPoolName: + description: defaultPoolName defines the name + of a VPC Load Balancer Backend Pool to use + for the VPC Load Balancer Listener. + maxLength: 63 + minLength: 1 + pattern: ^([a-z]|[a-z][-a-z0-9]*[a-z0-9])$ + type: string + port: + description: Port sets the port for the additional + listener. + format: int64 + maximum: 65535 + minimum: 1 + type: integer + protocol: + description: |- + protocol defines the protocol to use for the VPC Load Balancer Listener. + Will default to TCP protocol if not specified. + enum: + - http + - https + - tcp + - udp + type: string + required: + - port + type: object + type: array + x-kubernetes-list-map-keys: + - port + x-kubernetes-list-type: map + backendPools: + description: backendPools defines the load balancer's + backend pools. + items: + description: VPCLoadBalancerBackendPoolSpec defines + the desired configuration of a VPC Load Balancer + Backend Pool. + properties: + algorithm: + description: algorithm defines the load balancing + algorithm to use. + enum: + - least_connections + - round_robin + - weighted_round_robin + type: string + healthMonitor: + description: healthMonitor defines the backend + pool's health monitor. + properties: + delay: + description: delay defines the seconds + to wait between health checks. + format: int64 + maximum: 60 + minimum: 2 + type: integer + port: + description: port defines the port to + perform health monitoring on. + format: int64 + maximum: 65535 + minimum: 1 + type: integer + retries: + description: retries defines the max retries + for health check. + format: int64 + maximum: 10 + minimum: 1 + type: integer + timeout: + description: timeout defines the seconds + to wait for a health check response. + format: int64 + maximum: 59 + minimum: 1 + type: integer + type: + description: type defines the protocol + used for health checks. + enum: + - http + - https + - tcp + type: string + urlPath: + description: urlPath defines the URL to + use for health monitoring. + pattern: ^\/(([a-zA-Z0-9-._~!$&'()*+,;=:@]|%[a-fA-F0-9]{2})+(\/([a-zA-Z0-9-._~!$&'()*+,;=:@]|%[a-fA-F0-9]{2})*)*)?(\\?([a-zA-Z0-9-._~!$&'()*+,;=:@\/?]|%[a-fA-F0-9]{2})*)?$ + type: string + required: + - delay + - retries + - timeout + - type + type: object + name: + description: name defines the name of the + Backend Pool. + maxLength: 63 + minLength: 1 + pattern: ^([a-z]|[a-z][-a-z0-9]*[a-z0-9])$ + type: string + protocol: + description: protocol defines the protocol + to use for the Backend Pool. + enum: + - http + - https + - tcp + - udp + type: string + required: + - algorithm + - healthMonitor + - protocol + type: object + type: array + id: + description: id of the loadbalancer + maxLength: 64 + minLength: 1 + pattern: ^[-0-9a-z_]+$ + type: string + name: + description: Name sets the name of the VPC load + balancer. + maxLength: 63 + minLength: 1 + pattern: ^([a-z]|[a-z][-a-z0-9]*[a-z0-9])$ + type: string + public: + default: true + description: public indicates that load balancer + is public or private + type: boolean + securityGroups: + description: |- + securityGroups defines the Security Groups to attach to the load balancer. + Security Groups defined here are expected to already exist when the load balancer is reconciled (these do not get created when reconciling the load balancer). + items: + description: VPCResource represents a VPC resource. + properties: + id: + description: id of the resource. + minLength: 1 + type: string + name: + description: name of the resource. + minLength: 1 + type: string + type: object + x-kubernetes-validations: + - message: an id or name must be provided + rule: has(self.id) || has(self.name) + type: array + subnets: + description: |- + subnets defines the VPC Subnets to attach to the load balancer. + Subnets defiens here are expected to already exist when the load balancer is reconciled (these do not get created when reconciling the load balancer). + items: + description: VPCResource represents a VPC resource. + properties: + id: + description: id of the resource. + minLength: 1 + type: string + name: + description: name of the resource. + minLength: 1 + type: string + type: object + x-kubernetes-validations: + - message: an id or name must be provided + rule: has(self.id) || has(self.name) + type: array + type: object + type: array resourceGroup: description: |- - resourceGroup is the name of the Resource Group containing all of the newtork resources. + resourceGroup is the Resource Group containing all of the newtork resources. This can be different than the Resource Group containing the remaining cluster resources. - type: string + properties: + id: + description: id defines the IBM Cloud Resource ID. + type: string + name: + description: name defines the IBM Cloud Resource Name. + type: string + required: + - id + type: object + securityGroups: + description: securityGroups is a set of VPCSecurityGroup's + which define the VPC Security Groups that manage traffic + within and out of the VPC. + items: + description: VPCSecurityGroup defines a VPC Security + Group that should exist or be created within the specified + VPC, with the specified Security Group Rules. + properties: + id: + description: id of the Security Group. + type: string + name: + description: name of the Security Group. + type: string + rules: + description: rules are the Security Group Rules + for the Security Group. + items: + description: VPCSecurityGroupRule defines a VPC + Security Group Rule for a specified Security + Group. + properties: + action: + description: action defines whether to allow + or deny traffic defined by the Security + Group Rule. + enum: + - allow + - deny + type: string + destination: + description: |- + destination is a VPCSecurityGroupRulePrototype which defines the destination of outbound traffic for the Security Group Rule. + Only used when direction is VPCSecurityGroupRuleDirectionOutbound. + properties: + icmpCode: + description: |- + icmpCode is the ICMP code for the Rule. + Only used when Protocol is VPCSecurityGroupRuleProtocolIcmp. + format: int64 + type: integer + icmpType: + description: |- + icmpType is the ICMP type for the Rule. + Only used when Protocol is VPCSecurityGroupRuleProtocolIcmp. + format: int64 + type: integer + portRange: + description: portRange is a range of ports + allowed for the Rule's remote. + properties: + maximumPort: + description: maximumPort is the inclusive + upper range of ports. + format: int64 + maximum: 65535 + minimum: 1 + type: integer + minimumPort: + description: minimumPort is the inclusive + lower range of ports. + format: int64 + maximum: 65535 + minimum: 1 + type: integer + type: object + x-kubernetes-validations: + - message: maximum port must be greater + than or equal to minimum port + rule: self.maximumPort >= self.minimumPort + protocol: + description: protocol defines the traffic + protocol used for the Security Group + Rule. + enum: + - all + - icmp + - tcp + - udp + type: string + remotes: + description: |- + remotes is a set of VPCSecurityGroupRuleRemote's that define the traffic allowed by the Rule's remote. + Specifying multiple VPCSecurityGroupRuleRemote's creates a unique Security Group Rule with the shared Protocol, PortRange, etc. + This allows for easier management of Security Group Rule's for sets of CIDR's, IP's, etc. + items: + description: |- + VPCSecurityGroupRuleRemote defines a VPC Security Group Rule's remote details. + The type of remote defines the additional remote details where are used for defining the remote. + properties: + address: + description: |2- + address is the address to use for the remote's destination/source. + Only used when remoteType is VPCSecurityGroupRuleRemoteTypeAddress. + type: string + cidrSubnetName: + description: |- + cidrSubnetName is the name of the VPC Subnet to retrieve the CIDR from, to use for the remote's destination/source. + Only used when remoteType is VPCSecurityGroupRuleRemoteTypeCIDR. + type: string + remoteType: + description: remoteType defines + the type of filter to define for + the remote's destination/source. + enum: + - any + - cidr + - address + - sg + type: string + securityGroupName: + description: |- + securityGroupName is the name of the VPC Security Group to use for the remote's destination/source. + Only used when remoteType is VPCSecurityGroupRuleRemoteTypeSG + type: string + required: + - remoteType + type: object + x-kubernetes-validations: + - message: cidrSubnetName, addresss, + and securityGroupName are not valid + for VPCSecurityGroupRuleRemoteTypeAny + remoteType + rule: 'self.remoteType == ''any'' + ? (!has(self.cidrSubnetName) && + !has(self.address) && !has(self.securityGroupName)) + : true' + - message: only cidrSubnetName is valid + for VPCSecurityGroupRuleRemoteTypeCIDR + remoteType + rule: 'self.remoteType == ''cidr'' + ? (has(self.cidrSubnetName) && !has(self.address) + && !has(self.securityGroupName)) + : true' + - message: only address is valid for + VPCSecurityGroupRuleRemoteTypeIP + remoteType + rule: 'self.remoteType == ''address'' + ? (has(self.address) && !has(self.cidrSubnetName) + && !has(self.securityGroupName)) + : true' + - message: only securityGroupName is + valid for VPCSecurityGroupRuleRemoteTypeSG + remoteType + rule: 'self.remoteType == ''sg'' ? + (has(self.securityGroupName) && + !has(self.cidrSubnetName) && !has(self.address)) + : true' + type: array + required: + - protocol + - remotes + type: object + x-kubernetes-validations: + - message: icmpCode and icmpType are only + supported for VPCSecurityGroupRuleProtocolIcmp + protocol + rule: 'self.protocol != ''icmp'' ? (!has(self.icmpCode) + && !has(self.icmpType)) : true' + - message: portRange is not valid for VPCSecurityGroupRuleProtocolAll + protocol + rule: 'self.protocol == ''all'' ? !has(self.portRange) + : true' + - message: portRange is not valid for VPCSecurityGroupRuleProtocolIcmp + protocol + rule: 'self.protocol == ''icmp'' ? !has(self.portRange) + : true' + direction: + description: direction defines whether the + traffic is inbound or outbound for the Security + Group Rule. + enum: + - inbound + - outbound + type: string + securityGroupID: + description: securityGroupID is the ID of + the Security Group for the Security Group + Rule. + type: string + source: + description: |- + source is a VPCSecurityGroupRulePrototype which defines the source of inbound traffic for the Security Group Rule. + Only used when direction is VPCSecurityGroupRuleDirectionInbound. + properties: + icmpCode: + description: |- + icmpCode is the ICMP code for the Rule. + Only used when Protocol is VPCSecurityGroupRuleProtocolIcmp. + format: int64 + type: integer + icmpType: + description: |- + icmpType is the ICMP type for the Rule. + Only used when Protocol is VPCSecurityGroupRuleProtocolIcmp. + format: int64 + type: integer + portRange: + description: portRange is a range of ports + allowed for the Rule's remote. + properties: + maximumPort: + description: maximumPort is the inclusive + upper range of ports. + format: int64 + maximum: 65535 + minimum: 1 + type: integer + minimumPort: + description: minimumPort is the inclusive + lower range of ports. + format: int64 + maximum: 65535 + minimum: 1 + type: integer + type: object + x-kubernetes-validations: + - message: maximum port must be greater + than or equal to minimum port + rule: self.maximumPort >= self.minimumPort + protocol: + description: protocol defines the traffic + protocol used for the Security Group + Rule. + enum: + - all + - icmp + - tcp + - udp + type: string + remotes: + description: |- + remotes is a set of VPCSecurityGroupRuleRemote's that define the traffic allowed by the Rule's remote. + Specifying multiple VPCSecurityGroupRuleRemote's creates a unique Security Group Rule with the shared Protocol, PortRange, etc. + This allows for easier management of Security Group Rule's for sets of CIDR's, IP's, etc. + items: + description: |- + VPCSecurityGroupRuleRemote defines a VPC Security Group Rule's remote details. + The type of remote defines the additional remote details where are used for defining the remote. + properties: + address: + description: |2- + address is the address to use for the remote's destination/source. + Only used when remoteType is VPCSecurityGroupRuleRemoteTypeAddress. + type: string + cidrSubnetName: + description: |- + cidrSubnetName is the name of the VPC Subnet to retrieve the CIDR from, to use for the remote's destination/source. + Only used when remoteType is VPCSecurityGroupRuleRemoteTypeCIDR. + type: string + remoteType: + description: remoteType defines + the type of filter to define for + the remote's destination/source. + enum: + - any + - cidr + - address + - sg + type: string + securityGroupName: + description: |- + securityGroupName is the name of the VPC Security Group to use for the remote's destination/source. + Only used when remoteType is VPCSecurityGroupRuleRemoteTypeSG + type: string + required: + - remoteType + type: object + x-kubernetes-validations: + - message: cidrSubnetName, addresss, + and securityGroupName are not valid + for VPCSecurityGroupRuleRemoteTypeAny + remoteType + rule: 'self.remoteType == ''any'' + ? (!has(self.cidrSubnetName) && + !has(self.address) && !has(self.securityGroupName)) + : true' + - message: only cidrSubnetName is valid + for VPCSecurityGroupRuleRemoteTypeCIDR + remoteType + rule: 'self.remoteType == ''cidr'' + ? (has(self.cidrSubnetName) && !has(self.address) + && !has(self.securityGroupName)) + : true' + - message: only address is valid for + VPCSecurityGroupRuleRemoteTypeIP + remoteType + rule: 'self.remoteType == ''address'' + ? (has(self.address) && !has(self.cidrSubnetName) + && !has(self.securityGroupName)) + : true' + - message: only securityGroupName is + valid for VPCSecurityGroupRuleRemoteTypeSG + remoteType + rule: 'self.remoteType == ''sg'' ? + (has(self.securityGroupName) && + !has(self.cidrSubnetName) && !has(self.address)) + : true' + type: array + required: + - protocol + - remotes + type: object + x-kubernetes-validations: + - message: icmpCode and icmpType are only + supported for VPCSecurityGroupRuleProtocolIcmp + protocol + rule: 'self.protocol != ''icmp'' ? (!has(self.icmpCode) + && !has(self.icmpType)) : true' + - message: portRange is not valid for VPCSecurityGroupRuleProtocolAll + protocol + rule: 'self.protocol == ''all'' ? !has(self.portRange) + : true' + - message: portRange is not valid for VPCSecurityGroupRuleProtocolIcmp + protocol + rule: 'self.protocol == ''icmp'' ? !has(self.portRange) + : true' + required: + - action + - direction + type: object + x-kubernetes-validations: + - message: both destination and source cannot + be provided + rule: (has(self.destination) && !has(self.source)) + || (!has(self.destination) && has(self.source)) + - message: source must be set for VPCSecurityGroupRuleDirectionInbound + direction + rule: 'self.direction == ''inbound'' ? has(self.source) + : true' + - message: destination is not valid for VPCSecurityGroupRuleDirectionInbound + direction + rule: 'self.direction == ''inbound'' ? !has(self.destination) + : true' + - message: destination must be set for VPCSecurityGroupRuleDirectionOutbound + direction + rule: 'self.direction == ''outbound'' ? has(self.destination) + : true' + - message: source is not valid for VPCSecurityGroupRuleDirectionOutbound + direction + rule: 'self.direction == ''outbound'' ? !has(self.source) + : true' + type: array + tags: + description: tags are tags to add to the Security + Group. + items: + type: string + type: array + type: object + x-kubernetes-validations: + - message: either an id or name must be specified + rule: has(self.id) || has(self.name) + type: array vpc: description: vpc defines the IBM Cloud VPC for extended VPC Infrastructure support. From 4012d7ccba8fb30b80b81f2417ee3e83b67ef3b8 Mon Sep 17 00:00:00 2001 From: cjschaef Date: Mon, 19 Aug 2024 11:33:50 -0500 Subject: [PATCH 2/2] VPC: Update Network RG reference and lookup per API --- cloud/scope/vpc_cluster.go | 39 +++++++++++++------ .../mock/resourcemanager_generated.go | 16 ++++++++ .../resourcemanager/resourcemanager.go | 1 + pkg/cloud/services/resourcemanager/service.go | 5 +++ 4 files changed, 50 insertions(+), 11 deletions(-) diff --git a/cloud/scope/vpc_cluster.go b/cloud/scope/vpc_cluster.go index aafe578a6..2723ccec0 100644 --- a/cloud/scope/vpc_cluster.go +++ b/cloud/scope/vpc_cluster.go @@ -225,27 +225,44 @@ func (s *VPCClusterScope) GetNetworkResourceGroupID() (string, error) { } // If there is no Network Resource Group defined, use the cluster's Resource Group. - if s.NetworkSpec() == nil || s.NetworkSpec().ResourceGroup == nil { + if s.NetworkSpec() == nil || s.NetworkSpec().ResourceGroup == nil || (s.NetworkSpec().ResourceGroup.ID == "" && s.NetworkSpec().ResourceGroup.Name == nil) { return s.GetResourceGroupID() } - // Otherwise, Collect the Network's Resource Group Id. - // Retrieve the Resource Group based on the name. - resourceGroup, err := s.ResourceManagerClient.GetResourceGroupByName(*s.NetworkSpec().ResourceGroup) - if err != nil { - return "", fmt.Errorf("failed to retrieve network resource group id by name: %w", err) - } else if resourceGroup == nil || resourceGroup.ID == nil { - return "", fmt.Errorf("error retrieving network resource group by name: %s", *s.NetworkSpec().ResourceGroup) + // Otherwise, collect the Network's Resource Group Id. + resourceGroupID := s.NetworkSpec().ResourceGroup.ID + var resourceGroupName *string + if resourceGroupID != "" { + // Verify the Resource Group exists, using the provided ID. + resourceGroupDetails, _, err := s.ResourceManagerClient.GetResourceGroup(&resourcemanagerv2.GetResourceGroupOptions{ + ID: ptr.To(resourceGroupID), + }) + if err != nil { + return "", fmt.Errorf("failed to retrieve newtork resource group by id: %w", err) + } else if resourceGroupDetails == nil || resourceGroupDetails.Name == nil { + return "", fmt.Errorf("error retrieving network resource group by id: %s", resourceGroupID) + } + resourceGroupName = resourceGroupDetails.Name + } else { + // Retrieve the Resource Group based on the name (Name must exist if ID is empty). + resourceGroup, err := s.ResourceManagerClient.GetResourceGroupByName(*s.NetworkSpec().ResourceGroup.Name) + if err != nil { + return "", fmt.Errorf("failed to retrieve network resource group id by name: %w", err) + } else if resourceGroup == nil || resourceGroup.ID == nil { + return "", fmt.Errorf("error retrieving network resource group by name: %s", *s.NetworkSpec().ResourceGroup.Name) + } + resourceGroupID = *resourceGroup.ID + resourceGroupName = s.NetworkSpec().ResourceGroup.Name } // Populate the Network Status' Resource Group to shortcut future lookups. s.SetResourceStatus(infrav1beta2.ResourceTypeResourceGroup, &infrav1beta2.ResourceStatus{ - ID: *resourceGroup.ID, - Name: s.NetworkSpec().ResourceGroup, + ID: resourceGroupID, + Name: resourceGroupName, Ready: true, }) - return *resourceGroup.ID, nil + return resourceGroupID, nil } // GetResourceGroupID returns the Resource Group ID for the cluster. diff --git a/pkg/cloud/services/resourcemanager/mock/resourcemanager_generated.go b/pkg/cloud/services/resourcemanager/mock/resourcemanager_generated.go index 4b126d198..8be5208af 100644 --- a/pkg/cloud/services/resourcemanager/mock/resourcemanager_generated.go +++ b/pkg/cloud/services/resourcemanager/mock/resourcemanager_generated.go @@ -55,6 +55,22 @@ func (m *MockResourceManager) EXPECT() *MockResourceManagerMockRecorder { return m.recorder } +// GetResourceGroup mocks base method. +func (m *MockResourceManager) GetResourceGroup(arg0 *resourcemanagerv2.GetResourceGroupOptions) (*resourcemanagerv2.ResourceGroup, *core.DetailedResponse, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetResourceGroup", arg0) + ret0, _ := ret[0].(*resourcemanagerv2.ResourceGroup) + ret1, _ := ret[1].(*core.DetailedResponse) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 +} + +// GetResourceGroup indicates an expected call of GetResourceGroup. +func (mr *MockResourceManagerMockRecorder) GetResourceGroup(arg0 any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetResourceGroup", reflect.TypeOf((*MockResourceManager)(nil).GetResourceGroup), arg0) +} + // GetResourceGroupByName mocks base method. func (m *MockResourceManager) GetResourceGroupByName(arg0 string) (*resourcemanagerv2.ResourceGroup, error) { m.ctrl.T.Helper() diff --git a/pkg/cloud/services/resourcemanager/resourcemanager.go b/pkg/cloud/services/resourcemanager/resourcemanager.go index c3bc2fa0a..88fca166e 100644 --- a/pkg/cloud/services/resourcemanager/resourcemanager.go +++ b/pkg/cloud/services/resourcemanager/resourcemanager.go @@ -27,6 +27,7 @@ import ( // ResourceManager interface defines a method that a IBMCLOUD service object should implement in order to // use the manage lifecycle of cloud resource groups using Resource Manager APIs. type ResourceManager interface { + GetResourceGroup(*resourcemanagerv2.GetResourceGroupOptions) (*resourcemanagerv2.ResourceGroup, *core.DetailedResponse, error) ListResourceGroups(*resourcemanagerv2.ListResourceGroupsOptions) (*resourcemanagerv2.ResourceGroupList, *core.DetailedResponse, error) GetResourceGroupByName(string) (*resourcemanagerv2.ResourceGroup, error) diff --git a/pkg/cloud/services/resourcemanager/service.go b/pkg/cloud/services/resourcemanager/service.go index 027277358..09a8ab350 100644 --- a/pkg/cloud/services/resourcemanager/service.go +++ b/pkg/cloud/services/resourcemanager/service.go @@ -53,6 +53,11 @@ func NewService(options *resourcemanagerv2.ResourceManagerV2Options) (ResourceMa }, nil } +// GetResourceGroup returns a Resource Group. +func (s *Service) GetResourceGroup(getResourceGroupOptions *resourcemanagerv2.GetResourceGroupOptions) (*resourcemanagerv2.ResourceGroup, *core.DetailedResponse, error) { + return s.client.GetResourceGroup(getResourceGroupOptions) +} + // ListResourceGroups lists the resource groups. func (s *Service) ListResourceGroups(listResourceGroupsOptions *resourcemanagerv2.ListResourceGroupsOptions) (result *resourcemanagerv2.ResourceGroupList, response *core.DetailedResponse, err error) { return s.client.ListResourceGroups(listResourceGroupsOptions)