Skip to content

Commit 1f9046f

Browse files
authored
Enhance UT for ReconcileCOSInstance method (#2339)
1 parent ffe8b8b commit 1f9046f

File tree

4 files changed

+119
-11
lines changed

4 files changed

+119
-11
lines changed

cloud/scope/powervs_cluster.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2307,7 +2307,7 @@ func (s *PowerVSClusterScope) ReconcileCOSInstance(ctx context.Context) error {
23072307
},
23082308
}
23092309

2310-
cosClient, err := cos.NewService(cosOptions, apiKey, *cosServiceInstanceStatus.GUID)
2310+
cosClient, err := cos.NewServiceWrapper(cosOptions, apiKey, *cosServiceInstanceStatus.GUID)
23112311
if err != nil {
23122312
return fmt.Errorf("failed to create COS client: %w", err)
23132313
}

cloud/scope/powervs_cluster_test.go

Lines changed: 108 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,34 +22,36 @@ import (
2222
"os"
2323
"testing"
2424

25+
"go.uber.org/mock/gomock"
26+
2527
"github.com/IBM-Cloud/power-go-client/power/models"
2628
"github.com/IBM/go-sdk-core/v5/core"
2729
"github.com/IBM/ibm-cos-sdk-go/aws/awserr"
30+
"github.com/IBM/ibm-cos-sdk-go/service/s3"
31+
tgapiv1 "github.com/IBM/networking-go-sdk/transitgatewayapisv1"
2832
"github.com/IBM/platform-services-go-sdk/resourcecontrollerv2"
2933
"github.com/IBM/vpc-go-sdk/vpcv1"
3034
regionUtil "github.com/ppc64le-cloud/powervs-utils"
31-
"go.uber.org/mock/gomock"
3235

3336
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3437
"k8s.io/utils/ptr"
3538

36-
tgapiv1 "github.com/IBM/networking-go-sdk/transitgatewayapisv1"
37-
infrav1beta2 "sigs.k8s.io/cluster-api-provider-ibmcloud/api/v1beta2"
38-
mockP "sigs.k8s.io/cluster-api-provider-ibmcloud/pkg/cloud/services/powervs/mock"
39-
tgmock "sigs.k8s.io/cluster-api-provider-ibmcloud/pkg/cloud/services/transitgateway/mock"
4039
capiv1beta1 "sigs.k8s.io/cluster-api/api/v1beta1"
4140

41+
infrav1beta2 "sigs.k8s.io/cluster-api-provider-ibmcloud/api/v1beta2"
4242
"sigs.k8s.io/cluster-api-provider-ibmcloud/cmd/capibmadm/utils"
43+
"sigs.k8s.io/cluster-api-provider-ibmcloud/pkg/cloud/services/cos"
4344
mockcos "sigs.k8s.io/cluster-api-provider-ibmcloud/pkg/cloud/services/cos/mock"
4445
"sigs.k8s.io/cluster-api-provider-ibmcloud/pkg/cloud/services/powervs"
46+
mockP "sigs.k8s.io/cluster-api-provider-ibmcloud/pkg/cloud/services/powervs/mock"
4547
"sigs.k8s.io/cluster-api-provider-ibmcloud/pkg/cloud/services/resourcecontroller"
4648
mockRC "sigs.k8s.io/cluster-api-provider-ibmcloud/pkg/cloud/services/resourcecontroller/mock"
4749
"sigs.k8s.io/cluster-api-provider-ibmcloud/pkg/cloud/services/resourcemanager"
4850
"sigs.k8s.io/cluster-api-provider-ibmcloud/pkg/cloud/services/transitgateway"
51+
tgmock "sigs.k8s.io/cluster-api-provider-ibmcloud/pkg/cloud/services/transitgateway/mock"
4952
"sigs.k8s.io/cluster-api-provider-ibmcloud/pkg/cloud/services/vpc"
5053
"sigs.k8s.io/cluster-api-provider-ibmcloud/pkg/cloud/services/vpc/mock"
5154

52-
"github.com/IBM/ibm-cos-sdk-go/service/s3"
5355
. "github.com/onsi/gomega"
5456
)
5557

