Repository: metal3-io/baremetal-operator

Issue:
Enable "perfsprint" linter in golangci-lint
Enable "perfsprint" linter in golangci-lint. Fix any warnings enabling it causes.

/area ci
/help
/triage accepted

Hints from issue comments:
@metal3-io-bot: @tuminoid: 
	This request has been marked as needing help from a contributor.

Please ensure the request meets the requirements listed [here](https://git.k8s.io/community/contributors/guide/help-wanted.md).

If this request no longer meets these requirements, the label can be removed
by commenting with the `/remove-help` command.


<details>

In response to [this](https://github.com/metal3-io/baremetal-operator/issues/2361):

>Enable "perfsprint" linter in golangci-lint. Fix any warnings enabling it causes.
>
>/area ci
>/help
>/triage accepted


Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes-sigs/prow](https://github.com/kubernetes-sigs/prow/issues/new?title=Prow%20issue:) repository.
</details>@metal3-io-bot: @tuminoid: The label(s) `area/ci` cannot be applied, because the repository doesn't have them.

<details>

In response to [this](https://github.com/metal3-io/baremetal-operator/issues/2361):

>Enable "perfsprint" linter in golangci-lint. Fix any warnings enabling it causes.
>
>/area ci
>/help
>/triage accepted


Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes-sigs/prow](https://github.com/kubernetes-sigs/prow/issues/new?title=Prow%20issue:) repository.
</details>@metal3-io-bot: Issues go stale after 90d of inactivity.
Mark the issue as fresh with `/remove-lifecycle stale`.
Stale issues will close after an additional 30d of inactivity.

If this issue is safe to close now please do so with `/close`.

/lifecycle stale@tuminoid: /remove-lifecycle stale

Solution patch:
diff --git a/.golangci.yaml b/.golangci.yaml
index b22d8759..33892735 100644
--- a/.golangci.yaml
+++ b/.golangci.yaml
@@ -65,7 +65,7 @@ linters:
   - noctx
   - nolintlint
   - nosprintfhostport
-  #- perfsprint
+  - perfsprint
   - prealloc
   - predeclared
   - reassign
diff --git a/apis/metal3.io/v1alpha1/firmwareschema_types.go b/apis/metal3.io/v1alpha1/firmwareschema_types.go
index d9d020c4..036e00e8 100644
--- a/apis/metal3.io/v1alpha1/firmwareschema_types.go
+++ b/apis/metal3.io/v1alpha1/firmwareschema_types.go
@@ -88,7 +88,7 @@ func (schema *SettingSchema) Validate(name string, value intstr.IntOrString) err
 				return nil
 			}
 		}
-		return SchemaSettingError{name: name, message: fmt.Sprintf("unknown enumeration value - %s", value.String())}
+		return SchemaSettingError{name: name, message: "unknown enumeration value - " + value.String()}
 
 	case "Integer":
 		if value.Type == intstr.String {
@@ -118,7 +118,7 @@ func (schema *SettingSchema) Validate(name string, value intstr.IntOrString) err
 		if value.String() == "true" || value.String() == "false" {
 			return nil
 		}
-		return SchemaSettingError{name: name, message: fmt.Sprintf("%s is not a boolean", value.String())}
+		return SchemaSettingError{name: name, message: value.String() + " is not a boolean"}
 
 	case "Password":
 		// Prevent sets of password types
@@ -130,7 +130,7 @@ func (schema *SettingSchema) Validate(name string, value intstr.IntOrString) err
 
 	default:
 		// Unexpected attribute type
-		return SchemaSettingError{name: name, message: fmt.Sprintf("unexpected attribute type %s", schema.AttributeType)}
+		return SchemaSettingError{name: name, message: "unexpected attribute type " + schema.AttributeType}
 	}
 }
 
diff --git a/go.mod b/go.mod
index c8a635cb..de1a186a 100644
--- a/go.mod
+++ b/go.mod
@@ -19,7 +19,7 @@ require (
 	k8s.io/client-go v0.33.2
 	k8s.io/component-base v0.33.2
 	k8s.io/klog/v2 v2.130.1
-	k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738
+	k8s.io/utils v0.0.0-20241210054802-24370beab758
 	sigs.k8s.io/controller-runtime v0.21.0
 	sigs.k8s.io/yaml v1.5.0
 )
