From f25d97a2e2859ca9adf9bb0acb5183bfcbc2d384 Mon Sep 17 00:00:00 2001 From: Ilja Rotar Date: Fri, 26 Jun 2026 13:47:13 +0200 Subject: [PATCH 01/15] check admin status instead of actual status --- cmd/internal/core/reconfigure-switch.go | 2 +- cmd/internal/switcher/sonic/db/configdb.go | 4 + .../switcher/sonic/db/configdb_test.go | 59 +++++++ go.mod | 71 ++++---- go.sum | 162 +++++++++--------- 5 files changed, 182 insertions(+), 116 deletions(-) diff --git a/cmd/internal/core/reconfigure-switch.go b/cmd/internal/core/reconfigure-switch.go index b7a74fd6..0b6d0c4d 100644 --- a/cmd/internal/core/reconfigure-switch.go +++ b/cmd/internal/core/reconfigure-switch.go @@ -172,7 +172,7 @@ func (c *Core) buildSwitcherConfig(s *models.V1SwitchResponse) (*types.Conf, err continue } - if isPortStatusEqual(models.V1SwitchNicActualDOWN, nic.Actual) { + if isPortStatusEqual(models.V1SwitchNicActualDOWN, nic.AdminStatus) { if has := p.DownPorts[port]; !has { p.DownPorts[port] = true } diff --git a/cmd/internal/switcher/sonic/db/configdb.go b/cmd/internal/switcher/sonic/db/configdb.go index 9a47db2f..787beb47 100644 --- a/cmd/internal/switcher/sonic/db/configdb.go +++ b/cmd/internal/switcher/sonic/db/configdb.go @@ -347,6 +347,10 @@ func (d *ConfigDB) SetPortMtu(ctx context.Context, interfaceName string, val str return d.c.HSet(ctx, key, Val{mtu: val}) } +func (d *ConfigDB) GetAdminStatusUp(ctx context.Context, interfaceName string) (bool, error) { + return false, nil +} + func (d *ConfigDB) SetAdminStatusUp(ctx context.Context, interfaceName string, up bool) error { key := Key{portTable, interfaceName} diff --git a/cmd/internal/switcher/sonic/db/configdb_test.go b/cmd/internal/switcher/sonic/db/configdb_test.go index 60241a4c..c1d806b3 100644 --- a/cmd/internal/switcher/sonic/db/configdb_test.go +++ b/cmd/internal/switcher/sonic/db/configdb_test.go @@ -1881,3 +1881,62 @@ func TestConfigDB_SetAdminStatusUp(t *testing.T) { }) } } + +func TestConfigDB_GetAdminStatusUp(t *testing.T) { + tests := []struct { + name string + data test.StringMap + interfaceName string + want bool + }{ + { + name: "interface is up", + 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", + }, + }, + }, + interfaceName: "Ethernet0", + want: false, + }, + } + 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.GetAdminStatusUp(ctx, tt.interfaceName) + require.NoError(t, err) + if got != tt.want { + t.Errorf("ConfigDB.GetAdminStatusUp() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/go.mod b/go.mod index 9ae6bd0e..ffdc7a9a 100644 --- a/go.mod +++ b/go.mod @@ -9,16 +9,16 @@ 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.44.2-0.20260626113536-3df3908ace8b + github.com/metal-stack/metal-go v0.44.2-0.20260626114417-9780469ed2b6 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 +26,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 +63,32 @@ 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/metal-lib v0.25.1 // 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..309eff87 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.44.2-0.20260626113536-3df3908ace8b h1:q8D2/3FfGlqPheNlbWD1b5haQ7vkftinOPfQ4qJS67o= +github.com/metal-stack/metal-api v0.44.2-0.20260626113536-3df3908ace8b/go.mod h1:BFJEO2ALpSYy/ebUMzffunY/3gmcJGNqKJHWDCH34RI= +github.com/metal-stack/metal-go v0.44.2-0.20260626114417-9780469ed2b6 h1:J76PbDu8Fw96zPAkseqaK3VYGD5dUmQy1wEGVzGB4S0= +github.com/metal-stack/metal-go v0.44.2-0.20260626114417-9780469ed2b6/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= From 97fe64892e9f43e7975c5cd5535b0352709a9fb0 Mon Sep 17 00:00:00 2001 From: Ilja Rotar Date: Tue, 30 Jun 2026 11:34:33 +0200 Subject: [PATCH 02/15] use running instead of admin state of a nic --- cmd/internal/core/reconfigure-switch.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/cmd/internal/core/reconfigure-switch.go b/cmd/internal/core/reconfigure-switch.go index 0b6d0c4d..6baa2383 100644 --- a/cmd/internal/core/reconfigure-switch.go +++ b/cmd/internal/core/reconfigure-switch.go @@ -275,14 +275,12 @@ 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 + return nic.Flags&net.FlagRunning != 0, nil } func isPortStatusEqual(stat string, other *string) bool { From 81907e40691c3657bbac38696ddf9323a75173d1 Mon Sep 17 00:00:00 2001 From: Ilja Rotar Date: Tue, 30 Jun 2026 12:48:53 +0200 Subject: [PATCH 03/15] log switch notify request --- cmd/internal/core/reconfigure-switch.go | 1 + 1 file changed, 1 insertion(+) diff --git a/cmd/internal/core/reconfigure-switch.go b/cmd/internal/core/reconfigure-switch.go index 6baa2383..f49c67f0 100644 --- a/cmd/internal/core/reconfigure-switch.go +++ b/cmd/internal/core/reconfigure-switch.go @@ -91,6 +91,7 @@ func (c *Core) ConstantlyReconfigureSwitch(ctx context.Context, interval, timeou } params.Body = nr + c.log.Debug("notify switch", "request", nr) _, err = c.driver.SwitchOperations().NotifySwitch(params, nil) if err != nil { c.log.Error("notification about switch reconfiguration failed", "error", err) From a854219fdc5311e7963c813289570e8ed8f84b59 Mon Sep 17 00:00:00 2001 From: Ilja Rotar Date: Tue, 30 Jun 2026 13:42:13 +0200 Subject: [PATCH 04/15] print nic flags for debug --- cmd/internal/core/reconfigure-switch.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cmd/internal/core/reconfigure-switch.go b/cmd/internal/core/reconfigure-switch.go index f49c67f0..e67ab04a 100644 --- a/cmd/internal/core/reconfigure-switch.go +++ b/cmd/internal/core/reconfigure-switch.go @@ -281,6 +281,8 @@ func isLinkUp(nicname string) (bool, error) { if err != nil { return false, fmt.Errorf("cannot query interface %q : %w", nicname, err) } + // FIXME: remove log + fmt.Printf("%s: %v\n", nicname, nic.Flags) return nic.Flags&net.FlagRunning != 0, nil } From ed4c7969ba1d31aa07abf79905bf5196902c08d6 Mon Sep 17 00:00:00 2001 From: Ilja Rotar Date: Tue, 30 Jun 2026 15:57:22 +0200 Subject: [PATCH 05/15] debug log for down ports --- cmd/internal/core/reconfigure-switch.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cmd/internal/core/reconfigure-switch.go b/cmd/internal/core/reconfigure-switch.go index e67ab04a..0d711ef1 100644 --- a/cmd/internal/core/reconfigure-switch.go +++ b/cmd/internal/core/reconfigure-switch.go @@ -174,6 +174,7 @@ func (c *Core) buildSwitcherConfig(s *models.V1SwitchResponse) (*types.Conf, err } if isPortStatusEqual(models.V1SwitchNicActualDOWN, nic.AdminStatus) { + c.log.Debug("port was administratively shutdown", "port", nic.Name) if has := p.DownPorts[port]; !has { p.DownPorts[port] = true } @@ -281,8 +282,6 @@ func isLinkUp(nicname string) (bool, error) { if err != nil { return false, fmt.Errorf("cannot query interface %q : %w", nicname, err) } - // FIXME: remove log - fmt.Printf("%s: %v\n", nicname, nic.Flags) return nic.Flags&net.FlagRunning != 0, nil } From 493f88f4a77a47495954d85da77bfc709a9405c0 Mon Sep 17 00:00:00 2001 From: Ilja Rotar Date: Tue, 30 Jun 2026 15:58:53 +0200 Subject: [PATCH 06/15] remove switch notify request log --- cmd/internal/core/reconfigure-switch.go | 1 - 1 file changed, 1 deletion(-) diff --git a/cmd/internal/core/reconfigure-switch.go b/cmd/internal/core/reconfigure-switch.go index 0d711ef1..48f86d1b 100644 --- a/cmd/internal/core/reconfigure-switch.go +++ b/cmd/internal/core/reconfigure-switch.go @@ -91,7 +91,6 @@ func (c *Core) ConstantlyReconfigureSwitch(ctx context.Context, interval, timeou } params.Body = nr - c.log.Debug("notify switch", "request", nr) _, err = c.driver.SwitchOperations().NotifySwitch(params, nil) if err != nil { c.log.Error("notification about switch reconfiguration failed", "error", err) From 23fc084532ba19e28f0b6718be9621eba740f2f2 Mon Sep 17 00:00:00 2001 From: Ilja Rotar Date: Tue, 30 Jun 2026 16:02:48 +0200 Subject: [PATCH 07/15] fix flaky test --- cmd/internal/switcher/sonic/db/configdb_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/cmd/internal/switcher/sonic/db/configdb_test.go b/cmd/internal/switcher/sonic/db/configdb_test.go index c1d806b3..c4dc0c83 100644 --- a/cmd/internal/switcher/sonic/db/configdb_test.go +++ b/cmd/internal/switcher/sonic/db/configdb_test.go @@ -891,6 +891,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) From dc1f76ecc8d88ac58724d9090c274f909ed9128c Mon Sep 17 00:00:00 2001 From: Ilja Rotar Date: Tue, 30 Jun 2026 16:07:05 +0200 Subject: [PATCH 08/15] log port admin state --- cmd/internal/core/reconfigure-switch.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cmd/internal/core/reconfigure-switch.go b/cmd/internal/core/reconfigure-switch.go index 48f86d1b..52c18cf2 100644 --- a/cmd/internal/core/reconfigure-switch.go +++ b/cmd/internal/core/reconfigure-switch.go @@ -168,12 +168,14 @@ func (c *Core) buildSwitcherConfig(s *models.V1SwitchResponse) (*types.Conf, err for _, nic := range s.Nics { port := *nic.Name + fmt.Printf("%s: %v\n", port, nic.AdminStatus) + if slices.Contains(p.Underlay, port) { continue } if isPortStatusEqual(models.V1SwitchNicActualDOWN, nic.AdminStatus) { - c.log.Debug("port was administratively shutdown", "port", nic.Name) + c.log.Debug("port was administratively shutdown", "port", port) if has := p.DownPorts[port]; !has { p.DownPorts[port] = true } From ceee83f82bfd969d3a284b9ead25d25460e14cb2 Mon Sep 17 00:00:00 2001 From: Ilja Rotar Date: Wed, 1 Jul 2026 09:28:49 +0200 Subject: [PATCH 09/15] remove log --- cmd/internal/core/reconfigure-switch.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/cmd/internal/core/reconfigure-switch.go b/cmd/internal/core/reconfigure-switch.go index 52c18cf2..94f1b589 100644 --- a/cmd/internal/core/reconfigure-switch.go +++ b/cmd/internal/core/reconfigure-switch.go @@ -167,9 +167,6 @@ func (c *Core) buildSwitcherConfig(s *models.V1SwitchResponse) (*types.Conf, err for _, nic := range s.Nics { port := *nic.Name - - fmt.Printf("%s: %v\n", port, nic.AdminStatus) - if slices.Contains(p.Underlay, port) { continue } From 726a28745cb281375589dd4b15535e3569349793 Mon Sep 17 00:00:00 2001 From: Ilja Rotar Date: Thu, 2 Jul 2026 11:52:56 +0200 Subject: [PATCH 10/15] get rid of downports and bool port status --- cmd/internal/core/reconfigure-switch.go | 24 ++-- cmd/internal/core/reconfigure-switch_test.go | 2 +- cmd/internal/switcher/sonic/db/configdb.go | 34 ++--- .../switcher/sonic/db/configdb_test.go | 79 +++++++----- cmd/internal/switcher/sonic/redis/applier.go | 27 ++-- cmd/internal/switcher/sonic/redis/port.go | 10 +- .../conf_with_downports.yaml | 13 +- .../interfaces_with_downports | 17 +-- cmd/internal/switcher/types/conf.go | 91 +++++++------ cmd/internal/switcher/types/types.go | 122 +++++++++--------- 10 files changed, 234 insertions(+), 185 deletions(-) diff --git a/cmd/internal/core/reconfigure-switch.go b/cmd/internal/core/reconfigure-switch.go index 94f1b589..0e0c8cd4 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.AdminStatus) { - c.log.Debug("port was administratively shutdown", "port", port) - if has := p.DownPorts[port]; !has { - p.DownPorts[port] = true - } + adminStatus := types.PortStatus(strings.ToLower(pointer.SafeDeref(nic.AdminStatus))) + if adminStatus == types.PortStatusDown || adminStatus == types.PortStatusUp { + p.AdminStatus[port] = types.PortStatus(adminStatus) } if slices.Contains(c.additionalBridgePorts, port) { @@ -282,10 +285,3 @@ func isLinkUp(nicname string) (bool, error) { } return nic.Flags&net.FlagRunning != 0, nil } - -func isPortStatusEqual(stat string, other *string) bool { - if other == nil { - return false - } - return strings.EqualFold(stat, *other) -} 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 787beb47..adeec49e 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,16 +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) GetAdminStatusUp(ctx context.Context, interfaceName string) (bool, error) { - return false, nil -} - -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 "", nil + } + + 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 nil } - return d.c.HSet(ctx, key, Val{adminStatus: status}) + 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 c4dc0c83..eb1c4c9d 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" ) @@ -1652,7 +1653,7 @@ func TestConfigDB_GetPort(t *testing.T) { want: &Port{ Name: "Ethernet1", Alias: "Eth1/2", - AdminStatus: true, + AdminStatus: string(types.PortStatusUp), Mtu: "9000", }, }, @@ -1698,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", }, }, @@ -1817,14 +1818,14 @@ func TestConfigDB_SetAdminStatusUp(t *testing.T) { name string data test.StringMap interfaceName string - up bool + status types.PortStatus mods func(test.HashMap) }{ { 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", @@ -1835,14 +1836,14 @@ 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" }, @@ -1872,7 +1873,7 @@ func TestConfigDB_SetAdminStatusUp(t *testing.T) { d := &ConfigDB{ c: c, } - err = d.SetAdminStatusUp(ctx, tt.interfaceName, tt.up) + err = d.SetAdminStatus(ctx, tt.interfaceName, tt.status) require.NoError(t, err) data, err := test.GetData(ctx, vc, sep) require.NoError(t, err) @@ -1883,35 +1884,49 @@ func TestConfigDB_SetAdminStatusUp(t *testing.T) { } } -func TestConfigDB_GetAdminStatusUp(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 bool + want types.PortStatus }{ { - name: "interface is up", - 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", - }, - }, - }, + name: "interface is up", + data: data, interfaceName: "Ethernet0", - want: false, + 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 { @@ -1933,10 +1948,10 @@ func TestConfigDB_GetAdminStatusUp(t *testing.T) { d := &ConfigDB{ c: c, } - got, err := d.GetAdminStatusUp(ctx, tt.interfaceName) + got, err := d.GetAdminStatus(ctx, tt.interfaceName) require.NoError(t, err) if got != tt.want { - t.Errorf("ConfigDB.GetAdminStatusUp() = %v, want %v", 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..03c551a0 100644 --- a/cmd/internal/switcher/sonic/redis/applier.go +++ b/cmd/internal/switcher/sonic/redis/applier.go @@ -34,7 +34,7 @@ func NewApplier(log *slog.Logger, db *db.DB) *Applier { func (a *Applier) Apply(ctx context.Context, cfg *types.Conf) error { var errs []error - // only process if changes are detected + // TODO: get down ports from DB and compare with expected if a.previousCfg != nil { diff := cmp.Diff(a.previousCfg, cfg) if diff == "" { @@ -50,7 +50,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 +58,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,7 +76,7 @@ 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) } } @@ -131,42 +131,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 +176,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..3a39931e 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) { + 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) From 8887d26496e7bf9f8cb958a20de7d9c9b255eae4 Mon Sep 17 00:00:00 2001 From: Ilja Rotar Date: Thu, 2 Jul 2026 16:22:30 +0200 Subject: [PATCH 11/15] compare desired port states current admin states in configDB --- cmd/internal/switcher/sonic/redis/applier.go | 30 ++++++++++++++++---- cmd/internal/switcher/sonic/redis/port.go | 2 +- go.mod | 2 +- 3 files changed, 26 insertions(+), 8 deletions(-) diff --git a/cmd/internal/switcher/sonic/redis/applier.go b/cmd/internal/switcher/sonic/redis/applier.go index 03c551a0..b4fc60ed 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 + ) - // TODO: get down ports from DB and compare with expected 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 + 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 { @@ -82,7 +100,7 @@ func (a *Applier) Apply(ctx context.Context, cfg *types.Conf) error { } } - err := a.cleanupVrfs(ctx, cfg) + err = a.cleanupVrfs(ctx, cfg) if err != nil { errs = append(errs, err) } diff --git a/cmd/internal/switcher/sonic/redis/port.go b/cmd/internal/switcher/sonic/redis/port.go index 3a39931e..df22ea90 100644 --- a/cmd/internal/switcher/sonic/redis/port.go +++ b/cmd/internal/switcher/sonic/redis/port.go @@ -24,7 +24,7 @@ func (a *Applier) ensurePortConfiguration(ctx context.Context, portName, mtu str } } - if p.AdminStatus != string(adminStatus) { + 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) } diff --git a/go.mod b/go.mod index ffdc7a9a..22ce57a0 100644 --- a/go.mod +++ b/go.mod @@ -11,6 +11,7 @@ require ( github.com/metal-stack/go-lldpd v0.4.12 github.com/metal-stack/metal-api v0.44.2-0.20260626113536-3df3908ace8b github.com/metal-stack/metal-go v0.44.2-0.20260626114417-9780469ed2b6 + 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 @@ -68,7 +69,6 @@ require ( 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.1 // 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 From 8bdc6a04016b41835047c61ff883845d4f165ba1 Mon Sep 17 00:00:00 2001 From: Ilja Rotar Date: Thu, 2 Jul 2026 16:39:04 +0200 Subject: [PATCH 12/15] fix wrong condition --- cmd/internal/switcher/sonic/redis/applier.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/internal/switcher/sonic/redis/applier.go b/cmd/internal/switcher/sonic/redis/applier.go index b4fc60ed..a391e53a 100644 --- a/cmd/internal/switcher/sonic/redis/applier.go +++ b/cmd/internal/switcher/sonic/redis/applier.go @@ -39,7 +39,7 @@ func (a *Applier) Apply(ctx context.Context, cfg *types.Conf) error { if a.previousCfg != nil { diff := cmp.Diff(a.previousCfg, cfg) - if diff == "" { + if diff != "" { changed = true a.log.Debug("interface changes", "changes", diff) } From e8bb39a13ef8c13003ecf3dd5fa0ac99539c7164 Mon Sep 17 00:00:00 2001 From: Ilja Rotar Date: Wed, 15 Jul 2026 16:00:11 +0200 Subject: [PATCH 13/15] pin metal-api and metal-go --- cmd/internal/core/reconfigure-switch.go | 2 +- go.mod | 4 ++-- go.sum | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/cmd/internal/core/reconfigure-switch.go b/cmd/internal/core/reconfigure-switch.go index 0e0c8cd4..e03c020d 100644 --- a/cmd/internal/core/reconfigure-switch.go +++ b/cmd/internal/core/reconfigure-switch.go @@ -176,7 +176,7 @@ func (c *Core) buildSwitcherConfig(s *models.V1SwitchResponse) (*types.Conf, err continue } - adminStatus := types.PortStatus(strings.ToLower(pointer.SafeDeref(nic.AdminStatus))) + adminStatus := types.PortStatus(strings.ToLower(nic.AdminStatus)) if adminStatus == types.PortStatusDown || adminStatus == types.PortStatusUp { p.AdminStatus[port] = types.PortStatus(adminStatus) } diff --git a/go.mod b/go.mod index 22ce57a0..b1b162d4 100644 --- a/go.mod +++ b/go.mod @@ -9,8 +9,8 @@ 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.44.2-0.20260626113536-3df3908ace8b - github.com/metal-stack/metal-go v0.44.2-0.20260626114417-9780469ed2b6 + 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 diff --git a/go.sum b/go.sum index 309eff87..5566244a 100644 --- a/go.sum +++ b/go.sum @@ -127,10 +127,10 @@ 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.44.2-0.20260626113536-3df3908ace8b h1:q8D2/3FfGlqPheNlbWD1b5haQ7vkftinOPfQ4qJS67o= -github.com/metal-stack/metal-api v0.44.2-0.20260626113536-3df3908ace8b/go.mod h1:BFJEO2ALpSYy/ebUMzffunY/3gmcJGNqKJHWDCH34RI= -github.com/metal-stack/metal-go v0.44.2-0.20260626114417-9780469ed2b6 h1:J76PbDu8Fw96zPAkseqaK3VYGD5dUmQy1wEGVzGB4S0= -github.com/metal-stack/metal-go v0.44.2-0.20260626114417-9780469ed2b6/go.mod h1:GSfXrAj55LGsUSMHWGDsmq5n056NG0yb1JM8bgfvKOw= +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= From 4db5b7c0ec222eafa99c0bf8752e70135ef5c1a2 Mon Sep 17 00:00:00 2001 From: Ilja Rotar <77339620+iljarotar@users.noreply.github.com> Date: Thu, 16 Jul 2026 12:48:59 +0200 Subject: [PATCH 14/15] Update cmd/internal/switcher/sonic/db/configdb.go Co-authored-by: Markus Wennrich --- cmd/internal/switcher/sonic/db/configdb.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/internal/switcher/sonic/db/configdb.go b/cmd/internal/switcher/sonic/db/configdb.go index adeec49e..e5ee0481 100644 --- a/cmd/internal/switcher/sonic/db/configdb.go +++ b/cmd/internal/switcher/sonic/db/configdb.go @@ -351,7 +351,7 @@ func (d *ConfigDB) GetAdminStatus(ctx context.Context, interfaceName string) (ty status, err := d.c.HGet(ctx, key, adminStatusField) if err != nil { - return "", nil + return "", err } return types.PortStatus(status), nil From a0dfbcc05008ba1f889a398cbdbcc6adf72569ce Mon Sep 17 00:00:00 2001 From: Ilja Rotar Date: Fri, 17 Jul 2026 11:35:53 +0200 Subject: [PATCH 15/15] return error when admin status is not up or down --- cmd/internal/switcher/sonic/db/configdb.go | 2 +- cmd/internal/switcher/sonic/db/configdb_test.go | 12 +++++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/cmd/internal/switcher/sonic/db/configdb.go b/cmd/internal/switcher/sonic/db/configdb.go index e5ee0481..c6f9452d 100644 --- a/cmd/internal/switcher/sonic/db/configdb.go +++ b/cmd/internal/switcher/sonic/db/configdb.go @@ -359,7 +359,7 @@ func (d *ConfigDB) GetAdminStatus(ctx context.Context, interfaceName string) (ty func (d *ConfigDB) SetAdminStatus(ctx context.Context, interfaceName string, adminStatus types.PortStatus) error { if adminStatus != types.PortStatusDown && adminStatus != types.PortStatusUp { - return nil + 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 eb1c4c9d..be38aa0a 100644 --- a/cmd/internal/switcher/sonic/db/configdb_test.go +++ b/cmd/internal/switcher/sonic/db/configdb_test.go @@ -1820,6 +1820,7 @@ func TestConfigDB_SetAdminStatusUp(t *testing.T) { interfaceName string status types.PortStatus mods func(test.HashMap) + wantErr bool }{ { name: "set on non-existing", @@ -1848,6 +1849,13 @@ func TestConfigDB_SetAdminStatusUp(t *testing.T) { 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) { @@ -1874,7 +1882,9 @@ func TestConfigDB_SetAdminStatusUp(t *testing.T) { c: c, } err = d.SetAdminStatus(ctx, tt.interfaceName, tt.status) - require.NoError(t, err) + 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 != "" {