Repository: metallb/metallb
Pull request #1956 (2023-05-26 02:58:37)

Bump github.com/prometheus/common from 0.42.0 to 0.44.0
Bumps [github.com/prometheus/common](https://github.com/prometheus/common) from 0.42.0 to 0.44.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a href="https://github.com/prometheus/common/releases">github.com/prometheus/common's releases</a>.</em></p>
<blockquote>
<h2>v0.44.0</h2>
<h2>What's Changed</h2>
<ul>
<li>Allow custom log.Logger by <a href="https://github.com/jkroepke"><code>@​jkroepke</code></a> in <a href="https://redirect.github.com/prometheus/common/pull/474">prometheus/common#474</a></li>
<li>Allow TLS settings to be specified inline by <a href="https://github.com/rfratto"><code>@​rfratto</code></a> in <a href="https://redirect.github.com/prometheus/common/pull/472">prometheus/common#472</a></li>
<li>Enable dependabot for sigv4 by <a href="https://github.com/SuperQ"><code>@​SuperQ</code></a> in <a href="https://redirect.github.com/prometheus/common/pull/480">prometheus/common#480</a></li>
<li>Bump github.com/prometheus/common from 0.42.0 to 0.43.0 in /sigv4 by <a href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a href="https://redirect.github.com/prometheus/common/pull/486">prometheus/common#486</a></li>
<li>Bump golang.org/x/net from 0.9.0 to 0.10.0 by <a href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a href="https://redirect.github.com/prometheus/common/pull/483">prometheus/common#483</a></li>
<li>Bump github.com/stretchr/testify from 1.8.0 to 1.8.2 in /sigv4 by <a href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a href="https://redirect.github.com/prometheus/common/pull/485">prometheus/common#485</a></li>
<li>Bump golang.org/x/oauth2 from 0.7.0 to 0.8.0 by <a href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a href="https://redirect.github.com/prometheus/common/pull/482">prometheus/common#482</a></li>
<li>Bump github.com/aws/aws-sdk-go from 1.43.26 to 1.44.266 in /sigv4 by <a href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a href="https://redirect.github.com/prometheus/common/pull/489">prometheus/common#489</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/jkroepke"><code>@​jkroepke</code></a> made their first contribution in <a href="https://redirect.github.com/prometheus/common/pull/474">prometheus/common#474</a></li>
<li><a href="https://github.com/rfratto"><code>@​rfratto</code></a> made their first contribution in <a href="https://redirect.github.com/prometheus/common/pull/472">prometheus/common#472</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a href="https://github.com/prometheus/common/compare/v0.43.0...v0.43.1">https://github.com/prometheus/common/compare/v0.43.0...v0.43.1</a></p>
<h2>0.43.0 / 2023-05-04</h2>
<p>NOTE: The protobuf library has been changed from the deprecated <code>github.com/golang/protobuf</code> to the new officially supported <code>google.golang.org/protobuf</code>. If you have direct use of the proto, you may need to make changes for deprecated functions.</p>
<h2>What's Changed</h2>
<ul>
<li>Synchronize common files from prometheus/prometheus by <a href="https://github.com/prombot"><code>@​prombot</code></a> in <a href="https://redirect.github.com/prometheus/common/pull/463">prometheus/common#463</a></li>
<li>Negotiate OM v1.0.0 by <a href="https://github.com/gouthamve"><code>@​gouthamve</code></a> in <a href="https://redirect.github.com/prometheus/common/pull/475">prometheus/common#475</a></li>
<li>Bump golang.org/x/oauth2 from 0.5.0 to 0.7.0 by <a href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a href="https://redirect.github.com/prometheus/common/pull/478">prometheus/common#478</a></li>
<li>Bump github.com/prometheus/client_golang from 1.14.0 to 1.15.1 by <a href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a href="https://redirect.github.com/prometheus/common/pull/481">prometheus/common#481</a></li>
<li>Update Go modules by <a href="https://github.com/SuperQ"><code>@​SuperQ</code></a> in <a href="https://redirect.github.com/prometheus/common/pull/479">prometheus/common#479</a></li>
<li>Bump github.com/alecthomas/kingpin/v2 from 2.3.1 to 2.3.2 by <a href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a href="https://redirect.github.com/prometheus/common/pull/469">prometheus/common#469</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a href="https://github.com/prometheus/common/compare/v0.42.0...v0.43.0">https://github.com/prometheus/common/compare/v0.42.0...v0.43.0</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/prometheus/common/commit/94bf9828e56d9670579b28a9f78237d3cd8d0395"><code>94bf982</code></a> Merge pull request <a href="https://redirect.github.com/prometheus/common/issues/489">#489</a> from prometheus/dependabot/go_modules/sigv4/github.co...</li>
<li><a href="https://github.com/prometheus/common/commit/211d8fc4fe80f8e10e8a86f302791f4423a5a399"><code>211d8fc</code></a> Bump github.com/aws/aws-sdk-go from 1.43.26 to 1.44.266 in /sigv4</li>
<li><a href="https://github.com/prometheus/common/commit/ac0672340e5d40ed48492d0ff562bbd2bc613a98"><code>ac06723</code></a> Merge pull request <a href="https://redirect.github.com/prometheus/common/issues/482">#482</a> from prometheus/dependabot/go_modules/golang.org/x/oa...</li>
<li><a href="https://github.com/prometheus/common/commit/062aaeca9159a27ab55b03093baa2a9a8b4c6ea0"><code>062aaec</code></a> Merge pull request <a href="https://redirect.github.com/prometheus/common/issues/485">#485</a> from prometheus/dependabot/go_modules/sigv4/github.co...</li>
<li><a href="https://github.com/prometheus/common/commit/24a8815b146428161542dfe78206acd03e628d24"><code>24a8815</code></a> Bump github.com/stretchr/testify from 1.8.0 to 1.8.2 in /sigv4</li>
<li><a href="https://github.com/prometheus/common/commit/27af2c40490023c253bce01d677b7279cdb17ec1"><code>27af2c4</code></a> Bump golang.org/x/oauth2 from 0.7.0 to 0.8.0</li>
<li><a href="https://github.com/prometheus/common/commit/2f0f5c4b6d958963f2a8d5447ad27ca7a931dcda"><code>2f0f5c4</code></a> Merge pull request <a href="https://redirect.github.com/prometheus/common/issues/483">#483</a> from prometheus/dependabot/go_modules/golang.org/x/ne...</li>
<li><a href="https://github.com/prometheus/common/commit/96ade150bade73ca829fabb644117b38d7bc0c51"><code>96ade15</code></a> Merge pull request <a href="https://redirect.github.com/prometheus/common/issues/486">#486</a> from prometheus/dependabot/go_modules/sigv4/github.co...</li>
<li><a href="https://github.com/prometheus/common/commit/68e477e0a9e4f8da916aea7749f8864bbc3bcc20"><code>68e477e</code></a> Bump github.com/prometheus/common from 0.42.0 to 0.43.0 in /sigv4</li>
<li><a href="https://github.com/prometheus/common/commit/73645186918dfa40aff773e71f8c00a2ba0eb5d9"><code>7364518</code></a> Bump golang.org/x/net from 0.9.0 to 0.10.0</li>
<li>Additional commits viewable in <a href="https://github.com/prometheus/common/compare/v0.42.0...v0.44.0">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/prometheus/common&package-manager=go_modules&previous-version=0.42.0&new-version=0.44.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)


</details>


