@@ -31,8 +31,11 @@ import (
31
31
"github.com/gophercloud/gophercloud/v2/openstack/networking/v2/ports"
32
32
. "github.com/onsi/gomega" //nolint:revive
33
33
"go.uber.org/mock/gomock"
34
+ corev1 "k8s.io/api/core/v1"
34
35
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
35
36
"k8s.io/utils/ptr"
37
+ clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
38
+ "sigs.k8s.io/cluster-api/util/conditions"
36
39
37
40
infrav1alpha1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha1"
38
41
infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
@@ -548,3 +551,184 @@ func Test_OpenStackServerReconcileCreate(t *testing.T) {
548
551
})
549
552
}
550
553
}
554
+
555
+ func TestOpenStackServerReconciler_getOrCreateServer (t * testing.T ) {
556
+ tests := []struct {
557
+ name string
558
+ openStackServer * infrav1alpha1.OpenStackServer
559
+ setupMocks func (r * recorders )
560
+ wantServer * servers.Server
561
+ wantErr bool
562
+ wantCondition * clusterv1.Condition
563
+ }{
564
+ {
565
+ name : "instanceID set in status but server not found" ,
566
+ openStackServer : & infrav1alpha1.OpenStackServer {
567
+ Status : infrav1alpha1.OpenStackServerStatus {
568
+ InstanceID : ptr .To (instanceUUID ),
569
+ },
570
+ },
571
+ setupMocks : func (r * recorders ) {
572
+ r .compute .GetServer (instanceUUID ).Return (nil , gophercloud.ErrUnexpectedResponseCode {Actual : 404 })
573
+ },
574
+ wantErr : false ,
575
+ wantCondition : & clusterv1.Condition {
576
+ Type : infrav1 .InstanceReadyCondition ,
577
+ Status : corev1 .ConditionFalse ,
578
+ Reason : infrav1 .InstanceNotFoundReason ,
579
+ Message : infrav1 .ServerUnexpectedDeletedMessage ,
580
+ },
581
+ },
582
+ {
583
+ name : "instanceID set in status but server not found with error" ,
584
+ openStackServer : & infrav1alpha1.OpenStackServer {
585
+ Status : infrav1alpha1.OpenStackServerStatus {
586
+ InstanceID : ptr .To (instanceUUID ),
587
+ },
588
+ },
589
+ setupMocks : func (r * recorders ) {
590
+ r .compute .GetServer (instanceUUID ).Return (nil , fmt .Errorf ("error" ))
591
+ },
592
+ wantErr : true ,
593
+ wantCondition : & clusterv1.Condition {
594
+ Type : infrav1 .InstanceReadyCondition ,
595
+ Status : corev1 .ConditionFalse ,
596
+ Reason : infrav1 .OpenStackErrorReason ,
597
+ Message : "get server \" " + instanceUUID + "\" detail failed: error" ,
598
+ },
599
+ },
600
+ {
601
+ name : "instanceStatus is nil but server found with machine name" ,
602
+ openStackServer : & infrav1alpha1.OpenStackServer {
603
+ ObjectMeta : metav1.ObjectMeta {
604
+ Name : openStackServerName ,
605
+ },
606
+ Status : infrav1alpha1.OpenStackServerStatus {},
607
+ },
608
+ setupMocks : func (r * recorders ) {
609
+ r .compute .ListServers (servers.ListOpts {
610
+ Name : "^" + openStackServerName + "$" ,
611
+ }).Return ([]servers.Server {{ID : instanceUUID }}, nil )
612
+ },
613
+ wantErr : false ,
614
+ wantServer : & servers.Server {
615
+ ID : instanceUUID ,
616
+ },
617
+ },
618
+ {
619
+ name : "instanceStatus is nil and server not found and then created" ,
620
+ openStackServer : & infrav1alpha1.OpenStackServer {
621
+ ObjectMeta : metav1.ObjectMeta {
622
+ Name : openStackServerName ,
623
+ },
624
+ Status : infrav1alpha1.OpenStackServerStatus {
625
+ Resolved : & infrav1alpha1.ResolvedServerSpec {
626
+ ImageID : imageUUID ,
627
+ FlavorID : flavorUUID ,
628
+ Ports : defaultResolvedPorts ,
629
+ },
630
+ },
631
+ },
632
+ setupMocks : func (r * recorders ) {
633
+ r .compute .ListServers (servers.ListOpts {
634
+ Name : "^" + openStackServerName + "$" ,
635
+ }).Return ([]servers.Server {}, nil )
636
+ r .compute .CreateServer (gomock .Any (), gomock .Any ()).Return (& servers.Server {ID : instanceUUID }, nil )
637
+ },
638
+ wantErr : false ,
639
+ wantServer : & servers.Server {
640
+ ID : instanceUUID ,
641
+ },
642
+ // It's off but no condition is set because the server creation was kicked off but we
643
+ // don't know the result yet in this function.
644
+ },
645
+ {
646
+ name : "instanceStatus is nil and server not found and then created with error" ,
647
+ openStackServer : & infrav1alpha1.OpenStackServer {
648
+ ObjectMeta : metav1.ObjectMeta {
649
+ Name : openStackServerName ,
650
+ },
651
+ Status : infrav1alpha1.OpenStackServerStatus {
652
+ Resolved : & infrav1alpha1.ResolvedServerSpec {
653
+ ImageID : imageUUID ,
654
+ FlavorID : flavorUUID ,
655
+ Ports : defaultResolvedPorts ,
656
+ },
657
+ },
658
+ },
659
+ setupMocks : func (r * recorders ) {
660
+ r .compute .ListServers (servers.ListOpts {
661
+ Name : "^" + openStackServerName + "$" ,
662
+ }).Return ([]servers.Server {}, nil )
663
+ r .compute .CreateServer (gomock .Any (), gomock .Any ()).Return (nil , fmt .Errorf ("error" ))
664
+ },
665
+ wantErr : true ,
666
+ wantCondition : & clusterv1.Condition {
667
+ Type : infrav1 .InstanceReadyCondition ,
668
+ Status : corev1 .ConditionFalse ,
669
+ Reason : infrav1 .InstanceCreateFailedReason ,
670
+ Message : "error creating Openstack instance: " + "error" ,
671
+ },
672
+ },
673
+ }
674
+
675
+ for _ , tt := range tests {
676
+ t .Run (tt .name , func (t * testing.T ) {
677
+ g := NewGomegaWithT (t )
678
+ log := testr .New (t )
679
+
680
+ mockCtrl := gomock .NewController (t )
681
+ defer mockCtrl .Finish ()
682
+
683
+ mockScopeFactory := scope .NewMockScopeFactory (mockCtrl , "" )
684
+ scopeWithLogger := scope .NewWithLogger (mockScopeFactory , log )
685
+
686
+ computeRecorder := mockScopeFactory .ComputeClient .EXPECT ()
687
+ imageRecorder := mockScopeFactory .ImageClient .EXPECT ()
688
+ networkRecorder := mockScopeFactory .NetworkClient .EXPECT ()
689
+ volumeRecorder := mockScopeFactory .VolumeClient .EXPECT ()
690
+
691
+ recorders := & recorders {
692
+ compute : computeRecorder ,
693
+ image : imageRecorder ,
694
+ network : networkRecorder ,
695
+ volume : volumeRecorder ,
696
+ }
697
+
698
+ if tt .setupMocks != nil {
699
+ tt .setupMocks (recorders )
700
+ }
701
+
702
+ computeService , err := compute .NewService (scopeWithLogger )
703
+ g .Expect (err ).ToNot (HaveOccurred ())
704
+
705
+ reconciler := OpenStackServerReconciler {}
706
+ status , err := reconciler .getOrCreateServer (ctx , log , tt .openStackServer , computeService , []string {portUUID })
707
+
708
+ // Check error result
709
+ if tt .wantErr {
710
+ g .Expect (err ).To (HaveOccurred ())
711
+ } else {
712
+ g .Expect (err ).ToNot (HaveOccurred ())
713
+ }
714
+
715
+ // Check instance status
716
+ if tt .wantServer != nil {
717
+ g .Expect (status .ID ()).To (Equal (tt .wantServer .ID ))
718
+ }
719
+
720
+ // Check the condition is set correctly
721
+ if tt .wantCondition != nil {
722
+ // print openstackServer conditions
723
+ for _ , condition := range tt .openStackServer .Status .Conditions {
724
+ t .Logf ("Condition: %s, Status: %s, Reason: %s" , condition .Type , condition .Status , condition .Reason )
725
+ }
726
+ conditionType := conditions .Get (tt .openStackServer , tt .wantCondition .Type )
727
+ g .Expect (conditionType ).ToNot (BeNil ())
728
+ g .Expect (conditionType .Status ).To (Equal (tt .wantCondition .Status ))
729
+ g .Expect (conditionType .Reason ).To (Equal (tt .wantCondition .Reason ))
730
+ g .Expect (conditionType .Message ).To (Equal (tt .wantCondition .Message ))
731
+ }
732
+ })
733
+ }
734
+ }
0 commit comments