From c938df9940c9b8fd8483959dcc476ceedd3217d0 Mon Sep 17 00:00:00 2001 From: Tom Pantelis Date: Fri, 21 Aug 2026 10:43:28 -0400 Subject: [PATCH] Add ConfigMap hash annotation to networking console plugin deployment When TLS parameters change, the nginx ConfigMap is updated but the pods don't automatically restart to pick up the new configuration. This adds a hash of the ConfigMap content as a pod template annotation, which triggers a rolling update when the ConfigMap changes. Signed-off-by: Tom Pantelis --- .../003-deployment.yaml | 1 + pkg/network/render.go | 22 +++++++++++ pkg/network/render_test.go | 37 +++++++++++++++++++ 3 files changed, 60 insertions(+) diff --git a/bindata/networking-console-plugin/003-deployment.yaml b/bindata/networking-console-plugin/003-deployment.yaml index 777fc4d6ce..b24ffedf14 100644 --- a/bindata/networking-console-plugin/003-deployment.yaml +++ b/bindata/networking-console-plugin/003-deployment.yaml @@ -33,6 +33,7 @@ spec: annotations: target.workload.openshift.io/management: '{"effect": "PreferredDuringScheduling"}' openshift.io/required-scc: restricted-v2 + network.operator.openshift.io/config-hash: "{{.NetworkingConsolePluginConfigHash}}" labels: app.kubernetes.io/component: networking-console-plugin app.kubernetes.io/managed-by: cluster-network-operator diff --git a/pkg/network/render.go b/pkg/network/render.go index 632aa8e3df..610cfc7e7d 100644 --- a/pkg/network/render.go +++ b/pkg/network/render.go @@ -2,6 +2,9 @@ package network import ( "context" + "crypto/sha256" + "encoding/hex" + "encoding/json" "fmt" "log" "net" @@ -823,6 +826,25 @@ func renderNetworkingConsolePlugin(manifestDir string, bootstrapResult *bootstra addTLSInfoToRenderData(data.Data, bootstrapResult, true) + // Calculate hash of the ConfigMap to trigger pod restarts when TLS config changes + h := sha256.New() + configMapPath := filepath.Join(manifestDir, "networking-console-plugin", "002-config-map.yaml") + configMapManifests, err := render.RenderTemplate(configMapPath, &data) + if err != nil { + return nil, fmt.Errorf("failed to render ConfigMap template: %w", err) + } + + for _, m := range configMapManifests { + bytes, err := json.Marshal(m) + if err != nil { + return nil, fmt.Errorf("failed to marshal ConfigMap manifest: %w", err) + } + if _, err := h.Write(bytes); err != nil { + return nil, fmt.Errorf("failed to hash ConfigMap data: %w", err) + } + } + data.Data["NetworkingConsolePluginConfigHash"] = hex.EncodeToString(h.Sum(nil)) + manifests, err := render.RenderDir(filepath.Join(manifestDir, "networking-console-plugin"), &data) if err != nil { return nil, fmt.Errorf("failed to render networking-console-plugin manifests: %w", err) diff --git a/pkg/network/render_test.go b/pkg/network/render_test.go index 0e45ec1b92..b5f9d726c4 100644 --- a/pkg/network/render_test.go +++ b/pkg/network/render_test.go @@ -782,4 +782,41 @@ func Test_renderNetworkingConsolePlugin(t *testing.T) { g.Expect(nginxConf).NotTo(ContainSubstring("ssl_prefer_server_ciphers")) }) }) + + t.Run("config hash annotation should be present in deployment and change when TLS config changes", func(t *testing.T) { + g := NewWithT(t) + t.Setenv("NETWORKING_CONSOLE_PLUGIN_IMAGE", "quay.io/openshift/networking-console-plugin:latest") + bootstrapResult := fakeBootstrapResult() + bootstrapResult.Infra.ConsolePluginCRDExists = true + bootstrapResult.TLSProfile = bootstrap.TLSProfile{ + Spec: configv1.TLSProfileSpec{ + MinTLSVersion: configv1.VersionTLS12, + Ciphers: []string{"ECDHE-RSA-AES128-GCM-SHA256"}, + }, + Adherence: configv1.TLSAdherencePolicyStrictAllComponents, + } + + objs, err := renderNetworkingConsolePlugin(manifestDir, bootstrapResult) + g.Expect(err).NotTo(HaveOccurred()) + + deploy := mustFindRenderedObj[*appsv1.Deployment](t, objs, "Deployment", "networking-console-plugin") + hash1, ok := deploy.Spec.Template.Annotations["network.operator.openshift.io/config-hash"] + g.Expect(ok).To(BeTrue(), "config-hash annotation should be present") + g.Expect(hash1).NotTo(BeEmpty(), "config-hash should not be empty") + + // Render with different TLS config + bootstrapResult.TLSProfile = bootstrap.TLSProfile{ + Spec: configv1.TLSProfileSpec{ + MinTLSVersion: configv1.VersionTLS13, + Ciphers: nil, + }, + Adherence: configv1.TLSAdherencePolicyStrictAllComponents, + } + objs2, err := renderNetworkingConsolePlugin(manifestDir, bootstrapResult) + g.Expect(err).NotTo(HaveOccurred()) + deploy2 := mustFindRenderedObj[*appsv1.Deployment](t, objs2, "Deployment", "networking-console-plugin") + hash2 := deploy2.Spec.Template.Annotations["network.operator.openshift.io/config-hash"] + + g.Expect(hash1).NotTo(Equal(hash2), "config-hash should change when TLS config changes") + }) }