diff --git a/api/v1alpha1/linodecluster_types.go b/api/v1alpha1/linodecluster_types.go index 31ae6d277..46777975e 100644 --- a/api/v1alpha1/linodecluster_types.go +++ b/api/v1alpha1/linodecluster_types.go @@ -48,6 +48,11 @@ type LinodeClusterStatus struct { // +optional Ready bool `json:"ready"` + // NodeBalancerConfigID contains the config ID for the NodeBalancer associated with + // the LinodeCluster + // +optional + NodeBalancerConfigID *int `json:"nodeBalancerConfigID,omitempty"` + // FailureReason will be set in the event that there is a terminal problem // reconciling the LinodeCluster and will contain a succinct value suitable // for machine interpretation. @@ -98,6 +103,7 @@ type NetworkSpec struct { // LoadBalancerPort used by the api server. It must be valid ports range (1-65535). If omitted, default value is 6443. // +kubebuilder:validation:Minimum=1 // +kubebuilder:validation:Maximum=65535 + // +kubebuilder:default:=6443 // +optional LoadBalancerPort int `json:"loadBalancerPort,omitempty"` // NodeBalancerID is the id of api server NodeBalancer. diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index 84feb9fdd..f3497c04c 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -157,6 +157,11 @@ func (in *LinodeClusterSpec) DeepCopy() *LinodeClusterSpec { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *LinodeClusterStatus) DeepCopyInto(out *LinodeClusterStatus) { *out = *in + if in.NodeBalancerConfigID != nil { + in, out := &in.NodeBalancerConfigID, &out.NodeBalancerConfigID + *out = new(int) + **out = **in + } if in.FailureReason != nil { in, out := &in.FailureReason, &out.FailureReason *out = new(errors.ClusterStatusError) diff --git a/cloud/services/loadbalancers.go b/cloud/services/loadbalancers.go index dd1a20575..0bfd19d05 100644 --- a/cloud/services/loadbalancers.go +++ b/cloud/services/loadbalancers.go @@ -7,7 +7,6 @@ import ( "fmt" "net/http" "slices" - "strconv" "github.com/go-logr/logr" "github.com/linode/cluster-api-provider-linode/cloud/scope" @@ -16,10 +15,6 @@ import ( kutil "sigs.k8s.io/cluster-api/util" ) -var ( - defaultLBPort = 6443 -) - // CreateNodeBalancer creates a new NodeBalancer if one doesn't exist func CreateNodeBalancer(ctx context.Context, clusterScope *scope.ClusterScope, logger logr.Logger) (*linodego.NodeBalancer, error) { var linodeNBs []linodego.NodeBalancer @@ -81,32 +76,21 @@ func CreateNodeBalancerConfig( ctx context.Context, clusterScope *scope.ClusterScope, logger logr.Logger, -) (*linodego.NodeBalancerConfig, error) { - var linodeNBConfig *linodego.NodeBalancerConfig - var err error - - if linodeNBConfig, err = GetNodeBalancerConfig(ctx, clusterScope, logger); err != nil { - logger.Info("Failed to list NodeBalancer Configs", "error", err.Error()) - - return nil, err - } - if linodeNBConfig != nil { - logger.Info("NodeBalancer ", strconv.Itoa(linodeNBConfig.ID), " already exists") +) (configID *int, err error) { + if clusterScope.LinodeCluster.Status.NodeBalancerConfigID != nil { + logger.Info("NodeBalancer config already exists") - return linodeNBConfig, err + return clusterScope.LinodeCluster.Status.NodeBalancerConfigID, nil } - lbPort := defaultLBPort - if clusterScope.LinodeCluster.Spec.Network.LoadBalancerPort != 0 { - lbPort = clusterScope.LinodeCluster.Spec.Network.LoadBalancerPort - } createConfig := linodego.NodeBalancerConfigCreateOptions{ - Port: lbPort, + Port: clusterScope.LinodeCluster.Spec.Network.LoadBalancerPort, Protocol: linodego.ProtocolTCP, Algorithm: linodego.AlgorithmRoundRobin, Check: linodego.CheckConnection, } + var linodeNBConfig *linodego.NodeBalancerConfig if linodeNBConfig, err = clusterScope.LinodeClient.CreateNodeBalancerConfig( ctx, clusterScope.LinodeCluster.Spec.Network.NodeBalancerID, @@ -117,32 +101,7 @@ func CreateNodeBalancerConfig( return nil, err } - return linodeNBConfig, nil -} - -// GetNodeBalancerConfig gets the first NodeBalancer config -func GetNodeBalancerConfig( - ctx context.Context, - clusterScope *scope.ClusterScope, - logger logr.Logger, -) (*linodego.NodeBalancerConfig, error) { - var linodeNBConfigs []linodego.NodeBalancerConfig - var err error - - if linodeNBConfigs, err = clusterScope.LinodeClient.ListNodeBalancerConfigs( - ctx, - clusterScope.LinodeCluster.Spec.Network.NodeBalancerID, - linodego.NewListOptions(1, ""), - ); err != nil { - logger.Info("Failed to list NodeBalancer Configs", "error", err.Error()) - - return nil, err - } - if len(linodeNBConfigs) == 0 { - return nil, err - } - - return &linodeNBConfigs[0], err + return util.Pointer(linodeNBConfig.ID), nil } // AddNodeToNB adds a backend Node on the Node Balancer configuration @@ -171,8 +130,8 @@ func AddNodeToNB( return err } - linodeNBConfig, err := GetNodeBalancerConfig(ctx, clusterScope, logger) - if err != nil { + if machineScope.LinodeCluster.Status.NodeBalancerConfigID == nil { + err := errors.New("nil NodeBalancer config ID") logger.Error(err, "Failed to get Node Balancer config") return err @@ -180,11 +139,15 @@ func AddNodeToNB( _, err = machineScope.LinodeClient.CreateNodeBalancerNode( ctx, machineScope.LinodeCluster.Spec.Network.NodeBalancerID, - linodeNBConfig.ID, + *machineScope.LinodeCluster.Status.NodeBalancerConfigID, linodego.NodeBalancerNodeCreateOptions{ - Label: machineScope.Cluster.Name, - Address: fmt.Sprintf("%s:%d", addresses.IPv4.Private[0].Address, linodeNBConfig.Port), - Mode: linodego.ModeAccept, + Label: machineScope.Cluster.Name, + Address: fmt.Sprintf( + "%s:%d", + addresses.IPv4.Private[0].Address, + machineScope.LinodeCluster.Spec.Network.LoadBalancerPort, + ), + Mode: linodego.ModeAccept, }, ) if err != nil { @@ -212,17 +175,17 @@ func DeleteNodeFromNB( return errors.New("no InstanceID") } - linodeNBConfig, err := GetNodeBalancerConfig(ctx, clusterScope, logger) - if util.IgnoreLinodeAPIError(err, http.StatusNotFound) != nil || linodeNBConfig == nil { + if machineScope.LinodeCluster.Status.NodeBalancerConfigID == nil { + err := errors.New("nil NodeBalancer config ID") logger.Error(err, "Failed to get Node Balancer config") return err } - err = machineScope.LinodeClient.DeleteNodeBalancerNode( + err := machineScope.LinodeClient.DeleteNodeBalancerNode( ctx, machineScope.LinodeCluster.Spec.Network.NodeBalancerID, - linodeNBConfig.ID, + *machineScope.LinodeCluster.Status.NodeBalancerConfigID, *machineScope.LinodeMachine.Spec.InstanceID, ) if util.IgnoreLinodeAPIError(err, http.StatusNotFound) != nil { diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_linodeclusters.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_linodeclusters.yaml index 6fdc5281c..f4a323626 100644 --- a/config/crd/bases/infrastructure.cluster.x-k8s.io_linodeclusters.yaml +++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_linodeclusters.yaml @@ -73,6 +73,7 @@ spec: network. properties: loadBalancerPort: + default: 6443 description: LoadBalancerPort used by the api server. It must be valid ports range (1-65535). If omitted, default value is 6443. @@ -216,6 +217,10 @@ spec: a terminal problem reconciling the LinodeCluster and will contain a succinct value suitable for machine interpretation. type: string + nodeBalancerConfigID: + description: NodeBalancerConfigID contains the config ID for the NodeBalancer + associated with the LinodeCluster + type: integer ready: description: Ready denotes that the cluster (infrastructure) is ready. type: boolean diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_linodeclustertemplates.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_linodeclustertemplates.yaml index 70e93db67..368621491 100644 --- a/config/crd/bases/infrastructure.cluster.x-k8s.io_linodeclustertemplates.yaml +++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_linodeclustertemplates.yaml @@ -68,6 +68,7 @@ spec: Linode network. properties: loadBalancerPort: + default: 6443 description: LoadBalancerPort used by the api server. It must be valid ports range (1-65535). If omitted, default value is 6443. diff --git a/controller/linodecluster_controller.go b/controller/linodecluster_controller.go index fe5bf2323..8f9a3d4cc 100644 --- a/controller/linodecluster_controller.go +++ b/controller/linodecluster_controller.go @@ -171,7 +171,7 @@ func (r *LinodeClusterReconciler) reconcileCreate(ctx context.Context, logger lo clusterScope.LinodeCluster.Spec.Network.NodeBalancerID = linodeNB.ID - linodeNBConfig, err := services.CreateNodeBalancerConfig(ctx, clusterScope, logger) + configID, err := services.CreateNodeBalancerConfig(ctx, clusterScope, logger) if err != nil { setFailureReason(clusterScope, cerrs.CreateClusterError, err, r) @@ -180,7 +180,14 @@ func (r *LinodeClusterReconciler) reconcileCreate(ctx context.Context, logger lo clusterScope.LinodeCluster.Spec.ControlPlaneEndpoint = clusterv1.APIEndpoint{ Host: *linodeNB.IPv4, - Port: int32(linodeNBConfig.Port), + Port: int32(clusterScope.LinodeCluster.Spec.Network.LoadBalancerPort), + } + + clusterScope.LinodeCluster.Status.NodeBalancerConfigID = configID + if err = r.Status().Update(ctx, clusterScope.LinodeCluster); err != nil { + setFailureReason(clusterScope, cerrs.CreateClusterError, err, r) + + return err } return nil