@@ -5722,11 +5724,13 @@ func TestDeleteTransitGatewayConnections(t *testing.T) {
57225724
func TestReconcileCOSInstance(t *testing.T) {
57235725
var (
57245726
mockResourceController *mockRC.MockResourceController
5727+
mockCOSController *mockcos.MockCos
57255728
mockCtrl *gomock.Controller
57265729
)
57275730
setup := func(t *testing.T) {
57285731
t.Helper()
57295732
mockCtrl = gomock.NewController(t)
5733+
mockCOSController = mockcos.NewMockCos(mockCtrl)
57305734
mockResourceController = mockRC.NewMockResourceController(mockCtrl)
57315735
}
57325736
teardown := func() {
@@ -5986,14 +5990,110 @@ func TestReconcileCOSInstance(t *testing.T) {
59865990
Name: ptr.To("test-resource-instance-name"),
59875991
}, nil, nil)
59885992

5993+
mockCOSController.EXPECT().GetBucketByName(gomock.Any()).Return(nil, fmt.Errorf("failed to get bucket by name"))
5994+
5995+
cos.NewServiceFunc = func(_ cos.ServiceOptions, _, _ string) (cos.Cos, error) {
5996+
return mockCOSController, nil
5997+
}
5998+
5999+
err = clusterScope.ReconcileCOSInstance(ctx)
6000+
g.Expect(err).ToNot(BeNil())
6001+
g.Expect(clusterScope.IBMPowerVSCluster.Status.COSInstance.ID).To(Equal(ptr.To("test-resource-instance-guid")))
6002+
g.Expect(clusterScope.IBMPowerVSCluster.Status.COSInstance.ControllerCreated).To(Equal(ptr.To(true)))
6003+
})
6004+
t.Run("When create COS bucket fails", func(t *testing.T) {
6005+
g := NewWithT(t)
6006+
setup(t)
6007+
t.Cleanup(teardown)
6008+
err := os.Setenv("IBMCLOUD_APIKEY", "test-api-key")
6009+
g.Expect(err).To(BeNil())
6010+
defer os.Unsetenv("IBMCLOUD_APIKEY")
6011+
6012+
clusterScope := PowerVSClusterScope{
6013+
ResourceClient: mockResourceController,
6014+
IBMPowerVSCluster: &infrav1beta2.IBMPowerVSCluster{
6015+
Spec: infrav1beta2.IBMPowerVSClusterSpec{
6016+
CosInstance: &infrav1beta2.CosInstance{
6017+
BucketRegion: "test-bucket-region",
6018+
},
6019+
ResourceGroup: &infrav1beta2.IBMPowerVSResourceReference{
6020+
ID: ptr.To("test-resource-group-id"),
6021+
},
6022+
},
6023+
Status: infrav1beta2.IBMPowerVSClusterStatus{
6024+
ServiceInstance: &infrav1beta2.ResourceReference{
6025+
ID: ptr.To("test-serviceinstance-id"),
6026+
},
6027+
},
6028+
},
6029+
}
6030+
mockResourceController.EXPECT().GetInstanceByName(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, nil)
6031+
6032+
mockResourceController.EXPECT().CreateResourceInstance(gomock.Any()).Return(&resourcecontrollerv2.ResourceInstance{
6033+
ID: ptr.To("test-resource-instance-id"),
6034+
GUID: ptr.To("test-resource-instance-guid"),
6035+
Name: ptr.To("test-resource-instance-name"),
6036+
}, nil, nil)
6037+
6038+
mockCOSController.EXPECT().GetBucketByName(gomock.Any()).Return(nil, awserr.New(s3.ErrCodeNoSuchBucket, "bucket does not exist", nil))
6039+
mockCOSController.EXPECT().CreateBucket(gomock.Any()).Return(nil, fmt.Errorf("failed to create bucket"))
6040+
6041+
cos.NewServiceFunc = func(_ cos.ServiceOptions, _, _ string) (cos.Cos, error) {
6042+
return mockCOSController, nil
6043+
}
6044+
59896045
err = clusterScope.ReconcileCOSInstance(ctx)
59906046
g.Expect(err).ToNot(BeNil())
59916047
g.Expect(clusterScope.IBMPowerVSCluster.Status.COSInstance.ID).To(Equal(ptr.To("test-resource-instance-guid")))
59926048
g.Expect(clusterScope.IBMPowerVSCluster.Status.COSInstance.ControllerCreated).To(Equal(ptr.To(true)))
59936049
})
59946050

