Skip to content

Commit c2ec58d

Browse files
committed
PowerVS: add AddIPToLoadBalancerPool
We've asked the CAPI provider cluster-api-provider-ibmcloud to prioritize adding the bootstrap VM to the load balancer pools. However, they have not done so. Therefore, we will do it ourselves.
1 parent 19d5337 commit c2ec58d

File tree

3 files changed

+171
-0
lines changed

3 files changed

+171
-0
lines changed

pkg/asset/installconfig/powervs/client.go

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,9 @@ type API interface {
7575

7676
// SSH
7777
CreateSSHKey(ctx context.Context, serviceInstance string, zone string, sshKeyName string, sshKey string) error
78+
79+
// Load Balancer
80+
AddIPToLoadBalancerPool(ctx context.Context, lbID string, poolName string, port int64, ip string) error
7881
}
7982

8083
// Client makes calls to the PowerVS API.
@@ -1178,3 +1181,108 @@ func (c *Client) CreateSSHKey(ctx context.Context, serviceInstance string, zone
11781181

11791182
return nil
11801183
}
1184+
1185+
// AddIPToLoadBalancerPool adds a server to a load balancer pool for the specified port.
1186+
// @TODO Remove once https://github.com/kubernetes-sigs/cluster-api-provider-ibmcloud/issues/1679 is fixed.
1187+
func (c *Client) AddIPToLoadBalancerPool(ctx context.Context, lbID string, poolName string, port int64, ip string) error {
1188+
var (
1189+
glbOptions *vpcv1.GetLoadBalancerOptions
1190+
llbpOptions *vpcv1.ListLoadBalancerPoolsOptions
1191+
llbpmOptions *vpcv1.ListLoadBalancerPoolMembersOptions
1192+
clbpmOptions *vpcv1.CreateLoadBalancerPoolMemberOptions
1193+
lb *vpcv1.LoadBalancer
1194+
lbPools *vpcv1.LoadBalancerPoolCollection
1195+
lbPool vpcv1.LoadBalancerPool
1196+
lbPoolMembers *vpcv1.LoadBalancerPoolMemberCollection
1197+
lbpmtp *vpcv1.LoadBalancerPoolMemberTargetPrototypeIP
1198+
lbpm *vpcv1.LoadBalancerPoolMember
1199+
response *core.DetailedResponse
1200+
err error
1201+
)
1202+
1203+
// Make sure the load balancer exists
1204+
glbOptions = c.vpcAPI.NewGetLoadBalancerOptions(lbID)
1205+
1206+
lb, response, err = c.vpcAPI.GetLoadBalancerWithContext(ctx, glbOptions)
1207+
if err != nil {
1208+
return fmt.Errorf("failed to get load balancer and the response = %+v, err = %w", response, err)
1209+
}
1210+
logrus.Debugf("AddIPToLoadBalancerPool: GLBWC lb = %+v", lb)
1211+
1212+
// Query the existing load balancer pools
1213+
llbpOptions = c.vpcAPI.NewListLoadBalancerPoolsOptions(lbID)
1214+
1215+
lbPools, response, err = c.vpcAPI.ListLoadBalancerPoolsWithContext(ctx, llbpOptions)
1216+
if err != nil {
1217+
return fmt.Errorf("failed to list the load balancer pools and the response = %+v, err = %w",
1218+
response,
1219+
err)
1220+
}
1221+
1222+
// Find the pool with the specified name
1223+
for _, pool := range lbPools.Pools {
1224+
logrus.Debugf("AddIPToLoadBalancerPool: pool.ID = %v", *pool.ID)
1225+
logrus.Debugf("AddIPToLoadBalancerPool: pool.Name = %v", *pool.Name)
1226+
1227+
if *pool.Name == poolName {
1228+
lbPool = pool
1229+
break
1230+
}
1231+
}
1232+
if lbPool.ID == nil {
1233+
return fmt.Errorf("could not find loadbalancer pool with name %s", poolName)
1234+
}
1235+
1236+
// Query the load balancer pool members
1237+
llbpmOptions = c.vpcAPI.NewListLoadBalancerPoolMembersOptions(lbID, *lbPool.ID)
1238+
1239+
lbPoolMembers, response, err = c.vpcAPI.ListLoadBalancerPoolMembersWithContext(ctx, llbpmOptions)
1240+
if err != nil {
1241+
return fmt.Errorf("failed to list load balancer pool members and the response = %+v, err = %w",
1242+
response,
1243+
err)
1244+
}
1245+
1246+
// See if a member already exists with that IP
1247+
for _, poolMember := range lbPoolMembers.Members {
1248+
logrus.Debugf("AddIPToLoadBalancerPool: poolMember.ID = %s", *poolMember.ID)
1249+
1250+
switch pmt := poolMember.Target.(type) {
1251+
case *vpcv1.LoadBalancerPoolMemberTarget:
1252+
logrus.Debugf("AddIPToLoadBalancerPool: pmt.Address = %+v", *pmt.Address)
1253+
if ip == *pmt.Address {
1254+
logrus.Debugf("AddIPToLoadBalancerPool: found %s", ip)
1255+
return nil
1256+
}
1257+
case *vpcv1.LoadBalancerPoolMemberTargetIP:
1258+
logrus.Debugf("AddIPToLoadBalancerPool: pmt.Address = %+v", *pmt.Address)
1259+
if ip == *pmt.Address {
1260+
logrus.Debugf("AddIPToLoadBalancerPool: found %s", ip)
1261+
return nil
1262+
}
1263+
case *vpcv1.LoadBalancerPoolMemberTargetInstanceReference:
1264+
// No IP address, ignore
1265+
default:
1266+
logrus.Debugf("AddIPToLoadBalancerPool: unhandled type %T", poolMember.Target)
1267+
}
1268+
}
1269+
1270+
// Create a new member
1271+
lbpmtp, err = c.vpcAPI.NewLoadBalancerPoolMemberTargetPrototypeIP(ip)
1272+
if err != nil {
1273+
return fmt.Errorf("could not create a new load balancer pool member, err = %w", err)
1274+
}
1275+
logrus.Debugf("AddIPToLoadBalancerPool: lbpmtp = %+v", *lbpmtp)
1276+
1277+
// Add that member to the pool
1278+
clbpmOptions = c.vpcAPI.NewCreateLoadBalancerPoolMemberOptions(lbID, *lbPool.ID, port, lbpmtp)
1279+
logrus.Debugf("AddIPToLoadBalancerPool: clbpmOptions = %+v", clbpmOptions)
1280+
1281+
lbpm, response, err = c.vpcAPI.CreateLoadBalancerPoolMemberWithContext(ctx, clbpmOptions)
1282+
if err != nil {
1283+
return fmt.Errorf("could not add the load balancer pool member and the response = %+v, err = %w", response, err)
1284+
}
1285+
logrus.Debugf("AddIPToLoadBalancerPool: CLBPMWC lbpm = %+v", lbpm)
1286+
1287+
return nil
1288+
}

