Skip to content

Commit

Permalink
last steps
Browse files Browse the repository at this point in the history
  • Loading branch information
farodin91 committed Nov 6, 2023
1 parent 589beb1 commit 58745cf
Show file tree
Hide file tree
Showing 6 changed files with 141 additions and 63 deletions.
8 changes: 4 additions & 4 deletions api/v1alpha1/ionoscloudcluster_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,10 @@ type IONOSCloudClusterSpec struct {
Location Location `json:"location"`

// +kubebuilder:validation:MinLength=1
IdentityName string `json:"identityName"`
ControlPlaneEndpoint clusterv1.APIEndpoint `json:"controlPlaneEndpoint"`
Lans []IONOSLanSpec `json:"lans,omitempty"`
LoadBalancer *IONOSLoadBalancerSpec `json:"loadBalancer,omitempty"`
IdentityName string `json:"identityName"`
ControlPlaneEndpoint clusterv1.APIEndpoint `json:"controlPlaneEndpoint"`
Lans []IONOSLanSpec `json:"lans,omitempty"`
LoadBalancer IONOSLoadBalancerSpec `json:"loadBalancer,omitempty"`

// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="DataCenterID is immutable"
DataCenterID string `json:"dataCenterID,omitempty"`
Expand Down
6 changes: 1 addition & 5 deletions api/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 13 additions & 5 deletions internal/controller/ionoscloudcluster_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -202,9 +202,9 @@ func (r *IONOSCloudClusterReconciler) reconcileDataCenter(ctx *context.ClusterCo
}

func (r *IONOSCloudClusterReconciler) reconcileLan(ctx *context.ClusterContext) (*reconcile.Result, error) {
ctx.Logger.Info("Reconciling Lan")
for i := range ctx.IONOSCloudCluster.Spec.Lans {
lanSpec := &ctx.IONOSCloudCluster.Spec.Lans[i]
ctx.Logger.Info(fmt.Sprintf("Reconciling %s Lan", lanSpec.Name))
if lanSpec.LanID == nil {
lanID, err := createLan(ctx, lanSpec.Public)
if err != nil {
Expand All @@ -218,11 +218,11 @@ func (r *IONOSCloudClusterReconciler) reconcileLan(ctx *context.ClusterContext)
lan, resp, err := ctx.IONOSClient.GetLan(ctx, ctx.IONOSCloudCluster.Spec.DataCenterID, lanId)

if err != nil && resp.StatusCode != http.StatusNotFound {
return &reconcile.Result{}, errors.Wrap(err, "error getting public Lan")
return &reconcile.Result{}, errors.Wrap(err, fmt.Sprintf("error getting %s Lan", lanSpec.Name))
}

if resp.StatusCode == http.StatusNotFound || *lan.Metadata.State == STATE_BUSY {
return &reconcile.Result{RequeueAfter: defaultRetryIntervalOnBusy}, errors.New("public Lan not available (yet)")
return &reconcile.Result{RequeueAfter: defaultRetryIntervalOnBusy}, errors.New(fmt.Sprintf("%s Lan not available (yet)", lanSpec.Name))
}
}

Expand All @@ -233,10 +233,18 @@ func (r *IONOSCloudClusterReconciler) reconcileLan(ctx *context.ClusterContext)
func (r *IONOSCloudClusterReconciler) reconcileLoadBalancer(ctx *context.ClusterContext) (*reconcile.Result, error) {
ctx.Logger.Info("Reconciling LoadBalancer")
lbSpec := ctx.IONOSCloudCluster.Spec.LoadBalancer
listenerLan := ctx.IONOSCloudCluster.Lan(lbSpec.ListenerLanRef.Name)
targetLan := ctx.IONOSCloudCluster.Lan(lbSpec.TargetLanRef.Name)

if listenerLan == nil {
return &reconcile.Result{RequeueAfter: defaultRetryIntervalOnBusy}, errors.New(fmt.Sprintf("listener lb %s Lan not available (yet)", lbSpec.ListenerLanRef.Name))
}
if targetLan == nil {
return &reconcile.Result{RequeueAfter: defaultRetryIntervalOnBusy}, errors.New(fmt.Sprintf("target lb %s Lan not available (yet)", lbSpec.TargetLanRef.Name))
}

if lbSpec.ID == "" {
loadBalancerName := fmt.Sprintf("lb-%s", ctx.Cluster.Name)
listenerLan := ctx.IONOSCloudCluster.Lan(lbSpec.ListenerLanRef.Name)
targetLan := ctx.IONOSCloudCluster.Lan(lbSpec.TargetLanRef.Name)
loadBalancer := ionoscloud.NetworkLoadBalancer{
Entities: &ionoscloud.NetworkLoadBalancerEntities{
Forwardingrules: &ionoscloud.NetworkLoadBalancerForwardingRules{
Expand Down
22 changes: 22 additions & 0 deletions internal/controller/ionoscloudcluster_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,28 @@ var _ = Describe("IONOSCloudCluster controller", func() {
Port: 6443,
},
IdentityName: CAPICClusterIdentityName,
LoadBalancer: v1alpha1.IONOSLoadBalancerSpec{
ListenerLanRef: v1alpha1.IONOSLanRefSpec{
Name: "public",
},
TargetLanRef: v1alpha1.IONOSLanRefSpec{
Name: "private",
},
},
Lans: []v1alpha1.IONOSLanSpec{
{
Name: "public",
Public: true,
},
{
Name: "private",
Public: false,
},
{
Name: "internet",
Public: true,
},
},
},
}
identitySecret = &v1.Secret{
Expand Down
116 changes: 67 additions & 49 deletions internal/controller/ionoscloudmachine_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ import (
goctx "context"
b64 "encoding/base64"
"fmt"
"net/http"
"strings"
"time"

v1alpha1 "github.com/GDATASoftwareAG/cluster-api-provider-ionoscloud/api/v1alpha1"
"github.com/GDATASoftwareAG/cluster-api-provider-ionoscloud/internal/context"
"github.com/GDATASoftwareAG/cluster-api-provider-ionoscloud/internal/utils"
Expand All @@ -29,7 +33,6 @@ import (
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/types"
apitypes "k8s.io/apimachinery/pkg/types"
"net/http"
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
bootstrapv1 "sigs.k8s.io/cluster-api/bootstrap/kubeadm/api/v1beta1"
clusterutilv1 "sigs.k8s.io/cluster-api/util"
Expand All @@ -41,8 +44,6 @@ import (
ctrlutil "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
"sigs.k8s.io/controller-runtime/pkg/handler"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
"strings"
"time"
)

// IONOSCloudMachineReconciler reconciles a IONOSCloudMachine object
Expand Down Expand Up @@ -183,48 +184,8 @@ func (r *IONOSCloudMachineReconciler) reconcileDelete(ctx *context.MachineContex
}
}

if ctx.IONOSCloudMachine.Spec.IP != nil { // todo
if rules, _, err := ctx.IONOSClient.GetLoadBalancerForwardingRules(ctx, ctx.IONOSCloudCluster.Spec.DataCenterID, ctx.IONOSCloudCluster.Spec.LoadBalancerID); err != nil {
return reconcile.Result{}, err
} else {
targetToDelete := ionoscloud.NetworkLoadBalancerForwardingRuleTarget{
Ip: ctx.IONOSCloudMachine.Spec.IP,
Port: ionoscloud.PtrInt32(6443),
Weight: ionoscloud.PtrInt32(1),
}
for _, rule := range *rules.Items {
if *rule.Properties.ListenerPort != 6443 {
// we only care about the api server port
continue
}

for _, target := range *rule.Properties.Targets {
if *target.Ip == *targetToDelete.Ip {
targets := *rule.Properties.Targets
targets = findAndDeleteByIP(targets, targetToDelete)
properties := ionoscloud.NetworkLoadBalancerForwardingRuleProperties{
Algorithm: rule.Properties.Algorithm,
HealthCheck: rule.Properties.HealthCheck,
ListenerIp: rule.Properties.ListenerIp,
ListenerPort: rule.Properties.ListenerPort,
Name: rule.Properties.Name,
Protocol: rule.Properties.Protocol,
Targets: &targets,
}
if _, _, err = ctx.IONOSClient.PatchLoadBalancerForwardingRule(
ctx,
ctx.IONOSCloudCluster.Spec.DataCenterID,
ctx.IONOSCloudCluster.Spec.LoadBalancerID,
*rule.Id,
properties,
); err != nil {
return reconcile.Result{}, err
}

}
}
}
}
if err = r.reconcileDeleteLoadBalancerForwardingRule(ctx); err != nil {
return reconcile.Result{}, err
}

conditions.MarkFalse(ctx.IONOSCloudCluster, v1alpha1.ServerCreatedCondition, "ServerDeleted", clusterv1.ConditionSeverityInfo, "")
Expand All @@ -234,6 +195,62 @@ func (r *IONOSCloudMachineReconciler) reconcileDelete(ctx *context.MachineContex
return reconcile.Result{}, nil
}

func (r *IONOSCloudMachineReconciler) reconcileDeleteLoadBalancerForwardingRule(ctx *context.MachineContext) error {
if !clusterutilv1.IsControlPlaneMachine(ctx.Machine) {
ctx.Logger.Info("Deleting IONOSCLoudMachine is not a control plane...no forwarding rule deletion required.")
return nil
}

lbSpec := ctx.IONOSCloudCluster.Spec.LoadBalancer
nic := ctx.IONOSCloudMachine.NicByLan(lbSpec.TargetLanRef.Name)

if nic == nil && nic.PrimaryIP != nil {
return nil
}

if rules, _, err := ctx.IONOSClient.GetLoadBalancerForwardingRules(ctx, ctx.IONOSCloudCluster.Spec.DataCenterID, lbSpec.ID); err != nil {
return err
} else {
targetToDelete := ionoscloud.NetworkLoadBalancerForwardingRuleTarget{
Ip: nic.PrimaryIP,
Port: ionoscloud.PtrInt32(6443),
Weight: ionoscloud.PtrInt32(1),
}
for _, rule := range *rules.Items {
if *rule.Properties.ListenerPort != 6443 {
// we only care about the api server port
continue
}

for _, target := range *rule.Properties.Targets {
if *target.Ip == *targetToDelete.Ip {
targets := *rule.Properties.Targets
targets = findAndDeleteByIP(targets, targetToDelete)
properties := ionoscloud.NetworkLoadBalancerForwardingRuleProperties{
Algorithm: rule.Properties.Algorithm,
HealthCheck: rule.Properties.HealthCheck,
ListenerIp: rule.Properties.ListenerIp,
ListenerPort: rule.Properties.ListenerPort,
Name: rule.Properties.Name,
Protocol: rule.Properties.Protocol,
Targets: &targets,
}
if _, _, err = ctx.IONOSClient.PatchLoadBalancerForwardingRule(
ctx,
ctx.IONOSCloudCluster.Spec.DataCenterID,
lbSpec.ID,
*rule.Id,
properties,
); err != nil {
return err
}
}
}
}
}
return nil
}

func (r *IONOSCloudMachineReconciler) reconcileNormal(ctx *context.MachineContext) (reconcile.Result, error) {
ctx.Logger.Info("Reconciling IONOSCloudCluster")

Expand Down Expand Up @@ -352,7 +369,6 @@ func (r *IONOSCloudMachineReconciler) reconcileServer(ctx *context.MachineContex
},
},
Properties: &ionoscloud.ServerProperties{

Cores: ctx.IONOSCloudMachine.Spec.Cores,
CpuFamily: ctx.IONOSCloudMachine.Spec.CpuFamily,
Name: ionoscloud.ToPtr(ctx.IONOSCloudMachine.Name),
Expand All @@ -377,13 +393,15 @@ func (r *IONOSCloudMachineReconciler) reconcileServer(ctx *context.MachineContex
if resp.StatusCode == http.StatusNotFound || (server.Metadata != nil && *server.Metadata.State == STATE_BUSY) {
return &reconcile.Result{RequeueAfter: defaultRetryIntervalOnBusy}, errors.New("server not yet created")
}
ipObtained := false
nics := *server.Entities.Nics.Items
for _, nic := range nics {
ips := *nic.Properties.Ips
lan := ctx.IONOSCloudCluster.LanBy(nic.Properties.Lan)
if lan == nil {
if lan == nil || len(ips) != 0 {
continue
}
ipObtained = true
ctx.IONOSCloudMachine.EnsureNic(v1alpha1.IONOSNicSpec{
LanRef: v1alpha1.IONOSLanRefSpec{
Name: lan.Name,
Expand All @@ -392,7 +410,7 @@ func (r *IONOSCloudMachineReconciler) reconcileServer(ctx *context.MachineContex
})
}

if ctx.IONOSCloudMachine.Spec.IP == nil {
if !ipObtained {
return &reconcile.Result{RequeueAfter: defaultRetryIntervalOnBusy}, errors.New("server does not have an ip yet")
}

Expand All @@ -408,8 +426,8 @@ func (r *IONOSCloudMachineReconciler) reconcileLoadBalancerForwardingRule(ctx *c
ctx.Logger.Info("Reconciled IONOSCLoudMachine is not a control plane...no forwarding rule needed.")
return nil, nil
}
lbSpec := ctx.IONOSCloudCluster.Spec.LoadBalancer

lbSpec := ctx.IONOSCloudCluster.Spec.LoadBalancer
nic := ctx.IONOSCloudMachine.NicByLan(lbSpec.TargetLanRef.Name)

if nic == nil && nic.PrimaryIP != nil {
Expand Down
34 changes: 34 additions & 0 deletions internal/controller/ionoscloudmachine_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,28 @@ var _ = Describe("IONOSCloudMachine controller", func() {
Port: 6443,
},
IdentityName: CAPICClusterIdentityName,
LoadBalancer: v1alpha1.IONOSLoadBalancerSpec{
ListenerLanRef: v1alpha1.IONOSLanRefSpec{
Name: "public",
},
TargetLanRef: v1alpha1.IONOSLanRefSpec{
Name: "private",
},
},
Lans: []v1alpha1.IONOSLanSpec{
{
Name: "public",
Public: true,
},
{
Name: "private",
Public: false,
},
{
Name: "internet",
Public: true,
},
},
},
}
capicMachine = &v1alpha1.IONOSCloudMachine{
Expand Down Expand Up @@ -139,6 +161,18 @@ var _ = Describe("IONOSCloudMachine controller", func() {
},
IP: nil,
ProviderID: "",
Nics: []v1alpha1.IONOSNicSpec{
{
LanRef: v1alpha1.IONOSLanRefSpec{
Name: "private",
},
},
{
LanRef: v1alpha1.IONOSLanRefSpec{
Name: "internet",
},
},
},
},
}
identitySecret = &v1.Secret{
Expand Down

0 comments on commit 58745cf

Please sign in to comment.