Patch:
diff --git a/charts/metallb/templates/controller.yaml b/charts/metallb/templates/controller.yaml
index 5ba71891..2b522d1b 100644
--- a/charts/metallb/templates/controller.yaml
+++ b/charts/metallb/templates/controller.yaml
@@ -3,6 +3,7 @@ apiVersion: apps/v1
 kind: Deployment
 metadata:
   name: {{ template "metallb.fullname" . }}-controller
+  namespace: {{ .Release.Namespace | quote }}
   labels:
     {{- include "metallb.labels" . | nindent 4 }}
     app.kubernetes.io/component: controller
diff --git a/charts/metallb/templates/exclude-l2-config.yaml b/charts/metallb/templates/exclude-l2-config.yaml
index 7cc2ff34..f3302eb4 100644
--- a/charts/metallb/templates/exclude-l2-config.yaml
+++ b/charts/metallb/templates/exclude-l2-config.yaml
@@ -3,6 +3,7 @@ apiVersion: v1
 kind: ConfigMap
 metadata:
   name: metallb-excludel2
+  namespace: {{ .Release.Namespace | quote }}
 data:
   excludel2.yaml: |
     announcedInterfacesToExclude:
diff --git a/charts/metallb/templates/rbac.yaml b/charts/metallb/templates/rbac.yaml
index 6a38304b..ed6b8260 100644
--- a/charts/metallb/templates/rbac.yaml
+++ b/charts/metallb/templates/rbac.yaml
@@ -71,6 +71,7 @@ apiVersion: rbac.authorization.k8s.io/v1
 kind: Role
 metadata:
   name: {{ include "metallb.fullname" . }}-pod-lister
+  namespace: {{ .Release.Namespace | quote }}
   labels: {{- include "metallb.labels" . | nindent 4 }}
 rules:
 - apiGroups: [""]
@@ -108,6 +109,7 @@ apiVersion: rbac.authorization.k8s.io/v1
 kind: Role
 metadata:
   name: {{ include "metallb.fullname" . }}-controller
+  namespace: {{ .Release.Namespace | quote }}
   labels: {{- include "metallb.labels" . | nindent 4 }}
 rules:
 {{- if .Values.speaker.memberlist.enabled }}
@@ -182,6 +184,7 @@ apiVersion: rbac.authorization.k8s.io/v1
 kind: RoleBinding
 metadata:
   name: {{ include "metallb.fullname" . }}-pod-lister
+  namespace: {{ .Release.Namespace | quote }}
   labels: {{- include "metallb.labels" . | nindent 4 }}
 roleRef:
   apiGroup: rbac.authorization.k8s.io
@@ -195,6 +198,7 @@ apiVersion: rbac.authorization.k8s.io/v1
 kind: RoleBinding
 metadata:
   name: {{ include "metallb.fullname" . }}-controller
+  namespace: {{ .Release.Namespace | quote }}
   labels: {{- include "metallb.labels" . | nindent 4 }}
 roleRef:
   apiGroup: rbac.authorization.k8s.io
diff --git a/charts/metallb/templates/service-accounts.yaml b/charts/metallb/templates/service-accounts.yaml
index 95609e5e..9615acf3 100644
--- a/charts/metallb/templates/service-accounts.yaml
+++ b/charts/metallb/templates/service-accounts.yaml
@@ -4,6 +4,7 @@ apiVersion: v1
 kind: ServiceAccount
 metadata:
   name: {{ template "metallb.controller.serviceAccountName" . }}
+  namespace: {{ .Release.Namespace | quote }}
   labels:
     {{- include "metallb.labels" . | nindent 4 }}
     app.kubernetes.io/component: controller
@@ -18,6 +19,7 @@ apiVersion: v1
 kind: ServiceAccount
 metadata:
   name: {{ template "metallb.speaker.serviceAccountName" . }}
+  namespace: {{ .Release.Namespace | quote }}
   labels:
     {{- include "metallb.labels" . | nindent 4 }}
     app.kubernetes.io/component: speaker
diff --git a/charts/metallb/templates/servicemonitor.yaml b/charts/metallb/templates/servicemonitor.yaml
index 1d8563d2..1cfc0c43 100644
--- a/charts/metallb/templates/servicemonitor.yaml
+++ b/charts/metallb/templates/servicemonitor.yaml
@@ -3,6 +3,7 @@ apiVersion: monitoring.coreos.com/v1
 kind: ServiceMonitor
 metadata:
   name: {{ template "metallb.fullname" . }}-speaker-monitor
+  namespace: {{ .Release.Namespace | quote }}
   labels:
     {{- include "metallb.labels" . | nindent 4 }}
     app.kubernetes.io/component: speaker
@@ -70,6 +71,7 @@ metadata:
   labels:
     name: {{ template "metallb.fullname" . }}-speaker-monitor-service
   name: {{ template "metallb.fullname" . }}-speaker-monitor-service
+  namespace: {{ .Release.Namespace | quote }}
 spec:
   selector:
     {{- include "metallb.selectorLabels" . | nindent 4 }}
@@ -91,6 +93,7 @@ apiVersion: monitoring.coreos.com/v1
 kind: ServiceMonitor
 metadata:
   name: {{ template "metallb.fullname" . }}-controller-monitor
+  namespace: {{ .Release.Namespace | quote }}
   labels:
     {{- include "metallb.labels" . | nindent 4 }}
     app.kubernetes.io/component: speaker
@@ -160,6 +163,7 @@ apiVersion: rbac.authorization.k8s.io/v1
 kind: Role
 metadata:
   name: {{ template "metallb.fullname" . }}-prometheus
+  namespace: {{ .Release.Namespace | quote }}
 rules:
   - apiGroups:
       - ""
@@ -176,6 +180,7 @@ apiVersion: rbac.authorization.k8s.io/v1
 kind: RoleBinding
 metadata:
   name: {{ template "metallb.fullname" . }}-prometheus
+  namespace: {{ .Release.Namespace | quote }}
 roleRef:
   apiGroup: rbac.authorization.k8s.io
   kind: Role
diff --git a/charts/metallb/templates/speaker.yaml b/charts/metallb/templates/speaker.yaml
index 4bbbfb1d..9ba24b55 100644
--- a/charts/metallb/templates/speaker.yaml
+++ b/charts/metallb/templates/speaker.yaml
@@ -5,6 +5,7 @@ apiVersion: v1
 kind: ConfigMap
 metadata:
   name: {{ template "metallb.fullname" . }}-frr-startup
+  namespace: {{ .Release.Namespace | quote }}
   labels:
     {{- include "metallb.labels" . | nindent 4 }}
     app.kubernetes.io/component: speaker
@@ -107,6 +108,7 @@ apiVersion: apps/v1
 kind: DaemonSet
 metadata:
   name: {{ template "metallb.fullname" . }}-speaker
+  namespace: {{ .Release.Namespace | quote }}
   labels:
     {{- include "metallb.labels" . | nindent 4 }}
     app.kubernetes.io/component: speaker
diff --git a/charts/metallb/templates/webhooks.yaml b/charts/metallb/templates/webhooks.yaml
index 3f3d5ed7..3b587a42 100644
--- a/charts/metallb/templates/webhooks.yaml
+++ b/charts/metallb/templates/webhooks.yaml
@@ -150,6 +150,7 @@ apiVersion: v1
 kind: Service
 metadata:
   name: metallb-webhook-service
+  namespace: {{ .Release.Namespace | quote }}
   labels:
     {{- include "metallb.labels" . | nindent 4 }}
 spec:
@@ -164,5 +165,6 @@ apiVersion: v1
 kind: Secret
 metadata:
   name: webhook-server-cert
+  namespace: {{ .Release.Namespace | quote }}
   labels:
     {{- include "metallb.labels" . | nindent 4 }}