5995-
//TODO: Complete cases to cover control flow on checkCOSBucket and createCOSBucket
5996-
// Github issue: https://github.com/kubernetes-sigs/cluster-api-provider-ibmcloud/issues/2034
6051+
t.Run("When create COS bucket succeeds", func(t *testing.T) {
6052+
g := NewWithT(t)
6053+
setup(t)
6054+
t.Cleanup(teardown)
6055+
err := os.Setenv("IBMCLOUD_APIKEY", "test-api-key")
6056+
g.Expect(err).To(BeNil())
6057+
defer os.Unsetenv("IBMCLOUD_APIKEY")
6058+
6059+
clusterScope := PowerVSClusterScope{
6060+
ResourceClient: mockResourceController,
6061+
IBMPowerVSCluster: &infrav1beta2.IBMPowerVSCluster{
6062+
Spec: infrav1beta2.IBMPowerVSClusterSpec{
6063+
CosInstance: &infrav1beta2.CosInstance{
6064+
BucketRegion: "test-bucket-region",
6065+
},
6066+
ResourceGroup: &infrav1beta2.IBMPowerVSResourceReference{
6067+
ID: ptr.To("test-resource-group-id"),
6068+
},
6069+
},
6070+
Status: infrav1beta2.IBMPowerVSClusterStatus{
6071+
ServiceInstance: &infrav1beta2.ResourceReference{
6072+
ID: ptr.To("test-serviceinstance-id"),
6073+
},
6074+
},
6075+
},
6076+
}
6077+
mockResourceController.EXPECT().GetInstanceByName(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, nil)
6078+
6079+
mockResourceController.EXPECT().CreateResourceInstance(gomock.Any()).Return(&resourcecontrollerv2.ResourceInstance{
6080+
ID: ptr.To("test-resource-instance-id"),
6081+
GUID: ptr.To("test-resource-instance-guid"),
6082+
Name: ptr.To("test-resource-instance-name"),
6083+
}, nil, nil)
6084+
6085+
mockCOSController.EXPECT().GetBucketByName(gomock.Any()).Return(nil, awserr.New(s3.ErrCodeNoSuchBucket, "bucket does not exist", nil))
6086+
mockCOSController.EXPECT().CreateBucket(gomock.Any()).Return(nil, nil)
6087+
6088+
cos.NewServiceFunc = func(_ cos.ServiceOptions, _, _ string) (cos.Cos, error) {
6089+
return mockCOSController, nil
6090+
}
6091+
6092+
err = clusterScope.ReconcileCOSInstance(ctx)
6093+
g.Expect(err).To(BeNil())
6094+
g.Expect(clusterScope.IBMPowerVSCluster.Status.COSInstance.ID).To(Equal(ptr.To("test-resource-instance-guid")))
6095+
g.Expect(clusterScope.IBMPowerVSCluster.Status.COSInstance.ControllerCreated).To(Equal(ptr.To(true)))
6096+
})
59976097
}
59986098

59996099
func TestCheckCOSServiceInstance(t *testing.T) {

cloud/scope/powervs_machine.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -548,7 +548,7 @@ func (m *PowerVSMachineScope) DeleteMachineIgnition(ctx context.Context) error {
548548
}
549549

550550
// createCOSClient creates a new cosClient from the supplied parameters.
551-
func (m *PowerVSMachineScope) createCOSClient(ctx context.Context) (*cos.Service, error) {
551+
func (m *PowerVSMachineScope) createCOSClient(ctx context.Context) (cos.Cos, error) {
552552
log := ctrl.LoggerFrom(ctx)
553553
var cosInstanceName string
554554
if m.IBMPowerVSCluster.Spec.CosInstance == nil || m.IBMPowerVSCluster.Spec.CosInstance.Name == "" {

pkg/cloud/services/cos/service.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,16 @@ func (s *Service) PutPublicAccessBlock(input *s3.PutPublicAccessBlockInput) (*s3
9090
return s.client.PutPublicAccessBlock(input)
9191
}
9292

93+
// NewServiceFunc is a variable that will hold the function reference.
94+
var NewServiceFunc = NewService // Default to the original function
95+
96+
// NewServiceWrapper returns a new service for the IBM Cloud COS api client, useful in unit testing.
97+
func NewServiceWrapper(options ServiceOptions, apikey, serviceInstance string) (Cos, error) {
98+
return NewServiceFunc(options, apikey, serviceInstance)
99+
}
100+
93101
// NewService returns a new service for the IBM Cloud Resource Controller api client.
94-
func NewService(options ServiceOptions, apikey, serviceInstance string) (*Service, error) {
102+
func NewService(options ServiceOptions, apikey, serviceInstance string) (Cos, error) {
95103
if options.Options == nil {
96104
options.Options = &cosSession.Options{}
97105
}

0 commit comments

Comments
 (0)