k8s.io/kubernetes@v1.31.0-alpha.0.0.20240520171757-56147500dadc/pkg/proxy/ipvs/util/testing/fake.go (about) 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{})