Add fake CRD client

Change-Id: I4748ce465b2886098cfab37277a18cc0b571c22b
Implements: blueprint enhance-unit-testing
Signed-off-by: mozhuli <21621232@zju.edu.cn>
This commit is contained in:
mozhulee 2017-08-25 20:54:39 +08:00 committed by mozhuli
parent 23c2da8286
commit 7fed3d210b
9 changed files with 647 additions and 176 deletions

View File

@ -41,13 +41,13 @@ const (
// Controller manages life cycle of namespace's rbac. // Controller manages life cycle of namespace's rbac.
type Controller struct { type Controller struct {
k8sclient *kubernetes.Clientset k8sclient *kubernetes.Clientset
kubeCRDClient *crdClient.CRDClient kubeCRDClient crdClient.Interface
userCIDR string userCIDR string
userGateway string userGateway string
} }
// NewRBACController creates a new RBAC controller. // NewRBACController creates a new RBAC controller.
func NewRBACController(kubeClient *kubernetes.Clientset, kubeCRDClient *crdClient.CRDClient, userCIDR string, func NewRBACController(kubeClient *kubernetes.Clientset, kubeCRDClient crdClient.Interface, userCIDR string,
userGateway string) (*Controller, error) { userGateway string) (*Controller, error) {
c := &Controller{ c := &Controller{
k8sclient: kubeClient, k8sclient: kubeClient,

View File

@ -34,10 +34,10 @@ import (
"k8s.io/client-go/tools/cache" "k8s.io/client-go/tools/cache"
) )
// TenantController manages life cycle of Tenant. // TenantController manages the life cycle of Tenant.
type TenantController struct { type TenantController struct {
k8sClient *kubernetes.Clientset k8sClient *kubernetes.Clientset
kubeCRDClient *crdClient.CRDClient kubeCRDClient crdClient.Interface
openstackClient openstack.Interface openstackClient openstack.Interface
} }
@ -64,16 +64,12 @@ func NewTenantController(kubeClient *kubernetes.Clientset,
return c, nil return c, nil
} }
func (c *TenantController) GetKubeCRDClient() *crdClient.CRDClient {
return c.kubeCRDClient
}
// Run the controller. // Run the controller.
func (c *TenantController) Run(stopCh <-chan struct{}) error { func (c *TenantController) Run(stopCh <-chan struct{}) error {
defer utilruntime.HandleCrash() defer utilruntime.HandleCrash()
source := cache.NewListWatchFromClient( source := cache.NewListWatchFromClient(
c.kubeCRDClient.Client, c.kubeCRDClient.Client(),
crv1.TenantResourcePlural, crv1.TenantResourcePlural,
apiv1.NamespaceAll, apiv1.NamespaceAll,
fields.Everything()) fields.Everything())
@ -97,7 +93,7 @@ func (c *TenantController) onAdd(obj interface{}) {
tenant := obj.(*crv1.Tenant) tenant := obj.(*crv1.Tenant)
glog.V(3).Infof("Tenant controller received new object %#v\n", tenant) glog.V(3).Infof("Tenant controller received new object %#v\n", tenant)
copyObj, err := c.kubeCRDClient.Scheme.Copy(tenant) copyObj, err := c.kubeCRDClient.Scheme().Copy(tenant)
if err != nil { if err != nil {
glog.Errorf("ERROR creating a deep copy of tenant object: %#v\n", err) glog.Errorf("ERROR creating a deep copy of tenant object: %#v\n", err)
return return
@ -140,7 +136,7 @@ func (c *TenantController) onDelete(obj interface{}) {
glog.Errorf("failed to delete network for tenant: %v", tenantName) glog.Errorf("failed to delete network for tenant: %v", tenantName)
} }
//Delete namespace // Delete namespace
err = c.deleteNamespace(tenantName) err = c.deleteNamespace(tenantName)
if err != nil { if err != nil {
glog.Errorf("Delete namespace %s failed: %v", tenantName, err) glog.Errorf("Delete namespace %s failed: %v", tenantName, err)

View File

@ -30,12 +30,34 @@ import (
"github.com/golang/glog" "github.com/golang/glog"
) )
type CRDClient struct { // Interface should be implemented by a CRD client.
Client *rest.RESTClient type Interface interface {
Scheme *runtime.Scheme // AddTenant adds Tenant CRD object by given object.
AddTenant(tenant *crv1.Tenant) error
// GetTenant returns Tenant CRD object by tenantName.
GetTenant(tenantName string) (*crv1.Tenant, error)
// UpdateTenant updates Tenant CRD object by given object.
UpdateTenant(tenant *crv1.Tenant) error
// AddNetwork adds Network CRD object by given object.
AddNetwork(network *crv1.Network) error
// UpdateNetwork updates Network CRD object by given object.
UpdateNetwork(network *crv1.Network) error
// DeleteNetwork deletes Network CRD object by networkName.
DeleteNetwork(networkName string) error
// Client returns the RESTClient.
Client() *rest.RESTClient
// Scheme returns runtime scheme.
Scheme() *runtime.Scheme
} }
func NewCRDClient(cfg *rest.Config) (*CRDClient, error) { // CRDClient implements the Interface.
type CRDClient struct {
client *rest.RESTClient
scheme *runtime.Scheme
}
// NewCRDClient returns a new CRD client.
func NewCRDClient(cfg *rest.Config) (Interface, error) {
scheme := runtime.NewScheme() scheme := runtime.NewScheme()
if err := crv1.AddToScheme(scheme); err != nil { if err := crv1.AddToScheme(scheme); err != nil {
return nil, err return nil, err
@ -53,14 +75,24 @@ func NewCRDClient(cfg *rest.Config) (*CRDClient, error) {
} }
return &CRDClient{ return &CRDClient{
Client: client, client: client,
Scheme: scheme, scheme: scheme,
}, nil }, nil
} }
// UpdateNetwork updates Network CRD object by given object // Client returns the RESTClient.
func (c *CRDClient) UpdateNetwork(network *crv1.Network) { func (c *CRDClient) Client() *rest.RESTClient {
err := c.Client.Put(). return c.client
}
// Scheme returns runtime scheme.
func (c *CRDClient) Scheme() *runtime.Scheme {
return c.scheme
}
// UpdateNetwork updates Network CRD object by given object.
func (c *CRDClient) UpdateNetwork(network *crv1.Network) error {
err := c.client.Put().
Name(network.Name). Name(network.Name).
Namespace(network.Namespace). Namespace(network.Namespace).
Resource(crv1.NetworkResourcePlural). Resource(crv1.NetworkResourcePlural).
@ -70,14 +102,15 @@ func (c *CRDClient) UpdateNetwork(network *crv1.Network) {
if err != nil { if err != nil {
glog.Errorf("ERROR updating network: %v\n", err) glog.Errorf("ERROR updating network: %v\n", err)
} else { return err
glog.V(3).Infof("UPDATED network: %#v\n", network)
} }
glog.V(3).Infof("UPDATED network: %#v\n", network)
return nil
} }
// UpdateTenant updates Network CRD object by given object // UpdateTenant updates Network CRD object by given object.
func (c *CRDClient) UpdateTenant(tenant *crv1.Tenant) { func (c *CRDClient) UpdateTenant(tenant *crv1.Tenant) error {
err := c.Client.Put(). err := c.client.Put().
Name(tenant.Name). Name(tenant.Name).
Namespace(util.SystemTenant). Namespace(util.SystemTenant).
Resource(crv1.TenantResourcePlural). Resource(crv1.TenantResourcePlural).
@ -87,17 +120,18 @@ func (c *CRDClient) UpdateTenant(tenant *crv1.Tenant) {
if err != nil { if err != nil {
glog.Errorf("ERROR updating tenant: %v\n", err) glog.Errorf("ERROR updating tenant: %v\n", err)
} else { return err
glog.V(3).Infof("UPDATED tenant: %#v\n", tenant)
} }
glog.V(3).Infof("UPDATED tenant: %#v\n", tenant)
return nil
} }
// GetTenant returns tenant from CRD // GetTenant returns Tenant CRD object by tenantName.
// NOTE: all tenant are stored under system namespace // NOTE: all tenant are stored under system namespace.
func (c *CRDClient) GetTenant(tenantName string) (*crv1.Tenant, error) { func (c *CRDClient) GetTenant(tenantName string) (*crv1.Tenant, error) {
tenant := crv1.Tenant{} tenant := crv1.Tenant{}
// tenant always has same name and namespace // tenant always has the same name with namespace
err := c.Client.Get(). err := c.client.Get().
Resource(crv1.TenantResourcePlural). Resource(crv1.TenantResourcePlural).
Namespace(util.SystemTenant). Namespace(util.SystemTenant).
Name(tenantName). Name(tenantName).
@ -108,10 +142,10 @@ func (c *CRDClient) GetTenant(tenantName string) (*crv1.Tenant, error) {
return &tenant, nil return &tenant, nil
} }
// AddTenant adds tenant to CRD // AddTenant adds Tenant CRD object by given object.
// NOTE: all tenant are added to system namespace // NOTE: all tenant are added to system namespace.
func (c *CRDClient) AddTenant(tenant *crv1.Tenant) error { func (c *CRDClient) AddTenant(tenant *crv1.Tenant) error {
err := c.Client.Post(). err := c.client.Post().
Namespace(util.SystemTenant). Namespace(util.SystemTenant).
Resource(crv1.TenantResourcePlural). Resource(crv1.TenantResourcePlural).
Body(tenant). Body(tenant).
@ -122,8 +156,9 @@ func (c *CRDClient) AddTenant(tenant *crv1.Tenant) error {
return nil return nil
} }
// AddNetwork adds Network CRD object by given object.
func (c *CRDClient) AddNetwork(network *crv1.Network) error { func (c *CRDClient) AddNetwork(network *crv1.Network) error {
err := c.Client.Post(). err := c.client.Post().
Resource(crv1.NetworkResourcePlural). Resource(crv1.NetworkResourcePlural).
Namespace(network.GetNamespace()). Namespace(network.GetNamespace()).
Body(network). Body(network).
@ -134,12 +169,13 @@ func (c *CRDClient) AddNetwork(network *crv1.Network) error {
return nil return nil
} }
func (c *CRDClient) DeleteNetwork(namespace string) error { // DeleteNetwork deletes Network CRD object by networkName.
// NOTE: the automatically created network for tenant use namespace as name // NOTE: the automatically created network for tenant use namespace as name.
err := c.Client.Delete(). func (c *CRDClient) DeleteNetwork(networkName string) error {
err := c.client.Delete().
Resource(crv1.NetworkResourcePlural). Resource(crv1.NetworkResourcePlural).
Namespace(namespace). Namespace(networkName).
Name(namespace). Name(networkName).
Do().Error() Do().Error()
if err != nil { if err != nil {
return fmt.Errorf("failed to delete Network: %v", err) return fmt.Errorf("failed to delete Network: %v", err)

View File

@ -0,0 +1,245 @@
/*
Copyright (c) 2017 OpenStack Foundation.
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 kubecrd
import (
"fmt"
"sync"
crv1 "git.openstack.org/openstack/stackube/pkg/apis/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/rest"
)
// CalledDetail is the struct contains called function name and arguments.
type CalledDetail struct {
// Name of the function called.
Name string
// Argument of the function called.
Argument interface{}
}
// FakeCRDClient is a simple fake CRD client, so that stackube
// can be run for testing without requiring a real kubernetes setup.
type FakeCRDClient struct {
sync.Mutex
called []CalledDetail
errors map[string]error
Tenants map[string]*crv1.Tenant
Networks map[string]*crv1.Network
scheme *runtime.Scheme
}
var _ = Interface(&FakeCRDClient{})
// NewFake creates a new FakeCRDClient.
func NewFake() (*FakeCRDClient, error) {
scheme := runtime.NewScheme()
if err := crv1.AddToScheme(scheme); err != nil {
return nil, err
}
return &FakeCRDClient{
errors: make(map[string]error),
Tenants: make(map[string]*crv1.Tenant),
Networks: make(map[string]*crv1.Network),
scheme: scheme,
}, nil
}
func (f *FakeCRDClient) getError(op string) error {
err, ok := f.errors[op]
if ok {
delete(f.errors, op)
return err
}
return nil
}
// InjectError inject error for call
func (f *FakeCRDClient) InjectError(fn string, err error) {
f.Lock()
defer f.Unlock()
f.errors[fn] = err
}
// InjectErrors inject errors for calls
func (f *FakeCRDClient) InjectErrors(errs map[string]error) {
f.Lock()
defer f.Unlock()
for fn, err := range errs {
f.errors[fn] = err
}
}
// ClearErrors clear errors for call
func (f *FakeCRDClient) ClearErrors() {
f.Lock()
defer f.Unlock()
f.errors = make(map[string]error)
}
func (f *FakeCRDClient) appendCalled(name string, argument interface{}) {
call := CalledDetail{Name: name, Argument: argument}
f.called = append(f.called, call)
}
// GetCalledNames get names of call
func (f *FakeCRDClient) GetCalledNames() []string {
f.Lock()
defer f.Unlock()
names := []string{}
for _, detail := range f.called {
names = append(names, detail.Name)
}
return names
}
// GetCalledDetails get detail of each call.
func (f *FakeCRDClient) GetCalledDetails() []CalledDetail {
f.Lock()
defer f.Unlock()
// Copy the list and return.
return append([]CalledDetail{}, f.called...)
}
// SetTenants injects fake tenant.
func (f *FakeCRDClient) SetTenants(tenants []*crv1.Tenant) {
f.Lock()
defer f.Unlock()
for _, tenant := range tenants {
f.Tenants[tenant.Name] = tenant
}
}
// SetNetworks injects fake network.
func (f *FakeCRDClient) SetNetworks(networks []*crv1.Network) {
f.Lock()
defer f.Unlock()
for _, network := range networks {
f.Networks[network.Name] = network
}
}
// Client is a test implementation of Interface.Client.
func (f *FakeCRDClient) Client() *rest.RESTClient {
return nil
}
// Scheme is a test implementation of Interface.Scheme.
func (f *FakeCRDClient) Scheme() *runtime.Scheme {
return f.scheme
}
// AddTenant is a test implementation of Interface.AddTenant.
func (f *FakeCRDClient) AddTenant(tenant *crv1.Tenant) error {
f.Lock()
defer f.Unlock()
f.appendCalled("AddTenant", tenant)
if err := f.getError("AddTenant"); err != nil {
return err
}
if _, ok := f.Tenants[tenant.Name]; ok {
return nil
}
f.Tenants[tenant.Name] = tenant
return nil
}
// GetTenant is a test implementation of Interface.GetTenant.
func (f *FakeCRDClient) GetTenant(tenantName string) (*crv1.Tenant, error) {
f.Lock()
defer f.Unlock()
f.appendCalled("GetTenant", tenantName)
if err := f.getError("GetTenant"); err != nil {
return nil, err
}
tenant, ok := f.Tenants[tenantName]
if !ok {
return nil, fmt.Errorf("Tenant %s not found", tenantName)
}
return tenant, nil
}
// AddNetwork is a test implementation of Interface.AddNetwork.
func (f *FakeCRDClient) AddNetwork(network *crv1.Network) error {
f.Lock()
defer f.Unlock()
f.appendCalled("AddNetwork", network)
if err := f.getError("AddNetwork"); err != nil {
return err
}
if _, ok := f.Networks[network.Name]; ok {
return nil
}
f.Networks[network.Name] = network
return nil
}
// UpdateTenant is a test implementation of Interface.UpdateTenant.
func (f *FakeCRDClient) UpdateTenant(tenant *crv1.Tenant) error {
f.Lock()
defer f.Unlock()
f.appendCalled("UpdateTenant", tenant)
if err := f.getError("UpdateTenant"); err != nil {
return err
}
if _, ok := f.Tenants[tenant.Name]; !ok {
return fmt.Errorf("Tenant %s not exist", tenant.Name)
}
f.Tenants[tenant.Name] = tenant
return nil
}
// UpdateNetwork is a test implementation of Interface.UpdateNetwork.
func (f *FakeCRDClient) UpdateNetwork(network *crv1.Network) error {
f.Lock()
defer f.Unlock()
f.appendCalled("UpdateNetwork", network)
if err := f.getError("UpdateNetwork"); err != nil {
return err
}
if _, ok := f.Networks[network.Name]; !ok {
return fmt.Errorf("Network %s not exist", network.Name)
}
f.Networks[network.Name] = network
return nil
}
// DeleteNetwork is a test implementation of Interface.DeleteNetwork.
func (f *FakeCRDClient) DeleteNetwork(networkName string) error {
f.Lock()
defer f.Unlock()
f.appendCalled("DeleteNetwork", networkName)
if err := f.getError("DeleteNetwork"); err != nil {
return err
}
delete(f.Networks, networkName)
return nil
}

View File

@ -48,18 +48,15 @@ const (
defaultSideCarImage = "stackube/k8s-dns-sidecar-amd64:1.14.4" defaultSideCarImage = "stackube/k8s-dns-sidecar-amd64:1.14.4"
) )
// Watcher is an network of watching on resource create/update/delete events // NetworkController manages the life cycle of Network.
type NetworkController struct { type NetworkController struct {
k8sclient *kubernetes.Clientset k8sclient *kubernetes.Clientset
kubeCRDClient *kubecrd.CRDClient kubeCRDClient kubecrd.Interface
driver openstack.Interface driver openstack.Interface
networkInformer cache.Controller networkInformer cache.Controller
} }
func (c *NetworkController) GetKubeCRDClient() *kubecrd.CRDClient { // Run the network controller.
return c.kubeCRDClient
}
func (c *NetworkController) Run(stopCh <-chan struct{}) error { func (c *NetworkController) Run(stopCh <-chan struct{}) error {
defer utilruntime.HandleCrash() defer utilruntime.HandleCrash()
@ -69,6 +66,7 @@ func (c *NetworkController) Run(stopCh <-chan struct{}) error {
return nil return nil
} }
// NewNetworkController creates a new NetworkController.
func NewNetworkController(kubeClient *kubernetes.Clientset, osClient openstack.Interface, kubeExtClient *apiextensionsclient.Clientset) (*NetworkController, error) { func NewNetworkController(kubeClient *kubernetes.Clientset, osClient openstack.Interface, kubeExtClient *apiextensionsclient.Clientset) (*NetworkController, error) {
// initialize CRD if it does not exist // initialize CRD if it does not exist
_, err := kubecrd.CreateNetworkCRD(kubeExtClient) _, err := kubecrd.CreateNetworkCRD(kubeExtClient)
@ -77,7 +75,7 @@ func NewNetworkController(kubeClient *kubernetes.Clientset, osClient openstack.I
} }
source := cache.NewListWatchFromClient( source := cache.NewListWatchFromClient(
osClient.GetCRDClient().Client, osClient.GetCRDClient().Client(),
crv1.NetworkResourcePlural, crv1.NetworkResourcePlural,
apiv1.NamespaceAll, apiv1.NamespaceAll,
fields.Everything()) fields.Everything())
@ -108,7 +106,7 @@ func (c *NetworkController) onAdd(obj interface{}) {
// NEVER modify objects from the store. It's a read-only, local cache. // NEVER modify objects from the store. It's a read-only, local cache.
// You can use networkScheme.Copy() to make a deep copy of original object and modify this copy // You can use networkScheme.Copy() to make a deep copy of original object and modify this copy
// Or create a copy manually for better performance // Or create a copy manually for better performance
copyObj, err := c.GetKubeCRDClient().Scheme.Copy(network) copyObj, err := c.kubeCRDClient.Scheme().Copy(network)
if err != nil { if err != nil {
glog.Errorf("ERROR creating a deep copy of network object: %v\n", err) glog.Errorf("ERROR creating a deep copy of network object: %v\n", err)
return return

View File

@ -106,13 +106,14 @@ type Interface interface {
// EnsureLoadBalancerDeleted ensures a load balancer is deleted. // EnsureLoadBalancerDeleted ensures a load balancer is deleted.
EnsureLoadBalancerDeleted(name string) error EnsureLoadBalancerDeleted(name string) error
// GetCRDClient returns the CRDClient. // GetCRDClient returns the CRDClient.
GetCRDClient() *crdClient.CRDClient GetCRDClient() crdClient.Interface
// GetPluginName returns the plugin name. // GetPluginName returns the plugin name.
GetPluginName() string GetPluginName() string
// GetIntegrationBridge returns the integration bridge name. // GetIntegrationBridge returns the integration bridge name.
GetIntegrationBridge() string GetIntegrationBridge() string
} }
// Client implements the openstack client Interface.
type Client struct { type Client struct {
Identity *gophercloud.ServiceClient Identity *gophercloud.ServiceClient
Provider *gophercloud.ProviderClient Provider *gophercloud.ProviderClient
@ -121,7 +122,7 @@ type Client struct {
ExtNetID string ExtNetID string
PluginName string PluginName string
IntegrationBridge string IntegrationBridge string
CRDClient *crdClient.CRDClient CRDClient crdClient.Interface
} }
type PluginOpts struct { type PluginOpts struct {
@ -129,6 +130,7 @@ type PluginOpts struct {
IntegrationBridge string `gcfg:"integration-bridge"` IntegrationBridge string `gcfg:"integration-bridge"`
} }
// Config used to configure the openstack client.
type Config struct { type Config struct {
Global struct { Global struct {
AuthUrl string `gcfg:"auth-url"` AuthUrl string `gcfg:"auth-url"`
@ -151,6 +153,7 @@ func toAuthOptions(cfg Config) gophercloud.AuthOptions {
} }
} }
// NewClient returns a new openstack client.
func NewClient(config string, kubeConfig string) (Interface, error) { func NewClient(config string, kubeConfig string) (Interface, error) {
var opts gophercloud.AuthOptions var opts gophercloud.AuthOptions
cfg, err := readConfig(config) cfg, err := readConfig(config)
@ -221,7 +224,7 @@ func readConfig(config string) (Config, error) {
} }
// GetCRDClient returns the CRDClient. // GetCRDClient returns the CRDClient.
func (os *Client) GetCRDClient() *crdClient.CRDClient { func (os *Client) GetCRDClient() crdClient.Interface {
return os.CRDClient return os.CRDClient
} }
@ -466,6 +469,7 @@ func (os *Client) GetNetworkByName(networkName string) (*drivertypes.Network, er
return os.OSNetworktoProviderNetwork(osNetwork) return os.OSNetworktoProviderNetwork(osNetwork)
} }
// OSNetworktoProviderNetwork transfers networks.Network to drivertypes.Network.
func (os *Client) OSNetworktoProviderNetwork(osNetwork *networks.Network) (*drivertypes.Network, error) { func (os *Client) OSNetworktoProviderNetwork(osNetwork *networks.Network) (*drivertypes.Network, error) {
var providerNetwork drivertypes.Network var providerNetwork drivertypes.Network
var providerSubnets []*drivertypes.Subnet var providerSubnets []*drivertypes.Subnet
@ -487,6 +491,7 @@ func (os *Client) OSNetworktoProviderNetwork(osNetwork *networks.Network) (*driv
return &providerNetwork, nil return &providerNetwork, nil
} }
// ToProviderStatus transfers networks.Network's status to drivertypes.Network's status.
func (os *Client) ToProviderStatus(status string) string { func (os *Client) ToProviderStatus(status string) string {
switch status { switch status {
case "ACTIVE": case "ACTIVE":

View File

@ -18,11 +18,10 @@ package openstack
import ( import (
"crypto/sha1" "crypto/sha1"
"errors"
"fmt" "fmt"
"io" "io"
"sync"
crv1 "git.openstack.org/openstack/stackube/pkg/apis/v1"
crdClient "git.openstack.org/openstack/stackube/pkg/kubecrd" crdClient "git.openstack.org/openstack/stackube/pkg/kubecrd"
drivertypes "git.openstack.org/openstack/stackube/pkg/openstack/types" drivertypes "git.openstack.org/openstack/stackube/pkg/openstack/types"
"git.openstack.org/openstack/stackube/pkg/util" "git.openstack.org/openstack/stackube/pkg/util"
@ -34,19 +33,27 @@ import (
"github.com/gophercloud/gophercloud/openstack/networking/v2/subnets" "github.com/gophercloud/gophercloud/openstack/networking/v2/subnets"
) )
var ErrAlreadyExist = errors.New("AlreadyExist") // CalledDetail is the struct contains called function name and arguments.
type CalledDetail struct {
// Name of the function called.
Name string
// Argument of the function called.
Argument []interface{}
}
// FakeOSClient is a simple fake openstack client, so that stackube // FakeOSClient is a simple fake openstack client, so that stackube
// can be run for testing without requiring a real openstack setup. // can be run for testing without requiring a real openstack setup.
type FakeOSClient struct { type FakeOSClient struct {
Tenants map[string]*tenants.Tenant sync.Mutex
Users map[string]*users.User called []CalledDetail
Networks map[string]*drivertypes.Network errors map[string]error
Subnets map[string]*subnets.Subnet Tenants map[string]*tenants.Tenant
Routers map[string]*routers.Router Users map[string]*users.User
Ports map[string][]ports.Port Networks map[string]*drivertypes.Network
// TODO(mozhuli): Add fakeCRDClient. Subnets map[string]*subnets.Subnet
CRDClient *crdClient.CRDClient Routers map[string]*routers.Router
Ports map[string][]ports.Port
CRDClient crdClient.Interface
PluginName string PluginName string
IntegrationBridge string IntegrationBridge string
} }
@ -54,50 +61,116 @@ type FakeOSClient struct {
var _ = Interface(&FakeOSClient{}) var _ = Interface(&FakeOSClient{})
// NewFake creates a new FakeOSClient. // NewFake creates a new FakeOSClient.
func NewFake() *FakeOSClient { func NewFake(crdClient crdClient.Interface) *FakeOSClient {
return &FakeOSClient{ return &FakeOSClient{
errors: make(map[string]error),
Tenants: make(map[string]*tenants.Tenant), Tenants: make(map[string]*tenants.Tenant),
Users: make(map[string]*users.User), Users: make(map[string]*users.User),
Networks: make(map[string]*drivertypes.Network), Networks: make(map[string]*drivertypes.Network),
Subnets: make(map[string]*subnets.Subnet), Subnets: make(map[string]*subnets.Subnet),
Routers: make(map[string]*routers.Router), Routers: make(map[string]*routers.Router),
Ports: make(map[string][]ports.Port), Ports: make(map[string][]ports.Port),
CRDClient: crdClient,
PluginName: "ovs", PluginName: "ovs",
IntegrationBridge: "bi-int", IntegrationBridge: "bi-int",
} }
} }
func (f *FakeOSClient) getError(op string) error {
err, ok := f.errors[op]
if ok {
delete(f.errors, op)
return err
}
return nil
}
// InjectError inject error for call
func (f *FakeOSClient) InjectError(fn string, err error) {
f.Lock()
defer f.Unlock()
f.errors[fn] = err
}
// InjectErrors inject errors for calls
func (f *FakeOSClient) InjectErrors(errs map[string]error) {
f.Lock()
defer f.Unlock()
for fn, err := range errs {
f.errors[fn] = err
}
}
// ClearErrors clear errors for call
func (f *FakeOSClient) ClearErrors() {
f.Lock()
defer f.Unlock()
f.errors = make(map[string]error)
}
func (f *FakeOSClient) appendCalled(name string, argument ...interface{}) {
call := CalledDetail{Name: name, Argument: argument}
f.called = append(f.called, call)
}
// GetCalledNames get names of call
func (f *FakeOSClient) GetCalledNames() []string {
f.Lock()
defer f.Unlock()
names := []string{}
for _, detail := range f.called {
names = append(names, detail.Name)
}
return names
}
// GetCalledDetails get detail of each call.
func (f *FakeOSClient) GetCalledDetails() []CalledDetail {
f.Lock()
defer f.Unlock()
// Copy the list and return.
return append([]CalledDetail{}, f.called...)
}
// SetTenant injects fake tenant. // SetTenant injects fake tenant.
func (os *FakeOSClient) SetTenant(tenantName, tenantID string) { func (f *FakeOSClient) SetTenant(tenantName, tenantID string) {
f.Lock()
defer f.Unlock()
tenant := &tenants.Tenant{ tenant := &tenants.Tenant{
Name: tenantName, Name: tenantName,
ID: tenantID, ID: tenantID,
} }
os.Tenants[tenantName] = tenant f.Tenants[tenantName] = tenant
} }
// SetUser injects fake user. // SetUser injects fake user.
func (os *FakeOSClient) SetUser(userName, userID, tenantID string) { func (f *FakeOSClient) SetUser(userName, userID, tenantID string) {
f.Lock()
defer f.Unlock()
user := &users.User{ user := &users.User{
Username: userName, Username: userName,
ID: userID, ID: userID,
TenantID: tenantID, TenantID: tenantID,
} }
os.Users[tenantID] = user f.Users[tenantID] = user
} }
// SetNetwork injects fake network. // SetNetwork injects fake network.
func (os *FakeOSClient) SetNetwork(networkName, networkID string) { func (f *FakeOSClient) SetNetwork(networkName, networkID string) {
f.Lock()
defer f.Unlock()
network := &drivertypes.Network{ network := &drivertypes.Network{
Name: networkName, Name: networkName,
Uid: networkID, Uid: networkID,
} }
os.Networks[networkName] = network f.Networks[networkName] = network
} }
// SetPort injects fake port. // SetPort injects fake port.
func (os *FakeOSClient) SetPort(networkID, deviceOwner, deviceID string) { func (f *FakeOSClient) SetPort(networkID, deviceOwner, deviceID string) {
netPorts, ok := os.Ports[networkID] f.Lock()
defer f.Unlock()
netPorts, ok := f.Ports[networkID]
p := ports.Port{ p := ports.Port{
NetworkID: networkID, NetworkID: networkID,
DeviceOwner: deviceOwner, DeviceOwner: deviceOwner,
@ -106,10 +179,10 @@ func (os *FakeOSClient) SetPort(networkID, deviceOwner, deviceID string) {
if !ok { if !ok {
var ps []ports.Port var ps []ports.Port
ps = append(ps, p) ps = append(ps, p)
os.Ports[networkID] = ps f.Ports[networkID] = ps
} }
netPorts = append(netPorts, p) netPorts = append(netPorts, p)
os.Ports[networkID] = netPorts f.Ports[networkID] = netPorts
} }
func tenantIDHash(tenantName string) string { func tenantIDHash(tenantName string) string {
@ -146,84 +219,129 @@ func idHash(data ...string) string {
return fmt.Sprintf("%x", h.Sum(nil))[:16] return fmt.Sprintf("%x", h.Sum(nil))[:16]
} }
// CreateTenant creates tenant by tenantname. // CreateTenant is a test implementation of Interface.CreateTenant.
func (os *FakeOSClient) CreateTenant(tenantName string) (string, error) { func (f *FakeOSClient) CreateTenant(tenantName string) (string, error) {
if t, ok := os.Tenants[tenantName]; ok { f.Lock()
defer f.Unlock()
f.appendCalled("CreateTenant", tenantName)
if err := f.getError("CreateTenant"); err != nil {
return "", err
}
if t, ok := f.Tenants[tenantName]; ok {
return t.ID, nil return t.ID, nil
} }
tenant := &tenants.Tenant{ tenant := &tenants.Tenant{
Name: tenantName, Name: tenantName,
ID: tenantIDHash(tenantName), ID: tenantIDHash(tenantName),
} }
os.Tenants[tenantName] = tenant f.Tenants[tenantName] = tenant
return tenant.ID, nil return tenant.ID, nil
} }
// DeleteTenant deletes tenant by tenantName. // DeleteTenant is a test implementation of Interface.DeleteTenant.
func (os *FakeOSClient) DeleteTenant(tenantName string) error { func (f *FakeOSClient) DeleteTenant(tenantName string) error {
delete(os.Tenants, tenantName) f.Lock()
defer f.Unlock()
f.appendCalled("DeleteTenant", tenantName)
if err := f.getError("DeleteTenant"); err != nil {
return err
}
delete(f.Tenants, tenantName)
return nil return nil
} }
// GetTenantIDFromName gets tenantID by tenantName. // GetTenantIDFromName is a test implementation of Interface.GetTenantIDFromName.
func (os *FakeOSClient) GetTenantIDFromName(tenantName string) (string, error) { func (f *FakeOSClient) GetTenantIDFromName(tenantName string) (string, error) {
f.Lock()
defer f.Unlock()
f.appendCalled("GetTenantIDFromName", tenantName)
if err := f.getError("GetTenantIDFromName"); err != nil {
return "", err
}
if util.IsSystemNamespace(tenantName) { if util.IsSystemNamespace(tenantName) {
tenantName = util.SystemTenant tenantName = util.SystemTenant
} }
// If tenantID is specified, return it directly // If tenantID is specified, return it directly
var ( tenant, err := f.CRDClient.GetTenant(tenantName)
tenant *crv1.Tenant if err != nil {
err error
)
// TODO(mozhuli): use fakeCRDClient.
if tenant, err = os.CRDClient.GetTenant(tenantName); err != nil {
return "", err return "", err
} }
if tenant.Spec.TenantID != "" { if tenant.Spec.TenantID != "" {
return tenant.Spec.TenantID, nil return tenant.Spec.TenantID, nil
} }
t, ok := os.Tenants[tenantName] t, ok := f.Tenants[tenantName]
if !ok { if !ok {
return "", nil return "", fmt.Errorf("Tenant %s not exist", tenantName)
} }
return t.ID, nil return t.ID, nil
} }
// CheckTenantByID checks tenant exist or not by tenantID. // CheckTenantByID is a test implementation of Interface.CheckTenantByID.
func (os *FakeOSClient) CheckTenantByID(tenantID string) (bool, error) { func (f *FakeOSClient) CheckTenantByID(tenantID string) (bool, error) {
for _, tenent := range os.Tenants { f.Lock()
defer f.Unlock()
f.appendCalled("CheckTenantByID", tenantID)
if err := f.getError("CheckTenantByID"); err != nil {
return false, err
}
for _, tenent := range f.Tenants {
if tenent.ID == tenantID { if tenent.ID == tenantID {
return true, nil return true, nil
} }
} }
return false, ErrNotFound return false, fmt.Errorf("Tenant %s not exist", tenantID)
} }
// CreateUser creates user with username, password in the tenant. // CreateUser is a test implementation of Interface.CreateUser.
func (os *FakeOSClient) CreateUser(username, password, tenantID string) error { func (f *FakeOSClient) CreateUser(username, password, tenantID string) error {
f.Lock()
defer f.Unlock()
f.appendCalled("CreateUser", username, password, tenantID)
if err := f.getError("CreateUser"); err != nil {
return err
}
user := &users.User{ user := &users.User{
Name: username, Name: username,
TenantID: tenantID, TenantID: tenantID,
ID: userIDHash(username, tenantID), ID: userIDHash(username, tenantID),
} }
os.Users[tenantID] = user f.Users[tenantID] = user
return nil return nil
} }
// DeleteAllUsersOnTenant deletes all users on the tenant. // DeleteAllUsersOnTenant is a test implementation of Interface.DeleteAllUsersOnTenant.
func (os *FakeOSClient) DeleteAllUsersOnTenant(tenantName string) error { func (f *FakeOSClient) DeleteAllUsersOnTenant(tenantName string) error {
tenant := os.Tenants[tenantName] f.Lock()
defer f.Unlock()
f.appendCalled("DeleteAllUsersOnTenant", tenantName)
if err := f.getError("DeleteAllUsersOnTenant"); err != nil {
return err
}
delete(os.Users, tenant.ID) tenant := f.Tenants[tenantName]
delete(f.Users, tenant.ID)
return nil return nil
} }
func (os *FakeOSClient) createNetwork(networkName, tenantID string) error { func (f *FakeOSClient) createNetwork(networkName, tenantID string) error {
if _, ok := os.Networks[networkName]; ok { f.Lock()
return ErrAlreadyExist defer f.Unlock()
f.appendCalled("createNetwork", networkName, tenantID)
if err := f.getError("createNetwork"); err != nil {
return err
}
if _, ok := f.Networks[networkName]; ok {
return fmt.Errorf("Network %s already exist", networkName)
} }
network := &drivertypes.Network{ network := &drivertypes.Network{
@ -231,18 +349,32 @@ func (os *FakeOSClient) createNetwork(networkName, tenantID string) error {
Uid: networkIDHash(networkName), Uid: networkIDHash(networkName),
TenantID: tenantID, TenantID: tenantID,
} }
os.Networks[networkName] = network f.Networks[networkName] = network
return nil return nil
} }
func (os *FakeOSClient) deleteNetwork(networkName string) error { func (f *FakeOSClient) deleteNetwork(networkName string) error {
delete(os.Networks, networkName) f.Lock()
defer f.Unlock()
f.appendCalled("deleteNetwork", networkName)
if err := f.getError("deleteNetwork"); err != nil {
return err
}
delete(f.Networks, networkName)
return nil return nil
} }
func (os *FakeOSClient) createRouter(routerName, tenantID string) error { func (f *FakeOSClient) createRouter(routerName, tenantID string) error {
if _, ok := os.Routers[routerName]; ok { f.Lock()
return ErrAlreadyExist defer f.Unlock()
f.appendCalled("createRouter", routerName, tenantID)
if err := f.getError("createRouter"); err != nil {
return err
}
if _, ok := f.Routers[routerName]; ok {
return fmt.Errorf("Router %s already exist", routerName)
} }
router := &routers.Router{ router := &routers.Router{
@ -250,18 +382,32 @@ func (os *FakeOSClient) createRouter(routerName, tenantID string) error {
TenantID: tenantID, TenantID: tenantID,
ID: routerIDHash(routerName), ID: routerIDHash(routerName),
} }
os.Routers[routerName] = router f.Routers[routerName] = router
return nil return nil
} }
func (os *FakeOSClient) deleteRouter(routerName string) error { func (f *FakeOSClient) deleteRouter(routerName string) error {
delete(os.Routers, routerName) f.Lock()
defer f.Unlock()
f.appendCalled("deleteRouter", routerName)
if err := f.getError("deleteRouter"); err != nil {
return err
}
delete(f.Routers, routerName)
return nil return nil
} }
func (os *FakeOSClient) createSubnet(subnetName, networkID, tenantID string) error { func (f *FakeOSClient) createSubnet(subnetName, networkID, tenantID string) error {
if _, ok := os.Subnets[subnetName]; ok { f.Lock()
return ErrAlreadyExist defer f.Unlock()
f.appendCalled("createSubnet", subnetName, networkID, tenantID)
if err := f.getError("createSubnet"); err != nil {
return err
}
if _, ok := f.Subnets[subnetName]; ok {
return fmt.Errorf("Subnet %s already exist", subnetName)
} }
subnet := &subnets.Subnet{ subnet := &subnets.Subnet{
@ -270,77 +416,98 @@ func (os *FakeOSClient) createSubnet(subnetName, networkID, tenantID string) err
NetworkID: networkID, NetworkID: networkID,
ID: subnetIDHash(subnetName), ID: subnetIDHash(subnetName),
} }
os.Subnets[subnetName] = subnet f.Subnets[subnetName] = subnet
return nil return nil
} }
// CreateNetwork creates network. // CreateNetwork is a test implementation of Interface.CreateNetwork.
// TODO(mozhuli): make it more general. func (f *FakeOSClient) CreateNetwork(network *drivertypes.Network) error {
func (os *FakeOSClient) CreateNetwork(network *drivertypes.Network) error { f.Lock()
defer f.Unlock()
f.appendCalled("CreateNetwork", network)
if err := f.getError("CreateNetwork"); err != nil {
return err
}
if len(network.Subnets) == 0 { if len(network.Subnets) == 0 {
return errors.New("Subnets is null") return fmt.Errorf("Subnets is null")
} }
// create network // create network
err := os.createNetwork(network.Name, network.TenantID) err := f.createNetwork(network.Name, network.TenantID)
if err != nil { if err != nil {
return errors.New("Create network failed") return err
} }
// create router, and use network name as router name for convenience. // create router, and use network name as router name for convenience.
err = os.createRouter(network.Name, network.TenantID) err = f.createRouter(network.Name, network.TenantID)
if err != nil { if err != nil {
os.deleteNetwork(network.Name) f.deleteNetwork(network.Name)
return errors.New("Create router failed") return err
} }
// create subnets and connect them to router // create subnets and connect them to router
err = os.createSubnet(network.Subnets[0].Name, network.Uid, network.TenantID) err = f.createSubnet(network.Subnets[0].Name, network.Uid, network.TenantID)
if err != nil { if err != nil {
os.deleteRouter(network.Name) f.deleteRouter(network.Name)
os.deleteNetwork(network.Name) f.deleteNetwork(network.Name)
return errors.New("Create subnet failed") return err
} }
return nil return nil
} }
// GetNetworkByID gets network by networkID. // GetNetworkByID gets network by networkID.
func (os *FakeOSClient) GetNetworkByID(networkID string) (*drivertypes.Network, error) { // CreateTenant is a test implementation of Interface.CreateTenant.
func (f *FakeOSClient) GetNetworkByID(networkID string) (*drivertypes.Network, error) {
return nil, nil return nil, nil
} }
// GetNetworkByName get network by networkName // GetNetworkByName is a test implementation of Interface.GetNetworkByName.
func (os *FakeOSClient) GetNetworkByName(networkName string) (*drivertypes.Network, error) { func (f *FakeOSClient) GetNetworkByName(networkName string) (*drivertypes.Network, error) {
network, ok := os.Networks[networkName] f.Lock()
defer f.Unlock()
f.appendCalled("GetNetworkByName", networkName)
if err := f.getError("GetNetworkByName"); err != nil {
return nil, err
}
network, ok := f.Networks[networkName]
if !ok { if !ok {
return nil, ErrNotFound return nil, fmt.Errorf("Network %s not exist", networkName)
} }
return network, nil return network, nil
} }
// DeleteNetwork deletes network by networkName. // DeleteNetwork is a test implementation of Interface.DeleteNetwork.
func (os *FakeOSClient) DeleteNetwork(networkName string) error { func (f *FakeOSClient) DeleteNetwork(networkName string) error {
return nil return nil
} }
// GetProviderSubnet gets provider subnet by id // GetProviderSubnet is a test implementation of Interface.GetProviderSubnet.
func (os *FakeOSClient) GetProviderSubnet(osSubnetID string) (*drivertypes.Subnet, error) { func (f *FakeOSClient) GetProviderSubnet(osSubnetID string) (*drivertypes.Subnet, error) {
return nil, nil return nil, nil
} }
// CreatePort creates port by neworkID, tenantID and portName. // CreatePort is a test implementation of Interface.CreatePort.
func (os *FakeOSClient) CreatePort(networkID, tenantID, portName string) (*portsbinding.Port, error) { func (f *FakeOSClient) CreatePort(networkID, tenantID, portName string) (*portsbinding.Port, error) {
return nil, nil return nil, nil
} }
// GetPort gets port by portName. // GetPort is a test implementation of Interface.GetPort.
func (os *FakeOSClient) GetPort(name string) (*ports.Port, error) { func (f *FakeOSClient) GetPort(name string) (*ports.Port, error) {
return nil, nil return nil, nil
} }
// ListPorts list all ports which have the deviceOwner in the network. // ListPorts is a test implementation of Interface.ListPorts.
func (os *FakeOSClient) ListPorts(networkID, deviceOwner string) ([]ports.Port, error) { func (f *FakeOSClient) ListPorts(networkID, deviceOwner string) ([]ports.Port, error) {
f.Lock()
defer f.Unlock()
f.appendCalled("ListPorts", networkID, deviceOwner)
if err := f.getError("ListPorts"); err != nil {
return nil, err
}
var results []ports.Port var results []ports.Port
portList, ok := os.Ports[networkID] portList, ok := f.Ports[networkID]
if !ok { if !ok {
return results, nil return results, nil
} }
@ -353,48 +520,47 @@ func (os *FakeOSClient) ListPorts(networkID, deviceOwner string) ([]ports.Port,
return results, nil return results, nil
} }
// DeletePortByName deletes port by portName. // DeletePortByName is a test implementation of Interface.DeletePortByName.
func (os *FakeOSClient) DeletePortByName(portName string) error { func (f *FakeOSClient) DeletePortByName(portName string) error {
return nil return nil
} }
// DeletePortByID deletes port by portID. // DeletePortByID is a test implementation of Interface.DeletePortByID.
func (os *FakeOSClient) DeletePortByID(portID string) error { func (f *FakeOSClient) DeletePortByID(portID string) error {
return nil return nil
} }
// UpdatePortsBinding updates port binding. // UpdatePortsBinding is a test implementation of Interface.UpdatePortsBinding.
func (os *FakeOSClient) UpdatePortsBinding(portID, deviceOwner string) error { func (f *FakeOSClient) UpdatePortsBinding(portID, deviceOwner string) error {
return nil return nil
} }
// LoadBalancerExist returns whether a load balancer has already been exist. // LoadBalancerExist is a test implementation of Interface.LoadBalancerExist.
func (os *FakeOSClient) LoadBalancerExist(name string) (bool, error) { func (f *FakeOSClient) LoadBalancerExist(name string) (bool, error) {
return true, nil return true, nil
} }
// EnsureLoadBalancer ensures a load balancer is created. // EnsureLoadBalancer is a test implementation of Interface.EnsureLoadBalancer.
func (os *FakeOSClient) EnsureLoadBalancer(lb *LoadBalancer) (*LoadBalancerStatus, error) { func (f *FakeOSClient) EnsureLoadBalancer(lb *LoadBalancer) (*LoadBalancerStatus, error) {
return nil, nil return nil, nil
} }
// EnsureLoadBalancerDeleted ensures a load balancer is deleted. // EnsureLoadBalancerDeleted is a test implementation of Interface.EnsureLoadBalancerDeleted.
func (os *FakeOSClient) EnsureLoadBalancerDeleted(name string) error { func (f *FakeOSClient) EnsureLoadBalancerDeleted(name string) error {
return nil return nil
} }
// GetCRDClient returns the CRDClient. // GetCRDClient is a test implementation of Interface.GetCRDClient.
// TODO(mozhuli): use fakeCRDClient. func (f *FakeOSClient) GetCRDClient() crdClient.Interface {
func (os *FakeOSClient) GetCRDClient() *crdClient.CRDClient { return f.CRDClient
return os.CRDClient
} }
// GetPluginName returns the plugin name. // GetPluginName is a test implementation of Interface.GetPluginName.
func (os *FakeOSClient) GetPluginName() string { func (f *FakeOSClient) GetPluginName() string {
return os.PluginName return f.PluginName
} }
// GetIntegrationBridge returns the integration bridge name. // GetIntegrationBridge is a test implementation of Interface.GetIntegrationBridge.
func (os *FakeOSClient) GetIntegrationBridge() string { func (f *FakeOSClient) GetIntegrationBridge() string {
return os.IntegrationBridge return f.IntegrationBridge
} }

View File

@ -19,6 +19,7 @@ package proxy
import ( import (
"fmt" "fmt"
"strings" "strings"
"sync"
) )
const ( const (
@ -35,6 +36,7 @@ type Rule map[string]string
// FakeIPTables have noop implementation of fake iptables function. // FakeIPTables have noop implementation of fake iptables function.
type FakeIPTables struct { type FakeIPTables struct {
sync.Mutex
namespace string namespace string
NSLines map[string][]byte NSLines map[string][]byte
} }
@ -55,6 +57,8 @@ func (f *FakeIPTables) ensureRule(op, chain string, args []string) error {
} }
func (f *FakeIPTables) restoreAll(data []byte) error { func (f *FakeIPTables) restoreAll(data []byte) error {
f.Lock()
defer f.Unlock()
d := make([]byte, len(data)) d := make([]byte, len(data))
copy(d, data) copy(d, data)
f.NSLines[f.namespace] = d f.NSLines[f.namespace] = d

View File

@ -24,6 +24,7 @@ import (
"github.com/davecgh/go-spew/spew" "github.com/davecgh/go-spew/spew"
crdClient "git.openstack.org/openstack/stackube/pkg/kubecrd"
"git.openstack.org/openstack/stackube/pkg/openstack" "git.openstack.org/openstack/stackube/pkg/openstack"
"git.openstack.org/openstack/stackube/pkg/util" "git.openstack.org/openstack/stackube/pkg/util"
@ -190,10 +191,15 @@ func TestClusterNoEndpoint(t *testing.T) {
Port: "80", Port: "80",
} }
//Creates fake iptables. // Creates fake iptables.
ipt := NewFake() ipt := NewFake()
//Create a fake openstack client. // Creates fake CRD client.
osClient := openstack.NewFake() crdClient, err := crdClient.NewFake()
if err != nil {
t.Fatal("Failed init fake CRD client")
}
// Create a fake openstack client.
osClient := openstack.NewFake(crdClient)
// Injects fake network. // Injects fake network.
networkName := util.BuildNetworkName(testNamespace, testNamespace) networkName := util.BuildNetworkName(testNamespace, testNamespace)
osClient.SetNetwork(networkName, "123") osClient.SetNetwork(networkName, "123")
@ -226,7 +232,7 @@ func TestClusterNoEndpoint(t *testing.T) {
} }
} }
func noClusterIPType(svcType v1.ServiceType) []Rule { func noClusterIPType(t *testing.T, svcType v1.ServiceType) []Rule {
testNamespace := "test" testNamespace := "test"
svcIP := "1.2.3.4" svcIP := "1.2.3.4"
svcPort := 80 svcPort := 80
@ -237,8 +243,13 @@ func noClusterIPType(svcType v1.ServiceType) []Rule {
// Creates fake iptables. // Creates fake iptables.
ipt := NewFake() ipt := NewFake()
// Creates fake CRD client.
crdClient, err := crdClient.NewFake()
if err != nil {
t.Fatal("Failed init fake CRD client")
}
// Create a fake openstack client. // Create a fake openstack client.
osClient := openstack.NewFake() osClient := openstack.NewFake(crdClient)
// Injects fake network. // Injects fake network.
networkName := util.BuildNetworkName(testNamespace, testNamespace) networkName := util.BuildNetworkName(testNamespace, testNamespace)
osClient.SetNetwork(networkName, "123") osClient.SetNetwork(networkName, "123")
@ -277,7 +288,7 @@ func TestNoClusterIPType(t *testing.T) {
} }
for k, tc := range testCases { for k, tc := range testCases {
got := noClusterIPType(tc) got := noClusterIPType(t, tc)
if len(got) != 0 { if len(got) != 0 {
errorf(fmt.Sprintf("%v: unexpected rule for chain %v without ClusterIP service type", k, ChainSKPrerouting), got, t) errorf(fmt.Sprintf("%v: unexpected rule for chain %v without ClusterIP service type", k, ChainSKPrerouting), got, t)
} }
@ -295,8 +306,13 @@ func TestClusterIPEndpointsJump(t *testing.T) {
// Creates fake iptables. // Creates fake iptables.
ipt := NewFake() ipt := NewFake()
// Creates fake CRD client.
crdClient, err := crdClient.NewFake()
if err != nil {
t.Fatal("Failed init fake CRD client")
}
// Create a fake openstack client. // Create a fake openstack client.
osClient := openstack.NewFake() osClient := openstack.NewFake(crdClient)
// Injects fake network. // Injects fake network.
networkName := util.BuildNetworkName(testNamespace, testNamespace) networkName := util.BuildNetworkName(testNamespace, testNamespace)
osClient.SetNetwork(networkName, "123") osClient.SetNetwork(networkName, "123")
@ -365,8 +381,13 @@ func TestMultiNamespacesService(t *testing.T) {
// Creates fake iptables. // Creates fake iptables.
ipt := NewFake() ipt := NewFake()
// Creates fake CRD client.
crdClient, err := crdClient.NewFake()
if err != nil {
t.Fatal("Failed init fake CRD client")
}
// Create a fake openstack client. // Create a fake openstack client.
osClient := openstack.NewFake() osClient := openstack.NewFake(crdClient)
// Injects fake network. // Injects fake network.
networkName1 := util.BuildNetworkName(ns1, ns1) networkName1 := util.BuildNetworkName(ns1, ns1)
osClient.SetNetwork(networkName1, "123") osClient.SetNetwork(networkName1, "123")