diff --git a/Makefile b/Makefile index 5a143f79..dcf7c053 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ GITVERSION := $(shell git describe --long --all) BUILDDATE := $(shell date -Iseconds) VERSION := $(or ${VERSION},$(shell git describe --tags --exact-match 2> /dev/null || git symbolic-ref -q --short HEAD || git rev-parse --short HEAD)) -CONTROLLER_TOOLS_VERSION ?= v0.18.0 +CONTROLLER_TOOLS_VERSION ?= v0.21.0 LOCALBIN ?= $(shell pwd)/bin CONTROLLER_GEN ?= $(LOCALBIN)/controller-gen MOCKERY ?= $(LOCALBIN)/mockery @@ -89,4 +89,4 @@ go-mocks: --tmpfs /.cache:uid=$$(id -u),gid=$$(id -g) \ -w /work \ -v ${PWD}:/work \ - vektra/mockery:v3.6.4 \ No newline at end of file + vektra/mockery:v3.7.2 \ No newline at end of file diff --git a/api/v1/clusterwidenetworkpolicy_types.go b/api/v1/clusterwidenetworkpolicy_types.go index 740df40f..725f185d 100644 --- a/api/v1/clusterwidenetworkpolicy_types.go +++ b/api/v1/clusterwidenetworkpolicy_types.go @@ -287,7 +287,3 @@ func validateIPBlocks(blocks []networking.IPBlock) error { } return errors.Join(errs...) } - -func init() { - SchemeBuilder.Register(&ClusterwideNetworkPolicy{}, &ClusterwideNetworkPolicyList{}) -} diff --git a/api/v1/groupversion_info.go b/api/v1/groupversion_info.go index c1dd2632..2ed5e8e8 100644 --- a/api/v1/groupversion_info.go +++ b/api/v1/groupversion_info.go @@ -4,8 +4,9 @@ package v1 import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" - "sigs.k8s.io/controller-runtime/pkg/scheme" ) var ( @@ -13,15 +14,18 @@ var ( GroupVersion = schema.GroupVersion{Group: "metal-stack.io", Version: "v1"} // SchemeBuilder is used to add go types to the GroupVersionKind scheme - SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} + SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) // AddToScheme adds the types in this group-version to the given scheme. AddToScheme = SchemeBuilder.AddToScheme ) -func init() { - SchemeBuilder.Register( +func addKnownTypes(scheme *runtime.Scheme) error { + scheme.AddKnownTypes(GroupVersion, &ClusterwideNetworkPolicy{}, &ClusterwideNetworkPolicyList{}, ) + + metav1.AddToGroupVersion(scheme, GroupVersion) + return nil } diff --git a/config/crd/bases/metal-stack.io_clusterwidenetworkpolicies.yaml b/config/crd/bases/metal-stack.io_clusterwidenetworkpolicies.yaml index 18ac0e7c..9d507344 100644 --- a/config/crd/bases/metal-stack.io_clusterwidenetworkpolicies.yaml +++ b/config/crd/bases/metal-stack.io_clusterwidenetworkpolicies.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.18.0 + controller-gen.kubebuilder.io/version: v0.21.0 name: clusterwidenetworkpolicies.metal-stack.io spec: group: metal-stack.io diff --git a/controllers/clusterwidenetworkpolicy_controller.go b/controllers/clusterwidenetworkpolicy_controller.go index 3fba5316..9441c902 100644 --- a/controllers/clusterwidenetworkpolicy_controller.go +++ b/controllers/clusterwidenetworkpolicy_controller.go @@ -7,6 +7,7 @@ import ( "go4.org/netipx" + apiv2 "github.com/metal-stack/api/go/metalstack/api/v2" "github.com/metal-stack/firewall-controller/v2/pkg/dns" "github.com/metal-stack/firewall-controller/v2/pkg/helper" "github.com/metal-stack/firewall-controller/v2/pkg/nftables" @@ -46,6 +47,9 @@ type ClusterwideNetworkPolicyReconciler struct { Interval time.Duration DnsProxy *dns.DNSProxy SkipDNS bool + + DefaultRouteIp string + MachineAllocation *apiv2.MachineAllocation } // SetupWithManager configures this controller to run in schedule @@ -106,7 +110,7 @@ func (r *ClusterwideNetworkPolicyReconciler) Reconcile(ctx context.Context, _ ct } cwnps.Items = validCwnps - nftablesFirewall := nftables.NewFirewall(f, &cwnps, &services, r.DnsProxy, r.Log, r.Recorder) + nftablesFirewall := nftables.NewFirewall(f, &cwnps, &services, r.DnsProxy, r.Log, r.Recorder, r.MachineAllocation) if err := r.manageDNSProxy(f, cwnps, nftablesFirewall); err != nil { return ctrl.Result{}, err } @@ -145,7 +149,14 @@ func (r *ClusterwideNetworkPolicyReconciler) manageDNSProxy( if enableDNS && r.DnsProxy == nil { r.Log.Info("DNS Proxy is initialized") - if r.DnsProxy, err = dns.NewDNSProxy(r.Ctx, f.Spec.DNSServerAddress, f.Spec.DNSPort, r.ShootClient, ctrl.Log.WithName("DNS proxy")); err != nil { + dnsProxyConfig := &dns.DNSProxyConfig{ + Log: ctrl.Log.WithName("DNS proxy"), + DNSServer: f.Spec.DNSServerAddress, + Port: f.Spec.DNSPort, + ShootClient: r.ShootClient, + BindAddress: r.DefaultRouteIp, + } + if r.DnsProxy, err = dns.NewDNSProxy(r.Ctx, dnsProxyConfig); err != nil { return fmt.Errorf("failed to init DNS proxy: %w", err) } go r.DnsProxy.Run() diff --git a/controllers/firewall_controller.go b/controllers/firewall_controller.go index 63f84754..57fb3afc 100644 --- a/controllers/firewall_controller.go +++ b/controllers/firewall_controller.go @@ -11,6 +11,7 @@ import ( "github.com/Masterminds/semver/v3" "github.com/go-logr/logr" + apiv2 "github.com/metal-stack/api/go/metalstack/api/v2" mn "github.com/metal-stack/metal-lib/pkg/net" corev1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" @@ -52,7 +53,8 @@ type FirewallReconciler struct { SeedUpdatedFunc func() - FrrVersion *semver.Version + FrrVersion *semver.Version + MachineAllocation *apiv2.MachineAllocation } const ( @@ -90,7 +92,14 @@ func (r *FirewallReconciler) Reconcile(ctx context.Context, req ctrl.Request) (c if apierrors.IsNotFound(err) { r.Log.Info("flushing k8s firewall rules") - defaultFw := nftables.NewFirewall(&firewallv2.Firewall{}, &firewallv1.ClusterwideNetworkPolicyList{}, &corev1.ServiceList{}, nil, logr.Discard(), r.Recorder) + defaultFw := nftables.NewFirewall( + &firewallv2.Firewall{}, + &firewallv1.ClusterwideNetworkPolicyList{}, + &corev1.ServiceList{}, + nil, logr.Discard(), + r.Recorder, + r.MachineAllocation, + ) flushErr := defaultFw.Flush() if flushErr != nil { @@ -119,7 +128,8 @@ func (r *FirewallReconciler) Reconcile(ctx context.Context, req ctrl.Request) (c r.Log.Info("reconciling network settings") var errs []error - changed, err := network.ReconcileNetwork(f, r.FrrVersion) + nw := network.NewNetwork(r.Log, r.MachineAllocation) + changed, err := nw.ReconcileNetwork(f, r.FrrVersion) if changed && err == nil { r.recordFirewallEvent(f, corev1.EventTypeNormal, "Network settings", "reconciliation succeeded (frr.conf)") } else if changed && err != nil { diff --git a/go.mod b/go.mod index de55e10c..ac03adad 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/metal-stack/firewall-controller/v2 -go 1.26 +go 1.26.0 require ( github.com/Masterminds/semver/v3 v3.5.0 @@ -10,41 +10,48 @@ require ( github.com/google/go-cmp v0.7.0 github.com/google/nftables v0.3.0 github.com/ks2211/go-suricata v0.0.0-20200823200910-986ce1470707 + github.com/metal-stack/api v0.4.4 github.com/metal-stack/firewall-controller-manager v0.6.1 - github.com/metal-stack/metal-go v0.45.0 github.com/metal-stack/metal-lib v0.26.1 - github.com/metal-stack/metal-networker v0.47.0 + github.com/metal-stack/os-installer v0.3.1 github.com/metal-stack/v v1.0.3 github.com/miekg/dns v1.1.72 github.com/stretchr/testify v1.11.1 github.com/txn2/txeh v1.8.1 github.com/vishvananda/netlink v1.3.1 go4.org/netipx v0.0.0-20231129151722-fdeea329fbba - k8s.io/api v0.35.0 - k8s.io/apiextensions-apiserver v0.35.0 - k8s.io/apimachinery v0.35.0 - k8s.io/client-go v0.35.0 - sigs.k8s.io/controller-runtime v0.23.0 + k8s.io/api v0.36.3 + k8s.io/apiextensions-apiserver v0.36.3 + k8s.io/apimachinery v0.36.3 + k8s.io/client-go v0.36.3 + sigs.k8s.io/controller-runtime v0.24.1 sigs.k8s.io/yaml v1.6.0 ) replace github.com/imdario/mergo => dario.cat/mergo v1.0.0 require ( + buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.11-20260709200747-435963d16310.1 // indirect + buf.build/go/protovalidate v1.2.0 // indirect + buf.build/go/protoyaml v0.7.0 // indirect + cel.dev/expr v0.25.2 // indirect + dario.cat/mergo v1.0.2 // indirect + github.com/Masterminds/goutils v1.1.1 // indirect + github.com/Masterminds/sprig/v3 v3.3.0 // indirect + github.com/ajeddeloh/go-json v0.0.0-20200220154158-5ae607161559 // indirect + github.com/antlr4-go/antlr/v4 v4.13.1 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/coreos/go-semver v0.3.1 // indirect + github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/emicklei/go-restful/v3 v3.13.0 // indirect github.com/evanphx/json-patch/v5 v5.9.11 // indirect + github.com/flatcar/ignition v0.36.2 // indirect github.com/fsnotify/fsnotify v1.10.1 // indirect github.com/fxamacker/cbor/v2 v2.9.2 // indirect - github.com/go-openapi/analysis v0.25.5 // indirect - github.com/go-openapi/errors v0.22.8 // indirect github.com/go-openapi/jsonpointer v1.0.0 // indirect github.com/go-openapi/jsonreference v1.0.0 // indirect - github.com/go-openapi/loads v0.25.0 // indirect - github.com/go-openapi/spec v0.22.9 // indirect - github.com/go-openapi/strfmt v0.27.0 // indirect github.com/go-openapi/swag v0.28.0 // indirect github.com/go-openapi/swag/cmdutils v0.28.0 // indirect github.com/go-openapi/swag/conv v0.28.0 // indirect @@ -57,34 +64,40 @@ require ( github.com/go-openapi/swag/stringutils v0.28.0 // indirect github.com/go-openapi/swag/typeutils v0.28.0 // indirect github.com/go-openapi/swag/yamlutils v0.28.0 // indirect - github.com/go-openapi/validate v0.26.1 // indirect - github.com/go-viper/mapstructure/v2 v2.5.0 // indirect github.com/godbus/dbus/v5 v5.2.2 // indirect - github.com/google/btree v1.1.3 // indirect + github.com/google/cel-go v0.30.0 // indirect github.com/google/gnostic-models v0.7.1 // indirect github.com/google/uuid v1.6.0 // indirect + github.com/huandu/xstrings v1.5.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/kr/text v0.2.0 // indirect github.com/mattn/go-colorable v0.1.15 // indirect github.com/mattn/go-isatty v0.0.24 // indirect github.com/mdlayher/netlink v1.11.2 // indirect github.com/mdlayher/socket v0.6.1 // indirect - github.com/metal-stack/metal-hammer v0.13.17 // indirect + github.com/mitchellh/copystructure v1.2.0 // indirect + github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect - github.com/oklog/ulid/v2 v2.1.2 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/prometheus/client_golang v1.24.1 // indirect github.com/prometheus/client_model v0.6.2 // indirect github.com/prometheus/common v0.70.1 // indirect github.com/prometheus/procfs v0.21.1 // indirect + github.com/samber/lo v1.53.0 // indirect + github.com/shopspring/decimal v1.4.0 // indirect + github.com/spf13/afero v1.15.0 // indirect + github.com/spf13/cast v1.10.0 // indirect github.com/spf13/pflag v1.0.10 // indirect github.com/stretchr/objx v0.5.3 // indirect + github.com/vincent-petithory/dataurl v1.0.0 // indirect github.com/vishvananda/netns v0.0.5 // indirect github.com/x448/float16 v0.8.4 // indirect go.yaml.in/yaml/v2 v2.4.4 // indirect go.yaml.in/yaml/v3 v3.0.5 // indirect + go4.org v0.0.0-20260112195520-a5071408f32f // indirect + golang.org/x/crypto v0.54.0 // indirect + golang.org/x/exp v0.0.0-20260727155853-b88d891fe743 // indirect golang.org/x/mod v0.38.0 // indirect golang.org/x/net v0.57.0 // indirect golang.org/x/oauth2 v0.36.0 // indirect @@ -95,14 +108,16 @@ require ( golang.org/x/time v0.15.0 // indirect golang.org/x/tools v0.48.0 // indirect gomodules.xyz/jsonpatch/v2 v2.5.0 // indirect - google.golang.org/protobuf v1.36.11 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260803160001-6ac0973c030d // indirect + google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af // indirect gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/klog/v2 v2.130.1 // indirect - k8s.io/kube-openapi v0.0.0-20251125145642-4e65d59e963e // indirect - k8s.io/utils v0.0.0-20260108192941-914a6e750570 // indirect + k8s.io/klog/v2 v2.140.0 // indirect + k8s.io/kube-openapi v0.0.0-20260317180543-43fb72c5454a // indirect + k8s.io/utils v0.0.0-20260210185600-b8788abfbbc2 // indirect sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect sigs.k8s.io/randfill v1.0.0 // indirect - sigs.k8s.io/structured-merge-diff/v6 v6.3.1 // indirect + sigs.k8s.io/structured-merge-diff/v6 v6.3.3 // indirect ) diff --git a/go.sum b/go.sum index 23bb8531..215dceed 100644 --- a/go.sum +++ b/go.sum @@ -1,26 +1,43 @@ -buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.6-20250425153114-8976f5be98c1.1 h1:YhMSc48s25kr7kv31Z8vf7sPUIq5YJva9z1mn/hAt0M= -buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.6-20250425153114-8976f5be98c1.1/go.mod h1:avRlCjnFzl98VPaeCtJ24RrV/wwHFzB8sWXhj26+n/U= -buf.build/go/protovalidate v0.11.0 h1:qmX+1Z/t5lqlxQW6bNHnCGE9kX6yXBNul0jYFjD2r3Q= -buf.build/go/protovalidate v0.11.0/go.mod h1:Ryhm9EyqOxO/jdqEBpH4mI/FUk2ULyYeuhR+QRhOgqc= +buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.11-20260709200747-435963d16310.1 h1:fXh8CsdNpjRr8R5vFdqtIxPt/Lno2IIJlYOdZBIZn0w= +buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.11-20260709200747-435963d16310.1/go.mod h1:tvtbpgaVXZX4g6Pn+AnzFycuRK3MOz5HJfEGeEllXYM= +buf.build/go/protovalidate v1.2.0 h1:DQVrUWkmGTBij+kOYv/x2LLxwcLaGKMdzShj1/6/3H0= +buf.build/go/protovalidate v1.2.0/go.mod h1:7rYiQEhqvAipoazpVNBBH2S2f8bjG4huMVy1V2Yofn4= buf.build/go/protoyaml v0.7.0 h1:z4oVoFicbpPefhT7WAykxUdfp0yEQlhMQ2mCZOY5V38= buf.build/go/protoyaml v0.7.0/go.mod h1:+a0cavd0uMvirb87xdu2ZMMmjlIQoiH/N2Ich5MGSQ0= -cel.dev/expr v0.25.1 h1:1KrZg61W6TWSxuNZ37Xy49ps13NUovb66QLprthtwi4= -cel.dev/expr v0.25.1/go.mod h1:hrXvqGP6G6gyx8UAHSHJ5RGk//1Oj5nXQ2NI02Nrsg4= +cel.dev/expr v0.25.2 h1:K6j46C81hXtZQfuX60cVWQFBJahKSE2gfRbNuvr5bFs= +cel.dev/expr v0.25.2/go.mod h1:hrXvqGP6G6gyx8UAHSHJ5RGk//1Oj5nXQ2NI02Nrsg4= +dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8= +dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA= +github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= +github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= github.com/Masterminds/semver/v3 v3.5.0 h1:kQceYJfbupGfZOKZQg0kou0DgAKhzDg2NZPAwZ/2OOE= github.com/Masterminds/semver/v3 v3.5.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= -github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8TVTI= -github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g= +github.com/Masterminds/sprig/v3 v3.3.0 h1:mQh0Yrg1XPo6vjYXgtf5OtijNAKJRNcTdOOGZe3tPhs= +github.com/Masterminds/sprig/v3 v3.3.0/go.mod h1:Zy1iXRYNqNLUolqCpL4uhk6SHUMAOSCzdgBfDb35Lz0= +github.com/ajeddeloh/go-json v0.0.0-20160803184958-73d058cf8437/go.mod h1:otnto4/Icqn88WCcM4bhIJNSgsh9VLBuspyyCfvof9c= +github.com/ajeddeloh/go-json v0.0.0-20200220154158-5ae607161559 h1:4SPQljF/GJ8Q+QlCWMWxRBepub4DresnOm4eI2ebFGc= +github.com/ajeddeloh/go-json v0.0.0-20200220154158-5ae607161559/go.mod h1:otnto4/Icqn88WCcM4bhIJNSgsh9VLBuspyyCfvof9c= +github.com/antlr4-go/antlr/v4 v4.13.1 h1:SqQKkuVZ+zWkMMNkjy5FZe5mr5WURWnlpmOuzYWrPrQ= +github.com/antlr4-go/antlr/v4 v4.13.1/go.mod h1:GKmUxMtwp6ZgGwZSva4eWPC5mS6vUAmOABFgjdkM7Nw= +github.com/aws/aws-sdk-go v1.8.39/go.mod h1:ZRmQr0FajVIyZ4ZzBYKG5P3ZqPz9IHG41ZoMu1ADI3k= 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/brianvoe/gofakeit/v6 v6.28.0 h1:Xib46XXuQfmlLS2EXRuJpqcw8St6qSZz75OUo0tgAW4= +github.com/brianvoe/gofakeit/v6 v6.28.0/go.mod h1:Xj58BMSnFqcn/fAQeSK+/PLtC5kSb7FJIq4JyGa8vEs= 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/clipperhouse/displaywidth v0.10.0 h1:GhBG8WuerxjFQQYeuZAeVTuyxuX+UraiZGD4HJQ3Y8g= github.com/clipperhouse/displaywidth v0.10.0/go.mod h1:XqJajYsaiEwkxOj4bowCTMcT1SgvHo9flfF3jQasdbs= github.com/clipperhouse/uax29/v2 v2.6.0 h1:z0cDbUV+aPASdFb2/ndFnS9ts/WNXgTNNGFoKXuhpos= github.com/clipperhouse/uax29/v2 v2.6.0/go.mod h1:Wn1g7MK6OoeDT0vL+Q0SQLDz/KpfsVRgg6W7ihQeh4g= +github.com/coreos/go-semver v0.1.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4= +github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec= +github.com/coreos/go-systemd v0.0.0-20181031085051-9002847aa142/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf h1:iW4rZ826su+pqaw19uhpSCzhj44qo35pNgKFGqzDKkU= +github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= 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/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= @@ -33,28 +50,27 @@ github.com/evanphx/json-patch/v5 v5.9.11 h1:/8HVnzMq13/3x9TPvjG08wUGqBTmZBsCWzjT github.com/evanphx/json-patch/v5 v5.9.11/go.mod h1:3j+LviiESTElxA4p3EMKAB9HXj3/XEtnUf6OZxqIQTM= github.com/fatih/color v1.19.0 h1:Zp3PiM21/9Ld6FzSKyL5c/BULoe/ONr9KlbYVOfG8+w= github.com/fatih/color v1.19.0/go.mod h1:zNk67I0ZUT1bEGsSGyCZYZNrHuTkJJB+r6Q9VuMi0LE= +github.com/flatcar/ignition v0.36.2 h1:xGHgScUe0P4Fkprjqv7L2CE58emiQgP833OCCn9z2v4= +github.com/flatcar/ignition v0.36.2/go.mod h1:uk1tpzLFRXus4RrvzgMI+IqmmB8a/RGFSBlI+tMTbbA= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.10.1 h1:b0/UzAf9yR5rhf3RPm9gf3ehBPpf0oZKIjtpKrx59Ho= github.com/fsnotify/fsnotify v1.10.1/go.mod h1:TLheqan6HD6GBK6PrDWyDPBaEV8LspOxvPSjC+bVfgo= github.com/fxamacker/cbor/v2 v2.9.2 h1:X4Ksno9+x3cz0TZv69ec1hxP/+tymuR8PXQJyDwfh78= github.com/fxamacker/cbor/v2 v2.9.2/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ= +github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= github.com/go-logr/logr v1.4.4 h1:tG4xh9yMsRCAiodLVTxyrkzSZ9+o0L1Kg/+cPVcbP/8= github.com/go-logr/logr v1.4.4/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg= -github.com/go-openapi/analysis v0.25.5 h1:xPYEvTb90o1y0epuiOPAoG4QqahjP3cdp5xNlHeKJRI= -github.com/go-openapi/analysis v0.25.5/go.mod h1:d3UGtQC5uq5Kqqqis2VH09Km/v3vwsWrYkbp4gdm+Rc= -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/errors v0.22.7 h1:JLFBGC0Apwdzw3484MmBqspjPbwa2SHvpDm0u5aGhUA= +github.com/go-openapi/errors v0.22.7/go.mod h1://QW6SD9OsWtH6gHllUCddOXDL0tk0ZGNYHwsw4sW3w= github.com/go-openapi/jsonpointer v1.0.0 h1:kR9tHqY0CtZaOPVFm622dPVNhrvYpwr4uCxgL3h1H8s= github.com/go-openapi/jsonpointer v1.0.0/go.mod h1:Z3rw7dWu1p9IgitXCFamSlA5lmDiklEB6vkaxcNZW5Y= github.com/go-openapi/jsonreference v1.0.0 h1:jlmTr6torcd1YgDQvSfNmRtKzYDO4FGBkrAdlAVWnpY= github.com/go-openapi/jsonreference v1.0.0/go.mod h1:jtwdyGbJk0Xhe5Y+rwtglQP6Sb1WZST4rT32LWB+sv0= -github.com/go-openapi/loads v0.25.0 h1:74Bc2snfaVlsHzwdQj/3gsA9XJz3daXTJVs+4ZaK7jI= -github.com/go-openapi/loads v0.25.0/go.mod h1:JFBw4SIB9+PTIFHDfcXuSSy5h6aWzjtUCrPYyx3qWU8= -github.com/go-openapi/spec v0.22.9 h1:/vKIFDcGKp0ktZWGbym/tJEWbk6/XOEmAVU0kqKMH+w= -github.com/go-openapi/spec v0.22.9/go.mod h1:b/mNUYIOQOyIiUzUzXEE8xzyZqf93KvM9hQGP91yfl0= -github.com/go-openapi/strfmt v0.27.0 h1:kbcTeaD9TXuXD0hhMXzuYa1sdTo6+dWGvwjW93E80IM= -github.com/go-openapi/strfmt v0.27.0/go.mod h1:s/qhDqfY72irigXUGJmtgid2Rm+3tnz3k8hZaRmvWYc= +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/swag v0.28.0 h1:xkgbOSKj6DZziNpyqRRAOt3GJGtgjgsd2RoyT30VWuw= github.com/go-openapi/swag v0.28.0/go.mod h1:4qYnT3Cqr1p1VknOdPo70evN4rgQnAg6jwApHyxSGIg= github.com/go-openapi/swag/cmdutils v0.28.0 h1:7TOeNtkYru1SG8Y34tDh9WBbLsMqGnptuxWiHREPZ4Q= @@ -85,20 +101,17 @@ github.com/go-openapi/testify/enable/yaml/v2 v2.6.0 h1:gGHwAJ0R/5jU8BEGDbfRNR3hL github.com/go-openapi/testify/enable/yaml/v2 v2.6.0/go.mod h1:tY+St1SGq4NFl0QIqdTY4aEdbChAHxhyB77XQi9iJCo= github.com/go-openapi/testify/v2 v2.6.0 h1:5PKH2HE7YJ/LuRPQGvSxBRlFXNQhSetBLlGAgUEu3ug= github.com/go-openapi/testify/v2 v2.6.0/go.mod h1:SgsVHtfooshd0tublTtJ50FPKhujf47YRqauXXOUxfw= -github.com/go-openapi/validate v0.26.1 h1:pZSbvtRO8G2R2FpWTYRn3w8LrsNwbtaVhP2dWiBa0Us= -github.com/go-openapi/validate v0.26.1/go.mod h1:B8UMgXiQiwwQWIbmuROlwJZDPGlikPuh7iHV1vPX9Oo= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= 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-yaml v1.19.2 h1:PmFC1S6h8ljIz6gMRBopkjP1TVT7xuwrButHID66PoM= github.com/goccy/go-yaml v1.19.2/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= +github.com/godbus/dbus v0.0.0-20181025153459-66d97aec3384/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= github.com/godbus/dbus/v5 v5.2.2 h1:TUR3TgtSVDmjiXOgAAyaZbYmIeP3DPkld3jgKGV8mXQ= github.com/godbus/dbus/v5 v5.2.2/go.mod h1:3AAv2+hPq5rdnr5txxxRwiGjPXamgoIHgz9FPBfOp3c= -github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg= -github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= -github.com/google/cel-go v0.26.0 h1:DPGjXackMpJWH680oGY4lZhYjIameYmR+/6RBdDGmaI= -github.com/google/cel-go v0.26.0/go.mod h1:A9O8OU9rdvrK5MQyrqfIxo1a0u4g3sF8KB6PUIaryMM= +github.com/google/cel-go v0.30.0 h1:ll54AkzKunWkBn9wSoiUXbFZXYZTkdJGNXTBXUoolGo= +github.com/google/cel-go v0.30.0/go.mod h1:X0bD6iVNR8pkROSOoHVdgTkzmRcosof7WQqCD6wcMc8= github.com/google/gnostic-models v0.7.1 h1:SisTfuFKJSKM5CPZkffwi6coztzzeYUhc3v4yxLWH8c= github.com/google/gnostic-models v0.7.1/go.mod h1:whL5G0m6dmc5cPxKc5bdKdEN3UjI7OUGxBlw57miDrQ= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= @@ -112,10 +125,15 @@ github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 h1:BHT72Gu3keYf3ZEu2J github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/huandu/xstrings v1.5.0 h1:2ag3IFq9ZDANvthTwTiqSSZLjDc+BedvHPAp5tJy2TI= +github.com/huandu/xstrings v1.5.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/klauspost/compress v1.19.1 h1:VsB4HPswih7mmZ8WleSFQ75c/Ui1M4trX5oAsJnhSlk= github.com/klauspost/compress v1.19.1/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= @@ -136,20 +154,22 @@ github.com/mdlayher/netlink v1.11.2 h1:HKh2jqe+omdSWcQ88nrT7INE61B0NXfiSPFdgL4Yb github.com/mdlayher/netlink v1.11.2/go.mod h1:uT2Yc/QLaZubzDpZIBi9d4GoeLwtp3x1AMeqSRrK2sA= github.com/mdlayher/socket v0.6.1 h1:M7uj2NtuujUY4mYr1C57NmfNiRHbkKpnBxO856lsc3A= github.com/mdlayher/socket v0.6.1/go.mod h1:+/SGtqc9V+5dAuRgQsU0fGBI+oRDiW7O2Obx10OIWfg= +github.com/metal-stack/api v0.4.4 h1:NwJKCFHnbmsU7DjHLtBmpdPuPniXc2wDabHjdpXk3qA= +github.com/metal-stack/api v0.4.4/go.mod h1:E7f2GkKNSr4vBxhQwWrr/Mjnf4ctPqCX2dpDtXBqkBk= github.com/metal-stack/firewall-controller-manager v0.6.1 h1:JM5oCuye9GBY/QivK9qxY14hNh0xoidAGVkY7td8gnY= github.com/metal-stack/firewall-controller-manager v0.6.1/go.mod h1:bQjb3pVL3R6XPUqWA/WX8ktlzcgVYWDbsFANKcrW3FA= -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-hammer v0.13.17 h1:W2IrWmnz6IXpL7Y35RfVgSVO66EVdqeF+/WeopgycMI= -github.com/metal-stack/metal-hammer v0.13.17/go.mod h1:N+AEexkInMf1YHe40CkCSaAK4mkKh8ubB3Zsy1s6uzQ= github.com/metal-stack/metal-lib v0.26.1 h1:wMrhENm/HPq0t7cjCkhzepGD6dyxmX/4IMsaJZea874= github.com/metal-stack/metal-lib v0.26.1/go.mod h1:tnx4MM5oml10EMN6Nq6oFSbjOKB9B27WUZQUyZ4MywA= -github.com/metal-stack/metal-networker v0.47.0 h1:DsA7cLfcd/LtTv+bMqCX7a+uGRB4cTbNAguBu0EHNvI= -github.com/metal-stack/metal-networker v0.47.0/go.mod h1:IoxAZQXAc4h5mFGqSKOo7EAp7pYr+qK2B6qgf3kBu+U= +github.com/metal-stack/os-installer v0.3.1 h1:1gA7MF/CD0TIpGQnTP9LrgY0/lr2EJA7TOgdJ3zlYOs= +github.com/metal-stack/os-installer v0.3.1/go.mod h1:gIpJovxYMgF84E9eVkOWkKWGkLJA/qD90R/QnLixJDI= github.com/metal-stack/v v1.0.3 h1:Sh2oBlnxrCUD+mVpzfC8HiqL045YWkxs0gpTvkjppqs= github.com/metal-stack/v v1.0.3/go.mod h1:YTahEu7/ishwpYKnp/VaW/7nf8+PInogkfGwLcGPdXg= github.com/miekg/dns v1.1.72 h1:vhmr+TF2A3tuoGNkLDFK9zi36F2LS+hKTRW0Uf8kbzI= github.com/miekg/dns v1.1.72/go.mod h1:+EuEPhdHOsfk6Wk5TT2CzssZdqkmFhf8r+aVyDEToIs= +github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= +github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= +github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= +github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -158,8 +178,9 @@ github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFd github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/oklog/ulid/v2 v2.1.2 h1:IEclFb9JNvzYA6MW2SCxbLzcHTVsfqm3PrqGQJH5zec= -github.com/oklog/ulid/v2 v2.1.2/go.mod h1:rcEKHmBBKfef9DhnvX7y1HZBYxjXb0cP5ExxNsTT1QQ= +github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= +github.com/oklog/ulid/v2 v2.1.1 h1:suPZ4ARWLOJLegGFiZZ1dFAkqzhMjL3J1TzI+5wHz8s= +github.com/oklog/ulid/v2 v2.1.1/go.mod h1:rcEKHmBBKfef9DhnvX7y1HZBYxjXb0cP5ExxNsTT1QQ= github.com/olekukonko/cat v0.0.0-20250911104152-50322a0618f6 h1:zrbMGy9YXpIeTnGj4EljqMiZsIcE09mmF8XsD5AYOJc= github.com/olekukonko/cat v0.0.0-20250911104152-50322a0618f6/go.mod h1:rEKTHC9roVVicUIfZK7DYrdIoM0EOr8mK1Hj5s3JjH0= github.com/olekukonko/errors v1.2.0 h1:10Zcn4GeV59t/EGqJc8fUjtFT/FuUh5bTMzZ1XwmCRo= @@ -172,9 +193,10 @@ github.com/onsi/ginkgo/v2 v2.27.5 h1:ZeVgZMx2PDMdJm/+w5fE/OyG6ILo1Y3e+QX4zSR0zTE github.com/onsi/ginkgo/v2 v2.27.5/go.mod h1:ArE1D/XhNXBXCBkKOLkbsb2c81dQHCRcF5zwn/ykDRo= github.com/onsi/gomega v1.39.0 h1:y2ROC3hKFmQZJNFeGAMeHZKkjBL65mIZcvrLQBF9k6Q= github.com/onsi/gomega v1.39.0/go.mod h1:ZCU1pkQcXDO5Sl9/VVEGlDyp+zm0m1cmeG5TOzLgdh4= -github.com/pborman/getopt v0.0.0-20170112200414-7148bc3a4c30/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o= +github.com/pborman/uuid v0.0.0-20170612153648-e790cca94e6c/go.mod h1:VyrYX9gd7irzKovcSS6BIIEwPRkP2Wm2m9ufcdFSJ34= github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= +github.com/pin/tftp v2.1.0+incompatible/go.mod h1:xVpZOMCXTy+A5QMjEVN0Glwa1sUvaJhFXbr/aAxuxGY= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -188,10 +210,20 @@ github.com/prometheus/common v0.70.1 h1:1HvjP4D5oL3t8RsPlwxA9onvvStjtIHYE5XuuwOi github.com/prometheus/common v0.70.1/go.mod h1:VdFUQDMZK3VLkurFUVhia6uys/0suUp86TJz5qbJRhc= github.com/prometheus/procfs v0.21.1 h1:GljZCt+zSTS+NZq88cyQ1LjZ+RCHp3uVuabBWA5+OJI= github.com/prometheus/procfs v0.21.1/go.mod h1:aB55Cww9pdSJVHk0hUf0inxWyyjPogFIjmHKYgMKmtY= -github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= -github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= +github.com/rodaine/protogofakeit v0.1.1 h1:ZKouljuRM3A+TArppfBqnH8tGZHOwM/pjvtXe9DaXH8= +github.com/rodaine/protogofakeit v0.1.1/go.mod h1:pXn/AstBYMaSfc1/RqH3N82pBuxtWgejz1AlYpY1mI0= +github.com/rogpeppe/go-internal v1.15.0 h1:D0RCU5rMAp+SpgkiNdrjfJ+LX4J1M32V2NeCY7EJ6hc= +github.com/rogpeppe/go-internal v1.15.0/go.mod h1:DrUVZyrJU+txYW5/1kwtXQSMFio52ZOxX7yM1VHvnxs= github.com/sagikazarmark/locafero v0.11.0 h1:1iurJgmM9G3PA/I+wWYIOw/5SyBtxapeHDcg+AAIFXc= github.com/sagikazarmark/locafero v0.11.0/go.mod h1:nVIGvgyzw595SUSUE6tvCp3YYTeHs15MvlmU87WwIik= +github.com/samber/lo v1.53.0 h1:t975lj2py4kJPQ6haz1QMgtId2gtmfktACxIXArw3HM= +github.com/samber/lo v1.53.0/go.mod h1:4+MXEGsJzbKGaUEQFKBq2xtfuznW9oz/WrgyzMzRoM0= +github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k= +github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME= +github.com/sigma/bdoor v0.0.0-20160202064022-babf2a4017b0/go.mod h1:WBu7REWbxC/s/J06jsk//d+9DOz9BbsmcIrimuGRFbs= +github.com/sigma/vmw-guestinfo v0.0.0-20160204083807-95dd4126d6e8/go.mod h1:JrRFFC0veyh0cibh0DAhriSY7/gV3kDdNaVUOmfx01U= +github.com/smartystreets/assertions v1.2.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo= +github.com/smartystreets/goconvey v1.7.2/go.mod h1:Vw0tHAZW6lzCRk3xgdin6fKYcG+G3Pg9vgXWeJpQFMM= github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 h1:+jumHNA0Wrelhe64i8F6HNlS8pkoyMv5sreGx2Ry5Rw= github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8/go.mod h1:3n1Cwaq1E1/1lhQhtRK2ts/ZwZEhjcQeJQ1RuC6Q/8U= github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I= @@ -204,66 +236,82 @@ github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk= github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.21.0 h1:x5S+0EU27Lbphp4UKm1C+1oQO+rKx36vfCoaVebLFSU= github.com/spf13/viper v1.21.0/go.mod h1:P0lhsswPGWD/1lZJ9ny3fYnVqxiegrlNrEmgLjbTCAY= -github.com/stoewer/go-strcase v1.3.0 h1:g0eASXYtp+yvN9fK8sH94oCIk0fau9uV1/ZdJ0AVEzs= -github.com/stoewer/go-strcase v1.3.0/go.mod h1:fAH5hQ5pehh+j3nZfvwdk2RgEgQjAoM8wodgtPmh1xo= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.5.3 h1:jmXUvGomnU1o3W/V5h2VEradbpJDwGrzugQQvL0POH4= github.com/stretchr/objx v0.5.3/go.mod h1:rDQraq+vQZU7Fde9LOZLr8Tax6zZvy4kuNKF+QYS+U0= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/txn2/txeh v1.8.1 h1:zOwKCbiOUZRXmtZZSb0S45Jdf8r1s0rBwKBE6FRVCQY= github.com/txn2/txeh v1.8.1/go.mod h1:ltyfKOEbH5Tei2LAHxqTFi3leEzY2i1RjyLF7/J0hpo= +github.com/vincent-petithory/dataurl v1.0.0 h1:cXw+kPto8NLuJtlMsI152irrVw9fRDX8AbShPRpg2CI= +github.com/vincent-petithory/dataurl v1.0.0/go.mod h1:FHafX5vmDzyP+1CQATJn7WFKc9CvnvxyvZy6I1MrG/U= github.com/vishvananda/netlink v1.3.1 h1:3AEMt62VKqz90r0tmNhog0r/PpWKmrEShJU0wJW6bV0= github.com/vishvananda/netlink v1.3.1/go.mod h1:ARtKouGSTGchR8aMwmkzC0qiNPrrWO5JS/XMVl45+b4= github.com/vishvananda/netns v0.0.5 h1:DfiHV+j8bA32MFM7bfEunvT8IAqQ/NzSJHtcmW5zdEY= github.com/vishvananda/netns v0.0.5/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM= +github.com/vmware/vmw-guestinfo v0.0.0-20170707015358-25eff159a728/go.mod h1:x9oS4Wk2s2u4tS29nEaDLdzvuHdB19CvSGJjPgkZJNk= +github.com/vmware/vmw-ovflib v0.0.0-20170608004843-1f217b9dc714/go.mod h1:jiPk45kn7klhByRvUq5i2vo1RtHKBHj+iWGFpxbXuuI= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= -go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +go.uber.org/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc= +go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= go.yaml.in/yaml/v2 v2.4.4 h1:tuyd0P+2Ont/d6e2rl3be67goVK4R6deVxCUX5vyPaQ= go.yaml.in/yaml/v2 v2.4.4/go.mod h1:gMZqIpDtDqOfM0uNfy0SkpRhvUryYH0Z6wdMYcacYXQ= go.yaml.in/yaml/v3 v3.0.5 h1:N6y/pJk8buWs9NY5ERU2HSMfm+IuD/OtfdAnq6kESPw= go.yaml.in/yaml/v3 v3.0.5/go.mod h1:HVTZu1O7/Vkt2N+BFy8Zza+lnLsABggaTM2ZpNIGuKg= +go4.org v0.0.0-20160314031811-03efcb870d84/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE= +go4.org v0.0.0-20260112195520-a5071408f32f h1:ziUVAjmTPwQMBmYR1tbdRFJPtTcQUI12fH9QQjfb0Sw= +go4.org v0.0.0-20260112195520-a5071408f32f/go.mod h1:ZRJnO5ZI4zAwMFp+dS1+V6J6MSyAowhRqAE+DPa1Xp0= go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBseWJUpBw5I82+2U4M= go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y= -golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f h1:W3F4c+6OLc6H2lb//N1q4WpJkhzJCK5J6kUi1NTVXfM= -golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f/go.mod h1:J1xhfL/vlindoeF/aINzNzt2Bket5bjo9sdOYzOsU80= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.54.0 h1:YLIA59K4fiNzHzjnZt2tUJQjQtUWfWbeHBqKtk3eScw= +golang.org/x/crypto v0.54.0/go.mod h1:KWL8ny2AZdGR2cWmzeHrp2azQPGogOv+HeQaVEXC2dk= +golang.org/x/exp v0.0.0-20260727155853-b88d891fe743 h1:ex206bKw+v3K0dm3andkrIF+ijyQKJG1pLgwQ2PYdQM= +golang.org/x/exp v0.0.0-20260727155853-b88d891fe743/go.mod h1:EdfpwwqSu+0Li0mzskwHU6FWDV3t9Q+RZDo3QMUtL3Q= golang.org/x/mod v0.38.0 h1:MECBjubtXD7yj4HrhIUcywNaGeNVUdfVnxmPajOk4yk= golang.org/x/mod v0.38.0/go.mod h1:V6Xz0pq8TQ3dGqVQ1FVHuelZpAL0uNhSkk9ogYP3c40= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190320064053-1272bf9dcd53/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.57.0 h1:K5+3DljvIuDG9/Jv9rvyMywYNFCQ9RSUY6OOTTkT+tE= golang.org/x/net v0.57.0/go.mod h1:KpXc8iv+r3XplLAG/f7Jsf9RPszJzdR0f58q9vGOuEU= 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.22.0 h1:SZjpbeLmrCk4xhRSZFNZW5gFUeCeFgjekvI/+gfScek= golang.org/x/sync v0.22.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.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs= golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/term v0.45.0 h1:NwWyBmoJCbfTHpxrWoZ9C6/VxOf7ic219I8xZZFdrf0= golang.org/x/term v0.45.0/go.mod h1:9aqxs0blBcrm/n0L9QW0aRVD+ktan8ssZromtqJC43w= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.40.0 h1:Ub2Z6/xjgF1WrYQz2nuITOEegKFtiIy+rieRJ5lHZKs= golang.org/x/text v0.40.0/go.mod h1:hpnzDAfGV753zIKo+wk3u1bVKCGPbrnF7+7LBF/UHVY= golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U= golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.48.0 h1:3+hClM1aLL5mjMKm5ovokw9epgRXPuu2tILgismM6RE= golang.org/x/tools v0.48.0/go.mod h1:08xX0orndb/F7jJxGDicx061tyd5pcMto75YMAXr6lk= gomodules.xyz/jsonpatch/v2 v2.5.0 h1:JELs8RLM12qJGXU4u/TO3V25KW8GreMKl9pdkk14RM0= gomodules.xyz/jsonpatch/v2 v2.5.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= -google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa h1:Kjn0N0tCrDgiAFW+lGO4JZ3ck44CehvJQMAwj9QF0G8= -google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa/go.mod h1:q4lMZS6kskjT5HvCPrnnypcDPVJqT/f4nfxmkE7gryY= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260523011958-0a33c5d7ca68 h1:PvEgGJf9C/1u5CHkInMg7UFYYUoiaQmW2LbtH0pjB78= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260523011958-0a33c5d7ca68/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= -google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= -google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= +google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d h1:FarXi840EJWSHYTN3ERkADbPWjl307+FGrA22KAVjjc= +google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d/go.mod h1:K/+WGbmBY7aNW1HDw1fJnKYo10i0DkAX6pows00dLig= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260803160001-6ac0973c030d h1:IL4hdHzcUv2l/gcg98/Rj3FbtE6axwqslOW8SW0C+S0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260803160001-6ac0973c030d/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= +google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af h1:+5/Sw3GsDNlEmu7TfklWKPdQ0Ykja5VEmq2i817+jbI= +google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= @@ -271,31 +319,33 @@ gopkg.in/evanphx/json-patch.v4 v4.13.0 h1:czT3CmqEaQ1aanPc5SdlgQrrEIb8w/wwCvWWnf gopkg.in/evanphx/json-patch.v4 v4.13.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -k8s.io/api v0.35.0 h1:iBAU5LTyBI9vw3L5glmat1njFK34srdLmktWwLTprlY= -k8s.io/api v0.35.0/go.mod h1:AQ0SNTzm4ZAczM03QH42c7l3bih1TbAXYo0DkF8ktnA= -k8s.io/apiextensions-apiserver v0.35.0 h1:3xHk2rTOdWXXJM+RDQZJvdx0yEOgC0FgQ1PlJatA5T4= -k8s.io/apiextensions-apiserver v0.35.0/go.mod h1:E1Ahk9SADaLQ4qtzYFkwUqusXTcaV2uw3l14aqpL2LU= -k8s.io/apimachinery v0.35.0 h1:Z2L3IHvPVv/MJ7xRxHEtk6GoJElaAqDCCU0S6ncYok8= -k8s.io/apimachinery v0.35.0/go.mod h1:jQCgFZFR1F4Ik7hvr2g84RTJSZegBc8yHgFWKn//hns= -k8s.io/client-go v0.35.0 h1:IAW0ifFbfQQwQmga0UdoH0yvdqrbwMdq9vIFEhRpxBE= -k8s.io/client-go v0.35.0/go.mod h1:q2E5AAyqcbeLGPdoRB+Nxe3KYTfPce1Dnu1myQdqz9o= -k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= -k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= -k8s.io/kube-openapi v0.0.0-20251125145642-4e65d59e963e h1:iW9ChlU0cU16w8MpVYjXk12dqQ4BPFBEgif+ap7/hqQ= -k8s.io/kube-openapi v0.0.0-20251125145642-4e65d59e963e/go.mod h1:kdmbQkyfwUagLfXIad1y2TdrjPFWp2Q89B3qkRwf/pQ= -k8s.io/utils v0.0.0-20260108192941-914a6e750570 h1:JT4W8lsdrGENg9W+YwwdLJxklIuKWdRm+BC+xt33FOY= -k8s.io/utils v0.0.0-20260108192941-914a6e750570/go.mod h1:xDxuJ0whA3d0I4mf/C4ppKHxXynQ+fxnkmQH0vTHnuk= +k8s.io/api v0.36.3 h1:NxB+05W2UGqXWFXcLO0RB5cnqnUPP5v5sVlaOH0Iz4w= +k8s.io/api v0.36.3/go.mod h1:JzLQKqRHC5+I8RVj/lS3lCg0mg6nWI9Fo/Sk3ElxHzg= +k8s.io/apiextensions-apiserver v0.36.3 h1:dPmOAPhwTtqb1bTxbFPsy18KHPhktQeO3WUPXunZIB0= +k8s.io/apiextensions-apiserver v0.36.3/go.mod h1:KTXFqgXiuw2pRoL+Wpmttqc+up9Xt/GohadPWeLLOa4= +k8s.io/apimachinery v0.36.3 h1:PkzMRBRG8joFD8EhCuQAtNPvJlxb82FwplP26HIzvAM= +k8s.io/apimachinery v0.36.3/go.mod h1:cTSjBWgPe/6CQyBKzY/hDIRWCQQQeK0mfLbml0UYFHE= +k8s.io/client-go v0.36.3 h1:M4JdVzXxYcZk4fGpfDdYnxSwhLKWCFoQsHW6t+z8Hfg= +k8s.io/client-go v0.36.3/go.mod h1:gcPwr0c87vjjG6HB6pWEqOeuYVoXSsREjzux2j6GF30= +k8s.io/klog/v2 v2.140.0 h1:Tf+J3AH7xnUzZyVVXhTgGhEKnFqye14aadWv7bzXdzc= +k8s.io/klog/v2 v2.140.0/go.mod h1:o+/RWfJ6PwpnFn7OyAG3QnO47BFsymfEfrz6XyYSSp0= +k8s.io/kube-openapi v0.0.0-20260317180543-43fb72c5454a h1:xCeOEAOoGYl2jnJoHkC3hkbPJgdATINPMAxaynU2Ovg= +k8s.io/kube-openapi v0.0.0-20260317180543-43fb72c5454a/go.mod h1:uGBT7iTA6c6MvqUvSXIaYZo9ukscABYi2btjhvgKGZ0= +k8s.io/utils v0.0.0-20260210185600-b8788abfbbc2 h1:AZYQSJemyQB5eRxqcPky+/7EdBj0xi3g0ZcxxJ7vbWU= +k8s.io/utils v0.0.0-20260210185600-b8788abfbbc2/go.mod h1:xDxuJ0whA3d0I4mf/C4ppKHxXynQ+fxnkmQH0vTHnuk= pgregory.net/rapid v1.3.0 h1:vBvO0VSqti75J1jjYqpgPNBLKMd1+gxa9fYo7vk/Exc= pgregory.net/rapid v1.3.0/go.mod h1:dPlE4OBBxgXPqkP79flB6sJL1dx5azpI7HQ9MY9Z7uk= -sigs.k8s.io/controller-runtime v0.23.0 h1:Ubi7klJWiwEWqDY+odSVZiFA0aDSevOCXpa38yCSYu8= -sigs.k8s.io/controller-runtime v0.23.0/go.mod h1:DBOIr9NsprUqCZ1ZhsuJ0wAnQSIxY/C6VjZbmLgw0j0= +sigs.k8s.io/controller-runtime v0.24.1 h1:miPEwrmirImAvgME1L9qebGHrOnGJoVmVdtOU9fRfo4= +sigs.k8s.io/controller-runtime v0.24.1/go.mod h1:vFkfY5fGt5xAC/sKb8IBFKgWPNKG9OUG29dR8Y2wImw= sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5EXP7sU1kvOlxwZh5txg= sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg= sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU= sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= -sigs.k8s.io/structured-merge-diff/v6 v6.3.1 h1:JrhdFMqOd/+3ByqlP2I45kTOZmTRLBUm5pvRjeheg7E= -sigs.k8s.io/structured-merge-diff/v6 v6.3.1/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE= +sigs.k8s.io/structured-merge-diff/v6 v6.3.3 h1:u08YRbVUi59ri4YD6cg0UqNM4Dimn0sIl+wldcx5PYw= +sigs.k8s.io/structured-merge-diff/v6 v6.3.3/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE= sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs= sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4= diff --git a/main.go b/main.go index 51d93a77..8459e41e 100644 --- a/main.go +++ b/main.go @@ -2,12 +2,15 @@ package main import ( "context" + "errors" "flag" "fmt" "log/slog" "os" "time" + apiv2 "github.com/metal-stack/api/go/metalstack/api/v2" + "github.com/metal-stack/metal-lib/pkg/pointer" "github.com/metal-stack/v" "github.com/go-logr/logr" @@ -32,6 +35,10 @@ import ( "github.com/metal-stack/firewall-controller/v2/pkg/frr" "github.com/metal-stack/firewall-controller/v2/pkg/sysctl" "github.com/metal-stack/firewall-controller/v2/pkg/updater" + + installerv1 "github.com/metal-stack/os-installer/api/v1" + "github.com/metal-stack/os-installer/pkg/installer" + osnet "github.com/metal-stack/os-installer/pkg/network" // +kubebuilder:scaffold:imports ) @@ -233,21 +240,38 @@ func main() { } l.Info("detected frr", "version", frrVersion.String()) + allocation, err := getMachineAllocation() + if err != nil { + l.Error("reading machine allocation", "error", err) + panic(err) + } + defaultRouteNetwork, err := osnet.New(allocation).GetDefaultRouteNetwork() + if err != nil { + l.Error("unable to get a default route network", "error", err) + panic(err) + } + if len(defaultRouteNetwork.Ips) == 0 { + l.Error("default route network does not have ips") + panic(errors.New("default route network does not have ips")) + } + defaultRouteIp := defaultRouteNetwork.Ips[0] + updater := updater.New(ctrl.Log.WithName("updater"), shootMgr.GetEventRecorderFor("FirewallController")) // nolint:staticcheck // Firewall Reconciler if err = (&controllers.FirewallReconciler{ - SeedClient: seedMgr.GetClient(), - ShootClient: shootClient, - Log: ctrl.Log.WithName("controllers").WithName("Firewall"), - Scheme: scheme, - Namespace: seedNamespace, - FirewallName: firewallName, - Recorder: shootMgr.GetEventRecorderFor("FirewallController"), // nolint:staticcheck - Updater: updater, - SeedUpdatedFunc: fwmReconciler.SeedUpdated, - TokenUpdater: accessTokenUpdater, - FrrVersion: frrVersion, + SeedClient: seedMgr.GetClient(), + ShootClient: shootClient, + Log: ctrl.Log.WithName("controllers").WithName("Firewall"), + Scheme: scheme, + Namespace: seedNamespace, + FirewallName: firewallName, + Recorder: shootMgr.GetEventRecorderFor("FirewallController"), // nolint:staticcheck + Updater: updater, + SeedUpdatedFunc: fwmReconciler.SeedUpdated, + TokenUpdater: accessTokenUpdater, + FrrVersion: frrVersion, + MachineAllocation: allocation, }).SetupWithManager(seedMgr); err != nil { l.Error("unable to create firewall controller", "error", err) panic(err) @@ -265,13 +289,15 @@ func main() { // ClusterwideNetworkPolicy Reconciler if err = (&controllers.ClusterwideNetworkPolicyReconciler{ - SeedClient: seedMgr.GetClient(), - ShootClient: shootMgr.GetClient(), - Log: ctrl.Log.WithName("controllers").WithName("ClusterwideNetworkPolicy"), - Ctx: ctx, - Recorder: shootMgr.GetEventRecorderFor("FirewallController"), // nolint:staticcheck - FirewallName: firewallName, - SeedNamespace: seedNamespace, + SeedClient: seedMgr.GetClient(), + ShootClient: shootMgr.GetClient(), + Log: ctrl.Log.WithName("controllers").WithName("ClusterwideNetworkPolicy"), + Ctx: ctx, + Recorder: shootMgr.GetEventRecorderFor("FirewallController"), // nolint:staticcheck + FirewallName: firewallName, + SeedNamespace: seedNamespace, + DefaultRouteIp: defaultRouteIp, + MachineAllocation: allocation, }).SetupWithManager(shootMgr); err != nil { l.Error("unable to create clusterwidenetworkpolicy controller", "error", err) panic(err) @@ -378,3 +404,165 @@ func getSeedNamespace(rawKubeconfig []byte) (string, error) { return "", fmt.Errorf("unable to figure out seed namespace from kubeconfig") } + +func getMachineAllocation() (*apiv2.MachineAllocation, error) { + // TODO: check what we can take from the Firewall Object + _, err := os.Stat(installerv1.MachineAllocationPath) + if errors.Is(err, os.ErrNotExist) { + _, err = os.Stat(installerv1.LegacyInstallPath) + if errors.Is(err, os.ErrNotExist) { + return nil, fmt.Errorf("neither %s nor %s exists, exiting", installerv1.MachineAllocationPath, installerv1.LegacyInstallPath) + } + // /etc/metal/install.yaml exists but /etc/metal/machine-allocation does not + legacyInstallConfig, err := installer.ReadLegacyInstallYaml() + if err != nil { + return nil, err + } + + return convertLegacyInstallConfig(legacyInstallConfig) + } + + _, allocation, err := installer.ReadConfigurations() + if err != nil { + return nil, err + } + + return allocation, nil +} + +func convertLegacyInstallConfig(config *installerv1.InstallerConfig) (*apiv2.MachineAllocation, error) { + var vpn *apiv2.MachineVPN + if config.VPN != nil { + vpn = &apiv2.MachineVPN{ + ControlPlaneAddress: pointer.SafeDeref(config.VPN.Address), + AuthKey: pointer.SafeDeref(config.VPN.AuthKey), + Connected: pointer.SafeDeref(config.VPN.Connected), + } + } + + allocationType := apiv2.MachineAllocationType_MACHINE_ALLOCATION_TYPE_MACHINE + if config.Role == "firewall" { + allocationType = apiv2.MachineAllocationType_MACHINE_ALLOCATION_TYPE_FIREWALL + } + + var dnsservers []*apiv2.DNSServer + for _, dns := range config.DNSServers { + dnsservers = append(dnsservers, &apiv2.DNSServer{ + Ip: pointer.SafeDeref(dns.IP), + }) + } + var ntpservers []*apiv2.NTPServer + for _, ntp := range config.NTPServers { + ntpservers = append(ntpservers, &apiv2.NTPServer{ + Address: pointer.SafeDeref(ntp.Address), + }) + } + + var firewallRules *apiv2.FirewallRules + if config.FirewallRules != nil { + var egressrules []*apiv2.FirewallEgressRule + + for _, egress := range config.FirewallRules.Egress { + var proto apiv2.IPProtocol + if egress.Protocol == "tcp" { + proto = apiv2.IPProtocol_IP_PROTOCOL_TCP + } + if egress.Protocol == "udp" { + proto = apiv2.IPProtocol_IP_PROTOCOL_UDP + } + var ports []uint32 + for _, port := range egress.Ports { + ports = append(ports, uint32(port)) + } + + egressrules = append(egressrules, &apiv2.FirewallEgressRule{ + Comment: egress.Comment, + Protocol: proto, + Ports: ports, + To: egress.To, + }) + } + + var ingressrules []*apiv2.FirewallIngressRule + for _, ingress := range config.FirewallRules.Ingress { + var proto apiv2.IPProtocol + if ingress.Protocol == "tcp" { + proto = apiv2.IPProtocol_IP_PROTOCOL_TCP + } + if ingress.Protocol == "udp" { + proto = apiv2.IPProtocol_IP_PROTOCOL_UDP + } + var ports []uint32 + for _, port := range ingress.Ports { + ports = append(ports, uint32(port)) + } + + ingressrules = append(ingressrules, &apiv2.FirewallIngressRule{ + Comment: ingress.Comment, + Protocol: proto, + Ports: ports, + To: ingress.To, + From: ingress.From, + }) + } + + firewallRules = &apiv2.FirewallRules{ + Egress: egressrules, + Ingress: ingressrules, + } + } + + var networks []*apiv2.MachineNetwork + for _, nw := range config.Networks { + + natType := apiv2.NATType_NAT_TYPE_NONE + if nw.Nat != nil && *nw.Nat { + natType = apiv2.NATType_NAT_TYPE_IPV4_MASQUERADE + } + + var networkType apiv2.NetworkType + switch pointer.SafeDeref(nw.Networktypev2) { + case "external": + networkType = apiv2.NetworkType_NETWORK_TYPE_EXTERNAL + case "underlay": + networkType = apiv2.NetworkType_NETWORK_TYPE_UNDERLAY + case "super": + networkType = apiv2.NetworkType_NETWORK_TYPE_SUPER + case "super-namespaced": + networkType = apiv2.NetworkType_NETWORK_TYPE_SUPER_NAMESPACED + case "child": + networkType = apiv2.NetworkType_NETWORK_TYPE_CHILD + case "child-shared": + networkType = apiv2.NetworkType_NETWORK_TYPE_CHILD_SHARED + } + + networks = append(networks, &apiv2.MachineNetwork{ + Network: pointer.SafeDeref(nw.Networkid), + Prefixes: nw.Prefixes, + DestinationPrefixes: nw.Destinationprefixes, + Ips: nw.Ips, + Vrf: uint64(pointer.SafeDeref(nw.Vrf)), + Asn: uint32(pointer.SafeDeref(nw.Asn)), + // FIXME This is most probably empty as well, but can be taken from + // firewall.Status.FirewallNetworks.Project which must be added there + Project: nw.Projectid, + NatType: natType, + NetworkType: networkType, + }) + } + + machineAllocation := &apiv2.MachineAllocation{ + // FIXME Project of the machine is not stored in old install.yaml + // Maybe we take it from firewallv2.Firewall.Spec.Project ? + // Project: config.Projectid, + Hostname: config.Hostname, + AllocationType: allocationType, + FirewallRules: firewallRules, + Networks: networks, + DnsServers: dnsservers, + NtpServers: ntpservers, + Vpn: vpn, + } + + return machineAllocation, nil +} diff --git a/pkg/dns/dnsproxy.go b/pkg/dns/dnsproxy.go index b9a16212..ea57490d 100644 --- a/pkg/dns/dnsproxy.go +++ b/pkg/dns/dnsproxy.go @@ -7,70 +7,75 @@ import ( "strconv" "time" - "github.com/metal-stack/metal-networker/pkg/netconf" "sigs.k8s.io/controller-runtime/pkg/client" firewallv1 "github.com/metal-stack/firewall-controller/v2/api/v1" "github.com/go-logr/logr" dnsgo "github.com/miekg/dns" - - "github.com/metal-stack/firewall-controller/v2/pkg/network" ) const ( defaultDNSPort uint = 53 ) -type DNSHandler interface { - ServeDNS(w dnsgo.ResponseWriter, r *dnsgo.Msg) - UpdateDNSServerAddr(addr string) error -} +type ( + DNSHandler interface { + ServeDNS(w dnsgo.ResponseWriter, r *dnsgo.Msg) + UpdateDNSServerAddr(addr string) error + } -type DNSProxy struct { - log logr.Logger - ctx context.Context - cancelFunc context.CancelFunc - cache *DNSCache + DNSProxy struct { + log logr.Logger + ctx context.Context + cancelFunc context.CancelFunc + cache *DNSCache - udpServer *dnsgo.Server - tcpServer *dnsgo.Server + udpServer *dnsgo.Server + tcpServer *dnsgo.Server - handler DNSHandler -} + handler DNSHandler -func NewDNSProxy(ctx context.Context, dns string, port *uint, shootClient client.Client, log logr.Logger) (*DNSProxy, error) { - if dns == "" { - dns = defaultDNSServerAddr + bindAddress string } - host, err := getHost() - if err != nil { - return nil, err + DNSProxyConfig struct { + DNSServer string + Port *uint + ShootClient client.Client + Log logr.Logger + // BindAddress is the first ip of the defaultRouteNetwork + BindAddress string + } +) + +func NewDNSProxy(ctx context.Context, cfg *DNSProxyConfig) (*DNSProxy, error) { + if cfg.DNSServer == "" { + cfg.DNSServer = defaultDNSServerAddr } p := defaultDNSPort - if port != nil { - p = *port + if cfg.Port != nil { + p = *cfg.Port } - udpConn, tcpListener, err := bindToPort(host, int(p), log) // nolint:gosec + udpConn, tcpListener, err := bindToPort(cfg.BindAddress, int(p), cfg.Log) // nolint:gosec if err != nil { return nil, fmt.Errorf("failed to bind to port: %w", err) } backgroundCtx, cancel := context.WithCancel(ctx) - cache, err := newDNSCache(backgroundCtx, dns, true, false, shootClient, log.WithName("DNS cache")) + cache, err := newDNSCache(backgroundCtx, cfg.DNSServer, true, false, cfg.ShootClient, cfg.Log.WithName("DNS cache")) if err != nil { cancel() return nil, err } - handler := NewDNSProxyHandler(log, cache) + handler := NewDNSProxyHandler(cfg.Log, cache) udpServer := &dnsgo.Server{PacketConn: udpConn, Addr: udpConn.LocalAddr().String(), Net: "udp", Handler: handler} tcpServer := &dnsgo.Server{Listener: tcpListener, Addr: udpConn.LocalAddr().String(), Net: "tcp", Handler: handler} return &DNSProxy{ - log: log, + log: cfg.Log, ctx: backgroundCtx, cancelFunc: cancel, cache: cache, @@ -79,6 +84,8 @@ func NewDNSProxy(ctx context.Context, dns string, port *uint, shootClient client tcpServer: tcpServer, handler: handler, + + bindAddress: cfg.BindAddress, }, nil } @@ -136,22 +143,8 @@ func (p *DNSProxy) IsInitialized() bool { return p != nil } -func (p *DNSProxy) CacheAddr() (string, error) { - return getHost() -} - -func getHost() (string, error) { - c, err := netconf.New(network.GetLogger(), network.MetalNetworkerConfig) - if err != nil || c == nil { - return "", fmt.Errorf("failed to init networker config: %w", err) - } - - defaultNetwork := c.GetDefaultRouteNetwork() - if defaultNetwork == nil || len(defaultNetwork.Ips) < 1 { - return "", fmt.Errorf("failed to retrieve host IP for DNS Proxy") - } - - return defaultNetwork.Ips[0], nil +func (p *DNSProxy) CacheAddr() string { + return p.bindAddress } // bindToPort attempts to bind to port for both UDP and TCP diff --git a/pkg/network/network.go b/pkg/network/network.go index c2306371..83ecad78 100644 --- a/pkg/network/network.go +++ b/pkg/network/network.go @@ -1,37 +1,32 @@ package network import ( + "context" "fmt" "log/slog" - "os" - "path/filepath" "github.com/Masterminds/semver/v3" + "github.com/go-logr/logr" + apiv2 "github.com/metal-stack/api/go/metalstack/api/v2" firewallv2 "github.com/metal-stack/firewall-controller-manager/api/v2" - "github.com/metal-stack/metal-go/api/models" - "github.com/metal-stack/metal-networker/pkg/netconf" + "github.com/metal-stack/os-installer/pkg/frr" + osnet "github.com/metal-stack/os-installer/pkg/network" ) -const ( - MetalNetworkerConfig = "/etc/metal/install.yaml" - frrConfig = "/etc/frr/frr.conf" -) - -var logger *slog.Logger - -func init() { - jsonHandler := slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{}) - l := slog.New(jsonHandler) - - logger = l.WithGroup("networker") +type network struct { + log logr.Logger + allocation *apiv2.MachineAllocation } -func GetLogger() *slog.Logger { - return logger +func NewNetwork(log logr.Logger, allocation *apiv2.MachineAllocation) *network { + return &network{ + log: log, + allocation: allocation, + } } // GetNewNetworks returns updated network models -func GetNewNetworks(f *firewallv2.Firewall, oldNetworks []*models.V1MachineNetwork) []*models.V1MachineNetwork { +func GetNewNetworks(f *firewallv2.Firewall, oldNetworks []*apiv2.MachineNetwork) []*apiv2.MachineNetwork { networkMap := map[string]firewallv2.FirewallNetwork{} for _, n := range f.Status.FirewallNetworks { if n.NetworkType == nil { @@ -40,14 +35,14 @@ func GetNewNetworks(f *firewallv2.Firewall, oldNetworks []*models.V1MachineNetwo networkMap[*n.NetworkID] = n } - newNetworks := []*models.V1MachineNetwork{} + newNetworks := []*apiv2.MachineNetwork{} for _, n := range oldNetworks { if n == nil { continue } newNet := n - newNet.Prefixes = networkMap[*n.Networkid].Prefixes + newNet.Prefixes = networkMap[n.Network].Prefixes newNetworks = append(newNetworks, newNet) } @@ -56,42 +51,19 @@ func GetNewNetworks(f *firewallv2.Firewall, oldNetworks []*models.V1MachineNetwo // ReconcileNetwork reconciles the network settings for a firewall // Changes both the FRR-Configuration and Nftable rules when network prefixes or FRR template changes -func ReconcileNetwork(f *firewallv2.Firewall, frrVersion *semver.Version) (changed bool, err error) { - tmpFile, err := tmpFile(frrConfig) +func (n *network) ReconcileNetwork(f *firewallv2.Firewall, frrVersion *semver.Version) (bool, error) { + n.allocation.Networks = GetNewNetworks(f, n.allocation.Networks) + + changed, err := frr.Render(context.Background(), &frr.Config{ + Log: slog.New(logr.ToSlogHandler(n.log)), + Reload: true, + Validate: true, + Network: osnet.New(n.allocation), + FRRVersion: frrVersion, + }) if err != nil { - return false, fmt.Errorf("error during network reconciliation %v: %w", tmpFile, err) - } - defer func() { - _ = os.Remove(tmpFile) - }() - - c, err := netconf.New(GetLogger(), MetalNetworkerConfig) - if err != nil || c == nil { - return false, fmt.Errorf("failed to init networker config: %w", err) - } - c.Networks = GetNewNetworks(f, c.Networks) - - a := netconf.NewFrrConfigApplier(netconf.Firewall, *c, tmpFile, frrVersion) - tpl := netconf.MustParseTpl(netconf.TplFirewallFRR) - - changed, err = a.Apply(*tpl, tmpFile, frrConfig, true) - if err != nil { - return changed, fmt.Errorf("error during network reconciliation: %v: %w", tmpFile, err) + return changed, fmt.Errorf("error during network reconciliation: %w", err) } return changed, nil } - -func tmpFile(file string) (string, error) { - f, err := os.CreateTemp(filepath.Dir(file), filepath.Base(file)) - if err != nil { - return "", err - } - - err = f.Close() - if err != nil { - return "", err - } - - return f.Name(), nil -} diff --git a/pkg/nftables/firewall.go b/pkg/nftables/firewall.go index 7f753da5..6888782b 100644 --- a/pkg/nftables/firewall.go +++ b/pkg/nftables/firewall.go @@ -1,14 +1,17 @@ package nftables import ( + "context" "embed" "errors" "fmt" + "log/slog" "net/netip" "os" "os/exec" "path/filepath" + apiv2 "github.com/metal-stack/api/go/metalstack/api/v2" "github.com/metal-stack/firewall-controller/v2/pkg/dns" "github.com/metal-stack/firewall-controller/v2/pkg/network" @@ -20,7 +23,8 @@ import ( "k8s.io/client-go/tools/record" mn "github.com/metal-stack/metal-lib/pkg/net" - "github.com/metal-stack/metal-networker/pkg/netconf" + osnet "github.com/metal-stack/os-installer/pkg/network" + "github.com/metal-stack/os-installer/pkg/nftables" firewallv2 "github.com/metal-stack/firewall-controller-manager/api/v2" firewallv1 "github.com/metal-stack/firewall-controller/v2/api/v1" @@ -40,7 +44,7 @@ type FQDNCache interface { GetSetsForRendering(fqdns []firewallv1.FQDNSelector) (result []dns.RenderIPSet) GetSetsForFQDN(fqdn firewallv1.FQDNSelector) (result []firewallv1.IPSet) IsInitialized() bool - CacheAddr() (string, error) + CacheAddr() string } // Firewall assembles nftable rules based on k8s entities @@ -56,6 +60,7 @@ type Firewall struct { primaryPrivateNet *firewallv2.FirewallNetwork networkMap networkMap cache FQDNCache + allocation *apiv2.MachineAllocation enableDNS bool dryRun bool @@ -79,6 +84,7 @@ func NewFirewall( cache FQDNCache, log logr.Logger, recorder record.EventRecorder, + allocation *apiv2.MachineAllocation, ) *Firewall { networkMap := networkMap{} var primaryPrivateNet *firewallv2.FirewallNetwork @@ -104,6 +110,7 @@ func NewFirewall( enableDNS: len(cwnps.GetFQDNs()) > 0, log: log, recorder: recorder, + allocation: allocation, } } @@ -173,30 +180,30 @@ func (f *Firewall) Reconcile() (updated bool, err error) { } func (f *Firewall) ReconcileNetconfTables() error { - c, err := netconf.New(network.GetLogger(), network.MetalNetworkerConfig) - if err != nil || c == nil { - return fmt.Errorf("failed to init networker config: %w", err) - } - - c.Networks = network.GetNewNetworks(f.firewall, c.Networks) - - configurator, err := netconf.NewConfigurator(netconf.Firewall, *c, f.enableDNS) + f.allocation.Networks = network.GetNewNetworks(f.firewall, f.allocation.Networks) + + changed, err := nftables.Render(context.Background(), &nftables.Config{ + Log: slog.New(logr.ToSlogHandler(f.log)), + Reload: true, + Validate: true, + EnableDNSProxy: f.enableDNS, + ForwardPolicy: nftables.ForwardPolicyAccept, + Network: osnet.New(f.allocation), + }) if err != nil { - return fmt.Errorf("failed to init networker configurator: %w", err) + return fmt.Errorf("failed to render nftables: %w", err) + } + if changed { + f.log.Info("nftables rules have changed") } - configurator.ConfigureNftables(netconf.ForwardPolicyAccept) return nil } -func getConfiguredIPs(networkID string) []string { - c, err := netconf.New(network.GetLogger(), network.MetalNetworkerConfig) - if err != nil || c == nil { - return nil - } +func (f *Firewall) getConfiguredIPs(networkID string) []string { var ips []string - for _, nw := range c.Networks { - if nw.Networkid == nil || *nw.Networkid != networkID { + for _, nw := range osnet.New(f.allocation).AllocationNetworks() { + if nw.Network != networkID { continue } for _, ip := range nw.Ips { @@ -251,7 +258,7 @@ func (f *Firewall) reconcileIfaceAddresses() error { continue } - configureIPs := getConfiguredIPs(*n.NetworkID) + configureIPs := f.getConfiguredIPs(*n.NetworkID) wantedIPs := sets.NewString(configureIPs...) for _, i := range f.firewall.Spec.EgressRules { diff --git a/pkg/nftables/mocks/pkg/nftables/FQDNCache.go b/pkg/nftables/mocks/pkg/nftables/FQDNCache.go index 2c219fe6..08bf05a7 100644 --- a/pkg/nftables/mocks/pkg/nftables/FQDNCache.go +++ b/pkg/nftables/mocks/pkg/nftables/FQDNCache.go @@ -38,7 +38,7 @@ func (_m *FQDNCache) EXPECT() *FQDNCache_Expecter { } // CacheAddr provides a mock function for the type FQDNCache -func (_mock *FQDNCache) CacheAddr() (string, error) { +func (_mock *FQDNCache) CacheAddr() string { ret := _mock.Called() if len(ret) == 0 { @@ -46,21 +46,12 @@ func (_mock *FQDNCache) CacheAddr() (string, error) { } var r0 string - var r1 error - if returnFunc, ok := ret.Get(0).(func() (string, error)); ok { - return returnFunc() - } if returnFunc, ok := ret.Get(0).(func() string); ok { r0 = returnFunc() } else { r0 = ret.Get(0).(string) } - if returnFunc, ok := ret.Get(1).(func() error); ok { - r1 = returnFunc() - } else { - r1 = ret.Error(1) - } - return r0, r1 + return r0 } // FQDNCache_CacheAddr_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CacheAddr' @@ -80,12 +71,12 @@ func (_c *FQDNCache_CacheAddr_Call) Run(run func()) *FQDNCache_CacheAddr_Call { return _c } -func (_c *FQDNCache_CacheAddr_Call) Return(s string, err error) *FQDNCache_CacheAddr_Call { - _c.Call.Return(s, err) +func (_c *FQDNCache_CacheAddr_Call) Return(s string) *FQDNCache_CacheAddr_Call { + _c.Call.Return(s) return _c } -func (_c *FQDNCache_CacheAddr_Call) RunAndReturn(run func() (string, error)) *FQDNCache_CacheAddr_Call { +func (_c *FQDNCache_CacheAddr_Call) RunAndReturn(run func() string) *FQDNCache_CacheAddr_Call { _c.Call.Return(run) return _c } @@ -116,7 +107,7 @@ type FQDNCache_GetSetsForFQDN_Call struct { // GetSetsForFQDN is a helper method to define mock.On call // - fqdn v1.FQDNSelector -func (_e *FQDNCache_Expecter) GetSetsForFQDN(fqdn interface{}) *FQDNCache_GetSetsForFQDN_Call { +func (_e *FQDNCache_Expecter) GetSetsForFQDN(fqdn any) *FQDNCache_GetSetsForFQDN_Call { return &FQDNCache_GetSetsForFQDN_Call{Call: _e.mock.On("GetSetsForFQDN", fqdn)} } @@ -169,7 +160,7 @@ type FQDNCache_GetSetsForRendering_Call struct { // GetSetsForRendering is a helper method to define mock.On call // - fqdns []v1.FQDNSelector -func (_e *FQDNCache_Expecter) GetSetsForRendering(fqdns interface{}) *FQDNCache_GetSetsForRendering_Call { +func (_e *FQDNCache_Expecter) GetSetsForRendering(fqdns any) *FQDNCache_GetSetsForRendering_Call { return &FQDNCache_GetSetsForRendering_Call{Call: _e.mock.On("GetSetsForRendering", fqdns)} } diff --git a/pkg/nftables/networkpolicy.go b/pkg/nftables/networkpolicy.go index 4e13de38..ebc95b5a 100644 --- a/pkg/nftables/networkpolicy.go +++ b/pkg/nftables/networkpolicy.go @@ -60,10 +60,7 @@ func clusterwideNetworkPolicyIngressRules(np firewallv1.ClusterwideNetworkPolicy } func clusterwideNetworkPolicyEgressDNSCacheRules(cache FQDNCache, logAcceptedConnections bool) (nftablesRules, error) { - addr, err := cache.CacheAddr() - if err != nil { - return nil, err - } + addr := cache.CacheAddr() base := []string{"ip saddr == @cluster_prefixes", fmt.Sprintf("ip daddr { %s }", addr)} comment := "accept intercepted traffic for dns cache" return nftablesRules{ diff --git a/pkg/nftables/ratelimit_test.go b/pkg/nftables/ratelimit_test.go index 814ef94f..90fc97a1 100644 --- a/pkg/nftables/ratelimit_test.go +++ b/pkg/nftables/ratelimit_test.go @@ -80,7 +80,7 @@ func TestRateLimitRules(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - f := NewFirewall(&firewallv2.Firewall{Spec: tt.input.Spec, Status: tt.input.Status}, &firewallv1.ClusterwideNetworkPolicyList{}, nil, nil, logr.Discard(), nil) + f := NewFirewall(&firewallv2.Firewall{Spec: tt.input.Spec, Status: tt.input.Status}, &firewallv1.ClusterwideNetworkPolicyList{}, nil, nil, logr.Discard(), nil, nil) got := rateLimitRules(f) if !cmp.Equal(got, tt.want) { t.Errorf("rateLimitRules() diff: %v", cmp.Diff(got, tt.want)) diff --git a/pkg/nftables/service_test.go b/pkg/nftables/service_test.go index bae4e2f9..7f2b6ae1 100644 --- a/pkg/nftables/service_test.go +++ b/pkg/nftables/service_test.go @@ -16,11 +16,6 @@ func helpMustParseIPSet(ips []string) *netipx.IPSet { return res } -func port(p int) *intstr.IntOrString { - intstr := intstr.FromInt(p) - return &intstr -} - func TestServiceRules(t *testing.T) { type want struct { ingress nftablesRules @@ -45,7 +40,7 @@ func TestServiceRules(t *testing.T) { Ports: []corev1.ServicePort{ { Port: 443, - TargetPort: *port(30443), + TargetPort: intstr.FromInt(30443), Protocol: corev1.ProtocolTCP, }, }, @@ -78,7 +73,7 @@ func TestServiceRules(t *testing.T) { Ports: []corev1.ServicePort{ { Port: 443, - TargetPort: *port(30443), + TargetPort: intstr.FromInt(30443), Protocol: corev1.ProtocolTCP, }, }, @@ -94,7 +89,7 @@ func TestServiceRules(t *testing.T) { Ports: []corev1.ServicePort{ { Port: 443, - TargetPort: *port(30443), + TargetPort: intstr.FromInt(30443), Protocol: corev1.ProtocolTCP, }, }, @@ -115,7 +110,7 @@ func TestServiceRules(t *testing.T) { Ports: []corev1.ServicePort{ { Port: 443, - TargetPort: *port(30443), + TargetPort: intstr.FromInt(30443), Protocol: corev1.ProtocolTCP, }, }, @@ -153,7 +148,7 @@ func TestServiceRules(t *testing.T) { Ports: []corev1.ServicePort{ { Port: 443, - TargetPort: *port(30443), + TargetPort: intstr.FromInt(30443), Protocol: corev1.ProtocolTCP, }, }, @@ -191,7 +186,7 @@ func TestServiceRules(t *testing.T) { Ports: []corev1.ServicePort{ { Port: 443, - TargetPort: *port(30443), + TargetPort: intstr.FromInt(30443), Protocol: corev1.ProtocolTCP, }, }, diff --git a/pkg/nftables/snat_test.go b/pkg/nftables/snat_test.go index 8b9bde97..2d291ceb 100644 --- a/pkg/nftables/snat_test.go +++ b/pkg/nftables/snat_test.go @@ -196,7 +196,7 @@ func TestSnatRules(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - f := NewFirewall(&firewallv2.Firewall{Spec: tt.input.Spec, Status: tt.input.Status}, &tt.cwnps, nil, nil, logr.Discard(), nil) + f := NewFirewall(&firewallv2.Firewall{Spec: tt.input.Spec, Status: tt.input.Status}, &tt.cwnps, nil, nil, logr.Discard(), nil, nil) got, err := snatRules(f) if (err != nil) != tt.wantErr { t.Errorf("snatRules() error = %v, wantErr %v", err, tt.err)