diff --git a/go.sum b/go.sum
index 4c273a38..47e461e7 100644
--- a/go.sum
+++ b/go.sum
@@ -249,8 +249,8 @@ k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
 k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
 k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff h1:/usPimJzUKKu+m+TE36gUyGcf03XZEP0ZIKgKj35LS4=
 k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff/go.mod h1:5jIi+8yX4RIb8wk3XwBo5Pq2ccx4FP10ohkbSKCZoK8=
-k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro=
-k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
+k8s.io/utils v0.0.0-20241210054802-24370beab758 h1:sdbE21q2nlQtFh65saZY+rRM6x6aJJI8IUa1AmH/qa0=
+k8s.io/utils v0.0.0-20241210054802-24370beab758/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
 sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2 h1:jpcvIRr3GLoUoEKRkHKSmGjxb6lWwrBlJsXc+eUYQHM=
 sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw=
 sigs.k8s.io/controller-runtime v0.21.0 h1:CYfjpEuicjUecRk+KAeyYh+ouUBn4llGyDYytIGcJS8=
diff --git a/internal/controller/metal3.io/baremetalhost_controller.go b/internal/controller/metal3.io/baremetalhost_controller.go
index d04bb618..979911e4 100644
--- a/internal/controller/metal3.io/baremetalhost_controller.go
+++ b/internal/controller/metal3.io/baremetalhost_controller.go
@@ -906,7 +906,7 @@ func (r *BareMetalHostReconciler) registerHost(prov provisioner.Provisioner, inf
 	// Create the hostFirmwareComponents resource with same host name/namespace if it doesn't exist
 	if info.host.Name != "" {
 		if !info.host.DeletionTimestamp.IsZero() {
-			info.log.Info(fmt.Sprintf("will not attempt to create new hostFirmwareSettings and hostFirmwareComponents in %s", info.host.Namespace))
+			info.log.Info("will not attempt to create new hostFirmwareSettings and hostFirmwareComponents in " + info.host.Namespace)
 		} else {
 			if err = r.createHostFirmwareSettings(info); err != nil {
 				info.log.Info("failed creating hostfirmwaresettings")
@@ -1119,7 +1119,7 @@ func (r *BareMetalHostReconciler) matchProfile(info *reconcileInfo) (dirty bool,
 	if info.host.SetHardwareProfile(hardwareProfile) {
 		dirty = true
 		info.log.Info("updating hardware profile", "profile", hardwareProfile)
-		info.publishEvent("ProfileSet", fmt.Sprintf("Hardware profile set: %s", hardwareProfile))
+		info.publishEvent("ProfileSet", "Hardware profile set: "+hardwareProfile)
 	}
 
 	hintsDirty, err := updateRootDeviceHints(info.host, info)
diff --git a/internal/controller/metal3.io/errors.go b/internal/controller/metal3.io/errors.go
index 713e384a..fffa064b 100644
--- a/internal/controller/metal3.io/errors.go
+++ b/internal/controller/metal3.io/errors.go
@@ -11,8 +11,7 @@ type EmptyBMCAddressError struct {
 }
 
 func (e EmptyBMCAddressError) Error() string {
-	return fmt.Sprintf("Empty BMC address %s",
-		e.message)
+	return "Empty BMC address " + e.message
 }
 
 // EmptyBMCSecretError is returned when the BMC secret
@@ -22,8 +21,7 @@ type EmptyBMCSecretError struct {
 }
 
 func (e EmptyBMCSecretError) Error() string {
-	return fmt.Sprintf("No BMC CredentialsName defined %s",
-		e.message)
+	return "No BMC CredentialsName defined " + e.message
 }
 
 // ResolveBMCSecretRefError is returned when the BMC secret
@@ -33,8 +31,7 @@ type ResolveBMCSecretRefError struct {
 }
 
 func (e ResolveBMCSecretRefError) Error() string {
-	return fmt.Sprintf("BMC CredentialsName secret doesn't exist %s",
-		e.message)
+	return "BMC CredentialsName secret doesn't exist " + e.message
 }
 
 // NoDataInSecretError is returned when host configuration
diff --git a/internal/controller/metal3.io/hostfirmwaresettings_controller.go b/internal/controller/metal3.io/hostfirmwaresettings_controller.go
index 2f3fd9f3..78bc88da 100644
--- a/internal/controller/metal3.io/hostfirmwaresettings_controller.go
+++ b/internal/controller/metal3.io/hostfirmwaresettings_controller.go
@@ -19,6 +19,8 @@ package controllers
 import (
 	"context"
 	"crypto/sha256"
+	"encoding/hex"
+	"errors"
 	"fmt"
 	"reflect"
 	"sort"
@@ -381,31 +383,31 @@ func (r *HostFirmwareSettingsReconciler) updateEventHandler(e event.UpdateEvent)
 
 // Validate the HostFirmwareSetting Spec against the schema.
 func (r *HostFirmwareSettingsReconciler) validateHostFirmwareSettings(info *rInfo, status *metal3api.HostFirmwareSettingsStatus, schema *metal3api.FirmwareSchema) []error {
-	var errors []error
+	var errs []error
 
 	for name, val := range info.hfs.Spec.Settings {
 		// Prohibit any Spec settings with "Password"
 		if strings.Contains(name, "Password") {
-			errors = append(errors, fmt.Errorf("cannot set Password field"))
+			errs = append(errs, errors.New("cannot set Password field"))
 			continue
 		}
 
 		// The setting must be in the Status
 		if _, ok := status.Settings[name]; !ok {
-			errors = append(errors, fmt.Errorf("setting %s is not in the Status field", name))
+			errs = append(errs, fmt.Errorf("setting %s is not in the Status field", name))
 			continue
 		}
 
 		// check validity of updated value
 		if schema != nil {
 			if err := schema.ValidateSetting(name, val, schema.Spec.Schema); err != nil {
-				errors = append(errors, err)
+				errs = append(errs, err)
 			}
 		}
 	}
 
-	if len(errors) > 0 {
-		return errors
+	if len(errs) > 0 {
+		return errs
 	}
 
 	return nil
@@ -468,7 +470,7 @@ func GetSchemaName(schema map[string]metal3api.SettingSchema) string {
 
 	h := sha256.New()
 	fmt.Fprintf(h, "%v", hashkeys)
-	hash := fmt.Sprintf("%x", h.Sum(nil))[:8]
+	hash := hex.EncodeToString(h.Sum(nil))[:8]
 
 	return "schema-" + hash
 }
diff --git a/internal/webhooks/metal3.io/v1alpha1/baremetalhost_validation.go b/internal/webhooks/metal3.io/v1alpha1/baremetalhost_validation.go
index 42317923..e51350d8 100644
--- a/internal/webhooks/metal3.io/v1alpha1/baremetalhost_validation.go
+++ b/internal/webhooks/metal3.io/v1alpha1/baremetalhost_validation.go
@@ -376,7 +376,7 @@ func (webhook *BareMetalHost) validateCrossNamespaceSecretReferences(host *metal
 
 func validatePowerStatus(host *metal3api.BareMetalHost) error {
 	if host.Spec.DisablePowerOff && !host.Spec.Online {
-		return fmt.Errorf("node can't simultaneously have online set to false and have power off disabled")
+		return errors.New("node can't simultaneously have online set to false and have power off disabled")
 	}
 	return nil
 }
diff --git a/internal/webhooks/metal3.io/v1alpha1/bmceventsubscription_webhook.go b/internal/webhooks/metal3.io/v1alpha1/bmceventsubscription_webhook.go
index 4788b358..587dbec1 100644
--- a/internal/webhooks/metal3.io/v1alpha1/bmceventsubscription_webhook.go
+++ b/internal/webhooks/metal3.io/v1alpha1/bmceventsubscription_webhook.go
@@ -16,6 +16,7 @@ package webhooks
 
 import (
 	"context"
+	"errors"
 	"fmt"
 
 	metal3api "github.com/metal3-io/baremetal-operator/apis/metal3.io/v1alpha1"
@@ -71,7 +72,7 @@ func (webhook *BMCEventSubscription) ValidateUpdate(_ context.Context, oldObj, n
 	}
 
 	if newBMCES.Spec != oldBMCES.Spec {
-		return nil, fmt.Errorf("subscriptions cannot be updated, please recreate it")
+		return nil, errors.New("subscriptions cannot be updated, please recreate it")
 	}
 
 	return nil, nil
diff --git a/main.go b/main.go
index b8e519c0..ccdb60bf 100644
--- a/main.go
+++ b/main.go
@@ -78,11 +78,11 @@ func init() {
 }
 
 func printVersion() {
-	setupLog.Info(fmt.Sprintf("Go Version: %s", runtime.Version()))
+	setupLog.Info("Go Version: " + runtime.Version())
 	setupLog.Info(fmt.Sprintf("Go OS/Arch: %s/%s", runtime.GOOS, runtime.GOARCH))
-	setupLog.Info(fmt.Sprintf("Git commit: %s", version.Commit))
-	setupLog.Info(fmt.Sprintf("Build time: %s", version.BuildTime))
-	setupLog.Info(fmt.Sprintf("Component: %s", version.String))
+	setupLog.Info("Git commit: " + version.Commit)
+	setupLog.Info("Build time: " + version.BuildTime)
+	setupLog.Info("Component: " + version.String)
 }
 
 func setupChecks(mgr ctrl.Manager) {
diff --git a/pkg/hardwareutils/bmc/errors.go b/pkg/hardwareutils/bmc/errors.go
index a1d96ff9..7fa1b99d 100644
--- a/pkg/hardwareutils/bmc/errors.go
+++ b/pkg/hardwareutils/bmc/errors.go
@@ -23,6 +23,5 @@ type CredentialsValidationError struct {
 }
 
 func (e CredentialsValidationError) Error() string {
-	return fmt.Sprintf("Validation error with BMC credentials: %s",
-		e.message)
+	return "Validation error with BMC credentials: " + e.message
 }
diff --git a/pkg/imageprovider/invalid.go b/pkg/imageprovider/invalid.go
index de837918..9f016bc4 100644
--- a/pkg/imageprovider/invalid.go
+++ b/pkg/imageprovider/invalid.go
@@ -1,15 +1,11 @@
 package imageprovider
 
-import (
-	"fmt"
-)
-
 type ImageBuildInvalid struct {
 	err error
 }
 
 func (ibf ImageBuildInvalid) Error() string {
-	return fmt.Sprintf("Cannot generate image: %s", ibf.err.Error())
+	return "Cannot generate image: " + ibf.err.Error()
 }
 
 func (ibf ImageBuildInvalid) Unwrap() error {
diff --git a/pkg/provisioner/ironic/clients/auth.go b/pkg/provisioner/ironic/clients/auth.go
index 2b3c5e6f..2ff63e12 100644
--- a/pkg/provisioner/ironic/clients/auth.go
+++ b/pkg/provisioner/ironic/clients/auth.go
@@ -1,7 +1,7 @@
 package clients
 
 import (
-	"fmt"
+	"errors"
 	"net/url"
 	"os"
 	"path"
@@ -63,9 +63,9 @@ func LoadAuth() (auth AuthConfig, err error) {
 	}
 
 	if auth.Username == "" {
-		err = fmt.Errorf("empty HTTP Basic Auth username")
+		err = errors.New("empty HTTP Basic Auth username")
 	} else if auth.Password == "" {
-		err = fmt.Errorf("empty HTTP Basic Auth password")
+		err = errors.New("empty HTTP Basic Auth password")
 	}
 	return
 }
@@ -84,7 +84,7 @@ func ConfigFromEndpointURL(endpointURL string) (endpoint string, auth AuthConfig
 		auth.Username = parsedURL.User.Username()
 		auth.Password, hasPasswd = parsedURL.User.Password()
 		if !hasPasswd {
-			err = fmt.Errorf("no password supplied for HTTP Basic Auth")
+			err = errors.New("no password supplied for HTTP Basic Auth")
 		}
 		parsedURL.User = nil
 	} else {
diff --git a/pkg/provisioner/ironic/devicehints/devicehints.go b/pkg/provisioner/ironic/devicehints/devicehints.go
index db575c2d..f058d57f 100644
--- a/pkg/provisioner/ironic/devicehints/devicehints.go
+++ b/pkg/provisioner/ironic/devicehints/devicehints.go
@@ -18,34 +18,34 @@ func MakeHintMap(source *metal3api.RootDeviceHints) map[string]string {
 
 	if source.DeviceName != "" {
 		if strings.HasPrefix(source.DeviceName, "/dev/disk/by-path/") {
-			hints["by_path"] = fmt.Sprintf("s== %s", source.DeviceName)
+			hints["by_path"] = "s== " + source.DeviceName
 		} else {
-			hints["name"] = fmt.Sprintf("s== %s", source.DeviceName)
+			hints["name"] = "s== " + source.DeviceName
 		}
 	}
 	if source.HCTL != "" {
-		hints["hctl"] = fmt.Sprintf("s== %s", source.HCTL)
+		hints["hctl"] = "s== " + source.HCTL
 	}
 	if source.Model != "" {
-		hints["model"] = fmt.Sprintf("<in> %s", source.Model)
+		hints["model"] = "<in> " + source.Model
 	}
 	if source.Vendor != "" {
-		hints["vendor"] = fmt.Sprintf("<in> %s", source.Vendor)
+		hints["vendor"] = "<in> " + source.Vendor
 	}
 	if source.SerialNumber != "" {
-		hints["serial"] = fmt.Sprintf("s== %s", source.SerialNumber)
+		hints["serial"] = "s== " + source.SerialNumber
 	}
 	if source.MinSizeGigabytes != 0 {
 		hints["size"] = fmt.Sprintf(">= %d", source.MinSizeGigabytes)
 	}
 	if source.WWN != "" {
-		hints["wwn"] = fmt.Sprintf("s== %s", source.WWN)
+		hints["wwn"] = "s== " + source.WWN
 	}
 	if source.WWNWithExtension != "" {
-		hints["wwn_with_extension"] = fmt.Sprintf("s== %s", source.WWNWithExtension)
+		hints["wwn_with_extension"] = "s== " + source.WWNWithExtension
 	}
 	if source.WWNVendorExtension != "" {
-		hints["wwn_vendor_extension"] = fmt.Sprintf("s== %s", source.WWNVendorExtension)
+		hints["wwn_vendor_extension"] = "s== " + source.WWNVendorExtension
 	}
 	switch {
 	case source.Rotational == nil:
diff --git a/pkg/provisioner/ironic/factory.go b/pkg/provisioner/ironic/factory.go
index 95cc21b4..30c1e5c4 100644
--- a/pkg/provisioner/ironic/factory.go
+++ b/pkg/provisioner/ironic/factory.go
@@ -138,7 +138,7 @@ func loadConfigFromEnv(havePreprovImgBuilder bool) (ironicConfig, error) {
 
 	if forcePersistentBootDevice := os.Getenv("LIVE_ISO_FORCE_PERSISTENT_BOOT_DEVICE"); forcePersistentBootDevice != "" {
 		if forcePersistentBootDevice != "Default" && forcePersistentBootDevice != "Always" && forcePersistentBootDevice != "Never" {
-			return c, fmt.Errorf("invalid value for variable LIVE_ISO_FORCE_PERSISTENT_BOOT_DEVICE, must be one of Default, Always or Never")
+			return c, errors.New("invalid value for variable LIVE_ISO_FORCE_PERSISTENT_BOOT_DEVICE, must be one of Default, Always or Never")
 		}
 		c.liveISOForcePersistentBootDevice = forcePersistentBootDevice
 	}
diff --git a/pkg/provisioner/ironic/ironic.go b/pkg/provisioner/ironic/ironic.go
index 4bc753f2..e5f9941f 100644
--- a/pkg/provisioner/ironic/ironic.go
+++ b/pkg/provisioner/ironic/ironic.go
@@ -138,8 +138,7 @@ func (p *ironicProvisioner) validateNode(ironicNode *nodes.Node) (errorMessage s
 		// We expect to see errors of this nature sometimes, so rather
 		// than reporting it as a reconcile error we record the error
 		// status on the host and return.
-		errorMessage = fmt.Sprintf("host validation error: %s",
-			strings.Join(validationErrors, "; "))
+		errorMessage = "host validation error: " + strings.Join(validationErrors, "; ")
 		return errorMessage, nil
 	}
 	return "", nil
@@ -458,7 +457,7 @@ func setDeployImage(config ironicConfig, accessDetails bmc.AccessDetails, hostIm
 			deployImageInfo[deployRamdiskKey] = hostImage.ImageURL
 			if hostImage.ExtraKernelParams != "" {
 				// Using %default% prevents overriding the config in ironic-image
-				deployImageInfo[kernelParamsKey] = fmt.Sprintf("%%default%% %s", hostImage.ExtraKernelParams)
+				deployImageInfo[kernelParamsKey] = "%default% " + hostImage.ExtraKernelParams
 			}
 			return deployImageInfo
 		}
@@ -755,7 +754,7 @@ func (p *ironicProvisioner) GetFirmwareComponents() ([]metal3api.FirmwareCompone
 	}
 
 	if !p.availableFeatures.HasFirmwareUpdates() {
-		return nil, fmt.Errorf("current ironic version does not support firmware updates")
+		return nil, errors.New("current ironic version does not support firmware updates")
 	}
 
 	// Setting to 2 since we only support bmc and bios
@@ -825,7 +824,7 @@ func (p *ironicProvisioner) setUpForProvisioning(ironicNode *nodes.Node, data pr
 		"deploy step", ironicNode.DeployStep,
 	)
 	p.publisher("ProvisioningStarted",
-		fmt.Sprintf("Image provisioning started for %s", data.Image.URL))
+		"Image provisioning started for "+data.Image.URL)
 	return result, nil
 }
 
@@ -878,8 +877,8 @@ func (p *ironicProvisioner) Adopt(data provisioner.AdoptData, restartOnFailure b
 				},
 			)
 		}
-		return operationFailed(fmt.Sprintf("Host adoption failed: %s",
-			ironicNode.LastError))
+		return operationFailed("Host adoption failed: " +
+			ironicNode.LastError)
 	case nodes.Active:
 		// Empty Fault means that maintenance was set manually, not by Ironic
 		if ironicNode.Maintenance && ironicNode.Fault == "" && data.State != metal3api.StateDeleting {
@@ -1252,8 +1251,7 @@ func (p *ironicProvisioner) Provision(data provisioner.ProvisionData, forceReboo
 				return retryAfterDelay(0)
 			}
 			p.log.Info("found error", "msg", ironicNode.LastError)
-			return operationFailed(fmt.Sprintf("Image provisioning failed: %s",
-				ironicNode.LastError))
+			return operationFailed("Image provisioning failed: " + ironicNode.LastError)
 		}
 		p.log.Info("recovering from previous failure")
 		if provResult, err = p.setUpForProvisioning(ironicNode, data); err != nil || provResult.Dirty || provResult.ErrorMessage != "" {
@@ -1316,7 +1314,7 @@ func (p *ironicProvisioner) Provision(data provisioner.ProvisionData, forceReboo
 	case nodes.Active:
 		// provisioning is done
 		p.publisher("ProvisioningComplete",
-			fmt.Sprintf("Image provisioning completed for %s", data.Image.URL))
+			"Image provisioning completed for "+data.Image.URL)
 		p.log.Info("finished provisioning")
 		return operationComplete()
 
@@ -1402,7 +1400,7 @@ func (p *ironicProvisioner) Deprovision(restartOnFailure bool) (result provision
 	case nodes.CleanFail:
 		if !restartOnFailure {
 			p.log.Info("cleaning failed", "lastError", ironicNode.LastError)
-			return operationFailed(fmt.Sprintf("Cleaning failed: %s", ironicNode.LastError))
+			return operationFailed("Cleaning failed: " + ironicNode.LastError)
 		}
 		p.log.Info("retrying cleaning")
 		if ironicNode.Maintenance {
@@ -1621,8 +1619,8 @@ func (p *ironicProvisioner) PowerOn(force bool) (result provisioner.Result, err
 		}
 		if ironicNode.LastError != "" && !force {
 			p.log.Info("PowerOn operation failed", "msg", ironicNode.LastError)
-			return operationFailed(fmt.Sprintf("PowerOn operation failed: %s",
-				ironicNode.LastError))
+			return operationFailed("PowerOn operation failed: " +
+				ironicNode.LastError)
 		}
 		return p.changePower(ironicNode, nodes.PowerOn)
 	}
diff --git a/pkg/version/version.go b/pkg/version/version.go
index b2b69007..114e3f6f 100644
--- a/pkg/version/version.go
+++ b/pkg/version/version.go
@@ -1,8 +1,6 @@
 // Package version includes the version information.
 package version
 
-import "fmt"
-
 var (
 	// Raw is the string representation of the version. This will be replaced
 	// with the calculated version at build time.
@@ -10,7 +8,7 @@ var (
 	Raw = "was not built with version info"
 
 	// String is the human-friendly representation of the version.
-	String = fmt.Sprintf("metal3-io/baremetal-operator %s", Raw)
+	String = "metal3-io/baremetal-operator " + Raw
 
 	// Commit is the commit hash from which the software was built.
 	// Set via LDFLAGS in Makefile.



Test patch:
diff --git a/pkg/provisioner/ironic/clients/updateopts_test.go b/pkg/provisioner/ironic/clients/updateopts_test.go
index 8193f71c..fbe9fe3d 100644
--- a/pkg/provisioner/ironic/clients/updateopts_test.go
+++ b/pkg/provisioner/ironic/clients/updateopts_test.go
@@ -1,7 +1,6 @@
 package clients
 
 import (
-	"fmt"
 	"testing"
 
 	"github.com/go-logr/logr"
@@ -358,7 +357,7 @@ func TestGetUpdateOperation(t *testing.T) {
 
 	for _, c := range cases {
 		t.Run(c.Name, func(t *testing.T) {
-			path := fmt.Sprintf("test/%s", c.Field)
+			path := "test/" + c.Field
 			updateOp := getUpdateOperation(
 				c.Field, existingData,
 				c.NewValue,
diff --git a/pkg/provisioner/ironic/testserver/ironic.go b/pkg/provisioner/ironic/testserver/ironic.go
index d9864e52..0241fe41 100644
--- a/pkg/provisioner/ironic/testserver/ironic.go
+++ b/pkg/provisioner/ironic/testserver/ironic.go
@@ -225,7 +225,7 @@ func (m *IronicMock) NoNode(name string) *IronicMock {
 
 // NodeError configures the server to return the specified error code for /v1/nodes/name.
 func (m *IronicMock) NodeError(name string, errorCode int) *IronicMock {
-	m.ErrorResponse(fmt.Sprintf("/v1/nodes/%s", name), errorCode)
+	m.ErrorResponse("/v1/nodes/"+name, errorCode)
 	return m
 }
 
diff --git a/pkg/provisioner/ironic/testserver/server.go b/pkg/provisioner/ironic/testserver/server.go
index c6502af4..9ba08877 100644
--- a/pkg/provisioner/ironic/testserver/server.go
+++ b/pkg/provisioner/ironic/testserver/server.go
@@ -7,6 +7,7 @@ import (
 	"net/http"
 	"net/http/httptest"
 	"regexp"
+	"strconv"
 	"strings"
 	"testing"
 )
@@ -152,7 +153,7 @@ func (m *MockServer) ResponseJSON(pattern string, payload interface{}) *MockServ
 func (m *MockServer) ErrorResponse(pattern string, errorCode int) *MockServer {
 	m.t.Logf("%s: adding error response handler for %s", m.name, pattern)
 	m.mux.HandleFunc(pattern, func(w http.ResponseWriter, r *http.Request) {
-		m.logRequest(r, fmt.Sprintf("%d", errorCode))
+		m.logRequest(r, strconv.Itoa(errorCode))
 		http.Error(w, "An error", errorCode)
 	})
 	return m
diff --git a/test/e2e/e2e_config.go b/test/e2e/e2e_config.go
index 6600d8ba..21d481ef 100644
--- a/test/e2e/e2e_config.go
+++ b/test/e2e/e2e_config.go
@@ -178,7 +178,7 @@ func (c *Config) Validate() error {
 func (c *Config) GetIntervals(spec, key string) []interface{} {
 	intervals, ok := c.Intervals[fmt.Sprintf("%s/%s", spec, key)]
 	if !ok {
-		if intervals, ok = c.Intervals[fmt.Sprintf("default/%s", key)]; !ok {
+		if intervals, ok = c.Intervals["default/"+key]; !ok {
 			return nil
 		}
 	}
diff --git a/test/e2e/e2e_suite_test.go b/test/e2e/e2e_suite_test.go
index f189d619..217b1beb 100644
--- a/test/e2e/e2e_suite_test.go
+++ b/test/e2e/e2e_suite_test.go
@@ -99,7 +99,7 @@ func serviceAccountToken() (string, error) {
 	}`
 
 	// Temporary file to store the token request
-	secretName := fmt.Sprintf("%s-token-request", serviceAccountName)
+	secretName := serviceAccountName + "-token-request"
 	tokenRequestFile := filepath.Join("/tmp", secretName) //nolint: gocritic
 	err := os.WriteFile(tokenRequestFile, []byte(tokenRequestRawString), os.FileMode(0o644))
 	if err != nil {
@@ -271,7 +271,7 @@ var _ = SynchronizedBeforeSuite(func() []byte {
 			"--namespace", namespace,
 			"--image=curlimages/curl:7.87.0",
 			"--command",
-			"--", "curl", "-v", "--tlsv1.3", "-k", "-H", fmt.Sprintf("Authorization:Bearer %s", token),
+			"--", "curl", "-v", "--tlsv1.3", "-k", "-H", "Authorization:Bearer "+token,
 			fmt.Sprintf("https://%s.%s.svc.cluster.local:8443/metrics", metricsServiceName, namespace))
 		_, err = cmd.CombinedOutput()
 		Expect(err).NotTo(HaveOccurred(), "Failed to create curl-metrics pod")
diff --git a/test/e2e/live_iso_test.go b/test/e2e/live_iso_test.go
index 0ed61792..da1fdb29 100644
--- a/test/e2e/live_iso_test.go
+++ b/test/e2e/live_iso_test.go
@@ -37,7 +37,7 @@ var _ = Describe("Live-ISO", Label("required", "live-iso"), func() {
 		accessDetails, err := metal3bmc.NewAccessDetails(bmc.Address, false)
 		Expect(err).NotTo(HaveOccurred())
 		if !accessDetails.SupportsISOPreprovisioningImage() {
-			Skip(fmt.Sprintf("BMC does not support ISO images. It does not make sense to test live-ISO here. BMC address: %s", bmc.Address))
+			Skip("BMC does not support ISO images. It does not make sense to test live-ISO here. BMC address: " + bmc.Address)
 		}
 
 		imageURL = e2eConfig.GetVariable("ISO_IMAGE_URL")
diff --git a/test/e2e/upgrade_test.go b/test/e2e/upgrade_test.go
index 428af9cf..1f69c433 100644
--- a/test/e2e/upgrade_test.go
+++ b/test/e2e/upgrade_test.go
@@ -372,7 +372,7 @@ var _ = Describe("Upgrade", Label("optional", "upgrade"), func() {
 			Expect(upgradeClusterProvider).ToNot(BeNil(), "Failed to create a cluster")
 			kubeconfigPath = upgradeClusterProvider.GetKubeconfigPath()
 			DeferCleanup(func() {
-				By(fmt.Sprintf("Disposing the kind cluster %s", upgradeClusterName))
+				By("Disposing the kind cluster " + upgradeClusterName)
 				upgradeClusterProvider.Dispose(ctx)
 			})
 		}