mirror of
https://github.com/gravitl/netmaker.git
synced 2025-09-26 21:01:32 +08:00

* add support for egress domain routing * add domain info to egress range * fix egress domain update * send peer update domain resolution update * add egress domain update in the peer update * use range field for domain check * add egress domain to host pull * add egress domain model to egress host update * add egress domain model to egress host update * update egress domain model on acls * add check of range if domain is set * sync egress domains to dns system * add egress domain to match domain list, fix egress nat rule for domains * fix all rsrcs comms * fix static checks * fix egress acls on CE * check for all resources access on a node * simplify egress acl rules * merged ce and pro acl rule func * fix uni direction acl rule for static nodes * allow relayed nodes traffic * resolve merge conflicts * remove anywhere dst rule on user node acls * fix: broadcast user groups update for acl changes * add egress domain ans routes to nodes * add egress ranges to DST * add all egress ranges for all resources * fix DNS routing acls rules
143 lines
3.6 KiB
Go
143 lines
3.6 KiB
Go
package utils
|
|
|
|
import (
|
|
"fmt"
|
|
"log/slog"
|
|
"net"
|
|
"runtime"
|
|
"sort"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/gravitl/netmaker/models"
|
|
)
|
|
|
|
// RetryStrategy specifies a strategy to retry an operation after waiting a while,
|
|
// with hooks for successful and unsuccessful (>=max) tries.
|
|
type RetryStrategy struct {
|
|
Wait func(time.Duration)
|
|
WaitTime time.Duration
|
|
WaitTimeIncrease time.Duration
|
|
MaxTries int
|
|
Try func() error
|
|
OnMaxTries func()
|
|
OnSuccess func()
|
|
}
|
|
|
|
// DoStrategy does the retry strategy specified in the struct, waiting before retrying an operator,
|
|
// up to a max number of tries, and if executes a success "finalizer" operation if a retry is successful
|
|
func (rs RetryStrategy) DoStrategy() {
|
|
err := rs.Try()
|
|
if err == nil {
|
|
rs.OnSuccess()
|
|
return
|
|
}
|
|
|
|
tries := 1
|
|
for {
|
|
if tries >= rs.MaxTries {
|
|
rs.OnMaxTries()
|
|
return
|
|
}
|
|
rs.Wait(rs.WaitTime)
|
|
if err := rs.Try(); err != nil {
|
|
tries++ // we tried, increase count
|
|
rs.WaitTime += rs.WaitTimeIncrease // for the next time, sleep more
|
|
continue // retry
|
|
}
|
|
rs.OnSuccess()
|
|
return
|
|
}
|
|
}
|
|
|
|
func TraceCaller() {
|
|
// Skip 1 frame to get the caller of this function
|
|
pc, file, line, ok := runtime.Caller(2)
|
|
if !ok {
|
|
slog.Debug("Unable to get caller information")
|
|
return
|
|
}
|
|
|
|
// Get function name from the program counter (pc)
|
|
funcName := runtime.FuncForPC(pc).Name()
|
|
|
|
// Print trace details
|
|
slog.Debug("Called from function: %s\n", "func", funcName)
|
|
slog.Debug("File: %s, Line: %d\n", "file", file, "line", line)
|
|
}
|
|
|
|
// NoEmptyStringToCsv takes a bunch of strings, filters out empty ones and returns a csv version of the string
|
|
func NoEmptyStringToCsv(strs ...string) string {
|
|
var sb strings.Builder
|
|
for _, str := range strs {
|
|
trimmedStr := strings.TrimSpace(str)
|
|
if trimmedStr != "" && trimmedStr != "<nil>" {
|
|
if sb.Len() > 0 {
|
|
sb.WriteString(", ")
|
|
}
|
|
sb.WriteString(str)
|
|
}
|
|
}
|
|
return sb.String()
|
|
}
|
|
|
|
// GetExtClientEndpoint returns the external client endpoint in the format "host:port" or "[host]:port" for IPv6
|
|
func GetExtClientEndpoint(hostIpv4Endpoint, hostIpv6Endpoint net.IP, hostListenPort int) string {
|
|
if hostIpv4Endpoint.To4() == nil {
|
|
return fmt.Sprintf("[%s]:%d", hostIpv6Endpoint.String(), hostListenPort)
|
|
} else {
|
|
return fmt.Sprintf("%s:%d", hostIpv4Endpoint.String(), hostListenPort)
|
|
}
|
|
}
|
|
|
|
// SortIfacesByName sorts a slice of Iface by name in ascending order
|
|
func SortIfacesByName(ifaces []models.Iface) {
|
|
sort.Slice(ifaces, func(i, j int) bool {
|
|
return ifaces[i].Name < ifaces[j].Name
|
|
})
|
|
}
|
|
|
|
// CompareIfaces compares two slices of Iface and returns true if they are equal
|
|
// Two slices are considered equal if they have the same length and all corresponding
|
|
// elements have the same Name, AddressString, and IP address
|
|
func CompareIfaces(ifaces1, ifaces2 []models.Iface) bool {
|
|
// Check if lengths are different
|
|
if len(ifaces1) != len(ifaces2) {
|
|
return false
|
|
}
|
|
|
|
// Compare each element
|
|
for i := range ifaces1 {
|
|
if !CompareIface(ifaces1[i], ifaces2[i]) {
|
|
return false
|
|
}
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
// CompareIface compares two individual Iface structs and returns true if they are equal
|
|
func CompareIface(iface1, iface2 models.Iface) bool {
|
|
// Compare Name
|
|
if iface1.Name != iface2.Name {
|
|
return false
|
|
}
|
|
|
|
// Compare AddressString
|
|
if iface1.AddressString != iface2.AddressString {
|
|
return false
|
|
}
|
|
|
|
// Compare IP addresses
|
|
if !iface1.Address.IP.Equal(iface2.Address.IP) {
|
|
return false
|
|
}
|
|
|
|
// Compare network masks
|
|
if iface1.Address.Mask.String() != iface2.Address.Mask.String() {
|
|
return false
|
|
}
|
|
|
|
return true
|
|
}
|