Repository: metal3-io/baremetal-operator

Issue:
Switch to errors of standard library and drop deprecated github.com/pkg/errors
Switch to errors of standard library and drop deprecated github.com/pkg/errors

Discussion:
@fmuyassarov: /assign@dtantsur: /kind cleanup
/triage accepted@Rozzii: /kind cleanup
/triage accepted@Rozzii: /triage accepted

Solution patch:
diff --git a/go.mod b/go.mod
index ace3b15f..d7baa833 100644
--- a/go.mod
+++ b/go.mod
@@ -10,7 +10,6 @@ require (
 	github.com/metal3-io/baremetal-operator/apis v0.5.1
 	github.com/metal3-io/baremetal-operator/pkg/hardwareutils v0.5.1
 	github.com/onsi/gomega v1.37.0
-	github.com/pkg/errors v0.9.1
 	github.com/prometheus/client_golang v1.22.0
 	github.com/stretchr/testify v1.10.0
 	go.etcd.io/etcd/client/pkg/v3 v3.6.0
@@ -61,6 +60,7 @@ require (
 	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
 	github.com/modern-go/reflect2 v1.0.2 // indirect
 	github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
+	github.com/pkg/errors v0.9.1 // indirect
 	github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
 	github.com/prometheus/client_model v0.6.1 // indirect
 	github.com/prometheus/common v0.62.0 // indirect
diff --git a/hack/ci-e2e.sh b/hack/ci-e2e.sh
index 6d3af775..b7609991 100755
--- a/hack/ci-e2e.sh
+++ b/hack/ci-e2e.sh
@@ -53,6 +53,9 @@ export PATH="/usr/local/go/bin:${PATH}"
 "${REPO_ROOT}/hack/e2e/ensure_kubectl.sh"
 "${REPO_ROOT}/hack/e2e/ensure_yq.sh"
 
+sudo apt-get update
+sudo apt-get install -y libvirt-dev pkg-config
+
 # Build the container image with e2e tag (used in tests)
 IMG=quay.io/metal3-io/baremetal-operator:e2e make docker
 
diff --git a/hack/tools/go.mod b/hack/tools/go.mod
index 7f9a50b0..311ef472 100644
--- a/hack/tools/go.mod
+++ b/hack/tools/go.mod
@@ -5,7 +5,6 @@ go 1.23.7
 require (
 	github.com/blang/semver v3.5.1+incompatible
 	github.com/google/go-github v17.0.0+incompatible
-	github.com/pkg/errors v0.9.1
 	golang.org/x/crypto v0.38.0
 	golang.org/x/oauth2 v0.30.0
 	sigs.k8s.io/cluster-api/test v1.10.2
@@ -40,6 +39,7 @@ require (
 	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
 	github.com/modern-go/reflect2 v1.0.2 // indirect
 	github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
+	github.com/pkg/errors v0.9.1 // indirect
 	github.com/sergi/go-diff v1.2.0 // indirect
 	github.com/spf13/cobra v1.9.1 // indirect
 	github.com/spf13/pflag v1.0.6 // indirect
diff --git a/hack/tools/release/notes.go b/hack/tools/release/notes.go
index 9ffee57c..aa57861e 100644
--- a/hack/tools/release/notes.go
+++ b/hack/tools/release/notes.go
@@ -28,9 +28,10 @@ import (
 	"os/exec"
 	"strings"
 
+	"errors"
+
 	"github.com/blang/semver"
 	"github.com/google/go-github/github"
-	"github.com/pkg/errors"
 	"golang.org/x/oauth2"
 )
 
@@ -92,7 +93,7 @@ func lastTag(latestTag string) (string, error) {
 
 		semVersion, err := semver.New(latestTag)
 		if err != nil {
-			return "", errors.Wrapf(err, "parsing semver for %s", latestTag)
+			return "", fmt.Errorf("parsing semver for %s: %w", latestTag, err)
 		}
 		semVersion.Minor--
 		lastReleaseTag := fmt.Sprintf("v%s", semVersion.String())
@@ -103,7 +104,7 @@ func lastTag(latestTag string) (string, error) {
 
 	semVersion, err := semver.New(latestTag)
 	if err != nil {
-		return "", errors.Wrapf(err, "parsing semver for %s", latestTag)
+		return "", fmt.Errorf("parsing semver for %s: %w", latestTag, err)
 	}
 	semVersion.Patch--
 	lastReleaseTag := fmt.Sprintf("v%s", semVersion.String())
diff --git a/internal/controller/metal3.io/baremetalhost_controller.go b/internal/controller/metal3.io/baremetalhost_controller.go
index 3ad6b7b5..e4cf2d8f 100644
--- a/internal/controller/metal3.io/baremetalhost_controller.go
+++ b/internal/controller/metal3.io/baremetalhost_controller.go
@@ -18,6 +18,7 @@ package controllers
 import (
 	"context"
 	"encoding/json"
+	"errors"
 	"fmt"
 	"reflect"
 	"strings"
@@ -31,7 +32,6 @@ import (
 	"github.com/metal3-io/baremetal-operator/pkg/provisioner"
 	"github.com/metal3-io/baremetal-operator/pkg/secretutils"
 	"github.com/metal3-io/baremetal-operator/pkg/utils"
-	"github.com/pkg/errors"
 	"github.com/prometheus/client_golang/prometheus"
 	corev1 "k8s.io/api/core/v1"
 	apiequality "k8s.io/apimachinery/pkg/api/equality"
@@ -129,7 +129,7 @@ func (r *BareMetalHostReconciler) Reconcile(ctx context.Context, request ctrl.Re
 			return ctrl.Result{}, nil
 		}
 		// Error reading the object - requeue the request.
-		return ctrl.Result{}, errors.Wrap(err, "could not load host data")
+		return ctrl.Result{}, fmt.Errorf("could not load host data: %w", err)
 	}
 
 	// If the reconciliation is paused, requeue
@@ -143,7 +143,7 @@ func (r *BareMetalHostReconciler) Reconcile(ctx context.Context, request ctrl.Re
 
 	hostData, err := r.reconcileHostData(ctx, host, request)
 	if err != nil {
-		return ctrl.Result{}, errors.Wrap(err, "Could not reconcile host data")
+		return ctrl.Result{}, fmt.Errorf("could not reconcile host data: %w", err)
 	} else if hostData.Requeue {
 		return ctrl.Result{Requeue: true}, nil
 	}
@@ -151,7 +151,7 @@ func (r *BareMetalHostReconciler) Reconcile(ctx context.Context, request ctrl.Re
 	// Consume hardwaredetails from annotation if present
 	hwdUpdated, err := r.updateHardwareDetails(ctx, request, host)
 	if err != nil {
-		return ctrl.Result{}, errors.Wrap(err, "Could not update Hardware Details")
+		return ctrl.Result{}, fmt.Errorf("could not update hardware details: %w", err)
 	} else if hwdUpdated {
 		return ctrl.Result{Requeue: true}, nil
 	}
@@ -172,7 +172,7 @@ func (r *BareMetalHostReconciler) Reconcile(ctx context.Context, request ctrl.Re
 			metal3api.BareMetalHostFinalizer)
 		err := r.Update(ctx, host)
 		if err != nil {
-			return ctrl.Result{}, errors.Wrap(err, "failed to add finalizer")
+			return ctrl.Result{}, fmt.Errorf("failed to add finalizer: %w", err)
 		}
 		return ctrl.Result{Requeue: true}, nil
 	}
@@ -212,7 +212,7 @@ func (r *BareMetalHostReconciler) Reconcile(ctx context.Context, request ctrl.Re
 
 	prov, err := r.ProvisionerFactory.NewProvisioner(ctx, provisioner.BuildHostData(*host, *bmcCreds), info.publishEvent)
 	if err != nil {
-		return ctrl.Result{}, errors.Wrap(err, "failed to create provisioner")
+		return ctrl.Result{}, fmt.Errorf("failed to create provisioner: %w", err)
 	}
 
 	ready, err := prov.TryInit()
@@ -233,7 +233,7 @@ func (r *BareMetalHostReconciler) Reconcile(ctx context.Context, request ctrl.Re
 	result, err = actResult.Result()
 
 	if err != nil {
-		err = errors.Wrap(err, fmt.Sprintf("action %q failed", initialState))
+		err = fmt.Errorf("action %q failed: %w", initialState, err)
 		return result, err
 	}
 
@@ -248,8 +248,7 @@ func (r *BareMetalHostReconciler) Reconcile(ctx context.Context, request ctrl.Re
 			"provisioning state", host.Status.Provisioning.State)
 		err = r.saveHostStatus(ctx, host)
 		if err != nil {
-			return ctrl.Result{}, errors.Wrap(err,
-				fmt.Sprintf("failed to save host status after %q", initialState))
+			return ctrl.Result{}, fmt.Errorf("failed to save host status after %q: %w", initialState, err)
 		}
 
 		for _, cb := range info.postSaveCallbacks {
@@ -273,13 +272,13 @@ func (r *BareMetalHostReconciler) updateHardwareDetails(ctx context.Context, req
 	if host.Status.HardwareDetails == nil || inspectionDisabled(host) {
 		objHardwareDetails, err := r.getHardwareDetailsFromAnnotation(host)
 		if err != nil {
-			return updated, errors.Wrap(err, "Error parsing HardwareDetails from annotation")
+			return updated, fmt.Errorf("error parsing HardwareDetails from annotation: %w", err)
 		}
 		if objHardwareDetails != nil {
 			host.Status.HardwareDetails = objHardwareDetails
 			err = r.saveHostStatus(ctx, host)
 			if err != nil {
-				return updated, errors.Wrap(err, "Could not update hardwaredetails from annotation")
+				return updated, fmt.Errorf("could not update hardwaredetails from annotation: %w", err)
 			}
 			r.publishEvent(ctx, request, host.NewEvent("UpdateHardwareDetails", "Set HardwareDetails from annotation"))
 			updated = true
@@ -292,7 +291,7 @@ func (r *BareMetalHostReconciler) updateHardwareDetails(ctx context.Context, req
 		delete(host.Annotations, metal3api.HardwareDetailsAnnotation)
 		err := r.Update(ctx, host)
 		if err != nil {
-			return updated, errors.Wrap(err, "Could not update removing hardwaredetails annotation")
+			return updated, fmt.Errorf("could not update removing hardwaredetails annotation: %w", err)
 		}
 		// In the case where the value was not just consumed, generate an event
 		if !updated {
@@ -385,7 +384,7 @@ func (r *BareMetalHostReconciler) credentialsErrorResult(ctx context.Context, er
 		return ctrl.Result{}, nil
 	default:
 		unhandledCredentialsError.Inc()
-		return ctrl.Result{}, errors.Wrap(err, "An unhandled failure occurred with the BMC secret")
+		return ctrl.Result{}, fmt.Errorf("an unhandled failure occurred with the BMC secret: %w", err)
 	}
 }
 
@@ -507,7 +506,7 @@ func (r *BareMetalHostReconciler) actionPowerOffBeforeDeleting(prov provisioner.
 		info.host.Status.ErrorType == metal3api.PowerManagementError)
 
 	if err != nil {
-		return actionError{errors.Wrap(err, "failed to power off before deleting node")}
+		return actionError{fmt.Errorf("failed to power off before deleting node: %w", err)}
 	}
 
 	if provResult.ErrorMessage != "" {
@@ -540,7 +539,7 @@ func (r *BareMetalHostReconciler) actionDeleting(prov provisioner.Provisioner, i
 
 	provResult, err := prov.Delete()
 	if err != nil {
-		return actionError{errors.Wrap(err, "failed to delete")}
+		return actionError{fmt.Errorf("failed to delete: %w", err)}
 	}
 	if provResult.Dirty {
 		return actionContinue{provResult.RequeueAfter}
@@ -559,7 +558,7 @@ func (r *BareMetalHostReconciler) actionDeleting(prov provisioner.Provisioner, i
 	info.log.Info("cleanup is complete, removed finalizer",
 		"remaining", info.host.Finalizers)
 	if err := r.Update(info.ctx, info.host); err != nil {
-		return actionError{errors.Wrap(err, "failed to remove finalizer")}
+		return actionError{fmt.Errorf("failed to remove finalizer: %w", err)}
 	}
 
 	return deleteComplete{}
@@ -607,7 +606,7 @@ func hasCustomDeploy(host *metal3api.BareMetalHost) bool {
 func (r *BareMetalHostReconciler) detachHost(prov provisioner.Provisioner, info *reconcileInfo) actionResult {
 	provResult, err := prov.Detach()
 	if err != nil {
-		return actionError{errors.Wrap(err, "failed to detach")}
+		return actionError{fmt.Errorf("failed to detach: %w", err)}
 	}
 	if provResult.ErrorMessage != "" {
 		return recordActionFailure(info, metal3api.DetachError, provResult.ErrorMessage)
@@ -748,7 +747,7 @@ func (r *BareMetalHostReconciler) getPreprovImage(info *reconcileInfo, formats [
 		return nil, err
 	}
 	if err != nil {
-		return nil, errors.Wrap(err, "failed to retrieve pre-provisioning image data")
+		return nil, fmt.Errorf("failed to retrieve pre-provisioning image data: %w", err)
 	}
 
 	needsUpdate := false
@@ -861,7 +860,7 @@ func (r *BareMetalHostReconciler) registerHost(prov provisioner.Provisioner, inf
 	}
 	if err != nil {
 		noManagementAccess.Inc()
-		return actionError{errors.Wrap(err, "failed to validate BMC access")}
+		return actionError{fmt.Errorf("failed to validate BMC access: %w", err)}
 	}
 
 	if provResult.ErrorMessage != "" {
@@ -912,17 +911,17 @@ func (r *BareMetalHostReconciler) registerHost(prov provisioner.Provisioner, inf
 		} else {
 			if err = r.createHostFirmwareSettings(info); err != nil {
 				info.log.Info("failed creating hostfirmwaresettings")
-				return actionError{errors.Wrap(err, "failed creating hostFirmwareSettings")}
+				return actionError{fmt.Errorf("failed to validate BMC access: %w", err)}
 			}
 			if supportsFirmwareComponents {
 				if err = r.createHostFirmwareComponents(info); err != nil {
 					info.log.Info("failed creating hostfirmwarecomponents")
-					return actionError{errors.Wrap(err, "failed creating hostFirmwareComponents")}
+					return actionError{fmt.Errorf("failed creating hostFirmwareComponents: %w", err)}
 				}
 			}
 			if _, err = r.acquireHostUpdatePolicy(info); err != nil {
 				info.log.Info("failed setting owner reference on hostupdatepolicy")
-				return actionError{errors.Wrap(err, "failed setting owner reference on hostUpdatePolicy")}
+				return actionError{fmt.Errorf("failed setting owner reference on hostUpdatePolicy: %w", err)}
 			}
 		}
 	}
@@ -959,7 +958,7 @@ func updateRootDeviceHints(host *metal3api.BareMetalHost, info *reconcileInfo) (
 	if hintSource == nil {
 		hwProf, err := profile.GetProfile(host.HardwareProfile())
 		if err != nil {
-			return false, errors.Wrap(err, "failed to update root device hints")
+			return false, fmt.Errorf("failed to update root device hints: %w", err)
 		}
 		hintSource = &hwProf.RootDeviceHints
 	}
@@ -994,7 +993,7 @@ func (r *BareMetalHostReconciler) actionInspecting(prov provisioner.Provisioner,
 		refresh,
 		forceReboot)
 	if err != nil {
-		return actionError{errors.Wrap(err, "hardware inspection failed")}
+		return actionError{fmt.Errorf("hardware inspection failed: %w", err)}
 	}
 
 	if provResult.ErrorMessage != "" {
@@ -1017,7 +1016,7 @@ func (r *BareMetalHostReconciler) actionInspecting(prov provisioner.Provisioner,
 
 		if dirty {
 			if err := r.Update(info.ctx, info.host); err != nil {
-				return actionError{errors.Wrap(err, "failed to update the host after inspection start")}
+				return actionError{fmt.Errorf("failed to update the host after inspection start: %w", err)}
 			}
 			return actionContinue{}
 		}
@@ -1069,10 +1068,10 @@ func (r *BareMetalHostReconciler) actionInspecting(prov provisioner.Provisioner,
 			controllerutil.RemoveFinalizer(hardwareData, hardwareDataFinalizer)
 		}
 		if err := r.Update(info.ctx, hardwareData); err != nil {
-			return actionError{errors.Wrap(err, "failed to remove hardwareData finalizer")}
+			return actionError{fmt.Errorf("failed to remove hardwareData finalizer: %w", err)}
 		}
 		if err := r.Client.Delete(info.ctx, hd); err != nil {
-			return actionError{errors.Wrap(err, "failed to delete hardwareData")}
+			return actionError{fmt.Errorf("failed to delete hardwareData: %w", err)}
 		}
 	}
 
@@ -1083,7 +1082,7 @@ func (r *BareMetalHostReconciler) actionInspecting(prov provisioner.Provisioner,
 
 	// either hardwareData was deleted above, or not found. We need to re-create it
 	if err := r.Client.Create(info.ctx, hd); err != nil {
-		return actionError{errors.Wrap(err, "failed to create hardwareData")}
+		return actionError{fmt.Errorf("failed to create hardwareData: %w", err)}
 	}
 	info.log.Info(fmt.Sprintf("Created hardwareData %q in %q namespace\n", hd.Name, hd.Namespace))
 
@@ -1206,7 +1205,7 @@ func (r *BareMetalHostReconciler) actionPreparing(prov provisioner.Provisioner,
 		info.host.Status.ErrorType == metal3api.PreparationError)
 
 	if err != nil {
-		return actionError{errors.Wrap(err, "error preparing host")}
+		return actionError{fmt.Errorf("error preparing host: %w", err)}
 	}
 
 	if provResult.ErrorMessage != "" {
@@ -1218,7 +1217,7 @@ func (r *BareMetalHostReconciler) actionPreparing(prov provisioner.Provisioner,
 			info.log.Info("handling cleaning error during firmware update")
 			hfc.Status.Updates = nil
 			if err := r.Status().Update(info.ctx, hfc); err != nil {
-				return actionError{errors.Wrap(err, "failed to update hostfirmwarecomponents status")}
+				return actionError{fmt.Errorf("failed to update hostfirmwarecomponents status: %w", err)}
 			}
 		}
 		return recordActionFailure(info, metal3api.PreparationError, provResult.ErrorMessage)
@@ -1227,13 +1226,13 @@ func (r *BareMetalHostReconciler) actionPreparing(prov provisioner.Provisioner,
 	if hfcDirty && started {
 		hfcStillDirty, err := r.saveHostFirmwareComponents(prov, info, hfc)
 		if err != nil {
-			return actionError{errors.Wrap(err, "could not save the host firmware components")}
+			return actionError{fmt.Errorf("could not save the host firmware components: %w", err)}
 		}
 
 		if hfcStillDirty {
 			info.log.Info("going to update the host firmware components")
 			if err := r.Status().Update(info.ctx, hfc); err != nil {
-				return actionError{errors.Wrap(err, "failed to update hostfirmwarecomponents status")}
+				return actionError{fmt.Errorf("failed to update hostfirmwarecomponents status: %w", err)}
 			}
 		}
 	}
@@ -1242,7 +1241,7 @@ func (r *BareMetalHostReconciler) actionPreparing(prov provisioner.Provisioner,
 		info.log.Info("saving host provisioning settings")
 		_, err := saveHostProvisioningSettings(info.host, info)
 		if err != nil {
-			return actionError{errors.Wrap(err, "could not save the host provisioning settings")}
+			return actionError{fmt.Errorf("could not save the host provisioning settings: %w", err)}
 		}
 	}
 
@@ -1271,9 +1270,8 @@ func (r *BareMetalHostReconciler) actionProvisioning(prov provisioner.Provisione
 
 	hwProf, err := profile.GetProfile(info.host.HardwareProfile())
 	if err != nil {
-		return actionError{errors.Wrap(err,
-			fmt.Sprintf("could not start provisioning with bad hardware profile %s",
-				info.host.HardwareProfile()))}
+		return actionError{fmt.Errorf(" could not start provisioning with bad hardware profile %s: %w",
+			info.host.HardwareProfile(), err)}
 	}
 
 	forceReboot, _ := hasRebootAnnotation(info, true)
@@ -1293,7 +1291,7 @@ func (r *BareMetalHostReconciler) actionProvisioning(prov provisioner.Provisione
 		CPUArchitecture: getHostArchitecture(info.host),
 	}, forceReboot)
 	if err != nil {
-		return actionError{errors.Wrap(err, "failed to provision")}
+		return actionError{fmt.Errorf("failed to provision: %w", err)}
 	}
 
 	if provResult.ErrorMessage != "" {
@@ -1303,7 +1301,7 @@ func (r *BareMetalHostReconciler) actionProvisioning(prov provisioner.Provisione
 
 	if clearRebootAnnotations(info.host) {
 		if err := r.Update(info.ctx, info.host); err != nil {
-			return actionError{errors.Wrap(err, "failed to remove reboot annotations from host")}
+			return actionError{fmt.Errorf("failed to remove reboot annotations from host: %w", err)}
 		}
 		return actionContinue{}
 	}
@@ -1373,7 +1371,7 @@ func (r *BareMetalHostReconciler) actionDeprovisioning(prov provisioner.Provisio
 
 	provResult, err := prov.Deprovision(info.host.Status.ErrorType == metal3api.ProvisioningError)
 	if err != nil {
-		return actionError{errors.Wrap(err, "failed to deprovision")}
+		return actionError{fmt.Errorf("failed to deprovision: %w", err)}
 	}
 
 	if provResult.ErrorMessage != "" {
@@ -1390,7 +1388,7 @@ func (r *BareMetalHostReconciler) actionDeprovisioning(prov provisioner.Provisio
 
 	if clearRebootAnnotations(info.host) {
 		if err = r.Update(info.ctx, info.host); err != nil {
-			return actionError{errors.Wrap(err, "failed to remove reboot annotations from host")}
+			return actionError{fmt.Errorf("failed to remove reboot annotations from host: %w", err)}
 		}
 		return actionContinue{}
 	}
@@ -1483,7 +1481,7 @@ func (r *BareMetalHostReconciler) doServiceIfNeeded(prov provisioner.Provisioner
 		if hfcDirty && hfc.Status.Updates != nil {
 			hfc.Status.Updates = nil
 			if err := r.Status().Update(info.ctx, hfc); err != nil {
-				return actionError{errors.Wrap(err, "failed to update hostfirmwarecomponents status")}
+				return actionError{fmt.Errorf("failed to update hostfirmwarecomponents status: %w", err)}
 			}
 		}
 		result = recordActionFailure(info, metal3api.ServicingError, provResult.ErrorMessage)
@@ -1500,12 +1498,12 @@ func (r *BareMetalHostReconciler) doServiceIfNeeded(prov provisioner.Provisioner
 	if hfcDirty && started {
 		hfcDirty, err = r.saveHostFirmwareComponents(prov, info, hfc)
 		if err != nil {
-			return actionError{errors.Wrap(err, "could not save the host firmware components")}
+			return actionError{fmt.Errorf("could not save the host firmware components: %w", err)}
 		}
 
 		if hfcDirty {
 			if err := r.Status().Update(info.ctx, hfc); err != nil {
-				return actionError{errors.Wrap(err, "failed to update hostfirmwarecomponents status")}
+				return actionError{fmt.Errorf("failed to update hostfirmwarecomponents status: %w", err)}
 			}
 		}
 	}
@@ -1533,7 +1531,7 @@ func (r *BareMetalHostReconciler) manageHostPower(prov provisioner.Provisioner,
 	// Check the current status and save it before trying to update it.
 	hwState, err := prov.UpdateHardwareState()
 	if err != nil {
-		return actionError{errors.Wrap(err, "failed to update the host power status")}
+		return actionError{fmt.Errorf("failed to update the host power status: %w", err)}
 	}
 
 	if hwState.PoweredOn != nil && *hwState.PoweredOn != info.host.Status.PoweredOn {
@@ -1569,7 +1567,7 @@ func (r *BareMetalHostReconciler) manageHostPower(prov provisioner.Provisioner,
 			delete(info.host.Annotations, metal3api.RebootAnnotationPrefix)
 
 			if err = r.Update(info.ctx, info.host); err != nil {
-				return actionError{errors.Wrap(err, "failed to remove reboot annotation from host")}
+				return actionError{fmt.Errorf("failed to remove reboot annotation from host: %w", err)}
 			}
 
 			return actionContinue{}
@@ -1581,7 +1579,7 @@ func (r *BareMetalHostReconciler) manageHostPower(prov provisioner.Provisioner,
 		hup, err := r.acquireHostUpdatePolicy(info)
 		if err != nil {
 			info.log.Info("failed setting owner reference on hostupdatepolicy")
-			return actionError{errors.Wrap(err, "failed setting owner reference on hostUpdatePolicy")}
+			return actionError{fmt.Errorf("failed setting owner reference on hostUpdatePolicy: %w", err)}
 		}
 
 		result := r.doServiceIfNeeded(prov, info, hup)
@@ -1619,7 +1617,7 @@ func (r *BareMetalHostReconciler) manageHostPower(prov provisioner.Provisioner,
 		provResult, err = prov.PowerOff(desiredRebootMode, info.host.Status.ErrorType == metal3api.PowerManagementError)
 	}
 	if err != nil {
-		return actionError{errors.Wrap(err, "failed to manage power state of host")}
+		return actionError{fmt.Errorf("failed setting owner reference on hostUpdatePolicy: %w", err)}
 	}
 
 	// If DisablePowerOff was enabled then prov.PowerOff above will have rebooted instead of powering off, in this case
@@ -1628,7 +1626,7 @@ func (r *BareMetalHostReconciler) manageHostPower(prov provisioner.Provisioner,
 		if _, suffixlessAnnotationExists := info.host.Annotations[metal3api.RebootAnnotationPrefix]; suffixlessAnnotationExists {
 			delete(info.host.Annotations, metal3api.RebootAnnotationPrefix)
 			if err = r.Update(info.ctx, info.host); err != nil {
-				return actionError{errors.Wrap(err, "failed to remove reboot annotation from host")}
+				return actionError{fmt.Errorf("failed to remove reboot annotation from host: %w", err)}
 			}
 			return actionContinue{}
 		}
@@ -1891,7 +1889,7 @@ func getHostProvisioningSettings(host *metal3api.BareMetalHost, info *reconcileI
 	hostCopy := host.DeepCopy()
 	dirty, err = saveHostProvisioningSettings(hostCopy, info)
 	if err != nil {
-		err = errors.Wrap(err, "could not determine the host provisioning settings")
+		err = fmt.Errorf("could not determine the host provisioning settings: %w", err)
 	}
 	status = &hostCopy.Status
 	return
@@ -1981,26 +1979,26 @@ func (r *BareMetalHostReconciler) createHostFirmwareComponents(info *reconcileIn
 
 			// Set bmh as owner, this makes sure the resource is deleted when bmh is deleted
 			if err = controllerutil.SetOwnerReference(info.host, hfc, r.Scheme()); err != nil {
-				return errors.Wrap(err, "could not set bmh as owner for hostFirmwareComponents")
+				return fmt.Errorf("could not set bmh as owner for hostFirmwareComponents: %w", err)
 			}
 			if err = r.Create(info.ctx, hfc); err != nil {
-				return errors.Wrap(err, "failure creating hostFirmwareComponents resource")
+				return fmt.Errorf("failure creating hostFirmwareComponents resource: %w", err)
 			}
 
 			info.log.Info("created new hostFirmwareComponents resource")
 			return nil
 		}
 		// Error reading the object
-		return errors.Wrap(err, "could not load hostFirmwareComponents resource")
+		return fmt.Errorf("could not load hostFirmwareComponents resource: %w", err)
 	}
 	// Necessary in case the CRD is created manually.
 
 	if !ownerReferenceExists(info.host, hfc) {
 		if err := controllerutil.SetOwnerReference(info.host, hfc, r.Scheme()); err != nil {
-			return errors.Wrap(err, "could not set bmh as owner for hostFirmwareComponents")
+			return fmt.Errorf("could not set bmh as owner for hostFirmwareComponents: %w", err)
 		}
 		if err := r.Update(info.ctx, hfc); err != nil {
-			return errors.Wrap(err, "failure updating hostFirmwareComponents resource")
+			return fmt.Errorf("failure updating hostFirmwareComponents resource: %w", err)
 		}
 
 		return nil
@@ -2023,16 +2021,16 @@ func (r *BareMetalHostReconciler) createHostFirmwareSettings(info *reconcileInfo
 
 			// Set bmh as owner, this makes sure the resource is deleted when bmh is deleted
 			if err = controllerutil.SetControllerReference(info.host, hfs, r.Scheme()); err != nil {
-				return errors.Wrap(err, "could not set bmh as controller")
+				return fmt.Errorf("could not set bmh as controller: %w", err)
 			}
 			if err = r.Create(info.ctx, hfs); err != nil {
-				return errors.Wrap(err, "failure creating hostFirmwareSettings resource")
+				return fmt.Errorf("failure creating hostFirmwareSettings resource: %w", err)
 			}
 
 			info.log.Info("created new hostFirmwareSettings resource")
 		} else {
 			// Error reading the object
-			return errors.Wrap(err, "could not load hostFirmwareSettings resource")
+			return fmt.Errorf("could not load hostFirmwareSettings resource: %w", err)
 		}
 	}
 
@@ -2074,7 +2072,7 @@ func (r *BareMetalHostReconciler) getHostFirmwareSettings(info *reconcileInfo) (
 	if err = r.Get(info.ctx, info.request.NamespacedName, hfs); err != nil {
 		if !k8serrors.IsNotFound(err) {
 			// Error reading the object
-			return false, nil, errors.Wrap(err, "could not load host firmware settings")
+			return false, nil, fmt.Errorf("could not load host firmware settings: %w", err)
 		}
 
 		// Could not get settings, log it but don't return error as settings may not have been available at provisioner
@@ -2109,7 +2107,7 @@ func (r *BareMetalHostReconciler) getHostFirmwareComponents(info *reconcileInfo)
 	if err = r.Get(info.ctx, info.request.NamespacedName, hfc); err != nil {
 		if !k8serrors.IsNotFound(err) {
 			// Error reading the object
-			return false, nil, errors.Wrap(err, "could not load host firmware components")
+			return false, nil, fmt.Errorf("could not load host firmware components: %w", err)
 		}
 
 		// Could not get settings, log it but don't return error as settings may not have been available at provisioner
@@ -2142,7 +2140,7 @@ func (r *BareMetalHostReconciler) saveHostStatus(ctx context.Context, host *meta
 func unmarshalStatusAnnotation(content []byte) (*metal3api.BareMetalHostStatus, error) {
 	objStatus := &metal3api.BareMetalHostStatus{}
 	if err := json.Unmarshal(content, objStatus); err != nil {
-		return nil, errors.Wrap(err, "Failed to fetch Status from annotation")
+		return nil, fmt.Errorf("failed to fetch status from annotation: %w", err)
 	}
 	return objStatus, nil
 }
@@ -2187,7 +2185,7 @@ func (r *BareMetalHostReconciler) setErrorCondition(ctx context.Context, request
 	)
 	err = r.saveHostStatus(ctx, host)
 	if err != nil {
-		err = errors.Wrap(err, "failed to update error message")
+		err = fmt.Errorf("failed to update error message: %w", err)
 	}
 
 	return
@@ -2340,7 +2338,7 @@ func (r *BareMetalHostReconciler) reconcileHostData(ctx context.Context, host *m
 			controllerutil.RemoveFinalizer(hardwareData, hardwareDataFinalizer)
 			reqLogger.Info("removing finalizer from hardwareData")
 			if err := r.Update(ctx, hardwareData); err != nil {
-				return ctrl.Result{}, errors.Wrap(err, "failed to remove hardwareData finalizer")
+				return ctrl.Result{}, fmt.Errorf("failed to remove hardwareData finalizer: %w", err)
 			}
 		}
 		reqLogger.Info("hardwareData is ready to be deleted")
@@ -2368,7 +2366,7 @@ func (r *BareMetalHostReconciler) reconcileHostData(ctx context.Context, host *m
 			}
 			errStatus := r.Status().Update(ctx, host)
 			if errStatus != nil {
-				return ctrl.Result{}, errors.Wrap(errStatus, "Could not restore status from annotation")
+				return ctrl.Result{}, fmt.Errorf("could not restore status from annotation: %w", errStatus)
 			}
 			return ctrl.Result{Requeue: true}, nil
 		}
@@ -2381,7 +2379,7 @@ func (r *BareMetalHostReconciler) reconcileHostData(ctx context.Context, host *m
 		delete(annotations, metal3api.StatusAnnotation)
 		errStatus := r.Update(ctx, host)
 		if errStatus != nil {
-			return ctrl.Result{}, errors.Wrap(errStatus, "Could not delete status annotation")
+			return ctrl.Result{}, fmt.Errorf("could not delete status annotation: %w", errStatus)
 		}
 		reqLogger.Info("deleted status annotation")
 		return ctrl.Result{Requeue: true}, nil
@@ -2392,7 +2390,7 @@ func (r *BareMetalHostReconciler) reconcileHostData(ctx context.Context, host *m
 		reqLogger.Info("updating architecture", "Architecture", newArch)
 		host.Spec.Architecture = newArch
 		if err := r.Client.Update(ctx, host); err != nil {
-			return ctrl.Result{}, errors.Wrap(err, "failed to update architecture")
+			return ctrl.Result{}, fmt.Errorf("failed to update architecture: %w", err)
 		}
 		return ctrl.Result{Requeue: true}, nil
 	}
diff --git a/internal/controller/metal3.io/bmceventsubscription_controller.go b/internal/controller/metal3.io/bmceventsubscription_controller.go
index 7aa16d68..ece7edf5 100644
--- a/internal/controller/metal3.io/bmceventsubscription_controller.go
+++ b/internal/controller/metal3.io/bmceventsubscription_controller.go
@@ -17,6 +17,7 @@ package controllers
 
 import (
 	"context"
+	"errors"
 	"fmt"
 	"reflect"
 	"time"
@@ -25,7 +26,6 @@ import (
 	metal3api "github.com/metal3-io/baremetal-operator/apis/metal3.io/v1alpha1"
 	"github.com/metal3-io/baremetal-operator/pkg/provisioner"
 	"github.com/metal3-io/baremetal-operator/pkg/utils"
-	"github.com/pkg/errors"
 	corev1 "k8s.io/api/core/v1"
 	k8serrors "k8s.io/apimachinery/pkg/api/errors"
 	"k8s.io/apimachinery/pkg/types"
@@ -72,7 +72,7 @@ func (r *BMCEventSubscriptionReconciler) Reconcile(ctx context.Context, request
 			return ctrl.Result{}, nil
 		}
 		// Error reading the object - requeue the request.
-		return ctrl.Result{}, errors.Wrap(err, "could not load subscription")
+		return ctrl.Result{}, fmt.Errorf("could not load subscription: %w", err)
 	}
 
 	host := &metal3api.BareMetalHost{}
@@ -89,13 +89,13 @@ func (r *BMCEventSubscriptionReconciler) Reconcile(ctx context.Context, request
 			return r.handleError(ctx, subscription, err, message, true)
 		}
 		// Error reading the object - requeue the request.
-		return ctrl.Result{}, errors.Wrap(err, "could not load host data")
+		return ctrl.Result{}, fmt.Errorf("could not load host data: %w", err)
 	}
 
 	err = r.addFinalizer(ctx, subscription)
 
 	if err != nil {
-		return ctrl.Result{}, errors.Wrap(err, "failed add finalizer")
+		return ctrl.Result{}, fmt.Errorf("failed add finalizer: %w", err)
 	}
 
 	prov, ready, err := r.getProvisioner(ctx, request, host)
@@ -132,14 +132,14 @@ func (r *BMCEventSubscriptionReconciler) handleError(ctx context.Context, subscr
 	subscription.Status.Error = message
 	err := r.Status().Update(ctx, subscription)
 	if err != nil {
-		return ctrl.Result{}, errors.Wrap(err, "failed to update subscription status")
+		return ctrl.Result{}, fmt.Errorf("failed to update subscription status: %w", err)
 	}
 
 	if requeue {
 		return ctrl.Result{RequeueAfter: subscriptionRetryDelay}, nil
 	}
 
-	return ctrl.Result{}, errors.Wrap(e, message)
+	return ctrl.Result{}, fmt.Errorf("%s: %w", message, e)
 }
 
 func (r *BMCEventSubscriptionReconciler) addFinalizer(ctx context.Context, subscription *metal3api.BMCEventSubscription) error {
@@ -156,7 +156,7 @@ func (r *BMCEventSubscriptionReconciler) addFinalizer(ctx context.Context, subsc
 			metal3api.BMCEventSubscriptionFinalizer)
 		err := r.Update(ctx, subscription)
 		if err != nil {
-			return errors.Wrap(err, "failed to add finalizer")
+			return fmt.Errorf("failed to add finalizer: %w", err)
 		}
 		return nil
 	}
@@ -179,13 +179,13 @@ func (r *BMCEventSubscriptionReconciler) createSubscription(ctx context.Context,
 		subscription.Status.Error = "failed to retrieve HTTP headers secret"
 		updateErr := r.Status().Update(ctx, subscription)
 		if updateErr != nil {
-			return errors.Wrap(updateErr, "failed to update subscription status")
+			return fmt.Errorf("failed to update subscription status: %w", updateErr)
 		}
 		return err
 	}
 
 	if _, err := prov.AddBMCEventSubscriptionForNode(subscription, headers); err != nil {
-		return errors.Wrap(err, "failed to create subscription")
+		return fmt.Errorf("failed to create subscription: %w", err)
 	}
 
 	return r.Status().Update(ctx, subscription)
@@ -197,7 +197,7 @@ func (r *BMCEventSubscriptionReconciler) deleteSubscription(ctx context.Context,
 
 	if subscriptionHasFinalizer(subscription) {
 		if _, err := prov.RemoveBMCEventSubscriptionForNode(*subscription); err != nil {
-			return errors.Wrap(err, "failed to remove a subscription")
+			return fmt.Errorf("failed to remove a subscription: %w", err)
 		}
 
 		// Remove finalizer to allow deletion
@@ -218,7 +218,7 @@ func (r *BMCEventSubscriptionReconciler) getProvisioner(ctx context.Context, req
 
 	prov, err = r.ProvisionerFactory.NewProvisioner(ctx, provisioner.BuildHostDataNoBMC(*host), nil)
 	if err != nil {
-		return prov, ready, errors.Wrap(err, "failed to create provisioner")
+		return prov, ready, fmt.Errorf("failed to create provisioner: %w", err)
 	}
 
 	ready, err = prov.TryInit()
diff --git a/internal/controller/metal3.io/host_config_data.go b/internal/controller/metal3.io/host_config_data.go
index 037a0372..534fb93d 100644
--- a/internal/controller/metal3.io/host_config_data.go
+++ b/internal/controller/metal3.io/host_config_data.go
@@ -1,10 +1,11 @@
 package controllers
 
 import (
+	"fmt"
+
 	"github.com/go-logr/logr"
 	metal3api "github.com/metal3-io/baremetal-operator/apis/metal3.io/v1alpha1"
 	"github.com/metal3-io/baremetal-operator/pkg/secretutils"
-	"github.com/pkg/errors"
 	corev1 "k8s.io/api/core/v1"
 	"k8s.io/apimachinery/pkg/types"
 )
@@ -22,7 +23,7 @@ type hostConfigData struct {
 // keys.
 func (hcd *hostConfigData) getSecretData(name, namespace, dataKey string) (string, error) {
 	if namespace != hcd.host.Namespace {
-		return "", errors.Errorf("%s secret must be in same namespace as host %s/%s", dataKey, hcd.host.Namespace, hcd.host.Name)
+		return "", fmt.Errorf("%s secret must be in same namespace as host %s/%s", dataKey, hcd.host.Namespace, hcd.host.Name)
 	}
 
 	key := types.NamespacedName{
diff --git a/internal/controller/metal3.io/host_state_machine.go b/internal/controller/metal3.io/host_state_machine.go
index 0a6d8454..7267c0c7 100644
--- a/internal/controller/metal3.io/host_state_machine.go
+++ b/internal/controller/metal3.io/host_state_machine.go
@@ -7,7 +7,6 @@ import (
 	"github.com/go-logr/logr"
 	metal3api "github.com/metal3-io/baremetal-operator/apis/metal3.io/v1alpha1"
 	"github.com/metal3-io/baremetal-operator/pkg/provisioner"
-	"github.com/pkg/errors"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 )
 
@@ -88,7 +87,7 @@ func recordStateEnd(info *reconcileInfo, host *metal3api.BareMetalHost, state me
 func (hsm *hostStateMachine) ensureCapacity(info *reconcileInfo, state metal3api.ProvisioningState) actionResult {
 	hasCapacity, err := hsm.Provisioner.HasCapacity()
 	if err != nil {
-		return actionError{errors.Wrap(err, "failed to determine current provisioner capacity")}
+		return actionError{fmt.Errorf("failed to determine current provisioner capacity: %w", err)}
 	}
 
 	if !hasCapacity {
diff --git a/internal/controller/metal3.io/hostfirmwaresettings_controller.go b/internal/controller/metal3.io/hostfirmwaresettings_controller.go
index 41ef319f..2f3fd9f3 100644
--- a/internal/controller/metal3.io/hostfirmwaresettings_controller.go
+++ b/internal/controller/metal3.io/hostfirmwaresettings_controller.go
@@ -29,7 +29,6 @@ import (
 	"github.com/go-logr/logr"
 	metal3api "github.com/metal3-io/baremetal-operator/apis/metal3.io/v1alpha1"
 	"github.com/metal3-io/baremetal-operator/pkg/provisioner"
-	"github.com/pkg/errors"
 	corev1 "k8s.io/api/core/v1"
 	k8serrors "k8s.io/apimachinery/pkg/api/errors"
 	"k8s.io/apimachinery/pkg/api/meta"
@@ -139,13 +138,13 @@ func (r *HostFirmwareSettingsReconciler) Reconcile(ctx context.Context, req ctrl
 			return ctrl.Result{Requeue: true, RequeueAfter: resourceNotAvailableRetryDelay}, nil
 		}
 		// Error reading the object - requeue the request.
-		return ctrl.Result{}, errors.Wrap(err, "could not load hostFirmwareSettings")
+		return ctrl.Result{}, fmt.Errorf("could not load hostFirmwareSettings: %w", err)
 	}
 
 	// Create a provisioner that can access Ironic API
 	prov, err := r.ProvisionerFactory.NewProvisioner(ctx, provisioner.BuildHostDataNoBMC(*bmh), info.publishEvent)
 	if err != nil {
-		return ctrl.Result{}, errors.Wrap(err, "failed to create provisioner")
+		return ctrl.Result{}, fmt.Errorf("failed to create provisioner: %w", err)
 	}
 
 	ready, err := prov.TryInit()
@@ -170,7 +169,7 @@ func (r *HostFirmwareSettingsReconciler) Reconcile(ctx context.Context, req ctrl
 	}
 
 	if err = r.updateHostFirmwareSettings(currentSettings, schema, info); err != nil {
-		return ctrl.Result{}, errors.Wrap(err, "Could not update hostFirmwareSettings")
+		return ctrl.Result{}, fmt.Errorf("could not update hostFirmwareSettings: %w", err)
 	}
 
 	for _, e := range info.events {
@@ -190,11 +189,11 @@ func (r *HostFirmwareSettingsReconciler) updateHostFirmwareSettings(currentSetti
 	// get or create a firmwareSchema to hold schema
 	firmwareSchema, err := r.getOrCreateFirmwareSchema(info, schema)
 	if err != nil {
-		return errors.Wrap(err, "could not get/create firmware schema")
+		return fmt.Errorf("could not get/create firmware schema: %w", err)
 	}
 
 	if err = r.updateStatus(info, currentSettings, firmwareSchema); err != nil {
-		return errors.Wrap(err, "could not update hostFirmwareSettings")
+		return fmt.Errorf("could not update hostFirmwareSettings: %w", err)
 	}
 
 	return nil
@@ -303,7 +302,7 @@ func (r *HostFirmwareSettingsReconciler) getOrCreateFirmwareSchema(info *rInfo,
 
 		// Add hfs as owner so can be garbage collected on delete, if already an owner it will just be overwritten
 		if err = controllerutil.SetOwnerReference(info.hfs, firmwareSchema, r.Scheme()); err != nil {
-			return nil, errors.Wrap(err, "could not set owner of existing firmwareSchema")
+			return nil, fmt.Errorf("could not set owner of existing firmwareSchema: %w", err)
 		}
 		if err = r.Update(info.ctx, firmwareSchema); err != nil {
 			return nil, err
@@ -344,7 +343,7 @@ func (r *HostFirmwareSettingsReconciler) getOrCreateFirmwareSchema(info *rInfo,
 	}
 	// Set hfs as owner
 	if err = controllerutil.SetOwnerReference(info.hfs, firmwareSchema, r.Scheme()); err != nil {
-		return nil, errors.Wrap(err, "could not set owner of firmwareSchema")
+		return nil, fmt.Errorf("could not set owner of firmwareSchema: %w", err)
 	}
 
 	if err = r.Create(info.ctx, firmwareSchema); err != nil {
diff --git a/internal/controller/metal3.io/preprovisioningimage_controller.go b/internal/controller/metal3.io/preprovisioningimage_controller.go
index cd105394..92dc4150 100644
--- a/internal/controller/metal3.io/preprovisioningimage_controller.go
+++ b/internal/controller/metal3.io/preprovisioningimage_controller.go
@@ -18,6 +18,8 @@ package controllers
 
 import (
 	"context"
+	"errors"
+	"fmt"
 	"time"
 
 	"github.com/go-logr/logr"
@@ -25,7 +27,6 @@ import (
 	"github.com/metal3-io/baremetal-operator/pkg/imageprovider"
 	"github.com/metal3-io/baremetal-operator/pkg/secretutils"
 	"github.com/metal3-io/baremetal-operator/pkg/utils"
-	"github.com/pkg/errors"
 	corev1 "k8s.io/api/core/v1"
 	apiequality "k8s.io/apimachinery/pkg/api/equality"
 	k8serrors "k8s.io/apimachinery/pkg/api/errors"
@@ -89,7 +90,7 @@ func (r *PreprovisioningImageReconciler) Reconcile(ctx context.Context, req ctrl
 			img.Finalizers, metal3api.PreprovisioningImageFinalizer)
 		err := r.Update(ctx, &img)
 		if err != nil {
-			return ctrl.Result{}, errors.Wrap(err, "failed to remove finalizer")
+			return ctrl.Result{}, fmt.Errorf("failed to remove finalizer: %w", err)
 		}
 		return ctrl.Result{}, nil
 	}
@@ -99,7 +100,7 @@ func (r *PreprovisioningImageReconciler) Reconcile(ctx context.Context, req ctrl
 		img.Finalizers = append(img.Finalizers, metal3api.PreprovisioningImageFinalizer)
 		err := r.Update(ctx, &img)
 		if err != nil {
-			return ctrl.Result{}, errors.Wrap(err, "failed to add finalizer")
+			return ctrl.Result{}, fmt.Errorf("failed to add finalizer: %w", err)
 		}
 		return ctrl.Result{}, nil
 	}
diff --git a/ironic-deployment/overlays/e2e-release-29.0/ironic_bmo_configmap.env b/ironic-deployment/overlays/e2e-release-29.0/ironic_bmo_configmap.env
index 9dc4c4bf..3e41bfbe 100644
--- a/ironic-deployment/overlays/e2e-release-29.0/ironic_bmo_configmap.env
+++ b/ironic-deployment/overlays/e2e-release-29.0/ironic_bmo_configmap.env
@@ -1,6 +1,8 @@
 HTTP_PORT=6180
 PROVISIONING_INTERFACE=eth0
 CACHEURL=http://192.168.222.1/images
+IRONIC_HTTP_URL=http://192.168.222.1:6180
+IRONIC_BASE_URL=https://192.168.222.1:6385
 IRONIC_EXTERNAL_CALLBACK_URL=https://192.168.222.1:6385
 IRONIC_KERNEL_PARAMS=console=ttyS0
 IRONIC_INSPECTOR_VLAN_INTERFACES=all
diff --git a/main.go b/main.go
index 7426d4f0..8477a9a6 100644
--- a/main.go
+++ b/main.go
@@ -35,7 +35,6 @@ import (
 	"github.com/metal3-io/baremetal-operator/pkg/provisioner/ironic"
 	"github.com/metal3-io/baremetal-operator/pkg/secretutils"
 	"github.com/metal3-io/baremetal-operator/pkg/version"
-	"github.com/pkg/errors"
 	"go.uber.org/zap/zapcore"
 	k8sruntime "k8s.io/apimachinery/pkg/runtime"
 	clientgoscheme "k8s.io/client-go/kubernetes/scheme"
@@ -445,7 +444,7 @@ func getMaxConcurrentReconciles(controllerConcurrency int) (int, error) {
 	if mcrEnv, ok := os.LookupEnv("BMO_CONCURRENCY"); ok {
 		mcr, err := strconv.Atoi(mcrEnv)
 		if err != nil {
-			return 0, errors.Wrap(err, fmt.Sprintf("BMO_CONCURRENCY value: %s is invalid", mcrEnv))
+			return 0, fmt.Errorf("BMO_CONCURRENCY value: %s is invalid: %w", mcrEnv, err)
 		}
 		if mcr > 0 {
 			ctrl.Log.Info(fmt.Sprintf("BMO_CONCURRENCY of %d is set via an environment variable", mcr))
diff --git a/pkg/secretutils/secret_manager.go b/pkg/secretutils/secret_manager.go
index 96d16af7..795b42f7 100644
--- a/pkg/secretutils/secret_manager.go
+++ b/pkg/secretutils/secret_manager.go
@@ -7,7 +7,6 @@ import (
 	"github.com/go-logr/logr"
 	metal3api "github.com/metal3-io/baremetal-operator/apis/metal3.io/v1alpha1"
 	"github.com/metal3-io/baremetal-operator/pkg/utils"
-	"github.com/pkg/errors"
 	corev1 "k8s.io/api/core/v1"
 	k8serrors "k8s.io/apimachinery/pkg/api/errors"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -94,7 +93,7 @@ func (sm *SecretManager) claimSecret(secret *corev1.Secret, owner client.Object,
 		if !alreadyOwned {
 			ownerLog.Info("setting secret owner reference")
 			if err := controllerutil.SetOwnerReference(owner, secret, sm.client.Scheme()); err != nil {
-				return errors.Wrap(err, "failed to set secret owner reference")
+				return fmt.Errorf("failed to set secret owner reference: %w", err)
 			}
 			needsUpdate = true
 		}
@@ -108,7 +107,7 @@ func (sm *SecretManager) claimSecret(secret *corev1.Secret, owner client.Object,
 
 	if needsUpdate {
 		if err := sm.client.Update(sm.ctx, secret); err != nil {
-			return errors.Wrap(err, fmt.Sprintf("failed to update secret %s in namespace %s", secret.ObjectMeta.Name, secret.ObjectMeta.Namespace))
+			return fmt.Errorf("failed to update secret %s in namespace %s: %w", secret.ObjectMeta.Name, secret.ObjectMeta.Namespace, err)
 		}
 	}
 
@@ -122,7 +121,7 @@ func (sm *SecretManager) claimSecret(secret *corev1.Secret, owner client.Object,
 func (sm *SecretManager) obtainSecretForOwner(key types.NamespacedName, owner client.Object, addFinalizer bool) (*corev1.Secret, error) {
 	secret, err := sm.findSecret(key)
 	if err != nil {
-		return nil, errors.Wrap(err, fmt.Sprintf("failed to fetch secret %s in namespace %s", key.Name, key.Namespace))
+		return nil, fmt.Errorf("failed to fetch secret %s in namespace %s: %w", key.Name, key.Namespace, err)
 	}
 	err = sm.claimSecret(secret, owner, addFinalizer)
 
@@ -158,8 +157,8 @@ func (sm *SecretManager) ReleaseSecret(secret *corev1.Secret) error {
 		secret.Finalizers, SecretsFinalizer)
 
 	if err := sm.client.Update(sm.ctx, secret); err != nil {
-		return errors.Wrap(err, fmt.Sprintf("failed to remove finalizer from secret %s in namespace %s",
-			secret.ObjectMeta.Name, secret.ObjectMeta.Namespace))
+		return fmt.Errorf("failed to remove finalizer from secret %s in namespace %s: %w",
+			secret.ObjectMeta.Name, secret.ObjectMeta.Namespace, err)
 	}
 
 	sm.log.Info("removed secret finalizer",



Test patch:
diff --git a/test/e2e/cert_manager.go b/test/e2e/cert_manager.go
index a4ba2ea6..6a8abf4d 100644
--- a/test/e2e/cert_manager.go
+++ b/test/e2e/cert_manager.go
@@ -11,7 +11,6 @@ import (
 
 	cmapi "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1"
 	cmmeta "github.com/cert-manager/cert-manager/pkg/apis/meta/v1"
-	"github.com/pkg/errors"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"sigs.k8s.io/cluster-api/test/framework"
 	"sigs.k8s.io/controller-runtime/pkg/client"
@@ -27,16 +26,16 @@ func checkCertManagerAPI(clusterProxy framework.ClusterProxy) error {
 func installCertManager(ctx context.Context, clusterProxy framework.ClusterProxy, cmVersion string) error {
 	response, err := http.Get(fmt.Sprintf("https://github.com/cert-manager/cert-manager/releases/download/%s/cert-manager.yaml", cmVersion)) //nolint: noctx
 	if err != nil {
-		return errors.Wrapf(err, "Error downloading cert-manager manifest")
+		return fmt.Errorf("error downloading cert-manager manifest: %w", err)
 	}
 	defer response.Body.Close()
 	manifests, err := io.ReadAll(response.Body)
 	if err != nil {
-		return errors.Wrapf(err, "Error reading downloaded cert-manager manifest")
+		return fmt.Errorf("error reading downloaded cert-manager manifest: %w", err)
 	}
 	err = clusterProxy.CreateOrUpdate(ctx, manifests)
 	if err != nil {
-		return errors.Wrapf(err, "Error installing cert-manager from downloaded manifest")
+		return fmt.Errorf("error installing cert-manager from downloaded manifest: %w", err)
 	}
 	return nil
 }
@@ -70,7 +69,7 @@ func checkCertManagerWebhook(ctx context.Context, clusterProxy framework.Cluster
 		},
 	}
 	if err = c.Create(ctx, issuer); err != nil {
-		return errors.Wrapf(err, "cert-manager webhook not ready")
+		return fmt.Errorf("cert-manager webhook not ready: %w", err)
 	}
 	cert := &cmapi.Certificate{
 		ObjectMeta: metav1.ObjectMeta{
@@ -86,7 +85,7 @@ func checkCertManagerWebhook(ctx context.Context, clusterProxy framework.Cluster
 	}
 
 	if err = c.Create(ctx, cert); err != nil {
-		return errors.Wrapf(err, "cert-manager webhook not ready")
+		return fmt.Errorf("cert-manager webhook not ready: %w", err)
 	}
 	return nil
 }
diff --git a/test/e2e/common.go b/test/e2e/common.go
index 69fc5c11..d2362ad6 100644
--- a/test/e2e/common.go
+++ b/test/e2e/common.go
@@ -9,6 +9,7 @@ import (
 	"crypto/tls"
 	"encoding/base64"
 	"encoding/json"
+	"errors"
 	"fmt"
 	"io"
 	"log"
@@ -22,7 +23,6 @@ import (
 	metal3api "github.com/metal3-io/baremetal-operator/apis/metal3.io/v1alpha1"
 	. "github.com/onsi/ginkgo/v2"
 	. "github.com/onsi/gomega"
-	"github.com/pkg/errors"
 	"golang.org/x/crypto/ssh"
 	"gopkg.in/yaml.v2"
 	v1 "k8s.io/api/apps/v1"
@@ -356,13 +356,13 @@ func (input *BuildAndApplyKustomizationInput) validate() error {
 		return nil
 	}
 	if input.WaitForDeployment && input.WaitIntervals == nil {
-		return errors.Errorf("WaitIntervals is expected if WaitForDeployment is set to true")
+		return errors.New("WaitIntervals is expected if WaitForDeployment is set to true")
 	}
 	if input.WatchDeploymentLogs && input.LogPath == "" {
-		return errors.Errorf("LogPath is expected if WatchDeploymentLogs is set to true")
+		return errors.New("LogPath is expected if WatchDeploymentLogs is set to true")
 	}
 	if input.DeploymentName == "" || input.DeploymentNamespace == "" {
-		return errors.Errorf("DeploymentName and DeploymentNamespace are expected if WaitForDeployment or WatchDeploymentLogs is true")
+		return errors.New("DeploymentName and DeploymentNamespace are expected if WaitForDeployment or WatchDeploymentLogs is true")
 	}
 	return nil
 }
diff --git a/test/e2e/config/ironic.yaml b/test/e2e/config/ironic.yaml
index 0caa8edd..67af9108 100644
--- a/test/e2e/config/ironic.yaml
+++ b/test/e2e/config/ironic.yaml
@@ -79,10 +79,6 @@ kindExtraPortMappings:
   hostPort: 6385
   listenAddress: "0.0.0.0"
   protocol: TCP
-- containerPort: 5050
-  hostPort: 5050
-  listenAddress: "0.0.0.0"
-  protocol: TCP
 
 
 bmoIronicUpgradeSpecs:
@@ -127,6 +123,7 @@ bmoIronicUpgradeSpecs:
   initBMOKustomization: "../../config/overlays/e2e-release-0.10"
   initIronicKustomization: "../../ironic-deployment/overlays/e2e-release-28.0"
   upgradeEntityKustomization: "../../ironic-deployment/overlays/e2e"
+  upgradeEntityName: "ironic"
 # Upgrade Ironic 29.0 -> latest | BMO 0.10
 - deployIronic: true
   deployBMO: true
diff --git a/test/e2e/e2e_config.go b/test/e2e/e2e_config.go
index 17fbb411..3992b3b3 100644
--- a/test/e2e/e2e_config.go
+++ b/test/e2e/e2e_config.go
@@ -11,7 +11,6 @@ import (
 	"time"
 
 	. "github.com/onsi/gomega"
-	"github.com/pkg/errors"
 	"gopkg.in/yaml.v2"
 	"sigs.k8s.io/cluster-api/test/framework/clusterctl"
 	"sigs.k8s.io/kind/pkg/apis/config/v1alpha4"
@@ -104,13 +103,13 @@ func (c *Config) Validate() error {
 	// Image should have name and loadBehavior be one of [mustload, tryload].
 	for i, containerImage := range c.Images {
 		if containerImage.Name == "" {
-			return errors.Errorf("Container image is missing name: Images[%d].Name=%q", i, containerImage.Name)
+			return fmt.Errorf("container image is missing name: Images[%d].Name=%q", i, containerImage.Name)
 		}
 		switch containerImage.LoadBehavior {
 		case clusterctl.MustLoadImage, clusterctl.TryLoadImage:
 			// Valid
 		default:
-			return errors.Errorf("Invalid load behavior: Images[%d].LoadBehavior=%q", i, containerImage.LoadBehavior)
+			return fmt.Errorf("invalid load behavior: Images[%d].LoadBehavior=%q", i, containerImage.LoadBehavior)
 		}
 	}
 
@@ -118,14 +117,14 @@ func (c *Config) Validate() error {
 	for k, intervals := range c.Intervals {
 		switch len(intervals) {
 		case 0:
-			return errors.Errorf("Invalid interval: Intervals[%s]=%q", k, intervals)
+			return fmt.Errorf("invalid interval: Intervals[%s]=%q", k, intervals)
 		case 1, 2: //nolint: mnd
 		default:
-			return errors.Errorf("Invalid interval: Intervals[%s]=%q", k, intervals)
+			return fmt.Errorf("invalid interval: Intervals[%s]=%q", k, intervals)
 		}
 		for _, i := range intervals {
 			if _, err := time.ParseDuration(i); err != nil {
-				return errors.Errorf("Invalid interval: Intervals[%s]=%q", k, intervals)
+				return fmt.Errorf("invalid interval: Intervals[%s]=%q", k, intervals)
 			}
 		}
 	}
diff --git a/test/go.mod b/test/go.mod
index 450d177a..84b06fe5 100644
--- a/test/go.mod
+++ b/test/go.mod
@@ -9,7 +9,6 @@ require (
 	github.com/metal3-io/baremetal-operator/pkg/hardwareutils v0.5.1
 	github.com/onsi/ginkgo/v2 v2.23.4
 	github.com/onsi/gomega v1.37.0
-	github.com/pkg/errors v0.9.1
 	golang.org/x/crypto v0.38.0
 	gopkg.in/yaml.v2 v2.4.0
 	k8s.io/api v0.32.5
@@ -100,6 +99,7 @@ require (
 	github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799 // indirect
 	github.com/pelletier/go-toml v1.9.5 // indirect
 	github.com/pelletier/go-toml/v2 v2.2.3 // indirect
+	github.com/pkg/errors v0.9.1 // indirect
 	github.com/prometheus/client_golang v1.20.4 // indirect
 	github.com/prometheus/client_model v0.6.1 // indirect
 	github.com/prometheus/common v0.55.0 // indirect