@@ -44,6 +44,8 @@ import (
4444 "github.com/IBM/vpc-go-sdk/vpcv1"
4545
4646 corev1 "k8s.io/api/core/v1"
47+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
48+ "k8s.io/apimachinery/pkg/labels"
4749 "k8s.io/apimachinery/pkg/types"
4850 "k8s.io/apimachinery/pkg/util/intstr"
4951 "k8s.io/client-go/tools/cache"
@@ -996,7 +998,49 @@ func (m *PowerVSMachineScope) CreateVPCLoadBalancerPoolMember(ctx context.Contex
996998
997999 internalIP := m .GetMachineInternalIP ()
9981000
1001+ // lbAdditionalListeners is a mapping of additionalListener's port-protocol to the additionalListener as defined in the specification
1002+ // It will be used later to get the default pool associated with the listener
1003+ lbAdditionalListeners := map [string ]infrav1beta2.AdditionalListenerSpec {}
1004+ for _ , additionalListener := range lb .AdditionalListeners {
1005+ if additionalListener .Protocol == nil {
1006+ additionalListener .Protocol = & infrav1beta2 .VPCLoadBalancerListenerProtocolTCP
1007+ }
1008+ lbAdditionalListeners [fmt .Sprintf ("%d-%s" , additionalListener .Port , * additionalListener .Protocol )] = additionalListener
1009+ }
1010+
1011+ // loadBalancerListeners is a mapping of the loadBalancer listener's defaultPoolName to the additionalListener
1012+ // as the default pool name might be empty in spec and should be fetched from the cloud's listener
1013+ loadBalancerListeners := map [string ]infrav1beta2.AdditionalListenerSpec {}
1014+ for _ , listener := range loadBalancer .Listeners {
1015+ listenerOptions := & vpcv1.GetLoadBalancerListenerOptions {}
1016+ listenerOptions .SetLoadBalancerID (* loadBalancer .ID )
1017+ listenerOptions .SetID (* listener .ID )
1018+ loadBalancerListener , _ , err := m .IBMVPCClient .GetLoadBalancerListener (listenerOptions )
1019+ if err != nil {
1020+ return nil , fmt .Errorf ("failed to list %s load balancer listener: %w" , * listener .ID , err )
1021+ }
1022+ if additionalListener , ok := lbAdditionalListeners [fmt .Sprintf ("%d-%s" , * loadBalancerListener .Port , * loadBalancerListener .Protocol )]; ok {
1023+ if loadBalancerListener .DefaultPool != nil {
1024+ loadBalancerListeners [* loadBalancerListener .DefaultPool .Name ] = additionalListener
1025+ }
1026+ // loadBalancerListeners map is created only with the listeners provided in the spec,
1027+ // and targetPort is populated only if there is an entry in the map.
1028+ // Inorder for the default pool 6443 to be added to all control plane machines, creating an entry in the map for the same.
1029+ } else if loadBalancerListener .Port != nil && * loadBalancerListener .Port == int64 (6443 ) {
1030+ protocol := infrav1beta2 .VPCLoadBalancerListenerProtocol (* loadBalancerListener .Protocol )
1031+ listener := infrav1beta2.AdditionalListenerSpec {
1032+ Port : * loadBalancerListener .Port ,
1033+ Protocol : & protocol ,
1034+ }
1035+ if loadBalancerListener .DefaultPool != nil {
1036+ loadBalancerListeners [* loadBalancerListener .DefaultPool .Name ] = listener
1037+ } else {
1038+ log .V (3 ).Error (fmt .Errorf ("unable to get the default pool details" ), "default pool is nil" , "port" , loadBalancerListener .Port )
1039+ }
1040+ }
1041+ }
9991042 // Update each LoadBalancer pool
1043+ // For each pool, get the additionalListener associated with the pool from the loadBalancerListeners map.
10001044 for _ , pool := range loadBalancer .Pools {
10011045 log .V (3 ).Info ("Updating LoadBalancer pool member" , "pool" , * pool .Name , "loadBalancerName" , * loadBalancer .Name , "IP" , internalIP )
10021046 listOptions := & vpcv1.ListLoadBalancerPoolMembersOptions {}
@@ -1009,32 +1053,35 @@ func (m *PowerVSMachineScope) CreateVPCLoadBalancerPoolMember(ctx context.Contex
10091053 var targetPort int64
10101054 var alreadyRegistered bool
10111055
1012- if len (listLoadBalancerPoolMembers .Members ) == 0 {
1013- // For adding the first member to the pool we depend on the pool name to get the target port
1014- // pool name will have port number appended at the end
1015- lbNameSplit := strings .Split (* pool .Name , "-" )
1016- if len (lbNameSplit ) == 0 {
1017- // user might have created additional pool
1018- log .V (3 ).Info ("Not updating pool as it might be created externally" , "poolName" , * pool .Name )
1056+ if loadBalancerListener , ok := loadBalancerListeners [* pool .Name ]; ok {
1057+ targetPort = loadBalancerListener .Port
1058+ log .V (3 ).Info ("Checking if machine label matches with the label selector in listener" , "machineLabel" , m .IBMPowerVSMachine .Labels , "labelSelector" , loadBalancerListener .Selector )
1059+ selector , err := metav1 .LabelSelectorAsSelector (& loadBalancerListener .Selector )
1060+ if err != nil {
1061+ log .V (5 ).Error (err , "Skipping listener addition, failed to get label selector from spec selector" )
10191062 continue
10201063 }
1021- targetPort , err = strconv .ParseInt (lbNameSplit [len (lbNameSplit )- 1 ], 10 , 64 )
1022- if err != nil {
1023- // user might have created additional pool
1024- log .Error (err , "unable to fetch target port from pool name" , "poolName" , * pool .Name )
1064+
1065+ if selector .Empty () && ! util .IsControlPlaneMachine (m .Machine ) {
1066+ log .V (3 ).Info ("Skipping listener addition as the selector is empty and not a control plane machine" )
10251067 continue
10261068 }
1027- } else {
1028- for _ , member := range listLoadBalancerPoolMembers .Members {
1029- if target , ok := member .Target .(* vpcv1.LoadBalancerPoolMemberTarget ); ok {
1030- targetPort = * member .Port
1031- if * target .Address == internalIP {
1032- alreadyRegistered = true
1033- log .V (3 ).Info ("Target IP already configured for pool" , "IP" , internalIP , "poolName" , * pool .Name )
1034- }
1069+ // Skip adding the listener if the selector does not match
1070+ if ! selector .Empty () && ! selector .Matches (labels .Set (m .IBMPowerVSMachine .Labels )) {
1071+ log .V (3 ).Info ("Skip adding listener, machine label doesn't match with the listener label selector" , "pool" , * pool .Name , "IP" , internalIP )
1072+ continue
1073+ }
1074+ }
1075+
1076+ for _ , member := range listLoadBalancerPoolMembers .Members {
1077+ if target , ok := member .Target .(* vpcv1.LoadBalancerPoolMemberTarget ); ok {
1078+ if * target .Address == internalIP {
1079+ alreadyRegistered = true
1080+ log .V (3 ).Info ("Target IP already configured for pool" , "IP" , internalIP , "poolName" , * pool .Name )
10351081 }
10361082 }
10371083 }
1084+
10381085 if alreadyRegistered {
10391086 log .V (3 ).Info ("PoolMember already exist" , "poolName" , * pool .Name , "IP" , internalIP , "targetPort" , targetPort )
10401087 continue
0 commit comments