diff --git a/config/crd/kustomization.yaml b/config/crd/kustomization.yaml
index 919e4bf0..5bcf1339 100644
--- a/config/crd/kustomization.yaml
+++ b/config/crd/kustomization.yaml
@@ -1,13 +1,20 @@
 apiVersion: kustomize.config.k8s.io/v1beta1
 kind: Kustomization
 resources:
-  - bases/metallb.io_addresspools.yaml
-  - bases/metallb.io_ipaddresspools.yaml
-  - bases/metallb.io_bgppeers.yaml
-  - bases/metallb.io_bfdprofiles.yaml
-  - bases/metallb.io_bgpadvertisements.yaml
-  - bases/metallb.io_l2advertisements.yaml
-  - bases/metallb.io_communities.yaml
+- bases/metallb.io_addresspools.yaml
+- bases/metallb.io_ipaddresspools.yaml
+- bases/metallb.io_bgppeers.yaml
+- bases/metallb.io_bfdprofiles.yaml
+- bases/metallb.io_bgpadvertisements.yaml
+- bases/metallb.io_l2advertisements.yaml
+- bases/metallb.io_communities.yaml
 
-patchesStrategicMerge:
-- crd-conversion-patch.yaml
+patches:
+- path: patches/crd-conversion-patch-addresspools.yaml
+  target:
+    kind: CustomResourceDefinition
+    name: addresspools.metallb.io
+- path: patches/crd-conversion-patch-bgppeers.yaml
+  target:
+    kind: CustomResourceDefinition
+    name: bgppeers.metallb.io
diff --git a/config/crd/crd-conversion-patch.yaml b/config/crd/patches/crd-conversion-patch-addresspools.yaml
similarity index 50%
rename from config/crd/crd-conversion-patch.yaml
rename to config/crd/patches/crd-conversion-patch-addresspools.yaml
index 9f40f6c3..07dae1b1 100644
--- a/config/crd/crd-conversion-patch.yaml
+++ b/config/crd/patches/crd-conversion-patch-addresspools.yaml
@@ -17,21 +17,3 @@ spec:
           namespace: metallb-system
           name: webhook-service
           path: /convert
