github.com/webmeshproj/webmesh-cni@v0.0.27/internal/ipam/ipam.go (about) 1 /* 2 Copyright 2023 Avi Zimmerman <avi.zimmerman@gmail.com>. 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 IPAM provides IPv4 address allocation against the mesh database. 18 package ipam 19 20 import ( 21 "context" 22 "fmt" 23 "net/netip" 24 25 v1 "github.com/webmeshproj/api/go/v1" 26 meshplugins "github.com/webmeshproj/webmesh/pkg/plugins" 27 meshtypes "github.com/webmeshproj/webmesh/pkg/storage/types" 28 "k8s.io/client-go/rest" 29 ) 30 31 // Allocator is the interface for an IPAM allocator. 32 type Allocator interface { 33 // Allocate allocates an IP address for the given node ID. 34 Allocate(ctx context.Context, nodeID meshtypes.NodeID) (netip.Prefix, error) 35 // Locker returns the underlying Locker. Locks should be acquired before 36 // calls to allocate. They are provided as separate methods to ensure 37 // the caller has time to write the allocation to the DB. Allocate simply 38 // observes the current state and respond with an available address. 39 Locker() Locker 40 } 41 42 // Config is the configuration for the allocator. 43 type Config struct { 44 // IPAM is the IPAM configuration. 45 IPAM meshplugins.IPAMConfig 46 // Lock is the lock configuration. 47 Lock LockConfig 48 // Network is the IPv4 network to allocate addresses in. 49 Network netip.Prefix 50 } 51 52 var ( 53 // ErrNoNetwork is returned when no network is configured. 54 ErrNoNetwork = fmt.Errorf("no network configured") 55 // ErrNoStorage is returned when no storage is configured. 56 ErrNoStorage = fmt.Errorf("no storage configured") 57 ) 58 59 // NewAllocator creates a new IPAM allocator. The given configuration 60 // will be copied and modified. 61 func NewAllocator(cfg *rest.Config, conf Config) (Allocator, error) { 62 if conf.Network == (netip.Prefix{}) { 63 return nil, ErrNoNetwork 64 } 65 if conf.IPAM.Storage == nil { 66 return nil, ErrNoStorage 67 } 68 lock, err := NewLock(rest.CopyConfig(cfg), conf.Lock) 69 if err != nil { 70 return nil, err 71 } 72 ipam := meshplugins.NewBuiltinIPAM(conf.IPAM) 73 return &allocator{ 74 ipam: ipam, 75 lock: lock, 76 network: conf.Network, 77 }, nil 78 } 79 80 type allocator struct { 81 ipam *meshplugins.BuiltinIPAM 82 lock Locker 83 network netip.Prefix 84 } 85 86 func (a *allocator) Allocate(ctx context.Context, nodeID meshtypes.NodeID) (netip.Prefix, error) { 87 alloc, err := a.ipam.Allocate(ctx, &v1.AllocateIPRequest{ 88 NodeID: nodeID.String(), 89 Subnet: a.network.String(), 90 }) 91 if err != nil { 92 return netip.Prefix{}, err 93 } 94 return netip.ParsePrefix(alloc.GetIp()) 95 } 96 97 func (a *allocator) Locker() Locker { 98 return a.lock 99 }