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  }