...

Source file src/k8s.io/kubernetes/pkg/proxy/ipvs/util/testing/fake.go

Documentation: k8s.io/kubernetes/pkg/proxy/ipvs/util/testing

     1  //go:build linux
     2  // +build linux
     3  
     4  /*
     5  Copyright 2017 The Kubernetes Authors.
     6  
     7  Licensed under the Apache License, Version 2.0 (the "License");
     8  you may not use this file except in compliance with the License.
     9  You may obtain a copy of the License at
    10  
    11      http://www.apache.org/licenses/LICENSE-2.0
    12  
    13  Unless required by applicable law or agreed to in writing, software
    14  distributed under the License is distributed on an "AS IS" BASIS,
    15  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    16  See the License for the specific language governing permissions and
    17  limitations under the License.
    18  */
    19  
    20  package testing
    21  
    22  import (
    23  	"fmt"
    24  	"net"
    25  	"sort"
    26  	"strconv"
    27  	"time"
    28  
    29  	utilipvs "k8s.io/kubernetes/pkg/proxy/ipvs/util"
    30  )
    31  
    32  // FakeIPVS no-op implementation of ipvs Interface
    33  type FakeIPVS struct {
    34  	Scheduler    string
    35  	Services     map[ServiceKey]*utilipvs.VirtualServer
    36  	Destinations map[ServiceKey][]*utilipvs.RealServer
    37  }
    38  
    39  // ServiceKey uniquely identifies a Service for an IPVS virtual server
    40  type ServiceKey struct {
    41  	IP       string
    42  	Port     uint16
    43  	Protocol string
    44  }
    45  
    46  func (s *ServiceKey) String() string {
    47  	return fmt.Sprintf("%s:%d/%s", s.IP, s.Port, s.Protocol)
    48  }
    49  
    50  // RealServerKey uniquely identifies an Endpoint for an IPVS real server
    51  type RealServerKey struct {
    52  	Address net.IP
    53  	Port    uint16
    54  }
    55  
    56  func (r *RealServerKey) String() string {
    57  	return net.JoinHostPort(r.Address.String(), strconv.Itoa(int(r.Port)))
    58  }
    59  
    60  // Implement https://pkg.go.dev/sort#Interface
    61  type byAddress []*utilipvs.RealServer
    62  
    63  func (a byAddress) Len() int {
    64  	return len(a)
    65  }
    66  func (a byAddress) Less(i, j int) bool {
    67  	return a[i].String() < a[j].String()
    68  }
    69  func (a byAddress) Swap(i, j int) {
    70  	a[i], a[j] = a[j], a[i]
    71  }
    72  
    73  // NewFake creates a fake ipvs implementation - a cache store.
    74  func NewFake() *FakeIPVS {
    75  	return &FakeIPVS{
    76  		Services:     make(map[ServiceKey]*utilipvs.VirtualServer),
    77  		Destinations: make(map[ServiceKey][]*utilipvs.RealServer),
    78  	}
    79  }
    80  
    81  func toServiceKey(serv *utilipvs.VirtualServer) ServiceKey {
    82  	return ServiceKey{
    83  		IP:       serv.Address.String(),
    84  		Port:     serv.Port,
    85  		Protocol: serv.Protocol,
    86  	}
    87  }
    88  
    89  func toRealServerKey(rs *utilipvs.RealServer) *RealServerKey {
    90  	return &RealServerKey{
    91  		Address: rs.Address,
    92  		Port:    rs.Port,
    93  	}
    94  }
    95  
    96  // AddVirtualServer is a fake implementation, it simply adds the VirtualServer into the cache store.
    97  func (f *FakeIPVS) AddVirtualServer(serv *utilipvs.VirtualServer) error {
    98  	if serv == nil {
    99  		return fmt.Errorf("failed to add virtual server, error: virtual server can't be nil")
   100  	}
   101  	key := toServiceKey(serv)
   102  	f.Services[key] = serv
   103  	// make sure no destination present when creating new service
   104  	f.Destinations[key] = make([]*utilipvs.RealServer, 0)
   105  	return nil
   106  }
   107  
   108  // UpdateVirtualServer is a fake implementation, it updates the VirtualServer in the cache store.
   109  func (f *FakeIPVS) UpdateVirtualServer(serv *utilipvs.VirtualServer) error {
   110  	if serv == nil {
   111  		return fmt.Errorf("failed to update service, service can't be nil")
   112  	}
   113  	key := toServiceKey(serv)
   114  	f.Services[key] = serv
   115  	return nil
   116  }
   117  
   118  // DeleteVirtualServer is a fake implementation, it simply deletes the VirtualServer from the cache store.
   119  func (f *FakeIPVS) DeleteVirtualServer(serv *utilipvs.VirtualServer) error {
   120  	if serv == nil {
   121  		return fmt.Errorf("failed to delete service: service can't be nil")
   122  	}
   123  	key := toServiceKey(serv)
   124  	delete(f.Services, key)
   125  	// clear specific destinations as well
   126  	f.Destinations[key] = nil
   127  	return nil
   128  }
   129  
   130  // GetVirtualServer is a fake implementation, it tries to find a specific VirtualServer from the cache store.
   131  func (f *FakeIPVS) GetVirtualServer(serv *utilipvs.VirtualServer) (*utilipvs.VirtualServer, error) {
   132  	if serv == nil {
   133  		return nil, fmt.Errorf("failed to get service: service can't be nil")
   134  	}
   135  	key := toServiceKey(serv)
   136  	svc, found := f.Services[key]
   137  	if found {
   138  		return svc, nil
   139  	}
   140  	return nil, fmt.Errorf("not found serv: %v", key.String())
   141  }
   142  
   143  // GetVirtualServers is a fake implementation, it simply returns all VirtualServers in the cache store.
   144  func (f *FakeIPVS) GetVirtualServers() ([]*utilipvs.VirtualServer, error) {
   145  	res := make([]*utilipvs.VirtualServer, 0)
   146  	for _, svc := range f.Services {
   147  		res = append(res, svc)
   148  	}
   149  	return res, nil
   150  }
   151  
   152  // Flush is a fake implementation, it simply clears the cache store.
   153  func (f *FakeIPVS) Flush() error {
   154  	// directly drop old data
   155  	f.Services = nil
   156  	f.Destinations = nil
   157  	return nil
   158  }
   159  
   160  // AddRealServer is a fake implementation, it simply creates a RealServer for a VirtualServer in the cache store.
   161  func (f *FakeIPVS) AddRealServer(serv *utilipvs.VirtualServer, dest *utilipvs.RealServer) error {
   162  	if serv == nil || dest == nil {
   163  		return fmt.Errorf("failed to add destination for service, neither service nor destination shouldn't be nil")
   164  	}
   165  	key := toServiceKey(serv)
   166  	if _, ok := f.Services[key]; !ok {
   167  		return fmt.Errorf("failed to add destination for service %v, service not found", key.String())
   168  	}
   169  	dests := f.Destinations[key]
   170  	if dests == nil {
   171  		dests = make([]*utilipvs.RealServer, 0)
   172  		f.Destinations[key] = dests
   173  	}
   174  	f.Destinations[key] = append(f.Destinations[key], dest)
   175  	// The tests assumes that the slice is sorted
   176  	sort.Sort(byAddress(f.Destinations[key]))
   177  	return nil
   178  }
   179  
   180  // GetRealServers is a fake implementation, it simply returns all RealServers in the cache store.
   181  func (f *FakeIPVS) GetRealServers(serv *utilipvs.VirtualServer) ([]*utilipvs.RealServer, error) {
   182  	if serv == nil {
   183  		return nil, fmt.Errorf("failed to get destination for nil service")
   184  	}
   185  	key := toServiceKey(serv)
   186  	if _, ok := f.Services[key]; !ok {
   187  		return nil, fmt.Errorf("failed to get destinations for service %v, service not found", key.String())
   188  	}
   189  	return f.Destinations[key], nil
   190  }
   191  
   192  // DeleteRealServer is a fake implementation, it deletes the real server in the cache store.
   193  func (f *FakeIPVS) DeleteRealServer(serv *utilipvs.VirtualServer, dest *utilipvs.RealServer) error {
   194  	if serv == nil || dest == nil {
   195  		return fmt.Errorf("failed to delete destination, neither service nor destination can't be nil")
   196  	}
   197  	key := toServiceKey(serv)
   198  	if _, ok := f.Services[key]; !ok {
   199  		return fmt.Errorf("failed to delete destination for service %v, service not found", key.String())
   200  	}
   201  	dests := f.Destinations[key]
   202  	exist := false
   203  	for i := range dests {
   204  		if toRealServerKey(dests[i]).String() == toRealServerKey(dest).String() {
   205  			// Delete one element
   206  			f.Destinations[key] = append(f.Destinations[key][:i], f.Destinations[key][i+1:]...)
   207  			exist = true
   208  			break
   209  		}
   210  	}
   211  	// Not Found
   212  	if !exist {
   213  		return fmt.Errorf("failed to delete real server for service %v, real server not found", key.String())
   214  	}
   215  	return nil
   216  }
   217  
   218  // UpdateRealServer is a fake implementation, it deletes the old real server then add new real server
   219  func (f *FakeIPVS) UpdateRealServer(serv *utilipvs.VirtualServer, dest *utilipvs.RealServer) error {
   220  	err := f.DeleteRealServer(serv, dest)
   221  	if err != nil {
   222  		return err
   223  	}
   224  	return f.AddRealServer(serv, dest)
   225  }
   226  
   227  // ConfigureTimeouts is not supported for fake IPVS
   228  func (f *FakeIPVS) ConfigureTimeouts(time.Duration, time.Duration, time.Duration) error {
   229  	return fmt.Errorf("not supported in fake IPVS")
   230  }
   231  
   232  var _ = utilipvs.Interface(&FakeIPVS{})
   233  

View as plain text