----
-apiVersion: apiextensions.k8s.io/v1
-kind: CustomResourceDefinition
-metadata:
-  name: bgppeers.metallb.io
-spec:
-  conversion:
-    strategy: Webhook
-    webhook:
-      conversionReviewVersions: ["v1beta1", "v1beta2"]
-      clientConfig:
-        # this is a valid pem format, otherwise the apiserver will reject the deletion of the crds
-        # with "unable to parse bytes as PEM block", The controller will patch it with the right content after it starts
-        caBundle: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlGWlRDQ0EwMmdBd0lCQWdJVU5GRW1XcTM3MVpKdGkrMmlSQzk1WmpBV1MxZ3dEUVlKS29aSWh2Y05BUUVMDQpCUUF3UWpFTE1Ba0dBMVVFQmhNQ1dGZ3hGVEFUQmdOVkJBY01ERVJsWm1GMWJIUWdRMmwwZVRFY01Cb0dBMVVFDQpDZ3dUUkdWbVlYVnNkQ0JEYjIxd1lXNTVJRXgwWkRBZUZ3MHlNakEzTVRrd09UTXlNek5hRncweU1qQTRNVGd3DQpPVE15TXpOYU1FSXhDekFKQmdOVkJBWVRBbGhZTVJVd0V3WURWUVFIREF4RVpXWmhkV3gwSUVOcGRIa3hIREFhDQpCZ05WQkFvTUUwUmxabUYxYkhRZ1EyOXRjR0Z1ZVNCTWRHUXdnZ0lpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElDDQpEd0F3Z2dJS0FvSUNBUUNxVFpxMWZRcC9vYkdlenhES0o3OVB3Ny94azJwellualNzMlkzb1ZYSm5sRmM4YjVlDQpma2ZZQnY2bndscW1keW5PL2phWFBaQmRQSS82aFdOUDBkdVhadEtWU0NCUUpyZzEyOGNXb3F0MGNTN3pLb1VpDQpvcU1tQ0QvRXVBeFFNZjhRZDF2c1gvVllkZ0poVTZBRXJLZEpIaXpFOUJtUkNkTDBGMW1OVW55Rk82UnRtWFZUDQpidkxsTDVYeTc2R0FaQVBLOFB4aVlDa0NtbDdxN0VnTWNiOXlLWldCYmlxQ3VkTXE5TGJLNmdKNzF6YkZnSXV4DQo1L1pXK2JraTB2RlplWk9ZODUxb1psckFUNzJvMDI4NHNTWW9uN0pHZVZkY3NoUnh5R1VpSFpSTzdkaXZVTDVTDQpmM2JmSDFYbWY1ZDQzT0NWTWRuUUV2NWVaOG8zeWVLa3ZrbkZQUGVJMU9BbjdGbDlFRVNNR2dhOGFaSG1URSttDQpsLzlMSmdDYjBnQmtPT0M0WnV4bWh2aERKV1EzWnJCS3pMQlNUZXN0NWlLNVlwcXRWVVk2THRyRW9FelVTK1lsDQpwWndXY2VQWHlHeHM5ZURsR3lNVmQraW15Y3NTU1UvVno2Mmx6MnZCS21NTXBkYldDQWhud0RsRTVqU2dyMjRRDQp0eGNXLys2N3d5KzhuQlI3UXdqVTFITndVRjBzeERWdEwrZ1NHVERnSEVZSlhZelYvT05zMy94TkpoVFNPSkxNDQpoeXNVdyttaGdackdhbUdXcHVIVU1DUitvTWJzMTc1UkcrQjJnUFFHVytPTjJnUTRyOXN2b0ZBNHBBQm8xd1dLDQpRYjRhY3pmeVVscElBOVFoSmFsZEY3S3dPSHVlV3gwRUNrNXg0T2tvVDBvWVp0dzFiR0JjRGtaSmF3SURBUUFCDQpvMU13VVRBZEJnTlZIUTRFRmdRVW90UlNIUm9IWTEyRFZ4R0NCdEhpb1g2ZmVFQXdId1lEVlIwakJCZ3dGb0FVDQpvdFJTSFJvSFkxMkRWeEdDQnRIaW9YNmZlRUF3RHdZRFZSMFRBUUgvQkFVd0F3RUIvekFOQmdrcWhraUc5dzBCDQpBUXNGQUFPQ0FnRUFSbkpsWWRjMTFHd0VxWnh6RDF2R3BDR2pDN2VWTlQ3aVY1d3IybXlybHdPYi9aUWFEa0xYDQpvVStaOVVXT1VlSXJTdzUydDdmQUpvVVAwSm5iYkMveVIrU1lqUGhvUXNiVHduOTc2ZldBWTduM3FMOXhCd1Y0DQphek41OXNjeUp0dlhMeUtOL2N5ak1ReDRLajBIMFg0bWJ6bzVZNUtzWWtYVU0vOEFPdWZMcEd0S1NGVGgrSEFDDQpab1Q5YnZHS25adnNHd0tYZFF0Wnh0akhaUjVqK3U3ZGtQOTJBT051RFNabS8rWVV4b2tBK09JbzdSR3BwSHNXDQo1ZTdNY0FTVXRtb1FORXd6dVFoVkJaRWQ1OGtKYjUrV0VWbGNzanlXNnRTbzErZ25tTWNqR1BsMWgxR2hVbjV4DQpFY0lWRnBIWXM5YWo1NmpBSjk1MVQvZjhMaWxmTlVnanBLQ0c1bnl0SUt3emxhOHNtdGlPdm1UNEpYbXBwSkI2DQo4bmdHRVluVjUrUTYwWFJ2OEhSSGp1VG9CRHVhaERrVDA2R1JGODU1d09FR2V4bkZpMXZYWUxLVllWb1V2MXRKDQo4dVdUR1pwNllDSVJldlBqbzg5ZytWTlJSaVFYUThJd0dybXE5c0RoVTlqTjA0SjdVL1RvRDFpNHE3VnlsRUc5DQorV1VGNkNLaEdBeTJIaEhwVncyTGFoOS9lUzdZMUZ1YURrWmhPZG1laG1BOCtqdHNZamJadnR5Mm1SWlF0UUZzDQpUU1VUUjREbUR2bVVPRVRmeStpRHdzK2RkWXVNTnJGeVVYV2dkMnpBQU4ydVl1UHFGY2pRcFNPODFzVTJTU3R3DQoxVzAyeUtYOGJEYmZFdjBzbUh3UzliQnFlSGo5NEM1Mjg0YXpsdTBmaUdpTm1OUEM4ckJLRmhBPQ0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ==
-        service:
-          namespace: metallb-system
-          name: webhook-service
-          path: /convert
diff --git a/config/crd/patches/crd-conversion-patch-bgppeers.yaml b/config/crd/patches/crd-conversion-patch-bgppeers.yaml
new file mode 100644
index 00000000..ebf42123
--- /dev/null
+++ b/config/crd/patches/crd-conversion-patch-bgppeers.yaml
@@ -0,0 +1,17 @@
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+  name: bgppeers.metallb.io
+spec:
+  conversion:
+    strategy: Webhook
+    webhook:
+      conversionReviewVersions: ["v1beta1", "v1beta2"]
+      clientConfig:
+        # this is a valid pem format, otherwise the apiserver will reject the deletion of the crds
+        # with "unable to parse bytes as PEM block", The controller will patch it with the right content after it starts
+        caBundle: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlGWlRDQ0EwMmdBd0lCQWdJVU5GRW1XcTM3MVpKdGkrMmlSQzk1WmpBV1MxZ3dEUVlKS29aSWh2Y05BUUVMDQpCUUF3UWpFTE1Ba0dBMVVFQmhNQ1dGZ3hGVEFUQmdOVkJBY01ERVJsWm1GMWJIUWdRMmwwZVRFY01Cb0dBMVVFDQpDZ3dUUkdWbVlYVnNkQ0JEYjIxd1lXNTVJRXgwWkRBZUZ3MHlNakEzTVRrd09UTXlNek5hRncweU1qQTRNVGd3DQpPVE15TXpOYU1FSXhDekFKQmdOVkJBWVRBbGhZTVJVd0V3WURWUVFIREF4RVpXWmhkV3gwSUVOcGRIa3hIREFhDQpCZ05WQkFvTUUwUmxabUYxYkhRZ1EyOXRjR0Z1ZVNCTWRHUXdnZ0lpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElDDQpEd0F3Z2dJS0FvSUNBUUNxVFpxMWZRcC9vYkdlenhES0o3OVB3Ny94azJwellualNzMlkzb1ZYSm5sRmM4YjVlDQpma2ZZQnY2bndscW1keW5PL2phWFBaQmRQSS82aFdOUDBkdVhadEtWU0NCUUpyZzEyOGNXb3F0MGNTN3pLb1VpDQpvcU1tQ0QvRXVBeFFNZjhRZDF2c1gvVllkZ0poVTZBRXJLZEpIaXpFOUJtUkNkTDBGMW1OVW55Rk82UnRtWFZUDQpidkxsTDVYeTc2R0FaQVBLOFB4aVlDa0NtbDdxN0VnTWNiOXlLWldCYmlxQ3VkTXE5TGJLNmdKNzF6YkZnSXV4DQo1L1pXK2JraTB2RlplWk9ZODUxb1psckFUNzJvMDI4NHNTWW9uN0pHZVZkY3NoUnh5R1VpSFpSTzdkaXZVTDVTDQpmM2JmSDFYbWY1ZDQzT0NWTWRuUUV2NWVaOG8zeWVLa3ZrbkZQUGVJMU9BbjdGbDlFRVNNR2dhOGFaSG1URSttDQpsLzlMSmdDYjBnQmtPT0M0WnV4bWh2aERKV1EzWnJCS3pMQlNUZXN0NWlLNVlwcXRWVVk2THRyRW9FelVTK1lsDQpwWndXY2VQWHlHeHM5ZURsR3lNVmQraW15Y3NTU1UvVno2Mmx6MnZCS21NTXBkYldDQWhud0RsRTVqU2dyMjRRDQp0eGNXLys2N3d5KzhuQlI3UXdqVTFITndVRjBzeERWdEwrZ1NHVERnSEVZSlhZelYvT05zMy94TkpoVFNPSkxNDQpoeXNVdyttaGdackdhbUdXcHVIVU1DUitvTWJzMTc1UkcrQjJnUFFHVytPTjJnUTRyOXN2b0ZBNHBBQm8xd1dLDQpRYjRhY3pmeVVscElBOVFoSmFsZEY3S3dPSHVlV3gwRUNrNXg0T2tvVDBvWVp0dzFiR0JjRGtaSmF3SURBUUFCDQpvMU13VVRBZEJnTlZIUTRFRmdRVW90UlNIUm9IWTEyRFZ4R0NCdEhpb1g2ZmVFQXdId1lEVlIwakJCZ3dGb0FVDQpvdFJTSFJvSFkxMkRWeEdDQnRIaW9YNmZlRUF3RHdZRFZSMFRBUUgvQkFVd0F3RUIvekFOQmdrcWhraUc5dzBCDQpBUXNGQUFPQ0FnRUFSbkpsWWRjMTFHd0VxWnh6RDF2R3BDR2pDN2VWTlQ3aVY1d3IybXlybHdPYi9aUWFEa0xYDQpvVStaOVVXT1VlSXJTdzUydDdmQUpvVVAwSm5iYkMveVIrU1lqUGhvUXNiVHduOTc2ZldBWTduM3FMOXhCd1Y0DQphek41OXNjeUp0dlhMeUtOL2N5ak1ReDRLajBIMFg0bWJ6bzVZNUtzWWtYVU0vOEFPdWZMcEd0S1NGVGgrSEFDDQpab1Q5YnZHS25adnNHd0tYZFF0Wnh0akhaUjVqK3U3ZGtQOTJBT051RFNabS8rWVV4b2tBK09JbzdSR3BwSHNXDQo1ZTdNY0FTVXRtb1FORXd6dVFoVkJaRWQ1OGtKYjUrV0VWbGNzanlXNnRTbzErZ25tTWNqR1BsMWgxR2hVbjV4DQpFY0lWRnBIWXM5YWo1NmpBSjk1MVQvZjhMaWxmTlVnanBLQ0c1bnl0SUt3emxhOHNtdGlPdm1UNEpYbXBwSkI2DQo4bmdHRVluVjUrUTYwWFJ2OEhSSGp1VG9CRHVhaERrVDA2R1JGODU1d09FR2V4bkZpMXZYWUxLVllWb1V2MXRKDQo4dVdUR1pwNllDSVJldlBqbzg5ZytWTlJSaVFYUThJd0dybXE5c0RoVTlqTjA0SjdVL1RvRDFpNHE3VnlsRUc5DQorV1VGNkNLaEdBeTJIaEhwVncyTGFoOS9lUzdZMUZ1YURrWmhPZG1laG1BOCtqdHNZamJadnR5Mm1SWlF0UUZzDQpUU1VUUjREbUR2bVVPRVRmeStpRHdzK2RkWXVNTnJGeVVYV2dkMnpBQU4ydVl1UHFGY2pRcFNPODFzVTJTU3R3DQoxVzAyeUtYOGJEYmZFdjBzbUh3UzliQnFlSGo5NEM1Mjg0YXpsdTBmaUdpTm1OUEM4ckJLRmhBPQ0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ==
+        service:
+          namespace: metallb-system
+          name: webhook-service
+          path: /convert
diff --git a/config/webhook/kustomization.yaml b/config/webhook/kustomization.yaml
index 9a8ec42b..c424c862 100644
--- a/config/webhook/kustomization.yaml
+++ b/config/webhook/kustomization.yaml
@@ -1,3 +1,6 @@
+apiVersion: kustomize.config.k8s.io/v1beta1
+kind: Kustomization
+
 resources:
 - manifests.yaml
 - service.yaml
