@@ -22,7 +22,6 @@ import (
22
22
"testing"
23
23
"time"
24
24
25
- "github.com/IBM-Cloud/power-go-client/power/models"
26
25
"go.uber.org/mock/gomock"
27
26
28
27
corev1 "k8s.io/api/core/v1"
@@ -44,7 +43,11 @@ import (
44
43
"sigs.k8s.io/cluster-api-provider-ibmcloud/cloud/scope"
45
44
"sigs.k8s.io/cluster-api-provider-ibmcloud/pkg/cloud/services/powervs"
46
45
"sigs.k8s.io/cluster-api-provider-ibmcloud/pkg/cloud/services/powervs/mock"
46
+ mockVPC "sigs.k8s.io/cluster-api-provider-ibmcloud/pkg/cloud/services/vpc/mock"
47
47
48
+ "github.com/IBM-Cloud/power-go-client/power/models"
49
+ "github.com/IBM/go-sdk-core/v5/core"
50
+ "github.com/IBM/vpc-go-sdk/vpcv1"
48
51
. "github.com/onsi/gomega"
49
52
)
50
53
@@ -368,12 +371,14 @@ func TestIBMPowerVSMachineReconciler_ReconcileOperations(t *testing.T) {
368
371
mockCtrl * gomock.Controller
369
372
machineScope * scope.PowerVSMachineScope
370
373
reconciler IBMPowerVSMachineReconciler
374
+ mockvpc * mockVPC.MockVpc
371
375
)
372
376
373
377
setup := func (t * testing.T ) {
374
378
t .Helper ()
375
379
mockCtrl = gomock .NewController (t )
376
380
mockpowervs = mock .NewMockPowerVS (mockCtrl )
381
+ mockvpc = mockVPC .NewMockVpc (mockCtrl )
377
382
recorder := record .NewFakeRecorder (2 )
378
383
reconciler = IBMPowerVSMachineReconciler {
379
384
Client : testEnv .Client ,
@@ -492,6 +497,303 @@ func TestIBMPowerVSMachineReconciler_ReconcileOperations(t *testing.T) {
492
497
g .Expect (machineScope .IBMPowerVSMachine .Finalizers ).To (ContainElement (infrav1beta2 .IBMPowerVSMachineFinalizer ))
493
498
expectConditions (g , machineScope .IBMPowerVSMachine , []conditionAssertion {{infrav1beta2 .InstanceReadyCondition , corev1 .ConditionFalse , capiv1beta1 .ConditionSeverityError , infrav1beta2 .InstanceProvisionFailedReason }})
494
499
})
500
+
501
+ t .Run ("Should fail reconcile if creation of the load balancer pool member is unsuccessful" , func (t * testing.T ) {
502
+ g := NewWithT (t )
503
+ setup (t )
504
+ t .Cleanup (teardown )
505
+ secret := & corev1.Secret {
506
+ ObjectMeta : metav1.ObjectMeta {
507
+ Labels : map [string ]string {
508
+ capiv1beta1 .ClusterNameLabel : "powervs-cluster" ,
509
+ },
510
+ Name : "bootsecret" ,
511
+ Namespace : "default" ,
512
+ },
513
+ Data : map [string ][]byte {
514
+ "value" : []byte ("user data" ),
515
+ },
516
+ }
517
+
518
+ pvsmachine := & infrav1beta2.IBMPowerVSMachine {
519
+
520
+ ObjectMeta : metav1.ObjectMeta {
521
+ Name : * ptr .To ("capi-test-machine" ),
522
+ Finalizers : []string {infrav1beta2 .IBMPowerVSMachineFinalizer },
523
+ },
524
+ Status : infrav1beta2.IBMPowerVSMachineStatus {
525
+ Ready : true ,
526
+ },
527
+ Spec : infrav1beta2.IBMPowerVSMachineSpec {
528
+ MemoryGiB : 8 ,
529
+ Processors : intstr .FromString ("0.5" ),
530
+ Image : & infrav1beta2.IBMPowerVSResourceReference {
531
+ ID : ptr .To ("capi-image-id" ),
532
+ },
533
+ Network : infrav1beta2.IBMPowerVSResourceReference {
534
+ ID : ptr .To ("capi-net-id" ),
535
+ },
536
+ ServiceInstanceID : * ptr .To ("service-instance-1" ),
537
+ },
538
+ }
539
+
540
+ machine := & capiv1beta1.Machine {
541
+ ObjectMeta : metav1.ObjectMeta {
542
+ Name : "owner-machine" ,
543
+ Namespace : "default" ,
544
+ Labels : map [string ]string {
545
+ "cluster.x-k8s.io/control-plane" : "true" ,
546
+ },
547
+ },
548
+
549
+ Spec : capiv1beta1.MachineSpec {
550
+ Bootstrap : capiv1beta1.Bootstrap {
551
+ DataSecretName : ptr .To ("bootsecret" ),
552
+ },
553
+ },
554
+ }
555
+
556
+ mockclient := fake .NewClientBuilder ().WithObjects ([]client.Object {secret , pvsmachine , machine }... ).Build ()
557
+ machineScope = & scope.PowerVSMachineScope {
558
+ Logger : klog .Background (),
559
+ Client : mockclient ,
560
+
561
+ Cluster : & capiv1beta1.Cluster {
562
+ Status : capiv1beta1.ClusterStatus {
563
+ InfrastructureReady : true ,
564
+ },
565
+ },
566
+ Machine : machine ,
567
+ IBMPowerVSMachine : pvsmachine ,
568
+ IBMPowerVSImage : & infrav1beta2.IBMPowerVSImage {
569
+ Status : infrav1beta2.IBMPowerVSImageStatus {
570
+ Ready : true ,
571
+ },
572
+ },
573
+ IBMVPCClient : mockvpc ,
574
+ IBMPowerVSClient : mockpowervs ,
575
+ DHCPIPCacheStore : cache .NewTTLStore (powervs .CacheKeyFunc , powervs .CacheTTL ),
576
+ IBMPowerVSCluster : & infrav1beta2.IBMPowerVSCluster {
577
+ ObjectMeta : metav1.ObjectMeta {
578
+ Annotations : map [string ]string {
579
+ "powervs.cluster.x-k8s.io/create-infra" : "true" ,
580
+ },
581
+ },
582
+ Spec : infrav1beta2.IBMPowerVSClusterSpec {
583
+ LoadBalancers : []infrav1beta2.VPCLoadBalancerSpec {
584
+ {
585
+ Name : "capi-test-lb" ,
586
+ },
587
+ },
588
+ },
589
+ Status : infrav1beta2.IBMPowerVSClusterStatus {
590
+ LoadBalancers : map [string ]infrav1beta2.VPCLoadBalancerStatus {
591
+ "capi-test-lb" : {
592
+ ID : ptr .To ("capi-test-lb-id" ),
593
+ },
594
+ },
595
+ },
596
+ },
597
+ }
598
+
599
+ instanceReferences := & models.PVMInstances {
600
+ PvmInstances : []* models.PVMInstanceReference {
601
+ {
602
+ PvmInstanceID : ptr .To ("capi-test-machine-id" ),
603
+ ServerName : ptr .To ("capi-test-machine" ),
604
+ },
605
+ },
606
+ }
607
+ instance := & models.PVMInstance {
608
+ PvmInstanceID : ptr .To ("capi-test-machine-id" ),
609
+ ServerName : ptr .To ("capi-test-machine" ),
610
+ Status : ptr .To ("ACTIVE" ),
611
+ Networks : []* models.PVMInstanceNetwork {
612
+ {
613
+ IPAddress : "192.168.7.1" ,
614
+ },
615
+ },
616
+ }
617
+
618
+ loadBalancer := & vpcv1.LoadBalancer {
619
+ ID : core .StringPtr ("capi-test-lb-id" ),
620
+ ProvisioningStatus : core .StringPtr ("active" ),
621
+ Name : core .StringPtr ("capi-test-lb-name" ),
622
+ Pools : []vpcv1.LoadBalancerPoolReference {},
623
+ }
624
+
625
+ mockpowervs .EXPECT ().GetAllInstance ().Return (instanceReferences , nil )
626
+ mockpowervs .EXPECT ().GetInstance (gomock .AssignableToTypeOf ("capi-test-machine-id" )).Return (instance , nil )
627
+ mockvpc .EXPECT ().GetLoadBalancer (gomock .AssignableToTypeOf (& vpcv1.GetLoadBalancerOptions {})).Return (loadBalancer , & core.DetailedResponse {}, nil )
628
+ result , err := reconciler .reconcileNormal (machineScope )
629
+ g .Expect (err ).ToNot (BeNil ())
630
+ g .Expect (result .Requeue ).To ((BeFalse ()))
631
+ g .Expect (result .RequeueAfter ).To (BeZero ())
632
+ g .Expect (machineScope .IBMPowerVSMachine .Finalizers ).To (ContainElement (infrav1beta2 .IBMPowerVSMachineFinalizer ))
633
+ expectConditions (g , machineScope .IBMPowerVSMachine , []conditionAssertion {{infrav1beta2 .InstanceReadyCondition , corev1 .ConditionTrue , "" , "" }})
634
+ })
635
+
636
+ t .Run ("Should requeue if the load balancer pool member is created successfully, but its provisioning status is not active" , func (t * testing.T ) {
637
+ g := NewWithT (t )
638
+ setup (t )
639
+ t .Cleanup (teardown )
640
+ secret := & corev1.Secret {
641
+ ObjectMeta : metav1.ObjectMeta {
642
+ Labels : map [string ]string {
643
+ capiv1beta1 .ClusterNameLabel : "powervs-cluster" ,
644
+ },
645
+ Name : "bootsecret" ,
646
+ Namespace : "default" ,
647
+ },
648
+ Data : map [string ][]byte {
649
+ "value" : []byte ("user data" ),
650
+ },
651
+ }
652
+
653
+ pvsmachine := & infrav1beta2.IBMPowerVSMachine {
654
+
655
+ ObjectMeta : metav1.ObjectMeta {
656
+ Name : * ptr .To ("capi-test-machine" ),
657
+ Finalizers : []string {infrav1beta2 .IBMPowerVSMachineFinalizer },
658
+ },
659
+ Status : infrav1beta2.IBMPowerVSMachineStatus {
660
+ Ready : true ,
661
+ },
662
+ Spec : infrav1beta2.IBMPowerVSMachineSpec {
663
+ MemoryGiB : 8 ,
664
+ Processors : intstr .FromString ("0.5" ),
665
+ Image : & infrav1beta2.IBMPowerVSResourceReference {
666
+ ID : ptr .To ("capi-image-id" ),
667
+ },
668
+ Network : infrav1beta2.IBMPowerVSResourceReference {
669
+ ID : ptr .To ("capi-net-id" ),
670
+ },
671
+ ServiceInstanceID : * ptr .To ("service-instance-1" ),
672
+ },
673
+ }
674
+
675
+ machine := & capiv1beta1.Machine {
676
+ ObjectMeta : metav1.ObjectMeta {
677
+ Name : "owner-machine" ,
678
+ Namespace : "default" ,
679
+ Labels : map [string ]string {
680
+ "cluster.x-k8s.io/control-plane" : "true" ,
681
+ },
682
+ },
683
+
684
+ Spec : capiv1beta1.MachineSpec {
685
+ Bootstrap : capiv1beta1.Bootstrap {
686
+ DataSecretName : ptr .To ("bootsecret" ),
687
+ },
688
+ },
689
+ }
690
+
691
+ mockclient := fake .NewClientBuilder ().WithObjects ([]client.Object {secret , pvsmachine , machine }... ).Build ()
692
+ machineScope = & scope.PowerVSMachineScope {
693
+ Logger : klog .Background (),
694
+ Client : mockclient ,
695
+
696
+ Cluster : & capiv1beta1.Cluster {
697
+ Status : capiv1beta1.ClusterStatus {
698
+ InfrastructureReady : true ,
699
+ },
700
+ },
701
+ Machine : machine ,
702
+ IBMPowerVSMachine : pvsmachine ,
703
+ IBMPowerVSImage : & infrav1beta2.IBMPowerVSImage {
704
+ Status : infrav1beta2.IBMPowerVSImageStatus {
705
+ Ready : true ,
706
+ },
707
+ },
708
+ IBMVPCClient : mockvpc ,
709
+ IBMPowerVSClient : mockpowervs ,
710
+ DHCPIPCacheStore : cache .NewTTLStore (powervs .CacheKeyFunc , powervs .CacheTTL ),
711
+ IBMPowerVSCluster : & infrav1beta2.IBMPowerVSCluster {
712
+ ObjectMeta : metav1.ObjectMeta {
713
+ Annotations : map [string ]string {
714
+ "powervs.cluster.x-k8s.io/create-infra" : "true" ,
715
+ },
716
+ },
717
+ Spec : infrav1beta2.IBMPowerVSClusterSpec {
718
+ LoadBalancers : []infrav1beta2.VPCLoadBalancerSpec {
719
+ {
720
+ Name : "capi-test-lb" ,
721
+ },
722
+ },
723
+ },
724
+ Status : infrav1beta2.IBMPowerVSClusterStatus {
725
+ LoadBalancers : map [string ]infrav1beta2.VPCLoadBalancerStatus {
726
+ "capi-test-lb" : {
727
+ ID : ptr .To ("capi-test-lb-id" ),
728
+ },
729
+ },
730
+ },
731
+ },
732
+ }
733
+
734
+ instanceReferences := & models.PVMInstances {
735
+ PvmInstances : []* models.PVMInstanceReference {
736
+ {
737
+ PvmInstanceID : ptr .To ("capi-test-machine-id" ),
738
+ ServerName : ptr .To ("capi-test-machine" ),
739
+ },
740
+ },
741
+ }
742
+ instance := & models.PVMInstance {
743
+ PvmInstanceID : ptr .To ("capi-test-machine-id" ),
744
+ ServerName : ptr .To ("capi-test-machine" ),
745
+ Status : ptr .To ("ACTIVE" ),
746
+ Networks : []* models.PVMInstanceNetwork {
747
+ {
748
+ IPAddress : "192.168.7.1" ,
749
+ },
750
+ },
751
+ }
752
+
753
+ loadBalancer := & vpcv1.LoadBalancer {
754
+ ID : core .StringPtr ("capi-test-lb-id" ),
755
+ ProvisioningStatus : core .StringPtr ("active" ),
756
+ Name : core .StringPtr ("capi-test-lb-name" ),
757
+ Pools : []vpcv1.LoadBalancerPoolReference {
758
+ {
759
+ ID : core .StringPtr ("capi-test-lb-pool-id" ),
760
+ Name : core .StringPtr ("capi-test-lb-pool-name" ),
761
+ },
762
+ },
763
+ }
764
+
765
+ loadBalancerPoolMemberCollection := & vpcv1.LoadBalancerPoolMemberCollection {
766
+ Members : []vpcv1.LoadBalancerPoolMember {
767
+ {
768
+ Port : core .Int64Ptr (int64 (infrav1beta2 .DefaultAPIServerPort )),
769
+ Target : & vpcv1.LoadBalancerPoolMemberTarget {
770
+ Address : core .StringPtr ("192.168.1.1" ),
771
+ },
772
+ ID : core .StringPtr ("capi-test-lb-pool-id" ),
773
+ },
774
+ },
775
+ }
776
+
777
+ loadBalancerPoolMember := & vpcv1.LoadBalancerPoolMember {
778
+ ID : core .StringPtr ("capi-test-lb-pool-member-id" ),
779
+ Port : core .Int64Ptr (int64 (infrav1beta2 .DefaultAPIServerPort )),
780
+ ProvisioningStatus : core .StringPtr ("update-pending" ),
781
+ }
782
+
783
+ mockpowervs .EXPECT ().GetAllInstance ().Return (instanceReferences , nil )
784
+ mockpowervs .EXPECT ().GetInstance (gomock .AssignableToTypeOf ("capi-test-machine-id" )).Return (instance , nil )
785
+ mockvpc .EXPECT ().GetLoadBalancer (gomock .AssignableToTypeOf (& vpcv1.GetLoadBalancerOptions {})).Return (loadBalancer , & core.DetailedResponse {}, nil )
786
+ mockvpc .EXPECT ().ListLoadBalancerPoolMembers (gomock .AssignableToTypeOf (& vpcv1.ListLoadBalancerPoolMembersOptions {})).Return (loadBalancerPoolMemberCollection , & core.DetailedResponse {}, nil )
787
+ mockvpc .EXPECT ().CreateLoadBalancerPoolMember (gomock .AssignableToTypeOf (& vpcv1.CreateLoadBalancerPoolMemberOptions {})).Return (loadBalancerPoolMember , & core.DetailedResponse {}, nil )
788
+ mockvpc .EXPECT ().GetLoadBalancer (gomock .AssignableToTypeOf (& vpcv1.GetLoadBalancerOptions {})).Return (loadBalancer , & core.DetailedResponse {}, nil )
789
+ result , err := reconciler .reconcileNormal (machineScope )
790
+ g .Expect (err ).To (BeNil ())
791
+ g .Expect (result .RequeueAfter ).To (Not (BeZero ()))
792
+ g .Expect (machineScope .IBMPowerVSMachine .Status .Ready ).To (Equal (true ))
793
+ g .Expect (machineScope .IBMPowerVSMachine .Finalizers ).To (ContainElement (infrav1beta2 .IBMPowerVSMachineFinalizer ))
794
+ expectConditions (g , machineScope .IBMPowerVSMachine , []conditionAssertion {{infrav1beta2 .InstanceReadyCondition , corev1 .ConditionTrue , "" , "" }})
795
+ })
796
+
495
797
t .Run ("Should reconcile IBMPowerVSMachine instance creation in different states" , func (t * testing.T ) {
496
798
g := NewWithT (t )
497
799
setup (t )
@@ -629,6 +931,134 @@ func TestIBMPowerVSMachineReconciler_ReconcileOperations(t *testing.T) {
629
931
})
630
932
})
631
933
})
934
+
935
+ t .Run ("Should skip creation of loadbalancer pool member if not control plane machine" , func (t * testing.T ) {
936
+ g := NewWithT (t )
937
+ setup (t )
938
+ t .Cleanup (teardown )
939
+ secret := & corev1.Secret {
940
+ ObjectMeta : metav1.ObjectMeta {
941
+ Labels : map [string ]string {
942
+ capiv1beta1 .ClusterNameLabel : "powervs-cluster" ,
943
+ },
944
+ Name : "bootsecret" ,
945
+ Namespace : "default" ,
946
+ },
947
+ Data : map [string ][]byte {
948
+ "value" : []byte ("user data" ),
949
+ },
950
+ }
951
+
952
+ pvsmachine := & infrav1beta2.IBMPowerVSMachine {
953
+
954
+ ObjectMeta : metav1.ObjectMeta {
955
+ Name : * ptr .To ("capi-test-machine" ),
956
+ Finalizers : []string {infrav1beta2 .IBMPowerVSMachineFinalizer },
957
+ Labels : map [string ]string {
958
+ "node-role.kubernetes.io/worker" : "true" ,
959
+ },
960
+ },
961
+ Status : infrav1beta2.IBMPowerVSMachineStatus {
962
+ Ready : true ,
963
+ },
964
+ Spec : infrav1beta2.IBMPowerVSMachineSpec {
965
+ MemoryGiB : 8 ,
966
+ Processors : intstr .FromString ("0.5" ),
967
+ Image : & infrav1beta2.IBMPowerVSResourceReference {
968
+ ID : ptr .To ("capi-image-id" ),
969
+ },
970
+ Network : infrav1beta2.IBMPowerVSResourceReference {
971
+ ID : ptr .To ("capi-net-id" ),
972
+ },
973
+ ServiceInstanceID : * ptr .To ("service-instance-1" ),
974
+ },
975
+ }
976
+
977
+ machine := & capiv1beta1.Machine {
978
+ ObjectMeta : metav1.ObjectMeta {
979
+ Name : "owner-machine" ,
980
+ Namespace : "default" ,
981
+ },
982
+
983
+ Spec : capiv1beta1.MachineSpec {
984
+ Bootstrap : capiv1beta1.Bootstrap {
985
+ DataSecretName : ptr .To ("bootsecret" ),
986
+ },
987
+ },
988
+ }
989
+
990
+ mockclient := fake .NewClientBuilder ().WithObjects ([]client.Object {secret , pvsmachine , machine }... ).Build ()
991
+
992
+ machineScope = & scope.PowerVSMachineScope {
993
+ Logger : klog .Background (),
994
+ Client : mockclient ,
995
+
996
+ Cluster : & capiv1beta1.Cluster {
997
+ Status : capiv1beta1.ClusterStatus {
998
+ InfrastructureReady : true ,
999
+ },
1000
+ },
1001
+ Machine : machine ,
1002
+ IBMPowerVSMachine : pvsmachine ,
1003
+ IBMPowerVSImage : & infrav1beta2.IBMPowerVSImage {
1004
+ Status : infrav1beta2.IBMPowerVSImageStatus {
1005
+ Ready : true ,
1006
+ },
1007
+ },
1008
+ IBMPowerVSClient : mockpowervs ,
1009
+ DHCPIPCacheStore : cache .NewTTLStore (powervs .CacheKeyFunc , powervs .CacheTTL ),
1010
+ IBMPowerVSCluster : & infrav1beta2.IBMPowerVSCluster {
1011
+ ObjectMeta : metav1.ObjectMeta {
1012
+ Annotations : map [string ]string {
1013
+ "powervs.cluster.x-k8s.io/create-infra" : "true" ,
1014
+ },
1015
+ },
1016
+ Spec : infrav1beta2.IBMPowerVSClusterSpec {
1017
+ LoadBalancers : []infrav1beta2.VPCLoadBalancerSpec {
1018
+ {
1019
+ Name : "capi-test-lb" ,
1020
+ },
1021
+ },
1022
+ },
1023
+ Status : infrav1beta2.IBMPowerVSClusterStatus {
1024
+ LoadBalancers : map [string ]infrav1beta2.VPCLoadBalancerStatus {
1025
+ "capi-test-lb" : {
1026
+ ID : ptr .To ("capi-test-lb-id" ),
1027
+ },
1028
+ },
1029
+ },
1030
+ },
1031
+ }
1032
+
1033
+ instanceReferences := & models.PVMInstances {
1034
+ PvmInstances : []* models.PVMInstanceReference {
1035
+ {
1036
+ PvmInstanceID : ptr .To ("capi-test-machine-id" ),
1037
+ ServerName : ptr .To ("capi-test-machine" ),
1038
+ },
1039
+ },
1040
+ }
1041
+ instance := & models.PVMInstance {
1042
+ PvmInstanceID : ptr .To ("capi-test-machine-id" ),
1043
+ ServerName : ptr .To ("capi-test-machine" ),
1044
+ Status : ptr .To ("ACTIVE" ),
1045
+ Networks : []* models.PVMInstanceNetwork {
1046
+ {
1047
+ IPAddress : "192.168.7.1" ,
1048
+ },
1049
+ },
1050
+ }
1051
+
1052
+ mockpowervs .EXPECT ().GetAllInstance ().Return (instanceReferences , nil )
1053
+ mockpowervs .EXPECT ().GetInstance (gomock .AssignableToTypeOf ("capi-test-machine-id" )).Return (instance , nil )
1054
+ result , err := reconciler .reconcileNormal (machineScope )
1055
+ g .Expect (err ).To (BeNil ())
1056
+ g .Expect (result .Requeue ).To (BeFalse ())
1057
+ g .Expect (result .RequeueAfter ).To (BeZero ())
1058
+ g .Expect (machineScope .IBMPowerVSMachine .Status .Ready ).To (Equal (true ))
1059
+ g .Expect (machineScope .IBMPowerVSMachine .Finalizers ).To (ContainElement (infrav1beta2 .IBMPowerVSMachineFinalizer ))
1060
+ expectConditions (g , machineScope .IBMPowerVSMachine , []conditionAssertion {{infrav1beta2 .InstanceReadyCondition , corev1 .ConditionTrue , "" , "" }})
1061
+ })
632
1062
}
633
1063
634
1064
type conditionAssertion struct {
0 commit comments