From d6d4f9ef7fcefa0ea54ec184675931826073acd2 Mon Sep 17 00:00:00 2001 From: Xudong Liu Date: Fri, 26 Jan 2024 17:48:54 +0800 Subject: [PATCH] remove controller runtime dependency Signed-off-by: Xudong Liu --- .../vsphereparavirtual/instances.go | 4 +- .../vsphereparavirtual/instances_test.go | 30 ++--- .../vsphereparavirtual/loadbalancer_test.go | 41 +++--- .../vsphereparavirtual/vmoperator.go | 19 ++- .../vsphereparavirtual/vmservice/types.go | 4 +- .../vsphereparavirtual/vmservice/vmservice.go | 34 ++--- .../vmservice/vmservice_test.go | 34 ++--- pkg/cloudprovider/vsphereparavirtual/zone.go | 5 +- .../vsphereparavirtual/zone_test.go | 11 +- pkg/util/fake_client_wrapper.go | 126 ------------------ pkg/util/fake_vm_client_wrapper.go | 97 ++++++++++++++ pkg/util/fake_vm_service_client_wrapper.go | 97 ++++++++++++++ 12 files changed, 273 insertions(+), 229 deletions(-) delete mode 100644 pkg/util/fake_client_wrapper.go create mode 100644 pkg/util/fake_vm_client_wrapper.go create mode 100644 pkg/util/fake_vm_service_client_wrapper.go diff --git a/pkg/cloudprovider/vsphereparavirtual/instances.go b/pkg/cloudprovider/vsphereparavirtual/instances.go index 37bb8bcd9..e1f8b997c 100644 --- a/pkg/cloudprovider/vsphereparavirtual/instances.go +++ b/pkg/cloudprovider/vsphereparavirtual/instances.go @@ -27,17 +27,17 @@ import ( "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/wait" - "sigs.k8s.io/controller-runtime/pkg/client" cloudprovider "k8s.io/cloud-provider" "k8s.io/klog/v2" vmopv1alpha1 "github.com/vmware-tanzu/vm-operator-api/api/v1alpha1" + vmopclient "k8s.io/cloud-provider-vsphere/pkg/cloudprovider/vsphereparavirtual/vmop/clientset/versioned" "k8s.io/cloud-provider-vsphere/pkg/cloudprovider/vsphereparavirtual/vmservice" ) type instances struct { - vmClient client.Client + vmClient vmopclient.Interface namespace string } diff --git a/pkg/cloudprovider/vsphereparavirtual/instances_test.go b/pkg/cloudprovider/vsphereparavirtual/instances_test.go index 31988feed..fdf80017d 100644 --- a/pkg/cloudprovider/vsphereparavirtual/instances_test.go +++ b/pkg/cloudprovider/vsphereparavirtual/instances_test.go @@ -25,12 +25,10 @@ import ( vmopv1alpha1 "github.com/vmware-tanzu/vm-operator-api/api/v1alpha1" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" cloudprovider "k8s.io/cloud-provider" + faketvmclient "k8s.io/cloud-provider-vsphere/pkg/cloudprovider/vsphereparavirtual/vmop/clientset/versioned/fake" "k8s.io/cloud-provider-vsphere/pkg/util" - "sigs.k8s.io/controller-runtime/pkg/client" - fakeClient "sigs.k8s.io/controller-runtime/pkg/client/fake" "sigs.k8s.io/controller-runtime/pkg/envtest" ) @@ -73,7 +71,9 @@ func TestNewInstances(t *testing.T) { expectedErr error }{ { - name: "NewInstance: when everything is ok", + name: "NewInstance: when everything is ok", + // The above code is declaring a test environment variable of type `envtest.Environment` and + // initializing it with an empty instance of `envtest.Environment`. testEnv: &envtest.Environment{}, expectedErr: nil, }, @@ -94,13 +94,11 @@ func TestNewInstances(t *testing.T) { } } -func initTest(testVM *vmopv1alpha1.VirtualMachine) (*instances, *util.FakeClientWrapper) { - scheme := runtime.NewScheme() - _ = vmopv1alpha1.AddToScheme(scheme) - fc := fakeClient.NewClientBuilder().WithScheme(scheme).WithRuntimeObjects(testVM).Build() - fcw := util.NewFakeClientWrapper(fc) +func initTest(testVM *vmopv1alpha1.VirtualMachine) (*instances, *util.FakeVMClientWrapper) { + fc := faketvmclient.NewSimpleClientset() + fcw := util.NewFakeVMClientWrapper(fc) instance := &instances{ - vmClient: fcw, + vmClient: fc, namespace: testClusterNameSpace, } return instance, fcw @@ -166,8 +164,8 @@ func TestInstanceIDThrowsErr(t *testing.T) { for _, testCase := range testCases { t.Run(testCase.name, func(t *testing.T) { instance, fcw := initTest(testCase.testVM) - fcw.GetFunc = func(ctx context.Context, key client.ObjectKey, obj client.Object, opts ...client.GetOption) error { - return fmt.Errorf("Internal error getting VMs") + fcw.GetFunc = func(ctx context.Context, namespace, name string, opts metav1.GetOptions) (result *vmopv1alpha1.VirtualMachine, err error) { + return nil, fmt.Errorf("Internal error getting VMs") } instanceID, err := instance.InstanceID(context.Background(), testVMName) @@ -325,8 +323,8 @@ func TestNodeAddressesByProviderIDInternalErr(t *testing.T) { for _, testCase := range testCases { t.Run(testCase.name, func(t *testing.T) { instance, fcw := initTest(testCase.testVM) - fcw.ListFunc = func(ctx context.Context, list client.ObjectList, opts ...client.ListOption) error { - return fmt.Errorf("Internal error listing VMs") + fcw.ListFunc = func(ctx context.Context, namespace string, opts metav1.ListOptions) (result *vmopv1alpha1.VirtualMachineList, err error) { + return nil, fmt.Errorf("Internal error listing VMs") } ret, err := instance.NodeAddressesByProviderID(context.Background(), testProviderID) @@ -399,8 +397,8 @@ func TestNodeAddressesInternalErr(t *testing.T) { for _, testCase := range testCases { t.Run(testCase.name, func(t *testing.T) { instance, fcw := initTest(testCase.testVM) - fcw.GetFunc = func(ctx context.Context, key client.ObjectKey, obj client.Object, opts ...client.GetOption) error { - return fmt.Errorf("Internal error getting VMs") + fcw.GetFunc = func(ctx context.Context, namespace, name string, opts metav1.GetOptions) (result *vmopv1alpha1.VirtualMachine, err error) { + return nil, fmt.Errorf("Internal error getting VMs") } ret, err := instance.NodeAddresses(context.Background(), testVMName) diff --git a/pkg/cloudprovider/vsphereparavirtual/loadbalancer_test.go b/pkg/cloudprovider/vsphereparavirtual/loadbalancer_test.go index b3de904b8..dac0b3eca 100644 --- a/pkg/cloudprovider/vsphereparavirtual/loadbalancer_test.go +++ b/pkg/cloudprovider/vsphereparavirtual/loadbalancer_test.go @@ -26,10 +26,8 @@ import ( v1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" cloudprovider "k8s.io/cloud-provider" - "sigs.k8s.io/controller-runtime/pkg/client" - fakeClient "sigs.k8s.io/controller-runtime/pkg/client/fake" + faketvmclient "k8s.io/cloud-provider-vsphere/pkg/cloudprovider/vsphereparavirtual/vmop/clientset/versioned/fake" "sigs.k8s.io/controller-runtime/pkg/envtest" "k8s.io/cloud-provider-vsphere/pkg/cloudprovider/vsphereparavirtual/vmservice" @@ -51,11 +49,10 @@ var ( } ) -func newTestLoadBalancer() (cloudprovider.LoadBalancer, *util.FakeClientWrapper) { - scheme := runtime.NewScheme() - _ = vmopv1alpha1.AddToScheme(scheme) - fc := fakeClient.NewClientBuilder().WithScheme(scheme).Build() - fcw := util.NewFakeClientWrapper(fc) +func newTestLoadBalancer() (cloudprovider.LoadBalancer, *util.FakeVMServiceClientWrapper) { + fc := faketvmclient.NewSimpleClientset() + fcw := util.NewFakeVMServiceClientWrapper(fc) + vms := vmservice.NewVMService(fcw, testClusterNameSpace, &testOwnerReference) return &loadBalancer{ vmService: vms, @@ -181,8 +178,8 @@ func TestUpdateLoadBalancer(t *testing.T) { if testCase.expectErr { // Ensure that the client Update call returns an error on update - fcw.UpdateFunc = func(ctx context.Context, obj client.Object, opts ...client.UpdateOption) error { - return fmt.Errorf("Some undefined update error") + fcw.UpdateFunc = func(ctx context.Context, vm *vmopv1alpha1.VirtualMachineService, opts metav1.UpdateOptions) (result *vmopv1alpha1.VirtualMachineService, err error) { + return nil, fmt.Errorf("Some undefined update error") } err = lb.UpdateLoadBalancer(context.Background(), testClustername, testK8sService, []*v1.Node{}) assert.Error(t, err) @@ -205,7 +202,7 @@ func TestEnsureLoadBalancer_VMServiceExternalTrafficPolicyLocal(t *testing.T) { ExternalTrafficPolicy: v1.ServiceExternalTrafficPolicyTypeLocal, }, } - fcw.CreateFunc = func(ctx context.Context, obj client.Object, opts ...client.CreateOption) error { + fcw.CreateFunc = func(ctx context.Context, vm *vmopv1alpha1.VirtualMachineService, opts metav1.CreateOptions) (result *vmopv1alpha1.VirtualMachineService, err error) { vms := &vmopv1alpha1.VirtualMachineService{ Status: vmopv1alpha1.VirtualMachineServiceStatus{ LoadBalancer: vmopv1alpha1.LoadBalancerStatus{ @@ -217,8 +214,8 @@ func TestEnsureLoadBalancer_VMServiceExternalTrafficPolicyLocal(t *testing.T) { }, }, } - vms.DeepCopyInto(obj.(*vmopv1alpha1.VirtualMachineService)) - return nil + vms.DeepCopyInto(vm) + return vm, nil } _, ensureErr := lb.EnsureLoadBalancer(context.Background(), testClustername, testK8sService, []*v1.Node{}) @@ -231,7 +228,7 @@ func TestEnsureLoadBalancer_VMServiceExternalTrafficPolicyLocal(t *testing.T) { func TestEnsureLoadBalancer(t *testing.T) { testCases := []struct { name string - createFunc func(ctx context.Context, obj client.Object, opts ...client.CreateOption) error + createFunc func(ctx context.Context, vm *vmopv1alpha1.VirtualMachineService, opts metav1.CreateOptions) (result *vmopv1alpha1.VirtualMachineService, err error) expectErr error }{ { @@ -240,8 +237,8 @@ func TestEnsureLoadBalancer(t *testing.T) { }, { name: "when VMService creation failed", - createFunc: func(ctx context.Context, obj client.Object, opts ...client.CreateOption) error { - return fmt.Errorf(vmservice.ErrCreateVMService.Error()) + createFunc: func(ctx context.Context, vm *vmopv1alpha1.VirtualMachineService, opts metav1.CreateOptions) (result *vmopv1alpha1.VirtualMachineService, err error) { + return nil, fmt.Errorf(vmservice.ErrCreateVMService.Error()) }, expectErr: vmservice.ErrCreateVMService, }, @@ -276,7 +273,7 @@ func TestEnsureLoadBalancer_VMServiceCreatedIPFound(t *testing.T) { }, } // Ensure that the client Create call returns a VMService with a valid IP - fcw.CreateFunc = func(ctx context.Context, obj client.Object, opts ...client.CreateOption) error { + fcw.CreateFunc = func(ctx context.Context, vm *vmopv1alpha1.VirtualMachineService, opts metav1.CreateOptions) (result *vmopv1alpha1.VirtualMachineService, err error) { vms := &vmopv1alpha1.VirtualMachineService{ Status: vmopv1alpha1.VirtualMachineServiceStatus{ LoadBalancer: vmopv1alpha1.LoadBalancerStatus{ @@ -309,8 +306,8 @@ func TestEnsureLoadBalancer_VMServiceCreatedIPFound(t *testing.T) { }, }, } - vms.DeepCopyInto(obj.(*vmopv1alpha1.VirtualMachineService)) - return nil + vms.DeepCopyInto(vm) + return vm, nil } status, ensureErr := lb.EnsureLoadBalancer(context.Background(), testClustername, testK8sService, []*v1.Node{}) @@ -324,18 +321,18 @@ func TestEnsureLoadBalancer_VMServiceCreatedIPFound(t *testing.T) { func TestEnsureLoadBalancer_DeleteLB(t *testing.T) { testCases := []struct { name string - deleteFunc func(ctx context.Context, obj client.Object, opts ...client.DeleteOption) error + deleteFunc func(ctx context.Context, namespace, name string, opts metav1.DeleteOptions) error expectErr string }{ { name: "should ignore not found error", - deleteFunc: func(ctx context.Context, obj client.Object, opts ...client.DeleteOption) error { + deleteFunc: func(ctx context.Context, namespace, name string, opts metav1.DeleteOptions) error { return apierrors.NewNotFound(vmopv1alpha1.Resource("virtualmachineservice"), testClustername) }, }, { name: "should return error", - deleteFunc: func(ctx context.Context, obj client.Object, opts ...client.DeleteOption) error { + deleteFunc: func(ctx context.Context, namespace, name string, opts metav1.DeleteOptions) error { return fmt.Errorf("an error occurred while deleting load balancer") }, expectErr: "an error occurred while deleting load balancer", diff --git a/pkg/cloudprovider/vsphereparavirtual/vmoperator.go b/pkg/cloudprovider/vsphereparavirtual/vmoperator.go index f4ed891bb..5bc0fcb9e 100644 --- a/pkg/cloudprovider/vsphereparavirtual/vmoperator.go +++ b/pkg/cloudprovider/vsphereparavirtual/vmoperator.go @@ -5,14 +5,16 @@ import ( vmopv1alpha1 "github.com/vmware-tanzu/vm-operator-api/api/v1alpha1" apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/cloud-provider-vsphere/pkg/util" - "sigs.k8s.io/controller-runtime/pkg/client" + + vmopclient "k8s.io/cloud-provider-vsphere/pkg/cloudprovider/vsphereparavirtual/vmop/clientset/versioned" ) // discoverNodeByProviderID takes a ProviderID and returns a VirtualMachine if one exists, or nil otherwise // VirtualMachine not found is not an error -func discoverNodeByProviderID(ctx context.Context, providerID string, namespace string, vmClient client.Client) (*vmopv1alpha1.VirtualMachine, error) { +func discoverNodeByProviderID(ctx context.Context, providerID string, namespace string, vmClient vmopclient.Interface) (*vmopv1alpha1.VirtualMachine, error) { var discoveredNode *vmopv1alpha1.VirtualMachine = nil // Adding Retry here because there is no retry in caller from node controller @@ -22,10 +24,7 @@ func discoverNodeByProviderID(ctx context.Context, providerID string, namespace checkError, func() error { uuid := GetUUIDFromProviderID(providerID) - vms := vmopv1alpha1.VirtualMachineList{} - err := vmClient.List(ctx, &vms, &client.ListOptions{ - Namespace: namespace, - }) + vms, err := vmClient.VmoperatorV1alpha1().VirtualMachines(namespace).List(ctx, metav1.ListOptions{}) if err != nil { return err } @@ -45,7 +44,7 @@ func discoverNodeByProviderID(ctx context.Context, providerID string, namespace // discoverNodeByName takes a node name and returns a VirtualMachine if one exists, or nil otherwise // VirtualMachine not found is not an error -func discoverNodeByName(ctx context.Context, name types.NodeName, namespace string, vmClient client.Client) (*vmopv1alpha1.VirtualMachine, error) { +func discoverNodeByName(ctx context.Context, name types.NodeName, namespace string, vmClient vmopclient.Interface) (*vmopv1alpha1.VirtualMachine, error) { var discoveredNode *vmopv1alpha1.VirtualMachine = nil // Adding Retry here because there is no retry in caller from node controller @@ -54,16 +53,14 @@ func discoverNodeByName(ctx context.Context, name types.NodeName, namespace stri DiscoverNodeBackoff, checkError, func() error { - vmKey := types.NamespacedName{Name: string(name), Namespace: namespace} - vm := vmopv1alpha1.VirtualMachine{} - err := vmClient.Get(ctx, vmKey, &vm) + vm, err := vmClient.VmoperatorV1alpha1().VirtualMachines(namespace).Get(ctx, string(name), metav1.GetOptions{}) if err != nil { if apierrors.IsNotFound(err) { return nil } return err } - discoveredNode = &vm + discoveredNode = vm return nil }) diff --git a/pkg/cloudprovider/vsphereparavirtual/vmservice/types.go b/pkg/cloudprovider/vsphereparavirtual/vmservice/types.go index 556e9bb16..cd7726629 100644 --- a/pkg/cloudprovider/vsphereparavirtual/vmservice/types.go +++ b/pkg/cloudprovider/vsphereparavirtual/vmservice/types.go @@ -22,9 +22,9 @@ import ( v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/klog/v2/klogr" - "sigs.k8s.io/controller-runtime/pkg/client" "github.com/vmware-tanzu/vm-operator-api/api/v1alpha1" + vmopclient "k8s.io/cloud-provider-vsphere/pkg/cloudprovider/vsphereparavirtual/vmop/clientset/versioned" ) var log = klogr.New().WithName("vmservice") @@ -41,7 +41,7 @@ type VMService interface { // vmService takes care of mapping of LB type of service to VM service in supervisor cluster type vmService struct { - vmClient client.Client + vmClient vmopclient.Interface namespace string ownerReference *metav1.OwnerReference } diff --git a/pkg/cloudprovider/vsphereparavirtual/vmservice/vmservice.go b/pkg/cloudprovider/vsphereparavirtual/vmservice/vmservice.go index d5cc12120..267de3e7a 100644 --- a/pkg/cloudprovider/vsphereparavirtual/vmservice/vmservice.go +++ b/pkg/cloudprovider/vsphereparavirtual/vmservice/vmservice.go @@ -29,11 +29,10 @@ import ( apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/types" rest "k8s.io/client-go/rest" - client "sigs.k8s.io/controller-runtime/pkg/client" vmopv1alpha1 "github.com/vmware-tanzu/vm-operator-api/api/v1alpha1" + vmopclient "k8s.io/cloud-provider-vsphere/pkg/cloudprovider/vsphereparavirtual/vmop/clientset/versioned" ) const ( @@ -89,17 +88,14 @@ var ( // GetVmopClient gets a vm-operator-api client // This is separate from NewVMService so that a fake client can be injected for testing -func GetVmopClient(config *rest.Config) (client.Client, error) { +func GetVmopClient(config *rest.Config) (vmopclient.Interface, error) { scheme := runtime.NewScheme() _ = vmopv1alpha1.AddToScheme(scheme) - client, err := client.New(config, client.Options{ - Scheme: scheme, - }) - return client, err + return vmopclient.NewForConfig(config) } // NewVMService creates a vmService object -func NewVMService(vmClient client.Client, ns string, ownerRef *metav1.OwnerReference) VMService { +func NewVMService(vmClient vmopclient.Interface, ns string, ownerRef *metav1.OwnerReference) VMService { return &vmService{ vmClient: vmClient, namespace: ns, @@ -135,10 +131,8 @@ func (s *vmService) Get(ctx context.Context, service *v1.Service, clusterName st logger := log.WithValues("name", service.Name, "namespace", service.Namespace) logger.V(2).Info("Attempting to get VirtualMachineService") - vmService := vmopv1alpha1.VirtualMachineService{} - vmServiceKey := types.NamespacedName{Name: s.GetVMServiceName(service, clusterName), Namespace: s.namespace} - - if err := s.vmClient.Get(ctx, vmServiceKey, &vmService); err != nil { + vmService, err := s.vmClient.VmoperatorV1alpha1().VirtualMachineServices(s.namespace).Get(ctx, s.GetVMServiceName(service, clusterName), metav1.GetOptions{}) + if err != nil { if apierrors.IsNotFound(err) { return nil, nil } @@ -146,7 +140,7 @@ func (s *vmService) Get(ctx context.Context, service *v1.Service, clusterName st return nil, err } - return &vmService, nil + return vmService, nil } // Create creates a vmservice to map to the given lb type of service, it should be called if vmservice not found @@ -160,8 +154,8 @@ func (s *vmService) Create(ctx context.Context, service *v1.Service, clusterName return nil, err } - vmService.Namespace = s.namespace - if err = s.vmClient.Create(ctx, vmService); err != nil { + vmService, err = s.vmClient.VmoperatorV1alpha1().VirtualMachineServices(s.namespace).Create(ctx, vmService, metav1.CreateOptions{}) + if err != nil { logger.Error(ErrCreateVMService, fmt.Sprintf("%v", err)) return nil, err } @@ -258,7 +252,8 @@ func (s *vmService) Update(ctx context.Context, service *v1.Service, clusterName } if needsUpdate { - if err := s.vmClient.Update(ctx, newVMService); err != nil { + newVMService, err = s.vmClient.VmoperatorV1alpha1().VirtualMachineServices(s.namespace).Update(ctx, newVMService, metav1.UpdateOptions{}) + if err != nil { logger.Error(ErrUpdateVMService, fmt.Sprintf("%v", err)) return nil, err } @@ -275,11 +270,8 @@ func (s *vmService) Delete(ctx context.Context, service *v1.Service, clusterName logger := log.WithValues("name", service.Name, "namespace", service.Namespace) logger.V(2).Info("Attempting to delete VirtualMachineService") - vmService := vmopv1alpha1.VirtualMachineService{} - vmService.Name = s.GetVMServiceName(service, clusterName) - vmService.Namespace = s.namespace - - if err := s.vmClient.Delete(ctx, &vmService); err != nil { + err := s.vmClient.VmoperatorV1alpha1().VirtualMachineServices(s.namespace).Delete(ctx, s.GetVMServiceName(service, clusterName), metav1.DeleteOptions{}) + if err != nil { logger.Error(ErrDeleteVMService, fmt.Sprintf("%v", err)) return err } diff --git a/pkg/cloudprovider/vsphereparavirtual/vmservice/vmservice_test.go b/pkg/cloudprovider/vsphereparavirtual/vmservice/vmservice_test.go index 0436dc825..579925d3f 100644 --- a/pkg/cloudprovider/vsphereparavirtual/vmservice/vmservice_test.go +++ b/pkg/cloudprovider/vsphereparavirtual/vmservice/vmservice_test.go @@ -24,19 +24,15 @@ import ( "github.com/stretchr/testify/assert" + vmopv1alpha1 "github.com/vmware-tanzu/vm-operator-api/api/v1alpha1" v1 "k8s.io/api/core/v1" "k8s.io/api/node/v1alpha1" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/intstr" - "sigs.k8s.io/controller-runtime/pkg/client" - fakeClient "sigs.k8s.io/controller-runtime/pkg/client/fake" - "sigs.k8s.io/controller-runtime/pkg/envtest" - - vmopv1alpha1 "github.com/vmware-tanzu/vm-operator-api/api/v1alpha1" - + faketvmclient "k8s.io/cloud-provider-vsphere/pkg/cloudprovider/vsphereparavirtual/vmop/clientset/versioned/fake" "k8s.io/cloud-provider-vsphere/pkg/util" + "sigs.k8s.io/controller-runtime/pkg/envtest" ) var ( @@ -54,10 +50,10 @@ var ( fakeLBIP = "1.1.1.1" // FakeClientWrapper allows functions to be replaced for fault injection - fcw *util.FakeClientWrapper + fcw *util.FakeVMServiceClientWrapper ) -func initTest() (*v1.Service, VMService, *util.FakeClientWrapper) { +func initTest() (*v1.Service, VMService, *util.FakeVMServiceClientWrapper) { testK8sService := &v1.Service{ ObjectMeta: metav1.ObjectMeta{ Name: testK8sServiceName, @@ -78,10 +74,8 @@ func initTest() (*v1.Service, VMService, *util.FakeClientWrapper) { }, }, } - scheme := runtime.NewScheme() - _ = vmopv1alpha1.AddToScheme(scheme) - fc := fakeClient.NewClientBuilder().WithScheme(scheme).Build() - fcw = util.NewFakeClientWrapper(fc) + fc := faketvmclient.NewSimpleClientset() + fcw = util.NewFakeVMServiceClientWrapper(fc) vms = NewVMService(fcw, testClusterNameSpace, &testOwnerReference) return testK8sService, vms, fcw @@ -408,20 +402,20 @@ func TestCreateOrUpdateVMService(t *testing.T) { func TestCreateOrUpdateVMService_RedefineGetFunc(t *testing.T) { testCases := []struct { name string - getFunc func(ctx context.Context, key client.ObjectKey, obj client.Object, opts ...client.GetOption) error + getFunc func(ctx context.Context, namespace, name string, opts metav1.GetOptions) (result *vmopv1alpha1.VirtualMachineService, err error) expectedErr error }{ { name: "failed to create VirtualMachineService", - getFunc: func(ctx context.Context, key client.ObjectKey, obj client.Object, opts ...client.GetOption) error { - return fmt.Errorf("failed to get VirtualMachineService") + getFunc: func(ctx context.Context, namespace, name string, opts metav1.GetOptions) (result *vmopv1alpha1.VirtualMachineService, err error) { + return nil, fmt.Errorf("failed to get VirtualMachineService") }, expectedErr: ErrGetVMService, }, { name: "when VMService does not exist", - getFunc: func(ctx context.Context, key client.ObjectKey, obj client.Object, opts ...client.GetOption) error { - return apierrors.NewNotFound(v1alpha1.Resource("virtualmachineservice"), testClustername) + getFunc: func(ctx context.Context, namespace, name string, opts metav1.GetOptions) (result *vmopv1alpha1.VirtualMachineService, err error) { + return nil, apierrors.NewNotFound(v1alpha1.Resource("virtualmachineservice"), testClustername) }, expectedErr: ErrVMServiceIPNotFound, }, @@ -441,8 +435,8 @@ func TestCreateOrUpdateVMService_RedefineGetFunc(t *testing.T) { func TestCreateOrUpdateVMService_RedefineCreateFunc(t *testing.T) { testK8sService, vms, fcw := initTest() // Redefine Create in the client to return an error - fcw.CreateFunc = func(ctx context.Context, obj client.Object, opts ...client.CreateOption) error { - return fmt.Errorf("failed to create VirtualMachineService") + fcw.CreateFunc = func(ctx context.Context, vm *vmopv1alpha1.VirtualMachineService, opts metav1.CreateOptions) (result *vmopv1alpha1.VirtualMachineService, err error) { + return nil, fmt.Errorf("failed to create VirtualMachineService") } _, err := vms.CreateOrUpdate(context.Background(), testK8sService, testClustername) assert.Equal(t, ErrCreateVMService.Error(), err.Error()) diff --git a/pkg/cloudprovider/vsphereparavirtual/zone.go b/pkg/cloudprovider/vsphereparavirtual/zone.go index 7f896d0b5..aff4816a0 100644 --- a/pkg/cloudprovider/vsphereparavirtual/zone.go +++ b/pkg/cloudprovider/vsphereparavirtual/zone.go @@ -4,16 +4,17 @@ import ( "context" vmopv1alpha1 "github.com/vmware-tanzu/vm-operator-api/api/v1alpha1" + vmopclient "k8s.io/cloud-provider-vsphere/pkg/cloudprovider/vsphereparavirtual/vmop/clientset/versioned" + "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/rest" cloudprovider "k8s.io/cloud-provider" "k8s.io/cloud-provider-vsphere/pkg/cloudprovider/vsphereparavirtual/vmservice" "k8s.io/klog/v2" - "sigs.k8s.io/controller-runtime/pkg/client" ) type zones struct { - vmClient client.Client + vmClient vmopclient.Interface namespace string } diff --git a/pkg/cloudprovider/vsphereparavirtual/zone_test.go b/pkg/cloudprovider/vsphereparavirtual/zone_test.go index f898705b0..ccd098686 100644 --- a/pkg/cloudprovider/vsphereparavirtual/zone_test.go +++ b/pkg/cloudprovider/vsphereparavirtual/zone_test.go @@ -7,11 +7,10 @@ import ( "github.com/stretchr/testify/assert" vmopv1alpha1 "github.com/vmware-tanzu/vm-operator-api/api/v1alpha1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" cloudprovider "k8s.io/cloud-provider" + faketvmclient "k8s.io/cloud-provider-vsphere/pkg/cloudprovider/vsphereparavirtual/vmop/clientset/versioned/fake" "k8s.io/cloud-provider-vsphere/pkg/util" - fakeClient "sigs.k8s.io/controller-runtime/pkg/client/fake" "sigs.k8s.io/controller-runtime/pkg/envtest" ) @@ -135,11 +134,9 @@ func TestZonesByNodeName(t *testing.T) { } } -func initVMopClient(testVM *vmopv1alpha1.VirtualMachine) (zones, *util.FakeClientWrapper) { - scheme := runtime.NewScheme() - _ = vmopv1alpha1.AddToScheme(scheme) - fc := fakeClient.NewClientBuilder().WithScheme(scheme).WithRuntimeObjects(testVM).Build() - fcw := util.NewFakeClientWrapper(fc) +func initVMopClient(testVM *vmopv1alpha1.VirtualMachine) (zones, *util.FakeVMClientWrapper) { + fc := faketvmclient.NewSimpleClientset() + fcw := util.NewFakeVMClientWrapper(fc) zone := zones{ vmClient: fcw, namespace: testClusterNameSpace, diff --git a/pkg/util/fake_client_wrapper.go b/pkg/util/fake_client_wrapper.go deleted file mode 100644 index f39b81fdc..000000000 --- a/pkg/util/fake_client_wrapper.go +++ /dev/null @@ -1,126 +0,0 @@ -/* -Copyright 2021 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package util - -import ( - "context" - - "k8s.io/apimachinery/pkg/runtime/schema" - - "k8s.io/apimachinery/pkg/api/meta" - "k8s.io/apimachinery/pkg/runtime" - - client "sigs.k8s.io/controller-runtime/pkg/client" -) - -// FakeClientWrapper allows functions to be replaced for fault injection -type FakeClientWrapper struct { - fakeClient client.Client - // Set these functions if you want to override the default fakeClient behavior - GetFunc func(ctx context.Context, key client.ObjectKey, obj client.Object, opts ...client.GetOption) error - CreateFunc func(ctx context.Context, obj client.Object, opts ...client.CreateOption) error - UpdateFunc func(ctx context.Context, obj client.Object, opts ...client.UpdateOption) error - DeleteFunc func(ctx context.Context, obj client.Object, opts ...client.DeleteOption) error - ListFunc func(ctx context.Context, list client.ObjectList, opts ...client.ListOption) error -} - -// Scheme invokes the fakeClient's Scheme -func (w *FakeClientWrapper) Scheme() *runtime.Scheme { - return w.fakeClient.Scheme() -} - -// RESTMapper invokes the fakeClient's RESTMapper -func (w *FakeClientWrapper) RESTMapper() meta.RESTMapper { - return w.fakeClient.RESTMapper() -} - -// NewFakeClientWrapper creates a FakeClientWrapper -func NewFakeClientWrapper(fakeClient client.Client) *FakeClientWrapper { - fcw := FakeClientWrapper{} - fcw.fakeClient = fakeClient - return &fcw -} - -// Get retrieves an obj for the given object key from the Kubernetes Cluster. -func (w *FakeClientWrapper) Get(ctx context.Context, key client.ObjectKey, obj client.Object, opts ...client.GetOption) error { - if w.GetFunc != nil { - return w.GetFunc(ctx, key, obj, opts...) - } - return w.fakeClient.Get(ctx, key, obj, opts...) -} - -// List retrieves list of objects for a given namespace and list options. -func (w *FakeClientWrapper) List(ctx context.Context, list client.ObjectList, opts ...client.ListOption) error { - if w.ListFunc != nil { - return w.ListFunc(ctx, list, opts...) - } - return w.fakeClient.List(ctx, list, opts...) -} - -// Create saves the object obj in the Kubernetes cluster. -func (w *FakeClientWrapper) Create(ctx context.Context, obj client.Object, opts ...client.CreateOption) error { - if w.CreateFunc != nil { - return w.CreateFunc(ctx, obj, opts...) - } - return w.fakeClient.Create(ctx, obj, opts...) -} - -// Delete deletes the given obj from Kubernetes cluster. -func (w *FakeClientWrapper) Delete(ctx context.Context, obj client.Object, opts ...client.DeleteOption) error { - if w.DeleteFunc != nil { - return w.DeleteFunc(ctx, obj, opts...) - } - return w.fakeClient.Delete(ctx, obj, opts...) -} - -// Update updates the given obj in the Kubernetes cluster. -func (w *FakeClientWrapper) Update(ctx context.Context, obj client.Object, opts ...client.UpdateOption) error { - if w.UpdateFunc != nil { - return w.UpdateFunc(ctx, obj, opts...) - } - return w.fakeClient.Update(ctx, obj, opts...) -} - -// Patch patches the given obj in the Kubernetes cluster. -func (w *FakeClientWrapper) Patch(ctx context.Context, obj client.Object, patch client.Patch, opts ...client.PatchOption) error { - return w.fakeClient.Patch(ctx, obj, patch, opts...) -} - -// DeleteAllOf deletes all objects of the given type matching the given options. -func (w *FakeClientWrapper) DeleteAllOf(ctx context.Context, obj client.Object, opts ...client.DeleteAllOfOption) error { - return w.fakeClient.DeleteAllOf(ctx, obj, opts...) -} - -// Status returns a StatusWriter which knows how to update status subresource of a Kubernetes object. -func (w *FakeClientWrapper) Status() client.StatusWriter { - return w.fakeClient.Status() -} - -// SubResource returns a SubResourceClient for the resource. -func (w *FakeClientWrapper) SubResource(subResource string) client.SubResourceClient { - return w.fakeClient.SubResource(subResource) -} - -// GroupVersionKindFor returns the GroupVersionKind for the given object. -func (w *FakeClientWrapper) GroupVersionKindFor(obj runtime.Object) (schema.GroupVersionKind, error) { - return w.fakeClient.GroupVersionKindFor(obj) -} - -// IsObjectNamespaced returns true if the GroupVersionKind of the object is namespaced. -func (w *FakeClientWrapper) IsObjectNamespaced(obj runtime.Object) (bool, error) { - return w.fakeClient.IsObjectNamespaced(obj) -} diff --git a/pkg/util/fake_vm_client_wrapper.go b/pkg/util/fake_vm_client_wrapper.go new file mode 100644 index 000000000..9140994b2 --- /dev/null +++ b/pkg/util/fake_vm_client_wrapper.go @@ -0,0 +1,97 @@ +/* +Copyright 2021 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package util + +import ( + "context" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/discovery" + + vmopv1alpha1 "github.com/vmware-tanzu/vm-operator-api/api/v1alpha1" + vmopclient "k8s.io/cloud-provider-vsphere/pkg/cloudprovider/vsphereparavirtual/vmop/clientset/versioned" + fake "k8s.io/cloud-provider-vsphere/pkg/cloudprovider/vsphereparavirtual/vmop/clientset/versioned/fake" + vmoperatorv1alpha1 "k8s.io/cloud-provider-vsphere/pkg/cloudprovider/vsphereparavirtual/vmop/clientset/versioned/typed/vmop/v1alpha1" +) + +// FakeClientWrapper allows functions to be replaced for fault injection +type FakeVMClientWrapper struct { + fakeClient vmopclient.Interface + // Set these functions if you want to override the default fakeClient behavior + GetFunc func(ctx context.Context, namespace, name string, opts metav1.GetOptions) (result *vmopv1alpha1.VirtualMachine, err error) + ListFunc func(ctx context.Context, namespace string, opts metav1.ListOptions) (result *vmopv1alpha1.VirtualMachineList, err error) + CreateFunc func(ctx context.Context, vm *vmopv1alpha1.VirtualMachine, opts metav1.CreateOptions) (result *vmopv1alpha1.VirtualMachine, err error) + UpdateFunc func(ctx context.Context, vm *vmopv1alpha1.VirtualMachine, opts metav1.UpdateOptions) (result *vmopv1alpha1.VirtualMachine, err error) + DeleteFunc func(ctx context.Context, namespace, name string, opts metav1.DeleteOptions) error +} + +// NewFakeVMClientWrapper creates a FakeClientWrapper +func NewFakeVMClientWrapper(fakeClient *fake.Clientset) *FakeVMClientWrapper { + fcw := FakeVMClientWrapper{} + fcw.fakeClient = fakeClient + return &fcw +} + +// Get retrieves an obj for the given object key from the Kubernetes Cluster. +func (w *FakeVMClientWrapper) Get(ctx context.Context, namespace, name string, opts metav1.GetOptions) (result *vmopv1alpha1.VirtualMachine, err error) { + if w.GetFunc != nil { + return w.GetFunc(ctx, namespace, name, opts) + } + return w.fakeClient.VmoperatorV1alpha1().VirtualMachines(namespace).Get(ctx, name, opts) +} + +// List retrieves list of objects for a given namespace and list options. +func (w *FakeVMClientWrapper) List(ctx context.Context, namespace string, opts metav1.ListOptions) (result *vmopv1alpha1.VirtualMachineList, err error) { + if w.ListFunc != nil { + return w.ListFunc(ctx, namespace, opts) + } + return w.fakeClient.VmoperatorV1alpha1().VirtualMachines(namespace).List(ctx, opts) +} + +// Create saves the object obj in the Kubernetes cluster. +func (w *FakeVMClientWrapper) Create(ctx context.Context, vm *vmopv1alpha1.VirtualMachine, opts metav1.CreateOptions) (result *vmopv1alpha1.VirtualMachine, err error) { + if w.CreateFunc != nil { + return w.CreateFunc(ctx, vm, opts) + } + return w.fakeClient.VmoperatorV1alpha1().VirtualMachines(vm.Namespace).Create(ctx, vm, opts) +} + +// Update updates the given obj in the Kubernetes cluster. +func (w *FakeVMClientWrapper) Update(ctx context.Context, vm *vmopv1alpha1.VirtualMachine, opts metav1.UpdateOptions) (result *vmopv1alpha1.VirtualMachine, err error) { + if w.UpdateFunc != nil { + return w.UpdateFunc(ctx, vm, opts) + } + return w.fakeClient.VmoperatorV1alpha1().VirtualMachines(vm.Namespace).Update(ctx, vm, opts) +} + +// Delete deletes the given obj from Kubernetes cluster. +func (w *FakeVMClientWrapper) Delete(ctx context.Context, namespace, name string, opts metav1.DeleteOptions) error { + if w.DeleteFunc != nil { + return w.DeleteFunc(ctx, namespace, name, opts) + } + return w.fakeClient.VmoperatorV1alpha1().VirtualMachines(namespace).Delete(ctx, name, opts) +} + +// Discovery retrieves the DiscoveryClient +func (w *FakeVMClientWrapper) Discovery() discovery.DiscoveryInterface { + return w.fakeClient.Discovery() +} + +// VmoperatorV1alpha1 retrieves the VmoperatorV1alpha1Client +func (w *FakeVMClientWrapper) VmoperatorV1alpha1() vmoperatorv1alpha1.VmoperatorV1alpha1Interface { + return w.fakeClient.VmoperatorV1alpha1() +} diff --git a/pkg/util/fake_vm_service_client_wrapper.go b/pkg/util/fake_vm_service_client_wrapper.go new file mode 100644 index 000000000..f505904dd --- /dev/null +++ b/pkg/util/fake_vm_service_client_wrapper.go @@ -0,0 +1,97 @@ +/* +Copyright 2021 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package util + +import ( + "context" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/discovery" + + vmopv1alpha1 "github.com/vmware-tanzu/vm-operator-api/api/v1alpha1" + vmopclient "k8s.io/cloud-provider-vsphere/pkg/cloudprovider/vsphereparavirtual/vmop/clientset/versioned" + fake "k8s.io/cloud-provider-vsphere/pkg/cloudprovider/vsphereparavirtual/vmop/clientset/versioned/fake" + vmoperatorv1alpha1 "k8s.io/cloud-provider-vsphere/pkg/cloudprovider/vsphereparavirtual/vmop/clientset/versioned/typed/vmop/v1alpha1" +) + +// FakeVMServiceClientWrapper allows functions to be replaced for fault injection +type FakeVMServiceClientWrapper struct { + fakeClient vmopclient.Interface + // Set these functions if you want to override the default fakeClient behavior + GetFunc func(ctx context.Context, namespace, name string, opts metav1.GetOptions) (result *vmopv1alpha1.VirtualMachineService, err error) + ListFunc func(ctx context.Context, namespace string, opts metav1.ListOptions) (result *vmopv1alpha1.VirtualMachineServiceList, err error) + CreateFunc func(ctx context.Context, vm *vmopv1alpha1.VirtualMachineService, opts metav1.CreateOptions) (result *vmopv1alpha1.VirtualMachineService, err error) + UpdateFunc func(ctx context.Context, vm *vmopv1alpha1.VirtualMachineService, opts metav1.UpdateOptions) (result *vmopv1alpha1.VirtualMachineService, err error) + DeleteFunc func(ctx context.Context, namespace, name string, opts metav1.DeleteOptions) error +} + +// NewFakeVMClientWrapper creates a FakeClientWrapper +func NewFakeVMServiceClientWrapper(fakeClient *fake.Clientset) *FakeVMServiceClientWrapper { + fcw := FakeVMServiceClientWrapper{} + fcw.fakeClient = fakeClient + return &fcw +} + +// Get retrieves an obj for the given object key from the Kubernetes Cluster. +func (w *FakeVMServiceClientWrapper) Get(ctx context.Context, namespace, name string, opts metav1.GetOptions) (result *vmopv1alpha1.VirtualMachineService, err error) { + if w.GetFunc != nil { + return w.GetFunc(ctx, namespace, name, opts) + } + return w.fakeClient.VmoperatorV1alpha1().VirtualMachineServices(namespace).Get(ctx, name, opts) +} + +// List retrieves list of objects for a given namespace and list options. +func (w *FakeVMServiceClientWrapper) List(ctx context.Context, namespace string, opts metav1.ListOptions) (result *vmopv1alpha1.VirtualMachineServiceList, err error) { + if w.ListFunc != nil { + return w.ListFunc(ctx, namespace, opts) + } + return w.fakeClient.VmoperatorV1alpha1().VirtualMachineServices(namespace).List(ctx, opts) +} + +// Create saves the object obj in the Kubernetes cluster. +func (w *FakeVMServiceClientWrapper) Create(ctx context.Context, vmservice *vmopv1alpha1.VirtualMachineService, opts metav1.CreateOptions) (result *vmopv1alpha1.VirtualMachineService, err error) { + if w.CreateFunc != nil { + return w.CreateFunc(ctx, vmservice, opts) + } + return w.fakeClient.VmoperatorV1alpha1().VirtualMachineServices(vmservice.Namespace).Create(ctx, vmservice, opts) +} + +// Update updates the given obj in the Kubernetes cluster. +func (w *FakeVMServiceClientWrapper) Update(ctx context.Context, vmservice *vmopv1alpha1.VirtualMachineService, opts metav1.UpdateOptions) (result *vmopv1alpha1.VirtualMachineService, err error) { + if w.UpdateFunc != nil { + return w.UpdateFunc(ctx, vmservice, opts) + } + return w.fakeClient.VmoperatorV1alpha1().VirtualMachineServices(vmservice.Namespace).Update(ctx, vmservice, opts) +} + +// Delete deletes the given obj from Kubernetes cluster. +func (w *FakeVMServiceClientWrapper) Delete(ctx context.Context, namespace, name string, opts metav1.DeleteOptions) error { + if w.DeleteFunc != nil { + return w.DeleteFunc(ctx, namespace, name, opts) + } + return w.fakeClient.VmoperatorV1alpha1().VirtualMachineServices(namespace).Delete(ctx, name, opts) +} + +// Discovery retrieves the DiscoveryClient +func (w *FakeVMServiceClientWrapper) Discovery() discovery.DiscoveryInterface { + return w.fakeClient.Discovery() +} + +// VmoperatorV1alpha1 retrieves the VmoperatorV1alpha1Client +func (w *FakeVMServiceClientWrapper) VmoperatorV1alpha1() vmoperatorv1alpha1.VmoperatorV1alpha1Interface { + return w.fakeClient.VmoperatorV1alpha1() +}