pkg/asset/installconfig/powervs/mock/powervsclient_generated.go

Lines changed: 14 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/infrastructure/powervs/clusterapi/powervs.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,7 @@ func findMachineAddress(ctx context.Context, in clusterapi.PostProvisionInput, k
324324
func (p Provider) PostProvision(ctx context.Context, in clusterapi.PostProvisionInput) error {
325325
var (
326326
client *powervsconfig.Client
327+
vpcRegion string
327328
ipAddr string
328329
refServiceInstance *capibm.IBMPowerVSResourceReference
329330
sshKeyName string
@@ -340,6 +341,19 @@ func (p Provider) PostProvision(ctx context.Context, in clusterapi.PostProvision
340341
}
341342
logrus.Debugf("PostProvision: NewClient returns %+v", client)
342343

344+
// We need to set the region we will eventually query inside
345+
vpcRegion = in.InstallConfig.Config.Platform.PowerVS.VPCRegion
346+
if vpcRegion == "" {
347+
vpcRegion, err = powervstypes.VPCRegionForPowerVSRegion(in.InstallConfig.Config.Platform.PowerVS.Region)
348+
if err != nil {
349+
return fmt.Errorf("failed to get VPC region (%s) in PostProvision: %w", vpcRegion, err)
350+
}
351+
}
352+
logrus.Debugf("InfraReady: vpcRegion = %s", vpcRegion)
353+
if err = client.SetVPCServiceURLForRegion(ctx, vpcRegion); err != nil {
354+
return fmt.Errorf("failed to set the VPC service region (%s) in PostProvision: %w", vpcRegion, err)
355+
}
356+
343357
// Step 1.
344358
// Wait until bootstrap and master nodes have IP addresses. This will verify
345359
// that the Transit Gateway and DHCP server work correctly before continuing on.
@@ -438,5 +452,40 @@ func (p Provider) PostProvision(ctx context.Context, in clusterapi.PostProvision
438452
return fmt.Errorf("failed to add SSH key for the workers(%s): %w", fieldType, err)
439453
}
440454

455+
// Step 3.
456+
// @TODO Remove once https://github.com/kubernetes-sigs/cluster-api-provider-ibmcloud/issues/1679 is fixed
457+
// Add the bootstrap's IP address to the load balancer pool
458+
// Get the cluster from the provider so we can have what load balancers are attached
459+
powerVSCluster := &capibm.IBMPowerVSCluster{}
460+
key = crclient.ObjectKey{
461+
Name: in.InfraID,
462+
Namespace: capiutils.Namespace,
463+
}
464+
logrus.Debugf("PostProvision: cluster key = %+v", key)
465+
if err = in.Client.Get(ctx, key, powerVSCluster); err != nil {
466+
return fmt.Errorf("failed to get PowerVS cluster in PostProvision: %w", err)
467+
}
468+
469+
lbIntExp := regexp.MustCompile(`\b-loadbalancer-int\b$`)
470+
471+
// Find the internal load balancer
472+
for lbKey, loadBalancerStatus := range powerVSCluster.Status.LoadBalancers {
473+
if !lbIntExp.MatchString(lbKey) {
474+
continue
475+
}
476+
logrus.Debugf("PostProvision: Found internal load balancer ID = %s, State = %s, Hostname = %s",
477+
*loadBalancerStatus.ID,
478+
loadBalancerStatus.State,
479+
*loadBalancerStatus.Hostname)
480+
481+
if err = client.AddIPToLoadBalancerPool(ctx,
482+
*loadBalancerStatus.ID,
483+
"additional-pool-22623",
484+
22623,
485+
ipAddr); err != nil {
486+
return fmt.Errorf("failed to add the bootstrap IP to the load balancer pool: %w", err)
487+
}
488+
}
489+
441490
return nil
442491
}

0 commit comments

Comments
 (0)