k8s.io/kubernetes@v1.29.3/pkg/proxy/ipvs/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 "k8s.io/utils/net" 22 23 "k8s.io/apimachinery/pkg/util/sets" 24 ) 25 26 // FakeNetlinkHandle mock implementation of proxy NetlinkHandle 27 type FakeNetlinkHandle struct { 28 // localAddresses is a network interface name to all of its IP addresses map, e.g. 29 // eth0 -> [1.2.3.4, 10.20.30.40] 30 localAddresses map[string][]string 31 32 IsIPv6 bool 33 } 34 35 // NewFakeNetlinkHandle will create a new FakeNetlinkHandle 36 func NewFakeNetlinkHandle(isIPv6 bool) *FakeNetlinkHandle { 37 fake := &FakeNetlinkHandle{ 38 localAddresses: make(map[string][]string), 39 IsIPv6: isIPv6, 40 } 41 return fake 42 } 43 44 // EnsureAddressBind is a mock implementation 45 func (h *FakeNetlinkHandle) EnsureAddressBind(address, devName string) (exist bool, err error) { 46 if len(devName) == 0 { 47 return false, fmt.Errorf("device name can't be empty") 48 } 49 if _, ok := h.localAddresses[devName]; !ok { 50 return false, fmt.Errorf("error bind address: %s to a non-exist interface: %s", address, devName) 51 } 52 for _, addr := range h.localAddresses[devName] { 53 if addr == address { 54 // return true if the address is already bound to device 55 return true, nil 56 } 57 } 58 h.localAddresses[devName] = append(h.localAddresses[devName], address) 59 return false, nil 60 } 61 62 // UnbindAddress is a mock implementation 63 func (h *FakeNetlinkHandle) UnbindAddress(address, devName string) error { 64 if len(devName) == 0 { 65 return fmt.Errorf("device name can't be empty") 66 } 67 if _, ok := h.localAddresses[devName]; !ok { 68 return fmt.Errorf("error unbind address: %s from a non-exist interface: %s", address, devName) 69 } 70 for i, addr := range h.localAddresses[devName] { 71 if addr == address { 72 // delete address from slice h.localAddresses[devName] 73 h.localAddresses[devName] = append(h.localAddresses[devName][:i], h.localAddresses[devName][i+1:]...) 74 return nil 75 } 76 } 77 // return error message if address is not found in slice h.localAddresses[devName] 78 return fmt.Errorf("address: %s is not found in interface: %s", address, devName) 79 } 80 81 // EnsureDummyDevice is a mock implementation 82 func (h *FakeNetlinkHandle) EnsureDummyDevice(devName string) (bool, error) { 83 if len(devName) == 0 { 84 return false, fmt.Errorf("device name can't be empty") 85 } 86 if _, ok := h.localAddresses[devName]; !ok { 87 // create dummy interface if devName is not found in localAddress map 88 h.localAddresses[devName] = make([]string, 0) 89 return false, nil 90 } 91 // return true if devName is already created in localAddress map 92 return true, nil 93 } 94 95 // DeleteDummyDevice is a mock implementation 96 func (h *FakeNetlinkHandle) DeleteDummyDevice(devName string) error { 97 if len(devName) == 0 { 98 return fmt.Errorf("device name can't be empty") 99 } 100 if _, ok := h.localAddresses[devName]; !ok { 101 return fmt.Errorf("error deleting a non-exist interface: %s", devName) 102 } 103 delete(h.localAddresses, devName) 104 return nil 105 } 106 107 // ListBindAddress is a mock implementation 108 func (h *FakeNetlinkHandle) ListBindAddress(devName string) ([]string, error) { 109 if len(devName) == 0 { 110 return nil, fmt.Errorf("device name can't be empty") 111 } 112 if _, ok := h.localAddresses[devName]; !ok { 113 return nil, fmt.Errorf("error list addresses from a non-exist interface: %s", devName) 114 } 115 return h.localAddresses[devName], nil 116 } 117 118 // GetLocalAddresses is a mock implementation 119 func (h *FakeNetlinkHandle) GetLocalAddresses(dev string) (sets.Set[string], error) { 120 res := sets.New[string]() 121 // list all addresses from a given network interface. 122 for _, addr := range h.localAddresses[dev] { 123 if h.isValidForSet(addr) { 124 res.Insert(addr) 125 } 126 } 127 return res, nil 128 } 129 func (h *FakeNetlinkHandle) GetAllLocalAddresses() (sets.Set[string], error) { 130 res := sets.New[string]() 131 // List all addresses from all available network interfaces. 132 for linkName := range h.localAddresses { 133 // list all addresses from a given network interface. 134 for _, addr := range h.localAddresses[linkName] { 135 if h.isValidForSet(addr) { 136 res.Insert(addr) 137 } 138 } 139 } 140 return res, nil 141 } 142 143 func (h *FakeNetlinkHandle) GetAllLocalAddressesExcept(dev string) (sets.Set[string], error) { 144 res := sets.New[string]() 145 for linkName := range h.localAddresses { 146 if linkName == dev { 147 continue 148 } 149 for _, addr := range h.localAddresses[linkName] { 150 if h.isValidForSet(addr) { 151 res.Insert(addr) 152 } 153 } 154 } 155 return res, nil 156 } 157 158 // SetLocalAddresses set IP addresses to the given interface device. It's not part of interface. 159 func (h *FakeNetlinkHandle) SetLocalAddresses(dev string, ips ...string) error { 160 if h.localAddresses == nil { 161 h.localAddresses = make(map[string][]string) 162 } 163 if len(dev) == 0 { 164 return fmt.Errorf("device name can't be empty") 165 } 166 h.localAddresses[dev] = make([]string, 0) 167 h.localAddresses[dev] = append(h.localAddresses[dev], ips...) 168 return nil 169 } 170 171 func (h *FakeNetlinkHandle) isValidForSet(ipString string) bool { 172 ip := net.ParseIPSloppy(ipString) 173 if h.IsIPv6 != (ip.To4() == nil) { 174 return false 175 } 176 if h.IsIPv6 && ip.IsLinkLocalUnicast() { 177 return false 178 } 179 if ip.IsLoopback() { 180 return false 181 } 182 return true 183 }