k8s.io/kubernetes@v1.29.3/pkg/proxy/ipvs/util/testing/fake.go (about)

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