stackube/pkg/openstack/openstack_fake.go
mozhuli 1f950f63f0 Add fake files
including
* add fake openstack client framework.
* add fake iptables.
* add proxier unit tests.

Change-Id: I8e47ecd33a103ac736e0619e35cfe59cca8ef2e2
Implements: blueprint enhance-unit-testing
Signed-off-by: mozhuli <21621232@zju.edu.cn>
2017-08-22 21:47:33 +08:00

401 lines
10 KiB
Go

/*
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 openstack
import (
"crypto/sha1"
"errors"
"fmt"
"io"
crv1 "git.openstack.org/openstack/stackube/pkg/apis/v1"
crdClient "git.openstack.org/openstack/stackube/pkg/kubecrd"
drivertypes "git.openstack.org/openstack/stackube/pkg/openstack/types"
"git.openstack.org/openstack/stackube/pkg/util"
"github.com/gophercloud/gophercloud/openstack/identity/v2/tenants"
"github.com/gophercloud/gophercloud/openstack/identity/v2/users"
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/routers"
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/portsbinding"
"github.com/gophercloud/gophercloud/openstack/networking/v2/ports"
"github.com/gophercloud/gophercloud/openstack/networking/v2/subnets"
)
var ErrAlreadyExist = errors.New("AlreadyExist")
// FakeOSClient is a simple fake openstack client, so that stackube
// can be run for testing without requiring a real openstack setup.
type FakeOSClient struct {
Tenants map[string]*tenants.Tenant
Users map[string]*users.User
Networks map[string]*drivertypes.Network
Subnets map[string]*subnets.Subnet
Routers map[string]*routers.Router
Ports map[string][]ports.Port
// TODO(mozhuli): Add fakeCRDClient.
CRDClient *crdClient.CRDClient
PluginName string
IntegrationBridge string
}
var _ = Interface(&FakeOSClient{})
// NewFake creates a new FakeOSClient.
func NewFake() *FakeOSClient {
return &FakeOSClient{
Tenants: make(map[string]*tenants.Tenant),
Users: make(map[string]*users.User),
Networks: make(map[string]*drivertypes.Network),
Subnets: make(map[string]*subnets.Subnet),
Routers: make(map[string]*routers.Router),
Ports: make(map[string][]ports.Port),
PluginName: "ovs",
IntegrationBridge: "bi-int",
}
}
// SetTenant injects fake tenant.
func (os *FakeOSClient) SetTenant(tenantName, tenantID string) {
tenant := &tenants.Tenant{
Name: tenantName,
ID: tenantID,
}
os.Tenants[tenantName] = tenant
}
// SetUser injects fake user.
func (os *FakeOSClient) SetUser(userName, userID, tenantID string) {
user := &users.User{
Username: userName,
ID: userID,
TenantID: tenantID,
}
os.Users[tenantID] = user
}
// SetNetwork injects fake network.
func (os *FakeOSClient) SetNetwork(networkName, networkID string) {
network := &drivertypes.Network{
Name: networkName,
Uid: networkID,
}
os.Networks[networkName] = network
}
// SetPort injects fake port.
func (os *FakeOSClient) SetPort(networkID, deviceOwner, deviceID string) {
netPorts, ok := os.Ports[networkID]
p := ports.Port{
NetworkID: networkID,
DeviceOwner: deviceOwner,
DeviceID: deviceID,
}
if !ok {
var ps []ports.Port
ps = append(ps, p)
os.Ports[networkID] = ps
}
netPorts = append(netPorts, p)
os.Ports[networkID] = netPorts
}
func tenantIDHash(tenantName string) string {
return idHash(tenantName)
}
func userIDHash(userName, tenantID string) string {
return idHash(userName)
}
func networkIDHash(networkName string) string {
return idHash(networkName)
}
func subnetIDHash(subnetName string) string {
return idHash(subnetName)
}
func routerIDHash(routerName string) string {
return idHash(routerName)
}
func portdeviceIDHash(networkID, deviceOwner string) string {
return idHash(networkID, deviceOwner)
}
func idHash(data ...string) string {
var s string
for _, d := range data {
s += d
}
h := sha1.New()
io.WriteString(h, s)
return fmt.Sprintf("%x", h.Sum(nil))[:16]
}
// CreateTenant creates tenant by tenantname.
func (os *FakeOSClient) CreateTenant(tenantName string) (string, error) {
if t, ok := os.Tenants[tenantName]; ok {
return t.ID, nil
}
tenant := &tenants.Tenant{
Name: tenantName,
ID: tenantIDHash(tenantName),
}
os.Tenants[tenantName] = tenant
return tenant.ID, nil
}
// DeleteTenant deletes tenant by tenantName.
func (os *FakeOSClient) DeleteTenant(tenantName string) error {
delete(os.Tenants, tenantName)
return nil
}
// GetTenantIDFromName gets tenantID by tenantName.
func (os *FakeOSClient) GetTenantIDFromName(tenantName string) (string, error) {
if util.IsSystemNamespace(tenantName) {
tenantName = util.SystemTenant
}
// If tenantID is specified, return it directly
var (
tenant *crv1.Tenant
err error
)
// TODO(mozhuli): use fakeCRDClient.
if tenant, err = os.CRDClient.GetTenant(tenantName); err != nil {
return "", err
}
if tenant.Spec.TenantID != "" {
return tenant.Spec.TenantID, nil
}
t, ok := os.Tenants[tenantName]
if !ok {
return "", nil
}
return t.ID, nil
}
// CheckTenantByID checks tenant exist or not by tenantID.
func (os *FakeOSClient) CheckTenantByID(tenantID string) (bool, error) {
for _, tenent := range os.Tenants {
if tenent.ID == tenantID {
return true, nil
}
}
return false, ErrNotFound
}
// CreateUser creates user with username, password in the tenant.
func (os *FakeOSClient) CreateUser(username, password, tenantID string) error {
user := &users.User{
Name: username,
TenantID: tenantID,
ID: userIDHash(username, tenantID),
}
os.Users[tenantID] = user
return nil
}
// DeleteAllUsersOnTenant deletes all users on the tenant.
func (os *FakeOSClient) DeleteAllUsersOnTenant(tenantName string) error {
tenant := os.Tenants[tenantName]
delete(os.Users, tenant.ID)
return nil
}
func (os *FakeOSClient) createNetwork(networkName, tenantID string) error {
if _, ok := os.Networks[networkName]; ok {
return ErrAlreadyExist
}
network := &drivertypes.Network{
Name: networkName,
Uid: networkIDHash(networkName),
TenantID: tenantID,
}
os.Networks[networkName] = network
return nil
}
func (os *FakeOSClient) deleteNetwork(networkName string) error {
delete(os.Networks, networkName)
return nil
}
func (os *FakeOSClient) createRouter(routerName, tenantID string) error {
if _, ok := os.Routers[routerName]; ok {
return ErrAlreadyExist
}
router := &routers.Router{
Name: routerName,
TenantID: tenantID,
ID: routerIDHash(routerName),
}
os.Routers[routerName] = router
return nil
}
func (os *FakeOSClient) deleteRouter(routerName string) error {
delete(os.Routers, routerName)
return nil
}
func (os *FakeOSClient) createSubnet(subnetName, networkID, tenantID string) error {
if _, ok := os.Subnets[subnetName]; ok {
return ErrAlreadyExist
}
subnet := &subnets.Subnet{
Name: subnetName,
TenantID: tenantID,
NetworkID: networkID,
ID: subnetIDHash(subnetName),
}
os.Subnets[subnetName] = subnet
return nil
}
// CreateNetwork creates network.
// TODO(mozhuli): make it more general.
func (os *FakeOSClient) CreateNetwork(network *drivertypes.Network) error {
if len(network.Subnets) == 0 {
return errors.New("Subnets is null")
}
// create network
err := os.createNetwork(network.Name, network.TenantID)
if err != nil {
return errors.New("Create network failed")
}
// create router, and use network name as router name for convenience.
err = os.createRouter(network.Name, network.TenantID)
if err != nil {
os.deleteNetwork(network.Name)
return errors.New("Create router failed")
}
// create subnets and connect them to router
err = os.createSubnet(network.Subnets[0].Name, network.Uid, network.TenantID)
if err != nil {
os.deleteRouter(network.Name)
os.deleteNetwork(network.Name)
return errors.New("Create subnet failed")
}
return nil
}
// GetNetworkByID gets network by networkID.
func (os *FakeOSClient) GetNetworkByID(networkID string) (*drivertypes.Network, error) {
return nil, nil
}
// GetNetworkByName get network by networkName
func (os *FakeOSClient) GetNetworkByName(networkName string) (*drivertypes.Network, error) {
network, ok := os.Networks[networkName]
if !ok {
return nil, ErrNotFound
}
return network, nil
}
// DeleteNetwork deletes network by networkName.
func (os *FakeOSClient) DeleteNetwork(networkName string) error {
return nil
}
// GetProviderSubnet gets provider subnet by id
func (os *FakeOSClient) GetProviderSubnet(osSubnetID string) (*drivertypes.Subnet, error) {
return nil, nil
}
// CreatePort creates port by neworkID, tenantID and portName.
func (os *FakeOSClient) CreatePort(networkID, tenantID, portName string) (*portsbinding.Port, error) {
return nil, nil
}
// GetPort gets port by portName.
func (os *FakeOSClient) GetPort(name string) (*ports.Port, error) {
return nil, nil
}
// ListPorts list all ports which have the deviceOwner in the network.
func (os *FakeOSClient) ListPorts(networkID, deviceOwner string) ([]ports.Port, error) {
var results []ports.Port
portList, ok := os.Ports[networkID]
if !ok {
return results, nil
}
for _, port := range portList {
if port.DeviceOwner == deviceOwner {
results = append(results, port)
}
}
return results, nil
}
// DeletePortByName deletes port by portName.
func (os *FakeOSClient) DeletePortByName(portName string) error {
return nil
}
// DeletePortByID deletes port by portID.
func (os *FakeOSClient) DeletePortByID(portID string) error {
return nil
}
// UpdatePortsBinding updates port binding.
func (os *FakeOSClient) UpdatePortsBinding(portID, deviceOwner string) error {
return nil
}
// LoadBalancerExist returns whether a load balancer has already been exist.
func (os *FakeOSClient) LoadBalancerExist(name string) (bool, error) {
return true, nil
}
// EnsureLoadBalancer ensures a load balancer is created.
func (os *FakeOSClient) EnsureLoadBalancer(lb *LoadBalancer) (*LoadBalancerStatus, error) {
return nil, nil
}
// EnsureLoadBalancerDeleted ensures a load balancer is deleted.
func (os *FakeOSClient) EnsureLoadBalancerDeleted(name string) error {
return nil
}
// GetCRDClient returns the CRDClient.
// TODO(mozhuli): use fakeCRDClient.
func (os *FakeOSClient) GetCRDClient() *crdClient.CRDClient {
return os.CRDClient
}
// GetPluginName returns the plugin name.
func (os *FakeOSClient) GetPluginName() string {
return os.PluginName
}
// GetIntegrationBridge returns the integration bridge name.
func (os *FakeOSClient) GetIntegrationBridge() string {
return os.IntegrationBridge
}