@@ -6,9 +9,9 @@ resources:
 configurations:
 - kustomizeconfig.yaml
 
-patchesJson6902:
+patches:
 - path: patches/patch_webhook_configuration.yaml
   target:
-    version: v1
     kind: ValidatingWebhookConfiguration
     name: validating-webhook-configuration
+    version: v1
diff --git a/frr-tools/metrics/liveness/liveness.go b/frr-tools/metrics/liveness/liveness.go
index 7f9169a8..17405b34 100644
--- a/frr-tools/metrics/liveness/liveness.go
+++ b/frr-tools/metrics/liveness/liveness.go
@@ -32,7 +32,7 @@ func Handler(frrCli vtysh.Cli, logger log.Logger) http.Handler {
 			delete(expected, d)
 		}
 		if len(expected) > 0 {
-			logger.Log("daemons not running. got: ", res, "missing: ", res)
+			logger.Log("daemons not running. got: ", res, "missing: ", expected)
 			http.NotFound(w, r)
 		}
 	})
diff --git a/go.mod b/go.mod
index 050e2142..04778ccf 100644
--- a/go.mod
+++ b/go.mod
@@ -83,9 +83,8 @@ require (
 	github.com/opencontainers/image-spec v1.0.2 // indirect
 	github.com/opencontainers/runc v1.1.5 // indirect
 	github.com/prometheus/client_model v0.4.0 // indirect
-	github.com/prometheus/common v0.42.0 // indirect
+	github.com/prometheus/common v0.44.0 // indirect
 	github.com/prometheus/procfs v0.9.0 // indirect
-	github.com/rogpeppe/go-internal v1.10.0 // indirect
 	github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 // indirect
 	github.com/sirupsen/logrus v1.8.1 // indirect
 	github.com/spf13/pflag v1.0.5 // indirect
@@ -97,11 +96,11 @@ require (
 	go.uber.org/multierr v1.7.0 // indirect
 	go.uber.org/zap v1.24.0 // indirect
 	golang.org/x/mod v0.9.0 // indirect
-	golang.org/x/net v0.8.0 // indirect
-	golang.org/x/oauth2 v0.5.0 // indirect
+	golang.org/x/net v0.10.0 // indirect
+	golang.org/x/oauth2 v0.8.0 // indirect
 	golang.org/x/sync v0.2.0 // indirect
-	golang.org/x/term v0.6.0 // indirect
-	golang.org/x/text v0.8.0 // indirect
+	golang.org/x/term v0.8.0 // indirect
+	golang.org/x/text v0.9.0 // indirect
 	golang.org/x/time v0.3.0 // indirect
 	golang.org/x/tools v0.7.0 // indirect
 	gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect
diff --git a/go.sum b/go.sum
index bd9aa7b9..4a37885f 100644
--- a/go.sum
+++ b/go.sum
@@ -280,8 +280,8 @@ github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUo
 github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU=
 github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
 github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4=
-github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM=
-github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc=
+github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY=
+github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY=
 github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
 github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
 github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
@@ -289,7 +289,6 @@ github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJf
 github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY=
 github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
 github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
-github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
 github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
 github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I=
 github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
@@ -378,12 +377,12 @@ golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v
 golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
 golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
 golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ=
-golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
+golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
+golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
-golang.org/x/oauth2 v0.5.0 h1:HuArIo48skDwlrvM3sEdHXElYslAMsf3KwRkkW4MC4s=
-golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I=
+golang.org/x/oauth2 v0.8.0 h1:6dkIjl3j3LtZ/O3sTgZTMsLKSftL/B8Zgq4huOIIUu8=
+golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE=
 golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -427,15 +426,15 @@ golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBc
 golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
 golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
-golang.org/x/term v0.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw=
-golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
+golang.org/x/term v0.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols=
+golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
 golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68=
-golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
+golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
+golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
 golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
 golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
diff --git a/internal/bgp/frr/frr.go b/internal/bgp/frr/frr.go
index d22e1e46..c8dcff0d 100644
--- a/internal/bgp/frr/frr.go
+++ b/internal/bgp/frr/frr.go
@@ -298,8 +298,8 @@ func (sm *sessionManager) createConfig() (*frrConfig, error) {
 			advConfig := advertisementConfig{
 				IPFamily:         family,
 				Prefix:           prefix,
-				Communities:      communities,
-				LargeCommunities: largeCommunities,
+				Communities:      sort.StringSlice(communities),
+				LargeCommunities: sort.StringSlice(largeCommunities),
 				LocalPref:        adv.LocalPref,
 			}
 
@@ -313,6 +313,7 @@ func (sm *sessionManager) createConfig() (*frrConfig, error) {
 				neighbor.HasV6Advertisements = true
 			}
 		}
+		sortAdvertiesements(neighbor.Advertisements)
 	}
 
 	for _, r := range sortMap(routers) {
@@ -458,3 +459,35 @@ func sortMap[T any](toSort map[string]T) []T {
 	}
 	return res
 }
+
+func sortAdvertiesements(toSort []*advertisementConfig) {
+	sort.Slice(toSort, func(i, j int) bool {
+		if toSort[i].IPFamily != toSort[j].IPFamily {
+			return toSort[i].IPFamily < toSort[j].IPFamily
+		}
+		if toSort[i].Prefix != toSort[j].Prefix {
+			return toSort[i].Prefix < toSort[j].Prefix
+		}
+		if toSort[i].LocalPref != toSort[j].LocalPref {
+			return toSort[i].LocalPref < toSort[j].LocalPref
+		}
+		if len(toSort[i].Communities) != len(toSort[j].Communities) {
+			return len(toSort[i].Communities) < len(toSort[j].Communities)
+		}
+		for k := range toSort[i].Communities {
+			if toSort[i].Communities[k] != toSort[j].Communities[k] {
+				return toSort[i].Communities[k] < toSort[j].Communities[k]
+			}
+		}
+		if len(toSort[i].LargeCommunities) != len(toSort[j].LargeCommunities) {
+			return len(toSort[i].LargeCommunities) < len(toSort[j].LargeCommunities)
+		}
+
+		for k := range toSort[i].LargeCommunities {
+			if toSort[i].LargeCommunities[k] != toSort[j].LargeCommunities[k] {
+				return toSort[i].LargeCommunities[k] < toSort[j].LargeCommunities[k]
+			}
+		}
+		return false
+	})
+}
diff --git a/internal/k8s/controllers/config_controller.go b/internal/k8s/controllers/config_controller.go
index 712e167f..a4fc12f1 100644
--- a/internal/k8s/controllers/config_controller.go
+++ b/internal/k8s/controllers/config_controller.go
@@ -142,7 +142,7 @@ var requestHandler = func(r *ConfigReconciler, ctx context.Context, req ctrl.Req
 
 	level.Debug(r.Logger).Log("controller", "ConfigReconciler", "metallb CRs and Secrets", dumpClusterResources(&resources))
 
-	cfg, err := config.For(resources, r.ValidateConfig)
+	cfg, err := toConfig(resources, r.ValidateConfig)
 	if err != nil {
 		configStale.Set(1)
 		level.Error(r.Logger).Log("controller", "ConfigReconciler", "error", "failed to parse the configuration", "error", err)
diff --git a/internal/k8s/controllers/config_conversion.go b/internal/k8s/controllers/config_conversion.go
new file mode 100644
index 00000000..fc36e948
--- /dev/null
+++ b/internal/k8s/controllers/config_conversion.go
@@ -0,0 +1,45 @@
+// SPDX-License-Identifier:Apache-2.0
+
+package controllers
+
+import (
+	"sort"
+
+	"go.universe.tf/metallb/internal/config"
+)
+
+func toConfig(fromK8s config.ClusterResources, validate config.Validate) (*config.Config, error) {
+	resources := config.ClusterResources{
+		Pools:              sortedCopy(fromK8s.Pools),
+		Peers:              sortedCopy(fromK8s.Peers),
+		BFDProfiles:        sortedCopy(fromK8s.BFDProfiles),
+		L2Advs:             sortedCopy(fromK8s.L2Advs),
+		BGPAdvs:            sortedCopy(fromK8s.BGPAdvs),
+		LegacyAddressPools: sortedCopy(fromK8s.LegacyAddressPools),
+		Communities:        sortedCopy(fromK8s.Communities),
+		PasswordSecrets:    fromK8s.PasswordSecrets,
+		Nodes:              sortedCopy(fromK8s.Nodes),
+		Namespaces:         sortedCopy(fromK8s.Namespaces),
+		BGPExtras:          fromK8s.BGPExtras,
+	}
+
+	cfg, err := config.For(resources, validate)
+	return cfg, err
+}
+
+// We need to do this ballet because we need to leverage the GetName() function
+// of the objects, but the interface is implemented by the pointer, not the object,
+// whereas what we are given with .Items is the slice of objects.
+func sortedCopy[T any, PT interface {
+	GetName() string
+	*T
+}](toSort []T) []T {
+	res := make([]T, len(toSort))
+	copy(res, toSort)
+	sort.Slice(res, func(i, j int) bool {
+		first := PT(&toSort[i])
+		second := PT(&toSort[j])
+		return first.GetName() < second.GetName()
+	})
+	return res
+}
diff --git a/internal/k8s/controllers/pool_controller.go b/internal/k8s/controllers/pool_controller.go
index 52ceb111..5de8723f 100644
--- a/internal/k8s/controllers/pool_controller.go
+++ b/internal/k8s/controllers/pool_controller.go
@@ -83,7 +83,7 @@ func (r *PoolReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.
 
 	level.Debug(r.Logger).Log("controller", "PoolReconciler", "metallb CRs", dumpClusterResources(&resources))
 
-	cfg, err := config.For(resources, r.ValidateConfig)
+	cfg, err := toConfig(resources, r.ValidateConfig)
 	if err != nil {
 		configStale.Set(1)
 		level.Error(r.Logger).Log("controller", "PoolReconciler", "error", "failed to parse the configuration", "error", err)
diff --git a/internal/layer2/announcer.go b/internal/layer2/announcer.go
index 4ae3a46d..c63101e6 100644
--- a/internal/layer2/announcer.go
+++ b/internal/layer2/announcer.go
@@ -73,7 +73,7 @@ func (a *Announce) updateInterfaces() {
 		ifi := intf
 
 		if (a.excludeRegexp != nil) && a.excludeRegexp.MatchString(ifi.Name) {
-			level.Info(a.logger).Log("event", "announced interface to exclude", "interface", ifi.Name)
+			level.Debug(a.logger).Log("event", "announced interface to exclude", "interface", ifi.Name)
 			continue
 		}
 


Test patch:
diff --git a/e2etest/l2tests/l2.go b/e2etest/l2tests/l2.go
index 8ba8bdd2..b5d87181 100644
--- a/e2etest/l2tests/l2.go
+++ b/e2etest/l2tests/l2.go
@@ -239,6 +239,7 @@ var _ = ginkgo.Describe("L2", func() {
 				err := cs.CoreV1().Services(svc.Namespace).Delete(context.TODO(), svc.Name, metav1.DeleteOptions{})
 				framework.ExpectNoError(err)
 			}()
+			time.Sleep(time.Second)
 
 			allNodes, err := cs.CoreV1().Nodes().List(context.Background(), metav1.ListOptions{})
 			framework.ExpectNoError(err)
@@ -247,11 +248,11 @@ var _ = ginkgo.Describe("L2", func() {
 			var nodeToSet string
 
 			gomega.Eventually(func() error {
-				node, err := nodeForService(svc, allNodes.Items)
+				node, err := k8s.GetSvcNode(cs, svc.Namespace, svc.Name, allNodes)
 				if err != nil {
 					return err
 				}
-				nodeToSet = node
+				nodeToSet = node.Name
 				return nil
 			}, 3*time.Minute, time.Second).ShouldNot(gomega.HaveOccurred())
 
@@ -261,14 +262,15 @@ var _ = ginkgo.Describe("L2", func() {
 				err = k8s.SetNodeCondition(cs, nodeToSet, corev1.NodeNetworkUnavailable, corev1.ConditionFalse)
 				framework.ExpectNoError(err)
 			}()
+			time.Sleep(time.Second)
 
 			ginkgo.By("validating the service is announced from a different node")
 			gomega.Eventually(func() string {
-				node, err := nodeForService(svc, allNodes.Items)
+				node, err := k8s.GetSvcNode(cs, svc.Namespace, svc.Name, allNodes)
 				if err != nil {
 					return err.Error()
 				}
-				return node
+				return node.Name
 			}, time.Minute, time.Second).ShouldNot(gomega.Equal(nodeToSet))
 
 			ginkgo.By("setting the NetworkUnavailable condition back to false")
@@ -277,11 +279,11 @@ var _ = ginkgo.Describe("L2", func() {
 
 			ginkgo.By("validating the service is announced back again from the previous node")
 			gomega.Eventually(func() string {
-				node, err := nodeForService(svc, allNodes.Items)
+				node, err := k8s.GetSvcNode(cs, svc.Namespace, svc.Name, allNodes)
 				if err != nil {
 					return err.Error()
 				}
-				return node
+				return node.Name
 			}, time.Minute, time.Second).Should(gomega.Equal(nodeToSet))
 		})
 	})
diff --git a/e2etest/pkg/k8s/services.go b/e2etest/pkg/k8s/services.go
index e9d234a4..8de7c02b 100644
--- a/e2etest/pkg/k8s/services.go
+++ b/e2etest/pkg/k8s/services.go
@@ -5,6 +5,7 @@ package k8s
 import (
 	"context"
 	"fmt"
+	"sort"
 	"strings"
 
 	"github.com/pkg/errors"
@@ -30,17 +31,22 @@ func GetSvcNode(cs clientset.Interface, svcNS string, svcName string, allNodes *
 		return nil, err
 	}
 
-	msg := ""
+	svcEvents := make([]corev1.Event, 0)
 	for _, e := range events.Items {
 		if e.InvolvedObject.Name == svcName {
-			msg = e.Message
-			break
+			svcEvents = append(svcEvents, e)
 		}
 	}
-	if msg == "" {
+	if len(svcEvents) == 0 {
 		return nil, errors.New("service doesn't be assigned node")
 	}
 
+	sort.Slice(svcEvents, func(i, j int) bool {
+		return svcEvents[i].LastTimestamp.After(svcEvents[j].LastTimestamp.Time)
+	})
+
+	msg := svcEvents[0].Message
+
 	for _, node := range allNodes.Items {
 		if strings.Contains(msg, "\""+node.Name+"\"") {
 			return &node, nil
diff --git a/internal/bgp/frr/frr_test.go b/internal/bgp/frr/frr_test.go
index 8a9e4244..16132249 100644
--- a/internal/bgp/frr/frr_test.go
+++ b/internal/bgp/frr/frr_test.go
@@ -5,6 +5,7 @@ package frr
 import (
 	"flag"
 	"fmt"
+	"math/rand"
 	"net"
 	"os"
 	"os/exec"
@@ -81,6 +82,11 @@ func testSetup(t *testing.T) {
 }
 
 func testCheckConfigFile(t *testing.T) {
+	validateGoldenFile(t)
+	validateAgainstFRR(t)
+}
+
+func validateGoldenFile(t *testing.T) {
 	configFile, goldenFile := testGenerateFileNames(t)
 
 	if *update {
@@ -88,7 +94,10 @@ func testCheckConfigFile(t *testing.T) {
 	}
 
 	testCompareFiles(t, configFile, goldenFile)
+}
 
+func validateAgainstFRR(t *testing.T) {
+	configFile, _ := testGenerateFileNames(t)
 	if !strings.Contains(configFile, "Invalid") {
 		err := testFileIsValid(configFile)
 		if err != nil {
@@ -820,75 +829,97 @@ func TestTwoAdvertisementsTwoSessions(t *testing.T) {
 	l := log.NewNopLogger()
 	sessionManager := mockNewSessionManager(l, logging.LevelInfo)
 	defer close(sessionManager.reloadConfig)
-	session, err := sessionManager.NewSession(l,
-		bgp.SessionParameters{
-			PeerAddress:   "10.2.2.254:179",
-			SourceAddress: net.ParseIP("10.1.1.254"),
-			MyASN:         100,
-			RouterID:      net.ParseIP("10.1.1.254"),
-			PeerASN:       200,
-			HoldTime:      time.Second,
-			KeepAliveTime: time.Second,
-			Password:      "password",
-			CurrentNode:   "hostname",
-			EBGPMultiHop:  true,
-			SessionName:   "test-peer"})
-	if err != nil {
-		t.Fatalf("Could not create session: %s", err)
-	}
-	defer session.Close()
-
-	session1, err := sessionManager.NewSession(l,
-		bgp.SessionParameters{
-			PeerAddress:   "10.2.2.255:179",
-			SourceAddress: net.ParseIP("10.1.1.254"),
-			MyASN:         100,
-			RouterID:      net.ParseIP("10.1.1.254"),
-			PeerASN:       200,
-			HoldTime:      time.Second,
-			KeepAliveTime: time.Second,
-			Password:      "password",
-			CurrentNode:   "hostname",
-			EBGPMultiHop:  true,
-			SessionName:   "test-peer1"})
-	if err != nil {
-		t.Fatalf("Could not create session: %s", err)
-	}
-	defer session1.Close()
-
-	prefix1 := &net.IPNet{
-		IP:   net.ParseIP("172.16.1.10"),
-		Mask: classCMask,
-	}
-	communities := []community.BGPCommunity{}
-	community, _ := community.New("1111:2222")
-	communities = append(communities, community)
-	adv1 := &bgp.Advertisement{
-		Prefix:      prefix1,
-		Communities: communities,
-	}
-
-	prefix2 := &net.IPNet{
-		IP:   net.ParseIP("172.16.1.11"),
-		Mask: classCMask,
-	}
-
-	adv2 := &bgp.Advertisement{
-		Prefix:      prefix2,
-		Communities: communities,
-		LocalPref:   2,
-	}
-
-	err = session.Set(adv1, adv2)
-	if err != nil {
-		t.Fatalf("Could not advertise prefix: %s", err)
-	}
-	err = session1.Set(adv1, adv2)
-	if err != nil {
-		t.Fatalf("Could not advertise prefix: %s", err)
-	}
 
-	testCheckConfigFile(t)
+	for i := 0; i < 100; i++ {
+		func() {
+			sessionsParameters := []bgp.SessionParameters{
+				{
+					PeerAddress:   "10.2.2.254:179",
+					SourceAddress: net.ParseIP("10.1.1.254"),
+					MyASN:         100,
+					RouterID:      net.ParseIP("10.1.1.254"),
+					PeerASN:       200,
+					HoldTime:      time.Second,
+					KeepAliveTime: time.Second,
+					Password:      "password",
+					CurrentNode:   "hostname",
+					EBGPMultiHop:  true,
+					SessionName:   "test-peer"},
+				{
+					PeerAddress:   "10.2.2.255:179",
+					SourceAddress: net.ParseIP("10.1.1.254"),
+					MyASN:         100,
+					RouterID:      net.ParseIP("10.1.1.254"),
+					PeerASN:       200,
+					HoldTime:      time.Second,
+					KeepAliveTime: time.Second,
+					Password:      "password",
+					CurrentNode:   "hostname",
+					EBGPMultiHop:  true,
+					SessionName:   "test-peer1"},
+			}
+			seed := time.Now().UnixNano()
+			rand.Seed(seed)
+
+			rand.Shuffle(len(sessionsParameters), func(i, j int) {
+				sessionsParameters[i], sessionsParameters[j] = sessionsParameters[j], sessionsParameters[i]
+			})
+
+			session, err := sessionManager.NewSession(l, sessionsParameters[0])
+			if err != nil {
+				t.Fatalf("Could not create session: %s", err)
+			}
+			defer session.Close()
+
+			session1, err := sessionManager.NewSession(l, sessionsParameters[1])
+			if err != nil {
+				t.Fatalf("Could not create session: %s", err)
+			}
+			defer session1.Close()
+
+			prefix1 := &net.IPNet{
+				IP:   net.ParseIP("172.16.1.10"),
+				Mask: classCMask,
+			}
+			communities := []community.BGPCommunity{}
+			community, _ := community.New("1111:2222")
+			communities = append(communities, community)
+			adv1 := &bgp.Advertisement{
+				Prefix:      prefix1,
+				Communities: communities,
+			}
+
+			prefix2 := &net.IPNet{
+				IP:   net.ParseIP("172.16.1.11"),
+				Mask: classCMask,
+			}
+
+			adv2 := &bgp.Advertisement{
+				Prefix:      prefix2,
+				Communities: communities,
+				LocalPref:   2,
+			}
+			advs := []*bgp.Advertisement{adv1, adv2}
+			rand.Shuffle(len(advs), func(i, j int) {
+				advs[i], advs[j] = advs[j], advs[i]
+			})
+			err = session.Set(advs[0], advs[1])
+			if err != nil {
+				t.Fatalf("Could not advertise prefix: %s", err)
+			}
+
+			rand.Shuffle(len(advs), func(i, j int) {
+				advs[i], advs[j] = advs[j], advs[i]
+			})
+			err = session1.Set(advs[0], advs[1])
+			if err != nil {
+				t.Fatalf("Could not advertise prefix: %s", err)
+			}
+
+			validateGoldenFile(t)
+		}()
+	}
+	validateAgainstFRR(t)
 }
 
 func TestTwoAdvertisementsTwoSessionsOneWithPeerSelector(t *testing.T) {
diff --git a/internal/k8s/controllers/config_conversion_test.go b/internal/k8s/controllers/config_conversion_test.go
new file mode 100644
index 00000000..73092c0e
--- /dev/null
+++ b/internal/k8s/controllers/config_conversion_test.go
@@ -0,0 +1,254 @@
+// SPDX-License-Identifier:Apache-2.0
+
+package controllers
+
+import (
+	"math/rand"
+	"reflect"
+	"testing"
+	"time"
+
+	"github.com/davecgh/go-spew/spew"
+	v1beta1 "go.universe.tf/metallb/api/v1beta1"
+	v1beta2 "go.universe.tf/metallb/api/v1beta2"
+	"go.universe.tf/metallb/internal/config"
+	v1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+)
+
+func TestConversionIsStable(t *testing.T) {
+	peers := []v1beta2.BGPPeer{
+		{
+			ObjectMeta: metav1.ObjectMeta{
+				Name:      "peer1",
+				Namespace: "metallb-system",
+			},
+			Spec: v1beta2.BGPPeerSpec{
+				MyASN:      42,
+				ASN:        142,
+				Address:    "1.2.3.4",
+				BFDProfile: "default",
+			},
+		},
+		{
+			ObjectMeta: metav1.ObjectMeta{
+				Name:      "peer2",
+				Namespace: "metallb-system",
+			},
+			Spec: v1beta2.BGPPeerSpec{
+				MyASN:      42,
+				ASN:        142,
+				Address:    "1.2.3.5",
+				BFDProfile: "default",
+			},
+		},
+	}
+	bfdProfiles := []v1beta1.BFDProfile{
+		{
+			ObjectMeta: metav1.ObjectMeta{
+				Name:      "default",
+				Namespace: "metallb-system",
+			},
+		},
+		{
+			ObjectMeta: metav1.ObjectMeta{
+				Name:      "bar",
+				Namespace: "metallb-system",
+			},
+		},
+	}
+	pools := []v1beta1.IPAddressPool{
+		{
+			ObjectMeta: metav1.ObjectMeta{
+				Name:      "pool1",
+				Namespace: "metallb-system",
+			},
+			Spec: v1beta1.IPAddressPoolSpec{
+				Addresses: []string{
+					"10.20.0.0/16",
+				},
+			},
+		},
+		{
+			ObjectMeta: metav1.ObjectMeta{
+				Name:      "pool2",
+				Namespace: "metallb-system",
+			},
+			Spec: v1beta1.IPAddressPoolSpec{
+				Addresses: []string{
+					"10.10.0.0/16",
+				},
+				AllocateTo: &v1beta1.ServiceAllocation{
+					Namespaces: []string{"foo", "bar"},
+				},
+			},
+		},
+	}
+	legacyAddressPools := []v1beta1.AddressPool{
+		{
+			ObjectMeta: metav1.ObjectMeta{
+				Name:      "legacypool1",
+				Namespace: testNamespace,
+			},
+			Spec: v1beta1.AddressPoolSpec{
+				Addresses: []string{
+					"10.21.0.0/16",
+				},
+				Protocol: "bgp",
+			},
+		},
+		{
+			ObjectMeta: metav1.ObjectMeta{
+				Name:      "legacypool2",
+				Namespace: testNamespace,
+			},
+			Spec: v1beta1.AddressPoolSpec{
+				Addresses: []string{
+					"10.22.0.0/16",
+				},
+				Protocol: "layer2",
+			},
+		},
+	}
+	bgpAdvs := []v1beta1.BGPAdvertisement{
+		{
+			ObjectMeta: metav1.ObjectMeta{
+				Name:      "adv1",
+				Namespace: "metallb-system",
+			},
+			Spec: v1beta1.BGPAdvertisementSpec{
+				Communities: []string{"bar"},
+			},
+		},
+		{
+			ObjectMeta: metav1.ObjectMeta{
+				Name:      "adv2",
+				Namespace: "metallb-system",
+			},
+			Spec: v1beta1.BGPAdvertisementSpec{
+				Communities: []string{"bar2"},
+			},
+		},
+	}
+	l2Advs := []v1beta1.L2Advertisement{
+		{
+			ObjectMeta: metav1.ObjectMeta{
+				Name:      "l2adv1",
+				Namespace: "metallb-system",
+			},
+		},
+		{
+			ObjectMeta: metav1.ObjectMeta{
+				Name:      "l2adv2",
+				Namespace: "metallb-system",
+			},
+			Spec: v1beta1.L2AdvertisementSpec{
+				Interfaces: []string{"foo"},
+			},
+		},
+	}
+
+	communities := []v1beta1.Community{
+		{
+			ObjectMeta: metav1.ObjectMeta{
+				Name:      "community",
+				Namespace: "metallb-system",
+			},
+			Spec: v1beta1.CommunitySpec{
+				Communities: []v1beta1.CommunityAlias{
+					{
+						Name:  "bar",
+						Value: "64512:1234",
+					},
+				},
+			},
+		},
+		{
+			ObjectMeta: metav1.ObjectMeta{
+				Name:      "community1",
+				Namespace: "metallb-system",
+			},
+			Spec: v1beta1.CommunitySpec{
+				Communities: []v1beta1.CommunityAlias{
+					{
+						Name:  "bar2",
+						Value: "64512:1235",
+					},
+				},
+			},
+		},
+	}
+	namespaces := []v1.Namespace{
+		{
+			ObjectMeta: metav1.ObjectMeta{
+				Name: "foo",
+			},
+		},
+		{
+			ObjectMeta: metav1.ObjectMeta{
+				Name: "bar",
+			},
+		},
+	}
+	nodes := []v1.Node{
+		{
+			ObjectMeta: metav1.ObjectMeta{
+				Name: "node1",
+			},
+		},
+		{
+			ObjectMeta: metav1.ObjectMeta{
+				Name: "node2",
+			},
+		},
+	}
+
+	resources := config.ClusterResources{
+		Pools:              pools,
+		Peers:              peers,
+		BFDProfiles:        bfdProfiles,
+		L2Advs:             l2Advs,
+		BGPAdvs:            bgpAdvs,
+		LegacyAddressPools: legacyAddressPools,
+		Communities:        communities,
+		PasswordSecrets:    map[string]v1.Secret{},
+		Nodes:              nodes,
+		Namespaces:         namespaces,
+	}
+
+	firstConfig, err := toConfig(resources, config.DontValidate)
+
+	if err != nil {
+		t.Fatalf("conversion failed, err %v", err)
+	}
+	seed := time.Now().UnixNano()
+	rand.Seed(seed)
+
+	// Here we check the stability of the conversion, by shuffling the
+	// order of the resources and checking that the output is the same.
+	for i := 0; i < 100; i++ {
+		shuffleObjects(resources.Peers)
+		shuffleObjects(resources.BFDProfiles)
+		shuffleObjects(resources.Pools)
+		shuffleObjects(resources.BGPAdvs)
+		shuffleObjects(resources.L2Advs)
+		shuffleObjects(resources.Communities)
+		shuffleObjects(resources.LegacyAddressPools)
+		shuffleObjects(resources.Nodes)
+		shuffleObjects(resources.Namespaces)
+
+		config, err := toConfig(resources, config.DontValidate)
+
+		if err != nil {
+			t.Fatalf("conversion failed, seed %d, %v", seed, err)
+		}
+
+		if !reflect.DeepEqual(config, firstConfig) {
+			t.Fatalf("conversion is not stable, seed %d, current %v\n previous %v\n", seed, spew.Sdump(config), spew.Sdump(firstConfig))
+		}
+	}
+}
+
+func shuffleObjects[T any](toShuffle []T) {
+	rand.Shuffle(len(toShuffle), func(i, j int) { toShuffle[i], toShuffle[j] = toShuffle[j], toShuffle[i] })
+}