Repository: rancher/fleet
Pull request #2981 (2024-10-22 16:43:17)

Add helm value to disable securityContext
The securityContext needs to be disabled to allow for debugging with a debugger.
However it should be possible to run debug logs with security contexts enabled.




Patch:
diff --git a/charts/fleet/ci/debug-values.yaml b/charts/fleet/ci/debug-values.yaml
index f495e1f6..ab519706 100644
--- a/charts/fleet/ci/debug-values.yaml
+++ b/charts/fleet/ci/debug-values.yaml
@@ -25,6 +25,7 @@ metrics:
 debug: true
 debugLevel: 4
 propagateDebugSettingsToAgents: true
+disableSecurityContext: true
 
 cpuPprof:
   period: "60s"
diff --git a/charts/fleet/templates/deployment.yaml b/charts/fleet/templates/deployment.yaml
index 025eb071..f2c0d324 100644
--- a/charts/fleet/templates/deployment.yaml
+++ b/charts/fleet/templates/deployment.yaml
@@ -45,14 +45,6 @@ spec:
         - name: NO_PROXY
           value: {{ $.Values.noProxy }}
         {{- end }}
-        {{- if $.Values.cpuPprof }}
-        - name: FLEET_CPU_PPROF_DIR
-          value: /tmp/pprof/
-        {{- end }}
-        {{- if $.Values.cpuPprof }}
-        - name: FLEET_CPU_PPROF_PERIOD
-          value: {{ quote $.Values.cpuPprof.period }}
-        {{- end }}
         {{- if $.Values.leaderElection.leaseDuration }}
         - name: CATTLE_ELECTION_LEASE_DURATION
           value: {{$.Values.leaderElection.leaseDuration}}
@@ -101,7 +93,8 @@ spec:
         - --debug
         - --debug-level
         - {{ quote $.Values.debugLevel }}
-        {{- else }}
+        {{- end }}
+        {{- if not $.Values.disableSecurityContext }}
         securityContext:
           allowPrivilegeEscalation: false
           readOnlyRootFilesystem: true
@@ -113,10 +106,6 @@ spec:
         volumeMounts:
           - mountPath: /tmp
             name: tmp
-        {{- if $.Values.cpuPprof }}
-          - mountPath: /tmp/pprof
-            name: pprof
-        {{- end }}
       {{- if not $shard.id }} # Only deploy cleanup and agent management through sharding-less deployment
       - env:
         - name: NAMESPACE
@@ -161,7 +150,8 @@ spec:
         - --debug
         - --debug-level
         - {{ quote $.Values.debugLevel }}
-        {{- else }}
+        {{- end }}
+        {{- if not $.Values.disableSecurityContext }}
         securityContext:
           allowPrivilegeEscalation: false
           readOnlyRootFilesystem: true
@@ -206,7 +196,8 @@ spec:
         - --debug
         - --debug-level
         - {{ quote $.Values.debugLevel }}
-        {{- else }}
+        {{- end }}
+        {{- if not $.Values.disableSecurityContext }}
         securityContext:
           allowPrivilegeEscalation: false
           readOnlyRootFilesystem: true
@@ -219,9 +210,6 @@ spec:
       volumes:
         - name: tmp
           emptyDir: {}
-      {{- if $.Values.cpuPprof }}
-        - name: pprof {{ toYaml $.Values.cpuPprof.volumeConfiguration | nindent 10 }}
-      {{- end }}
 
       serviceAccountName: fleet-controller
       nodeSelector: {{ include "linux-node-selector" $shard.id | nindent 8 }}
@@ -241,7 +229,7 @@ spec:
       priorityClassName: "{{$.Values.priorityClassName}}"
       {{- end }}
 
-{{- if not $.Values.debug }}
+{{- if not $.Values.disableSecurityContext }}
       securityContext:
         runAsNonRoot: true
         runAsUser: 1000
diff --git a/charts/fleet/templates/deployment_gitjob.yaml b/charts/fleet/templates/deployment_gitjob.yaml
index 5c3df960..686608d1 100644
--- a/charts/fleet/templates/deployment_gitjob.yaml
+++ b/charts/fleet/templates/deployment_gitjob.yaml
@@ -93,7 +93,8 @@ spec:
           {{- if $.Values.debug }}
             - name: CATTLE_DEV_MODE
               value: "true"
-          {{- else }}
+          {{- end }}
+          {{- if not $.Values.disableSecurityContext }}
           securityContext:
             allowPrivilegeEscalation: false
             readOnlyRootFilesystem: true
@@ -122,7 +123,7 @@ spec:
       priorityClassName: "{{$.Values.priorityClassName}}"
       {{- end }}
 
