diff --git a/cmd/internal/core/reconfigure-switch.go b/cmd/internal/core/reconfigure-switch.go index b7a74fd6..e03c020d 100644 --- a/cmd/internal/core/reconfigure-switch.go +++ b/cmd/internal/core/reconfigure-switch.go @@ -17,6 +17,7 @@ import ( "github.com/metal-stack/metal-core/cmd/internal/vlan" sw "github.com/metal-stack/metal-go/api/client/switch_operations" "github.com/metal-stack/metal-go/api/models" + "github.com/metal-stack/metal-lib/pkg/pointer" ) // ConstantlyReconfigureSwitch reconfigures the switch. @@ -162,20 +163,22 @@ func (c *Core) buildSwitcherConfig(s *models.V1SwitchResponse) (*types.Conf, err Unprovisioned: []string{}, Vrfs: map[string]*types.Vrf{}, Firewalls: map[string]*types.Firewall{}, - DownPorts: map[string]bool{}, + AdminStatus: map[string]types.PortStatus{}, } for _, nic := range s.Nics { - port := *nic.Name + if nic == nil { + continue + } + port := pointer.SafeDeref(nic.Name) if slices.Contains(p.Underlay, port) { continue } - if isPortStatusEqual(models.V1SwitchNicActualDOWN, nic.Actual) { - if has := p.DownPorts[port]; !has { - p.DownPorts[port] = true - } + adminStatus := types.PortStatus(strings.ToLower(nic.AdminStatus)) + if adminStatus == types.PortStatusDown || adminStatus == types.PortStatusUp { + p.AdminStatus[port] = types.PortStatus(adminStatus) } if slices.Contains(c.additionalBridgePorts, port) { @@ -275,19 +278,10 @@ func fillEth0Info(c *types.Conf, gw string) error { return nil } -// isLinkUp checks if the interface with the given name is up. -// It returns a boolean indicating if the interface is up, and an error if there was a problem checking the interface. func isLinkUp(nicname string) (bool, error) { nic, err := net.InterfaceByName(nicname) if err != nil { return false, fmt.Errorf("cannot query interface %q : %w", nicname, err) } - return nic.Flags&net.FlagUp != 0, nil -} - -func isPortStatusEqual(stat string, other *string) bool { - if other == nil { - return false - } - return strings.EqualFold(stat, *other) + return nic.Flags&net.FlagRunning != 0, nil } diff --git a/cmd/internal/core/reconfigure-switch_test.go b/cmd/internal/core/reconfigure-switch_test.go index 30ada4b7..2ded589e 100644 --- a/cmd/internal/core/reconfigure-switch_test.go +++ b/cmd/internal/core/reconfigure-switch_test.go @@ -63,7 +63,7 @@ func TestBuildSwitcherConfig(t *testing.T) { MetalCoreCIDR: "10.255.255.2/24", ASN: 420000001, Ports: types.Ports{ - DownPorts: map[string]bool{}, + AdminStatus: map[string]types.PortStatus{}, Underlay: []string{"swp31", "swp32"}, Unprovisioned: []string{"swp1"}, Firewalls: map[string]*types.Firewall{ diff --git a/cmd/internal/switcher/sonic/db/configdb.go b/cmd/internal/switcher/sonic/db/configdb.go index 9a47db2f..c6f9452d 100644 --- a/cmd/internal/switcher/sonic/db/configdb.go +++ b/cmd/internal/switcher/sonic/db/configdb.go @@ -4,13 +4,12 @@ import ( "context" "fmt" + "github.com/metal-stack/metal-core/cmd/internal/switcher/types" "github.com/valkey-io/valkey-go" ) const ( - adminStatus = "admin_status" - adminStatusUp = "up" - adminStatusDown = "down" + adminStatusField = "admin_status" alias = "alias" enable = "enable" interfaceTable = "INTERFACE" @@ -35,7 +34,7 @@ type ConfigDB struct { type Port struct { Name string Alias string - AdminStatus bool + AdminStatus string Mtu string } @@ -303,7 +302,7 @@ func (d *ConfigDB) GetPort(ctx context.Context, interfaceName string) (*Port, er return &Port{ Name: interfaceName, Alias: result[alias], - AdminStatus: result[adminStatus] == adminStatusUp, + AdminStatus: result[adminStatusField], Mtu: result[mtu], }, nil } @@ -333,7 +332,7 @@ func (d *ConfigDB) GetPorts(ctx context.Context) ([]*Port, error) { ports = append(ports, &Port{ Name: p, Alias: result[alias], - AdminStatus: result[adminStatus] == adminStatusUp, + AdminStatus: result[adminStatusField], Mtu: result[mtu], }) } @@ -347,12 +346,21 @@ func (d *ConfigDB) SetPortMtu(ctx context.Context, interfaceName string, val str return d.c.HSet(ctx, key, Val{mtu: val}) } -func (d *ConfigDB) SetAdminStatusUp(ctx context.Context, interfaceName string, up bool) error { +func (d *ConfigDB) GetAdminStatus(ctx context.Context, interfaceName string) (types.PortStatus, error) { key := Key{portTable, interfaceName} - status := adminStatusUp - if !up { - status = adminStatusDown + status, err := d.c.HGet(ctx, key, adminStatusField) + if err != nil { + return "", err } - return d.c.HSet(ctx, key, Val{adminStatus: status}) + + return types.PortStatus(status), nil +} + +func (d *ConfigDB) SetAdminStatus(ctx context.Context, interfaceName string, adminStatus types.PortStatus) error { + if adminStatus != types.PortStatusDown && adminStatus != types.PortStatusUp { + return fmt.Errorf("unknown admin status %s", adminStatus) + } + key := Key{portTable, interfaceName} + return d.c.HSet(ctx, key, Val{adminStatusField: string(adminStatus)}) } diff --git a/cmd/internal/switcher/sonic/db/configdb_test.go b/cmd/internal/switcher/sonic/db/configdb_test.go index 60241a4c..be38aa0a 100644 --- a/cmd/internal/switcher/sonic/db/configdb_test.go +++ b/cmd/internal/switcher/sonic/db/configdb_test.go @@ -7,6 +7,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/metal-stack/metal-core/cmd/internal/switcher/sonic/db/test" + "github.com/metal-stack/metal-core/cmd/internal/switcher/types" "github.com/stretchr/testify/require" ) @@ -891,6 +892,7 @@ func TestConfigDB_GetVrfs(t *testing.T) { c: c, } got, err := d.GetVrfs(ctx) + slices.Sort(got) require.NoError(t, err) if diff := cmp.Diff(tt.want, got); diff != "" { t.Errorf("ConfigDB.GetVrfs() diff = %s", diff) @@ -1651,7 +1653,7 @@ func TestConfigDB_GetPort(t *testing.T) { want: &Port{ Name: "Ethernet1", Alias: "Eth1/2", - AdminStatus: true, + AdminStatus: string(types.PortStatusUp), Mtu: "9000", }, }, @@ -1697,13 +1699,13 @@ func TestConfigDB_GetPorts(t *testing.T) { { Name: "Ethernet0", Alias: "Eth1/1", - AdminStatus: true, + AdminStatus: string(types.PortStatusUp), Mtu: "9216", }, { Name: "Ethernet1", Alias: "Eth1/2", - AdminStatus: true, + AdminStatus: string(types.PortStatusUp), Mtu: "9000", }, }, @@ -1816,14 +1818,15 @@ func TestConfigDB_SetAdminStatusUp(t *testing.T) { name string data test.StringMap interfaceName string - up bool + status types.PortStatus mods func(test.HashMap) + wantErr bool }{ { name: "set on non-existing", data: configDBTestData, interfaceName: "Ethernet2", - up: false, + status: types.PortStatusDown, mods: func(data test.HashMap) { data["PORT|Ethernet2"] = map[string]string{ "admin_status": "down", @@ -1834,18 +1837,25 @@ func TestConfigDB_SetAdminStatusUp(t *testing.T) { name: "set same as existing", data: configDBTestData, interfaceName: "Ethernet1", - up: true, + status: types.PortStatusUp, mods: func(data test.HashMap) {}, }, { name: "change existing", data: configDBTestData, interfaceName: "Ethernet1", - up: false, + status: types.PortStatusDown, mods: func(data test.HashMap) { data["PORT|Ethernet1"]["admin_status"] = "down" }, }, + { + name: "invalid input", + data: configDBTestData, + interfaceName: "Ethernet1", + status: "unknown", + wantErr: true, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -1871,8 +1881,10 @@ func TestConfigDB_SetAdminStatusUp(t *testing.T) { d := &ConfigDB{ c: c, } - err = d.SetAdminStatusUp(ctx, tt.interfaceName, tt.up) - require.NoError(t, err) + err = d.SetAdminStatus(ctx, tt.interfaceName, tt.status) + if (err != nil) != tt.wantErr { + t.Errorf("ConfigDB.SetAdminStatusUp() err = %v, want err %v", err, tt.wantErr) + } data, err := test.GetData(ctx, vc, sep) require.NoError(t, err) if diff := cmp.Diff(initData, data); diff != "" { @@ -1881,3 +1893,76 @@ func TestConfigDB_SetAdminStatusUp(t *testing.T) { }) } } + +func TestConfigDB_GetAdminStatus(t *testing.T) { + data := test.StringMap{ + "PORT": test.StringMap{ + "Ethernet0": test.StringMap{ + "admin_status": "up", + "alias": "Eth1/1", + "mtu": "9216", + }, + "Ethernet1": test.StringMap{ + "alias": "Eth1/2", + "mtu": "9000", + }, + "Ethernet2": test.StringMap{ + "admin_status": "down", + "alias": "Eth1/3", + "mtu": "9000", + }, + }, + } + + tests := []struct { + name string + data test.StringMap + interfaceName string + want types.PortStatus + }{ + { + name: "interface is up", + data: data, + interfaceName: "Ethernet0", + want: types.PortStatusUp, + }, + { + name: "interface is down", + data: data, + interfaceName: "Ethernet2", + want: types.PortStatusDown, + }, + { + name: "no admin_status defined", + data: data, + interfaceName: "Ethernet1", + want: "", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + var ( + ctx = t.Context() + sep = "|" + vc = test.StartValkey(t) + ) + defer vc.Close() + + err := test.LoadData(ctx, vc, tt.data, sep) + require.NoError(t, err) + + c := &Client{ + rdb: vc, + sep: sep, + } + d := &ConfigDB{ + c: c, + } + got, err := d.GetAdminStatus(ctx, tt.interfaceName) + require.NoError(t, err) + if got != tt.want { + t.Errorf("ConfigDB.GetAdminStatus() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/cmd/internal/switcher/sonic/redis/applier.go b/cmd/internal/switcher/sonic/redis/applier.go index 672510ab..a391e53a 100644 --- a/cmd/internal/switcher/sonic/redis/applier.go +++ b/cmd/internal/switcher/sonic/redis/applier.go @@ -32,16 +32,34 @@ func NewApplier(log *slog.Logger, db *db.DB) *Applier { } func (a *Applier) Apply(ctx context.Context, cfg *types.Conf) error { - var errs []error + var ( + errs []error + changed bool + ) - // only process if changes are detected if a.previousCfg != nil { diff := cmp.Diff(a.previousCfg, cfg) - if diff == "" { - a.log.Info("no changes on interfaces detected, nothing to do") - return nil + if diff != "" { + changed = true + a.log.Debug("interface changes", "changes", diff) } - a.log.Debug("interface changes", "changes", diff) + } + + currentPorts, err := a.db.Config.GetPorts(ctx) + if err != nil { + return fmt.Errorf("failed to apply config: %w", err) + } + + for _, port := range currentPorts { + if types.PortStatus(port.AdminStatus) != cfg.Ports.AdminStatus[port.Name] { + changed = true + break + } + } + + if !changed { + a.log.Info("no changes on interfaces detected, nothing to do") + return nil } if err := a.refreshOidMaps(ctx); err != nil { @@ -50,7 +68,7 @@ func (a *Applier) Apply(ctx context.Context, cfg *types.Conf) error { a.log.Debug("configure underlay ports", "ports", cfg.Ports.Underlay) for _, interfaceName := range cfg.Ports.Underlay { - if err := a.configureUnderlayPort(ctx, interfaceName, !cfg.Ports.DownPorts[interfaceName]); err != nil { + if err := a.configureUnderlayPort(ctx, interfaceName, cfg.Ports.AdminStatus[interfaceName]); err != nil { errs = append(errs, err) } } @@ -58,14 +76,14 @@ func (a *Applier) Apply(ctx context.Context, cfg *types.Conf) error { a.log.Debug("configure unprovisioned ports", "ports", cfg.Ports.Unprovisioned) for _, interfaceName := range cfg.Ports.Unprovisioned { pxeVlan := fmt.Sprintf("Vlan%d", cfg.PXEVlanID) - if err := a.configureUnprovisionedPort(ctx, interfaceName, !cfg.Ports.DownPorts[interfaceName], pxeVlan); err != nil { + if err := a.configureUnprovisionedPort(ctx, interfaceName, cfg.Ports.AdminStatus[interfaceName], pxeVlan); err != nil { errs = append(errs, err) } } a.log.Debug("configure firewall ports", "ports", cfg.Ports.Firewalls) for interfaceName := range cfg.Ports.Firewalls { - if err := a.configureFirewallPort(ctx, interfaceName, !cfg.Ports.DownPorts[interfaceName]); err != nil { + if err := a.configureFirewallPort(ctx, interfaceName, cfg.Ports.AdminStatus[interfaceName]); err != nil { errs = append(errs, err) } } @@ -76,13 +94,13 @@ func (a *Applier) Apply(ctx context.Context, cfg *types.Conf) error { errs = append(errs, err) } for _, interfaceName := range vrf.Neighbors { - if err := a.configureVrfNeighbor(ctx, interfaceName, vrfName, !cfg.Ports.DownPorts[interfaceName]); err != nil { + if err := a.configureVrfNeighbor(ctx, interfaceName, vrfName, cfg.Ports.AdminStatus[interfaceName]); err != nil { errs = append(errs, err) } } } - err := a.cleanupVrfs(ctx, cfg) + err = a.cleanupVrfs(ctx, cfg) if err != nil { errs = append(errs, err) } @@ -131,42 +149,41 @@ func (a *Applier) refreshOidMaps(ctx context.Context) error { return nil } -func (a *Applier) configureUnprovisionedPort(ctx context.Context, interfaceName string, isUp bool, pxeVlan string) error { +func (a *Applier) configureUnprovisionedPort(ctx context.Context, interfaceName string, adminStatus types.PortStatus, pxeVlan string) error { err := a.ensureNotRouted(ctx, interfaceName) if err != nil { return err } - // unprovisioned ports should be up - if err := a.ensurePortConfiguration(ctx, interfaceName, "9000", isUp); err != nil { + if err := a.ensurePortConfiguration(ctx, interfaceName, "9000", adminStatus); err != nil { return fmt.Errorf("failed to update Port info for interface %s: %w", interfaceName, err) } return a.ensureInterfaceIsVlanMember(ctx, interfaceName, pxeVlan) } -func (a *Applier) configureFirewallPort(ctx context.Context, interfaceName string, isUp bool) error { +func (a *Applier) configureFirewallPort(ctx context.Context, interfaceName string, adminStatus types.PortStatus) error { err := a.ensureNotBridged(ctx, interfaceName) if err != nil { return err } // a firewall port should always be up - if err := a.ensurePortConfiguration(ctx, interfaceName, "9216", isUp); err != nil { + if err := a.ensurePortConfiguration(ctx, interfaceName, "9216", adminStatus); err != nil { return fmt.Errorf("failed to update Port info for interface %s: %w", interfaceName, err) } return a.ensureLinkLocalOnlyIsEnabled(ctx, interfaceName) } -func (a *Applier) configureUnderlayPort(ctx context.Context, interfaceName string, isUp bool) error { - if err := a.ensurePortConfiguration(ctx, interfaceName, "9216", isUp); err != nil { +func (a *Applier) configureUnderlayPort(ctx context.Context, interfaceName string, adminStatus types.PortStatus) error { + if err := a.ensurePortConfiguration(ctx, interfaceName, "9216", adminStatus); err != nil { return fmt.Errorf("failed to update Port info for interface %s: %w", interfaceName, err) } return a.ensureLinkLocalOnlyIsEnabled(ctx, interfaceName) } -func (a *Applier) configureVrfNeighbor(ctx context.Context, interfaceName, vrfName string, isUp bool) error { +func (a *Applier) configureVrfNeighbor(ctx context.Context, interfaceName, vrfName string, adminStatus types.PortStatus) error { err := a.ensureNotBridged(ctx, interfaceName) if err != nil { return err @@ -177,7 +194,7 @@ func (a *Applier) configureVrfNeighbor(ctx context.Context, interfaceName, vrfNa return err } - if err := a.ensurePortConfiguration(ctx, interfaceName, "9000", isUp); err != nil { + if err := a.ensurePortConfiguration(ctx, interfaceName, "9000", adminStatus); err != nil { return fmt.Errorf("failed to update Port info for interface %s: %w", interfaceName, err) } diff --git a/cmd/internal/switcher/sonic/redis/port.go b/cmd/internal/switcher/sonic/redis/port.go index 3fdd3118..df22ea90 100644 --- a/cmd/internal/switcher/sonic/redis/port.go +++ b/cmd/internal/switcher/sonic/redis/port.go @@ -3,9 +3,11 @@ package redis import ( "context" "fmt" + + "github.com/metal-stack/metal-core/cmd/internal/switcher/types" ) -func (a *Applier) ensurePortConfiguration(ctx context.Context, portName, mtu string, isUp bool) error { +func (a *Applier) ensurePortConfiguration(ctx context.Context, portName, mtu string, adminStatus types.PortStatus) error { p, err := a.db.Config.GetPort(ctx, portName) if err != nil { return fmt.Errorf("could not retrieve port info for %s from redis: %w", portName, err) @@ -22,9 +24,9 @@ func (a *Applier) ensurePortConfiguration(ctx context.Context, portName, mtu str } } - if p.AdminStatus != isUp { - a.log.Debug("set admin status to", "port", portName, "admin_status_up", isUp) - return a.db.Config.SetAdminStatusUp(ctx, portName, isUp) + if p.AdminStatus != string(adminStatus) && adminStatus != "" { + a.log.Debug("set admin status to", "port", portName, "admin_status", adminStatus) + return a.db.Config.SetAdminStatus(ctx, portName, adminStatus) } return nil diff --git a/cmd/internal/switcher/templates/test_down_interfaces/conf_with_downports.yaml b/cmd/internal/switcher/templates/test_down_interfaces/conf_with_downports.yaml index df278021..90d32014 100644 --- a/cmd/internal/switcher/templates/test_down_interfaces/conf_with_downports.yaml +++ b/cmd/internal/switcher/templates/test_down_interfaces/conf_with_downports.yaml @@ -11,8 +11,14 @@ ports: vlanid: 2 neighbors: - swp3 + - swp4 cidrs: - 10.255.255.1/28 + firewalls: + fw1: + port: swp5 + fw2: + port: swp6 eth0: addresscidr: 192.168.0.11 gateway: 192.168.0.254 @@ -22,6 +28,9 @@ ports: unprovisioned: - swp1 - swp2 - downports: - swp3: True + adminstatus: + swp1: down + swp3: down + swp6: down + swp32: down pxevlanid: 966 diff --git a/cmd/internal/switcher/templates/test_down_interfaces/interfaces_with_downports b/cmd/internal/switcher/templates/test_down_interfaces/interfaces_with_downports index 341e4d12..9ada173e 100644 --- a/cmd/internal/switcher/templates/test_down_interfaces/interfaces_with_downports +++ b/cmd/internal/switcher/templates/test_down_interfaces/interfaces_with_downports @@ -24,13 +24,13 @@ auto swp31 iface swp31 mtu 9216 -auto swp32 -iface swp32 +auto swp5 +iface swp5 mtu 9216 auto bridge iface bridge - bridge-ports vni100966 swp1 swp2 vni1 + bridge-ports vni100966 swp2 vni1 bridge-vids 966 2 bridge-vlan-aware yes @@ -40,6 +40,12 @@ auto vrf1 iface vrf1 vrf-table auto +auto swp4 +iface swp4 + mtu 9000 + post-up sysctl -w net.ipv6.conf.swp4.disable_ipv6=0 + vrf vrf1 + auto vlan2 iface vlan2 mtu 9000 @@ -76,11 +82,6 @@ iface vni100966 vxlan-id 100966 vxlan-local-tunnelip 10.0.0.10 -auto swp1 -iface swp1 - mtu 9000 - bridge-access 966 - auto swp2 iface swp2 mtu 9000 diff --git a/cmd/internal/switcher/types/conf.go b/cmd/internal/switcher/types/conf.go index bfa6e24b..1fdda194 100644 --- a/cmd/internal/switcher/types/conf.go +++ b/cmd/internal/switcher/types/conf.go @@ -88,55 +88,74 @@ func (c *Conf) CapitalizeVrfName() { } func (c *Conf) NewWithoutDownPorts() *Conf { - if len(c.Ports.DownPorts) < 1 { - return c - } - newConf := *c - newConf.Ports.Vrfs = make(map[string]*Vrf) - - // create a copy of the VRFs and filter out the interfaces which should be down - for vrf, vrfConf := range c.Ports.Vrfs { - newVrfConf := *vrfConf - newVrfConf.Neighbors = []string{} - for _, port := range vrfConf.Neighbors { - if _, isdown := c.Ports.DownPorts[port]; !isdown { - newVrfConf.Neighbors = append(newVrfConf.Neighbors, port) - } + var ( + underlay []string + unprovisioned []string + bladePorts []string + vrfs = map[string]*Vrf{} + firewalls = map[string]*Firewall{} + ) + + ports := c.Ports + for _, port := range ports.Underlay { + if ports.AdminStatus[port] != PortStatusDown { + underlay = append(underlay, port) } - newConf.Ports.Vrfs[vrf] = &newVrfConf } - newConf.Ports.Underlay = []string{} - newConf.Ports.Unprovisioned = []string{} - newConf.Ports.BladePorts = []string{} - newConf.Ports.Firewalls = make(map[string]*Firewall) - - // create a copy of the firewalls and filter out the interfaces which should be down - for port, fwConf := range c.Ports.Firewalls { - if _, isdown := c.Ports.DownPorts[port]; !isdown { - newConf.Ports.Firewalls[port] = fwConf + + for _, port := range ports.Unprovisioned { + if ports.AdminStatus[port] != PortStatusDown { + unprovisioned = append(unprovisioned, port) } } - // create a copy of the underlay ports without the downports - for _, port := range c.Ports.Underlay { - if _, isdown := c.Ports.DownPorts[port]; !isdown { - newConf.Ports.Underlay = append(newConf.Ports.Underlay, port) + for _, port := range ports.BladePorts { + if ports.AdminStatus[port] != PortStatusDown { + bladePorts = append(bladePorts, port) } } - // create a copy of the unprovisioned ports without the downports - for _, port := range c.Ports.Unprovisioned { - if _, isdown := c.Ports.DownPorts[port]; !isdown { - newConf.Ports.Unprovisioned = append(newConf.Ports.Unprovisioned, port) + for name, vrf := range ports.Vrfs { + newVrf := Vrf{ + Filter: vrf.Filter, + VNI: vrf.VNI, + VLANID: vrf.VLANID, + Cidrs: vrf.Cidrs, + Has4: vrf.Has4, + Has6: vrf.Has6, } + + var neighbors []string + for _, neigh := range vrf.Neighbors { + if ports.AdminStatus[neigh] != PortStatusDown { + neighbors = append(neighbors, neigh) + } + } + newVrf.Neighbors = neighbors + vrfs[name] = &newVrf } - // create a copy of the blade ports without the downports - for _, port := range c.Ports.BladePorts { - if _, isdown := c.Ports.DownPorts[port]; !isdown { - newConf.Ports.BladePorts = append(newConf.Ports.BladePorts, port) + for name, fw := range ports.Firewalls { + if ports.AdminStatus[fw.Port] == PortStatusDown { + continue + } + firewalls[name] = &Firewall{ + Filter: fw.Filter, + Port: fw.Port, + Cidrs: fw.Cidrs, + Vnis: fw.Vnis, } } + newConf := *c + newConf.Ports = Ports{ + Eth0: c.Ports.Eth0, + Underlay: underlay, + Unprovisioned: unprovisioned, + BladePorts: bladePorts, + Vrfs: vrfs, + Firewalls: firewalls, + AdminStatus: c.Ports.AdminStatus, + } return &newConf } diff --git a/cmd/internal/switcher/types/types.go b/cmd/internal/switcher/types/types.go index 3a769544..f6226879 100644 --- a/cmd/internal/switcher/types/types.go +++ b/cmd/internal/switcher/types/types.go @@ -5,72 +5,76 @@ import ( "net/netip" ) -// Conf holds the switch configuration -type Conf struct { - Name string - LogLevel string - Loopback string - ASN uint32 - Ports Ports - MetalCoreCIDR string - AdditionalBridgeVIDs []string - PXEVlanID uint16 - SetSrcLoopback bool -} +type ( + Conf struct { + Name string + LogLevel string + Loopback string + ASN uint32 + Ports Ports + MetalCoreCIDR string + AdditionalBridgeVIDs []string + PXEVlanID uint16 + SetSrcLoopback bool + } -type Ports struct { - Eth0 Nic - Underlay []string - Unprovisioned []string - BladePorts []string - DownPorts map[string]bool - Vrfs map[string]*Vrf - Firewalls map[string]*Firewall -} + Ports struct { + Eth0 Nic + Underlay []string + Unprovisioned []string + BladePorts []string + Vrfs map[string]*Vrf + Firewalls map[string]*Firewall + AdminStatus map[string]PortStatus + } -// Tenant holds the switch configuration for a specific tenant -type Vrf struct { - Filter - VNI uint32 - VLANID uint16 - Neighbors []string - Cidrs []string - Has4 bool - Has6 bool -} + Vrf struct { + Filter + VNI uint32 + VLANID uint16 + Neighbors []string + Cidrs []string + Has4 bool + Has6 bool + } -type Firewall struct { - Filter - Port string - Cidrs []string - Vnis []string -} + Firewall struct { + Filter + Port string + Cidrs []string + Vnis []string + } -type Filter struct { - IPPrefixLists []IPPrefixList - RouteMaps []RouteMap -} + Filter struct { + IPPrefixLists []IPPrefixList + RouteMaps []RouteMap + } -// Nic holds the configuration for a network interface -type Nic struct { - AddressCIDR string - Gateway string -} + Nic struct { + AddressCIDR string + Gateway string + } -// RouteMap represents a route-map to permit or deny routes. -type RouteMap struct { - Name string - Entries []string - Policy string - Order int -} + RouteMap struct { + Name string + Entries []string + Policy string + Order int + } -// IPPrefixList represents 'ip prefix-list' filtering mechanism to be used in combination with route-maps. -type IPPrefixList struct { - AddressFamily string - Name string - Spec string -} + IPPrefixList struct { + AddressFamily string + Name string + Spec string + } + + PortStatus string +) + +const ( + PortStatusUp = PortStatus("up") + PortStatusDown = PortStatus("down") +) func (s *Filter) Assemble(rmPrefix string, vnis, cidrs []string) { cidrsByAf := cidrsByAddressfamily(cidrs) diff --git a/go.mod b/go.mod index 9ae6bd0e..b1b162d4 100644 --- a/go.mod +++ b/go.mod @@ -9,16 +9,17 @@ require ( github.com/google/go-cmp v0.7.0 github.com/kelseyhightower/envconfig v1.4.0 github.com/metal-stack/go-lldpd v0.4.12 - github.com/metal-stack/metal-api v0.43.1 - github.com/metal-stack/metal-go v0.43.1 + github.com/metal-stack/metal-api v0.45.0 + github.com/metal-stack/metal-go v0.45.0 + github.com/metal-stack/metal-lib v0.25.1 github.com/metal-stack/v v1.0.3 github.com/prometheus/client_golang v1.23.2 github.com/stretchr/testify v1.11.1 github.com/valkey-io/valkey-go v1.0.74 github.com/vishvananda/netlink v1.3.1 go4.org/netipx v0.0.0-20231129151722-fdeea329fbba - golang.org/x/text v0.36.0 - google.golang.org/grpc v1.80.0 + golang.org/x/text v0.38.0 + google.golang.org/grpc v1.81.1 google.golang.org/protobuf v1.36.11 gopkg.in/yaml.v3 v3.0.1 ) @@ -26,33 +27,34 @@ require ( require ( github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect - github.com/coreos/go-oidc/v3 v3.18.0 // indirect + github.com/coreos/go-oidc/v3 v3.19.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.1 // indirect github.com/go-jose/go-jose/v4 v4.1.4 // indirect github.com/go-logr/logr v1.4.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect - github.com/go-openapi/analysis v0.25.0 // indirect - github.com/go-openapi/errors v0.22.7 // indirect + github.com/go-openapi/analysis v0.25.2 // indirect + github.com/go-openapi/errors v0.22.8 // indirect github.com/go-openapi/jsonpointer v0.23.1 // indirect - github.com/go-openapi/jsonreference v0.21.5 // indirect - github.com/go-openapi/loads v0.23.3 // indirect - github.com/go-openapi/runtime v0.29.4 // indirect - github.com/go-openapi/spec v0.22.4 // indirect - github.com/go-openapi/strfmt v0.26.1 // indirect + github.com/go-openapi/jsonreference v0.21.6 // indirect + github.com/go-openapi/loads v0.24.0 // indirect + github.com/go-openapi/runtime v0.32.4 // indirect + github.com/go-openapi/runtime/server-middleware v0.30.0 // indirect + github.com/go-openapi/spec v0.22.6 // indirect + github.com/go-openapi/strfmt v0.26.3 // indirect github.com/go-openapi/swag v0.26.0 // indirect github.com/go-openapi/swag/cmdutils v0.26.0 // indirect - github.com/go-openapi/swag/conv v0.26.0 // indirect - github.com/go-openapi/swag/fileutils v0.26.0 // indirect - github.com/go-openapi/swag/jsonname v0.26.0 // indirect - github.com/go-openapi/swag/jsonutils v0.26.0 // indirect - github.com/go-openapi/swag/loading v0.26.0 // indirect - github.com/go-openapi/swag/mangling v0.26.0 // indirect + github.com/go-openapi/swag/conv v0.26.1 // indirect + github.com/go-openapi/swag/fileutils v0.26.1 // indirect + github.com/go-openapi/swag/jsonname v0.26.1 // indirect + github.com/go-openapi/swag/jsonutils v0.26.1 // indirect + github.com/go-openapi/swag/loading v0.26.1 // indirect + github.com/go-openapi/swag/mangling v0.26.1 // indirect github.com/go-openapi/swag/netutils v0.26.0 // indirect - github.com/go-openapi/swag/stringutils v0.26.0 // indirect - github.com/go-openapi/swag/typeutils v0.26.0 // indirect - github.com/go-openapi/swag/yamlutils v0.26.0 // indirect - github.com/go-openapi/validate v0.25.2 // indirect + github.com/go-openapi/swag/stringutils v0.26.1 // indirect + github.com/go-openapi/swag/typeutils v0.26.1 // indirect + github.com/go-openapi/swag/yamlutils v0.26.1 // indirect + github.com/go-openapi/validate v0.26.0 // indirect github.com/go-viper/mapstructure/v2 v2.5.0 // indirect github.com/goccy/go-json v0.10.6 // indirect github.com/godbus/dbus/v5 v5.2.2 // indirect @@ -62,32 +64,31 @@ require ( github.com/gorilla/mux v1.8.1 // indirect github.com/lestrrat-go/blackmagic v1.0.4 // indirect github.com/lestrrat-go/httpcc v1.0.1 // indirect - github.com/lestrrat-go/httprc/v3 v3.0.5 // indirect - github.com/lestrrat-go/jwx/v3 v3.1.0 // indirect + github.com/lestrrat-go/httprc/v3 v3.0.6 // indirect + github.com/lestrrat-go/jwx/v3 v3.1.1 // indirect github.com/lestrrat-go/option/v2 v2.0.0 // indirect github.com/mdlayher/ethernet v0.0.0-20220221185849-529eae5b6118 // indirect github.com/mdlayher/lldp v0.0.0-20150915211757-afd9f83164c5 // indirect - github.com/metal-stack/metal-lib v0.25.0 // indirect github.com/metal-stack/security v0.9.6 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/oklog/ulid/v2 v2.1.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/prometheus/client_model v0.6.2 // indirect - github.com/prometheus/common v0.67.5 // indirect + github.com/prometheus/common v0.69.0 // indirect github.com/prometheus/procfs v0.20.1 // indirect github.com/segmentio/asm v1.2.1 // indirect + github.com/valyala/fastjson v1.6.10 // indirect github.com/vishvananda/netns v0.0.5 // indirect github.com/yuin/gopher-lua v1.1.2 // indirect go.opentelemetry.io/auto/sdk v1.2.1 // indirect - go.opentelemetry.io/otel v1.43.0 // indirect - go.opentelemetry.io/otel/metric v1.43.0 // indirect - go.opentelemetry.io/otel/trace v1.43.0 // indirect - go.yaml.in/yaml/v2 v2.4.4 // indirect + go.opentelemetry.io/otel v1.44.0 // indirect + go.opentelemetry.io/otel/metric v1.44.0 // indirect + go.opentelemetry.io/otel/trace v1.44.0 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect - golang.org/x/crypto v0.50.0 // indirect - golang.org/x/net v0.53.0 // indirect + golang.org/x/crypto v0.53.0 // indirect + golang.org/x/net v0.56.0 // indirect golang.org/x/oauth2 v0.36.0 // indirect - golang.org/x/sync v0.20.0 // indirect - golang.org/x/sys v0.43.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20260420184626-e10c466a9529 // indirect + golang.org/x/sync v0.21.0 // indirect + golang.org/x/sys v0.46.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260622175928-b703f567277d // indirect ) diff --git a/go.sum b/go.sum index 79a5fa50..5566244a 100644 --- a/go.sum +++ b/go.sum @@ -6,8 +6,8 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/coreos/go-oidc/v3 v3.18.0 h1:V9orjXynvu5wiC9SemFTWnG4F45v403aIcjWo0d41+A= -github.com/coreos/go-oidc/v3 v3.18.0/go.mod h1:DYCf24+ncYi+XkIH97GY1+dqoRlbaSI26KVTCI9SrY4= +github.com/coreos/go-oidc/v3 v3.19.0 h1:F/xyOi3x1UnG1U27YVnM1N6bHiL1K2upi6U/0qr8r+I= +github.com/coreos/go-oidc/v3 v3.19.0/go.mod h1:DYCf24+ncYi+XkIH97GY1+dqoRlbaSI26KVTCI9SrY4= github.com/coreos/go-systemd/v22 v22.7.0 h1:LAEzFkke61DFROc7zNLX/WA2i5J8gYqe0rSj9KI28KA= github.com/coreos/go-systemd/v22 v22.7.0/go.mod h1:xNUYtjHu2EDXbsxz1i41wouACIwT7Ybq9o0BQhMwD0w= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -24,54 +24,56 @@ github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-openapi/analysis v0.25.0 h1:EnjAq1yO8wEO9HbPmY8vLPEIkdZuuFhCAKBPvCB7bCs= -github.com/go-openapi/analysis v0.25.0/go.mod h1:5WFTRE43WLkPG9r9OtlMfqkkvUTYLVVCIxLlEpyF8kE= -github.com/go-openapi/errors v0.22.7 h1:JLFBGC0Apwdzw3484MmBqspjPbwa2SHvpDm0u5aGhUA= -github.com/go-openapi/errors v0.22.7/go.mod h1://QW6SD9OsWtH6gHllUCddOXDL0tk0ZGNYHwsw4sW3w= +github.com/go-openapi/analysis v0.25.2 h1:I0vy4n3alz+DHTiN1PRhCb7QZxkK6g5YmswZKv2TKuw= +github.com/go-openapi/analysis v0.25.2/go.mod h1:Uhs1t/2XR10EnwONYILGEzw8gcfGIG5Xk5K2AxnhqDo= +github.com/go-openapi/errors v0.22.8 h1:oP7sW7TWc3wFFjrzzj0nI83H2qMBkNjNfSd+XRejk/I= +github.com/go-openapi/errors v0.22.8/go.mod h1:BuUoHcYrU6E7V9gfj1I5wLQqgtIHnup/alXZ8KdgQ0w= github.com/go-openapi/jsonpointer v0.23.1 h1:1HBACs7XIwR2RcmItfdSFlALhGbe6S92p0ry4d1GWg4= github.com/go-openapi/jsonpointer v0.23.1/go.mod h1:iWRmZTrGn7XwYhtPt/fvdSFj1OfNBngqRT2UG3BxSqY= -github.com/go-openapi/jsonreference v0.21.5 h1:6uCGVXU/aNF13AQNggxfysJ+5ZcU4nEAe+pJyVWRdiE= -github.com/go-openapi/jsonreference v0.21.5/go.mod h1:u25Bw85sX4E2jzFodh1FOKMTZLcfifd1Q+iKKOUxExw= -github.com/go-openapi/loads v0.23.3 h1:g5Xap1JfwKkUnZdn+S0L3SzBDpcTIYzZ5Qaag0YDkKQ= -github.com/go-openapi/loads v0.23.3/go.mod h1:NOH07zLajXo8y55hom0omlHWDVVvCwBM/S+csCK8LqA= -github.com/go-openapi/runtime v0.29.4 h1:k2lDxrGoSAJRdhFG2tONKMpkizY/4X1cciSdtzk4Jjo= -github.com/go-openapi/runtime v0.29.4/go.mod h1:K0k/2raY6oqXJnZAgWJB2i/12QKrhUKpZcH4PfV9P18= -github.com/go-openapi/spec v0.22.4 h1:4pxGjipMKu0FzFiu/DPwN3CTBRlVM2yLf/YTWorYfDQ= -github.com/go-openapi/spec v0.22.4/go.mod h1:WQ6Ai0VPWMZgMT4XySjlRIE6GP1bGQOtEThn3gcWLtQ= -github.com/go-openapi/strfmt v0.26.1 h1:7zGCHji7zSYDC2tCXIusoxYQz/48jAf2q+sF6wXTG+c= -github.com/go-openapi/strfmt v0.26.1/go.mod h1:Zslk5VZPOISLwmWTMBIS7oiVFem1o1EI6zULY8Uer7Y= +github.com/go-openapi/jsonreference v0.21.6 h1:NZ5nGfnaM1n4I43Xjm1e5/M2GjOwQwndQz22uhxwD+Y= +github.com/go-openapi/jsonreference v0.21.6/go.mod h1:xzbgtQ3ZbWxvET3AxdzCJlJt6vkovbf+IfSPJjD0tUY= +github.com/go-openapi/loads v0.24.0 h1:4LLorXRPTzIN9V6ngMUZbAscsBOUBk3Oa8cClu/bFrQ= +github.com/go-openapi/loads v0.24.0/go.mod h1:xQMgX+hw5xRAhGrcDXxeMw78IFqUpIzhleu3HqPhyF4= +github.com/go-openapi/runtime v0.32.4 h1:8ElGj/3goG0itt0nBPP6Cm57ehcYyuHoI3O20nxgvkw= +github.com/go-openapi/runtime v0.32.4/go.mod h1:Bz6keOZw1NX4T6f+m42OoT1MBPDt6Re13dbccHyGH/4= +github.com/go-openapi/runtime/server-middleware v0.30.0 h1:8rPoJ/xv7JL8BsovaqboKETlpWBArVh8n+0L/GyePog= +github.com/go-openapi/runtime/server-middleware v0.30.0/go.mod h1:OYNT/TxNvB/VK5oe4htM2jDTwlEXuejVJmu0DVZfAMs= +github.com/go-openapi/spec v0.22.6 h1:Tyy1pLaNCM8GBCFLoGYLonjJi6zykqyLCjXLc19ZPic= +github.com/go-openapi/spec v0.22.6/go.mod h1:HZvTHat+iH0PALQRWhrqIHtU/PEqxqd89fu0MxGlMeM= +github.com/go-openapi/strfmt v0.26.3 h1:rzmslHarJgBbf2qfGge+X3htclQfmXqBZMm0Too0HhU= +github.com/go-openapi/strfmt v0.26.3/go.mod h1:a5nsUw0oRpQzZeOwx8bi6cKbzFZslpbCKt1LEot+KnQ= github.com/go-openapi/swag v0.26.0 h1:GVDXCmfvhfu1BxiHo8/FA+BbKmhecHnG3varjON5/RI= github.com/go-openapi/swag v0.26.0/go.mod h1:82g3193sZJRbocs7bNCqGfIgq8pkuwVwCfhKIRlEQF0= github.com/go-openapi/swag/cmdutils v0.26.0 h1:iowihOcvq7y4egO8cOq0dmfohz6wfeQ63U1EnuhO2TU= github.com/go-openapi/swag/cmdutils v0.26.0/go.mod h1:Sm1MVFMkF6guJJ+pQqHnQA3N0j9qALV3NxzDSv6bETM= -github.com/go-openapi/swag/conv v0.26.0 h1:5yGGsPYI1ZCva93U0AoKi/iZrNhaJEjr324YVsiD89I= -github.com/go-openapi/swag/conv v0.26.0/go.mod h1:tpAmIL7X58VPnHHiSO4uE3jBeRamGsFsfdDeDtb5ECE= -github.com/go-openapi/swag/fileutils v0.26.0 h1:WJoPRvsA7QRiiWluowkLJa9jaYR7FCuxmDvnCgaRRxU= -github.com/go-openapi/swag/fileutils v0.26.0/go.mod h1:0WDJ7lp67eNjPMO50wAWYlKvhOb6CQ37rzR7wrgI8Tc= -github.com/go-openapi/swag/jsonname v0.26.0 h1:gV1NFX9M8avo0YSpmWogqfQISigCmpaiNci8cGECU5w= -github.com/go-openapi/swag/jsonname v0.26.0/go.mod h1:urBBR8bZNoDYGr653ynhIx+gTeIz0ARZxHkAPktJK2M= -github.com/go-openapi/swag/jsonutils v0.26.0 h1:FawFML2iAXsPqmERscuMPIHmFsoP1tOqWkxBaKNMsnA= -github.com/go-openapi/swag/jsonutils v0.26.0/go.mod h1:2VmA0CJlyFqgawOaPI9psnjFDqzyivIqLYN34t9p91E= -github.com/go-openapi/swag/jsonutils/fixtures_test v0.26.0 h1:apqeINu/ICHouqiRZbyFvuDge5jCmmLTqGQ9V95EaOM= -github.com/go-openapi/swag/jsonutils/fixtures_test v0.26.0/go.mod h1:AyM6QT8uz5IdKxk5akv0y6u4QvcL9GWERt0Jx/F/R8Y= -github.com/go-openapi/swag/loading v0.26.0 h1:Apg6zaKhCJurpJer0DCxq99qwmhFddBhaMX7kilDcko= -github.com/go-openapi/swag/loading v0.26.0/go.mod h1:dBxQ/6V2uBaAQdevN18VELE6xSpJWZxLX4txe12JwDg= -github.com/go-openapi/swag/mangling v0.26.0 h1:Du2YC4YLA/Y5m/YKQd7AnY5qq0wRKSFZTTt8ktFaXcQ= -github.com/go-openapi/swag/mangling v0.26.0/go.mod h1:jifS7W9vbg+pw63bT+GI53otluMQL3CeemuyCHKwVx0= +github.com/go-openapi/swag/conv v0.26.1 h1:slr5FVkg9Wc3Y5zcwenD8Sd/PQ94b2I/QJI7N7KTBpg= +github.com/go-openapi/swag/conv v0.26.1/go.mod h1:mvQXgPptZk9GTrFgGwWvT4q+dN+zQej9JfmGwnipz1A= +github.com/go-openapi/swag/fileutils v0.26.1 h1:K1XCM2CGhfNsc6YDt6v7Q5+1e59rftYWdcu/isZhvFw= +github.com/go-openapi/swag/fileutils v0.26.1/go.mod h1:mYUgxQAKX4ShS3qvvySx+/9yrlUnDhjiD1CalaQl8lQ= +github.com/go-openapi/swag/jsonname v0.26.1 h1:VReupaV6WxlAsCn0e4DUfgV6bPmINnPpyJDLqSfNPcE= +github.com/go-openapi/swag/jsonname v0.26.1/go.mod h1:OvdW6BoWoj33pTfi7x9vFrgmT+fk7aw0BRwvCE0YOuc= +github.com/go-openapi/swag/jsonutils v0.26.1 h1:2hdBfFkHg+7Wrz2VsCbeyR6hzkRDs7AztnMR2u84yOY= +github.com/go-openapi/swag/jsonutils v0.26.1/go.mod h1:U+RMJH3wa+6BRiphuRtIyI8fW9HPFqFQ4sHk2oRx0UQ= +github.com/go-openapi/swag/jsonutils/fixtures_test v0.26.1 h1:1CD7NiLLb/TXl3tOnFYU4b+mNfb5rtgHkaA+q7RMYYQ= +github.com/go-openapi/swag/jsonutils/fixtures_test v0.26.1/go.mod h1:ZWafc8nMdYzTE3uYY6W86f0n46+IF0g4uUyRhJw/kXc= +github.com/go-openapi/swag/loading v0.26.1 h1:E9K4wqXeROlhjFQ13K9zMz6ojFGXIggGe+ad1odrK9w= +github.com/go-openapi/swag/loading v0.26.1/go.mod h1:3qvRIlWzWdq1HvmldwmuJ2ohpcAryN6xVt2OTKd0/7E= +github.com/go-openapi/swag/mangling v0.26.1 h1:gpYI4WuPKFJJVjV5cDLGlDVJhFIxYjQc7yN5eEb4CqM= +github.com/go-openapi/swag/mangling v0.26.1/go.mod h1:POETDH01hqAdASXfw7ISEd9bCOE6xBHOt8NHmGZRmYM= github.com/go-openapi/swag/netutils v0.26.0 h1:CmZp+ZT7HrmFwrC3GdGsXBq2+42T1bjKBapcqVpIs3c= github.com/go-openapi/swag/netutils v0.26.0/go.mod h1:5iK+Ok3ZohWWex1C50BFTPexi03UaPwjW4Oj8kgrpwo= -github.com/go-openapi/swag/stringutils v0.26.0 h1:qZQngLxs5s7SLijc3N2ZO+fUq2o8LjuWAASSrJuh+xg= -github.com/go-openapi/swag/stringutils v0.26.0/go.mod h1:sWn5uY+QIIspwPhvgnqJsH8xqFT2ZbYcvbcFanRyhFE= -github.com/go-openapi/swag/typeutils v0.26.0 h1:2kdEwdiNWy+JJdOvu5MA2IIg2SylWAFuuyQIKYybfq4= -github.com/go-openapi/swag/typeutils v0.26.0/go.mod h1:oovDuIUvTrEHVMqWilQzKzV4YlSKgyZmFh7AlfABNVE= -github.com/go-openapi/swag/yamlutils v0.26.0 h1:H7O8l/8NJJQ/oiReEN+oMpnGMyt8G0hl460nRZxhLMQ= -github.com/go-openapi/swag/yamlutils v0.26.0/go.mod h1:1evKEGAtP37Pkwcc7EWMF0hedX0/x3Rkvei2wtG/TbU= -github.com/go-openapi/testify/enable/yaml/v2 v2.4.2 h1:5zRca5jw7lzVREKCZVNBpysDNBjj74rBh0N2BGQbSR0= -github.com/go-openapi/testify/enable/yaml/v2 v2.4.2/go.mod h1:XVevPw5hUXuV+5AkI1u1PeAm27EQVrhXTTCPAF85LmE= -github.com/go-openapi/testify/v2 v2.4.2 h1:tiByHpvE9uHrrKjOszax7ZvKB7QOgizBWGBLuq0ePx4= -github.com/go-openapi/testify/v2 v2.4.2/go.mod h1:SgsVHtfooshd0tublTtJ50FPKhujf47YRqauXXOUxfw= -github.com/go-openapi/validate v0.25.2 h1:12NsfLAwGegqbGWr2CnvT65X/Q2USJipmJ9b7xDJZz0= -github.com/go-openapi/validate v0.25.2/go.mod h1:Pgl1LpPPGFnZ+ys4/hTlDiRYQdI1ocKypgE+8Q8BLfY= +github.com/go-openapi/swag/stringutils v0.26.1 h1:f88uYyTso7TnHrKM/bUBsQ5e2wKf37cpgo6pvbzd9yU= +github.com/go-openapi/swag/stringutils v0.26.1/go.mod h1:Sc6d3bU8fgk5AyZR8/8jEQ+Is/Ald+TD/IIggPN8UJk= +github.com/go-openapi/swag/typeutils v0.26.1 h1:yg42FgMzRR6PVQ3M3qHz1s+Y6/P4HoJ3cBarXa3OVnU= +github.com/go-openapi/swag/typeutils v0.26.1/go.mod h1:VfnV+oUtSP2vCSCn2aJgnr8OevUYemyIzzS1VOzS10o= +github.com/go-openapi/swag/yamlutils v0.26.1 h1:0TSLK+lXs9vfIhAWzBeI/lOzEnIoot6WTCO1aAeWFTk= +github.com/go-openapi/swag/yamlutils v0.26.1/go.mod h1:7W5b7PRX9MxwL7TjeG7H8HkyBGRsIDRObhyMWFgBI2M= +github.com/go-openapi/testify/enable/yaml/v2 v2.5.1 h1:q9NtHwK4qHF7yZziBPvZyv7zWAIk8ok88Gh2mR6Jpc8= +github.com/go-openapi/testify/enable/yaml/v2 v2.5.1/go.mod h1:JW0MXIotCYps/XsgJnG3a8Q7rE5xAiBwoOD5OfaIQBk= +github.com/go-openapi/testify/v2 v2.5.1 h1:TMdhCaw8fUNraVSf3Omoob1dO/AzBfhtFAPW0an6sBo= +github.com/go-openapi/testify/v2 v2.5.1/go.mod h1:SgsVHtfooshd0tublTtJ50FPKhujf47YRqauXXOUxfw= +github.com/go-openapi/validate v0.26.0 h1:dxWzQ3F+vb1SajqUxHjwb5T4mTpSHmdrtv5Bi7+ZNhw= +github.com/go-openapi/validate v0.26.0/go.mod h1:b4o00uq7fJeJA+wWhVFCJpKTctzeFwzZImGGmHsl2JA= github.com/go-viper/mapstructure/v2 v2.5.0 h1:vM5IJoUAy3d7zRSVtIwQgBj7BiWtMPfmPEgAXnvj1Ro= github.com/go-viper/mapstructure/v2 v2.5.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/goccy/go-json v0.10.6 h1:p8HrPJzOakx/mn/bQtjgNjdTcN+/S6FcG2CTtQOrHVU= @@ -95,8 +97,8 @@ github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWS github.com/josharian/native v1.0.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w= github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8= github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg= -github.com/klauspost/compress v1.18.5 h1:/h1gH5Ce+VWNLSWqPzOVn6XBO+vJbCNGvjoaGBFW2IE= -github.com/klauspost/compress v1.18.5/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= +github.com/klauspost/compress v1.18.6 h1:2jupLlAwFm95+YDR+NwD2MEfFO9d4z4Prjl1XXDjuao= +github.com/klauspost/compress v1.18.6/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= @@ -111,10 +113,10 @@ github.com/lestrrat-go/dsig-secp256k1 v1.0.0 h1:JpDe4Aybfl0soBvoVwjqDbp+9S1Y2OM7 github.com/lestrrat-go/dsig-secp256k1 v1.0.0/go.mod h1:CxUgAhssb8FToqbL8NjSPoGQlnO4w3LG1P0qPWQm/NU= github.com/lestrrat-go/httpcc v1.0.1 h1:ydWCStUeJLkpYyjLDHihupbn2tYmZ7m22BGkcvZZrIE= github.com/lestrrat-go/httpcc v1.0.1/go.mod h1:qiltp3Mt56+55GPVCbTdM9MlqhvzyuL6W/NMDA8vA5E= -github.com/lestrrat-go/httprc/v3 v3.0.5 h1:S+Mb4L2I+bM6JGTibLmxExhyTOqnXjqx+zi9MoXw/TM= -github.com/lestrrat-go/httprc/v3 v3.0.5/go.mod h1:mSMtkZW92Z98M5YoNNztbRGxbXHql7tSitCvaxvo9l0= -github.com/lestrrat-go/jwx/v3 v3.1.0 h1:AyyLtxc0QM75F75JroWgt1phwC7X+wOb3XKhH7XBZWw= -github.com/lestrrat-go/jwx/v3 v3.1.0/go.mod h1:uw/MN2M/Xiu4FhwcIwH11Zsh9JWx9SWzgALl7/uIEkU= +github.com/lestrrat-go/httprc/v3 v3.0.6 h1:4FpLQ18KK/ypPbVU3NLWJNRvH3kcYiqKqWfKGqNWxxI= +github.com/lestrrat-go/httprc/v3 v3.0.6/go.mod h1:mSMtkZW92Z98M5YoNNztbRGxbXHql7tSitCvaxvo9l0= +github.com/lestrrat-go/jwx/v3 v3.1.1 h1:yd9AdPmZ4INnQ7k42IrzXYpnEG803+SrQ6hdMvzHJzw= +github.com/lestrrat-go/jwx/v3 v3.1.1/go.mod h1:uw/MN2M/Xiu4FhwcIwH11Zsh9JWx9SWzgALl7/uIEkU= github.com/lestrrat-go/option/v2 v2.0.0 h1:XxrcaJESE1fokHy3FpaQ/cXW8ZsIdWcdFzzLOcID3Ss= github.com/lestrrat-go/option/v2 v2.0.0/go.mod h1:oSySsmzMoR0iRzCDCaUfsCzxQHUEuhOViQObyy7S6Vg= github.com/mdlayher/ethernet v0.0.0-20220221185849-529eae5b6118 h1:2oDp6OOhLxQ9JBoUuysVz9UZ9uI6oLUbvAZu0x8o+vE= @@ -125,12 +127,12 @@ github.com/mdlayher/packet v1.0.0/go.mod h1:eE7/ctqDhoiRhQ44ko5JZU2zxB88g+JH/6jm github.com/mdlayher/socket v0.2.1/go.mod h1:QLlNPkFR88mRUNQIzRBMfXxwKal8H7u1h3bL1CV+f0E= github.com/metal-stack/go-lldpd v0.4.12 h1:sWicQFm3ItLmfIWjkAyOwcakA8mFfnm6OVuLNUogvy8= github.com/metal-stack/go-lldpd v0.4.12/go.mod h1:tpEvX6G+kYycoouN6csQzjFIwXNFuu9hZE3U2Y2INNU= -github.com/metal-stack/metal-api v0.43.1 h1:cJr2Mz0nNYOjyiCobp6j9F6O3qmIzzSj13hPu7aI32Q= -github.com/metal-stack/metal-api v0.43.1/go.mod h1:2JCVjO1/mcD0Sg2DLvo0hlG8AT5wwuZ6sWoMRd8WQpg= -github.com/metal-stack/metal-go v0.43.1 h1:pPkABQKbx5FaUFNzHIjSDKTj7jP4vXusEiaRK697EN0= -github.com/metal-stack/metal-go v0.43.1/go.mod h1:GSfXrAj55LGsUSMHWGDsmq5n056NG0yb1JM8bgfvKOw= -github.com/metal-stack/metal-lib v0.25.0 h1:ETGPFf0/GgAshCDtrWzm6tPlv3abRZjFnE+GHd1C/oY= -github.com/metal-stack/metal-lib v0.25.0/go.mod h1:FWviUPM7oH1CnmCwkyLjWpd3yuzf6NnR97Xf45P2/Fk= +github.com/metal-stack/metal-api v0.45.0 h1:FG/byWdsN4x6Oy3I4MWp7BhHG6TRVBVSlwbf2cukmG8= +github.com/metal-stack/metal-api v0.45.0/go.mod h1:VvibW4YHsdyQaStxpu3KDpL41BMhL12ADdVUR56Mo2A= +github.com/metal-stack/metal-go v0.45.0 h1:X5BCppdE3RYNScfwQxv9JTehyFIv6LhVzhbG25k27KQ= +github.com/metal-stack/metal-go v0.45.0/go.mod h1:GSfXrAj55LGsUSMHWGDsmq5n056NG0yb1JM8bgfvKOw= +github.com/metal-stack/metal-lib v0.25.1 h1:z14xNl59ueQavNvMG4wcIZGqVyosNlaNFcy8hUu3SCU= +github.com/metal-stack/metal-lib v0.25.1/go.mod h1:FWviUPM7oH1CnmCwkyLjWpd3yuzf6NnR97Xf45P2/Fk= github.com/metal-stack/security v0.9.6 h1:q+JbfFis/G2IuyKky2btmDmO0Y2GQ47p7lmzOi80kMY= github.com/metal-stack/security v0.9.6/go.mod h1:HBwf4y3E4VLJPG6vNW1ynlrym46cENDtzIoN9c7uxFI= github.com/metal-stack/v v1.0.3 h1:Sh2oBlnxrCUD+mVpzfC8HiqL045YWkxs0gpTvkjppqs= @@ -149,8 +151,8 @@ github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg= github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= -github.com/prometheus/common v0.67.5 h1:pIgK94WWlQt1WLwAC5j2ynLaBRDiinoAb86HZHTUGI4= -github.com/prometheus/common v0.67.5/go.mod h1:SjE/0MzDEEAyrdr5Gqc6G+sXI67maCxzaT3A2+HqjUw= +github.com/prometheus/common v0.69.0 h1:OA85nJQS/T/MaYh/Q2CcgDKSGWqNIgrBDvDH85CuiNk= +github.com/prometheus/common v0.69.0/go.mod h1:ZzL3f6u94qUxh9p+tJTrF+FvBS1XXbbRAZCQkytAL0Y= github.com/prometheus/procfs v0.20.1 h1:XwbrGOIplXW/AU3YhIhLODXMJYyC1isLFfYCsTEycfc= github.com/prometheus/procfs v0.20.1/go.mod h1:o9EMBZGRyvDrSPH1RqdxhojkuXstoe4UlK79eF5TGGo= github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= @@ -173,16 +175,16 @@ github.com/yuin/gopher-lua v1.1.2 h1:yF/FjE3hD65tBbt0VXLE13HWS9h34fdzJmrWRXwobGA github.com/yuin/gopher-lua v1.1.2/go.mod h1:7aRmXIWl37SqRf0koeyylBEzJ+aPt8A+mmkQ4f1ntR8= go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= -go.opentelemetry.io/otel v1.43.0 h1:mYIM03dnh5zfN7HautFE4ieIig9amkNANT+xcVxAj9I= -go.opentelemetry.io/otel v1.43.0/go.mod h1:JuG+u74mvjvcm8vj8pI5XiHy1zDeoCS2LB1spIq7Ay0= -go.opentelemetry.io/otel/metric v1.43.0 h1:d7638QeInOnuwOONPp4JAOGfbCEpYb+K6DVWvdxGzgM= -go.opentelemetry.io/otel/metric v1.43.0/go.mod h1:RDnPtIxvqlgO8GRW18W6Z/4P462ldprJtfxHxyKd2PY= -go.opentelemetry.io/otel/sdk v1.43.0 h1:pi5mE86i5rTeLXqoF/hhiBtUNcrAGHLKQdhg4h4V9Dg= -go.opentelemetry.io/otel/sdk v1.43.0/go.mod h1:P+IkVU3iWukmiit/Yf9AWvpyRDlUeBaRg6Y+C58QHzg= -go.opentelemetry.io/otel/sdk/metric v1.39.0 h1:cXMVVFVgsIf2YL6QkRF4Urbr/aMInf+2WKg+sEJTtB8= -go.opentelemetry.io/otel/sdk/metric v1.39.0/go.mod h1:xq9HEVH7qeX69/JnwEfp6fVq5wosJsY1mt4lLfYdVew= -go.opentelemetry.io/otel/trace v1.43.0 h1:BkNrHpup+4k4w+ZZ86CZoHHEkohws8AY+WTX09nk+3A= -go.opentelemetry.io/otel/trace v1.43.0/go.mod h1:/QJhyVBUUswCphDVxq+8mld+AvhXZLhe+8WVFxiFff0= +go.opentelemetry.io/otel v1.44.0 h1:JjwHmHpA4iZ3wBxluu2fbbE7j4kqlE8jXyAyPXH7HqU= +go.opentelemetry.io/otel v1.44.0/go.mod h1:BMgjTHL9WPRlRjL2oZCBTL4whCGtXch2H4BhOPIAyYc= +go.opentelemetry.io/otel/metric v1.44.0 h1:1w0gILTcHdr3YI+ixLyjemwrVnsMURbTZFrSYCdDdmc= +go.opentelemetry.io/otel/metric v1.44.0/go.mod h1:8O7hanEPBNgEMmybD3s2VBKcgWOCsA6tzHBPODAiquo= +go.opentelemetry.io/otel/sdk v1.44.0 h1:nHYwb9lK+fJPU/dnT6s7W7Z8itMWyqrnVfbheVYrZ58= +go.opentelemetry.io/otel/sdk v1.44.0/go.mod h1:Osuydd3Se74nqjAKxid74N5eC+jfEqfTegHRnq58oK0= +go.opentelemetry.io/otel/sdk/metric v1.43.0 h1:S88dyqXjJkuBNLeMcVPRFXpRw2fuwdvfCGLEo89fDkw= +go.opentelemetry.io/otel/sdk/metric v1.43.0/go.mod h1:C/RJtwSEJ5hzTiUz5pXF1kILHStzb9zFlIEe85bhj6A= +go.opentelemetry.io/otel/trace v1.44.0 h1:jxF5CsGYCe74MCRx2X4g7WsY/VBKRqqpNvXlX/6gtIk= +go.opentelemetry.io/otel/trace v1.44.0/go.mod h1:oLl1jrMQAVo6v3GAggN+1VH9VIz9iUSvW53sW1Q8PIE= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.yaml.in/yaml/v2 v2.4.4 h1:tuyd0P+2Ont/d6e2rl3be67goVK4R6deVxCUX5vyPaQ= @@ -193,42 +195,42 @@ go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBs go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.50.0 h1:zO47/JPrL6vsNkINmLoo/PH1gcxpls50DNogFvB5ZGI= -golang.org/x/crypto v0.50.0/go.mod h1:3muZ7vA7PBCE6xgPX7nkzzjiUq87kRItoJQM1Yo8S+Q= +golang.org/x/crypto v0.53.0 h1:QZ4Muo8THX6CizN2vPPd5fBGHyogrdK9fG4wLPFUsto= +golang.org/x/crypto v0.53.0/go.mod h1:DNLU434OwVakk9PzuwV8w62mAJpRJL3vsgcfp4Qnsio= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.53.0 h1:d+qAbo5L0orcWAr0a9JweQpjXF19LMXJE8Ey7hwOdUA= -golang.org/x/net v0.53.0/go.mod h1:JvMuJH7rrdiCfbeHoo3fCQU24Lf5JJwT9W3sJFulfgs= +golang.org/x/net v0.56.0 h1:Rw8j/hFzGvJUZwNBXnAtf5sVDVt+65SK2C7IxCxZt5o= +golang.org/x/net v0.56.0/go.mod h1:D3Ku6r+V6JROoZK144D2XfMHFcMq/0zSfLelVTCFKec= golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs= golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= -golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= +golang.org/x/sync v0.21.0 h1:HLII4xRRTtCRkxYp4HNFF0Js/Og6q2i++KXbg0gHCwM= +golang.org/x/sync v0.21.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI= -golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/sys v0.46.0 h1:noSf2Fq6F8DBgS+LysIkx7rIExoNHJsxOAtPp4rthXw= +golang.org/x/sys v0.46.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg= -golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164= +golang.org/x/text v0.38.0 h1:sXmwo9DwP3OK9EZ7PqAdaooSGozfl/3a6/xJcbzPRhE= +golang.org/x/text v0.38.0/go.mod h1:YXZt3QhHUKYT53r2lLKFIVi6Ao1jdzrTR/KQ09qyxF4= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4= gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260420184626-e10c466a9529 h1:XF8+t6QQiS0o9ArVan/HW8Q7cycNPGsJf6GA2nXxYAg= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260420184626-e10c466a9529/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= -google.golang.org/grpc v1.80.0 h1:Xr6m2WmWZLETvUNvIUmeD5OAagMw3FiKmMlTdViWsHM= -google.golang.org/grpc v1.80.0/go.mod h1:ho/dLnxwi3EDJA4Zghp7k2Ec1+c2jqup0bFkw07bwF4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260622175928-b703f567277d h1:mpAgMyM9vQHxycBlDq50y1VHpfSfVwzXvrQKtYbXuUY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260622175928-b703f567277d/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= +google.golang.org/grpc v1.81.1 h1:VnnIIZ88UzOOKLukQi+ImGz8O1Wdp8nAGGnvOfEIWQQ= +google.golang.org/grpc v1.81.1/go.mod h1:xGH9GfzOyMTGIOXBJmXt+BX/V0kcdQbdcuwQ/zNw42I= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=