From b28404788f329453967adc850cb0e290a56464af Mon Sep 17 00:00:00 2001 From: Ori Braunshtein Date: Tue, 30 Jun 2026 13:48:15 +0300 Subject: [PATCH 1/2] Expose frrk8sConfig.secretPassthrough in MetalLB CR Allows passing BGP secret references to frr-k8s without resolving them to cleartext. Requires frr-k8s external mode. The secret must exist in the frr-k8s namespace in order for frr-k8s to read it. Co-Authored-By: Claude Opus 4.6 (1M context) Signed-off-by: Ori Braunshtein (cherry picked from commit 59e506ec3d8102882da435038a25bbdd687d0f68) (cherry picked from commit 1469dd0706a89987a47839c9792eebc5053f30c9) --- api/v1beta1/metallb_types.go | 5 +++ bin/metallb-operator.yaml | 6 +++ bundle/manifests/metallb.io_metallbs.yaml | 6 +++ config/crd/bases/metallb.io_metallbs.yaml | 6 +++ pkg/helm/metallb.go | 11 +++-- pkg/helm/metallb_test.go | 55 +++++++++++++++++++++++ 6 files changed, 86 insertions(+), 3 deletions(-) diff --git a/api/v1beta1/metallb_types.go b/api/v1beta1/metallb_types.go index 48e7173df..734c1cc50 100644 --- a/api/v1beta1/metallb_types.go +++ b/api/v1beta1/metallb_types.go @@ -106,6 +106,11 @@ type FRRK8SConfig struct { AlwaysBlock []string `json:"alwaysBlock,omitempty"` // The namespace frr-k8s is running on in case of frr-k8s external mode Namespace string `json:"namespace,omitempty"` + // When set, BGP secret references are passed to frr-k8s without resolving them. + // The secret must exist in the frr-k8s namespace. + // Only valid when frr-k8s runs in external mode. + // +optional + SecretPassthrough bool `json:"secretPassthrough,omitempty"` } type Config struct { diff --git a/bin/metallb-operator.yaml b/bin/metallb-operator.yaml index b417b4043..68ca3d248 100644 --- a/bin/metallb-operator.yaml +++ b/bin/metallb-operator.yaml @@ -3071,6 +3071,12 @@ spec: description: The namespace frr-k8s is running on in case of frr-k8s external mode type: string + secretPassthrough: + description: |- + When set, BGP secret references are passed to frr-k8s without resolving them. + The secret must exist in the frr-k8s namespace. + Only valid when frr-k8s runs in external mode. + type: boolean type: object image: description: Foo is an example field of MetalLB. Edit MetalLB_types.go diff --git a/bundle/manifests/metallb.io_metallbs.yaml b/bundle/manifests/metallb.io_metallbs.yaml index a87206b65..2c42a2b6c 100644 --- a/bundle/manifests/metallb.io_metallbs.yaml +++ b/bundle/manifests/metallb.io_metallbs.yaml @@ -1099,6 +1099,12 @@ spec: description: The namespace frr-k8s is running on in case of frr-k8s external mode type: string + secretPassthrough: + description: |- + When set, BGP secret references are passed to frr-k8s without resolving them. + The secret must exist in the frr-k8s namespace. + Only valid when frr-k8s runs in external mode. + type: boolean type: object image: description: Foo is an example field of MetalLB. Edit MetalLB_types.go diff --git a/config/crd/bases/metallb.io_metallbs.yaml b/config/crd/bases/metallb.io_metallbs.yaml index e764520b2..2b02d89e9 100644 --- a/config/crd/bases/metallb.io_metallbs.yaml +++ b/config/crd/bases/metallb.io_metallbs.yaml @@ -1099,6 +1099,12 @@ spec: description: The namespace frr-k8s is running on in case of frr-k8s external mode type: string + secretPassthrough: + description: |- + When set, BGP secret references are passed to frr-k8s without resolving them. + The secret must exist in the frr-k8s namespace. + Only valid when frr-k8s runs in external mode. + type: boolean type: object image: description: Foo is an example field of MetalLB. Edit MetalLB_types.go diff --git a/pkg/helm/metallb.go b/pkg/helm/metallb.go index 5180ff19a..c2c04abd3 100644 --- a/pkg/helm/metallb.go +++ b/pkg/helm/metallb.go @@ -355,10 +355,15 @@ func metalLBFrrk8sValues(envConfig params.EnvConfig, crdConfig *metallbv1beta1.M if params.BGPType(crdConfig, envConfig) == metallbv1beta1.FRRK8sExternalMode { external = true } + secretPassthrough := false + if crdConfig.Spec.FRRK8SConfig != nil { + secretPassthrough = crdConfig.Spec.FRRK8SConfig.SecretPassthrough + } frrk8sValuesMap := map[string]interface{}{ - "enabled": enabled, - "external": external, - "namespace": frrK8sNamespace, + "enabled": enabled, + "external": external, + "namespace": frrK8sNamespace, + "secretPassthrough": secretPassthrough, } return frrk8sValuesMap } diff --git a/pkg/helm/metallb_test.go b/pkg/helm/metallb_test.go index 320e74ae0..5e9c75ba3 100644 --- a/pkg/helm/metallb_test.go +++ b/pkg/helm/metallb_test.go @@ -228,6 +228,61 @@ func TestParseMetalLBChartWithCustomValues(t *testing.T) { g.Expect(isControllerFound).To(BeTrue()) } +func TestSecretPassthrough(t *testing.T) { + tests := []struct { + name string + secretPassthrough bool + expectFlag bool + }{ + {"enabled", true, true}, + {"disabled", false, false}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + g := NewGomegaWithT(t) + chart, err := NewMetalLBChart(metalLBChartPath, metalLBChartName, MetalLBTestNameSpace, nil) + g.Expect(err).To(BeNil()) + + metallb := &metallbv1beta1.MetalLB{ + ObjectMeta: metav1.ObjectMeta{ + Name: "metallb", + Namespace: MetalLBTestNameSpace, + }, + Spec: metallbv1beta1.MetalLBSpec{ + BGPBackend: metallbv1beta1.FRRK8sExternalMode, + FRRK8SConfig: &metallbv1beta1.FRRK8SConfig{ + Namespace: "frr-k8s-external-namespace", + SecretPassthrough: tt.secretPassthrough, + }, + }, + } + + objs, err := chart.Objects(defaultEnvConfig, metallb) + g.Expect(err).To(BeNil()) + var speakerFound bool + for _, obj := range objs { + if obj.GetKind() == "DaemonSet" && obj.GetName() == speakerDaemonSet { + speaker := appsv1.DaemonSet{} + err = runtime.DefaultUnstructuredConverter.FromUnstructured(obj.UnstructuredContent(), &speaker) + g.Expect(err).To(BeNil()) + for _, container := range speaker.Spec.Template.Spec.Containers { + if container.Name == "speaker" { + if tt.expectFlag { + g.Expect(container.Args).To(ContainElement("--frrk8s-secret-passthrough")) + } else { + g.Expect(container.Args).NotTo(ContainElement("--frrk8s-secret-passthrough")) + } + g.Expect(container.Args).To(ContainElement("--frrk8s-namespace=frr-k8s-external-namespace")) + speakerFound = true + } + } + } + } + g.Expect(speakerFound).To(BeTrue()) + }) + } +} + func TestParseOCPSecureMetrics(t *testing.T) { g := NewGomegaWithT(t) From 17d409ae00d3d1d88928925a12fe104a9efd0468 Mon Sep 17 00:00:00 2001 From: Ori Braunshtein Date: Wed, 15 Jul 2026 11:53:50 +0300 Subject: [PATCH 2/2] OpenShift Only: sync bundle with secretPassthrough Signed-off-by: Ori Braunshtein (cherry picked from commit dc49d003d6939b3d3e586df07984f7080419799d) --- manifests/stable/metallb.io_metallbs.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/manifests/stable/metallb.io_metallbs.yaml b/manifests/stable/metallb.io_metallbs.yaml index 5d90faeba..c5be9c644 100644 --- a/manifests/stable/metallb.io_metallbs.yaml +++ b/manifests/stable/metallb.io_metallbs.yaml @@ -1101,6 +1101,12 @@ spec: description: The namespace frr-k8s is running on in case of frr-k8s external mode type: string + secretPassthrough: + description: |- + When set, BGP secret references are passed to frr-k8s without resolving them. + The secret must exist in the frr-k8s namespace. + Only valid when frr-k8s runs in external mode. + type: boolean type: object image: description: Foo is an example field of MetalLB. Edit MetalLB_types.go