-{{- if not $.Values.debug }}
+{{- if not $.Values.disableSecurityContext }}
       securityContext:
         runAsNonRoot: true
         runAsUser: 1000
diff --git a/charts/fleet/values.yaml b/charts/fleet/values.yaml
index b0d289c2..6e9d8744 100644
--- a/charts/fleet/values.yaml
+++ b/charts/fleet/values.yaml
@@ -84,15 +84,7 @@ metrics:
 debug: false
 debugLevel: 0
 propagateDebugSettingsToAgents: true
-
-## Optional CPU pprof configuration. Profiles are collected continuously and saved every period
-## Any valid volume configuration can be provided, the example below uses hostPath
-# cpuPprof:
-#   period: "60s"
-#   volumeConfiguration:
-#     hostPath:
-#       path: /tmp/pprof
-#       type: DirectoryOrCreate
+disableSecurityContext: false
 
 migrations:
   clusterRegistrationCleanup: true
diff --git a/docs/performance.md b/docs/performance.md
index eed2610a..7fbadb6b 100644
--- a/docs/performance.md
+++ b/docs/performance.md
@@ -11,34 +11,4 @@ For example: you may encounter a pod with high compute usage, but that could be
 
 [http pprof](https://pkg.go.dev/net/http/pprof) handlers are enabled by default with all [default profiles](https://pkg.go.dev/runtime/pprof#Profile) under the `/debug/pprof` prefix.
 
-Additionally, it is possible to enable continuous CPU profiling for `fleetcontroller` to observe how CPU usage changes over time.
-
-Add the following extra Helm values:
-```yaml
-cpuPprof:
-  period: "60s"
-  volumeConfiguration:
-    hostPath:
-      path: /tmp/pprof
-      type: DirectoryOrCreate
-```
-
-Notes:
- - `period` is the pprof CPU period and can be changed with any other value
- - `volumeConfiguration` can be any valid volume configuration (not necessarily `hostPath`)
-
-Alternatively, use the following Helm commandline arguments:
-```
---set cpuPprof.period=60s \
---set cpuPprof.volumeConfiguration.hostPath.path=/tmp/pprof \
---set cpuPprof.volumeConfiguration.hostPath.type=DirectoryOrCreate \
-```
-
-If using `hostPath`, make sure that the target directory (`/tmp/pprof` in above examples) is writable.
-
-Profiles can be inspected with the [pprof tool](https://github.com/google/pprof), eg.:
-
-```sh
-pprof -http=localhost:5000 ./2022-11-04_19_47_18.pprof.fleetcontroller.samples.cpu.pb.gz
-```
-
+To collect profiling information continuously one can use https://github.com/rancherlabs/support-tools/tree/master/collection/rancher/v2.x/profile-collector
diff --git a/go.mod b/go.mod
index 2f59c284..42929d4d 100644
--- a/go.mod
+++ b/go.mod
@@ -22,7 +22,6 @@ require (
 	github.com/go-playground/webhooks/v6 v6.4.0
 	github.com/gobwas/glob v0.2.3
 	github.com/gogits/go-gogs-client v0.0.0-20210131175652-1d7215cd8d85
-	github.com/golang/mock v1.6.0
 	github.com/google/go-cmp v0.6.0
 	github.com/google/go-containerregistry v0.20.2
 	github.com/gorilla/mux v1.8.1
@@ -39,7 +38,7 @@ require (
 	github.com/prometheus/common v0.60.0
 	github.com/rancher/fleet/pkg/apis v0.10.0
 	github.com/rancher/lasso v0.0.0-20240924233157-8f384efc8813
-	github.com/rancher/wrangler/v3 v3.0.0
+	github.com/rancher/wrangler/v3 v3.0.1-rc.3
 	github.com/reugn/go-quartz v0.13.0
 	github.com/sirupsen/logrus v1.9.3
 	github.com/spf13/cobra v1.8.1
@@ -249,7 +248,7 @@ require (
 	k8s.io/apiserver v0.31.1 // indirect
 	k8s.io/code-generator v0.31.1 // indirect
 	k8s.io/component-base v0.31.1 // indirect
-	k8s.io/gengo v0.0.0-20240310015720-9cff6334dab4 // indirect
+	k8s.io/gengo v0.0.0-20240826214909-a7b603a56eb7 // indirect
 	k8s.io/gengo/v2 v2.0.0-20240826214909-a7b603a56eb7 // indirect
 	oras.land/oras-go v1.2.5 // indirect
 	sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
diff --git a/go.sum b/go.sum
index d866044d..03922c20 100644
--- a/go.sum
+++ b/go.sum
@@ -427,7 +427,6 @@ github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt
 github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
 github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
 github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8=
-github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
 github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
 github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
 github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
@@ -735,8 +734,8 @@ github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0leargg
 github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
 github.com/rancher/lasso v0.0.0-20240924233157-8f384efc8813 h1:V/LY8pUHZG9Kc+xEDWDOryOnCU6/Q+Lsr9QQEQnshpU=
 github.com/rancher/lasso v0.0.0-20240924233157-8f384efc8813/go.mod h1:IxgTBO55lziYhTEETyVKiT8/B5Rg92qYiRmcIIYoPgI=
-github.com/rancher/wrangler/v3 v3.0.0 h1:IHHCA+vrghJDPxjtLk4fmeSCFhNe9fFzLFj3m2B0YpA=
-github.com/rancher/wrangler/v3 v3.0.0/go.mod h1:Dfckuuq7MJk2JWVBDywRlZXMxEyPxHy4XqGrPEzu5Eg=
+github.com/rancher/wrangler/v3 v3.0.1-rc.3 h1:C2d1GoP500SEFARVcb6EpbcNaXH3i8Yu9fzAe/0n4C0=
+github.com/rancher/wrangler/v3 v3.0.1-rc.3/go.mod h1:gUPHS1ANs2NyByfeERHwkGiQ1rlIa8BpTJZtNSgMlZw=
 github.com/reugn/go-quartz v0.13.0 h1:0eMxvj28Qu1npIDdN9Mzg9hwyksGH6XJt4Cz0QB8EUk=
 github.com/reugn/go-quartz v0.13.0/go.mod h1:0ghKksELp8MJ4h84T203aTHRF3Kug5BrxEW3ErBvhzY=
 github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
@@ -1475,8 +1474,8 @@ k8s.io/code-generator v0.31.1 h1:GvkRZEP2g2UnB2QKT2Dgc/kYxIkDxCHENv2Q1itioVs=
 k8s.io/code-generator v0.31.1/go.mod h1:oL2ky46L48osNqqZAeOcWWy0S5BXj50vVdwOtTefqIs=
 k8s.io/component-base v0.31.1 h1:UpOepcrX3rQ3ab5NB6g5iP0tvsgJWzxTyAo20sgYSy8=
 k8s.io/component-base v0.31.1/go.mod h1:WGeaw7t/kTsqpVTaCoVEtillbqAhF2/JgvO0LDOMa0w=
-k8s.io/gengo v0.0.0-20240310015720-9cff6334dab4 h1:v8TcVKY4HxDaiNH8xnHEEGfx80twQJL9cOQuhd55fcY=
-k8s.io/gengo v0.0.0-20240310015720-9cff6334dab4/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
+k8s.io/gengo v0.0.0-20240826214909-a7b603a56eb7 h1:HCbtr1pVu/ElMcTTs18KdMtH5y6f7PQvrjh1QZj3qCI=
+k8s.io/gengo v0.0.0-20240826214909-a7b603a56eb7/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
 k8s.io/gengo/v2 v2.0.0-20240826214909-a7b603a56eb7 h1:cErOOTkQ3JW19o4lo91fFurouhP8NcoBvb7CkvhZZpk=
 k8s.io/gengo/v2 v2.0.0-20240826214909-a7b603a56eb7/go.mod h1:EJykeLsmFC60UQbYJezXkEsG2FLrt0GPNkU5iK5GWxU=
 k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
diff --git a/internal/cmd/cli/deploy.go b/internal/cmd/cli/deploy.go
index be4334c5..7cb87e42 100644
--- a/internal/cmd/cli/deploy.go
+++ b/internal/cmd/cli/deploy.go
@@ -9,6 +9,7 @@ import (
 
 	"github.com/spf13/cobra"
 	"helm.sh/helm/v3/pkg/cli"
+	"helm.sh/helm/v3/pkg/release"
 	"k8s.io/apimachinery/pkg/runtime"
 
 	command "github.com/rancher/fleet/internal/cmd"
@@ -117,17 +118,12 @@ func (d *Deploy) Run(cmd *cobra.Command, args []string) error {
 	}
 
 	if d.DryRun {
-		resources, err := helmdeployer.Template(ctx, bd.Name, manifest, bd.Spec.Options, d.KubeVersion)
+		rel, err := helmdeployer.Template(ctx, bd.Name, manifest, bd.Spec.Options, d.KubeVersion)
 		if err != nil {
 			return err
 		}
-		b, err = yaml.Marshal(resources)
-		if err != nil {
-			return err
-		}
-		cmd.Println(string(b))
 
-		return nil
+		return printRelease(cmd, rel)
 	}
 
 	cfg := ctrl.GetConfigOrDie()
@@ -159,17 +155,29 @@ func (d *Deploy) Run(cmd *cobra.Command, args []string) error {
 		return err
 	}
 
-	release, err := deployer.Deploy(ctx, bd.Name, manifest, bd.Spec.Options)
+	rel, err := deployer.Deploy(ctx, bd.Name, manifest, bd.Spec.Options)
 	if err != nil {
 		return err
 	}
 
-	objects, err := helmdeployer.ReleaseToObjects(release)
+	return printRelease(cmd, rel)
+}
+
+func printRelease(cmd *cobra.Command, rel *release.Release) error {
+	resources, err := wyaml.ToObjects(bytes.NewBufferString(rel.Manifest))
 	if err != nil {
 		return err
 	}
 
-	b, err = yaml.Marshal(objects)
+	for _, h := range rel.Hooks {
+		hookResources, err := wyaml.ToObjects(bytes.NewBufferString(h.Manifest))
+		if err != nil {
+			return err
+		}
+		resources = append(resources, hookResources...)
+	}
+
+	b, err := yaml.Marshal(resources)
 	if err != nil {
 		return err
 	}
diff --git a/internal/cmd/cli/match/match.go b/internal/cmd/cli/match/match.go
index d877aa73..c6b5eebd 100644
--- a/internal/cmd/cli/match/match.go
+++ b/internal/cmd/cli/match/match.go
@@ -89,7 +89,12 @@ func printMatch(ctx context.Context, bundle *fleet.Bundle, target *fleet.BundleT
 
 	manifest := manifest.New(bundle.Spec.Resources)
 
-	objs, err := helmdeployer.Template(ctx, bundle.Name, manifest, opts, "")
+	rel, err := helmdeployer.Template(ctx, bundle.Name, manifest, opts, "")
+	if err != nil {
+		return err
+	}
+
+	objs, err := yaml.ToObjects(bytes.NewBufferString(rel.Manifest))
 	if err != nil {
 		return err
 	}
diff --git a/internal/cmd/controller/root.go b/internal/cmd/controller/root.go
index 1e49f07d..4e4c7906 100644
--- a/internal/cmd/controller/root.go
+++ b/internal/cmd/controller/root.go
@@ -2,30 +2,24 @@
 package controller
 
 import (
-	"context"
 	"flag"
 	"fmt"
 	"log"
 	"net/http"
 	"os"
-	"path"
-	"runtime/pprof"
 	"strconv"
-	"time"
 
 	"github.com/rancher/fleet/internal/cmd/controller/agentmanagement"
 	"github.com/rancher/fleet/internal/cmd/controller/gitops"
 
 	"github.com/spf13/cobra"
 
-	"k8s.io/apimachinery/pkg/util/wait"
 	ctrl "sigs.k8s.io/controller-runtime"
 	clog "sigs.k8s.io/controller-runtime/pkg/log"
 	"sigs.k8s.io/controller-runtime/pkg/log/zap"
 
 	command "github.com/rancher/fleet/internal/cmd"
 	"github.com/rancher/fleet/internal/cmd/controller/cleanup"
-	"github.com/rancher/fleet/pkg/durations"
 	"github.com/rancher/fleet/pkg/version"
 )
 
@@ -102,7 +96,6 @@ func (f *FleetController) Run(cmd *cobra.Command, args []string) error {
 		workersOpts.BundleDeployment = w
 	}
 
-	setupCpuPprof(ctx)
 	go func() {
 		log.Println(http.ListenAndServe("localhost:6060", nil)) // nolint:gosec // Debugging only
 	}()
@@ -139,46 +132,3 @@ func App() *cobra.Command {
 	)
 	return root
 }
-
-// setupCpuPprof starts a goroutine that captures a cpu pprof profile
-// into FLEET_CPU_PPROF_DIR every FLEET_CPU_PPROF_PERIOD
-func setupCpuPprof(ctx context.Context) {
-	if dir, ok := os.LookupEnv("FLEET_CPU_PPROF_DIR"); ok {
-		go func() {
-			var pprofCpuFile *os.File
-
-			period := durations.DefaultCpuPprofPeriod
-			if customPeriod, err := time.ParseDuration(os.Getenv("FLEET_CPU_PPROF_PERIOD")); err == nil {
-				period = customPeriod
-			}
-			wait.UntilWithContext(ctx, func(ctx context.Context) {
-				stopCpuPprof(pprofCpuFile)
-				pprofCpuFile = startCpuPprof(dir)
-			}, period)
-		}()
-	}
-}
-
-// stopCpuPprof concludes a cpu pprof capture, if any is ongoing
-func stopCpuPprof(f *os.File) {
-	pprof.StopCPUProfile()
-	if f != nil {
-		err := f.Close()
-		if err != nil {
-			log.Println("could not close CPU profile file ", err)
-		}
-	}
-}
-
-// startCpuPprof starts a pprof cpu capture into a timestamp-prefixed file in dir
-func startCpuPprof(dir string) *os.File {
-	name := time.Now().UTC().Format("2006-01-02_15_04_05") + ".pprof.fleetcontroller.samples.cpu.pb.gz"
-	f, err := os.Create(path.Join(dir, name))
-	if err != nil {
-		log.Println("could not create CPU profile: ", err)
-	}
-	if err := pprof.StartCPUProfile(f); err != nil {
-		log.Println("could not start CPU profile: ", err)
-	}
-	return f
-}
diff --git a/internal/helmdeployer/template.go b/internal/helmdeployer/template.go
index 4eef67da..907190f0 100644
--- a/internal/helmdeployer/template.go
+++ b/internal/helmdeployer/template.go
@@ -14,10 +14,9 @@ import (
 	"helm.sh/helm/v3/pkg/action"
 	"helm.sh/helm/v3/pkg/chartutil"
 	kubefake "helm.sh/helm/v3/pkg/kube/fake"
+	"helm.sh/helm/v3/pkg/release"
 	"helm.sh/helm/v3/pkg/storage"
 	"helm.sh/helm/v3/pkg/storage/driver"
-
-	"k8s.io/apimachinery/pkg/runtime"
 )
 
 var (
@@ -25,7 +24,7 @@ var (
 )
 
 // Template runs helm template and returns the resources as a list of objects, without applying them.
-func Template(ctx context.Context, bundleID string, manifest *manifest.Manifest, options fleet.BundleDeploymentOptions, kubeVersionString string) ([]runtime.Object, error) {
+func Template(ctx context.Context, bundleID string, manifest *manifest.Manifest, options fleet.BundleDeploymentOptions, kubeVersionString string) (*release.Release, error) {
 	h := &Helm{
 		globalCfg:    action.Configuration{},
 		useGlobalCfg: true,
@@ -52,10 +51,5 @@ func Template(ctx context.Context, bundleID string, manifest *manifest.Manifest,
 	h.globalCfg.Log = logrus.Infof
 	h.globalCfg.Releases = storage.Init(mem)
 
-	release, err := h.Deploy(ctx, bundleID, manifest, options)
-	if err != nil {
-		return nil, err
-	}
-
-	return ReleaseToObjects(release)
+	return h.Deploy(ctx, bundleID, manifest, options)
 }
diff --git a/internal/mocks/orastarget_mock.go b/internal/mocks/orastarget_mock.go
index 20e28370..d3cfef2b 100644
--- a/internal/mocks/orastarget_mock.go
+++ b/internal/mocks/orastarget_mock.go
@@ -9,7 +9,7 @@ import (
 	io "io"
 	reflect "reflect"
 
-	gomock "github.com/golang/mock/gomock"
+	gomock "go.uber.org/mock/gomock"
 	v1 "github.com/opencontainers/image-spec/specs-go/v1"
 )
 
diff --git a/pkg/apis/go.mod b/pkg/apis/go.mod
index 704a4e41..748f8131 100644
--- a/pkg/apis/go.mod
+++ b/pkg/apis/go.mod
@@ -1,11 +1,11 @@
 module github.com/rancher/fleet/pkg/apis
 
-go 1.23.0
+go 1.22.0
 
-toolchain go1.23.2
+toolchain go1.22.7
 
 require (
-	github.com/rancher/wrangler/v3 v3.0.0
+	github.com/rancher/wrangler/v3 v3.0.1-rc.3
 	k8s.io/api v0.31.1
 	k8s.io/apimachinery v0.31.1
 )
@@ -19,8 +19,8 @@ require (
 	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
 	github.com/modern-go/reflect2 v1.0.2 // indirect
 	github.com/x448/float16 v0.8.4 // indirect
-	golang.org/x/net v0.26.0 // indirect
-	golang.org/x/text v0.16.0 // indirect
+	golang.org/x/net v0.28.0 // indirect
+	golang.org/x/text v0.17.0 // indirect
 	gopkg.in/inf.v0 v0.9.1 // indirect
 	gopkg.in/yaml.v2 v2.4.0 // indirect
 	k8s.io/klog/v2 v2.130.1 // indirect
diff --git a/pkg/apis/go.sum b/pkg/apis/go.sum
index 19daab7f..375b5dbd 100644
--- a/pkg/apis/go.sum
+++ b/pkg/apis/go.sum
@@ -30,8 +30,8 @@ github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjY
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
 github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
-github.com/rancher/wrangler/v3 v3.0.0 h1:IHHCA+vrghJDPxjtLk4fmeSCFhNe9fFzLFj3m2B0YpA=
-github.com/rancher/wrangler/v3 v3.0.0/go.mod h1:Dfckuuq7MJk2JWVBDywRlZXMxEyPxHy4XqGrPEzu5Eg=
+github.com/rancher/wrangler/v3 v3.0.1-rc.3 h1:C2d1GoP500SEFARVcb6EpbcNaXH3i8Yu9fzAe/0n4C0=
+github.com/rancher/wrangler/v3 v3.0.1-rc.3/go.mod h1:gUPHS1ANs2NyByfeERHwkGiQ1rlIa8BpTJZtNSgMlZw=
 github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
 github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
 github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
@@ -53,8 +53,8 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
 golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
-golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ=
-golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
+golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE=
+golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg=
 golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -63,8 +63,8 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
-golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
+golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
+golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
 golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=


Test patch:
diff --git a/.github/workflows/e2e-nightly-ci.yml b/.github/workflows/e2e-nightly-ci.yml
index cd305f12..88b29c5b 100644
--- a/.github/workflows/e2e-nightly-ci.yml
+++ b/.github/workflows/e2e-nightly-ci.yml
@@ -56,12 +56,15 @@ jobs:
 
           DOCKER_BUILDKIT=1 docker build -f e2e/assets/gitrepo/Dockerfile.gitserver -t nginx-git:test --build-arg="passwd=$(openssl passwd foo)" e2e/assets/gitrepo
       -
-        name: Provision k3d Cluster
+        name: Install k3d
         run: curl --silent --fail https://raw.githubusercontent.com/k3d-io/k3d/main/install.sh | TAG=${{ env.SETUP_K3D_VERSION }} bash
+      -
+        name: Provision k3d Cluster
+        run: |
           k3d cluster create upstream --wait \
             --agents 1 \
             --network "nw01" \
-            --image docker.io/rancher/k3s:${{matrix.k3s.version}}
+            --image docker.io/rancher/k3s:${{matrix.k3s_version}}
       -
         name: Import Images Into k3d
         run: |
diff --git a/integrationtests/cli/apply/apply_online_test.go b/integrationtests/cli/apply/apply_online_test.go
index d0b34752..9f1d52fa 100644
--- a/integrationtests/cli/apply/apply_online_test.go
+++ b/integrationtests/cli/apply/apply_online_test.go
@@ -4,7 +4,7 @@
 package apply
 
 import (
-	"github.com/golang/mock/gomock"
+	"go.uber.org/mock/gomock"
 
 	. "github.com/onsi/ginkgo/v2"
 	. "github.com/onsi/gomega"
diff --git a/integrationtests/cli/assets/bundledeployment/bd.yaml b/integrationtests/cli/assets/bundledeployment/bd.yaml
index da43ea7a..f75567ec 100644
--- a/integrationtests/cli/assets/bundledeployment/bd.yaml
+++ b/integrationtests/cli/assets/bundledeployment/bd.yaml
@@ -1,11 +1,11 @@
 ---
 apiVersion: fleet.cattle.io/v1alpha1
-content: H4sIAAAAAAAA/4SRMW/bMBCF9/6KA2eLtlygA7fCa7t6KTucpZNNhKII8iTEEPTfA5KRESdOsgjQ3Xv33gfOIlAcxtBQFOrfLBz2JJRoBteZc9VcMPD2kL7yir0Vm7RhciyUQG+OFKIZnIJpr12yKnjr1K6l2ATjOYt+A1NkyCvgCzJMFExnKILh+OrUjq+eFKD31jSYnNpNa85O1nKnHXp/i9ailvUvudNCO7FsHiMw9d4iU9yWcY/+G6BauyfjWgWHbPiLXrueGFtkVNoBFNxEVEXTe0slqloxbsIkSTUntCPV+5+p6GqfZ5DHNI8yDWBZvoCYivBD73KqpQ5Hy1X6uz/SWaIH73ch2+eC+fr7lwMocVmx1qVnzKR5dR/yWbkxWAVnO5zQylKksWNkCn/wRLZgp0v/lx8vAQAA//+su6S1jAIAAA==
+content: H4sIAK9MFmcAA51TPW/bMBDd/SsOmi05SoEO2oKsyRQgS5nhTJ0sItSRICmhgeH/Hn5YbhGgtduFgO7eu3fv8HTcAFSOvJmdJF918CMWAI75jS3GiWK1koYHdajliC7sHtPbfOCkq+0KjIBAHBIWrXol55XhDpZ7wWlGB79PENyTl07ZkEEPEMgHyC0IIwZYyKlBkQcV/JkpOHzYOAet1UpiYgpeVp27pm3uBMfmRVpUbdN+j9VKcJXXPG1vMBdoshrjQrtSntDeaLUV/K647+AxE5/RCp4oYI8BO8EA5RDJa+1VVKEiWa8GL8AESQYW1DO199+ShZV+PELzmuq+SQU4nf7J3lKof3RURHoacNahTl/Xxg+a6C9pGElP2VTW/5oDgLJQRqwW6Sfm6+TWNflrhmanOzhos0fdlFWlnn0g94R70uWI/xkQT25RklBKM/OtP8QlJS+F/VDYX6KCzCbkkK+nSXds/LgbjXnvwDqqFfuAWm/zx2wPDntKWJ2NnWmDMR3s0f0KkDcT1caSw2Dc2Xd83zanzScIJmgxDgQAAA==
 kind: Content
 metadata:
   creationTimestamp: null
-  name: s-ee0480cffe0c0da150814f6844d7c5bc49cc05c158c5ba1efe9a45142f36e
-sha256sum: ee0480cffe0c0da150814f6844d7c5bc49cc05c158c5ba1efe9a45142f36eebc
+  name: s-eaab4652f067cb4cbb2498af40082a70b5bf089873703a72b6895e53daaf0dac
+sha256sum: eaab4652f067cb4cbb2498af40082a70b5bf089873703a72b6895e53daaf0dac
 
 ---
 apiVersion: fleet.cattle.io/v1alpha1
@@ -22,14 +22,14 @@ metadata:
   name: testbundle-simple-chart
   namespace: cluster-fleet-local-local-1a3d67d0a899
 spec:
-  deploymentID: s-ee0480cffe0c0da150814f6844d7c5bc49cc05c158c5ba1efe9a45142f36e:c32e813ecbf48f56833aa2267cd3d8758eecc94f9948fb0dea510147a57760b5
+  deploymentID: s-eaab4652f067cb4cbb2498af40082a70b5bf089873703a72b6895e53daaf0dac:c32e813ecbf48f56833aa2267cd3d8758eecc94f9948fb0dea510147a57760b5
   options:
     helm:
       chart: config-chart
       values:
         name: example-value
     ignore: {}
-  stagedDeploymentID: s-ee0480cffe0c0da150814f6844d7c5bc49cc05c158c5ba1efe9a45142f36e:c32e813ecbf48f56833aa2267cd3d8758eecc94f9948fb0dea510147a57760b5
+  stagedDeploymentID: s-eaab4652f067cb4cbb2498af40082a70b5bf089873703a72b6895e53daaf0dac:c32e813ecbf48f56833aa2267cd3d8758eecc94f9948fb0dea510147a57760b5
   stagedOptions:
     helm:
       chart: config-chart
diff --git a/integrationtests/cli/deploy/deploy_test.go b/integrationtests/cli/deploy/deploy_test.go
index 62165028..abfc78d3 100644
--- a/integrationtests/cli/deploy/deploy_test.go
+++ b/integrationtests/cli/deploy/deploy_test.go
@@ -157,9 +157,15 @@ var _ = Describe("Fleet CLI Deploy", func() {
 		It("prints a manifest and bundledeployment", func() {
 			buf, err := act(args)
 			Expect(err).NotTo(HaveOccurred())
-			Expect(buf).To(gbytes.Say("- apiVersion: v1"))
-			Expect(buf).To(gbytes.Say("  data:"))
-			Expect(buf).To(gbytes.Say("    name: example-value"))
+			Expect(buf.Contents()).To(And(
+				ContainSubstring("- apiVersion: v1"),
+				ContainSubstring("ConfigMap"),
+				ContainSubstring("  data:"),
+				ContainSubstring("    name: example-value"),
+				ContainSubstring("ServiceAccount"),
+				ContainSubstring("helm.sh/hook"),
+				ContainSubstring("some-operator"),
+			))
 
 			cm := &corev1.ConfigMap{}
 			err = k8sClient.Get(ctx, types.NamespacedName{Namespace: namespace, Name: "test-simple-chart-config"}, cm)
diff --git a/integrationtests/mocks/fleet_controller_mock.go b/integrationtests/mocks/fleet_controller_mock.go
index a3371fa1..4f52f3b0 100644
--- a/integrationtests/mocks/fleet_controller_mock.go
+++ b/integrationtests/mocks/fleet_controller_mock.go
@@ -7,7 +7,7 @@ package mocks
 import (
 	reflect "reflect"
 
-	gomock "github.com/golang/mock/gomock"
+	gomock "go.uber.org/mock/gomock"
 	v1alpha1 "github.com/rancher/fleet/pkg/generated/controllers/fleet.cattle.io/v1alpha1"
 )
 
diff --git a/integrationtests/mocks/getter_mock.go b/integrationtests/mocks/getter_mock.go
index add20daa..47fc119f 100644
--- a/integrationtests/mocks/getter_mock.go
+++ b/integrationtests/mocks/getter_mock.go
@@ -7,7 +7,7 @@ package mocks
 import (
 	reflect "reflect"
 
-	gomock "github.com/golang/mock/gomock"
+	gomock "go.uber.org/mock/gomock"
 	client "github.com/rancher/fleet/internal/client"
 )
 
diff --git a/internal/cmd/agent/clusterstatus/ticker_test.go b/internal/cmd/agent/clusterstatus/ticker_test.go
index d0d02f81..0321d769 100644
--- a/internal/cmd/agent/clusterstatus/ticker_test.go
+++ b/internal/cmd/agent/clusterstatus/ticker_test.go
@@ -5,11 +5,11 @@ import (
 	"encoding/json"
 	"time"
 
-	"github.com/golang/mock/gomock"
 	. "github.com/onsi/ginkgo/v2"
 	. "github.com/onsi/gomega"
 	fleet "github.com/rancher/fleet/pkg/apis/fleet.cattle.io/v1alpha1"
 	"github.com/rancher/wrangler/v3/pkg/generic/fake"
+	"go.uber.org/mock/gomock"
 	v1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/types"
diff --git a/internal/cmd/agent/register/register_test.go b/internal/cmd/agent/register/register_test.go
index 4b8c78bf..7537736b 100644
--- a/internal/cmd/agent/register/register_test.go
+++ b/internal/cmd/agent/register/register_test.go
@@ -7,10 +7,10 @@ import (
 	"testing"
 	"time"
 
-	"github.com/golang/mock/gomock"
 	corecontrollers "github.com/rancher/wrangler/v3/pkg/generated/controllers/core/v1"
 	"github.com/rancher/wrangler/v3/pkg/generic/fake"
 	"github.com/stretchr/testify/assert"
+	"go.uber.org/mock/gomock"
 	corev1 "k8s.io/api/core/v1"
 	apierrors "k8s.io/apimachinery/pkg/api/errors"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
diff --git a/internal/cmd/controller/agentmanagement/controllers/clusterregistration/controller_test.go b/internal/cmd/controller/agentmanagement/controllers/clusterregistration/controller_test.go
index a3163e19..930ee6da 100644
--- a/internal/cmd/controller/agentmanagement/controllers/clusterregistration/controller_test.go
+++ b/internal/cmd/controller/agentmanagement/controllers/clusterregistration/controller_test.go
@@ -3,9 +3,9 @@ package clusterregistration
 import (
 	"fmt"
 
-	"github.com/golang/mock/gomock"
 	"github.com/rancher/wrangler/v3/pkg/generic"
 	"github.com/rancher/wrangler/v3/pkg/generic/fake"
+	"go.uber.org/mock/gomock"
 	corev1 "k8s.io/api/core/v1"
 	"k8s.io/apimachinery/pkg/api/errors"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
diff --git a/internal/cmd/controller/agentmanagement/controllers/manageagent/manageagent_test.go b/internal/cmd/controller/agentmanagement/controllers/manageagent/manageagent_test.go
index 0bca795e..946f9ec4 100644
--- a/internal/cmd/controller/agentmanagement/controllers/manageagent/manageagent_test.go
+++ b/internal/cmd/controller/agentmanagement/controllers/manageagent/manageagent_test.go
@@ -3,8 +3,8 @@ package manageagent
 import (
 	"testing"
 
-	"github.com/golang/mock/gomock"
 	"github.com/rancher/wrangler/v3/pkg/generic/fake"
+	"go.uber.org/mock/gomock"
 	corev1 "k8s.io/api/core/v1"
 	"k8s.io/apimachinery/pkg/api/resource"
 	"k8s.io/utils/ptr"
diff --git a/internal/ociwrapper/ociwrapper_test.go b/internal/ociwrapper/ociwrapper_test.go
index a3f3752e..7b697ecc 100644
--- a/internal/ociwrapper/ociwrapper_test.go
+++ b/internal/ociwrapper/ociwrapper_test.go
@@ -8,8 +8,8 @@ import (
 	"net/http"
 	"os"
 
-	"github.com/golang/mock/gomock"
 	"github.com/opencontainers/go-digest"
+	"go.uber.org/mock/gomock"
 
 	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
 	"oras.land/oras-go/v2"